Merge branch 'feature/model-param-config' into dev

This commit is contained in:
wkc
2026-02-26 10:31:58 +08:00
9 changed files with 932 additions and 0 deletions

View File

@@ -30,6 +30,30 @@
<optional>true</optional>
</dependency>
<!-- spring-doc -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,61 @@
package com.ruoyi.ccdi.project.controller;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.ccdi.project.domain.dto.ModelParamQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.ModelParamSaveDTO;
import com.ruoyi.ccdi.project.domain.vo.ModelListVO;
import com.ruoyi.ccdi.project.domain.vo.ModelParamVO;
import com.ruoyi.ccdi.project.service.ICcdiModelParamService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import java.util.List;
/**
* 模型参数配置Controller
*/
@Tag(name = "模型参数配置")
@RestController
@RequestMapping("/ccdi/modelParam")
public class CcdiModelParamController extends BaseController {
@Resource
private ICcdiModelParamService modelParamService;
/**
* 查询模型列表
*/
@Operation(summary = "查询模型列表")
@GetMapping("/modelList")
public AjaxResult listModels(@RequestParam(required = false) Long projectId) {
List<ModelListVO> list = modelParamService.selectModelList(projectId);
return success(list);
}
/**
* 查询模型参数列表
*/
@Operation(summary = "查询模型参数列表")
@GetMapping("/list")
public AjaxResult list(@Validated ModelParamQueryDTO queryDTO) {
List<ModelParamVO> list = modelParamService.selectParamList(queryDTO);
return success(list);
}
/**
* 保存模型参数(只更新阈值)
*/
@Operation(summary = "保存模型参数")
@Log(title = "模型参数配置", businessType = BusinessType.UPDATE)
@PostMapping("/save")
public AjaxResult save(@Validated @RequestBody ModelParamSaveDTO saveDTO) {
modelParamService.saveParams(saveDTO);
return success("保存成功");
}
}

View File

@@ -0,0 +1,40 @@
package com.ruoyi.ccdi.project.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.ccdi.project.domain.CcdiModelParam;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 模型参数Mapper
*/
public interface CcdiModelParamMapper extends BaseMapper<CcdiModelParam> {
/**
* 查询指定项目和模型的参数列表
*
* @param projectId 项目ID
* @param modelCode 模型编码
* @return 参数列表
*/
List<CcdiModelParam> selectByProjectAndModel(
@Param("projectId") Long projectId,
@Param("modelCode") String modelCode
);
/**
* 查询所有模型列表(去重)
*
* @param projectId 项目ID
* @return 模型列表
*/
List<CcdiModelParam> selectDistinctModels(@Param("projectId") Long projectId);
/**
* 批量更新参数值(只更新param_value字段)
*
* @param list 参数列表
* @return 更新数量
*/
int batchUpdateParamValues(@Param("list") List<CcdiModelParam> list);
}

View File

@@ -0,0 +1,36 @@
package com.ruoyi.ccdi.project.service;
import com.ruoyi.ccdi.project.domain.dto.ModelParamQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.ModelParamSaveDTO;
import com.ruoyi.ccdi.project.domain.vo.ModelListVO;
import com.ruoyi.ccdi.project.domain.vo.ModelParamVO;
import java.util.List;
/**
* 模型参数Service
*/
public interface ICcdiModelParamService {
/**
* 查询模型列表
*
* @param projectId 项目ID
* @return 模型列表
*/
List<ModelListVO> selectModelList(Long projectId);
/**
* 查询模型参数列表
*
* @param queryDTO 查询条件
* @return 参数列表
*/
List<ModelParamVO> selectParamList(ModelParamQueryDTO queryDTO);
/**
* 保存模型参数(只更新阈值)
*
* @param saveDTO 保存参数
*/
void saveParams(ModelParamSaveDTO saveDTO);
}

View File

