Explorar el Código

Merge branch 'sso' of shuzhihua/randd-vue into master

yanghao hace 6 días
padre
commit
faa034c9ca

+ 42 - 0
src/api/project/index.ts

@@ -0,0 +1,42 @@
+import request from '@/config/axios'
+
+// 获取专家列表
+export const getProjectPage = (params) => {
+  return request.get({ url: '/rd/research-project/page', params })
+}
+
+// 新增项目
+export const createProject = (data: any) => {
+  return request.post({ url: '/rd/research-project/create', data })
+}
+
+// 删除项目
+export const deleteProject = (id) => {
+  return request.delete({ url: '/rd/research-project/delete?id=' + id })
+}
+
+// 修改项目
+export const updateProject = (data: any) => {
+  return request.put({ url: '/rd/research-project/update', data })
+}
+
+// 获取项目详情
+export const getProject = (id: number) => {
+  return request.get({ url: '/rd/research-project/get?id=' + id })
+}
+
+export const submitPre = (id: number) =>
+  request.post({ url: '/rd/research-project/submit-pre', params: { id } })
+
+export const submitFormal = (id: number) =>
+  request.post({ url: '/rd/research-project/submit-formal', params: { id } })
+
+export const approvePre = (data: any) =>
+  request.post({ url: '/rd/research-project/approve-pre', data })
+
+export const approveFormal = (data: any) =>
+  request.post({ url: '/rd/research-project/approve-formal', data })
+
+/** 待我审批的分页 */
+export const getProjectTodoPage = (params: any) =>
+  request.get({ url: '/rd/research-project/todo-page', params })

+ 6 - 1
src/utils/dict.ts

@@ -272,5 +272,10 @@ export enum DICT_TYPE {
   HONOR_SUB_TYPE = 'rd_honor_sub_type', // 荣誉级别子类型
 
   // 资讯类别   数据字典
-  NEWS_CATEGORY = 'rd_news_category' // 资讯类别
+  NEWS_CATEGORY = 'rd_news_category', // 资讯类别
+
+  // 科研项目
+  PROJECT_TYPE = 'rd_project_type', // 项目类型
+  // 项目级别
+  PROJECT_LEVEL = 'rd_project_level'
 }

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 606 - 500
src/views/researchProject/approval/index.vue


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 628 - 312
src/views/researchProject/list/index.vue


+ 831 - 476
src/views/researchProject/wbs/index.vue

@@ -1,83 +1,721 @@
 <template>
-  <div>
-    <vxe-switch v-model="treeConfig.showIcon" />
+  <div class="progress-page">
+    <!-- 统计卡片:放最上面,占满宽度 -->
+    <div class="progress-summary">
+      <div class="summary-item">
+        <span>任务总数</span><strong>{{ totalCount }}</strong>
+      </div>
+      <div class="summary-item doing">
+        <span>进行中</span><strong>{{ doingCount }}</strong>
+      </div>
+      <div class="summary-item done">
+        <span>已完成</span><strong>{{ doneCount }}</strong>
+      </div>
+      <div class="summary-item delayed">
+        <span>已延期</span><strong>{{ delayedCount }}</strong>
+      </div>
+    </div>
 
-    <vxe-gantt v-bind="ganttOptions" />
+    <!-- 筛选栏:白底 -->
+    <div class="progress-filter">
+      <el-form :model="query" inline>
+        <el-form-item label="项目">
+          <el-select
+            v-model="query.projectId"
+            clearable
+            placeholder="全部项目"
+            class="!w-240px"
+            @change="applyFilter"
+          >
+            <el-option v-for="p in projectOptions" :key="p.id" :label="p.title" :value="p.id" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="责任人">
+          <el-select
+            v-model="query.owner"
+            clearable
+            placeholder="全部责任人"
+            class="!w-180px"
+            @change="applyFilter"
+          >
+            <el-option v-for="name in ownerOptions" :key="name" :label="name" :value="name" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="时间范围">
+          <el-date-picker
+            v-model="query.dateRange"
+            type="daterange"
+            value-format="YYYY-MM-DD"
+            range-separator="至"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            class="!w-260px"
+            @change="applyFilter"
+          />
+        </el-form-item>
+
+        <el-form-item>
+          <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" />重置</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <!-- 工具栏:左侧留空,右侧视图切换 -->
+    <div class="progress-toolbar">
+      <div class="toolbar-right">
+        <vxe-switch v-model="treeConfig.showIcon" />
+        <span class="toolbar-hint">展开/收起</span>
+        <el-radio-group v-model="viewMode" size="default">
+          <el-radio-button label="gantt"
+            ><Icon icon="ep:data-line" class="mr-5px" />甘特图</el-radio-button
+          >
+          <el-radio-button label="list"><Icon icon="ep:list" class="mr-5px" />列表</el-radio-button>
+        </el-radio-group>
+      </div>
+    </div>
+
+    <!-- 甘特图 -->
+    <vxe-gantt v-if="viewMode === 'gantt'" v-bind="ganttOptions" />
+
+    <!-- 列表 -->
+    <el-table
+      v-else
+      :data="flatTasks"
+      border
+      class="progress-table"
+      :row-class-name="rowClassName"
+      :tree-props="{ children: 'children' }"
+      row-key="newId"
+      default-expand-all
+    >
+      <el-table-column prop="newTitle" label="任务名称" min-width="260" show-overflow-tooltip />
+      <el-table-column prop="owner" label="责任人" width="120" align="center" />
+      <el-table-column prop="start" label="开始时间" width="130" align="center" />
+      <el-table-column prop="end" label="截止时间" width="130" align="center" />
+      <el-table-column label="进度" width="200" align="center">
+        <template #default="{ row }">
+          <el-progress
+            :percentage="Number(row.progress) || 0"
+            :status="row.state === 'delayed' ? 'exception' : row.state === 'done' ? 'success' : ''"
+            :stroke-width="10"
+          />
+        </template>
+      </el-table-column>
+      <el-table-column label="状态" width="110" align="center">
+        <template #default="{ row }">
+          <el-tag v-if="row.state" :type="stateTagType(row.state)" effect="light">
+            {{ stateLabel(row.state) }}
+          </el-tag>
+          <span v-else>—</span>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <el-empty v-if="!hasAnyTask" description="暂无任务进度" :image-size="80" />
   </div>
 </template>
 
 <script setup>
