From b23820e873bfc7a3ec777e6e46361790f357d043 Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Thu, 26 Feb 2026 10:38:23 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=82=E6=95=B0=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../01-数据库设计与后端实体类创建.md | 450 ++++++++++++++ doc/参数配置功能/02-后端业务逻辑开发.md | 420 ++++++++++++++ doc/参数配置功能/03-后端功能测试.md | 353 +++++++++++ doc/参数配置功能/04-前端代码开发.md | 549 ++++++++++++++++++ doc/参数配置功能/设计文档.md | 348 +++++++++++ ruoyi-ui/src/views/ccdi/modelParam/index.vue | 20 +- 6 files changed, 2121 insertions(+), 19 deletions(-) create mode 100644 doc/参数配置功能/01-数据库设计与后端实体类创建.md create mode 100644 doc/参数配置功能/02-后端业务逻辑开发.md create mode 100644 doc/参数配置功能/03-后端功能测试.md create mode 100644 doc/参数配置功能/04-前端代码开发.md create mode 100644 doc/参数配置功能/设计文档.md diff --git a/doc/参数配置功能/01-数据库设计与后端实体类创建.md b/doc/参数配置功能/01-数据库设计与后端实体类创建.md new file mode 100644 index 0000000..06b4a87 --- /dev/null +++ b/doc/参数配置功能/01-数据库设计与后端实体类创建.md @@ -0,0 +1,450 @@ +# 模型参数配置功能 - 后端实体类创建 + +## 任务概述 + +**任务编号:** 01 +**任务名称:** 数据库设计与后端实体类创建 +**前置任务:** 无 +**预计工时:** 1.5小时 + +## 任务目标 + +创建模型参数配置功能的数据库表和初始化数据,以及所有后端实体类、DTO、VO和Maven模块配置。 + +--- + +## 开发步骤 + +### 1. 创建 Maven 模块 + +#### 1.1 创建模块目录 + +在项目根目录下创建 `ccdi-project` 模块: + +``` +ccdi-project/ +├── pom.xml +└── src/main/ + ├── java/ + └── resources/ +``` + +#### 1.2 编写 pom.xml + +**文件路径:** `ccdi-project/pom.xml` + +```xml + + + + ccdi + com.ruoyi + 1.0.0 + + 4.0.0 + + ccdi-project + + + + + com.ruoyi + ruoyi-common + + + +``` + +#### 1.3 修改根 pom.xml + +**文件路径:** `pom.xml` (项目根目录) + +在 `` 标签中添加: + +```xml + + ... + ccdi-project + +``` + +#### 1.4 修改 ruoyi-admin/pom.xml + +**文件路径:** `ruoyi-admin/pom.xml` + +在 `` 标签中添加: + +```xml + + + com.ruoyi + ccdi-project + +``` + +--- + +### 2. 创建数据库脚本 + +#### 2.1 编写建表脚本 + +**文件路径:** `sql/ccdi_model_param.sql` + +```sql +-- ---------------------------- +-- 1. 创建模型参数配置表 +-- ---------------------------- +DROP TABLE IF EXISTS `ccdi_model_param`; +CREATE TABLE `ccdi_model_param` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `project_id` bigint DEFAULT 0 COMMENT '项目ID(0表示默认参数,其他值为具体项目ID)', + `model_code` varchar(100) NOT NULL COMMENT '模型编码', + `model_name` varchar(100) NOT NULL COMMENT '模型名称', + `param_code` varchar(100) NOT NULL COMMENT '参数编码', + `param_name` varchar(100) NOT NULL COMMENT '监测项名称', + `param_desc` varchar(500) DEFAULT NULL COMMENT '参数描述', + `param_value` varchar(200) NOT NULL COMMENT '参数值', + `param_unit` varchar(50) DEFAULT NULL COMMENT '参数单位', + `sort_order` int DEFAULT 0 COMMENT '排序号(参数展示顺序)', + `create_by` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_by` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_project_model_param` (`project_id`, `model_code`, `param_code`) COMMENT '同一项目下模型参数唯一', + KEY `idx_project_id` (`project_id`) COMMENT '项目ID索引', + KEY `idx_model_code` (`model_code`) COMMENT '模型编码索引' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='模型参数配置表'; + +-- ---------------------------- +-- 2. 初始化大额交易模型参数 +-- ---------------------------- +INSERT INTO ccdi_model_param (project_id, model_code, model_name, param_code, param_name, param_desc, param_value, param_unit, sort_order, create_by, remark) VALUES +(0, 'LARGE_TRANSACTION', '大额交易模型', 'SINGLE_TRANSACTION_AMOUNT', '单笔交易额', '单笔超过该金额视为大额交易', '50000', '元', 1, 'admin', '系统默认参数'), +(0, 'LARGE_TRANSACTION', '大额交易模型', 'CUMULATIVE_TRANSACTION_AMOUNT', '累计交易额', '年累计交易额超过该金额', '5000000', '元', 2, 'admin', '系统默认参数'), +(0, 'LARGE_TRANSACTION', '大额交易模型', 'LARGE_CASH_DEPOSIT', '大额存现', '单笔存现金额超过', '200000', '元', 3, 'admin', '系统默认参数'), +(0, 'LARGE_TRANSACTION', '大额交易模型', 'FREQUENT_CASH_DEPOSIT', '短时多次存现', '24小时内累计存现超过', '100000', '元/4小时', 4, 'admin', '系统默认参数'), +(0, 'LARGE_TRANSACTION', '大额交易模型', 'FREQUENT_TRANSFER', '频繁转账', '单日转账次数超过', '10', '次/日', 5, 'admin', '系统默认参数'), +(0, 'LARGE_TRANSACTION', '大额交易模型', 'TRANSFER_FREQUENCY', '转账频率', '单日累计转账金额超过', '1000000', '元/日', 6, 'admin', '系统默认参数'); + +-- ---------------------------- +-- 3. 初始化可疑兼职模型参数 +-- ---------------------------- +INSERT INTO ccdi_model_param (project_id, model_code, model_name, param_code, param_name, param_desc, param_value, param_unit, sort_order, create_by, remark) VALUES +(0, 'SUSPICIOUS_PART_TIME', '可疑兼职模型', 'MONTHLY_FIXED_INCOME', '月度固定收入', '除本行工资外,每月固定收入超过', '5000', '元/月', 1, 'admin', '系统默认参数'), +(0, 'SUSPICIOUS_PART_TIME', '可疑兼职模型', 'FIXED_COUNTERPARTY_TRANSFER', '固定对手转入', '每季从固定交易对手转入金额', '15000', '元/季', 2, 'admin', '系统默认参数'), +(0, 'SUSPICIOUS_PART_TIME', '可疑兼职模型', 'SUSPICIOUS_TIME_TRANSACTION', '非工作时间交易', '非工作时间(22:00-06:00)交易次数', '20', '次/月', 3, 'admin', '系统默认参数'); + +-- ---------------------------- +-- 4. 初始化可疑外汇交易模型参数 +-- ---------------------------- +INSERT INTO ccdi_model_param (project_id, model_code, model_name, param_code, param_name, param_desc, param_value, param_unit, sort_order, create_by, remark) VALUES +(0, 'SUSPICIOUS_FOREIGN_EXCHANGE', '可疑外汇交易模型', 'SINGLE_PURCHASE_AMOUNT', '单笔购汇金额', '单笔购汇超过该金额', '50000', '美元/笔', 1, 'admin', '系统默认参数'), +(0, 'SUSPICIOUS_FOREIGN_EXCHANGE', '可疑外汇交易模型', 'SINGLE_SETTLEMENT_AMOUNT', '单笔结汇金额', '单笔结汇超过该金额', '50000', '美元/笔', 2, 'admin', '系统默认参数'), +(0, 'SUSPICIOUS_FOREIGN_EXCHANGE', '可疑外汇交易模型', 'CROSS_BORDER_REMITTANCE', '跨境汇款金额', '跨境汇款金额超过', '200000', '美元/笔', 3, 'admin', '系统默认参数'), +(0, 'SUSPICIOUS_FOREIGN_EXCHANGE', '可疑外汇交易模型', 'MONTHLY_PURCHASE_TOTAL', '月度购汇总额', '月度购汇总额超过', '100000', '美元/月', 4, 'admin', '系统默认参数'), +(0, 'SUSPICIOUS_FOREIGN_EXCHANGE', '可疑外汇交易模型', 'MONTHLY_SETTLEMENT_TOTAL', '月度结汇总额', '月度结汇总额超过', '100000', '美元/月', 5, 'admin', '系统默认参数'), +(0, 'SUSPICIOUS_FOREIGN_EXCHANGE', '可疑外汇交易模型', 'FREQUENT_FOREX_TRADE', '频繁外汇交易', '单日外汇交易次数超过', '5', '次/日', 6, 'admin', '系统默认参数'); +``` + +#### 2.2 执行数据库脚本 + +**使用MCP连接数据库执行:** + +```bash +# 通过MCP工具连接数据库并执行SQL脚本 +# 注意:不使用命令行的mysql,使用MCP连接项目配置文件中的数据库 +``` + +--- + +### 3. 创建实体类 + +#### 3.1 创建包结构 + +``` +ccdi-project/src/main/java/com/ruoyi/ccdi/project/ +├── domain/ +│ ├── CcdiModelParam.java +│ ├── dto/ +│ └── vo/ +``` + +#### 3.2 创建 Entity + +**文件路径:** `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/CcdiModelParam.java` + +```java +package com.ruoyi.ccdi.project.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import java.util.Date; + +/** + * 模型参数配置 ccdi_model_param + */ +@Data +@TableName("ccdi_model_param") +public class CcdiModelParam { + + /** 主键ID */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 项目ID(0表示默认参数) */ + private Long projectId; + + /** 模型编码 */ + private String modelCode; + + /** 模型名称 */ + private String modelName; + + /** 参数编码 */ + private String paramCode; + + /** 监测项名称 */ + private String paramName; + + /** 参数描述 */ + private String paramDesc; + + /** 参数值 */ + private String paramValue; + + /** 参数单位 */ + private String paramUnit; + + /** 排序号 */ + private Integer sortOrder; + + /** 创建者 */ + private String createBy; + + /** 创建时间 */ + private Date createTime; + + /** 更新者 */ + private String updateBy; + + /** 更新时间 */ + private Date updateTime; + + /** 备注 */ + private String remark; +} +``` + +--- + +### 4. 创建 DTO + +#### 4.1 查询 DTO + +**文件路径:** `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/ModelParamQueryDTO.java` + +```java +package com.ruoyi.ccdi.project.domain.dto; + +import lombok.Data; +import jakarta.validation.constraints.NotBlank; + +/** + * 模型参数查询DTO + */ +@Data +public class ModelParamQueryDTO { + + /** 项目ID */ + private Long projectId; + + /** 模型编码 */ + @NotBlank(message = "模型编码不能为空") + private String modelCode; +} +``` + +#### 4.2 保存 DTO + +**文件路径:** `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/ModelParamSaveDTO.java` + +```java +package com.ruoyi.ccdi.project.domain.dto; + +import lombok.Data; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import java.util.List; + +/** + * 模型参数保存DTO + */ +@Data +public class ModelParamSaveDTO { + + /** 项目ID */ + private Long projectId; + + /** 模型编码 */ + @NotBlank(message = "模型编码不能为空") + private String modelCode; + + /** 模型名称 */ + @NotBlank(message = "模型名称不能为空") + private String modelName; + + /** 参数列表 */ + @NotNull(message = "参数列表不能为空") + private List params; + + @Data + public static class ParamItem { + + /** 参数编码 */ + @NotBlank(message = "参数编码不能为空") + private String paramCode; + + /** 监测项名称 */ + private String paramName; + + /** 参数描述 */ + private String paramDesc; + + /** 参数值 - 唯一可修改字段 */ + @NotBlank(message = "参数值不能为空") + private String paramValue; + + /** 参数单位 */ + private String paramUnit; + + /** 排序号 */ + private Integer sortOrder; + } +} +``` + +--- + +### 5. 创建 VO + +#### 5.1 参数 VO + +**文件路径:** `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/ModelParamVO.java` + +```java +package com.ruoyi.ccdi.project.domain.vo; + +import lombok.Data; + +/** + * 模型参数VO + */ +@Data +public class ModelParamVO { + + /** 主键ID */ + private Long id; + + /** 模型编码 */ + private String modelCode; + + /** 模型名称 */ + private String modelName; + + /** 参数编码 */ + private String paramCode; + + /** 监测项名称 */ + private String paramName; + + /** 参数描述 */ + private String paramDesc; + + /** 参数值 */ + private String paramValue; + + /** 参数单位 */ + private String paramUnit; + + /** 排序号 */ + private Integer sortOrder; +} +``` + +#### 5.2 模型列表 VO + +**文件路径:** `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/ModelListVO.java` + +```java +package com.ruoyi.ccdi.project.domain.vo; + +import lombok.Data; + +/** + * 模型列表VO + */ +@Data +public class ModelListVO { + + /** 模型编码 */ + private String modelCode; + + /** 模型名称 */ + private String modelName; +} +``` + +--- + +## 验证清单 + +完成以下验证后,本任务才算完成: + +**数据库部分:** + +- [ ] sql/ccdi_model_param.sql 脚本创建完成 +- [ ] 数据库表创建成功 +- [ ] 初始化数据插入成功(3个模型共15条参数) + +**后端部分:** + +- [ ] ccdi-project 模块创建成功 +- [ ] 根 pom.xml 已添加模块 +- [ ] ruoyi-admin/pom.xml 已添加依赖 +- [ ] CcdiModelParam 实体类创建完成 +- [ ] ModelParamQueryDTO 创建完成 +- [ ] ModelParamSaveDTO 创建完成 +- [ ] ModelParamVO 创建完成 +- [ ] ModelListVO 创建完成 +- [ ] 项目编译无错误: `mvn clean compile` + +--- + +## 注意事项 + +**数据库部分:** + +1. **执行顺序**: 必须先创建数据库表,再创建实体类 +2. **使用MCP**: 使用MCP连接数据库执行SQL,不使用命令行mysql +3. **数据验证**: 执行后验证3个模型的15条参数数据是否正确插入 + +**后端部分:** + +1. **包名规范**: 必须使用 `com.ruoyi.ccdi.project` 作为基础包名 +2. **注解使用**: 实体类使用 `@Data` 注解,不继承 BaseEntity +3. **字段验证**: DTO 中必须添加验证注解 `@NotBlank`、`@NotNull` +4. **注释完整**: 所有字段必须添加注释说明 +5. **导入语句**: 禁止使用全限定类名,必须使用 import 语句 + +--- + +## 下一步 + +完成本任务后,进入下一个任务: **02-后端业务逻辑开发.md** diff --git a/doc/参数配置功能/02-后端业务逻辑开发.md b/doc/参数配置功能/02-后端业务逻辑开发.md new file mode 100644 index 0000000..8e59c03 --- /dev/null +++ b/doc/参数配置功能/02-后端业务逻辑开发.md @@ -0,0 +1,420 @@ +# 模型参数配置功能 - 后端业务逻辑开发 + +## 任务概述 + +**任务编号:** 02 +**任务名称:** 后端业务逻辑开发 +**前置任务:** 01-后端实体类创建 +**预计工时:** 2小时 + +## 任务目标 + +开发模型参数配置功能的 Mapper 层、Service 层和 Controller 层,实现查询模型列表、查询参数列表、保存参数配置三个核心接口。 + +--- + +## 开发步骤 + +### 1. 创建 Mapper 接口 + +#### 1.1 创建 Mapper 接口 + +**文件路径:** `ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiModelParamMapper.java` + +```java +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 { + + /** + * 查询指定项目和模型的参数列表 + * + * @param projectId 项目ID + * @param modelCode 模型编码 + * @return 参数列表 + */ + List selectByProjectAndModel( + @Param("projectId") Long projectId, + @Param("modelCode") String modelCode + ); + + /** + * 查询所有模型列表(去重) + * + * @param projectId 项目ID + * @return 模型列表 + */ + List selectDistinctModels(@Param("projectId") Long projectId); + + /** + * 批量更新参数值(只更新param_value字段) + * + * @param list 参数列表 + * @return 更新数量 + */ + int batchUpdateParamValues(@Param("list") List list); +} +``` + +--- + +### 2. 创建 Mapper XML + +#### 2.1 创建资源目录 + +``` +ccdi-project/src/main/resources/ +└── mapper/ + └── ccdi/ + └── project/ +``` + +#### 2.2 编写 Mapper XML + +**文件路径:** `ccdi-project/src/main/resources/mapper/ccdi/project/CcdiModelParamMapper.xml` + +```xml + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + update ccdi_model_param + set param_value = #{item.paramValue}, + update_by = #{item.updateBy}, + update_time = sysdate() + where id = #{item.id} + + + + +``` + +--- + +### 3. 创建 Service 接口 + +**文件路径:** `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiModelParamService.java` + +```java +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 selectModelList(Long projectId); + + /** + * 查询模型参数列表 + * + * @param queryDTO 查询条件 + * @return 参数列表 + */ + List selectParamList(ModelParamQueryDTO queryDTO); + + /** + * 保存模型参数(只更新阈值) + * + * @param saveDTO 保存参数 + */ + void saveParams(ModelParamSaveDTO saveDTO); +} +``` + +--- + +### 4. 创建 Service 实现 + +#### 4.1 创建实现类目录 + +``` +ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ +└── impl/ +``` + +#### 4.2 编写 Service 实现 + +**文件路径:** `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiModelParamServiceImpl.java` + +```java +package com.ruoyi.ccdi.project.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +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; + +/** + * 模型参数Service实现 + */ +@Service +public class CcdiModelParamServiceImpl implements ICcdiModelParamService { + + @Resource + private CcdiModelParamMapper modelParamMapper; + + @Override + public List selectModelList(Long projectId) { + if (projectId == null) { + projectId = 0L; // 默认查询系统级参数 + } + + List result = new ArrayList<>(); + List 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 selectParamList(ModelParamQueryDTO queryDTO) { + Long projectId = queryDTO.getProjectId(); + if (projectId == null) { + projectId = 0L; + } + + List params = modelParamMapper.selectByProjectAndModel( + projectId, + queryDTO.getModelCode() + ); + + List 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; + } + + String username = SecurityUtils.getUsername(); + Date now = new Date(); + + // 查询现有参数 + List existingParams = modelParamMapper.selectByProjectAndModel( + projectId, + saveDTO.getModelCode() + ); + + if (existingParams.isEmpty()) { + throw new ServiceException("未找到模型参数配置"); + } + + // 准备更新列表 - 只更新 param_value 字段 + List updateList = new ArrayList<>(); + for (ModelParamSaveDTO.ParamItem item : saveDTO.getParams()) { + CcdiModelParam existing = existingParams.stream() + .filter(p -> p.getParamCode().equals(item.getParamCode())) + .findFirst() + .orElse(null); + + 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); + } + } +} +``` + +--- + +### 5. 创建 Controller + +**文件路径:** `ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiModelParamController.java` + +```java +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 list = modelParamService.selectModelList(projectId); + return success(list); + } + + /** + * 查询模型参数列表 + */ + @Operation(summary = "查询模型参数列表") + @GetMapping("/list") + public AjaxResult list(@Validated ModelParamQueryDTO queryDTO) { + List 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("保存成功"); + } +} +``` + +--- + +## 验证清单 + +完成以下验证后,本任务才算完成: + +- [ ] CcdiModelParamMapper 接口创建完成 +- [ ] CcdiModelParamMapper.xml 创建完成 +- [ ] ICcdiModelParamService 接口创建完成 +- [ ] CcdiModelParamServiceImpl 实现类创建完成 +- [ ] CcdiModelParamController 创建完成 +- [ ] 所有类使用 import 导入,无全限定类名 +- [ ] Service 使用 @Resource 注入 +- [ ] Controller 添加了 Swagger 注解 +- [ ] 项目编译无错误: `mvn clean compile` + +--- + +## 注意事项 + +1. **Mapper XML 位置**: 必须放在 `resources/mapper/ccdi/project/` 目录下 +2. **批量更新**: 使用 `separator=";"` 实现批量更新 +3. **只更新阈值**: UPDATE 语句只更新 `param_value` 字段 +4. **事务管理**: Service 实现类必须添加 `@Transactional` 注解 +5. **异常处理**: 使用 `ServiceException` 抛出业务异常 +6. **Swagger 文档**: Controller 必须添加 `@Tag` 和 `@Operation` 注解 + +--- + +## 下一步 + +完成本任务后,进入下一个任务: **03-后端功能测试.md** diff --git a/doc/参数配置功能/03-后端功能测试.md b/doc/参数配置功能/03-后端功能测试.md new file mode 100644 index 0000000..d0b8425 --- /dev/null +++ b/doc/参数配置功能/03-后端功能测试.md @@ -0,0 +1,353 @@ +# 模型参数配置功能 - 后端功能测试 + +## 任务概述 + +**任务编号:** 03 +**任务名称:** 后端功能测试 +**前置任务:** 02-后端业务逻辑开发 +**预计工时:** 1小时 + +## 任务目标 + +启动后端服务,使用 Swagger 测试所有接口,确保功能正常。 + +--- + +## 开发步骤 + +### 1. 启动后端服务 + +#### 1.1 编译项目 + +```bash +# 在项目根目录执行 +mvn clean compile +``` + +#### 1.2 启动应用 + +**方式一:使用 Maven** + +```bash +mvn spring-boot:run +``` + +**方式二:使用启动脚本** + +```bash +# Windows +ry.bat + +# Linux/Mac +./ry.sh start +``` + +#### 1.3 验证启动成功 + +访问: http://localhost:8080 + +看到若依登录页面即表示启动成功。 + +--- + +### 2. 获取测试 Token + +#### 2.1 登录获取 Token + +**请求地址:** + +``` +POST http://localhost:8080/login/test?username=admin&password=admin123 +``` + +**使用 curl:** + +```bash +curl -X POST "http://localhost:8080/login/test?username=admin&password=admin123" +``` + +**响应示例:** + +```json +{ + "msg": "操作成功", + "code": 200, + "data": { + "token": "eyJhbGciOiJIUzUxMiJ9..." + } +} +``` + +**记录 Token:** 将返回的 token 值保存,后续测试需要使用。 + +--- + +### 3. Swagger 接口测试 + +#### 3.1 访问 Swagger UI + +浏览器访问: http://localhost:8080/swagger-ui/index.html + +#### 3.2 配置 Authorization + +1. 点击右上角 "Authorize" 按钮 +2. 在弹出框中输入: `Bearer <你的token>` +3. 点击 "Authorize" 确认 + +#### 3.3 测试接口1: 查询模型列表 + +**接口路径:** `GET /ccdi/modelParam/modelList` + +**测试步骤:** + +1. 在 Swagger UI 中找到 "模型参数配置" 分组 +2. 点击 `GET /ccdi/modelParam/modelList` 接口 +3. 点击 "Try it out" +4. 参数 `projectId` 留空(默认查询系统参数) +5. 点击 "Execute" + +**预期响应:** + +```json +{ + "msg": "操作成功", + "code": 200, + "data": [ + { + "modelCode": "LARGE_TRANSACTION", + "modelName": "大额交易模型" + }, + { + "modelCode": "SUSPICIOUS_FOREIGN_EXCHANGE", + "modelName": "可疑外汇交易模型" + }, + { + "modelCode": "SUSPICIOUS_PART_TIME", + "modelName": "可疑兼职模型" + } + ] +} +``` + +#### 3.4 测试接口2: 查询模型参数列表 + +**接口路径:** `GET /ccdi/modelParam/list` + +**测试步骤:** + +1. 点击 `GET /ccdi/modelParam/list` 接口 +2. 点击 "Try it out" +3. 参数填写: + - `modelCode`: `LARGE_TRANSACTION` + - `projectId`: 留空 +4. 点击 "Execute" + +**预期响应:** + +```json +{ + "msg": "操作成功", + "code": 200, + "data": [ + { + "id": 1, + "modelCode": "LARGE_TRANSACTION", + "modelName": "大额交易模型", + "paramCode": "SINGLE_TRANSACTION_AMOUNT", + "paramName": "单笔交易额", + "paramDesc": "单笔超过该金额视为大额交易", + "paramValue": "50000", + "paramUnit": "元", + "sortOrder": 1 + }, + ... + ] +} +``` + +#### 3.5 测试接口3: 保存参数配置 + +**接口路径:** `POST /ccdi/modelParam/save` + +**测试步骤:** + +1. 点击 `POST /ccdi/modelParam/save` 接口 +2. 点击 "Try it out" +3. 在 Request body 中填写: + +```json +{ + "projectId": 0, + "modelCode": "LARGE_TRANSACTION", + "modelName": "大额交易模型", + "params": [ + { + "paramCode": "SINGLE_TRANSACTION_AMOUNT", + "paramName": "单笔交易额", + "paramDesc": "单笔超过该金额视为大额交易", + "paramValue": "60000", + "paramUnit": "元", + "sortOrder": 1 + }, + { + "paramCode": "CUMULATIVE_TRANSACTION_AMOUNT", + "paramName": "累计交易额", + "paramDesc": "年累计交易额超过该金额", + "paramValue": "6000000", + "paramUnit": "元", + "sortOrder": 2 + } + ] +} +``` + +4. 点击 "Execute" + +**预期响应:** + +```json +{ + "msg": "保存成功", + "code": 200 +} +``` + +#### 3.6 验证数据已更新 + +再次调用 `GET /ccdi/modelParam/list` 接口,确认参数值已更新为 60000 和 6000000。 + +--- + +### 4. 数据库验证 + +#### 4.1 查询参数数据 + +```sql +-- 查询大额交易模型的参数 +SELECT id, model_code, param_name, param_value, update_by, update_time +FROM ccdi_model_param +WHERE model_code = 'LARGE_TRANSACTION' +ORDER BY sort_order; +``` + +**预期结果:** + +``` +id | model_code | param_name | param_value | update_by | update_time +---|---------------------|-------------------------|-------------|-----------|------------------ +1 | LARGE_TRANSACTION | 单笔交易额 | 60000 | admin | 2026-02-26 10:30:00 +2 | LARGE_TRANSACTION | 累计交易额 | 6000000 | admin | 2026-02-26 10:30:00 +3 | LARGE_TRANSACTION | 大额存现 | 200000 | NULL | 2026-02-26 09:00:00 +4 | LARGE_TRANSACTION | 短时多次存现 | 100000 | NULL | 2026-02-26 09:00:00 +5 | LARGE_TRANSACTION | 频繁转账 | 10 | NULL | 2026-02-26 09:00:00 +6 | LARGE_TRANSACTION | 转账频率 | 1000000 | NULL | 2026-02-26 09:00:00 +``` + +验证点: + +- ✅ 只有被修改的参数有 `update_by` 和 `update_time` +- ✅ 参数值已更新为提交的值 +- ✅ 其他未修改的参数保持原值 + +--- + +### 5. 安全性验证 + +#### 5.1 验证只能修改阈值 + +尝试在保存接口中修改其他字段(如 param_name): + +```json +{ + "projectId": 0, + "modelCode": "LARGE_TRANSACTION", + "modelName": "大额交易模型", + "params": [ + { + "paramCode": "SINGLE_TRANSACTION_AMOUNT", + "paramName": "修改后的名称", // 尝试修改名称 + "paramValue": "70000", + "paramUnit": "修改后的单位", // 尝试修改单位 + "sortOrder": 1 + } + ] +} +``` + +**验证数据库:** + +```sql +SELECT param_name, param_unit, param_value +FROM ccdi_model_param +WHERE param_code = 'SINGLE_TRANSACTION_AMOUNT'; +``` + +**预期结果:** + +- ✅ `param_value` 已更新为 70000 +- ✅ `param_name` 仍为 "单笔交易额" (未改变) +- ✅ `param_unit` 仍为 "元" (未改变) + +--- + +## 测试清单 + +完成以下测试后,本任务才算完成: + +- [ ] 后端服务启动成功 +- [ ] 获取 Token 成功 +- [ ] Swagger 测试:查询模型列表接口正常 +- [ ] Swagger 测试:查询参数列表接口正常 +- [ ] Swagger 测试:保存参数接口正常 +- [ ] 数据库验证:数据已正确更新 +- [ ] 安全性验证:只能修改阈值字段 + +--- + +## 测试报告模板 + +完成测试后,请填写以下测试报告: + +### 测试报告 + +**测试日期:** 2026-02-26 +**测试人员:** ___________ +**测试环境:** + +- 数据库地址: ___________ +- 后端地址: http://localhost:8080 + +**测试结果:** + +| 测试项 | 预期结果 | 实际结果 | 是否通过 | +|----------|--------|------|------| +| 查询模型列表 | 返回3个模型 | | | +| 查询大额交易参数 | 返回6个参数 | | | +| 保存参数配置 | 返回成功 | | | +| 数据更新验证 | 数据已更新 | | | +| 安全性验证 | 只更新阈值 | | | + +**发现问题:** + +- (如有问题请记录) + +**结论:** + +- [ ] 通过 +- [ ] 不通过 + +--- + +## 注意事项 + +1. **测试顺序**: 必须按照测试步骤的顺序执行 +2. **Token 有效期**: Token 有效期 30 分钟,过期需重新获取 +3. **数据库连接**: 确保数据库连接配置正确 +4. **端口占用**: 确保 8080 端口未被占用 +5. **日志查看**: 如遇问题,查看后端日志排查 + +--- + +## 下一步 + +完成本任务后,进入下一个任务: **04-前端代码开发.md** diff --git a/doc/参数配置功能/04-前端代码开发.md b/doc/参数配置功能/04-前端代码开发.md new file mode 100644 index 0000000..d0f704f --- /dev/null +++ b/doc/参数配置功能/04-前端代码开发.md @@ -0,0 +1,549 @@ +# 模型参数配置功能 - 前端代码开发 + +## 任务概述 + +**任务编号:** 04 +**任务名称:** 前端代码开发 +**前置任务:** 03-后端功能测试 +**预计工时:** 2小时 + +## 任务目标 + +开发模型参数配置功能的前端页面,包括 API 请求文件和 Vue 页面组件,实现模型选择、参数查询、参数修改、保存配置等功能。 + +--- + +## 开发步骤 + +### 1. 创建 API 文件 + +#### 1.1 创建 API 目录 + +``` +ruoyi-ui/src/api/ +└── ccdi/ +``` + +#### 1.2 编写 API 文件 + +**文件路径:** `ruoyi-ui/src/api/ccdi/modelParam.js` + +```javascript +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 + }) +} +``` + +--- + +### 2. 创建页面组件 + +#### 2.1 创建页面目录 + +``` +ruoyi-ui/src/views/ +└── ccdi/ + └── modelParam/ +``` + +#### 2.2 编写页面组件 + +**文件路径:** `ruoyi-ui/src/views/ccdi/modelParam/index.vue` + +```vue + + + + + +``` + +--- + +### 3. 配置路由(可选) + +如果需要独立访问路径,可以配置路由。 + +#### 3.1 查找路由配置文件 + +**文件路径:** `ruoyi-ui/src/router/index.js` + +#### 3.2 添加路由配置(如需要) + +```javascript +{ + path: '/ccdi/modelParam', + component: Layout, + children: [ + { + path: '', + name: 'ModelParam', + component: () => import('@/views/ccdi/modelParam/index'), + meta: { title: '模型参数管理', icon: 'setting' } + } + ] +} +``` + +**注意:** 若依框架通常通过数据库菜单表动态生成路由,可以不配置静态路由。 + +--- + +### 4. 添加菜单(通过数据库) + +#### 4.1 准备菜单数据 + +```sql +-- 添加模型参数管理菜单 +INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) VALUES +('模型参数管理', 0, 10, 'modelParam', 'ccdi/modelParam/index', 1, 0, 'C', '0', '0', 'ccdi:modelParam:list', 'setting', 'admin', sysdate(), '模型参数管理菜单'); +``` + +#### 4.2 执行 SQL + +```bash +mysql -h<数据库地址> -u<用户名> -p<密码> ccdi < sql/ccdi_model_param_menu.sql +``` + +**注意:** 具体的 parent_id 需要根据实际的父菜单ID调整。 + +--- + +### 5. 前端测试 + +#### 5.1 启动前端服务 + +```bash +cd ruoyi-ui +npm run dev +``` + +#### 5.2 访问页面 + +浏览器访问: http://localhost:80 + +登录后,在菜单中找到"模型参数管理"并点击。 + +#### 5.3 功能测试清单 + +**测试1: 页面加载** + +- [ ] 页面正常加载,显示标题"模型参数管理" +- [ ] 模型下拉框自动加载模型列表 +- [ ] 默认选中第一个模型 +- [ ] 自动加载第一个模型的参数 + +**测试2: 模型切换** + +- [ ] 切换模型下拉框选择"可疑兼职模型" +- [ ] 点击"查询"按钮 +- [ ] 参数列表正确显示可疑兼职模型的参数 + +**测试3: 参数修改** + +- [ ] 在"阈值设置"输入框中修改数值 +- [ ] 只能修改阈值列,其他列只读 +- [ ] 修改后可以继续编辑其他参数 + +**测试4: 保存配置** + +- [ ] 点击"保存配置"按钮 +- [ ] 按钮显示 loading 状态 +- [ ] 保存成功后显示"保存成功"提示 +- [ ] 页面刷新后数据已更新 + +**测试5: 未修改提示** + +- [ ] 不修改任何参数 +- [ ] 点击"保存配置"按钮 +- [ ] 显示"没有需要保存的修改"提示 + +**测试6: 验证只能修改阈值** + +- [ ] 尝试点击"监测项"、"描述"、"单位"列 +- [ ] 确认这些列无法编辑 +- [ ] 只有"阈值设置"列可以编辑 + +--- + +### 6. 样式调整 + +#### 6.1 检查页面样式 + +确保页面样式与设计稿一致: + +- [ ] 背景色为 #f5f5f5 +- [ ] 卡片背景色为 #fff +- [ ] 标题颜色为 #333 +- [ ] 链接颜色为 #1890ff +- [ ] 边框圆角为 4px +- [ ] 表格边框清晰 + +#### 6.2 响应式适配(可选) + +如需支持移动端,可以添加响应式样式: + +```scss +@media screen and (max-width: 768px) { + .app-container { + padding: 10px; + } + + .header { + flex-direction: column; + align-items: flex-start; + } + + .el-table { + font-size: 14px; + } +} +``` + +--- + +## 验证清单 + +完成以下验证后,本任务才算完成: + +- [ ] API 文件创建完成 +- [ ] 页面组件创建完成 +- [ ] 页面可以正常访问 +- [ ] 模型列表加载正常 +- [ ] 参数列表查询正常 +- [ ] 参数修改功能正常 +- [ ] 保存配置功能正常 +- [ ] 只有阈值列可编辑 +- [ ] 样式与设计稿一致 +- [ ] 所有功能测试通过 + +--- + +## 常见问题 + +### 问题1: 跨域错误 + +**现象:** 浏览器控制台显示 CORS 错误 + +**解决:** +检查 `ruoyi-ui/vue.config.js` 中的代理配置: + +```javascript +proxy: { + [process.env.VUE_APP_BASE_API]: { + target: 'http://localhost:8080', + changeOrigin: true, + pathRewrite: { + ['^' + process.env.VUE_APP_BASE_API]: '' + } + } +} +``` + +### 问题2: Token 过期 + +**现象:** 接口返回 401 未授权 + +**解决:** +重新登录获取新 Token,或清除浏览器缓存。 + +### 问题3: 菜单不显示 + +**现象:** 登录后看不到"模型参数管理"菜单 + +**解决:** + +1. 检查菜单 SQL 是否执行成功 +2. 检查当前用户是否有该菜单权限 +3. 清除浏览器缓存并重新登录 + +--- + +## 优化建议(可选) + +### 1. 输入验证 + +为阈值输入框添加数值验证: + +```vue + +``` + +### 2. 批量修改 + +添加"批量修改"功能,一次性修改多个模型的参数。 + +### 3. 修改历史记录 + +显示参数的修改历史,包括修改时间、修改人、修改前后的值。 + +--- + +## 下一步 + +完成本任务后,整个模型参数配置功能开发完成! + +**总结:** + +- ✅ 后端实体类创建完成 +- ✅ 后端业务逻辑开发完成 +- ✅ 后端功能测试通过 +- ✅ 前端代码开发完成 + +**功能已上线,可以进行功能验收。** diff --git a/doc/参数配置功能/设计文档.md b/doc/参数配置功能/设计文档.md new file mode 100644 index 0000000..4f2e852 --- /dev/null +++ b/doc/参数配置功能/设计文档.md @@ -0,0 +1,348 @@ +# 模型参数配置功能 - 设计文档 + +## 1. 功能概述 + +### 1.1 功能定位 + +模型参数配置管理功能,用于配置风险监测模型的阈值参数,支持多模型参数管理,为未来的项目级自定义参数预留扩展能力。 + +### 1.2 核心能力 + +- ✅ 支持多模型参数配置(大额交易、可疑兼职、可疑外汇等) +- ✅ 参数持久化存储到数据库 +- ✅ 按模型查询和修改参数 +- ✅ 只允许修改阈值,其他信息只读 +- ✅ 为未来项目级配置预留扩展能力 + +### 1.3 用户场景 + +1. **系统管理员** 选择需要配置的模型 +2. **系统管理员** 修改模型的阈值参数 +3. **系统管理员** 保存配置,参数立即生效 + +--- + +## 2. 需求分析 + +### 2.1 业务需求 + +根据需求截图,系统需要支持多个风险监测模型的参数配置: + +**模型清单:** + +- 大额交易模型 +- 可疑兼职模型 +- 可疑外汇交易模型 +- (未来可能新增其他模型) + +**参数特征:** + +- 每个模型有固定数量的参数项(3-6个不等) +- 每个参数包含:监测项名称、描述、阈值设置、单位 +- 只有阈值可以修改,其他信息只读 + +### 2.2 功能需求 + +| 需求项 | 说明 | +|-------|------------------------| +| 数据存储 | 参数配置需要持久化存储到数据库 | +| 参数项管理 | 参数项固定,在开发时确定,后期不频繁增减 | +| 新增模型 | 需要开发介入,通过代码和数据库脚本实现 | +| 权限控制 | 统一权限控制,有菜单权限即可修改所有模型参数 | +| 修改历史 | 不需要记录修改历史,只保存当前状态 | +| 恢复默认 | 不需要开发恢复默认功能 | +| 其他功能 | 只需要基本的查询、修改、保存功能 | + +### 2.3 非功能需求 + +| 需求项 | 说明 | +|------|-----------------------------| +| 性能 | 单表查询,响应时间 < 500ms | +| 安全性 | 后端只能修改阈值字段,其他字段不可修改 | +| 可扩展性 | 预留 project_id 字段,支持未来的项目级配置 | +| 易用性 | 界面简洁,操作直观 | + +--- + +## 3. 架构设计 + +### 3.1 模块架构 + +**新建模块:** `ccdi-project` + +**模块定位:** 项目相关功能模块,包含参数配置等项目管理功能 + +**依赖关系:** + +``` +ruoyi-admin (启动模块) + ├── ruoyi-framework + ├── ruoyi-system + ├── ruoyi-common + ├── ccdi-project (新建模块) ⭐ + │ └── ruoyi-common + └── ruoyi-info-collection +``` + +### 3.2 分层架构 + +``` +前端 (Vue.js) + ↓ HTTP请求 +Controller (CcdiModelParamController) + ↓ 调用 +Service (ICcdiModelParamService) + ↓ 调用 +Mapper (CcdiModelParamMapper) + ↓ SQL +Database (ccdi_model_param) +``` + +--- + +## 4. 数据库设计 + +### 4.1 表结构 + +**表名:** `ccdi_model_param` + +```sql +CREATE TABLE `ccdi_model_param` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `project_id` bigint DEFAULT 0 COMMENT '项目ID(0表示默认参数,其他值为具体项目ID)', + `model_code` varchar(100) NOT NULL COMMENT '模型编码', + `model_name` varchar(100) NOT NULL COMMENT '模型名称', + `param_code` varchar(100) NOT NULL COMMENT '参数编码', + `param_name` varchar(100) NOT NULL COMMENT '监测项名称', + `param_desc` varchar(500) DEFAULT NULL COMMENT '参数描述', + `param_value` varchar(200) NOT NULL COMMENT '参数值', + `param_unit` varchar(50) DEFAULT NULL COMMENT '参数单位', + `sort_order` int DEFAULT 0 COMMENT '排序号(参数展示顺序)', + `create_by` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_by` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_project_model_param` (`project_id`, `model_code`, `param_code`) COMMENT '同一项目下模型参数唯一', + KEY `idx_project_id` (`project_id`) COMMENT '项目ID索引', + KEY `idx_model_code` (`model_code`) COMMENT '模型编码索引' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='模型参数配置表'; +``` + +### 4.2 字段说明 + +| 字段名 | 类型 | 说明 | 是否可修改 | +|-----------------|--------------|-------------|-------------| +| id | bigint | 主键ID | ❌ | +| project_id | bigint | 项目ID(0=默认) | ❌ | +| model_code | varchar(100) | 模型编码 | ❌ | +| model_name | varchar(100) | 模型名称 | ❌ | +| param_code | varchar(100) | 参数编码 | ❌ | +| param_name | varchar(100) | 监测项名称 | ❌ | +| param_desc | varchar(500) | 参数描述 | ❌ | +| **param_value** | varchar(200) | **参数值(阈值)** | ✅ **唯一可修改** | +| param_unit | varchar(50) | 参数单位 | ❌ | +| sort_order | int | 排序号 | ❌ | +| create_by | varchar(64) | 创建者 | ❌ | +| create_time | datetime | 创建时间 | ❌ | +| update_by | varchar(64) | 更新者 | 自动 | +| update_time | datetime | 更新时间 | 自动 | +| remark | varchar(500) | 备注 | ❌ | + +### 4.3 索引设计 + +| 索引名 | 索引类型 | 字段 | 用途 | +|------------------------|------|------------------------------------|---------| +| PRIMARY | 主键 | id | 主键索引 | +| uk_project_model_param | 唯一索引 | project_id, model_code, param_code | 保证参数唯一性 | +| idx_project_id | 普通索引 | project_id | 加速项目查询 | +| idx_model_code | 普通索引 | model_code | 加速模型查询 | + +### 4.4 初始化数据 + +参见开发计划文档中的数据初始化脚本。 + +--- + +## 5. 后端设计 + +### 5.1 模块结构 + +``` +ccdi-project/ +├── pom.xml +└── src/main/ + ├── java/com/ruoyi/ccdi/project/ + │ ├── controller/ + │ │ └── CcdiModelParamController.java + │ ├── service/ + │ │ ├── ICcdiModelParamService.java + │ │ └── impl/ + │ │ └── CcdiModelParamServiceImpl.java + │ ├── mapper/ + │ │ └── CcdiModelParamMapper.java + │ └── domain/ + │ ├── CcdiModelParam.java + │ ├── dto/ + │ │ ├── ModelParamQueryDTO.java + │ │ └── ModelParamSaveDTO.java + │ └── vo/ + │ ├── ModelParamVO.java + │ └── ModelListVO.java + └── resources/ + └── mapper/ccdi/project/ + └── CcdiModelParamMapper.xml +``` + +### 5.2 核心接口 + +| 接口路径 | 方法 | 说明 | +|----------------------------|------|---------------| +| /ccdi/modelParam/modelList | GET | 查询模型列表 | +| /ccdi/modelParam/list | GET | 查询指定模型的参数列表 | +| /ccdi/modelParam/save | POST | 保存参数配置(只更新阈值) | + +### 5.3 安全保障 + +**三层防护确保只能修改阈值:** + +1. **Mapper XML 层** + ```xml + + update ccdi_model_param + set param_value = #{item.paramValue}, + update_by = #{item.updateBy}, + update_time = sysdate() + where id = #{item.id} + + ``` + +2. **Service 层** + ```java + // 只设置需要更新的字段 + updateParam.setParamValue(item.getParamValue()); + updateParam.setUpdateBy(username); + updateParam.setUpdateTime(now); + // 其他字段不设置 + ``` + +3. **前端层** + ```vue + + + + + ``` + +--- + +## 6. 前端设计 + +### 6.1 页面布局 + +``` +┌─────────────────────────────────────┐ +│ 模型参数管理 ← 返回项目管理 │ +├─────────────────────────────────────┤ +│ 模型名称: [下拉选择] [查询] │ +├─────────────────────────────────────┤ +│ 阈值参数配置 │ +│ ┌─────┬──────┬────────┬────┐ │ +│ │监测项│ 描述 │阈值设置 │单位│ │ +│ ├─────┼──────┼────────┼────┤ │ +│ │单笔 │单笔超│[输入框] │ 元 │ │ +│ │交易额│该金额│ │ │ │ +│ └─────┴──────┴────────┴────┘ │ +├─────────────────────────────────────┤ +│ [保存配置] │ +└─────────────────────────────────────┘ +``` + +### 6.2 交互流程 + +1. 用户选择模型 → 点击"查询" +2. 系统加载该模型的参数列表 +3. 用户修改阈值(只有这一列可编辑) +4. 用户点击"保存配置" +5. 系统提交修改的参数值 +6. 保存成功后显示提示 + +### 6.3 用户体验优化 + +- 修改跟踪:只提交变更的参数 +- 防重复提交:保存中禁用按钮 +- 成功提示:保存成功后清空修改标记 + +--- + +## 7. 实施计划 + +本功能拆分为以下3个子任务,每个子任务有独立的开发计划: + +1. **数据库设计与后端实体类创建** - 参见 `01-数据库设计与后端实体类创建.md` +2. **后端业务逻辑开发** - 参见 `02-后端业务逻辑开发.md` +3. **后端功能测试** - 参见 `03-后端功能测试.md` +4. **前端代码开发** - 参见 `04-前端代码开发.md` + +--- + +## 8. 风险与应对 + +| 风险 | 影响 | 应对措施 | +|-----------|----|---------------------| +| 参数值格式不统一 | 中 | 前端验证输入格式,后端也做校验 | +| 并发修改冲突 | 低 | 使用乐观锁或最后修改覆盖策略 | +| 新增模型需要改代码 | 低 | 符合设计预期,通过数据库脚本和代码发布 | + +--- + +## 9. 未来扩展 + +### 9.1 项目级参数配置 + +通过 `project_id` 字段预留了扩展能力: + +- `project_id = 0`: 系统默认参数 +- `project_id > 0`: 具体项目的自定义参数 + +**扩展步骤:** + +1. 添加项目管理界面 +2. 允许用户为具体项目复制默认参数 +3. 修改参数时指定 `project_id` + +### 9.2 参数修改历史 + +如需添加审计功能: + +1. 创建 `ccdi_model_param_history` 表 +2. 在更新参数前先插入历史记录 +3. 提供历史查询界面 + +--- + +## 10. 附录 + +### 10.1 参考文档 + +- 若依框架官方文档 +- 项目 CLAUDE.md 规范文档 +- 需求截图(见 doc/参数配置功能/ 目录) + +### 10.2 术语说明 + +| 术语 | 说明 | +|------------|-------------------------| +| 模型 | 风险监测模型,如大额交易模型、可疑兼职模型等 | +| 参数 | 模型的阈值配置项,如单笔交易额、累计交易额等 | +| 阈值 | 参数的具体数值,是唯一可修改的字段 | +| project_id | 项目ID,用于区分系统默认参数和项目自定义参数 | + +--- + +**文档版本:** v1.0 +**创建日期:** 2026-02-26 +**创建人:** Claude Code diff --git a/ruoyi-ui/src/views/ccdi/modelParam/index.vue b/ruoyi-ui/src/views/ccdi/modelParam/index.vue index 142d4ac..8ddc338 100644 --- a/ruoyi-ui/src/views/ccdi/modelParam/index.vue +++ b/ruoyi-ui/src/views/ccdi/modelParam/index.vue @@ -3,9 +3,6 @@
模型参数管理 - - 返回项目管理 -
@@ -58,7 +55,7 @@