Files
ccdi/docs/plans/2026-03-06-model-param-config-optimization-split.md

1442 lines
32 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.
**目标:** 优化模型参数配置页面,取消模型下拉切换,改为垂直堆叠展示所有模型参数,并实现统一保存
**架构:** 采用前后端分离架构,后端新增批量查询和批量保存接口,前端重构两个配置页面使用统一布局
**技术栈:** Spring Boot 3.5.8 + MyBatis Plus 3.0.5 + Vue 2.6.12 + Element UI 2.15.14
**设计文档:** `docs/plans/2026-03-06-model-param-config-optimization-design.md`
---
## 📋 任务概览
| 阶段 | 任务范围 | 任务数 | 预计时间 |
|------|---------|--------|---------|
| **阶段1后端开发** | DTO/VO、Mapper、Service、Controller | 16个任务 | 2-3小时 |
| **阶段2后端测试** | Swagger接口测试 | 1个任务 | 30分钟 |
| **阶段3前端开发** | API、页面重构 | 10个任务 | 2-3小时 |
| **阶段4前端测试** | 功能测试 | 3个任务 | 1小时 |
| **总计** | | **30个任务** | **5-7小时** |
---
## 🔧 阶段1后端开发16个任务
### Task 1: 创建批量查询请求DTO
**文件:**
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/ModelParamAllQueryDTO.java`
**步骤 1: 创建类文件**
```java
package com.ruoyi.ccdi.project.domain.dto;
import lombok.Data;
/**
* 批量查询所有模型参数DTO
*/
@Data
public class ModelParamAllQueryDTO {
/** 项目ID0表示全局配置>0表示项目配置 */
private Long projectId;
}
```
**步骤 2: 提交**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/ModelParamAllQueryDTO.java
git commit -m "feat: 添加批量查询所有模型参数DTO"
```
---
### Task 2: 创建模型分组VO
**文件:**
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/ModelGroupVO.java`
**步骤 1: 创建类文件**
```java
package com.ruoyi.ccdi.project.domain.vo;
import lombok.Data;
import java.util.List;
/**
* 模型分组VO用于按模型分组展示参数
*/
@Data
public class ModelGroupVO {
/** 模型编码 */
private String modelCode;
/** 模型名称 */
private String modelName;
/** 参数列表 */
private List<ModelParamVO> params;
}
```
**步骤 2: 提交**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/ModelGroupVO.java
git commit -m "feat: 添加模型分组VO"
```
---
### Task 3: 创建批量查询响应VO
**文件:**
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/ModelParamAllVO.java`
**步骤 1: 创建类文件**
```java
package com.ruoyi.ccdi.project.domain.vo;
import lombok.Data;
import java.util.List;
/**
* 批量查询所有模型参数响应VO
*/
@Data
public class ModelParamAllVO {
/** 模型列表(包含每个模型及其参数) */
private List<ModelGroupVO> models;
}
```
**步骤 2: 提交**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/ModelParamAllVO.java
git commit -m "feat: 添加批量查询所有模型参数响应VO"
```
---
### Task 4: 创建批量保存参数项DTO
**文件:**
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/ParamValueItem.java`
**步骤 1: 创建类文件**
```java
package com.ruoyi.ccdi.project.domain.dto;
import lombok.Data;
/**
* 参数值项DTO
*/
@Data
public class ParamValueItem {
/** 参数编码 */
private String paramCode;
/** 参数值 */
private String paramValue;
}
```
**步骤 2: 提交**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/ParamValueItem.java
git commit -m "feat: 添加参数值项DTO"
```
---
### Task 5: 创建批量保存模型参数组DTO
**文件:**
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/ModelParamGroupDTO.java`
**步骤 1: 创建类文件**
```java
package com.ruoyi.ccdi.project.domain.dto;
import lombok.Data;
import java.util.List;
/**
* 模型参数分组DTO用于批量保存
*/
@Data
public class ModelParamGroupDTO {
/** 模型编码 */
private String modelCode;
/** 该模型下修改过的参数 */
private List<ParamValueItem> params;
}
```
**步骤 2: 提交**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/ModelParamGroupDTO.java
git commit -m "feat: 添加模型参数分组DTO"
```
---
### Task 6: 创建批量保存请求DTO
**文件:**
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/ModelParamSaveAllDTO.java`
**步骤 1: 创建类文件**
```java
package com.ruoyi.ccdi.project.domain.dto;
import lombok.Data;
import java.util.List;
/**
* 批量保存所有模型参数DTO
*/
@Data
public class ModelParamSaveAllDTO {
/** 项目ID */
private Long projectId;
/** 所有模型的参数修改(只包含修改过的参数) */
private List<ModelParamGroupDTO> models;
}
```
**步骤 2: 提交**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/ModelParamSaveAllDTO.java
git commit -m "feat: 添加批量保存所有模型参数DTO"
```
---
### Task 7: 在Mapper接口中添加批量查询方法
**文件:**
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiModelParamMapper.java`
**步骤 1: 添加方法**
在接口中添加:
```java
/**
* 根据项目ID查询所有模型参数
*
* @param projectId 项目ID
* @return 参数列表
*/
List<CcdiModelParam> selectByProjectId(@Param("projectId") Long projectId);
```
**步骤 2: 检查导入**
确保包含:
```java
import org.apache.ibatis.annotations.Param;
import java.util.List;
```
**步骤 3: 提交**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiModelParamMapper.java
git commit -m "feat: 在Mapper接口中添加批量查询方法"
```
---
### Task 8: 在Mapper XML中添加SQL查询
**文件:**
- Modify: `ccdi-project/src/main/resources/mapper/ccdi/project/CcdiModelParamMapper.xml`
**步骤 1: 添加SQL**
`<mapper>` 标签内添加:
```xml
<!-- 根据项目ID查询所有模型参数 -->
<select id="selectByProjectId" resultType="CcdiModelParam">
SELECT * FROM ccdi_model_param
WHERE project_id = #{projectId}
ORDER BY model_code, sort_order
</select>
```
**步骤 2: 提交**
```bash
git add ccdi-project/src/main/resources/mapper/ccdi/project/CcdiModelParamMapper.xml
git commit -m "feat: 在Mapper XML中添加批量查询SQL"
```
---
### Task 9: 在Service接口中添加批量查询方法
**文件:**
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiModelParamService.java`
**步骤 1: 添加方法签名**
```java
/**
* 查询所有模型及其参数(按模型分组)
*
* @param projectId 项目ID0表示全局配置
* @return 所有模型的参数配置
*/
ModelParamAllVO selectAllParams(Long projectId);
```
**步骤 2: 添加导入**
```java
import com.ruoyi.ccdi.project.domain.vo.ModelParamAllVO;
```
**步骤 3: 提交**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiModelParamService.java
git commit -m "feat: 在Service接口中添加批量查询方法"
```
---
### Task 10: 在Service接口中添加批量保存方法
**文件:**
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiModelParamService.java`
**步骤 1: 添加方法签名**
```java
/**
* 批量保存所有模型的参数修改
*
* @param saveAllDTO 所有模型的参数修改数据
*/
void saveAllParams(ModelParamSaveAllDTO saveAllDTO);
```
**步骤 2: 添加导入**
```java
import com.ruoyi.ccdi.project.domain.dto.ModelParamSaveAllDTO;
```
**步骤 3: 提交**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiModelParamService.java
git commit -m "feat: 在Service接口中添加批量保存方法"
```
---
### Task 11: 实现批量查询方法(第一部分 - 导入)
**文件:**
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiModelParamServiceImpl.java`
**步骤 1: 添加导入语句**
在文件顶部添加:
```java
import com.ruoyi.ccdi.project.domain.dto.ModelParamSaveAllDTO;
import com.ruoyi.ccdi.project.domain.dto.ModelParamGroupDTO;
import com.ruoyi.ccdi.project.domain.dto.ParamValueItem;
import com.ruoyi.ccdi.project.domain.vo.ModelParamAllVO;
import com.ruoyi.ccdi.project.domain.vo.ModelGroupVO;
import java.util.Comparator;
```
**步骤 2: 提交**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiModelParamServiceImpl.java
git commit -m "feat: 添加批量操作所需的导入语句"
```
---
### Task 12: 实现批量查询方法(第二部分 - 实现逻辑)
**文件:**
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiModelParamServiceImpl.java`
**步骤 1: 实现 selectAllParams 方法**
在类中添加:
```java
@Override
public ModelParamAllVO selectAllParams(Long projectId) {
// 1. 参数验证
if (projectId == null) {
projectId = 0L;
}
// 2. 如果是项目查询,根据 configType 决定查询哪组参数
Long effectiveProjectId = projectId;
if (projectId > 0) {
CcdiProject project = projectMapper.selectById(projectId);
if (project == null) {
throw new ServiceException("项目不存在");
}
if ("default".equals(project.getConfigType())) {
effectiveProjectId = 0L;
}
}
// 3. 查询所有模型的参数
List<CcdiModelParam> allParams = modelParamMapper.selectByProjectId(effectiveProjectId);
// 4. 按模型分组
Map<String, List<CcdiModelParam>> groupedParams = allParams.stream()
.collect(Collectors.groupingBy(CcdiModelParam::getModelCode));
// 5. 转换为VO
ModelParamAllVO result = new ModelParamAllVO();
List<ModelGroupVO> models = new ArrayList<>();
groupedParams.forEach((modelCode, params) -> {
ModelGroupVO groupVO = new ModelGroupVO();
groupVO.setModelCode(modelCode);
groupVO.setModelName(params.get(0).getModelName());
List<ModelParamVO> paramVOs = params.stream()
.map(param -> {
ModelParamVO vo = new ModelParamVO();
BeanUtils.copyProperties(param, vo);
return vo;
})
.collect(Collectors.toList());
groupVO.setParams(paramVOs);
models.add(groupVO);
});
// 6. 按模型编码排序(保证固定顺序)
models.sort(Comparator.comparing(ModelGroupVO::getModelCode));
result.setModels(models);
return result;
}
```
**步骤 2: 提交**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiModelParamServiceImpl.java
git commit -m "feat: 实现批量查询所有模型参数方法"
```
---
### Task 13: 实现批量保存方法
**文件:**
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiModelParamServiceImpl.java`
**步骤 1: 实现 saveAllParams 方法**
在类中添加:
```java
@Override
@Transactional(rollbackFor = Exception.class)
public void saveAllParams(ModelParamSaveAllDTO saveAllDTO) {
try {
// 1. 参数验证
if (saveAllDTO.getProjectId() == null) {
throw new ServiceException("项目ID不能为空");
}
if (saveAllDTO.getModels() == null || saveAllDTO.getModels().isEmpty()) {
throw new ServiceException("参数列表不能为空");
}
Long projectId = saveAllDTO.getProjectId();
// 2. 如果是项目保存,检查是否需要复制默认参数
if (projectId > 0) {
CcdiProject project = projectMapper.selectById(projectId);
if (project == null) {
throw new ServiceException("项目不存在");
}
// 如果是首次保存configType=default需要复制所有模型的系统默认参数
if ("default".equals(project.getConfigType())) {
for (ModelParamGroupDTO modelGroup : saveAllDTO.getModels()) {
copyDefaultParamsToProject(projectId, modelGroup.getModelCode());
}
// 更新项目配置类型为 custom
project.setConfigType("custom");
projectMapper.updateById(project);
}
}
// 3. 批量更新所有模型的参数值
for (ModelParamGroupDTO modelGroup : saveAllDTO.getModels()) {
for (ParamValueItem item : modelGroup.getParams()) {
int updated = modelParamMapper.updateParamValue(
projectId,
modelGroup.getModelCode(),
item.getParamCode(),
item.getParamValue()
);
if (updated == 0) {
log.warn("参数不存在或未更新modelCode={}, paramCode={}",
modelGroup.getModelCode(), item.getParamCode());
}
}
}
} catch (ServiceException e) {
throw e;
} catch (Exception e) {
log.error("批量保存模型参数失败", e);
throw new ServiceException("批量保存模型参数失败:" + e.getMessage());
}
}
```
**步骤 2: 提交**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiModelParamServiceImpl.java
git commit -m "feat: 实现批量保存所有模型参数方法"
```
---
### Task 14: 在Controller中添加批量查询接口
**文件:**
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiModelParamController.java`
**步骤 1: 添加导入**
```java
import com.ruoyi.ccdi.project.domain.dto.ModelParamAllQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.ModelParamSaveAllDTO;
import com.ruoyi.ccdi.project.domain.vo.ModelParamAllVO;
```
**步骤 2: 添加接口方法**
```java
/**
* 查询所有模型及其参数(按模型分组)
*/
@Operation(summary = "查询所有模型及其参数")
@GetMapping("/listAll")
public AjaxResult listAll(@Validated ModelParamAllQueryDTO queryDTO) {
ModelParamAllVO result = modelParamService.selectAllParams(queryDTO.getProjectId());
return success(result);
}
```
**步骤 3: 提交**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiModelParamController.java
git commit -m "feat: 在Controller中添加批量查询接口"
```
---
### Task 15: 在Controller中添加批量保存接口
**文件:**
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiModelParamController.java`
**步骤 1: 添加接口方法**
```java
/**
* 批量保存所有模型的参数修改
*/
@Operation(summary = "批量保存所有模型参数")
@Log(title = "模型参数配置", businessType = BusinessType.UPDATE)
@PostMapping("/saveAll")
public AjaxResult saveAll(@Validated @RequestBody ModelParamSaveAllDTO saveAllDTO) {
modelParamService.saveAllParams(saveAllDTO);
return success("保存成功");
}
```
**步骤 2: 提交**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiModelParamController.java
git commit -m "feat: 在Controller中添加批量保存接口"
```
---
## 🧪 阶段2后端测试1个任务
### Task 16: 使用Swagger测试后端接口
**检查点:后端开发完成**
**步骤 1: 启动后端**
```bash
# 提示用户手动启动
mvn spring-boot:run
```
**步骤 2: 访问Swagger UI**
打开:`http://localhost:8080/swagger-ui/index.html`
**步骤 3: 测试批量查询接口**
1. 找到 `GET /ccdi/modelParam/listAll`
2. 点击 "Try it out"
3. 输入:`projectId = 0`
4. 点击 "Execute"
5. 验证响应200包含 models 数组
**预期结果:**
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"models": [
{
"modelCode": "LARGE_TRANSACTION",
"modelName": "大额交易模型",
"params": [...]
}
]
}
}
```
**步骤 4: 测试批量保存接口**
1. 找到 `POST /ccdi/modelParam/saveAll`
2. 点击 "Try it out"
3. 输入请求体:
```json
{
"projectId": 0,
"models": [
{
"modelCode": "LARGE_TRANSACTION",
"params": [
{
"paramCode": "THRESHOLD_AMOUNT",
"paramValue": "60000"
}
]
}
]
}
```
4. 点击 "Execute"
5. 验证200"保存成功"
**步骤 5: 提交测试记录**
```bash
git add docs/test-records/
git commit -m "test: 记录后端接口测试结果"
```
---
## 🎨 阶段3前端开发10个任务
### Task 17: 在API层添加批量查询方法
**文件:**
- Modify: `ruoyi-ui/src/api/ccdi/modelParam.js`
**步骤 1: 添加方法**
```javascript
/**
* 查询所有模型及其参数(按模型分组)
*/
export function listAllParams(query) {
return request({
url: '/ccdi/modelParam/listAll',
method: 'get',
params: query
})
}
```
**步骤 2: 提交**
```bash
git add ruoyi-ui/src/api/ccdi/modelParam.js
git commit -m "feat: 在API层添加批量查询方法"
```
---
### Task 18: 在API层添加批量保存方法
**文件:**
- Modify: `ruoyi-ui/src/api/ccdi/modelParam.js`
**步骤 1: 添加方法**
```javascript
/**
* 批量保存所有模型的参数修改
*/
export function saveAllParams(data) {
return request({
url: '/ccdi/modelParam/saveAll',
method: 'post',
data: data
})
}
```
**步骤 2: 提交**
```bash
git add ruoyi-ui/src/api/ccdi/modelParam.js
git commit -m "feat: 在API层添加批量保存方法"
```
---
### Task 19: 重构全局配置页面 - 模板部分
**文件:**
- Modify: `ruoyi-ui/src/views/ccdi/modelParam/index.vue`
**步骤 1: 替换 template 部分**
```vue
<template>
<div class="param-config-container">
<!-- 页面标题 -->
<div class="page-header">
<h2>全局模型参数管理</h2>
</div>
<!-- 模型参数卡片组垂直堆叠 -->
<div class="model-cards-container">
<div
v-for="model in modelGroups"
:key="model.modelCode"
class="model-card"
>
<!-- 模型标题 -->
<div class="model-header">
<h3>{{ model.modelName }}</h3>
</div>
<!-- 参数表格 -->
<el-table :data="model.params" border style="width: 100%">
<el-table-column label="监测项" prop="paramName" width="200" />
<el-table-column label="描述" prop="paramDesc" />
<el-table-column label="阈值设置" width="200">
<template #default="{ row }">
<el-input
v-model="row.paramValue"
placeholder="请输入阈值"
@input="markAsModified(model.modelCode, row)"
/>
</template>
</el-table-column>
<el-table-column label="单位" prop="paramUnit" width="120" />
</el-table>
</div>
</div>
<!-- 统一保存按钮 -->
<div class="button-section">
<el-button type="primary" @click="handleSaveAll" :loading="saving">
保存所有修改
</el-button>
<span v-if="modifiedCount > 0" class="modified-tip">
已修改 {{ modifiedCount }} 个参数
</span>
</div>
</div>
</template>
```
**步骤 2: 暂不提交**
---
### Task 20: 重构全局配置页面 - 脚本部分
**文件:**
- Modify: `ruoyi-ui/src/views/ccdi/modelParam/index.vue`
**步骤 1: 替换 script 部分**
```vue
<script>
import { listAllParams, saveAllParams } from "@/api/ccdi/modelParam";
export default {
name: "ModelParam",
data() {
return {
modelGroups: [],
modifiedParams: new Map(),
saving: false
};
},
computed: {
modifiedCount() {
let count = 0;
this.modifiedParams.forEach(params => {
count += params.size;
});
return count;
}
},
created() {
this.loadAllParams();
},
methods: {
async loadAllParams() {
try {
const res = await listAllParams({ projectId: 0 });
this.modelGroups = res.data.models;
this.modifiedParams.clear();
} catch (error) {
this.$message.error('加载参数失败:' + error.message);
}
},
markAsModified(modelCode, row) {
if (!this.modifiedParams.has(modelCode)) {
this.modifiedParams.set(modelCode, new Set());
}
this.modifiedParams.get(modelCode).add(row.paramCode);
},
async handleSaveAll() {
if (this.modifiedCount === 0) {
this.$message.info('没有需要保存的修改');
return;
}
const saveDTO = {
projectId: 0,
models: []
};
this.modifiedParams.forEach((paramCodes, modelCode) => {
const modelGroup = this.modelGroups.find(m => m.modelCode === modelCode);
const modifiedParamList = modelGroup.params
.filter(p => paramCodes.has(p.paramCode))
.map(p => ({
paramCode: p.paramCode,
paramValue: p.paramValue
}));
if (modifiedParamList.length > 0) {
saveDTO.models.push({
modelCode: modelCode,
params: modifiedParamList
});
}
});
this.saving = true;
try {
await saveAllParams(saveDTO);
this.$modal.msgSuccess('保存成功');
this.modifiedParams.clear();
await this.loadAllParams();
} catch (error) {
this.$message.error('保存失败:' + (error.response?.data?.msg || error.message));
} finally {
this.saving = false;
}
}
}
};
</script>
```
**步骤 2: 暂不提交**
---
### Task 21: 重构全局配置页面 - 样式部分
**文件:**
- Modify: `ruoyi-ui/src/views/ccdi/modelParam/index.vue`
**步骤 1: 替换 style 部分**
```vue
<style scoped lang="scss">
.param-config-container {
padding: 20px;
background-color: #f5f5f5;
min-height: 100vh;
}
.page-header {
margin-bottom: 20px;
padding: 15px;
background: #fff;
border-radius: 4px;
h2 {
font-size: 18px;
font-weight: bold;
color: #333;
margin: 0;
}
}
.model-cards-container {
margin-bottom: 20px;
}
.model-card {
background: #fff;
border-radius: 4px;
padding: 20px;
margin-bottom: 20px;
border: 1px solid #e4e7ed;
.model-header {
margin-bottom: 15px;
h3 {
font-size: 16px;
font-weight: bold;
color: #333;
margin: 0;
}
}
}
.button-section {
padding: 15px;
background: #fff;
border-radius: 4px;
text-align: left;
.modified-tip {
margin-left: 15px;
color: #909399;
font-size: 14px;
}
}
</style>
```
**步骤 2: 提交**
```bash
git add ruoyi-ui/src/views/ccdi/modelParam/index.vue
git commit -m "feat: 重构全局模型参数配置页面"
```
---
### Task 22: 测试全局配置页面
**检查点:全局配置页面完成**
**步骤 1: 启动前端**
```bash
cd ruoyi-ui
npm run dev
```
**步骤 2: 访问页面**
- 打开:`http://localhost:80`
- 登录admin / admin123
- 导航到:系统管理 > 模型参数管理
**步骤 3: 验证功能**
- [ ] 页面标题正确
- [ ] 所有模型垂直堆叠显示
- [ ] 参数表格数据正确
- [ ] 修改参数后显示"已修改 X 个参数"
- [ ] 保存功能正常
- [ ] 错误提示友好
**步骤 4: 提交测试记录**
```bash
git add docs/test-records/
git commit -m "test: 记录全局配置页面测试结果"
```
---
### Task 23: 重构项目配置页面 - 模板部分
**文件:**
- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/ParamConfig.vue`
**步骤 1: 替换 template 部分**
```vue
<template>
<div class="param-config-container">
<!-- 模型参数卡片组垂直堆叠 -->
<div class="model-cards-container">
<div
v-for="model in modelGroups"
:key="model.modelCode"
class="model-card"
>
<!-- 模型标题 -->
<div class="model-header">
<h3>{{ model.modelName }}</h3>
</div>
<!-- 参数表格 -->
<el-table :data="model.params" border style="width: 100%">
<el-table-column label="监测项" prop="paramName" width="200" />
<el-table-column label="描述" prop="paramDesc" />
<el-table-column label="阈值设置" width="200">
<template #default="{ row }">
<el-input
v-model="row.paramValue"
placeholder="请输入阈值"
@input="markAsModified(model.modelCode, row)"
/>
</template>
</el-table-column>
<el-table-column label="单位" prop="paramUnit" width="120" />
</el-table>
</div>
</div>
<!-- 统一保存按钮 -->
<div class="button-section">
<el-button type="primary" @click="handleSaveAll" :loading="saving">
保存所有修改
</el-button>
<span v-if="modifiedCount > 0" class="modified-tip">
已修改 {{ modifiedCount }} 个参数
</span>
</div>
</div>
</template>
```
**步骤 2: 暂不提交**
---
### Task 24: 重构项目配置页面 - 脚本部分
**文件:**
- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/ParamConfig.vue`
**步骤 1: 替换 script 部分**
```vue
<script>
import { listAllParams, saveAllParams } from "@/api/ccdi/modelParam";
export default {
name: 'ParamConfig',
props: {
projectId: {
type: [String, Number],
required: true
},
projectInfo: {
type: Object,
default: () => ({})
}
},
data() {
return {
modelGroups: [],
modifiedParams: new Map(),
saving: false
}
},
computed: {
modifiedCount() {
let count = 0;
this.modifiedParams.forEach(params => {
count += params.size;
});
return count;
}
},
watch: {
projectId(newVal) {
if (newVal) {
this.loadAllParams();
}
}
},
created() {
if (this.projectId) {
this.loadAllParams();
}
},
methods: {
async loadAllParams() {
try {
const res = await listAllParams({ projectId: this.projectId });
this.modelGroups = res.data.models;
this.modifiedParams.clear();
} catch (error) {
this.$message.error('加载参数失败:' + error.message);
}
},
markAsModified(modelCode, row) {
if (!this.modifiedParams.has(modelCode)) {
this.modifiedParams.set(modelCode, new Set());
}
this.modifiedParams.get(modelCode).add(row.paramCode);
},
async handleSaveAll() {
if (this.modifiedCount === 0) {
this.$message.info('没有需要保存的修改');
return;
}
const saveDTO = {
projectId: this.projectId,
models: []
};
this.modifiedParams.forEach((paramCodes, modelCode) => {
const modelGroup = this.modelGroups.find(m => m.modelCode === modelCode);
const modifiedParamList = modelGroup.params
.filter(p => paramCodes.has(p.paramCode))
.map(p => ({
paramCode: p.paramCode,
paramValue: p.paramValue
}));
if (modifiedParamList.length > 0) {
saveDTO.models.push({
modelCode: modelCode,
params: modifiedParamList
});
}
});
this.saving = true;
try {
await saveAllParams(saveDTO);
this.$message.success('保存成功');
this.modifiedParams.clear();
await this.loadAllParams();
} catch (error) {
this.$message.error('保存失败:' + (error.response?.data?.msg || error.message));
} finally {
this.saving = false;
}
}
}
}
</script>
```
**步骤 2: 暂不提交**
---
### Task 25: 重构项目配置页面 - 样式部分
**文件:**
- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/ParamConfig.vue`
**步骤 1: 替换 style 部分**
```vue
<style scoped lang="scss">
.param-config-container {
padding: 20px;
background-color: #fff;
min-height: 400px;
}
.model-cards-container {
margin-bottom: 20px;
}
.model-card {
background: #fff;
border-radius: 4px;
padding: 20px;
margin-bottom: 20px;
border: 1px solid #e4e7ed;
.model-header {
margin-bottom: 15px;
h3 {
font-size: 16px;
font-weight: bold;
color: #333;
margin: 0;
}
}
}
.button-section {
padding: 15px;
background: #fff;
border-radius: 4px;
text-align: left;
.modified-tip {
margin-left: 15px;
color: #909399;
font-size: 14px;
}
}
</style>
```
**步骤 2: 提交**
```bash
git add ruoyi-ui/src/views/ccdiProject/components/detail/ParamConfig.vue
git commit -m "feat: 重构项目内模型参数配置页面"
```
---
### Task 26: 测试项目配置页面
**检查点:项目配置页面完成**
**步骤 1: 确保前后端启动**
**步骤 2: 访问项目页面**
- 导航到:初核项目管理 > 进入项目 > 参数配置标签页
**步骤 3: 验证功能**
- [ ] 参数正确显示
- [ ] 使用默认配置的项目显示系统参数
- [ ] 首次保存后配置类型变为"自定义"
- [ ] 多模型同时修改保存成功
**步骤 4: 提交测试记录**
```bash
git add docs/test-records/
git commit -m "test: 记录项目配置页面测试结果"
```
---
## ✅ 阶段4集成测试4个任务
### Task 27: 端到端功能测试
**步骤 1: 测试全局配置影响项目配置**
1. 全局配置页面修改参数
2. 创建新项目(使用默认配置)
3. 验证项目显示修改后的参数
**步骤 2: 测试项目配置不影响全局配置**
1. 项目配置页面修改参数
2. 返回全局配置页面
3. 验证全局参数未改变
**步骤 3: 提交测试记录**
```bash
git add docs/test-records/
git commit -m "test: 完成端到端功能测试"
```
---
### Task 28: 性能测试
**步骤 1: 测试页面加载性能**
- 验证 `listAll` 接口响应时间 < 200ms
**步骤 2: 测试保存性能**
- 验证 `saveAll` 接口响应时间 < 500ms
**步骤 3: 测试渲染性能**
- 验证首次渲染 < 300ms
- 验证交互响应 < 100ms
**步骤 4: 提交测试记录**
```bash
git add docs/test-records/
git commit -m "test: 完成性能测试"
```
---
### Task 29: 更新API文档
**文件:**
- Create: `docs/api-docs/model-param-batch-api.md`
**步骤 1: 创建文档**
```markdown
# 模型参数批量操作API文档
## 批量查询所有模型参数
**接口地址:** `GET /ccdi/modelParam/listAll`
**请求参数:**
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| projectId | Long | 否 | 项目ID0或不传表示全局配置 |
**响应示例:**
\`\`\`json
{
"code": 200,
"msg": "操作成功",
"data": {
"models": [...]
}
}
\`\`\`
## 批量保存所有模型参数
**接口地址:** `POST /ccdi/modelParam/saveAll`
**请求体示例:**
\`\`\`json
{
"projectId": 1,
"models": [
{
"modelCode": "LARGE_TRANSACTION",
"params": [
{
"paramCode": "THRESHOLD_AMOUNT",
"paramValue": "60000"
}
]
}
]
}
\`\`\`
```
**步骤 2: 提交**
```bash
git add docs/api-docs/model-param-batch-api.md
git commit -m "docs: 添加模型参数批量操作API文档"
```
---
### Task 30: 最终提交和推送
**检查点:所有任务完成**
**步骤 1: 检查所有更改**
```bash
git status
```
**步骤 2: 推送到远程**
```bash
git push origin dev
```
**步骤 3: 创建Pull Request可选**
- 标题:`feat: 优化模型参数配置页面布局`
- 描述:
- 取消模型下拉切换
- 改为垂直堆叠展示所有模型参数
- 统一保存机制
- 全局配置和项目配置页面同步修改
**完成!🎉**
---
## 📊 总结
**完成的功能:**
- ✅ 后端批量查询和保存接口
- ✅ 前端全局配置页面重构
- ✅ 前端项目配置页面重构
- ✅ 统一保存机制
- ✅ 修改提示
- ✅ 完整测试
**技术亮点:**
- 垂直堆叠布局,用户体验更好
- 批量操作减少HTTP请求
- 只保存修改过的参数
- 保留向后兼容
**后续优化建议:**
- 添加"重置为默认值"功能
- 添加参数修改历史记录
- 添加参数导入导出功能