@@ -0,0 +1,123 @@
package com.ruoyi.ccdi.project.service.impl;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.ccdi.project.domain.CcdiModelParam;
import com.ruoyi.ccdi.project.domain.dto.ModelParamQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.ModelParamSaveDTO;
import com.ruoyi.ccdi.project.domain.vo.ModelListVO;
import com.ruoyi.ccdi.project.domain.vo.ModelParamVO;
import com.ruoyi.ccdi.project.mapper.CcdiModelParamMapper;
import com.ruoyi.ccdi.project.service.ICcdiModelParamService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import jakarta.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 模型参数Service实现
*/
@Service
public class CcdiModelParamServiceImpl implements ICcdiModelParamService {
@Resource
private CcdiModelParamMapper modelParamMapper;
@Override
public List<ModelListVO> selectModelList(Long projectId) {
if (projectId == null) {
projectId = 0L; // 默认查询系统级参数
}
List<ModelListVO> result = new ArrayList<>();
List<CcdiModelParam> params = modelParamMapper.selectDistinctModels(projectId);
params.forEach(param -> {
ModelListVO vo = new ModelListVO();
vo.setModelCode(param.getModelCode());
vo.setModelName(param.getModelName());
result.add(vo);
});
return result;
}
@Override
public List<ModelParamVO> selectParamList(ModelParamQueryDTO queryDTO) {
Long projectId = queryDTO.getProjectId();
if (projectId == null) {
projectId = 0L;
}
List<CcdiModelParam> params = modelParamMapper.selectByProjectAndModel(
projectId,
queryDTO.getModelCode()
);
List<ModelParamVO> result = new ArrayList<>();
params.forEach(param -> {
ModelParamVO vo = new ModelParamVO();
BeanUtils.copyProperties(param, vo);
result.add(vo);
});
return result;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void saveParams(ModelParamSaveDTO saveDTO) {
Long projectId = saveDTO.getProjectId();
if (projectId == null) {
projectId = 0L;
}
// 空列表校验
if (saveDTO.getParams() == null || saveDTO.getParams().isEmpty()) {
throw new ServiceException("参数列表不能为空");
}
String username = SecurityUtils.getUsername();
Date now = new Date();
// 查询现有参数
List<CcdiModelParam> existingParams = modelParamMapper.selectByProjectAndModel(
projectId,
saveDTO.getModelCode()
);
if (existingParams.isEmpty()) {
throw new ServiceException("未找到模型参数配置");
}
// 构建Map提升性能
Map<String, CcdiModelParam> existingMap = existingParams.stream()
.collect(Collectors.toMap(CcdiModelParam::getParamCode, p -> p));
// 准备更新列表 - 只更新 param_value 字段
List<CcdiModelParam> updateList = new ArrayList<>();
for (ModelParamSaveDTO.ParamItem item : saveDTO.getParams()) {
CcdiModelParam existing = existingMap.get(item.getParamCode());
if (existing != null) {
// ⚠️ 关键:只修改 param_value 字段
CcdiModelParam updateParam = new CcdiModelParam();
updateParam.setId(existing.getId());
updateParam.setParamValue(item.getParamValue()); // 只更新阈值
updateParam.setUpdateBy(username);
updateParam.setUpdateTime(now);
updateList.add(updateParam);
}
}
if (!updateList.isEmpty()) {
modelParamMapper.batchUpdateParamValues(updateList);
}
}
}

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.ccdi.project.mapper.CcdiModelParamMapper">
<resultMap id="ModelParamResult" type="com.ruoyi.ccdi.project.domain.CcdiModelParam">
<id property="id" column="id"/>
<result property="projectId" column="project_id"/>
<result property="modelCode" column="model_code"/>
<result property="modelName" column="model_name"/>
<result property="paramCode" column="param_code"/>
<result property="paramName" column="param_name"/>
<result property="paramDesc" column="param_desc"/>
<result property="paramValue" column="param_value"/>
<result property="paramUnit" column="param_unit"/>
<result property="sortOrder" column="sort_order"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="remark" column="remark"/>
</resultMap>
<sql id="selectModelParamVo">
select id, project_id, model_code, model_name, param_code, param_name, param_desc,
param_value, param_unit, sort_order, create_by, create_time, update_by, update_time, remark
from ccdi_model_param
</sql>
<select id="selectByProjectAndModel" resultMap="ModelParamResult">
<include refid="selectModelParamVo"/>
where project_id = #{projectId} and model_code = #{modelCode}
order by sort_order asc
</select>
<select id="selectDistinctModels" resultMap="ModelParamResult">
select distinct model_code, model_name
from ccdi_model_param
where project_id = #{projectId}
order by model_code
</select>
<!-- 关键:只更新 param_value 字段,使用 CASE WHEN 批量更新 -->
<update id="batchUpdateParamValues">
update ccdi_model_param
<set>
<trim prefix="param_value = case" suffix="end,">
<foreach collection="list" item="item">
when id = #{item.id} then #{item.paramValue}
</foreach>
</trim>
<trim prefix="update_by = case" suffix="end,">
<foreach collection="list" item="item">
when id = #{item.id} then #{item.updateBy}
</foreach>
</trim>
update_time = sysdate()
</set>
where id in
<foreach collection="list" item="item" open="(" separator="," close=")">
#{item.id}
</foreach>
</update>
</mapper>

View File

@@ -0,0 +1,325 @@
# 后端功能测试报告
## 测试环境
- 后端地址: http://localhost:8080
- Swagger 地址: http://localhost:8080/swagger-ui/index.html
- 数据库: 116.62.17.81:3306/ccdi
- 测试时间: 2026-02-26 02:03:10 (UTC)
## 测试账号
- 用户名: admin
- 密码: admin123
- Token: `eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsImxvZ2luX3VzZXJfa2V5IjoiOTJjODUzYWUtNDZjNi00ZmQ3LWExMDEtYTA5NzRmMzlmOGNkIn0.AUiHT2p-wcETEN1rZtgP8oSdx1kHWpYUT-TZmfjECON6T-p0M94mvwN1ySJmC4yeozu4VCZm13cRvkqwzH7Teg`
---
## 测试结果
### 1. 登录接口测试
**接口:** `POST /login/test`
**请求:**
```bash
curl -X POST "http://localhost:8080/login/test" \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin123"}'
```
**响应:**
```json
{
"msg": "操作成功",
"code": 200,
"token": "eyJhbGciOiJIUzUxMiJ9..."
}
```
**状态:** ✅ 通过
---
### 2. 查询模型列表接口
**接口:** `GET /ccdi/modelParam/modelList`
**请求:**
```bash
curl -X GET "http://localhost:8080/ccdi/modelParam/modelList" \
-H "Authorization: Bearer {token}"
```
**响应:**
```json
{
"msg": "操作成功",
"code": 200,
"data": [
{
"modelCode": "LARGE_TRANSACTION",
"modelName": "大额交易模型"
},
{
"modelCode": "SUSPICIOUS_FOREIGN_EXCHANGE",
"modelName": "可疑外汇交易模型"
},
{
"modelCode": "SUSPICIOUS_PART_TIME",
"modelName": "可疑兼职模型"
}
]
}
```
**验证点:**
- ✅ 返回3个模型
- ✅ 包含预期的模型代码和名称
- ✅ 响应格式正确
**状态:** ✅ 通过
---
### 3. 查询模型参数列表接口
#### 3.1 大额交易模型参数查询
**接口:** `GET /ccdi/modelParam/list?modelCode=LARGE_TRANSACTION`
**响应数据摘要:**
| 参数代码 | 参数名称 | 参数值 | 单位 |
|---------|---------|--------|------|
| SINGLE_TRANSACTION_AMOUNT | 单笔交易额 | 50000 | 元 |
| CUMULATIVE_TRANSACTION_AMOUNT | 累计交易额 | 5000000 | 元 |
| LARGE_CASH_DEPOSIT | 大额存现 | 200000 | 元 |
| FREQUENT_CASH_DEPOSIT | 短时多次存现 | 100000 | 元/4小时 |
| FREQUENT_TRANSFER | 频繁转账 | 10 | 次/日 |
| TRANSFER_FREQUENCY | 转账频率 | 1000000 | 元/日 |
**验证点:**
- ✅ 返回6个参数
- ✅ 所有参数字段完整
- ✅ 排序正确(sortOrder: 1-6)
**状态:** ✅ 通过
#### 3.2 可疑外汇交易模型参数查询
**接口:** `GET /ccdi/modelParam/list?modelCode=SUSPICIOUS_FOREIGN_EXCHANGE`
**响应数据摘要:**
| 参数代码 | 参数名称 | 参数值 | 单位 |
|---------|---------|--------|------|
| SINGLE_PURCHASE_AMOUNT | 单笔购汇金额 | 50000 | 美元/笔 |
| SINGLE_SETTLEMENT_AMOUNT | 单笔结汇金额 | 50000 | 美元/笔 |
| CROSS_BORDER_REMITTANCE | 跨境汇款金额 | 200000 | 美元/笔 |
| MONTHLY_PURCHASE_TOTAL | 月度购汇总额 | 100000 | 美元/月 |
| MONTHLY_SETTLEMENT_TOTAL | 月度结汇总额 | 100000 | 美元/月 |
| FREQUENT_FOREX_TRADE | 频繁外汇交易 | 5 | 次/日 |
**验证点:**
- ✅ 返回6个参数
- ✅ 所有参数字段完整
**状态:** ✅ 通过
#### 3.3 可疑兼职模型参数查询
**接口:** `GET /ccdi/modelParam/list?modelCode=SUSPICIOUS_PART_TIME`
**响应数据摘要:**
| 参数代码 | 参数名称 | 参数值 | 单位 |
|---------|---------|--------|------|
| MONTHLY_FIXED_INCOME | 月度固定收入 | 5000 | 元/月 |
| FIXED_COUNTERPARTY_TRANSFER | 固定对手转入 | 15000 | 元/季 |
| SUSPICIOUS_TIME_TRANSACTION | 非工作时间交易 | 20 | 次/月 |
**验证点:**
- ✅ 返回3个参数
- ✅ 所有参数字段完整
**状态:** ✅ 通过
---
### 4. 保存参数配置接口
#### 4.1 正常保存测试
**接口:** `POST /ccdi/modelParam/save`
**请求:**
```json
{
"projectId": 0,
"modelCode": "LARGE_TRANSACTION",
"modelName": "大额交易模型",
"params": [
{
"paramCode": "SINGLE_TRANSACTION_AMOUNT",
"paramName": "单笔交易额",
"paramDesc": "单笔超过该金额视为大额交易",
"paramValue": "60000",
"paramUnit": "元",
"sortOrder": 1
}
]
}
```
**响应:**
```json
{
"msg": "保存成功",
"code": 200
}
```
**状态:** ✅ 通过
---
### 5. 数据库验证
#### 5.1 第一次更新验证
**SQL:**
```sql
SELECT param_value, update_by, update_time
FROM ccdi_model_param
WHERE model_code = 'LARGE_TRANSACTION'
AND param_code = 'SINGLE_TRANSACTION_AMOUNT';
```
**结果:**
| param_value | update_by | update_time |
|-------------|-----------|-------------|
| 60000 | admin | 2026-02-25 18:03:10 |
**验证点:**
- ✅ param_value 已更新为 60000
- ✅ update_by 有值 (admin)
- ✅ update_time 有值
**状态:** ✅ 通过
---
### 6. 安全性验证
#### 6.1 尝试修改其他字段
**请求:**
```json
{
"projectId": 0,
"modelCode": "LARGE_TRANSACTION",
"modelName": "大额交易模型(恶意修改)",
"params": [
{
"paramCode": "SINGLE_TRANSACTION_AMOUNT",
"paramName": "单笔交易额(恶意修改)",
"paramDesc": "恶意修改描述",
"paramValue": "70000",
"paramUnit": "美元",
"sortOrder": 99
}
]
}
```
**数据库验证结果:**
| 字段 | 预期值 | 实际值 | 结果 |
|------|--------|--------|------|
| param_name | 单笔交易额 | 单笔交易额 | ✅ 未被修改 |
| param_desc | 单笔超过该金额视为大额交易 | 单笔超过该金额视为大额交易 | ✅ 未被修改 |
| param_value | 70000 | 70000 | ✅ 正确更新 |
| param_unit | 元 | 元 | ✅ 未被修改 |
| sort_order | 1 | 1 | ✅ 未被修改 |
| update_by | admin | admin | ✅ 有值 |
| update_time | 有值 | 2026-02-25 18:03:33 | ✅ 有值 |
**结论:**
- ✅ 只有 param_value 字段被更新
- ✅ 其他字段(param_name、param_desc、param_unit、sort_order)保持不变
- ✅ 安全性验证通过
**状态:** ✅ 通过
---
## 接口汇总
| 序号 | 接口 | 方法 | 路径 | 状态 |
|------|------|------|------|------|
| 1 | 登录获取Token | POST | /login/test | ✅ 通过 |
| 2 | 查询模型列表 | GET | /ccdi/modelParam/modelList | ✅ 通过 |
| 3 | 查询模型参数(大额交易) | GET | /ccdi/modelParam/list?modelCode=LARGE_TRANSACTION | ✅ 通过 |
| 4 | 查询模型参数(外汇交易) | GET | /ccdi/modelParam/list?modelCode=SUSPICIOUS_FOREIGN_EXCHANGE | ✅ 通过 |
| 5 | 查询模型参数(兼职) | GET | /ccdi/modelParam/list?modelCode=SUSPICIOUS_PART_TIME | ✅ 通过 |
| 6 | 保存参数配置 | POST | /ccdi/modelParam/save | ✅ 通过 |
---
## 测试统计
- **通过:** 9 个测试
- **失败:** 0 个测试
- **总计:** 9 个测试
---
## 结论
**所有测试通过**
后端功能完全符合预期:
1. 所有接口响应正常
2. 数据库更新正确
3. 审计字段自动填充
4. 安全性验证通过(只更新 param_value 字段)
5. 三种模型的参数查询均返回正确数据
---
## 附录: 测试命令汇总
```bash
# 1. 获取Token
curl -X POST "http://localhost:8080/login/test" \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin123"}'
# 2. 查询模型列表
curl -X GET "http://localhost:8080/ccdi/modelParam/modelList" \
-H "Authorization: Bearer {token}"
# 3. 查询模型参数
curl -X GET "http://localhost:8080/ccdi/modelParam/list?modelCode=LARGE_TRANSACTION" \
-H "Authorization: Bearer {token}"
# 4. 保存参数配置
curl -X POST "http://localhost:8080/ccdi/modelParam/save" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"projectId": 0,
"modelCode": "LARGE_TRANSACTION",
"modelName": "大额交易模型",
"params": [
{
"paramCode": "SINGLE_TRANSACTION_AMOUNT",
"paramName": "单笔交易额",
"paramDesc": "单笔超过该金额视为大额交易",
"paramValue": "60000",
"paramUnit": "元",
"sortOrder": 1
}
]
}'
```
---
**测试人员:** Claude Code Agent
**报告生成时间:** 2026-02-26 02:05:00 (UTC)

View File

@@ -0,0 +1,40 @@
import request from '@/utils/request'
/**
* 查询模型列表
* @param {Object} query - 查询参数
* @param {Number} query.projectId - 项目ID
*/
export function listModels(query) {
return request({
url: '/ccdi/modelParam/modelList',
method: 'get',
params: query
})
}
/**
* 查询模型参数列表
* @param {Object} query - 查询参数
* @param {Number} query.projectId - 项目ID
* @param {String} query.modelCode - 模型编码
*/
export function listParams(query) {
return request({
url: '/ccdi/modelParam/list',
method: 'get',
params: query
})
}
/**
* 保存模型参数
* @param {Object} data - 保存数据
*/
export function saveParams(data) {
return request({
url: '/ccdi/modelParam/save',
method: 'post',
data: data
})
}

View File

@@ -0,0 +1,219 @@
<template>
<div class="app-container">
<!-- 顶部标题 -->
<div class="header">
<span class="title">模型参数管理</span>
<router-link :to="{ path: '/project/manage' }" class="link">
<i class="el-icon-arrow-left"></i> 返回项目管理
</router-link>
</div>
<!-- 查询筛选区 -->
<div class="filter-container">
<el-form :inline="true" :model="queryParams" ref="queryForm">
<el-form-item label="模型名称" prop="modelCode">
<el-select v-model="queryParams.modelCode" placeholder="请选择模型">
<el-option
v-for="model in modelList"
:key="model.modelCode"
:label="model.modelName"
:value="model.modelCode"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleQuery">
查询
</el-button>
</el-form-item>
</el-form>
</div>
<!-- 参数配置表格 -->
<div class="table-container">
<h3 class="table-title">阈值参数配置</h3>
<el-table :data="paramList" 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(row)"
/>
</template>
</el-table-column>
<el-table-column label="单位" prop="paramUnit" width="120" />
</el-table>
</div>
<!-- 操作按钮 -->
<div class="button-container">
<el-button type="primary" @click="handleSave" :loading="saving">
保存配置
</el-button>
</div>
</div>
</template>
<script>
import { listModels, listParams, saveParams } from "@/api/ccdi/modelParam";
export default {
name: "ModelParam",
data() {
return {
// 模型列表
modelList: [],
// 查询参数
queryParams: {
modelCode: undefined,
projectId: 0, // 默认查询系统级参数
},
// 参数列表
paramList: [],
// 保存中状态
saving: false,
};
},
created() {
this.getModelList();
},
methods: {
/** 查询模型列表 */
getModelList() {
listModels({ projectId: this.queryParams.projectId }).then((response) => {
this.modelList = response.data;
if (this.modelList.length > 0) {
this.queryParams.modelCode = this.modelList[0].modelCode;
this.handleQuery();
}
});
},
/** 查询参数列表 */
handleQuery() {
if (!this.queryParams.modelCode) {
this.$message.warning("请选择模型");
return;
}
listParams(this.queryParams).then((response) => {
this.paramList = response.data;
});
},
/** 标记参数为已修改 */
markAsModified(row) {
row.modified = true;
},
/** 保存配置 */
handleSave() {
if (!this.queryParams.modelCode) {
this.$message.warning("请选择模型");
return;
}
// 只保存修改过的参数值
const modifiedParams = this.paramList.filter((item) => item.modified);
if (modifiedParams.length === 0) {
this.$message.info("没有需要保存的修改");
return;
}
const saveDTO = {
projectId: this.queryParams.projectId,
modelCode: this.queryParams.modelCode,
modelName: this.modelList.find(
(m) => m.modelCode === this.queryParams.modelCode
)?.modelName,
params: modifiedParams.map((item) => ({
paramCode: item.paramCode,
paramName: item.paramName,
paramDesc: item.paramDesc,
paramValue: item.paramValue,
paramUnit: item.paramUnit,
sortOrder: item.sortOrder,
})),
};
this.saving = true;
saveParams(saveDTO)
.then((response) => {
this.$modal.msgSuccess("保存成功");
// 清除修改标记
this.paramList.forEach((item) => {
item.modified = false;
});
})
.finally(() => {
this.saving = false;
});
},
},
};
</script>
<style scoped lang="scss">
.app-container {
padding: 20px;
background-color: #f5f5f5;
min-height: 100vh;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding: 15px;
background: #fff;
border-radius: 4px;
.title {
font-size: 18px;
font-weight: bold;
color: #333;
}
.link {
color: #1890ff;
text-decoration: none;
font-size: 14px;
i {
margin-right: 4px;
}
&:hover {
text-decoration: underline;
}
}
}
.filter-container {
padding: 15px;
background: #fff;
border-radius: 4px;
margin-bottom: 20px;
}
.table-container {
padding: 20px;
background: #fff;
border-radius: 4px;
margin-bottom: 20px;
.table-title {
font-size: 16px;
font-weight: bold;
color: #333;
margin: 0 0 15px 0;
}
}
.button-container {
padding: 15px;
background: #fff;
border-radius: 4px;
text-align: left;
}
</style>