From 375263dee528ef6e68c63626744b08341abdc40c Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Fri, 6 Mar 2026 14:03:23 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E8=AF=A6=E6=83=85=E5=8F=82=E6=95=B0=E9=85=8D=E7=BD=AE=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E5=AE=9E=E6=96=BD=E8=AE=A1=E5=88=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...-06-project-param-config-implementation.md | 723 ++++++++++++++++++ 1 file changed, 723 insertions(+) create mode 100644 ruoyi-ui/src/docs/plans/2026-03-06-project-param-config-implementation.md diff --git a/ruoyi-ui/src/docs/plans/2026-03-06-project-param-config-implementation.md b/ruoyi-ui/src/docs/plans/2026-03-06-project-param-config-implementation.md new file mode 100644 index 0000000..d7e097d --- /dev/null +++ b/ruoyi-ui/src/docs/plans/2026-03-06-project-param-config-implementation.md @@ -0,0 +1,723 @@ +# 项目详情参数配置页面实施计划 + +> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. + +**Goal:** 在项目详情页面实现参数配置功能,允许每个项目自定义模型参数,首次保存时自动从系统默认参数复制。 + +**Architecture:** 前端组件复用独立页面代码,后端修改 Service 根据 configType 返回对应参数,首次保存时自动复制默认参数并切换 configType。 + +**Tech Stack:** Spring Boot 3, MyBatis Plus, Vue.js 2, Element UI + +--- + +## Task 1: 修改后端 Mapper 接口 + +**Files:** +- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiModelParamMapper.java` + +**Step 1: 添加更新参数值方法** + +在 `CcdiModelParamMapper.java` 接口中添加方法: + +```java +/** + * 更新参数值 + * + * @param projectId 项目ID + * @param modelCode 模型编码 + * @param paramCode 参数编码 + * @param paramValue 参数值 + * @return 影响行数 + */ +int updateParamValue(@Param("projectId") Long projectId, + @Param("modelCode") String modelCode, + @Param("paramCode") String paramCode, + @Param("paramValue") String paramValue); + +/** + * 批量插入参数 + * + * @param params 参数列表 + * @return 影响行数 + */ +int insertBatch(@Param("list") List params); +``` + +**Step 2: 提交** + +```bash +git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiModelParamMapper.java +git commit -m "feat: 添加 Mapper 接口方法 updateParamValue 和 insertBatch" +``` + +--- + +## Task 2: 修改后端 Mapper XML + +**Files:** +- Modify: `ccdi-project/src/main/resources/mapper/ccdi/project/CcdiModelParamMapper.xml` + +**Step 1: 添加 updateParamValue SQL** + +在 `` 标签之前添加: + +```xml + + + UPDATE ccdi_model_param + SET param_value = #{paramValue}, + update_time = NOW() + WHERE project_id = #{projectId} + AND model_code = #{modelCode} + AND param_code = #{paramCode} + + + + + INSERT INTO ccdi_model_param ( + project_id, model_code, model_name, param_code, param_name, + param_desc, param_value, param_unit, sort_order, remark, + create_time, update_time + ) VALUES + + ( + #{item.projectId}, #{item.modelCode}, #{item.modelName}, + #{item.paramCode}, #{item.paramName}, #{item.paramDesc}, + #{item.paramValue}, #{item.paramUnit}, #{item.sortOrder}, + #{item.remark}, NOW(), NOW() + ) + + +``` + +**Step 2: 提交** + +```bash +git add ccdi-project/src/main/resources/mapper/ccdi/project/CcdiModelParamMapper.xml +git commit -m "feat: 添加 Mapper XML SQL updateParamValue 和 insertBatch" +``` + +--- + +## Task 3: 注入 ProjectMapper 依赖 + +**Files:** +- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiModelParamServiceImpl.java` + +**Step 1: 添加 import 语句** + +在文件顶部的 import 区域添加: + +```java +import com.ruoyi.ccdi.project.domain.CcdiProject; +import com.ruoyi.ccdi.project.mapper.CcdiProjectMapper; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +``` + +**Step 2: 添加 Logger** + +在类开始处添加: + +```java +private static final Logger log = LoggerFactory.getLogger(CcdiModelParamServiceImpl.class); +``` + +**Step 3: 注入 ProjectMapper** + +在 `@Resource private CcdiModelParamMapper modelParamMapper;` 之后添加: + +```java +@Resource +private CcdiProjectMapper projectMapper; +``` + +**Step 4: 提交** + +```bash +git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiModelParamServiceImpl.java +git commit -m "feat: 注入 CcdiProjectMapper 依赖" +``` + +--- + +## Task 4: 修改 selectParamList 方法 + +**Files:** +- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiModelParamServiceImpl.java:52-71` + +**Step 1: 替换 selectParamList 方法** + +完全替换 `selectParamList` 方法: + +```java +@Override +public List selectParamList(ModelParamQueryDTO queryDTO) { + // 1. 参数验证 + Long projectId = queryDTO.getProjectId(); + if (projectId == null) { + projectId = 0L; + } + + // 2. 如果是项目查询(projectId > 0),需要根据 configType 决定查询哪组参数 + Long effectiveProjectId = projectId; + if (projectId > 0) { + // 查询项目信息 + CcdiProject project = projectMapper.selectById(projectId); + if (project == null) { + throw new ServiceException("项目不存在"); + } + + // 根据 configType 决定查询哪组参数 + if ("default".equals(project.getConfigType())) { + // 使用系统默认参数 + effectiveProjectId = 0L; + } else { + // 使用项目自定义参数 + effectiveProjectId = projectId; + } + } + + // 3. 查询参数列表 + List params = modelParamMapper.selectByProjectAndModel( + effectiveProjectId, + queryDTO.getModelCode() + ); + + // 4. 转换为 VO + List result = new ArrayList<>(); + params.forEach(param -> { + ModelParamVO vo = new ModelParamVO(); + BeanUtils.copyProperties(param, vo); + result.add(vo); + }); + + return result; +} +``` + +**Step 2: 提交** + +```bash +git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiModelParamServiceImpl.java +git commit -m "feat: 修改 selectParamList 方法支持根据 configType 返回对应参数" +``` + +--- + +## Task 5: 添加 copyDefaultParamsToProject 私有方法 + +**Files:** +- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiModelParamServiceImpl.java` + +**Step 1: 添加复制参数方法** + +在 `saveParams` 方法之后添加: + +```java +/** + * 复制系统默认参数到项目 + * + * @param projectId 项目ID + * @param modelCode 模型编码 + * @return 复制的参数数量 + */ +private int copyDefaultParamsToProject(Long projectId, String modelCode) { + // 查询系统默认参数 + List defaultParams = modelParamMapper.selectByProjectAndModel(0L, modelCode); + + if (defaultParams.isEmpty()) { + log.warn("系统默认参数为空,modelCode={}", modelCode); + return 0; + } + + // 复制到项目 + List projectParams = defaultParams.stream() + .map(param -> { + CcdiModelParam newParam = new CcdiModelParam(); + BeanUtils.copyProperties(param, newParam); + newParam.setId(null); // 清空ID,让数据库自动生成 + newParam.setProjectId(projectId); + newParam.setCreateBy(null); // 清空审计字段,让 MyBatis Plus 自动填充 + newParam.setCreateTime(null); + newParam.setUpdateBy(null); + newParam.setUpdateTime(null); + return newParam; + }) + .collect(Collectors.toList()); + + // 批量插入 + int count = modelParamMapper.insertBatch(projectParams); + + log.info("复制系统默认参数到项目成功,projectId={}, modelCode={}, count={}", + projectId, modelCode, count); + + return count; +} +``` + +**Step 2: 提交** + +```bash +git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiModelParamServiceImpl.java +git commit -m "feat: 添加 copyDefaultParamsToProject 私有方法" +``` + +--- + +## Task 6: 修改 saveParams 方法 + +**Files:** +- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiModelParamServiceImpl.java:74-122` + +**Step 1: 替换 saveParams 方法** + +完全替换 `saveParams` 方法: + +```java +@Override +@Transactional(rollbackFor = Exception.class) +public void saveParams(ModelParamSaveDTO saveDTO) { + try { + // 1. 参数验证 + if (saveDTO.getProjectId() == null) { + throw new ServiceException("项目ID不能为空"); + } + if (StringUtils.isBlank(saveDTO.getModelCode())) { + throw new ServiceException("模型编码不能为空"); + } + if (saveDTO.getParams() == null || saveDTO.getParams().isEmpty()) { + throw new ServiceException("参数列表不能为空"); + } + + Long projectId = saveDTO.getProjectId(); + + // 2. 如果是项目保存(projectId > 0),需要检查是否首次保存 + if (projectId > 0) { + // 查询项目信息 + CcdiProject project = projectMapper.selectById(projectId); + if (project == null) { + throw new ServiceException("项目不存在"); + } + + // 3. 如果是首次保存(configType=default),需要复制系统默认参数 + if ("default".equals(project.getConfigType())) { + int copiedCount = copyDefaultParamsToProject(projectId, saveDTO.getModelCode()); + if (copiedCount == 0) { + log.warn("系统默认参数为空,projectId={}, modelCode={}", + projectId, saveDTO.getModelCode()); + } + + // 更新项目配置类型为 custom + project.setConfigType("custom"); + projectMapper.updateById(project); + + log.info("项目配置类型已更新为 custom,projectId={}", projectId); + } + } + + // 4. 更新参数值 + String username = SecurityUtils.getUsername(); + for (ModelParamSaveDTO.ParamValueItem item : saveDTO.getParams()) { + int updated = modelParamMapper.updateParamValue( + projectId, + saveDTO.getModelCode(), + item.getParamCode(), + item.getParamValue() + ); + if (updated == 0) { + log.warn("参数不存在或未更新,paramCode={}", item.getParamCode()); + } + } + + } catch (ServiceException e) { + // 业务异常,直接抛出 + throw e; + } catch (Exception e) { + // 系统异常,记录日志并抛出 + log.error("保存模型参数失败", e); + throw new ServiceException("保存模型参数失败:" + e.getMessage()); + } +} +``` + +**Step 2: 提交** + +```bash +git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiModelParamServiceImpl.java +git commit -m "feat: 修改 saveParams 方法支持首次保存自动复制默认参数" +``` + +--- + +## Task 7: 实现前端 ParamConfig 组件(模板部分) + +**Files:** +- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/ParamConfig.vue` + +**Step 1: 替换模板部分** + +完全替换文件内容: + +```vue + +``` + +**Step 2: 提交** + +```bash +git add ruoyi-ui/src/views/ccdiProject/components/detail/ParamConfig.vue +git commit -m "feat: 实现 ParamConfig 组件模板部分" +``` + +--- + +## Task 8: 实现前端 ParamConfig 组件(脚本部分) + +**Files:** +- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/ParamConfig.vue` + +**Step 1: 添加脚本部分** + +在 `` 之后添加: + +```vue + + +``` + +**Step 2: 提交** + +```bash +git add ruoyi-ui/src/views/ccdiProject/components/detail/ParamConfig.vue +git commit -m "feat: 实现 ParamConfig 组件脚本部分" +``` + +--- + +## Task 9: 实现前端 ParamConfig 组件(样式部分) + +**Files:** +- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/ParamConfig.vue` + +**Step 1: 添加样式部分** + +在 `` 之后添加: + +```vue + + +``` + +**Step 2: 提交** + +```bash +git add ruoyi-ui/src/views/ccdiProject/components/detail/ParamConfig.vue +git commit -m "feat: 实现 ParamConfig 组件样式部分" +``` + +--- + +## Task 10: 手动测试功能 + +**Step 1: 启动后端服务** + +提示用户手动启动后端服务(不要自动运行)。 + +**Step 2: 启动前端服务** + +```bash +cd ruoyi-ui +npm run dev +``` + +**Step 3: 访问测试页面** + +1. 访问 `http://localhost:80` +2. 登录系统(admin/admin123) +3. 进入"项目管理"页面 +4. 点击任意项目的"详情"按钮 +5. 点击"参数配置"菜单 + +**Step 4: 测试场景 1 - 查看默认配置** + +**操作:** +- 新项目查看参数配置 + +**预期结果:** +- 显示系统默认参数 +- 参数值与系统默认一致 + +**Step 5: 测试场景 2 - 首次保存参数** + +**操作:** +- 修改参数值 +- 点击"保存配置" + +**预期结果:** +- 显示"保存成功"提示 +- 项目的 `configType` 变为 `custom` +- 再次查看参数显示修改后的值 + +**Step 6: 测试场景 3 - 切换模型** + +**操作:** +- 切换到另一个模型 + +**预期结果:** +- 参数列表正确切换 +- 显示新模型的参数 + +**Step 7: 测试场景 4 - 不修改参数点击保存** + +**操作:** +- 不修改任何参数 +- 点击"保存配置" + +**预期结果:** +- 显示"没有需要保存的修改"提示 + +**Step 8: 测试场景 5 - 清空参数值后保存** + +**操作:** +- 清空某个参数值 +- 点击"保存配置" + +**预期结果:** +- 显示"请填写所有参数值"错误提示 +- 不发起保存请求 + +**Step 9: 提交测试完成** + +```bash +git add . +git commit -m "test: 项目详情参数配置功能手动测试完成" +``` + +--- + +## 完成检查清单 + +- [ ] 后端 Mapper 接口已修改 +- [ ] 后端 Mapper XML 已修改 +- [ ] 后端 Service 已修改 +- [ ] 前端 ParamConfig 组件已实现 +- [ ] 所有测试场景通过 +- [ ] 代码已提交到 git + +--- + +## 注意事项 + +1. **不要自动启动后端服务** - 提示用户手动启动 +2. **不需要后端单元测试** - 用户明确要求 +3. **首次保存会触发复制** - 确保系统默认参数存在 +4. **事务回滚** - 如果复制失败,事务会自动回滚 +5. **前端验证优先** - 参数值验证在前端完成