参数配置
This commit is contained in:
450
doc/参数配置功能/01-数据库设计与后端实体类创建.md
Normal file
450
doc/参数配置功能/01-数据库设计与后端实体类创建.md
Normal file
@@ -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
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>ccdi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ccdi-project</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<!-- 通用工具 -->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
```
|
||||
|
||||
#### 1.3 修改根 pom.xml
|
||||
|
||||
**文件路径:** `pom.xml` (项目根目录)
|
||||
|
||||
在 `<modules>` 标签中添加:
|
||||
|
||||
```xml
|
||||
<modules>
|
||||
...
|
||||
<module>ccdi-project</module>
|
||||
</modules>
|
||||
```
|
||||
|
||||
#### 1.4 修改 ruoyi-admin/pom.xml
|
||||
|
||||
**文件路径:** `ruoyi-admin/pom.xml`
|
||||
|
||||
在 `<dependencies>` 标签中添加:
|
||||
|
||||
```xml
|
||||
<!-- 项目管理模块 -->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ccdi-project</artifactId>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 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<ParamItem> 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**
|
||||
420
doc/参数配置功能/02-后端业务逻辑开发.md
Normal file
420
doc/参数配置功能/02-后端业务逻辑开发.md
Normal file
@@ -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<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);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 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
|
||||
<?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 字段 -->
|
||||
<update id="batchUpdateParamValues">
|
||||
<foreach collection="list" item="item" separator=";">
|
||||
update ccdi_model_param
|
||||
set param_value = #{item.paramValue},
|
||||
update_by = #{item.updateBy},
|
||||
update_time = sysdate()
|
||||
where id = #{item.id}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 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<ModelListVO> selectModelList(Long projectId);
|
||||
|
||||
/**
|
||||
* 查询模型参数列表
|
||||
*
|
||||
* @param queryDTO 查询条件
|
||||
* @return 参数列表
|
||||
*/
|
||||
List<ModelParamVO> 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<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;
|
||||
}
|
||||
|
||||
String username = SecurityUtils.getUsername();
|
||||
Date now = new Date();
|
||||
|
||||
// 查询现有参数
|
||||
List<CcdiModelParam> existingParams = modelParamMapper.selectByProjectAndModel(
|
||||
projectId,
|
||||
saveDTO.getModelCode()
|
||||
);
|
||||
|
||||
if (existingParams.isEmpty()) {
|
||||
throw new ServiceException("未找到模型参数配置");
|
||||
}
|
||||
|
||||
// 准备更新列表 - 只更新 param_value 字段
|
||||
List<CcdiModelParam> 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<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("保存成功");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 验证清单
|
||||
|
||||
完成以下验证后,本任务才算完成:
|
||||
|
||||
- [ ] 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**
|
||||
353
doc/参数配置功能/03-后端功能测试.md
Normal file
353
doc/参数配置功能/03-后端功能测试.md
Normal file
@@ -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**
|
||||
549
doc/参数配置功能/04-前端代码开发.md
Normal file
549
doc/参数配置功能/04-前端代码开发.md
Normal file
@@ -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
|
||||
<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>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 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
|
||||
<el-input
|
||||
v-model.number="row.paramValue"
|
||||
type="number"
|
||||
placeholder="请输入阈值"
|
||||
@input="markAsModified(row)"
|
||||
/>
|
||||
```
|
||||
|
||||
### 2. 批量修改
|
||||
|
||||
添加"批量修改"功能,一次性修改多个模型的参数。
|
||||
|
||||
### 3. 修改历史记录
|
||||
|
||||
显示参数的修改历史,包括修改时间、修改人、修改前后的值。
|
||||
|
||||
---
|
||||
|
||||
## 下一步
|
||||
|
||||
完成本任务后,整个模型参数配置功能开发完成!
|
||||
|
||||
**总结:**
|
||||
|
||||
- ✅ 后端实体类创建完成
|
||||
- ✅ 后端业务逻辑开发完成
|
||||
- ✅ 后端功能测试通过
|
||||
- ✅ 前端代码开发完成
|
||||
|
||||
**功能已上线,可以进行功能验收。**
|
||||
348
doc/参数配置功能/设计文档.md
Normal file
348
doc/参数配置功能/设计文档.md
Normal file
@@ -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 id="batchUpdateParamValues">
|
||||
update ccdi_model_param
|
||||
set param_value = #{item.paramValue}, <!-- 只更新这个字段 -->
|
||||
update_by = #{item.updateBy},
|
||||
update_time = sysdate()
|
||||
where id = #{item.id}
|
||||
</update>
|
||||
```
|
||||
|
||||
2. **Service 层**
|
||||
```java
|
||||
// 只设置需要更新的字段
|
||||
updateParam.setParamValue(item.getParamValue());
|
||||
updateParam.setUpdateBy(username);
|
||||
updateParam.setUpdateTime(now);
|
||||
// 其他字段不设置
|
||||
```
|
||||
|
||||
3. **前端层**
|
||||
```vue
|
||||
<!-- 表格只有"阈值设置"列使用 el-input -->
|
||||
<el-table-column label="阈值设置" width="200">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.paramValue" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
Reference in New Issue
Block a user