-import { reactive } from 'vue'
+import { computed, reactive, ref } from 'vue'
 import { VxeGanttTaskType } from 'vxe-gantt'
 
+/* ===================== 原始数据 ===================== */
+// 先把源数据抽出来,方便筛选时反复使用
+const rawList = [
+  {
+    id: 10001,
+    parentId: null,
+    title: '任务1',
+    planStartDate: '',
+    planEndDate: '',
+    actualStartDate: '',
+    actualEndDate: '',
+    planProgress: 90,
+    actualProgress: 80,
+    hasChild: true,
+    owner: '张明远'
+  },
+  {
+    id: 10002,
+    parentId: 10001,
+    title: '任务2',
+    planStartDate: '2024-02-27',
+    planEndDate: '2024-03-03',
+    actualStartDate: '2024-03-01',
+    actualEndDate: '2024-03-02',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '张明远'
+  },
+  {
+    id: 10003,
+    parentId: null,
+    title: '任务3',
+    planStartDate: '',
+    planEndDate: '',
+    actualStartDate: '',
+    actualEndDate: '',
+    planProgress: 90,
+    actualProgress: 80,
+    hasChild: true,
+    owner: '李强'
+  },
+  {
+    id: 10004,
+    parentId: 10003,
+    title: '任务4',
+    planStartDate: '2024-03-01',
+    planEndDate: '2024-03-02',
+    actualStartDate: '2024-03-03',
+    actualEndDate: '2024-03-04',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '李强'
+  },
+  {
+    id: 10005,
+    parentId: 10003,
+    title: '任务5',
+    planStartDate: '2024-03-03',
+    planEndDate: '2024-03-05',
+    actualStartDate: '2024-03-04',
+    actualEndDate: '2024-03-07',
+    planProgress: 90,
+    actualProgress: 80,
+    hasChild: true,
+    owner: '李强'
+  },
+  {
+    id: 10006,
+    parentId: 10003,
+    title: '任务6',
+    planStartDate: '2024-03-19',
+    planEndDate: '2024-03-22',
+    actualStartDate: '2024-03-17',
+    actualEndDate: '2024-03-20',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '李强'
+  },
+  {
+    id: 10007,
+    parentId: 10005,
+    title: '任务7',
+    planStartDate: '2024-03-17',
+    planEndDate: '2024-03-20',
+    actualStartDate: '2024-03-19',
+    actualEndDate: '2024-03-22',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '李强'
+  },
+  {
+    id: 10008,
+    parentId: null,
+    title: '任务8',
+    planStartDate: '',
+    planEndDate: '',
+    actualStartDate: '',
+    actualEndDate: '',
+    planProgress: 90,
+    actualProgress: 80,
+    hasChild: true,
+    owner: '王璐'
+  },
+  {
+    id: 10009,
+    parentId: 10008,
+    title: '任务9',
+    planStartDate: '2024-03-02',
+    planEndDate: '2024-03-03',
+    actualStartDate: '2024-03-02',
+    actualEndDate: '2024-03-03',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '王璐'
+  },
+  {
+    id: 10010,
+    parentId: 10008,
+    title: '任务10',
+    planStartDate: '2024-03-05',
+    planEndDate: '2024-03-07',
+    actualStartDate: '2024-03-05',
+    actualEndDate: '2024-03-09',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '王璐'
+  },
+  {
+    id: 10011,
+    parentId: 10008,
+    title: '任务11',
+    planStartDate: '2024-03-08',
+    planEndDate: '2024-03-11',
+    actualStartDate: '2024-03-11',
+    actualEndDate: '2024-03-15',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '王璐'
+  },
+  {
+    id: 10012,
+    parentId: null,
+    title: '任务12',
+    planStartDate: '',
+    planEndDate: '',
+    actualStartDate: '',
+    actualEndDate: '',
+    planProgress: 90,
+    actualProgress: 80,
+    hasChild: true,
+    owner: '赵磊'
+  },
+  {
+    id: 10013,
+    parentId: 10012,
+    title: '任务13',
+    planStartDate: '2024-03-04',
+    planEndDate: '2024-03-05',
+    actualStartDate: '2024-03-06',
+    actualEndDate: '2024-03-08',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '赵磊'
+  },
+  {
+    id: 10014,
+    parentId: 10012,
+    title: '任务14',
+    planStartDate: '2024-03-06',
+    planEndDate: '2024-03-07',
+    actualStartDate: '2024-03-03',
+    actualEndDate: '2024-03-05',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '赵磊'
+  },
+  {
+    id: 10015,
+    parentId: 10012,
+    title: '任务15',
+    planStartDate: '2024-03-09',
+    planEndDate: '2024-03-12',
+    actualStartDate: '2024-03-10',
+    actualEndDate: '2024-03-11',
+    planProgress: 90,
+    actualProgress: 80,
+    hasChild: true,
+    owner: '赵磊'
+  },
+  {
+    id: 10016,
+    parentId: 10012,
+    title: '任务16',
+    planStartDate: '2024-03-13',
+    planEndDate: '2024-03-15',
+    actualStartDate: '2024-03-17',
+    actualEndDate: '2024-03-18',
+    planProgress: 90,
+    actualProgress: 80,
+    hasChild: true,
+    owner: '赵磊'
+  },
+  {
+    id: 10017,
+    parentId: 10012,
+    title: '任务17',
+    planStartDate: '2024-03-17',
+    planEndDate: '2024-03-21',
+    actualStartDate: '2024-03-18',
+    actualEndDate: '2024-03-19',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '赵磊'
+  },
+  {
+    id: 10018,
+    parentId: null,
+    title: '任务18',
+    planStartDate: '2024-03-11',
+    planEndDate: '2024-03-12',
+    actualStartDate: '2024-03-12',
+    actualEndDate: '2024-03-15',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '孙浩'
+  },
+  {
+    id: 10019,
+    parentId: null,
+    title: '任务19',
+    planStartDate: '2024-03-15',
+    planEndDate: '2024-03-17',
+    actualStartDate: '2024-03-17',
+    actualEndDate: '2024-03-20',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '孙浩'
+  },
+  {
+    id: 10020,
+    parentId: null,
+    title: '任务20',
+    planStartDate: '',
+    planEndDate: '',
+    actualStartDate: '',
+    actualEndDate: '',
+    planProgress: 90,
+    actualProgress: 80,
+    hasChild: true,
+    owner: '周敏'
+  },
+  {
+    id: 10021,
+    parentId: 10020,
+    title: '任务21',
+    planStartDate: '2024-03-18',
+    planEndDate: '2024-03-21',
+    actualStartDate: '2024-03-19',
+    actualEndDate: '2024-03-21',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '周敏'
+  },
+  {
+    id: 10022,
+    parentId: 10020,
+    title: '任务22',
+    planStartDate: '2024-03-23',
+    planEndDate: '2024-03-25',
+    actualStartDate: '2024-03-23',
+    actualEndDate: '2024-03-25',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '周敏'
+  },
+  {
+    id: 10023,
+    parentId: 10020,
+    title: '任务23',
+    planStartDate: '2024-03-27',
+    planEndDate: '2024-04-02',
+    actualStartDate: '2024-03-27',
+    actualEndDate: '2024-03-28',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '周敏'
+  },
+  {
+    id: 10024,
+    parentId: 10020,
+    title: '任务24',
+    planStartDate: '2024-04-04',
+    planEndDate: '2024-04-06',
+    actualStartDate: '2024-04-02',
+    actualEndDate: '2024-04-05',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '周敏'
+  },
+  {
+    id: 10025,
+    parentId: 10020,
+    title: '任务25',
+    planStartDate: '2024-04-07',
+    planEndDate: '2024-04-11',
+    actualStartDate: '2024-04-08',
+    actualEndDate: '2024-04-13',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '周敏'
+  },
+  {
+    id: 10026,
+    parentId: null,
+    title: '任务26',
+    planStartDate: '2024-04-05',
+    planEndDate: '2024-04-08',
+    actualStartDate: '2024-04-07',
+    actualEndDate: '2024-04-10',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '孙浩'
+  },
+  {
+    id: 10027,
+    parentId: null,
+    title: '任务27',
+    planStartDate: '',
+    planEndDate: '',
+    actualStartDate: '',
+    actualEndDate: '',
+    planProgress: 90,
+    actualProgress: 80,
+    hasChild: true,
+    owner: '吴迪'
+  },
+  {
+    id: 10028,
+    parentId: 10027,
+    title: '任务28',
+    planStartDate: '2024-03-10',
+    planEndDate: '2024-03-13',
+    actualStartDate: '2024-03-13',
+    actualEndDate: '2024-03-14',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '吴迪'
+  },
+  {
+    id: 10029,
+    parentId: 10027,
+    title: '任务29',
+    planStartDate: '2024-03-14',
+    planEndDate: '2024-03-18',
+    actualStartDate: '2024-03-16',
+    actualEndDate: '2024-03-18',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '吴迪'
+  },
+  {
+    id: 10030,
+    parentId: 10027,
+    title: '任务30',
+    planStartDate: '2024-03-19',
+    planEndDate: '2024-03-25',
+    actualStartDate: '2024-03-20',
+    actualEndDate: '2024-03-26',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '吴迪'
+  },
+  {
+    id: 10031,
+    parentId: null,
+    title: '任务31',
+    planStartDate: '2024-03-22',
+    planEndDate: '2024-03-24',
+    actualStartDate: '2024-03-19',
+    actualEndDate: '2024-03-20',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '郑凯'
+  },
+  {
+    id: 10032,
+    parentId: null,
+    title: '任务32',
+    planStartDate: '',
+    planEndDate: '',
+    actualStartDate: '',
+    actualEndDate: '',
+    planProgress: 90,
+    actualProgress: 80,
+    hasChild: true,
+    owner: '郑凯'
+  },
+  {
+    id: 10033,
+    parentId: 10032,
+    title: '任务33',
+    planStartDate: '2024-03-09',
+    planEndDate: '2024-03-14',
+    actualStartDate: '2024-03-11',
+    actualEndDate: '2024-03-15',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '郑凯'
+  },
+  {
+    id: 10034,
+    parentId: 10032,
+    title: '任务34',
+    planStartDate: '2024-03-15',
+    planEndDate: '2024-03-21',
+    actualStartDate: '2024-03-16',
+    actualEndDate: '2024-03-19',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '郑凯'
+  },
+  {
+    id: 10035,
+    parentId: 10015,
+    title: '任务35',
+    planStartDate: '2024-03-16',
+    planEndDate: '2024-03-18',
+    actualStartDate: '2024-03-17',
+    actualEndDate: '2024-03-19',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '赵磊'
+  },
+  {
+    id: 10036,
+    parentId: 10015,
+    title: '任务36',
+    planStartDate: '2024-03-12',
+    planEndDate: '2024-03-14',
+    actualStartDate: '2024-03-13',
+    actualEndDate: '2024-03-15',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '赵磊'
+  },
+  {
+    id: 10037,
+    parentId: 10016,
+    title: '任务37',
+    planStartDate: '2024-03-19',
+    planEndDate: '2024-03-22',
+    actualStartDate: '2024-03-21',
+    actualEndDate: '2024-03-23',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '赵磊'
+  },
+  {
+    id: 10038,
+    parentId: 10016,
+    title: '任务38',
+    planStartDate: '2024-03-23',
+    planEndDate: '2024-03-25',
+    actualStartDate: '2024-03-24',
+    actualEndDate: '2024-03-27',
+    planProgress: 90,
+    actualProgress: 80,
+    owner: '赵磊'
+  }
+]
+
+/* ===================== 筛选状态 ===================== */
+const query = reactive({
+  projectId: null,
+  owner: '',
+  dateRange: [],
+  state: 'all'
+})
+const viewMode = ref('gantt')
+
 const treeConfig = reactive({
-  transform: true, // 自动将列表转为树结构
-  rowField: 'newId', // 自定义树节点关联的主键
-  parentField: 'newParentId', // 自定义树节点关联的父节点的字段名
-  showIcon: true // 是否显示展开按钮
+  transform: true,
+  rowField: 'newId',
+  parentField: 'newParentId',
+  showIcon: true
 })
