R60 A1-A6:首页工作台优化

这个提交包含在:
2026-04-12 12:30:14 +08:00
父节点 dbab1d7b6e
当前提交 3f8c5144c2
共修改 7 个文件,包含 1514 行新增和 14 行删除
@@ -0,0 +1,7 @@
ID,Title,Description,Acceptance,Test_Method,Tools,Dev_Status,Review1_Status,Regression_Status,Files,Dependencies,Notes
"A1","R60 执行合同建档与范围冻结","创建并校验 R60 首页工作台优化执行合同 CSV,冻结范围:1) 后端扩展 portal/home 返回 recentActivities 与 teamStatusBoard;2) 新增 GET /api/portal/team-status 轻量端点;3) PortalHomePage 增加快捷操作栏、团队全员状态、近期动态流三个区块;4) MobilePortalPage 增加团队状态卡片与待办聚合。不新增 Prisma 迁移,所有数据从现有表聚合。","issues/2026-04-12_r60-portal-workbench.csv 列完整、Dependencies 为 JSON 数组字符串、Test_Method 可复现;范围仅覆盖 R60,不混入其他模块。","命令:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-04-12_r60-portal-workbench.csv。检查:1) 对照 AGENTS.md 与 issues/README.md 确认 12 列完整;2) A2-A6 依赖链符合 backend→frontend→reviewer→qa 收口;3) 无 Prisma 迁移。","manual","DONE","DONE","DONE","issues/2026-04-12_r60-portal-workbench.csv","[]","回滚路径:删除本次 CSV 不影响业务。"
"A2","后端扩展 portal/home 与新增 team-status 端点","在 portal.js 扩展 GET /api/portal/home 返回两个新字段:1) recentActivities[]——从 auditLog 聚合最近 15 条业务动态(报销提交/审批、请假提交/审批、考勤异常、资产变动等),每条含 type/actor/summary/timestamp/href;2) teamStatusBoard[]——全员今日状态列表(id/name/avatarUrl/presenceStatus/attendanceStatus/leaveInfo)。新增 GET /api/portal/team-status 独立端点返回 teamStatusBoard,供移动端单独刷新。两个端点均需认证,team-status 端点不依赖 portalHome 特性开关。","1) GET /api/portal/home 响应新增 recentActivities(数组,每项含 id/type/actorName/summary/createdAt/href)和 teamStatusBoard(数组,每项含 employeeId/name/avatarUrl/presenceStatus/attendanceClockIn/attendanceClockOut/onLeave/leaveType);2) GET /api/portal/team-status 独立返回 teamStatusBoard,响应结构与 portal/home 中一致;3) recentActivities 从 auditLog 表按 created_at DESC 取最近 15 条,过滤 action 在 [reimbursement.submit, reimbursement.approve, reimbursement.reject, leave.submit, leave.approve, leave.reject, attendance.clock_in, attendance.clock_out, attendance.supplement, asset.assign, asset.return] 范围内;4) teamStatusBoard 聚合 employee(active)+ 今日 presenceHistory + 今日 attendanceRecord + 当日 leaveRequest 状态;5) 不新增 Prisma 迁移。","命令:export PATH=/home/shunli/.nvm/versions/node/v22.20.0/bin:$PATH && cd server && npx prisma validate && node --check src/routes/portal.js && npm test -- server/tests/unit/routes/portal.test.js 2>/dev/null; echo done。业务:1) 调用 GET /api/portal/home,检查响应含 recentActivities 和 teamStatusBoard 字段;2) 调用 GET /api/portal/team-status,检查返回全员状态数组;3) recentActivities 按时间倒序、不超过 15 条;4) teamStatusBoard 包含所有 active 员工。","manual","DONE","DONE","DONE","server/src/routes/portal.js|server/tests/unit/routes/portal.test.js","[""A1""]","回滚路径:移除 portal.js 新增的 recentActivities/teamStatusBoard 聚合逻辑与 team-status 路由。无 Prisma 迁移,回退仅需代码回滚。auditLog action 值需与现有审计日志 action 字段实际值对齐,实现时先查 schema 确认。"
"A3","PortalHomePage 快捷操作栏与团队全员状态","重构 PortalHomePage 布局,在原有 Hero 区域下方新增两个区块:1) 快捷操作栏——一排图标按钮(提交请假、提交报销、打卡、提交周报),点击跳转对应页面或触发打卡操作;2) 团队全员状态面板——展示 teamStatusBoard 全员头像+姓名+今日状态(在岗/请假/外出/未打卡等),<10 人一屏展示无需分页,每人显示 avatar、name、presenceStatus badge、attendanceStatus、leaveInfo。使用 Tailwind grid 布局,响应式适配移动端。","1) 首页 Hero 下方出现快捷操作栏,含至少 4 个操作按钮(请假/报销/打卡/周报),各按钮点击跳转正确路径;2) 团队全员状态面板展示所有 active 员工,每人显示头像(或首字 fallback)、姓名、出勤状态 badge(在岗绿/请假橙/外出蓝/未打卡灰);3) 考勤打卡按钮调用 POST /api/attendance/clock-in 或 clock-out(根据今日状态判断),成功后刷新状态;4) 页面首屏加载时请求 portal/home 一次即获取所有数据,不额外请求 team-status。","命令:export PATH=/home/shunli/.nvm/versions/node/v22.20.0/bin:$PATH && cd client && npm run typecheck && npm run build。业务:1) 登录后访问 /portal,确认快捷操作栏可见且各按钮可点击跳转;2) 团队状态面板显示全员,badge 颜色符合状态;3) 打卡按钮调用正确 API 并刷新显示。","manual","DONE","DONE","DOING","client/src/pages/PortalHomePage.tsx|client/src/api/portal.ts","[""A2""]","回滚路径:恢复 PortalHomePage 原有布局,移除快捷操作栏与团队状态面板。打卡操作复用 R59 已有的 attendance API,不新增端点。"
"A4","PortalHomePage 待办聚合与近期动态流","在 PortalHomePage 继续新增两个区块:1) 今日待办聚合——将待审批任务、逾期 TODO、合同到期预警等散落在各模块的待办事项合并展示,每条含图标+标题+来源模块+操作按钮(跳转),按优先级排序,最多展示 10 条;2) 近期动态流——展示 recentActivities,每条显示操作人头像+操作描述+时间戳,可点击跳转详情页。两个区块放在团队状态面板下方,使用 card 容器。","1) 今日待办聚合区块可见,从 portal/home 现有的 pendingTasks/todoSummary/cards 中提取并合并展示,每条可点击跳转;2) 近期动态流区块可见,展示 recentActivities 列表,每条含操作人名、操作摘要、相对时间(如'2小时前')、可点击跳转 href;3) 动态流为空时显示'暂无近期动态'占位;4) 待办为空时显示'暂无待办事项,休息一下吧'占位。","命令:export PATH=/home/shunli/.nvm/versions/node/v22.20.0/bin:$PATH && cd client && npm run typecheck && npm run build。业务:1) 登录后 /portal 可见待办聚合和动态流两个区块;2) 待办条目点击可跳转到正确页面;3) 动态流显示最近业务操作,时间格式友好。","manual","DONE","DONE","DOING","client/src/pages/PortalHomePage.tsx","[""A3""]","回滚路径:移除待办聚合与动态流区块,保留 A3 的快捷操作和团队状态。相对时间格式化可用简单工具函数,不引入 dayjs/moment。"
"A5","MobilePortalPage 团队状态与待办聚合同步","在 MobilePortalPage 新增两个区块:1) 团队状态卡片——在考勤打卡区域下方展示全员今日状态,紧凑的横向滚动或 grid 布局,显示头像+姓名+状态 badge;2) 待办聚合——合并审批待办与 TODO 展示前 5 条,每条可点击跳转。团队状态使用 GET /api/portal/team-status 端点获取,支持下拉刷新。","1) MobilePortalPage 考勤区域下方出现团队状态卡片,展示全员头像+姓名+状态;2) 团队状态下方出现待办聚合,展示前 5 条待办,每条可点击;3) 团队状态卡片调用 GET /api/portal/team-status(非 portal/home),减少移动端数据传输;4) 下拉或点击刷新可更新团队状态。","命令:export PATH=/home/shunli/.nvm/versions/node/v22.20.0/bin:$PATH && cd client && npm run typecheck && npm run build。业务:1) 访问 /mobile,考勤区下方可见团队状态和待办聚合;2) 点击待办跳转正确页面;3) 团队状态数据来自 /api/portal/team-status 端点。","manual","DONE","DONE","DOING","client/src/pages/MobilePortalPage.tsx|client/src/api/portal.ts","[""A2"",""A4""]","回滚路径:移除 MobilePortalPage 新增的团队状态和待办区块,恢复原布局。"
"A6","QA、状态回填与提交收口","执行 R60 post-check 与业务回归,回填 CSV 状态并完成提交收口,确保首页工作台新功能无回归。","后端与前端校验全部通过;快捷操作、团队状态、待办聚合、动态流、移动端同步回归完成;issues/2026-04-12_r60-portal-workbench.csv 的 Dev_Status、Review1_Status、Regression_Status 按测试结果回填。","命令:export PATH=/home/shunli/.nvm/versions/node/v22.20.0/bin:$PATH && cd server && npx prisma validate && node --check src/routes/portal.js && npm test -- server/tests/unit/routes/portal.test.js 2>/dev/null && cd ../client && npm run typecheck && npm run build。业务:1) /portal 首页可见快捷操作栏、团队状态、待办聚合、动态流四个新区块;2) 各操作按钮功能正常;3) /mobile 可见团队状态和待办聚合;4) 不影响原有 portal 卡片、公告、快捷入口等功能。","manual","DOING","DOING","DOING","issues/2026-04-12_r60-portal-workbench.csv|server/src/routes/portal.js|client/src/pages/PortalHomePage.tsx|client/src/pages/MobilePortalPage.tsx","[""A5""]","回滚路径:若 QA 发现关键回归,暂停提交并回退对应代码变更。"
1 ID Title Description Acceptance Test_Method Tools Dev_Status Review1_Status Regression_Status Files Dependencies Notes
2 A1 R60 执行合同建档与范围冻结 创建并校验 R60 首页工作台优化执行合同 CSV,冻结范围:1) 后端扩展 portal/home 返回 recentActivities 与 teamStatusBoard;2) 新增 GET /api/portal/team-status 轻量端点;3) PortalHomePage 增加快捷操作栏、团队全员状态、近期动态流三个区块;4) MobilePortalPage 增加团队状态卡片与待办聚合。不新增 Prisma 迁移,所有数据从现有表聚合。 issues/2026-04-12_r60-portal-workbench.csv 列完整、Dependencies 为 JSON 数组字符串、Test_Method 可复现;范围仅覆盖 R60,不混入其他模块。 命令:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-04-12_r60-portal-workbench.csv。检查:1) 对照 AGENTS.md 与 issues/README.md 确认 12 列完整;2) A2-A6 依赖链符合 backend→frontend→reviewer→qa 收口;3) 无 Prisma 迁移。 manual DONE DONE DONE issues/2026-04-12_r60-portal-workbench.csv [] 回滚路径:删除本次 CSV 不影响业务。
3 A2 后端扩展 portal/home 与新增 team-status 端点 在 portal.js 扩展 GET /api/portal/home 返回两个新字段:1) recentActivities[]——从 auditLog 聚合最近 15 条业务动态(报销提交/审批、请假提交/审批、考勤异常、资产变动等),每条含 type/actor/summary/timestamp/href;2) teamStatusBoard[]——全员今日状态列表(id/name/avatarUrl/presenceStatus/attendanceStatus/leaveInfo)。新增 GET /api/portal/team-status 独立端点返回 teamStatusBoard,供移动端单独刷新。两个端点均需认证,team-status 端点不依赖 portalHome 特性开关。 1) GET /api/portal/home 响应新增 recentActivities(数组,每项含 id/type/actorName/summary/createdAt/href)和 teamStatusBoard(数组,每项含 employeeId/name/avatarUrl/presenceStatus/attendanceClockIn/attendanceClockOut/onLeave/leaveType);2) GET /api/portal/team-status 独立返回 teamStatusBoard,响应结构与 portal/home 中一致;3) recentActivities 从 auditLog 表按 created_at DESC 取最近 15 条,过滤 action 在 [reimbursement.submit, reimbursement.approve, reimbursement.reject, leave.submit, leave.approve, leave.reject, attendance.clock_in, attendance.clock_out, attendance.supplement, asset.assign, asset.return] 范围内;4) teamStatusBoard 聚合 employee(active)+ 今日 presenceHistory + 今日 attendanceRecord + 当日 leaveRequest 状态;5) 不新增 Prisma 迁移。 命令:export PATH=/home/shunli/.nvm/versions/node/v22.20.0/bin:$PATH && cd server && npx prisma validate && node --check src/routes/portal.js && npm test -- server/tests/unit/routes/portal.test.js 2>/dev/null; echo done。业务:1) 调用 GET /api/portal/home,检查响应含 recentActivities 和 teamStatusBoard 字段;2) 调用 GET /api/portal/team-status,检查返回全员状态数组;3) recentActivities 按时间倒序、不超过 15 条;4) teamStatusBoard 包含所有 active 员工。 manual DONE DONE DONE server/src/routes/portal.js|server/tests/unit/routes/portal.test.js ["A1"] 回滚路径:移除 portal.js 新增的 recentActivities/teamStatusBoard 聚合逻辑与 team-status 路由。无 Prisma 迁移,回退仅需代码回滚。auditLog action 值需与现有审计日志 action 字段实际值对齐,实现时先查 schema 确认。
4 A3 PortalHomePage 快捷操作栏与团队全员状态 重构 PortalHomePage 布局,在原有 Hero 区域下方新增两个区块:1) 快捷操作栏——一排图标按钮(提交请假、提交报销、打卡、提交周报),点击跳转对应页面或触发打卡操作;2) 团队全员状态面板——展示 teamStatusBoard 全员头像+姓名+今日状态(在岗/请假/外出/未打卡等),<10 人一屏展示无需分页,每人显示 avatar、name、presenceStatus badge、attendanceStatus、leaveInfo。使用 Tailwind grid 布局,响应式适配移动端。 1) 首页 Hero 下方出现快捷操作栏,含至少 4 个操作按钮(请假/报销/打卡/周报),各按钮点击跳转正确路径;2) 团队全员状态面板展示所有 active 员工,每人显示头像(或首字 fallback)、姓名、出勤状态 badge(在岗绿/请假橙/外出蓝/未打卡灰);3) 考勤打卡按钮调用 POST /api/attendance/clock-in 或 clock-out(根据今日状态判断),成功后刷新状态;4) 页面首屏加载时请求 portal/home 一次即获取所有数据,不额外请求 team-status。 命令:export PATH=/home/shunli/.nvm/versions/node/v22.20.0/bin:$PATH && cd client && npm run typecheck && npm run build。业务:1) 登录后访问 /portal,确认快捷操作栏可见且各按钮可点击跳转;2) 团队状态面板显示全员,badge 颜色符合状态;3) 打卡按钮调用正确 API 并刷新显示。 manual DONE DONE DOING client/src/pages/PortalHomePage.tsx|client/src/api/portal.ts ["A2"] 回滚路径:恢复 PortalHomePage 原有布局,移除快捷操作栏与团队状态面板。打卡操作复用 R59 已有的 attendance API,不新增端点。
5 A4 PortalHomePage 待办聚合与近期动态流 在 PortalHomePage 继续新增两个区块:1) 今日待办聚合——将待审批任务、逾期 TODO、合同到期预警等散落在各模块的待办事项合并展示,每条含图标+标题+来源模块+操作按钮(跳转),按优先级排序,最多展示 10 条;2) 近期动态流——展示 recentActivities,每条显示操作人头像+操作描述+时间戳,可点击跳转详情页。两个区块放在团队状态面板下方,使用 card 容器。 1) 今日待办聚合区块可见,从 portal/home 现有的 pendingTasks/todoSummary/cards 中提取并合并展示,每条可点击跳转;2) 近期动态流区块可见,展示 recentActivities 列表,每条含操作人名、操作摘要、相对时间(如'2小时前')、可点击跳转 href;3) 动态流为空时显示'暂无近期动态'占位;4) 待办为空时显示'暂无待办事项,休息一下吧'占位。 命令:export PATH=/home/shunli/.nvm/versions/node/v22.20.0/bin:$PATH && cd client && npm run typecheck && npm run build。业务:1) 登录后 /portal 可见待办聚合和动态流两个区块;2) 待办条目点击可跳转到正确页面;3) 动态流显示最近业务操作,时间格式友好。 manual DONE DONE DOING client/src/pages/PortalHomePage.tsx ["A3"] 回滚路径:移除待办聚合与动态流区块,保留 A3 的快捷操作和团队状态。相对时间格式化可用简单工具函数,不引入 dayjs/moment。
6 A5 MobilePortalPage 团队状态与待办聚合同步 在 MobilePortalPage 新增两个区块:1) 团队状态卡片——在考勤打卡区域下方展示全员今日状态,紧凑的横向滚动或 grid 布局,显示头像+姓名+状态 badge;2) 待办聚合——合并审批待办与 TODO 展示前 5 条,每条可点击跳转。团队状态使用 GET /api/portal/team-status 端点获取,支持下拉刷新。 1) MobilePortalPage 考勤区域下方出现团队状态卡片,展示全员头像+姓名+状态;2) 团队状态下方出现待办聚合,展示前 5 条待办,每条可点击;3) 团队状态卡片调用 GET /api/portal/team-status(非 portal/home),减少移动端数据传输;4) 下拉或点击刷新可更新团队状态。 命令:export PATH=/home/shunli/.nvm/versions/node/v22.20.0/bin:$PATH && cd client && npm run typecheck && npm run build。业务:1) 访问 /mobile,考勤区下方可见团队状态和待办聚合;2) 点击待办跳转正确页面;3) 团队状态数据来自 /api/portal/team-status 端点。 manual DONE DONE DOING client/src/pages/MobilePortalPage.tsx|client/src/api/portal.ts ["A2","A4"] 回滚路径:移除 MobilePortalPage 新增的团队状态和待办区块,恢复原布局。
7 A6 QA、状态回填与提交收口 执行 R60 post-check 与业务回归,回填 CSV 状态并完成提交收口,确保首页工作台新功能无回归。 后端与前端校验全部通过;快捷操作、团队状态、待办聚合、动态流、移动端同步回归完成;issues/2026-04-12_r60-portal-workbench.csv 的 Dev_Status、Review1_Status、Regression_Status 按测试结果回填。 命令:export PATH=/home/shunli/.nvm/versions/node/v22.20.0/bin:$PATH && cd server && npx prisma validate && node --check src/routes/portal.js && npm test -- server/tests/unit/routes/portal.test.js 2>/dev/null && cd ../client && npm run typecheck && npm run build。业务:1) /portal 首页可见快捷操作栏、团队状态、待办聚合、动态流四个新区块;2) 各操作按钮功能正常;3) /mobile 可见团队状态和待办聚合;4) 不影响原有 portal 卡片、公告、快捷入口等功能。 manual DOING DOING DOING issues/2026-04-12_r60-portal-workbench.csv|server/src/routes/portal.js|client/src/pages/PortalHomePage.tsx|client/src/pages/MobilePortalPage.tsx ["A5"] 回滚路径:若 QA 发现关键回归,暂停提交并回退对应代码变更。