Files
Environment-Monitoring-System/Design/frontend_Design/TaskManagementPage_Design.md
ChuXun 4ce487588a 1
2025-10-19 20:31:01 +08:00

8.9 KiB

任务管理页面设计文档

1. 页面概述

任务管理页面是系统的核心功能模块之一,允许主管和管理员对任务进行全面的管理。用户可以在此页面上查看所有任务,并使用筛选、排序和搜索功能快速定位任务。此外,页面还支持任务的分配、审核以及查看任务详情等操作。

2. 页面布局

任务管理页面布局示意图

2.1 布局结构

页面采用经典的后台管理布局:

  • 顶部: 包含页面标题和操作按钮(如"新建任务")。
  • 中部: 筛选和搜索区域,提供多种条件来过滤任务列表。
  • 下部: 任务数据表格,以列表形式展示任务,并包含操作列。
  • 底部: 分页组件,用于浏览大量任务数据。

2.2 响应式设计

  • 桌面端: 多列表格,所有筛选条件水平排列。
  • 平板端: 表格列数减少,部分次要信息可能隐藏,筛选条件折叠或垂直排列。
  • 移动端: 表格转为卡片列表视图,每个卡片显示一个任务的核心信息,筛选功能通过抽屉或模态框提供。

3. 组件结构