+
+// 顶层任务作为「项目」下拉
+const projectOptions = computed(() =>
+  rawList.filter((t) => t.parentId === null).map((t) => ({ id: t.id, title: t.title }))
+)
+const ownerOptions = computed(() => [...new Set(rawList.map((t) => t.owner).filter(Boolean))])
+
+/* ===================== 状态计算 ===================== */
+// 判定单个任务状态:延期 / 已完成 / 进行中
+const taskState = (row) => {
+  const progress = Number(row.planProgress || row.actualProgress || 0)
+  if (progress >= 100) return 'done'
+  const end = row.actualEndDate || row.planEndDate
+  if (end && new Date(end) < new Date('2024-03-20')) return 'delayed'
+  return 'doing'
+}
+
+// 过滤逻辑:项目 → 责任人 → 时间范围 → 状态
+const filteredList = computed(() => {
+  const { projectId, owner, dateRange, state } = query
+  // 命中筛选条件的叶子任务 id 集合
+  const matchIds = new Set()
+  rawList.forEach((row) => {
+    if (projectId && !isDescendantOf(row, projectId)) return
+    if (owner && row.owner !== owner) return
+    if (dateRange && dateRange.length === 2) {
+      const [start, end] = dateRange
+      const rowStart = row.planStartDate || row.actualStartDate || ''
+      const rowEnd = row.planEndDate || row.actualEndDate || ''
+      if (rowEnd && rowEnd < start) return
+      if (rowStart && rowStart > end) return
+    }
+    if (state !== 'all' && taskState(row) !== state) return
+    matchIds.add(row.id)
+  })
+  // 保留命中节点 + 其所有祖先,保证树结构不断裂
+  const keep = new Set()
+  rawList.forEach((row) => {
+    if (matchIds.has(row.id)) {
+      keep.add(row.id)
+      let parentId = row.parentId
+      while (parentId) {
+        keep.add(parentId)
+        const parent = rawList.find((r) => r.id === parentId)
+        parentId = parent?.parentId ?? null
+      }
+    }
+  })
+  return rawList.filter((row) => keep.has(row.id))
+})
+
+const isDescendantOf = (row, ancestorId) => {
+  let parentId = row.parentId
+  while (parentId) {
+    if (parentId === ancestorId) return true
+    const parent = rawList.find((r) => r.id === parentId)
+    parentId = parent?.parentId ?? null
+  }
+  return row.id === ancestorId
+}
+
+/* ===================== 甘特图数据 ===================== */
 const ganttOptions = reactive({
   border: true,
   height: 600,
-  columnConfig: {
-    resizable: true
-  },
+  columnConfig: { resizable: true },
   treeConfig,
   taskConfig: {
-    titleField: 'newTitle', // 自定义标题字段名
-    startField: 'start', // 自定义开始日期字段名
-    endField: 'end', // 自定义结束期字段名
-    progressField: 'progress', // 自定义进度值字段名
-    typeField: 'type' // 自定义渲染类型字段名
+    titleField: 'newTitle',
+    startField: 'start',
+    endField: 'end',
+    progressField: 'progress',
+    typeField: 'type'
   },
   taskBarSubviewConfig: {
-    showOverview: true, // 是否显示任务总览,当子任务被展开后自动显示任务总览
-    // 自定义子任务视图任务条的样式
+    showOverview: true,
     barStyle({ row }) {
       if (row.flag === 1) {
-        return {
-          top: '-12px', // 偏移位置,计划于实际不重叠
-          backgroundColor: '#40d9eff'
-        }
+        return { top: '-12px', backgroundColor: '#40d9ef' }
       }
       if (row.flag === 2) {
-        return {
-          top: '12px', // 偏移位置,计划于实际不重叠
-          backgroundColor: '#31d231'
-        }
+        return { top: '12px', backgroundColor: '#31d231' }
       }
     }
   },
   taskBarConfig: {
-    showContent: true, // 是否在任务条显示内容
-    moveable: true, // 是否允许拖拽任务移动日期
-    resizable: true, // 是否允许拖拽任务调整日期
+    showContent: true,
+    moveable: true,
+    resizable: true,
     barStyle({ row }) {
       return {
-        round: true, // 圆角
-        bgColor: row.flag === 1 ? '#40d9eff' : '#31d231' // 已完成部分任务条的背景颜色
+        round: true,
+        bgColor: row.flag === 1 ? '#40d9ef' : '#31d231'
       }
     }
   },
   taskViewConfig: {
-    tableStyle: {
-      width: 200
-    },
-    viewStyle: {
-      border: 'inner'
-    }
+    tableStyle: { width: 200 },
+    viewStyle: { border: 'inner' }
   },
   columns: [
     { field: 'newTitle', title: '任务名称', minWidth: 160, treeNode: true },
     { field: 'planStartDate', title: '计划开始日期', width: 140 },
-    { field: 'planEndDate', title: '实际 结束日期', width: 140 },
-    { field: 'actualStartDate', title: '计划开始日期', width: 140 },
+    { field: 'planEndDate', title: '计划结束日期', width: 140 },
+    { field: 'actualStartDate', title: '实际开始日期', width: 140 },
     { field: 'actualEndDate', title: '实际结束日期', width: 140 }
   ],
   data: []
 })
 
