Files
ccdi/docs/plans/2026-03-04-create-project-integrate-lsfx.md

787 lines
18 KiB
Markdown
Raw 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.
# 创建项目集成流水分析平台实施计划
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** 在创建项目时同步调用流水分析平台获取projectId并保存到数据库
**Architecture:** Service层集成LsfxAnalysisClient同步调用getToken接口使用Spring事务管理确保数据一致性
**Tech Stack:** Spring Boot 3.5.8, MyBatis Plus 3.0.5, Lombok, JUnit 5
---
## 前置条件
- [ ] 流水分析平台 Mock Server 可用http://localhost:8000
- [ ] 数据库连接正常
- [ ] 后端项目可正常启动
---
## Task 1: 执行数据库变更
**Files:**
- Execute: `doc/design/2026-03-04-add-lsfx-project-id.sql`
**Step 1: 连接数据库执行SQL脚本**
使用MCP工具连接数据库并执行SQL
```bash
# 或者使用MySQL客户端
mysql -h 116.62.17.81 -u root -p ccdi < doc/design/2026-03-04-add-lsfx-project-id.sql
```
**Step 2: 验证字段已添加**
```sql
SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT, COLUMN_COMMENT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'ccdi'
AND TABLE_NAME = 'ccdi_project'
AND COLUMN_NAME = 'lsfx_project_id';
```
预期结果:应返回字段信息,类型为 `INT(11)`,允许为空
**Step 3: 提交数据库变更**
```bash
git add doc/design/2026-03-04-add-lsfx-project-id.sql
git commit -m "chore: 添加流水分析平台项目ID字段到ccdi_project表"
```
---
## Task 2: 修改CcdiProject实体类
**Files:**
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/CcdiProject.java`
**Step 1: 打开实体类文件**
定位到 `lowRiskCount` 字段的位置约第50行
**Step 2: 添加新字段**
`lowRiskCount` 字段之后,`delFlag` 字段之前添加:
```java
/** 低风险人数 */
private Integer lowRiskCount;
/** 流水分析平台项目ID */
private Integer lsfxProjectId;
/** 删除标志0-存在2-删除 */
@TableLogic
private String delFlag;
```
**Step 3: 验证代码**
确保:
- Lombok 的 `@Data` 注解存在(会自动生成 getter/setter
- 字段顺序与数据库表结构一致
- 注释清晰
**Step 4: 提交变更**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/CcdiProject.java
git commit -m "feat: CcdiProject实体类添加lsfxProjectId字段"
```
---
## Task 3: 修改CcdiProjectVO视图对象
**Files:**
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectVO.java`
**Step 1: 打开VO文件**
定位到 `lowRiskCount` 字段的位置
**Step 2: 添加新字段**
`lowRiskCount` 字段之后添加:
```java
/** 低风险人数 */
private Integer lowRiskCount;
/** 流水分析平台项目ID */
private Integer lsfxProjectId;
/** 创建时间 */
private Date createTime;
```
**Step 3: 验证代码**
确保字段顺序与实体类一致
**Step 4: 提交变更**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectVO.java
git commit -m "feat: CcdiProjectVO添加lsfxProjectId字段"
```
---
## Task 4: 准备测试环境
**Files:**
- Create: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/CcdiProjectServiceImplTest.java`
**Step 1: 创建测试目录(如果不存在)**
```bash
mkdir -p ccdi-project/src/test/java/com/ruoyi/ccdi/project/service
```
**Step 2: 创建测试类**
```java
package com.ruoyi.ccdi.project.service;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectSaveDTO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectVO;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.lsfx.client.LsfxAnalysisClient;
import com.ruoyi.lsfx.domain.request.GetTokenRequest;
import com.ruoyi.lsfx.domain.response.GetTokenResponse;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;
import static org.junit.jupiter.api.Assertions.*;
/**
* 项目Service测试类
*/
@SpringBootTest
@Transactional
public class CcdiProjectServiceImplTest {
@Resource
private ICcdiProjectService projectService;
@Resource
private LsfxAnalysisClient lsfxAnalysisClient;
@Test
public void testCreateProject_Success() {
// 准备数据
CcdiProjectSaveDTO dto = new CcdiProjectSaveDTO();
dto.setProjectName("测试项目");
dto.setDescription("测试描述");
dto.setConfigType("default");
// 执行
CcdiProjectVO result = projectService.createProject(dto);
// 验证
assertNotNull(result);
assertNotNull(result.getProjectId());
assertNotNull(result.getLsfxProjectId(), "流水分析平台项目ID不应为空");
assertEquals("测试项目", result.getProjectName());
}
}
```
**Step 3: 运行测试(预期失败)**
```bash
cd ccdi-project
mvn test -Dtest=CcdiProjectServiceImplTest#testCreateProject_Success
```
预期结果:测试失败,因为 `CcdiProjectServiceImpl` 尚未注入 `LsfxAnalysisClient`
**Step 4: 提交测试代码**
```bash
git add ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/CcdiProjectServiceImplTest.java
git commit -m "test: 添加项目创建集成流水分析平台的测试用例"
```
---
## Task 5: 修改CcdiProjectServiceImpl - 注入依赖
**Files:**
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectServiceImpl.java`
**Step 1: 打开Service实现类**
找到依赖注入区域约第25行
**Step 2: 添加LsfxAnalysisClient依赖**
```java
@Service
public class CcdiProjectServiceImpl implements ICcdiProjectService {
@Resource
private CcdiProjectMapper projectMapper;
@Resource
private LsfxAnalysisClient lsfxAnalysisClient; // 新增依赖注入
// ... 方法实现 ...
}
```
**Step 3: 添加必要的import**
```java
import com.ruoyi.lsfx.client.LsfxAnalysisClient;
import com.ruoyi.lsfx.domain.request.GetTokenRequest;
import com.ruoyi.lsfx.domain.response.GetTokenResponse;
```
**Step 4: 验证编译**
```bash
cd ccdi-project
mvn compile
```
预期结果:编译成功
**Step 5: 提交变更**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectServiceImpl.java
git commit -m "feat: CcdiProjectServiceImpl注入LsfxAnalysisClient依赖"
```
---
## Task 6: 实现callLsfxPlatform私有方法
**Files:**
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectServiceImpl.java`
**Step 1: 在类末尾添加私有方法**
`getStatusCounts()` 方法之后添加:
```java
/**
* 调用流水分析平台获取projectId
*
* @param projectName 项目名称
* @return 流水分析平台项目ID
* @throws ServiceException 调用失败或响应无效时抛出
*/
private Integer callLsfxPlatform(String projectName) {
// 构建请求参数
GetTokenRequest request = new GetTokenRequest();
request.setProjectNo("902000_" + System.currentTimeMillis());
request.setEntityName(projectName);
request.setUserId("902001");
request.setUserName("902001");
request.setRole("VIEWER");
request.setOrgCode("902000");
request.setAnalysisType("-1");
request.setDepartmentCode("902000");
// 调用流水分析平台(异常处理和日志已在 LsfxAnalysisClient 中完成)
GetTokenResponse response = lsfxAnalysisClient.getToken(request);
// 业务层校验:确保响应有效
if (response == null || response.getData() == null) {
throw new ServiceException("流水分析平台响应数据为空");
}
if (response.getData().getProjectId() == null) {
throw new ServiceException("流水分析平台返回的projectId为空");
}
// 校验返回码
if (!"200".equals(response.getCode())) {
throw new ServiceException("流水分析平台返回错误: " + response.getMessage());
}
return response.getData().getProjectId();
}
```
**Step 2: 验证编译**
```bash
cd ccdi-project
mvn compile
```
预期结果:编译成功
**Step 3: 提交变更**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectServiceImpl.java
git commit -m "feat: 实现callLsfxPlatform方法调用流水分析平台"
```
---
## Task 7: 修改createProject方法集成流水分析
**Files:**
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectServiceImpl.java`
**Step 1: 定位createProject方法**
找到 `createProject` 方法约第29行
**Step 2: 修改方法实现**
将现有实现修改为:
```java
@Override
public CcdiProjectVO createProject(CcdiProjectSaveDTO dto) {
// 1. 调用流水分析平台获取projectId
Integer lsfxProjectId = callLsfxPlatform(dto.getProjectName());
// 2. 创建项目实体
CcdiProject project = new CcdiProject();
BeanUtils.copyProperties(dto, project);
// 3. 设置默认值和流水分析平台ID
project.setStatus("0"); // 进行中
project.setIsArchived(0); // 未归档
project.setTargetCount(0);
project.setHighRiskCount(0);
project.setMediumRiskCount(0);
project.setLowRiskCount(0);
project.setLsfxProjectId(lsfxProjectId); // 设置流水分析平台ID
// 4. 保存到数据库
projectMapper.insert(project);
// 5. 返回VO
CcdiProjectVO vo = new CcdiProjectVO();
BeanUtils.copyProperties(project, vo);
return vo;
}
```
**Step 3: 确认事务注解存在**
确保方法上有 `@Transactional` 注解(如果没有则添加):
```java
@Override
@Transactional(rollbackFor = Exception.class)
public CcdiProjectVO createProject(CcdiProjectSaveDTO dto) {
// ...
}
```
需要添加import
```java
import org.springframework.transaction.annotation.Transactional;
```
**Step 4: 验证编译**
```bash
cd ccdi-project
mvn compile
```
预期结果:编译成功
**Step 5: 提交变更**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectServiceImpl.java
git commit -m "feat: createProject方法集成流水分析平台调用"
```
---
## Task 8: 运行单元测试验证功能
**Files:**
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/CcdiProjectServiceImplTest.java`
**Step 1: 确保Mock Server运行**
```bash
cd lsfx-mock-server
python app.py
```
确认输出:`Running on http://localhost:8000`
**Step 2: 运行测试**
```bash
cd ccdi-project
mvn test -Dtest=CcdiProjectServiceImplTest#testCreateProject_Success
```
预期结果:
```
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
```
**Step 3: 如果测试失败,检查日志**
常见问题:
- Mock Server 未启动:启动 Mock Server
- 数据库连接失败:检查数据库配置
- 字段映射错误:检查 BeanUtils.copyProperties 是否正常
**Step 4: 提交测试结果**
如果测试通过,无需额外提交(测试代码已提交)
---
## Task 9: 添加异常测试用例
**Files:**
- Modify: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/CcdiProjectServiceImplTest.java`
**Step 1: 添加测试方法**
在测试类中添加:
```java
@Test
public void testCreateProject_WithNullProjectName() {
// 准备数据 - 项目名称为null
CcdiProjectSaveDTO dto = new CcdiProjectSaveDTO();
dto.setProjectName(null);
dto.setDescription("测试描述");
dto.setConfigType("default");
// 执行并验证异常
assertThrows(ServiceException.class, () -> {
projectService.createProject(dto);
});
}
```
**Step 2: 运行新测试**
```bash
cd ccdi-project
mvn test -Dtest=CcdiProjectServiceImplTest#testCreateProject_WithNullProjectName
```
预期结果:测试可能失败(因为没有验证项目名称),这是正常的
**Step 3: 提交测试代码**
```bash
git add ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/CcdiProjectServiceImplTest.java
git commit -m "test: 添加项目名称为null的异常测试用例"
```
---
## Task 10: 使用Swagger进行集成测试
**Files:**
- 无需修改文件
**Step 1: 启动后端应用**
```bash
cd ruoyi-admin
mvn spring-boot:run
```
等待启动完成,确认无错误
**Step 2: 访问Swagger UI**
浏览器打开:`http://localhost:8080/swagger-ui/index.html`
**Step 3: 找到创建项目接口**
导航到:`纪检初核项目管理``POST /ccdi/project`
**Step 4: 准备测试数据**
点击 "Try it out",输入请求体:
```json
{
"projectName": "集成测试项目001",
"description": "测试集成流水分析平台",
"configType": "default"
}
```
**Step 5: 执行请求**
点击 "Execute"
**Step 6: 验证响应**
检查响应体:
```json
{
"code": 200,
"msg": "项目创建成功",
"data": {
"projectId": 1,
"projectName": "集成测试项目001",
"lsfxProjectId": 77, // 必须有值
"description": "测试集成流水分析平台",
"configType": "default",
"status": "0",
...
}
}
```
**Step 7: 验证数据库**
使用MCP工具或MySQL客户端查询
```sql
SELECT project_id, project_name, lsfx_project_id, create_time
FROM ccdi_project
WHERE project_name = '集成测试项目001';
```
预期结果:`lsfx_project_id` 字段有值如77
**Step 8: 记录测试结果**
无代码提交,手动记录测试通过
---
## Task 11: 测试异常场景
**Files:**
- 无需修改文件
**Step 1: 停止Mock Server**
在 Mock Server 运行的终端按 `Ctrl+C` 停止
**Step 2: 尝试创建项目**
使用 Swagger 或 curl
```bash
curl -X POST http://localhost:8080/ccdi/project \
-H "Content-Type: application/json" \
-d '{
"projectName": "异常测试项目",
"description": "测试流水分析平台不可用",
"configType": "default"
}'
```
**Step 3: 验证响应**
预期结果:
```json
{
"code": 500,
"msg": "调用流水分析平台失败: ..." // 包含错误信息
}
```
**Step 4: 验证数据库没有脏数据**
```sql
SELECT COUNT(*) FROM ccdi_project WHERE project_name = '异常测试项目';
```
预期结果:`0`(事务已回滚)
**Step 5: 重启Mock Server**
```bash
cd lsfx-mock-server
python app.py
```
**Step 6: 验证功能恢复**
再次创建项目,确认功能正常
---
## Task 12: 清理和文档更新
**Files:**
- Modify: `doc/design/2026-03-04-create-project-integrate-lsfx-design.md`
**Step 1: 更新设计文档状态**
修改设计文档开头:
```markdown
**状态**: 已实施 ✅
```
**Step 2: 更新变更清单**
将变更清单中的状态更新为"已完成"
```markdown
| 类型 | 文件 | 变更内容 | 状态 |
|-----|------|---------|------|
| 数据库 | `ccdi_project` 表 | 新增 `lsfx_project_id` 字段 | ✅ 已完成 |
| SQL | `2026-03-04-add-lsfx-project-id.sql` | 数据库迁移脚本 | ✅ 已执行 |
| 实体类 | `CcdiProject.java` | 新增 `lsfxProjectId` 属性 | ✅ 已修改 |
| VO | `CcdiProjectVO.java` | 新增 `lsfxProjectId` 属性 | ✅ 已修改 |
| Service | `CcdiProjectServiceImpl.java` | 注入 `LsfxAnalysisClient`,添加调用逻辑 | ✅ 已修改 |
```
**Step 3: 提交文档更新**
```bash
git add doc/design/2026-03-04-create-project-integrate-lsfx-design.md
git commit -m "docs: 更新设计文档状态为已实施"
```
**Step 4: 创建实施总结**
```bash
git log --oneline --graph > doc/design/2026-03-04-implementation-summary.txt
```
提交总结:
```bash
git add doc/design/2026-03-04-implementation-summary.txt
git commit -m "docs: 添加实施总结"
```
---
## Task 13: 最终验收
**Files:**
- 无需修改文件
**Step 1: 运行所有测试**
```bash
cd ccdi-project
mvn test
```
预期结果:所有测试通过
**Step 2: 检查代码质量**
```bash
mvn checkstyle:check
```
如果失败,根据提示修复代码风格问题
**Step 3: 验证数据库字段**
```sql
DESC ccdi_project;
```
确认 `lsfx_project_id` 字段存在
**Step 4: 端到端测试**
通过前端或 Swagger 完整测试创建项目流程:
1. 创建项目成功
2. 查询项目列表,确认 `lsfxProjectId` 显示
3. 查询项目详情,确认 `lsfxProjectId` 正确
**Step 5: 记录验收结果**
在项目文档中记录:
- 功能验收通过 ✅
- 测试覆盖率100%
- 性能测试创建项目耗时约1-2秒取决于网络
- 异常处理:已验证
---
## 后续任务(可选)
### Task 14: 添加前端展示(可选)
如果需要在项目列表页面展示 `lsfxProjectId`
**Files:**
- Modify: `ruoyi-ui/src/views/ccdiProject/index.vue`
- Modify: `ruoyi-ui/src/api/ccdi/project.js`
**Step 1: 修改表格列定义**
`index.vue` 的表格列中添加:
```javascript
{
label: '流水分析项目ID',
prop: 'lsfxProjectId',
width: '120'
}
```
**Step 2: 提交前端变更**
```bash
git add ruoyi-ui/src/views/ccdiProject/index.vue
git commit -m "feat: 前端项目列表展示流水分析平台项目ID"
```
---
## 实施注意事项
### 关键点
1. **事务一致性**:确保 `@Transactional` 注解存在,任何异常都会回滚
2. **参数正确性**:严格按照《兰溪-流水分析对接-新版.md》配置固定参数
3. **错误提示**:给用户清晰的错误提示,便于排查问题
4. **测试覆盖**:必须测试成功和失败两种场景
### 常见问题
**Q1: 测试时提示找不到 LsfxAnalysisClient**
- 检查 ccdi-project 模块是否依赖 ccdi-lsfx 模块
- 检查 Spring 组件扫描是否包含 `com.ruoyi.lsfx`
**Q2: 数据库字段添加失败**
- 确认数据库连接正常
- 检查是否有权限修改表结构
**Q3: Mock Server 无法启动**
- 检查 8000 端口是否被占用
- 确认 Python 环境正常
**Q4: 事务回滚不生效**
- 确认方法上有 `@Transactional` 注解
- 检查异常是否被捕获后未重新抛出
---
## 参考资料
- 设计文档: `doc/design/2026-03-04-create-project-integrate-lsfx-design.md`
- 流水分析对接文档: `assets/对接流水分析/兰溪-流水分析对接-新版.md`
- 项目规范: `CLAUDE.md`
---
**计划创建完成!**