<template>
  <div class="task-management-page">
    <!-- 页面头部 -->
    <el-page-header title="任务管理" content="任务列表与分配" />

    <el-card class="page-container">
      <!-- 筛选与搜索区域 -->
      <div class="filter-container">
        <el-form :model="filters" inline>
          <el-form-item label="任务状态">
            <el-select v-model="filters.status" placeholder="请选择状态" clearable>
              <el-option label="待处理" value="PENDING" />
              <el-option label="进行中" value="IN_PROGRESS" />
              <el-option label="已完成" value="COMPLETED" />
              <el-option label="已审核" value="REVIEWED" />
            </el-select>
          </el-form-item>
          <el-form-item label="执行人">
            <el-input v-model="filters.assignee" placeholder="请输入执行人" clearable />
          </el-form-item>
          <el-form-item>
            <el-button type="primary" icon="Search" @click="handleSearch">搜索</el-button>
            <el-button icon="Refresh" @click="handleReset">重置</el-button>
          </el-form-item>
        </el-form>
      </div>

      <!-- 操作按钮区域 -->
      <div class="action-buttons">
        <el-button type="primary" icon="Plus" @click="handleCreateTask" v-permission="'SUPERVISOR'">
          新建任务
        </el-button>
      </div>

      <!-- 任务表格 -->
      <el-table :data="tasks" v-loading="loading" stripe>
        <el-table-column type="index" width="50" />
        <el-table-column prop="title" label="任务标题" min-width="150" />
        <el-table-column prop="grid" label="所属网格" />
        <el-table-column prop="assignee" label="执行人" />
        <el-table-column prop="status" label="状态">
          <template #default="{ row }">
            <el-tag :type="getStatusTagType(row.status)">{{ formatStatus(row.status) }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="createdAt" label="创建时间" sortable />
        <el-table-column label="操作" width="200" fixed="right">
          <template #default="{ row }">
            <el-button link type="primary" @click="handleView(row)">查看</el-button>
            <el-button link type="primary" @click="handleAssign(row)" v-if="canAssign(row)">分配</el-button>
            <el-button link type="primary" @click="handleReview(row)" v-if="canReview(row)">审核</el-button>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页组件 -->
      <el-pagination
        v-if="total > 0"
        class="pagination-container"
        :current-page="pagination.page"
        :page-size="pagination.pageSize"
        :total="total"
        layout="total, sizes, prev, pager, next, jumper"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </el-card>

    <!-- 任务分配/审核/新建的对话框 -->
    <TaskFormDialog v-model="dialogVisible" :task-id="selectedTaskId" :mode="dialogMode" @success="handleSuccess" />
  </div>
</template>

4. 数据结构

// 任务筛选条件
interface TaskFilters {
  status?: 'PENDING' | 'IN_PROGRESS' | 'COMPLETED' | 'REVIEWED';
  assignee?: string;
}

// 分页信息
interface Pagination {
  page: number;
  pageSize: number;
}

// 任务列表项
interface TaskItem {
  id: number;
  title: string;
  grid: string;
  assignee: string | null;
  status: 'PENDING' | 'IN_PROGRESS' | 'COMPLETED' | 'REVIEWED';
  createdAt: string;
}

// 对话框模式
type DialogMode = 'create' | 'assign' | 'review' | 'view';

5. 状态管理

// 组件内状态
const filters = ref<TaskFilters>({});
const pagination = ref<Pagination>({ page: 1, pageSize: 10 });
const dialogVisible = ref(false);
const selectedTaskId = ref<number | null>(null);
const dialogMode = ref<DialogMode>('view');

// 全局状态 (Pinia Store)
const taskStore = useTaskStore();
const { tasks, total, loading } = storeToRefs(taskStore);
const authStore = useAuthStore();
const { user } = storeToRefs(authStore);

6. 交互逻辑

6.1 数据获取与筛选

const fetchTasks = () => {
  taskStore.fetchTasks({ ...filters.value, ...pagination.value });
};

onMounted(fetchTasks);

const handleSearch = () => {
  pagination.value.page = 1;
  fetchTasks();
};

const handleReset = () => {
  filters.value = {};
  handleSearch();
};

const handleSizeChange = (size: number) => {
  pagination.value.pageSize = size;
  fetchTasks();
};

const handleCurrentChange = (page: number) => {
  pagination.value.page = page;
  fetchTasks();
};

6.2 表格操作

const handleView = (task: TaskItem) => {
  selectedTaskId.value = task.id;
  dialogMode.value = 'view';
  dialogVisible.value = true;
};

const handleAssign = (task: TaskItem) => {
  selectedTaskId.value = task.id;
  dialogMode.value = 'assign';
  dialogVisible.value = true;
};

const handleReview = (task: TaskItem) => {
  selectedTaskId.value = task.id;
  dialogMode.value = 'review';
  dialogVisible.value = true;
};

const handleCreateTask = () => {
  selectedTaskId.value = null;
  dialogMode.value = 'create';
  dialogVisible.value = true;
};

const handleSuccess = () => {
  dialogVisible.value = false;
  fetchTasks(); // 操作成功后刷新列表
};

6.3 权限控制

const canAssign = (task: TaskItem) => {
  return user.value?.role === 'SUPERVISOR' && task.status === 'PENDING';
};

const canReview = (task: TaskItem) => {
  return user.value?.role === 'SUPERVISOR' && task.status === 'COMPLETED';
};

6.4 辅助函数

const formatStatus = (status: TaskItem['status']) => {
  const map = { PENDING: '待处理', IN_PROGRESS: '进行中', COMPLETED: '已完成', REVIEWED: '已审核' };
  return map[status] || '未知';
};

// getStatusTagType 函数同仪表盘页面设计

7. API 调用

// api/tasks.ts
export const taskApi = {
  getTasks: (params) => apiClient.get('/management/tasks', { params }),
  // ... 其他任务相关API
};

// stores/task.ts
export const useTaskStore = defineStore('task', {
  state: () => ({
    tasks: [] as TaskItem[],
    total: 0,
    loading: false,
  }),
  actions: {
    async fetchTasks(params) {
      this.loading = true;
      try {
        const { data } = await taskApi.getTasks(params);
        this.tasks = data.items;
        this.total = data.total;
      } catch (error) {
        console.error('获取任务列表失败', error);
      } finally {
        this.loading = false;
      }
    }
  }
});

8. 样式设计

.task-management-page {
  padding: 24px;

  .page-container {
    margin-top: 24px;
    padding: 24px;
    border-radius: 8px;
    border: none;
  }

  .filter-container {
    margin-bottom: 20px;
  }
  
  .action-buttons {
    margin-bottom: 20px;
  }

  .pagination-container {
    margin-top: 24px;
    display: flex;
    justify-content: flex-end;
  }
}

9. 测试用例

  1. 单元测试:

    • 测试权限控制函数 canAssigncanReview 的逻辑。
    • 测试 formatStatus 辅助函数的正确性。
    • 测试 Pinia store 的 action 是否能正确调用 API 并更新 state。
  2. 集成测试:

    • 测试筛选、搜索和重置功能是否正常工作。
    • 测试分页组件是否能正确切换页面和每页数量。
    • 测试"查看"、"分配"、"审核"、"新建"按钮能否正确打开对应模式的对话框。
    • 测试对话框操作成功后,任务列表是否刷新。

10. 性能优化

  1. 后端分页: 必须使用后端分页来处理大量任务数据。
  2. 防抖: 对搜索输入框使用防抖处理,避免用户输入时频繁触发 API 请求。
  3. 组件懒加载: TaskFormDialog 组件可以通过动态导入实现懒加载,只在需要时才加载。