-// 将实际和计划一分二
+// 将实际和计划一分二(保留你原有逻辑)
 const handleMultiTask = (list) => {
   const multiRest = []
   list.forEach((item) => {
@@ -95,7 +733,6 @@ const handleMultiTask = (list) => {
       }
       multiRest.push(groupRow)
     } else {
-      // 计划
       const planRow = {
         ...item,
         newTitle: `计划:${item.title}`,
@@ -106,7 +743,6 @@ const handleMultiTask = (list) => {
         end: item.planEndDate,
         progress: 0
       }
-      // 实际
       const actualRow = {
         ...item,
         newTitle: `实际:${item.title}`,
@@ -123,440 +759,159 @@ const handleMultiTask = (list) => {
   return multiRest
 }
 
-const loadList = () => {
-  const list = [
-    {
-      id: 10001,
-      parentId: null,
-      title: '任务1',
-      planStartDate: '',
-      planEndDate: '',
-      actualStartDate: '',
-      actualEndDate: '',
-      planProgress: 90,
-      actualProgress: 80,
-      hasChild: true
-    },
-    {
-      id: 10002,
-      parentId: 10001,
-      title: '任务2',
-      planStartDate: '2024-02-27',
-      planEndDate: '2024-03-03',
-      actualStartDate: '2024-03-01',
-      actualEndDate: '2024-03-02',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10003,
-      parentId: null,
-      title: '任务3',
-      planStartDate: '',
-      planEndDate: '',
-      actualStartDate: '',
-      actualEndDate: '',
-      planProgress: 90,
-      actualProgress: 80,
-      hasChild: true
-    },
-    {
-      id: 10004,
-      parentId: 10003,
-      title: '任务4',
-      planStartDate: '2024-03-01',
-      planEndDate: '2024-03-02',
-      actualStartDate: '2024-03-03',
-      actualEndDate: '2024-03-04',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10005,
-      parentId: 10003,
-      title: '任务5',
-      planStartDate: '2024-03-03',
-      planEndDate: '2024-03-05',
-      actualStartDate: '2024-03-04',
-      actualEndDate: '2024-03-07',
-      planProgress: 90,
-      actualProgress: 80,
-      hasChild: true
-    },
-    {
-      id: 10006,
-      parentId: 10003,
-      title: '任务6',
-      planStartDate: '2024-03-19',
-      planEndDate: '2024-03-22',
-      actualStartDate: '2024-03-17',
-      actualEndDate: '2024-03-20',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10007,
-      parentId: 10005,
-      title: '任务7',
-      planStartDate: '2024-03-17',
-      planEndDate: '2024-03-20',
-      actualStartDate: '2024-03-19',
-      actualEndDate: '2024-03-22',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10008,
-      parentId: null,
-      title: '任务8',
-      planStartDate: '',
-      planEndDate: '',
-      actualStartDate: '',
-      actualEndDate: '',
-      planProgress: 90,
-      actualProgress: 80,
-      hasChild: true
-    },
-    {
-      id: 10009,
-      parentId: 10008,
-      title: '任务9',
-      planStartDate: '2024-03-02',
-      planEndDate: '2024-03-03',
-      actualStartDate: '2024-03-02',
-      actualEndDate: '2024-03-03',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10010,
-      parentId: 10008,
-      title: '任务10',
-      planStartDate: '2024-03-05',
-      planEndDate: '2024-03-07',
-      actualStartDate: '2024-03-05',
-      actualEndDate: '2024-03-09',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10011,
-      parentId: 10008,
-      title: '任务11',
-      planStartDate: '2024-03-08',
-      planEndDate: '2024-03-11',
-      actualStartDate: '2024-03-11',
-      actualEndDate: '2024-03-15',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10012,
-      parentId: null,
-      title: '任务12',
-      planStartDate: '',
-      planEndDate: '',
-      actualStartDate: '',
-      actualEndDate: '',
-      planProgress: 90,
-      actualProgress: 80,
-      hasChild: true
-    },
-    {
-      id: 10013,
-      parentId: 10012,
-      title: '任务13',
-      planStartDate: '2024-03-04',
-      planEndDate: '2024-03-05',
-      actualStartDate: '2024-03-06',
-      actualEndDate: '2024-03-08',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10014,
-      parentId: 10012,
-      title: '任务14',
-      planStartDate: '2024-03-06',
-      planEndDate: '2024-03-07',
-      actualStartDate: '2024-03-03',
-      actualEndDate: '2024-03-05',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10015,
-      parentId: 10012,
-      title: '任务15',
-      planStartDate: '2024-03-09',
-      planEndDate: '2024-03-12',
-      actualStartDate: '2024-03-10',
-      actualEndDate: '2024-03-11',
-      planProgress: 90,
-      actualProgress: 80,
-      hasChild: true
-    },
-    {
-      id: 10016,
-      parentId: 10012,
-      title: '任务16',
-      planStartDate: '2024-03-13',
-      planEndDate: '2024-03-15',
-      actualStartDate: '2024-03-17',
-      actualEndDate: '2024-03-18',
-      planProgress: 90,
-      actualProgress: 80,
-      hasChild: true
-    },
-    {
-      id: 10017,
-      parentId: 10012,
-      title: '任务17',
-      planStartDate: '2024-03-17',
-      planEndDate: '2024-03-21',
-      actualStartDate: '2024-03-18',
-      actualEndDate: '2024-03-19',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10018,
-      parentId: null,
-      title: '任务18',
-      planStartDate: '2024-03-11',
-      planEndDate: '2024-03-12',
-      actualStartDate: '2024-03-12',
-      actualEndDate: '2024-03-15',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10019,
-      parentId: null,
-      title: '任务19',
-      planStartDate: '2024-03-15',
-      planEndDate: '2024-03-17',
-      actualStartDate: '2024-03-17',
-      actualEndDate: '2024-03-20',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10020,
-      parentId: null,
-      title: '任务20',
-      planStartDate: '',
-      planEndDate: '',
-      actualStartDate: '',
-      actualEndDate: '',
-      planProgress: 90,
-      actualProgress: 80,
-      hasChild: true
-    },
-    {
-      id: 10021,
-      parentId: 10020,
-      title: '任务21',
-      planStartDate: '2024-03-18',
-      planEndDate: '2024-03-21',
-      actualStartDate: '2024-03-19',
-      actualEndDate: '2024-03-21',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10022,
-      parentId: 10020,
-      title: '任务22',
-      planStartDate: '2024-03-23',
-      planEndDate: '2024-03-25',
-      actualStartDate: '2024-03-23',
-      actualEndDate: '2024-03-25',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10023,
-      parentId: 10020,
-      title: '任务23',
-      planStartDate: '2024-03-27',
-      planEndDate: '2024-04-02',
-      actualStartDate: '2024-03-27',
-      actualEndDate: '2024-03-28',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10024,
-      parentId: 10020,
-      title: '任务24',
-      planStartDate: '2024-04-04',
-      planEndDate: '2024-04-06',
-      actualStartDate: '2024-04-02',
-      actualEndDate: '2024-04-05',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10025,
-      parentId: 10020,
-      title: '任务25',
-      planStartDate: '2024-04-07',
-      planEndDate: '2024-04-11',
-      actualStartDate: '2024-04-08',
-      actualEndDate: '2024-04-13',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10026,
-      parentId: null,
-      title: '任务26',
-      planStartDate: '2024-04-05',
-      planEndDate: '2024-04-08',
-      actualStartDate: '2024-04-07',
-      actualEndDate: '2024-04-10',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10027,
-      parentId: null,
-      title: '任务27',
-      planStartDate: '',
-      planEndDate: '',
-      actualStartDate: '',
-      actualEndDate: '',
-      planProgress: 90,
-      actualProgress: 80,
-      hasChild: true
-    },
-    {
-      id: 10028,
-      parentId: 10027,
-      title: '任务28',
-      planStartDate: '2024-03-10',
-      planEndDate: '2024-03-13',
-      actualStartDate: '2024-03-13',
-      actualEndDate: '2024-03-14',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10029,
-      parentId: 10027,
-      title: '任务29',
-      planStartDate: '2024-03-14',
-      planEndDate: '2024-03-18',
-      actualStartDate: '2024-03-16',
-      actualEndDate: '2024-03-18',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10030,
-      parentId: 10027,
-      title: '任务30',
-      planStartDate: '2024-03-19',
-      planEndDate: '2024-03-25',
-      actualStartDate: '2024-03-20',
-      actualEndDate: '2024-03-26',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10031,
-      parentId: null,
-      title: '任务31',
-      planStartDate: '2024-03-22',
-      planEndDate: '2024-03-24',
-      actualStartDate: '2024-03-19',
-      actualEndDate: '2024-03-20',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10032,
-      parentId: null,
-      title: '任务32',
-      planStartDate: '',
-      planEndDate: '',
-      actualStartDate: '',
-      actualEndDate: '',
-      planProgress: 90,
-      actualProgress: 80,
-      hasChild: true
-    },
-    {
-      id: 10033,
-      parentId: 10032,
-      title: '任务33',
-      planStartDate: '2024-03-09',
-      planEndDate: '2024-03-14',
-      actualStartDate: '2024-03-11',
-      actualEndDate: '2024-03-15',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10034,
-      parentId: 10032,
-      title: '任务34',
-      planStartDate: '2024-03-15',
-      planEndDate: '2024-03-21',
-      actualStartDate: '2024-03-16',
-      actualEndDate: '2024-03-19',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10035,
-      parentId: 10015,
-      title: '任务35',
-      planStartDate: '2024-03-16',
-      planEndDate: '2024-03-18',
-      actualStartDate: '2024-03-17',
-      actualEndDate: '2024-03-19',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10036,
-      parentId: 10015,
-      title: '任务36',
-      planStartDate: '2024-03-12',
-      planEndDate: '2024-03-14',
-      actualStartDate: '2024-03-13',
-      actualEndDate: '2024-03-15',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10037,
-      parentId: 10016,
-      title: '任务37',
-      planStartDate: '2024-03-19',
-      planEndDate: '2024-03-22',
-      actualStartDate: '2024-03-21',
-      actualEndDate: '2024-03-23',
-      planProgress: 90,
-      actualProgress: 80
-    },
-    {
-      id: 10038,
-      parentId: 10016,
-      title: '任务38',
-      planStartDate: '2024-03-23',
-      planEndDate: '2024-03-25',
-      actualStartDate: '2024-03-24',
-      actualEndDate: '2024-03-27',
-      planProgress: 90,
-      actualProgress: 80
-    }
-  ]
-  const multiRest = handleMultiTask(list)
-  ganttOptions.data = multiRest
+const applyFilter = () => {
+  ganttOptions.data = handleMultiTask(filteredList.value)
 }
 
-loadList()
+// 初始化 + 筛选变化时刷新甘特图
+applyFilter()
+
+/* ===================== 列表视图数据 ===================== */
+// 直接复用 filteredList,并补上状态字段
+const flatTasks = computed(() =>
+  filteredList.value.map((row) => ({
+    ...row,
+    state: row.hasChild ? '' : taskState(row)
+  }))
+)
+
+const hasAnyTask = computed(() => filteredList.value.length > 0)
+
+/* ===================== 统计 ===================== */
+// 只统计叶子任务
+const leafTasks = computed(() =>
+  rawList.filter((row) => !row.hasChild && filteredList.value.some((r) => r.id === row.id))
+)
+const totalCount = computed(() => leafTasks.value.length)
+const doingCount = computed(() => leafTasks.value.filter((r) => taskState(r) === 'doing').length)
+const doneCount = computed(() => leafTasks.value.filter((r) => taskState(r) === 'done').length)
+const delayedCount = computed(
+  () => leafTasks.value.filter((r) => taskState(r) === 'delayed').length
+)
+
+const stateLabel = (state) =>
+  state === 'done' ? '已完成' : state === 'delayed' ? '已延期' : '进行中'
+const stateTagType = (state) =>
+  state === 'done' ? 'success' : state === 'delayed' ? 'danger' : 'primary'
+const rowClassName = ({ row }) => (row.state === 'delayed' ? 'row-delayed' : '')
+
+const resetQuery = () => {
+  query.projectId = null
+  query.owner = ''
+  query.dateRange = []
+  query.state = 'all'
+  applyFilter()
+}
 </script>
+
+<style scoped lang="scss">
+.progress-page {
+  padding: 4px;
+}
+.progress-filter {
+  padding: 12px 16px;
+  margin-bottom: 12px;
+  background: var(--el-fill-color-light);
+  border-radius: 8px;
+}
+.progress-filter :deep(.el-form-item) {
+  margin-bottom: 8px;
+}
+.progress-toolbar {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  margin-bottom: 16px;
+}
+.progress-summary {
+  display: flex;
+  gap: 12px;
+}
+.summary-item {
+  min-width: 96px;
+  padding: 8px 14px;
+  background: var(--el-bg-color);
+  border: 1px solid var(--el-border-color-lighter);
+  border-radius: 8px;
+  text-align: center;
+}
+.summary-item span {
+  display: block;
+  color: var(--el-text-color-secondary);
+  font-size: 12px;
+}
+.summary-item strong {
+  font-size: 20px;
+  font-variant-numeric: tabular-nums;
+}
+.summary-item.doing strong {
+  color: var(--el-color-primary);
+}
+.summary-item.done strong {
+  color: var(--el-color-success);
+}
+.summary-item.delayed strong {
+  color: var(--el-color-danger);
+}
+.toolbar-right {
+  display: flex;
+  align-items: center;
+  gap: 12px;
+}
+.toolbar-hint {
+  color: var(--el-text-color-secondary);
+  font-size: 12px;
+}
+.progress-table :deep(.row-delayed) {
+  background: var(--el-color-danger-light-9);
+}
+
+.progress-page {
+  padding: 4px;
+}
+
+/* 四个统计卡片:顶部一行,等分占满宽度 */
+.progress-summary {
+  display: grid;
+  grid-template-columns: repeat(4, 1fr);
+  gap: 12px;
+  margin-bottom: 12px;
+}
+.summary-item {
+  padding: 14px 18px;
+  background: var(--el-bg-color);
+  border: 1px solid var(--el-border-color-lighter);
+  border-radius: 8px;
+  text-align: center;
+}
+.summary-item span {
+  display: block;
+  color: var(--el-text-color-secondary);
+  font-size: 12px;
+}
+.summary-item strong {
+  font-size: 22px;
+  font-variant-numeric: tabular-nums;
+}
+.summary-item.doing strong {
+  color: var(--el-color-primary);
+}
+.summary-item.done strong {
+  color: var(--el-color-success);
+}
+.summary-item.delayed strong {
+  color: var(--el-color-danger);
+}
+
+/* 筛选栏:白色背景 */
+.progress-filter {
+  padding: 12px 16px;
+  margin-bottom: 12px;
+  background: #fff;
+  border: 1px solid var(--el-border-color-lighter);
+  border-radius: 8px;
+}
+.progress-filter :deep(.el-form-item) {
+  margin-bottom: 8px;
+}
+</style>

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio