18 KiB
创建项目集成流水分析平台实施计划
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:
# 或者使用MySQL客户端
mysql -h 116.62.17.81 -u root -p ccdi < doc/design/2026-03-04-add-lsfx-project-id.sql
Step 2: 验证字段已添加
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: 提交数据库变更
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 字段之前添加:
/** 低风险人数 */
private Integer lowRiskCount;
/** 流水分析平台项目ID */
private Integer lsfxProjectId;
/** 删除标志:0-存在,2-删除 */
@TableLogic
private String delFlag;
Step 3: 验证代码
确保:
- Lombok 的
@Data注解存在(会自动生成 getter/setter) - 字段顺序与数据库表结构一致
- 注释清晰
Step 4: 提交变更
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 字段之后添加:
/** 低风险人数 */
private Integer lowRiskCount;
/** 流水分析平台项目ID */
private Integer lsfxProjectId;
/** 创建时间 */
private Date createTime;
Step 3: 验证代码
确保字段顺序与实体类一致
Step 4: 提交变更
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: 创建测试目录(如果不存在)
mkdir -p ccdi-project/src/test/java/com/ruoyi/ccdi/project/service
Step 2: 创建测试类
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: 运行测试(预期失败)
cd ccdi-project
mvn test -Dtest=CcdiProjectServiceImplTest#testCreateProject_Success
预期结果:测试失败,因为 CcdiProjectServiceImpl 尚未注入 LsfxAnalysisClient
Step 4: 提交测试代码
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依赖
@Service
public class CcdiProjectServiceImpl implements ICcdiProjectService {
@Resource
private CcdiProjectMapper projectMapper;
@Resource
private LsfxAnalysisClient lsfxAnalysisClient; // 新增依赖注入
// ... 方法实现 ...
}
Step 3: 添加必要的import
import com.ruoyi.lsfx.client.LsfxAnalysisClient;
import com.ruoyi.lsfx.domain.request.GetTokenRequest;
import com.ruoyi.lsfx.domain.response.GetTokenResponse;
Step 4: 验证编译
cd ccdi-project
mvn compile
预期结果:编译成功
Step 5: 提交变更
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() 方法之后添加:
/**
* 调用流水分析平台获取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: 验证编译
cd ccdi-project
mvn compile
预期结果:编译成功
Step 3: 提交变更
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: 修改方法实现
将现有实现修改为:
@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 注解(如果没有则添加):
@Override
@Transactional(rollbackFor = Exception.class)
public CcdiProjectVO createProject(CcdiProjectSaveDTO dto) {
// ...
}
需要添加import:
import org.springframework.transaction.annotation.Transactional;
Step 4: 验证编译
cd ccdi-project
mvn compile
预期结果:编译成功
Step 5: 提交变更
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运行
cd lsfx-mock-server
python app.py
确认输出:Running on http://localhost:8000
Step 2: 运行测试
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: 添加测试方法
在测试类中添加:
@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: 运行新测试
cd ccdi-project
mvn test -Dtest=CcdiProjectServiceImplTest#testCreateProject_WithNullProjectName
预期结果:测试可能失败(因为没有验证项目名称),这是正常的
Step 3: 提交测试代码
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: 启动后端应用
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",输入请求体:
{
"projectName": "集成测试项目001",
"description": "测试集成流水分析平台",
"configType": "default"
}
Step 5: 执行请求
点击 "Execute"
Step 6: 验证响应
检查响应体:
{
"code": 200,
"msg": "项目创建成功",
"data": {
"projectId": 1,
"projectName": "集成测试项目001",
"lsfxProjectId": 77, // 必须有值
"description": "测试集成流水分析平台",
"configType": "default",
"status": "0",
...
}
}
Step 7: 验证数据库
使用MCP工具或MySQL客户端查询:
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:
curl -X POST http://localhost:8080/ccdi/project \
-H "Content-Type: application/json" \
-d '{
"projectName": "异常测试项目",
"description": "测试流水分析平台不可用",
"configType": "default"
}'
Step 3: 验证响应
预期结果:
{
"code": 500,
"msg": "调用流水分析平台失败: ..." // 包含错误信息
}
Step 4: 验证数据库没有脏数据
SELECT COUNT(*) FROM ccdi_project WHERE project_name = '异常测试项目';
预期结果:0(事务已回滚)
Step 5: 重启Mock Server
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: 更新设计文档状态
修改设计文档开头:
**状态**: 已实施 ✅
Step 2: 更新变更清单
将变更清单中的状态更新为"已完成":
| 类型 | 文件 | 变更内容 | 状态 |
|-----|------|---------|------|
| 数据库 | `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: 提交文档更新
git add doc/design/2026-03-04-create-project-integrate-lsfx-design.md
git commit -m "docs: 更新设计文档状态为已实施"
Step 4: 创建实施总结
git log --oneline --graph > doc/design/2026-03-04-implementation-summary.txt
提交总结:
git add doc/design/2026-03-04-implementation-summary.txt
git commit -m "docs: 添加实施总结"
Task 13: 最终验收
Files:
- 无需修改文件
Step 1: 运行所有测试
cd ccdi-project
mvn test
预期结果:所有测试通过
Step 2: 检查代码质量
mvn checkstyle:check
如果失败,根据提示修复代码风格问题
Step 3: 验证数据库字段
DESC ccdi_project;
确认 lsfx_project_id 字段存在
Step 4: 端到端测试
通过前端或 Swagger 完整测试创建项目流程:
- 创建项目成功
- 查询项目列表,确认
lsfxProjectId显示 - 查询项目详情,确认
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 的表格列中添加:
{
label: '流水分析项目ID',
prop: 'lsfxProjectId',
width: '120'
}
Step 2: 提交前端变更
git add ruoyi-ui/src/views/ccdiProject/index.vue
git commit -m "feat: 前端项目列表展示流水分析平台项目ID"
实施注意事项
关键点
- 事务一致性:确保
@Transactional注解存在,任何异常都会回滚 - 参数正确性:严格按照《兰溪-流水分析对接-新版.md》配置固定参数
- 错误提示:给用户清晰的错误提示,便于排查问题
- 测试覆盖:必须测试成功和失败两种场景
常见问题
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
计划创建完成!