# 原型完善 WBS 执行计划 — P0/P1/P2 任务拆解 > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. **Goal:** 基于原型复盘结论,按优先级分 5 个迭代完成全部 15 个遗留工作项 **Architecture:** 增量修改现有代码,不重构。后端 Spring Boot + MyBatis-Plus,前端 Vue 3 + Element Plus,遵循已有代码模式。每次迭代产出可编译、可运行的增量。 **Tech Stack:** Java 17, Spring Boot 3.4.5, MyBatis-Plus, Vue 3 (Composition API), Element Plus, Pinia, PostgreSQL 15 --- ## 迭代路线图 | 迭代 | 周期 | 聚焦 | 任务数 | 估计工时 | |------|------|------|--------|---------| | **I10** | T0+1W | M1 字段补齐 + M4 批量导入 | 4 | 8.5h | | **I11** | T0+2W | M2 增强 + M11 基础安全 | 5 | 10.5h | | **I12** | T0+3W | M6 配置管理 | 2 | 7h | | **I13** | T0+4W | M9 CSV + M10 审计 | 2 | 5h | | **V2.0** | T0+6W | M11 角色模型重构 | 2 | 14h | --- ## 迭代 I10:M1 字段补齐 + M4 批量导入(P0) ### Task I10-1: M1 客户表加字段(行业/地址/开票信息) **Files:** - Create: `services/delivery-platform-api/src/main/resources/db/migration/V9__m1_customer_fields.sql` - Modify: `services/delivery-platform-api/src/main/java/.../persistence/customer/PlatformCustomer.java` - Modify: `services/delivery-platform-api/src/main/java/.../customer/CustomerController.java` - Modify: `services/delivery-platform-api/src/main/java/.../web/dto/CustomerRequest.java` - Modify: `services/delivery-platform-api/src/main/java/.../web/dto/CustomerResponse.java` - Modify: `web/delivery-platform-ui/src/views/CustomersView.vue` **DB Migration:** ```sql -- V9__m1_customer_fields.sql ALTER TABLE platform_customer ADD COLUMN IF NOT EXISTS industry VARCHAR(128), ADD COLUMN IF NOT EXISTS address TEXT, ADD COLUMN IF NOT EXISTS billing_info TEXT, ADD COLUMN IF NOT EXISTS customer_code VARCHAR(64); ``` **Backend:** - `PlatformCustomer.java`: 添加 `industry`, `address`, `billingInfo`, `customerCode` 字段 (String, OffsetDateTime 无需) - `CustomerRequest.java`: 添加 industry, address, billingInfo, customerCode 字段 + getters/setters - `CustomerResponse.java`: 同前 - `CustomerController.java`: 在 create/update 中透传新字段 **Frontend:** - `CustomersView.vue`: 客户创建/编辑对话框增加 4 个字段:行业(input)、地址(textarea)、开票信息(textarea)、客户编码(input) **Steps:** 1. Create V9 migration SQL 2. Update PlatformCustomer entity 3. Update CustomerRequest/CustomerResponse DTOs 4. Update CustomersView.vue dialog 5. Compile & build 6. Commit --- ### Task I10-2: M1 项目表加字段(计划起止/项目经理) **Files:** - Modify: `services/.../db/migration/V9__m1_customer_fields.sql` (append) - Modify: `services/.../persistence/project/PlatformProject.java` - Modify: `services/.../project/ProjectController.java` - Modify: `services/.../web/dto/ProjectRequest.java` - Modify: `services/.../web/dto/ProjectResponse.java` - Modify: `web/.../views/ProjectsView.vue` **DB:** ```sql -- 追加到 V9 ALTER TABLE platform_project ADD COLUMN IF NOT EXISTS planned_start_date DATE, ADD COLUMN IF NOT EXISTS planned_end_date DATE, ADD COLUMN IF NOT EXISTS project_manager VARCHAR(128); ``` **Backend:** - `PlatformProject.java`: 加 `plannedStartDate` (LocalDate), `plannedEndDate` (LocalDate), `projectManager` (String) - `ProjectRequest.java` / `ProjectResponse.java`: 对应加字段 - `ProjectController.java`: 透传 **Frontend:** - `ProjectsView.vue`: 对话框加 计划开始日期(日期选择器)、计划结束日期(日期选择器)、项目经理(input) --- ### Task I10-3: M1 客户详情聚合视图 **Files:** - Create: `web/.../views/CustomerDetailView.vue` - Modify: `web/.../router/index.js` - Modify: `web/.../views/CustomersView.vue` (行操作加「详情」) - Modify: `web/.../api/platform.js` **Backend:** - `CustomerController.java`: 添加 `GET /api/v1/customers/{id}/summary` 返回聚合数据 - `CustomerService.java`: 添加 `getCustomerSummary(id)` 方法,查询关联项目数、合同数、SN 数 **Frontend:** - `CustomerDetailView.vue`: 展示客户基本信息 + 聚合卡片(关联项目数、在履约合同数、在途 SN 数) - `CustomersView.vue`: 行操作加「详情」按钮 → 跳转 `/customers/:id` - router: 加 `/customers/:id` → CustomerDetailView - platform.js: 加 `getCustomerSummary(id)` --- ### Task I10-4: M4 SN 批量导入 **Files:** - Create: `services/.../api/web/dto/SnBatchImportRequest.java` - Modify: `services/.../api/license/LicenseSnController.java` - Modify: `services/.../api/service/LicenseSnService.java` - Modify: `web/.../views/LicenseSnListView.vue` - Modify: `web/.../api/platform.js` **Backend:** - `LicenseSnController.java`: 添加 `POST /api/v1/license-sns/batch-import` - `LicenseSnService.java`: 添加 `batchImport(List)` 方法,逐条校验并插入,返回成功数/失败数 - `SnBatchImportRequest.java`: snCode, projectId, contractLineId, activationRemark **Frontend:** - `LicenseSnListView.vue`: 加「批量导入」按钮 → 弹窗文本域(一行一个 SN) - `platform.js`: 加 `batchImportLicenseSns(body)` --- ## 迭代 I11:M2 增强 + M11 基础安全(P1) ### Task I11-1: M2 合同附件上传 **Files:** - Modify: `services/.../api/contracts/ContractController.java` - Modify: `services/.../api/service/ContractService.java` - Modify: `web/.../views/ContractDetailView.vue` - Modify: `web/.../api/platform.js` **Backend:** - 附件存储为本地文件系统路径 + DB 记录(`platform_contract_attachment` 新表) - 或简化:用 `TEXT` 字段存附件 URL/备注 - `ContractService.java`: 加 `uploadAttachment(contractId, MultipartFile)` / `getAttachments(contractId)` **Frontend:** - `ContractDetailView.vue`: 加「附件」区块 + 上传按钮 + 文件列表 --- ### Task I11-2: M2 合同变更版本 **Files:** - Create: `services/.../db/migration/V10__contract_change_version.sql` - Create: `services/.../api/contracts/ContractChangeController.java` - Create: `services/.../api/web/dto/ContractChangeRequest.java` - Modify: `services/.../api/service/ContractService.java` - Modify: `web/.../views/ContractDetailView.vue` - Modify: `web/.../router/index.js` **DB:** ```sql CREATE TABLE platform_contract_change ( id BIGSERIAL PRIMARY KEY, contract_id BIGINT NOT NULL REFERENCES platform_contract(id), version INT NOT NULL, change_type VARCHAR(64) NOT NULL, before_snapshot JSONB, after_snapshot JSONB, reason TEXT, status VARCHAR(32) NOT NULL DEFAULT 'DRAFT', created_by VARCHAR(256), created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); ``` **Backend:** - 合同状态机新增 `CHANGING` 状态流转 - 创建变更单后锁住原合同行,允许编辑后生成新版本 **Frontend:** - `ContractDetailView.vue`: 状态操作条加「发起变更」「完成变更」按钮 - 「变更历史」区块展示版本列表 --- ### Task I11-3: M11 空闲超时自动登出 **Files:** - Modify: `web/.../src/layout/MainLayout.vue` - Possibly: `web/.../src/stores/auth.js` **Frontend:** - `MainLayout.vue`: 监听用户活动事件(mousemove, keydown, click),空闲 N 分钟后自动调用 `auth.logout()` + 跳转登录页 - 可配置超时时间(默认 30 分钟) - 超时前 1 分钟弹窗提示 --- ### Task I11-4: M11 登录失败锁定机制 **Files:** - Modify: `services/.../api/auth/AuthController.java` - Modify: `services/.../api/config/SecurityConfig.java` - Possibly new table `platform_login_attempt` **Backend:** - 记录登录失败次数(内存 Map 或 DB 表) - 连续失败 N 次(默认 5 次)后锁定账号 X 分钟 - 返回错误码 `ACCOUNT_LOCKED` --- ### Task I11-5: M11 密码修改功能 **Files:** - Modify: `services/.../api/auth/AuthController.java` - Modify: `web/.../views/LoginView.vue` 或新建 `ProfileView.vue` - Modify: `web/.../router/index.js` **Backend:** - `POST /api/v1/auth/change-password` : body { oldPassword, newPassword } - 校验旧密码正确性 + 新密码强度 **Frontend:** - 用户菜单加「修改密码」入口 - 弹窗表单:旧密码、新密码、确认新密码 --- ## 迭代 I12:M6 配置管理(P1) ### Task I12-1: M6 比特 ID 映射管理 **Files:** - Create: `services/.../db/migration/V11__m6_id_mapping.sql` - Create: `services/.../api/web/dto/BitanswerIdMappingRequest.java` - Create: `services/.../api/web/dto/BitanswerIdMappingResponse.java` - Create: `services/.../api/persistence/integration/PlatformBitanswerIdMapping.java` - Create: `services/.../api/persistence/integration/PlatformBitanswerIdMappingMapper.java` - Modify: `services/.../api/integration/IntegrationCatalogController.java` - Modify: `services/.../api/service/IntegrationCatalogService.java` - Create: `web/.../views/IntegrationIdMappingView.vue` - Modify: `web/.../router/index.js` - Modify: `web/.../api/platform.js` **DB:** ```sql CREATE TABLE platform_bitanswer_id_mapping ( id BIGSERIAL PRIMARY KEY, product_line_id BIGINT NOT NULL REFERENCES platform_product_line(id), environment_id BIGINT REFERENCES platform_integration_environment(id), bitanswer_product_id VARCHAR(128), bitanswer_template_id VARCHAR(128), bitanswer_business_id VARCHAR(128), feature_key VARCHAR(64), bitanswer_feature_id VARCHAR(128), created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); ``` **Backend:** CRUD **Frontend:** 映射管理页面,按产品线+环境筛选,表格展示映射关系 --- ### Task I12-2: M6 授权 JSON 模板管理 **Files:** - Create: `services/.../db/migration/V12__m6_json_template.sql` - Create: `services/.../api/persistence/integration/PlatformJsonTemplate.java` - Create: `services/.../api/persistence/integration/PlatformJsonTemplateMapper.java` - Create: `services/.../api/web/dto/JsonTemplateRequest.java` - Modify: `services/.../api/service/IntegrationCatalogService.java` - Modify: `services/.../api/integration/IntegrationCatalogController.java` - Create: `web/.../views/IntegrationJsonTemplateView.vue` - Modify: `web/.../router/index.js` **DB:** ```sql CREATE TABLE platform_json_template ( id BIGSERIAL PRIMARY KEY, name VARCHAR(128) NOT NULL, version INT NOT NULL DEFAULT 1, template_content TEXT NOT NULL, schema_version INT NOT NULL DEFAULT 1, change_notes TEXT, created_by VARCHAR(256), created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); ``` **Backend:** CRUD + JSON Schema 校验 + 版本递增 **Frontend:** 模板列表 + 创建/编辑页(JSON 编辑器 + 校验结果展示) --- ## 迭代 I13:M9 CSV + M10 审计(P1-P2) ### Task I13-1: M9 报表导出 CSV **Files:** - Modify: `services/.../api/report/ReportController.java` - Modify: `services/.../api/service/ReportService.java` - Modify: `web/.../views/ContractSnReportView.vue` **Backend:** - `ReportController.java`: 加 `GET /api/v1/reports/export?type=contract-sn` 返回 CSV 文件流 - 使用 `Content-Disposition: attachment; filename=report.csv` - `ReportService.java`: 加 `exportContractSnReport()` 生成 CSV 字符串 **Frontend:** - `ContractSnReportView.vue`: 加「导出 CSV」按钮,调后端接口下载文件 --- ### Task I13-2: M10 审计检索/导出 **Files:** - Create: `web/.../views/AuditSearchView.vue` - Modify: `web/.../router/index.js` - Modify: `web/.../api/platform.js` - Modify: `services/.../api/service/AuditService.java` - Modify: `services/.../api/web/dto/AuditEventResponse.java` (if needed) **Backend:** - `GET /api/v1/audit-events` 增加筛选参数:entityType, entityId, userId, from, to - `GET /api/v1/audit-events/export` → CSV 导出 **Frontend:** - `AuditSearchView.vue`: 筛选表单 + 审计日志表格 + 导出按钮 - Router: `/audit` → AuditSearchView --- ## V2.0:M11 角色模型重构(P2) ### Task V2-1: M11 角色模型对齐产品定义 **Files:** (大量修改) - Modify: `services/.../api/config/SecurityConfig.java` - Modify: `services/.../api/security/PlatformRoles.java` - Modify: 所有 Controller 的 `@PreAuthorize` 注解 - Modify: `web/.../router/index.js` - Modify: `web/.../layout/MainLayout.vue` - Modify: `web/.../views/HomeView.vue` - New seeds: `services/.../db/migration/V13__seed_roles.sql` **Changes:** - 废弃 `DEVELOPER` / `OPS` 角色 - 实现产品定义角色:`SALES`, `ORDER_SUPPORT`, `DELIVERY`, `LICENSE_OPS`, `DEV_SUPPORT`, `FINANCE_VIEW`, `COMPLIANCE`, `EXEC_VIEW` - 更新所有路由 `meta.roles` - 更新侧栏菜单 `roles` - 更新后端所有 `@PreAuthorize` 注解 --- ### Task V2-2: M11 按钮级权限码 **Files:** (大量修改) - Create: `web/.../src/directives/permission.js` - Modify: 所有 Vue 页面的操作按钮加 `v-permission` 指令 - Modify: 后端 Controller 方法加细粒度 `@PreAuthorize` **Frontend:** - 创建 `v-permission` 自定义指令 (类似 `v-permission="'contract:order:export'"`) - Pinia store 存储用户权限码列表 - 按钮级:`新建` **Backend:** - 在 JWT token 中包含权限码列表 - 每个 mutating 接口用 `@PreAuthorize("hasAuthority('license:sn:rw')")` --- ## 任务依赖关系 ```mermaid flowchart LR subgraph I10["I10 (P0聚焦)"] T10_1[Task I10-1: M1客户字段] --> T10_3[Task I10-3: 客户详情页] T10_2[Task I10-2: M1项目字段] T10_4[Task I10-4: SN批量导入] end subgraph I11["I11 (M2+M11安全)"] T11_1[Task I11-1: 合同附件] T11_2[Task I11-2: 合同变更版本] T11_3[Task I11-3: 空闲超时] T11_4[Task I11-4: 登录锁定] T11_5[Task I11-5: 密码修改] end subgraph I12["I12 (M6配置)"] T12_1[Task I12-1: 比特ID映射] T12_2[Task I12-2: JSON模板] end subgraph I13["I13 (报表+审计)"] T13_1[Task I13-1: CSV导出] T13_2[Task I13-2: 审计检索] end subgraph V2["V2.0 (架构债)"] V2_1[Task V2-1: 角色模型] V2_2[Task V2-2: 权限码] end I10 --> I11 --> I12 --> I13 --> V2 ``` --- ## 工作量汇总 | 迭代 | 任务 | 后端文件 | 前端文件 | 迁移文件 | 估计工时 | |------|------|---------|---------|---------|---------| | **I10** | 4 | 8 | 4 | 1 | 8.5h | | **I11** | 5 | 8 | 5 | 1 | 10.5h | | **I12** | 2 | 10 | 3 | 2 | 7h | | **I13** | 2 | 3 | 3 | 0 | 5h | | **V2.0** | 2 | 10+ | 10+ | 1 | 14h | | **总计** | **15** | **39+** | **25+** | **5** | **45h** |