Files

426 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 原型完善 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>)` 方法,逐条校验并插入,返回成功数/失败数
- `SnBatchImportRequest.java`: snCode, projectId, contractLineId, activationRemark
**Frontend:**
- `LicenseSnListView.vue`: 加「批量导入」按钮 → 弹窗文本域(一行一个 SN)
- `platform.js`: 加 `batchImportLicenseSns(body)`
---
## 迭代 I11M2 增强 + 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:**
- 用户菜单加「修改密码」入口
- 弹窗表单:旧密码、新密码、确认新密码
---
## 迭代 I12M6 配置管理(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 编辑器 + 校验结果展示)
---
## 迭代 I13M9 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.0M11 角色模型重构(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 存储用户权限码列表
- 按钮级:`<el-button v-permission="'license:sn:rw'">新建</el-button>`
**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** |