diff --git a/docs/plans/backend/2026-03-24-project-list-reanalyze-backend-implementation.md b/docs/plans/backend/2026-03-24-project-list-reanalyze-backend-implementation.md new file mode 100644 index 00000000..801f244f --- /dev/null +++ b/docs/plans/backend/2026-03-24-project-list-reanalyze-backend-implementation.md @@ -0,0 +1,151 @@ +# Project List Reanalyze Backend Implementation Plan + +> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** 确认并验证项目管理列表“重新分析”复用现有项目级重打标链路即可满足“重新打标并重新计算人数”的后端要求,不新增额外接口或并行逻辑。 + +**Architecture:** 后端实现保持不改代码的最短路径,继续复用 `CcdiBankTagController -> ProjectBankTagRebuildCoordinator -> CcdiBankTagServiceImpl -> CcdiProjectOverviewServiceImpl` 这条现有链路。实施工作集中在边界核验、接口契约回归、关键测试运行和实施记录沉淀,确保前端接入后不会因为后端口径不清而额外返工。 + +**Tech Stack:** Java 21, Spring Boot 3, JUnit 5, Mockito, Maven + +--- + +### Task 1: 核验现有后端链路已覆盖需求 + +**Files:** +- Modify: `docs/plans/backend/2026-03-24-project-list-reanalyze-backend-implementation.md` +- Reference: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiBankTagController.java` +- Reference: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/ProjectBankTagRebuildCoordinator.java` +- Reference: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiBankTagServiceImpl.java` +- Reference: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectOverviewServiceImpl.java` + +- [ ] **Step 1: Write the acceptance checklist** + +先在计划中明确本次后端必须被验证的四个事实: + +- `POST /ccdi/project/tags/rebuild` 支持只传 `projectId` +- 手动提交后项目状态会切换为 `3-打标中` +- 打标成功后会调用 `refreshOverviewEmployeeResults(projectId, operator)` +- `refreshOverviewEmployeeResults(...)` 会同步刷新高/中/低风险人数 + +- [ ] **Step 2: Run repository grep to verify the call chain** + +Run: + +```bash +rg -n "refreshOverviewEmployeeResults|submitManual|/rebuild|updateProjectStatus\\(projectId, CcdiProjectStatusConstants.TAGGING" ccdi-project/src/main/java -S +``` + +Expected: + +- 能同时看到控制器入口、协调器提交流程、`TAGGING` 状态切换和人数重算调用 + +- [ ] **Step 3: Keep implementation minimal** + +如果上述四个事实都成立,则明确记录: + +- 本次后端不新增接口 +- 本次后端不新增服务分支 +- 本次后端不新增人数重算调用 + +- [ ] **Step 4: Commit** + +```bash +git add docs/plans/backend/2026-03-24-project-list-reanalyze-backend-implementation.md +git commit -m "补充项目列表重新分析后端实施计划" +``` + +### Task 2: 运行关键后端测试锁定现有契约 + +**Files:** +- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiBankTagControllerTest.java` +- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/ProjectBankTagRebuildCoordinatorTest.java` +- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiBankTagServiceRiskCountRefreshTest.java` + +- [ ] **Step 1: Run controller and coordinator contract tests** + +Run: + +```bash +mvn -pl ccdi-project -Dtest=CcdiBankTagControllerTest,ProjectBankTagRebuildCoordinatorTest test +``` + +Expected: + +- `PASS` +- 能证明手动重打标入口、运行中防重提交流程和归档保护逻辑都已存在 + +- [ ] **Step 2: Run risk count refresh test** + +Run: + +```bash +mvn -pl ccdi-project -Dtest=CcdiBankTagServiceRiskCountRefreshTest test +``` + +Expected: + +- `PASS` +- 能证明重打标成功后会刷新员工结果并同步更新项目风险人数 + +- [ ] **Step 3: If any test fails, inspect before changing code** + +若失败,先检查是否为环境或依赖问题,再决定是否需要补充代码;本次默认目标是不产生新的后端代码改动。 + +- [ ] **Step 4: Commit** + +```bash +git status --short +``` + +Expected: + +- 若仅运行测试无文件变化,则本任务无需代码提交 + +### Task 3: 补充后端验证记录与边界说明 + +**Files:** +- Create: `docs/tests/records/2026-03-24-project-list-reanalyze-backend-verification.md` +- Create: `docs/reports/implementation/2026-03-24-project-list-reanalyze-backend-record.md` + +- [ ] **Step 1: Write verification skeleton** + +创建后端验证记录,至少包含: + +```markdown +# 项目管理列表重新分析后端验证记录 + +## 验证范围 +- 手动重打标接口可直接复用于列表页 +- 重打标开始后项目进入打标中 +- 重打标成功后自动重算项目风险人数 +- 运行中任务和归档项目保留既有后端保护 +``` + +- [ ] **Step 2: Record exact commands and results** + +把实际执行的测试命令和结果写入验证记录: + +```bash +mvn -pl ccdi-project -Dtest=CcdiBankTagControllerTest,ProjectBankTagRebuildCoordinatorTest,CcdiBankTagServiceRiskCountRefreshTest test +``` + +Expected: + +- 记录通过或失败原因 + +- [ ] **Step 3: Write the implementation record** + +在 `docs/reports/implementation/2026-03-24-project-list-reanalyze-backend-record.md` 中写明: + +- 为什么本次后端不需要改代码 +- 现有复用链路覆盖了哪些需求 +- 已验证的保护场景有哪些 +- 后续仅由前端接线即可进入实现阶段 + +- [ ] **Step 4: Commit** + +```bash +git add docs/tests/records/2026-03-24-project-list-reanalyze-backend-verification.md docs/reports/implementation/2026-03-24-project-list-reanalyze-backend-record.md +git commit -m "补充项目列表重新分析后端验证记录" +``` diff --git a/docs/plans/frontend/2026-03-24-project-list-reanalyze-frontend-implementation.md b/docs/plans/frontend/2026-03-24-project-list-reanalyze-frontend-implementation.md new file mode 100644 index 00000000..df2748cb --- /dev/null +++ b/docs/plans/frontend/2026-03-24-project-list-reanalyze-frontend-implementation.md @@ -0,0 +1,292 @@ +# Project List Reanalyze Frontend Implementation Plan + +> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** 让项目管理列表中的“重新分析”按钮真正调用现有项目重打标接口,提交成功后立即刷新列表并展示“打标中”状态。 + +**Architecture:** 复用现有 `ruoyi-ui/src/api/ccdiProject.js` 作为 API 收口点,在 `ruoyi-ui/src/views/ccdiProject/index.vue` 中把 `handleReAnalyze` 从本地提示改为真实异步提交逻辑,并将按钮级提交态透传到 `ProjectTable.vue`。测试采用现有前端仓库里“读取源码断言文案/调用痕迹”的轻量风格,补充一条接口接线测试和一条交互状态测试。 + +**Tech Stack:** Vue 2, Element UI, Axios request wrapper, Node, npm + +--- + +### Task 1: 先锁定“重新分析”接口契约 + +**Files:** +- Modify: `ruoyi-ui/src/api/ccdiProject.js` +- Test: `ruoyi-ui/tests/unit/project-list-reanalyze-api.test.js` + +- [ ] **Step 1: Write the failing test** + +新增一个轻量源码契约测试,锁定新增接口会调用正确的后端地址和请求方式: + +```javascript +const assert = require("assert"); +const fs = require("fs"); +const path = require("path"); + +const apiPath = path.resolve(__dirname, "../../src/api/ccdiProject.js"); +const source = fs.readFileSync(apiPath, "utf8"); + +assert( + source.includes("export function rebuildProjectTags(data)"), + "应新增项目重新分析接口封装" +); + +assert( + source.includes("url: '/ccdi/project/tags/rebuild'"), + "重新分析接口应指向项目标签重打标地址" +); + +assert( + source.includes("method: 'post'"), + "重新分析接口应使用 POST 请求" +); +``` + +- [ ] **Step 2: Run test to verify it fails** + +Run: + +```bash +cd ruoyi-ui +node tests/unit/project-list-reanalyze-api.test.js +``` + +Expected: + +- `FAIL` +- 原因是当前 `ccdiProject.js` 还没有 `rebuildProjectTags` 接口 + +- [ ] **Step 3: Write minimal implementation** + +在 `ruoyi-ui/src/api/ccdiProject.js` 中新增: + +```javascript +export function rebuildProjectTags(data) { + return request({ + url: '/ccdi/project/tags/rebuild', + method: 'post', + data + }) +} +``` + +约束: + +- 不新建独立 API 文件 +- 不改动现有其他接口命名和返回处理方式 + +- [ ] **Step 4: Run test to verify it passes** + +Run: + +```bash +cd ruoyi-ui +node tests/unit/project-list-reanalyze-api.test.js +``` + +Expected: + +- `PASS` + +- [ ] **Step 5: Commit** + +```bash +git add ruoyi-ui/src/api/ccdiProject.js ruoyi-ui/tests/unit/project-list-reanalyze-api.test.js +git commit -m "新增项目列表重新分析前端接口" +``` + +### Task 2: 将列表页重新分析按钮接入真实异步流程 + +**Files:** +- Modify: `ruoyi-ui/src/views/ccdiProject/index.vue` +- Modify: `ruoyi-ui/src/views/ccdiProject/components/ProjectTable.vue` +- Test: `ruoyi-ui/tests/unit/project-list-reanalyze-flow.test.js` + +- [ ] **Step 1: Write the failing test** + +新增一条交互接线测试,至少锁定以下行为: + +```javascript +const assert = require("assert"); +const fs = require("fs"); +const path = require("path"); + +const pagePath = path.resolve(__dirname, "../../src/views/ccdiProject/index.vue"); +const tablePath = path.resolve(__dirname, "../../src/views/ccdiProject/components/ProjectTable.vue"); +const pageSource = fs.readFileSync(pagePath, "utf8"); +const tableSource = fs.readFileSync(tablePath, "utf8"); + +assert( + pageSource.includes("rebuildProjectTags({ projectId: row.projectId })"), + "重新分析应调用真实重打标接口" +); + +assert( + pageSource.includes("this.$modal.msgSuccess(\"已开始重新分析\")") || + pageSource.includes("this.$modal.msgSuccess('已开始重新分析')"), + "重新分析成功提示应统一为已开始重新分析" +); + +assert( + /finally\\s*\\(.*?this\\.getList\\(/s.test(pageSource) || pageSource.includes("this.getList()"), + "重新分析成功后应刷新列表" +); + +assert( + tableSource.includes(":loading=\"reAnalyzeLoadingMap[String(scope.row.projectId)]\"") || + tableSource.includes(":loading=\"reAnalyzeLoadingMap[scope.row.projectId]\""), + "表格中的重新分析按钮应支持提交态" +); +``` + +- [ ] **Step 2: Run test to verify it fails** + +Run: + +```bash +cd ruoyi-ui +node tests/unit/project-list-reanalyze-flow.test.js +``` + +Expected: + +- `FAIL` +- 原因是当前 `handleReAnalyze` 仍然只是 `console.log` 加本地提示 + +- [ ] **Step 3: Write minimal implementation** + +在 `ruoyi-ui/src/views/ccdiProject/index.vue` 中: + +1. 引入 `rebuildProjectTags` +2. 在 `data()` 中新增按钮级提交态,例如: + +```javascript +reAnalyzeLoadingMap: {} +``` + +3. 将 `handleReAnalyze(row)` 改为: + +```javascript +async handleReAnalyze(row) { + const projectKey = String(row.projectId) + if (this.reAnalyzeLoadingMap[projectKey]) { + return + } + this.$set(this.reAnalyzeLoadingMap, projectKey, true) + try { + await rebuildProjectTags({ projectId: row.projectId }) + this.$modal.msgSuccess("已开始重新分析") + this.getList() + } catch (error) { + const message = error && error.message ? error.message : "重新分析失败,请稍后重试" + this.$modal.msgError(message) + } finally { + this.$set(this.reAnalyzeLoadingMap, projectKey, false) + } +} +``` + +在 `ruoyi-ui/src/views/ccdiProject/components/ProjectTable.vue` 中: + +1. 新增 `reAnalyzeLoadingMap` 属性 +2. 给“重新分析”按钮增加: + +```vue +:loading="reAnalyzeLoadingMap[String(scope.row.projectId)]" +:disabled="reAnalyzeLoadingMap[String(scope.row.projectId)]" +``` + +约束: + +- 只对“重新分析”按钮加提交态 +- 不引入轮询 +- 不新增确认弹窗 +- 不修改按钮显示范围,仍只在 `status === '1'` 时显示 + +- [ ] **Step 4: Run test to verify it passes** + +Run: + +```bash +cd ruoyi-ui +node tests/unit/project-list-reanalyze-flow.test.js +``` + +Expected: + +- `PASS` + +- [ ] **Step 5: Commit** + +```bash +git add ruoyi-ui/src/views/ccdiProject/index.vue ruoyi-ui/src/views/ccdiProject/components/ProjectTable.vue ruoyi-ui/tests/unit/project-list-reanalyze-flow.test.js +git commit -m "实现项目列表重新分析交互" +``` + +### Task 3: 补齐失败提示与回归验证 + +**Files:** +- Modify: `ruoyi-ui/tests/unit/project-list-reanalyze-flow.test.js` +- Create: `docs/reports/implementation/2026-03-24-project-list-reanalyze-frontend-record.md` + +- [ ] **Step 1: Extend the failing test for error handling** + +在 `project-list-reanalyze-flow.test.js` 中继续锁定以下文案与行为: + +```javascript +assert( + pageSource.includes("重新分析失败,请稍后重试"), + "重新分析失败时应有统一兜底提示" +); + +assert( + pageSource.includes("error.message"), + "有明确业务异常时应优先透传后端返回文案" +); +``` + +- [ ] **Step 2: Run tests to verify the final contract** + +Run: + +```bash +cd ruoyi-ui +node tests/unit/project-list-reanalyze-api.test.js +node tests/unit/project-list-reanalyze-flow.test.js +``` + +Expected: + +- 两条测试都 `PASS` + +- [ ] **Step 3: Run frontend build smoke check** + +Run: + +```bash +cd ruoyi-ui +npm run build:prod +``` + +Expected: + +- 构建成功 +- 不引入新的 ESLint 或模板编译错误 + +- [ ] **Step 4: Write the implementation record** + +新增实施记录 `docs/reports/implementation/2026-03-24-project-list-reanalyze-frontend-record.md`,覆盖: + +- 新增项目重分析 API 封装 +- 列表页“重新分析”按钮接入真实接口 +- 按钮提交态与成功/失败提示 +- 执行过的测试命令和结果 + +- [ ] **Step 5: Commit** + +```bash +git add ruoyi-ui/tests/unit/project-list-reanalyze-flow.test.js docs/reports/implementation/2026-03-24-project-list-reanalyze-frontend-record.md +git commit -m "补充项目列表重新分析前端实施记录" +``` diff --git a/docs/reports/implementation/2026-03-24-project-list-reanalyze-plan-record.md b/docs/reports/implementation/2026-03-24-project-list-reanalyze-plan-record.md new file mode 100644 index 00000000..4f3eef00 --- /dev/null +++ b/docs/reports/implementation/2026-03-24-project-list-reanalyze-plan-record.md @@ -0,0 +1,17 @@ +# 2026-03-24 项目管理列表重新分析实施计划产出记录 + +## 本次产出 + +- 新增后端实施计划 `docs/plans/backend/2026-03-24-project-list-reanalyze-backend-implementation.md` +- 新增前端实施计划 `docs/plans/frontend/2026-03-24-project-list-reanalyze-frontend-implementation.md` + +## 关键结论 + +- 前端实施计划负责真实接线、按钮提交态和单测补充 +- 后端实施计划负责现有链路验证和边界确认,不新增多余接口 +- 本次仍遵循“最短路径实现”,不引入轮询、进度条或额外重算接口 + +## 后续动作 + +- 进入实现阶段时,先执行前端实施计划 +- 后端按计划完成关键测试与验证记录沉淀