参数配置
This commit is contained in:
168
CLAUDE.md
168
CLAUDE.md
@@ -2,6 +2,29 @@
|
|||||||
|
|
||||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## 快速参考
|
||||||
|
|
||||||
|
**启动项目:**
|
||||||
|
- 后端: `mvn spring-boot:run` 或运行 `ry.bat`
|
||||||
|
- 前端: `cd ruoyi-ui && npm run dev`
|
||||||
|
|
||||||
|
**访问地址:**
|
||||||
|
- 前端: http://localhost:80
|
||||||
|
- 后端: http://localhost:8080
|
||||||
|
- Swagger: http://localhost:8080/swagger-ui/index.html
|
||||||
|
- Druid 监控: http://localhost:8080/druid/ (ruoyi/123456)
|
||||||
|
|
||||||
|
**测试账号:**
|
||||||
|
- 用户名: `admin`
|
||||||
|
- 密码: `admin123`
|
||||||
|
|
||||||
|
**获取 Token:**
|
||||||
|
```bash
|
||||||
|
POST http://localhost:8080/login/test?username=admin&password=admin123
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 项目概述
|
## 项目概述
|
||||||
|
|
||||||
**纪检初核系统** - 基于 **若依管理系统 v3.9.1** 构建的企业级前后端分离管理系统,用于员工异常行为风险识别。
|
**纪检初核系统** - 基于 **若依管理系统 v3.9.1** 构建的企业级前后端分离管理系统,用于员工异常行为风险识别。
|
||||||
@@ -62,10 +85,23 @@ npm run preview
|
|||||||
### 数据库初始化
|
### 数据库初始化
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# 初始化若依框架基础表
|
||||||
mysql -u root -p < sql/ry_20250522.sql
|
mysql -u root -p < sql/ry_20250522.sql
|
||||||
|
|
||||||
|
# 初始化定时任务表
|
||||||
mysql -u root -p < sql/quartz.sql
|
mysql -u root -p < sql/quartz.sql
|
||||||
|
|
||||||
|
# 导入业务表(根据需要执行)
|
||||||
|
mysql -u root -p ccdi < sql/dpc_employee.sql
|
||||||
|
mysql -u root -p ccdi < sql/dpc_intermediary_blacklist.sql
|
||||||
|
# ... 其他业务表脚本
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**注意:**
|
||||||
|
- 业务表脚本文件名以 `ccdi_` 或 `dpc_` 开头
|
||||||
|
- 部分脚本包含菜单数据,需要按顺序执行
|
||||||
|
- 数据库需要先创建(数据库名: `ccdi`)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 模块架构
|
## 模块架构
|
||||||
@@ -95,8 +131,15 @@ ruoyi-admin (启动模块)
|
|||||||
├── ruoyi-quartz (定时任务)
|
├── ruoyi-quartz (定时任务)
|
||||||
├── ruoyi-generator (代码生成)
|
├── ruoyi-generator (代码生成)
|
||||||
└── ruoyi-info-collection (信息采集模块)
|
└── ruoyi-info-collection (信息采集模块)
|
||||||
|
└── 依赖 ruoyi-common
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**添加新业务模块:**
|
||||||
|
1. 在根目录 `pom.xml` 的 `<modules>` 中添加新模块
|
||||||
|
2. 在新模块的 `pom.xml` 中添加对 `ruoyi-common` 的依赖
|
||||||
|
3. 在 `ruoyi-admin/pom.xml` 中添加对新模块的依赖
|
||||||
|
4. 在新模块中按照分层规范创建 controller/service/mapper/domain 包
|
||||||
|
|
||||||
### ruoyi-info-collection 业务模块 (核心)
|
### ruoyi-info-collection 业务模块 (核心)
|
||||||
|
|
||||||
自定义业务模块,包含以下核心功能:
|
自定义业务模块,包含以下核心功能:
|
||||||
@@ -161,6 +204,14 @@ public class CcdiBaseStaff {
|
|||||||
- **Controller**: 所有接口添加 Swagger 注释,分页使用 MyBatis Plus Page
|
- **Controller**: 所有接口添加 Swagger 注释,分页使用 MyBatis Plus Page
|
||||||
- **Service**: 简单 CRUD 用 MyBatis Plus 方法,复杂操作在 XML 写 SQL
|
- **Service**: 简单 CRUD 用 MyBatis Plus 方法,复杂操作在 XML 写 SQL
|
||||||
- **DTO/VO**: 接口传参使用独立 DTO,返回使用独立 VO,不与 entity 混用
|
- **DTO/VO**: 接口传参使用独立 DTO,返回使用独立 VO,不与 entity 混用
|
||||||
|
- **Mapper**: 简单操作继承 BaseMapper,复杂操作在 XML 中定义
|
||||||
|
|
||||||
|
### 禁止事项
|
||||||
|
|
||||||
|
- **禁止使用全限定类名**: 必须使用 `import` 语句导入类,不要在代码中使用 `java.util.List` 这样的全限定名
|
||||||
|
- **禁止使用 `extends ServiceImpl<>`**: Service 接口和实现类分离定义
|
||||||
|
- **禁止 Entity 混用**: DTO、VO、Excel 类必须独立,不与 Entity 混用
|
||||||
|
- **禁止缺少 `@Resource`**: Service 注入必须使用 `@Resource` 注解
|
||||||
|
|
||||||
### API 响应格式
|
### API 响应格式
|
||||||
|
|
||||||
@@ -234,9 +285,20 @@ public AjaxResult getImportStatus(@PathVariable String taskId) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**导入流程:**
|
||||||
|
1. 前端上传 Excel 文件
|
||||||
|
2. 后端异步处理,返回 taskId
|
||||||
|
3. 前端轮询 `/import/status/{taskId}` 获取导入进度
|
||||||
|
4. 导入完成后,可获取成功/失败数据统计
|
||||||
|
|
||||||
|
**导入结果处理:**
|
||||||
|
- 只返回导入失败的数据(含失败原因)
|
||||||
|
- 成功数据不返回,减少响应体积
|
||||||
|
- 支持批量插入,提高性能
|
||||||
|
|
||||||
### EasyExcel 字典下拉框
|
### EasyExcel 字典下拉框
|
||||||
|
|
||||||
导入模板支持字典下拉框配置,提升数据录入准确性。
|
导入模板支持字典下拉框配置,提升数据录入准确性。使用 `DictDropdownWriteHandler` 实现。
|
||||||
|
|
||||||
### 权限控制
|
### 权限控制
|
||||||
|
|
||||||
@@ -272,6 +334,24 @@ POST /login/test?username=admin&password=admin123
|
|||||||
- 生成可执行的测试脚本进行验证
|
- 生成可执行的测试脚本进行验证
|
||||||
- 测试完成后保存接口输出并生成测试用例报告
|
- 测试完成后保存接口输出并生成测试用例报告
|
||||||
|
|
||||||
|
### 开发调试技巧
|
||||||
|
|
||||||
|
**使用 Swagger 测试接口:**
|
||||||
|
1. 访问 `/swagger-ui/index.html`
|
||||||
|
2. 点击接口展开详情
|
||||||
|
3. 点击 "Try it out" 进行测试
|
||||||
|
4. 填写参数后点击 "Execute" 执行
|
||||||
|
|
||||||
|
**查看 SQL 执行日志:**
|
||||||
|
- 在 `application.yml` 中设置日志级别: `com.ruoyi: debug`
|
||||||
|
- 使用 Druid 监控台查看慢 SQL
|
||||||
|
|
||||||
|
**前端代理配置:**
|
||||||
|
前端开发服务器通过代理转发请求到后端:
|
||||||
|
- 前端地址: `http://localhost:80`
|
||||||
|
- 后端地址: `http://localhost:8080`
|
||||||
|
- 代理配置文件: `ruoyi-ui/vue.config.js`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 配置说明
|
## 配置说明
|
||||||
@@ -293,6 +373,30 @@ POST /login/test?username=admin&password=admin123
|
|||||||
| 数据库连接 | `application-dev.yml` |
|
| 数据库连接 | `application-dev.yml` |
|
||||||
| Redis 配置 | `application-dev.yml` |
|
| Redis 配置 | `application-dev.yml` |
|
||||||
|
|
||||||
|
### 数据源配置
|
||||||
|
|
||||||
|
项目使用 Druid 连接池,支持主从分离(默认关闭从库):
|
||||||
|
|
||||||
|
- **数据库连接**: `jdbc:mysql://host:3306/ccdi`
|
||||||
|
- **初始连接数**: 5
|
||||||
|
- **最小连接数**: 10
|
||||||
|
- **最大连接数**: 20
|
||||||
|
- **慢 SQL 记录**: 超过 1000ms 的 SQL 会被记录
|
||||||
|
|
||||||
|
### Redis 配置
|
||||||
|
|
||||||
|
- **默认端口**: 6379
|
||||||
|
- **数据库索引**: 0
|
||||||
|
- **连接超时**: 10s
|
||||||
|
|
||||||
|
### Druid 监控台
|
||||||
|
|
||||||
|
访问地址: `http://localhost:8080/druid/`
|
||||||
|
- 用户名: `ruoyi`
|
||||||
|
- 密码: `123456`
|
||||||
|
|
||||||
|
用于监控 SQL 执行情况、连接池状态等。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 重要文件路径
|
## 重要文件路径
|
||||||
@@ -360,3 +464,65 @@ doc/
|
|||||||
## 沟通规范
|
## 沟通规范
|
||||||
|
|
||||||
- 永远使用简体中文进行思考和对话
|
- 永远使用简体中文进行思考和对话
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 常见问题排查
|
||||||
|
|
||||||
|
### 数据库连接失败
|
||||||
|
|
||||||
|
**检查项:**
|
||||||
|
1. 确认 MySQL 服务已启动
|
||||||
|
2. 检查 `application-dev.yml` 中的数据库连接配置
|
||||||
|
3. 确认数据库用户名和密码正确
|
||||||
|
4. 检查数据库是否已创建(数据库名: `ccdi`)
|
||||||
|
|
||||||
|
### Redis 连接失败
|
||||||
|
|
||||||
|
**检查项:**
|
||||||
|
1. 确认 Redis 服务已启动
|
||||||
|
2. 检查 `application-dev.yml` 中的 Redis 配置
|
||||||
|
3. 如果 Redis 不需要密码,将 `password` 配置注释掉
|
||||||
|
|
||||||
|
### 前端无法访问后端接口
|
||||||
|
|
||||||
|
**检查项:**
|
||||||
|
1. 确认后端已启动(端口 8080)
|
||||||
|
2. 检查前端代理配置(`ruoyi-ui/vue.config.js`)
|
||||||
|
3. 确认后端接口路径正确(查看 Controller 的 `@RequestMapping`)
|
||||||
|
|
||||||
|
### 导入功能无响应
|
||||||
|
|
||||||
|
**检查项:**
|
||||||
|
1. 检查文件大小是否超过限制(默认 10MB)
|
||||||
|
2. 查看后端日志是否有异常
|
||||||
|
3. 确认 Excel 模板格式正确
|
||||||
|
4. 检查必填字段是否为空
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## MyBatis Plus 分页使用
|
||||||
|
|
||||||
|
```java
|
||||||
|
// Controller 层
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo list(QueryDTO queryDTO) {
|
||||||
|
PageDomain pageDomain = TableSupport.buildPageRequest();
|
||||||
|
Page<VO> page = new Page<>(pageDomain.getPageNum(), pageDomain.getPageSize());
|
||||||
|
Page<VO> result = service.selectPage(page, queryDTO);
|
||||||
|
return getDataTable(result.getRecords(), result.getTotal());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Service 层
|
||||||
|
Page<VO> selectPage(Page<VO> page, QueryDTO queryDTO);
|
||||||
|
|
||||||
|
// Mapper 层 (使用 XML)
|
||||||
|
<select id="selectPage" resultType="VO">
|
||||||
|
SELECT * FROM table_name
|
||||||
|
<where>
|
||||||
|
<if test="queryDTO.name != null">
|
||||||
|
AND name LIKE CONCAT('%', #{queryDTO.name}, '%')
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
</select>
|
||||||
|
```
|
||||||
|
|||||||
BIN
doc/参数配置功能/ScreenShot_2026-02-25_162807_126.png
Normal file
BIN
doc/参数配置功能/ScreenShot_2026-02-25_162807_126.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
BIN
doc/参数配置功能/ScreenShot_2026-02-25_162819_927.png
Normal file
BIN
doc/参数配置功能/ScreenShot_2026-02-25_162819_927.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
BIN
doc/参数配置功能/ScreenShot_2026-02-25_162831_473.png
Normal file
BIN
doc/参数配置功能/ScreenShot_2026-02-25_162831_473.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
0
doc/参数配置功能/task.md
Normal file
0
doc/参数配置功能/task.md
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,962 +0,0 @@
|
|||||||
# 信贷客户家庭关系维护功能实施计划
|
|
||||||
|
|
||||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
||||||
|
|
||||||
**目标:** 开发信贷客户家庭关系维护功能,实现对信贷客户家庭成员信息的完整CRUD操作
|
|
||||||
|
|
||||||
**架构:** 完全复用员工亲属关系维护功能的实现逻辑,创建独立模块 `CustFamilyRelation`,新建独立表 `ccdi_cust_fmy_relation`
|
|
||||||
|
|
||||||
**技术栈:** Spring Boot 3.5.8 + MyBatis Plus 3.5.10 + Vue 2.6.12 + Element UI 2.15.14 + EasyExcel + Redis
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 前置准备
|
|
||||||
|
|
||||||
### Task 0: 创建数据库表
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `sql/ccdi_cust_fmy_relation.sql`
|
|
||||||
|
|
||||||
**Step 1: 创建建表SQL文件**
|
|
||||||
|
|
||||||
```sql
|
|
||||||
-- 信贷客户家庭关系表
|
|
||||||
CREATE TABLE `ccdi_cust_fmy_relation` (
|
|
||||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
|
||||||
`person_id` VARCHAR(50) NOT NULL COMMENT '信贷客户身份证号',
|
|
||||||
`relation_type` VARCHAR(50) NOT NULL COMMENT '关系类型',
|
|
||||||
`relation_name` VARCHAR(100) NOT NULL COMMENT '关系人姓名',
|
|
||||||
`gender` CHAR(1) DEFAULT NULL COMMENT '性别:M-男,F-女,O-其他',
|
|
||||||
`birth_date` DATE DEFAULT NULL COMMENT '关系人出生日期',
|
|
||||||
`relation_cert_type` VARCHAR(50) NOT NULL COMMENT '证件类型',
|
|
||||||
`relation_cert_no` VARCHAR(50) NOT NULL COMMENT '证件号码',
|
|
||||||
`mobile_phone1` VARCHAR(20) DEFAULT NULL COMMENT '手机号码1',
|
|
||||||
`mobile_phone2` VARCHAR(20) DEFAULT NULL COMMENT '手机号码2',
|
|
||||||
`wechat_no1` VARCHAR(50) DEFAULT NULL COMMENT '微信名称1',
|
|
||||||
`wechat_no2` VARCHAR(50) DEFAULT NULL COMMENT '微信名称2',
|
|
||||||
`wechat_no3` VARCHAR(50) DEFAULT NULL COMMENT '微信名称3',
|
|
||||||
`contact_address` VARCHAR(500) DEFAULT NULL COMMENT '详细联系地址',
|
|
||||||
`relation_desc` VARCHAR(500) DEFAULT NULL COMMENT '关系详细描述',
|
|
||||||
`status` INT NOT NULL DEFAULT 1 COMMENT '状态:0-无效,1-有效',
|
|
||||||
`effective_date` DATETIME DEFAULT NULL COMMENT '关系生效日期',
|
|
||||||
`invalid_date` DATETIME DEFAULT NULL COMMENT '关系失效日期',
|
|
||||||
`remark` TEXT COMMENT '备注信息',
|
|
||||||
`data_source` VARCHAR(50) DEFAULT NULL COMMENT '数据来源:MANUAL-手动录入,IMPORT-批量导入',
|
|
||||||
`is_emp_family` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否是员工的家庭关系:0-否',
|
|
||||||
`is_cust_family` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否是信贷客户的家庭关系:1-是',
|
|
||||||
`created_by` VARCHAR(50) NOT NULL COMMENT '记录创建人',
|
|
||||||
`updated_by` VARCHAR(50) DEFAULT NULL COMMENT '记录更新人',
|
|
||||||
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '记录创建时间',
|
|
||||||
`update_time` DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '记录更新时间',
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `idx_person_id` (`person_id`),
|
|
||||||
KEY `idx_relation_cert_no` (`relation_cert_no`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='信贷客户家庭关系表';
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 2: 执行SQL创建表**
|
|
||||||
|
|
||||||
Run: 连接数据库并执行 `sql/ccdi_cust_fmy_relation.sql`
|
|
||||||
Expected: 表创建成功
|
|
||||||
|
|
||||||
**Step 3: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add sql/ccdi_cust_fmy_relation.sql
|
|
||||||
git commit -m "feat: 创建信贷客户家庭关系表"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 后端开发
|
|
||||||
|
|
||||||
### Task 1: 创建实体类
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/CcdiCustFmyRelation.java`
|
|
||||||
- Reference: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/CcdiStaffFmyRelation.java:1-108`
|
|
||||||
|
|
||||||
**Step 1: 创建实体类**
|
|
||||||
|
|
||||||
复制 `CcdiStaffFmyRelation.java`,修改以下内容:
|
|
||||||
- 类名: `CcdiCustFmyRelation`
|
|
||||||
- 注释: `信贷客户家庭关系对象 ccdi_cust_fmy_relation`
|
|
||||||
- 表名: `@TableName("ccdi_cust_fmy_relation")`
|
|
||||||
- JavaDoc: 全部替换"员工"为"信贷客户"
|
|
||||||
|
|
||||||
```java
|
|
||||||
package com.ruoyi.ccdi.domain;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.io.Serial;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 信贷客户家庭关系对象 ccdi_cust_fmy_relation
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-02-11
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@TableName("ccdi_cust_fmy_relation")
|
|
||||||
public class CcdiCustFmyRelation implements Serializable {
|
|
||||||
|
|
||||||
@Serial
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
/** 主键ID */
|
|
||||||
@TableId(type = IdType.AUTO)
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
/** 信贷客户身份证号 */
|
|
||||||
private String personId;
|
|
||||||
|
|
||||||
/** 关系类型 */
|
|
||||||
private String relationType;
|
|
||||||
|
|
||||||
/** 关系人姓名 */
|
|
||||||
private String relationName;
|
|
||||||
|
|
||||||
/** 性别:M-男,F-女,O-其他 */
|
|
||||||
private String gender;
|
|
||||||
|
|
||||||
/** 出生日期 */
|
|
||||||
private Date birthDate;
|
|
||||||
|
|
||||||
/** 关系人证件类型 */
|
|
||||||
private String relationCertType;
|
|
||||||
|
|
||||||
/** 关系人证件号码 */
|
|
||||||
private String relationCertNo;
|
|
||||||
|
|
||||||
/** 手机号码1 */
|
|
||||||
private String mobilePhone1;
|
|
||||||
|
|
||||||
/** 手机号码2 */
|
|
||||||
private String mobilePhone2;
|
|
||||||
|
|
||||||
/** 微信名称1 */
|
|
||||||
private String wechatNo1;
|
|
||||||
|
|
||||||
/** 微信名称2 */
|
|
||||||
private String wechatNo2;
|
|
||||||
|
|
||||||
/** 微信名称3 */
|
|
||||||
private String wechatNo3;
|
|
||||||
|
|
||||||
/** 详细联系地址 */
|
|
||||||
private String contactAddress;
|
|
||||||
|
|
||||||
/** 关系详细描述 */
|
|
||||||
private String relationDesc;
|
|
||||||
|
|
||||||
/** 状态:0-无效,1-有效 */
|
|
||||||
private Integer status;
|
|
||||||
|
|
||||||
/** 生效日期 */
|
|
||||||
private Date effectiveDate;
|
|
||||||
|
|
||||||
/** 失效日期 */
|
|
||||||
private Date invalidDate;
|
|
||||||
|
|
||||||
/** 备注 */
|
|
||||||
private String remark;
|
|
||||||
|
|
||||||
/** 数据来源:MANUAL-手工录入,IMPORT-导入 */
|
|
||||||
private String dataSource;
|
|
||||||
|
|
||||||
/** 是否是员工亲属:0-否 */
|
|
||||||
private Boolean isEmpFamily;
|
|
||||||
|
|
||||||
/** 是否是客户亲属:1-是 */
|
|
||||||
private Boolean isCustFamily;
|
|
||||||
|
|
||||||
/** 创建时间 */
|
|
||||||
@TableField(fill = FieldFill.INSERT)
|
|
||||||
private Date createTime;
|
|
||||||
|
|
||||||
/** 更新时间 */
|
|
||||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
|
||||||
private Date updateTime;
|
|
||||||
|
|
||||||
/** 创建人 */
|
|
||||||
@TableField(fill = FieldFill.INSERT)
|
|
||||||
private String createdBy;
|
|
||||||
|
|
||||||
/** 更新人 */
|
|
||||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
|
||||||
private String updatedBy;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 2: Compile**
|
|
||||||
|
|
||||||
Run: `mvn compile -pl ruoyi-ccdi`
|
|
||||||
Expected: BUILD SUCCESS
|
|
||||||
|
|
||||||
**Step 3: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/CcdiCustFmyRelation.java
|
|
||||||
git commit -m "feat: 添加信贷客户家庭关系实体类"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 2: 创建DTO类
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiCustFmyRelationAddDTO.java`
|
|
||||||
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiCustFmyRelationEditDTO.java`
|
|
||||||
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiCustFmyRelationQueryDTO.java`
|
|
||||||
- Reference: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiStaffFmyRelationAddDTO.java`
|
|
||||||
|
|
||||||
**Step 1: 创建AddDTO**
|
|
||||||
|
|
||||||
复制 `CcdiStaffFmyRelationAddDTO.java`,修改:
|
|
||||||
- 类名: `CcdiCustFmyRelationAddDTO`
|
|
||||||
- 注释中"员工" → "信贷客户"
|
|
||||||
- personId字段注释: `@Schema(description = "信贷客户身份证号")`
|
|
||||||
- 验证消息: "员工身份证号" → "信贷客户身份证号"
|
|
||||||
|
|
||||||
**Step 2: 创建EditDTO**
|
|
||||||
|
|
||||||
复制 `CcdiStaffFmyRelationEditDTO.java`,修改:
|
|
||||||
- 类名: `CcdiCustFmyRelationEditDTO`
|
|
||||||
- 注释中"员工" → "信贷客户"
|
|
||||||
- 添加 `id` 字段和 `@NotNull` 验证
|
|
||||||
|
|
||||||
**Step 3: 创建QueryDTO(简化版)**
|
|
||||||
|
|
||||||
```java
|
|
||||||
package com.ruoyi.ccdi.domain.dto;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.io.Serial;
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 信贷客户家庭关系查询DTO
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
* @date 2026-02-11
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Schema(description = "信贷客户家庭关系查询")
|
|
||||||
public class CcdiCustFmyRelationQueryDTO implements Serializable {
|
|
||||||
|
|
||||||
@Serial
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
/** 信贷客户身份证号 */
|
|
||||||
@Schema(description = "信贷客户身份证号")
|
|
||||||
private String personId;
|
|
||||||
|
|
||||||
/** 关系类型 */
|
|
||||||
@Schema(description = "关系类型")
|
|
||||||
private String relationType;
|
|
||||||
|
|
||||||
/** 关系人姓名 */
|
|
||||||
@Schema(description = "关系人姓名")
|
|
||||||
private String relationName;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 4: Compile**
|
|
||||||
|
|
||||||
Run: `mvn compile -pl ruoyi-ccdi`
|
|
||||||
Expected: BUILD SUCCESS
|
|
||||||
|
|
||||||
**Step 5: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/
|
|
||||||
git commit -m "feat: 添加信贷客户家庭关系DTO类"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 3: 创建VO类
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/vo/CcdiCustFmyRelationVO.java`
|
|
||||||
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/vo/CustFmyRelationImportFailureVO.java`
|
|
||||||
- Reference: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/vo/CcdiStaffFmyRelationVO.java`
|
|
||||||
|
|
||||||
**Step 1: 创建主VO**
|
|
||||||
|
|
||||||
复制 `CcdiStaffFmyRelationVO.java`,修改:
|
|
||||||
- 类名: `CcdiCustFmyRelationVO`
|
|
||||||
- 移除 `personName` 字段(不关联其他表)
|
|
||||||
- 注释中"员工" → "信贷客户"
|
|
||||||
|
|
||||||
**Step 2: 创建导入失败VO**
|
|
||||||
|
|
||||||
复制 `StaffFmyRelationImportFailureVO.java`,修改:
|
|
||||||
- 类名: `CustFmyRelationImportFailureVO`
|
|
||||||
- 注释中"员工" → "信贷客户"
|
|
||||||
|
|
||||||
**Step 3: Compile**
|
|
||||||
|
|
||||||
Run: `mvn compile -pl ruoyi-ccdi`
|
|
||||||
Expected: BUILD SUCCESS
|
|
||||||
|
|
||||||
**Step 4: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/vo/
|
|
||||||
git commit -m "feat: 添加信贷客户家庭关系VO类"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 4: 创建Excel类
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/excel/CcdiCustFmyRelationExcel.java`
|
|
||||||
- Reference: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/excel/CcdiStaffFmyRelationExcel.java`
|
|
||||||
|
|
||||||
**Step 1: 创建Excel类**
|
|
||||||
|
|
||||||
复制 `CcdiStaffFmyRelationExcel.java`,修改:
|
|
||||||
- 类名: `CcdiCustFmyRelationExcel`
|
|
||||||
- 注释: `信贷客户家庭关系Excel导入导出对象`
|
|
||||||
- personId字段: `@ExcelProperty(value = "信贷客户身份证号*", index = 0)`
|
|
||||||
- 其他保持不变
|
|
||||||
|
|
||||||
**Step 2: Compile**
|
|
||||||
|
|
||||||
Run: `mvn compile -pl ruoyi-ccdi`
|
|
||||||
Expected: BUILD SUCCESS
|
|
||||||
|
|
||||||
**Step 3: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/excel/CcdiCustFmyRelationExcel.java
|
|
||||||
git commit -m "feat: 添加信贷客户家庭关系Excel类"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 5: 创建Mapper接口
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/mapper/CcdiCustFmyRelationMapper.java`
|
|
||||||
- Reference: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/mapper/CcdiStaffFmyRelationMapper.java`
|
|
||||||
|
|
||||||
**Step 1: 创建Mapper接口**
|
|
||||||
|
|
||||||
复制 `CcdiStaffFmyRelationMapper.java`,修改:
|
|
||||||
- 包名和导入: 全部 `Staff` → `Cust`
|
|
||||||
- 类名: `CcdiCustFmyRelationMapper`
|
|
||||||
- 泛型: `CcdiCustFmyRelation`
|
|
||||||
- DTO: `CcdiCustFmyRelationQueryDTO`
|
|
||||||
- VO: `CcdiCustFmyRelationVO`
|
|
||||||
- 方法注释: "员工" → "信贷客户"
|
|
||||||
|
|
||||||
**Step 2: Compile**
|
|
||||||
|
|
||||||
Run: `mvn compile -pl ruoyi-ccdi`
|
|
||||||
Expected: BUILD SUCCESS
|
|
||||||
|
|
||||||
**Step 3: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/mapper/CcdiCustFmyRelationMapper.java
|
|
||||||
git commit -m "feat: 添加信贷客户家庭关系Mapper接口"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 6: 创建Mapper XML映射
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `ruoyi-ccdi/src/main/resources/mapper/ccdi/CcdiCustFmyRelationMapper.xml`
|
|
||||||
- Reference: `ruoyi-ccdi/src/main/resources/mapper/ccdi/CcdiStaffFmyRelationMapper.xml`
|
|
||||||
|
|
||||||
**Step 1: 创建XML映射文件**
|
|
||||||
|
|
||||||
复制 `CcdiStaffFmyRelationMapper.xml`,修改:
|
|
||||||
- namespace: `com.ruoyi.ccdi.mapper.CcdiCustFmyRelationMapper`
|
|
||||||
- resultMap: `CcdiCustFmyRelationVOResult`
|
|
||||||
- type: `com.ruoyi.ccdi.domain.vo.CcdiCustFmyRelationVO`
|
|
||||||
- 表名: `ccdi_cust_fmy_relation`
|
|
||||||
- **移除 LEFT JOIN**(不关联员工表)
|
|
||||||
- WHERE条件: `r.is_cust_family = 1`
|
|
||||||
- **移除 personName 相关字段**
|
|
||||||
|
|
||||||
```xml
|
|
||||||
<!-- 关键修改:移除LEFT JOIN和person_name -->
|
|
||||||
<select id="selectRelationPage" resultMap="CcdiCustFmyRelationVOResult">
|
|
||||||
SELECT
|
|
||||||
r.id, r.person_id, r.relation_type, r.relation_name,
|
|
||||||
r.gender, r.birth_date, r.relation_cert_type, r.relation_cert_no,
|
|
||||||
r.mobile_phone1, r.mobile_phone2, r.wechat_no1, r.wechat_no2, r.wechat_no3,
|
|
||||||
r.contact_address, r.relation_desc, r.effective_date, r.invalid_date,
|
|
||||||
r.status, r.remark, r.data_source, r.is_emp_family, r.is_cust_family,
|
|
||||||
r.created_by, r.create_time, r.updated_by, r.update_time
|
|
||||||
FROM ccdi_cust_fmy_relation r
|
|
||||||
<where>
|
|
||||||
r.is_cust_family = 1
|
|
||||||
<if test="query.personId != null and query.personId != ''">
|
|
||||||
AND r.person_id = #{query.personId}
|
|
||||||
</if>
|
|
||||||
<if test="query.relationType != null and query.relationType != ''">
|
|
||||||
AND r.relation_type = #{query.relationType}
|
|
||||||
</if>
|
|
||||||
<if test="query.relationName != null and query.relationName != ''">
|
|
||||||
AND r.relation_name LIKE CONCAT('%', #{query.relationName}, '%')
|
|
||||||
</if>
|
|
||||||
</where>
|
|
||||||
ORDER BY r.create_time DESC
|
|
||||||
</select>
|
|
||||||
```
|
|
||||||
|
|
||||||
- selectExistingRelations: `is_cust_family = 1`
|
|
||||||
|
|
||||||
**Step 2: Compile**
|
|
||||||
|
|
||||||
Run: `mvn compile -pl ruoyi-ccdi`
|
|
||||||
Expected: BUILD SUCCESS
|
|
||||||
|
|
||||||
**Step 3: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add ruoyi-ccdi/src/main/resources/mapper/ccdi/CcdiCustFmyRelationMapper.xml
|
|
||||||
git commit -m "feat: 添加信贷客户家庭关系Mapper XML映射"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 7: 创建Service接口
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/ICcdiCustFmyRelationService.java`
|
|
||||||
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/ICcdiCustFmyRelationImportService.java`
|
|
||||||
- Reference: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/ICcdiStaffFmyRelationService.java`
|
|
||||||
|
|
||||||
**Step 1: 创建主Service接口**
|
|
||||||
|
|
||||||
复制 `ICcdiStaffFmyRelationService.java`,修改:
|
|
||||||
- 接口名: `ICcdiCustFmyRelationService`
|
|
||||||
- 泛型: `CcdiCustFmyRelationVO`, `CcdiCustFmyRelationQueryDTO`, `CcdiCustFmyRelationAddDTO`, `CcdiCustFmyRelationEditDTO`, `CcdiCustFmyRelationExcel`
|
|
||||||
|
|
||||||
**Step 2: 创建导入Service接口**
|
|
||||||
|
|
||||||
复制 `ICcdiStaffFmyRelationImportService.java`,修改:
|
|
||||||
- 接口名: `ICcdiCustFmyRelationImportService`
|
|
||||||
- 泛型: `CcdiCustFmyRelationExcel`, `CustFmyRelationImportFailureVO`
|
|
||||||
|
|
||||||
**Step 3: Compile**
|
|
||||||
|
|
||||||
Run: `mvn compile -pl ruoyi-ccdi`
|
|
||||||
Expected: BUILD SUCCESS
|
|
||||||
|
|
||||||
**Step 4: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/
|
|
||||||
git commit -m "feat: 添加信贷客户家庭关系Service接口"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 8: 创建Service实现类
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiCustFmyRelationServiceImpl.java`
|
|
||||||
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiCustFmyRelationImportServiceImpl.java`
|
|
||||||
- Reference: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiStaffFmyRelationServiceImpl.java`
|
|
||||||
|
|
||||||
**Step 1: 创建主Service实现类**
|
|
||||||
|
|
||||||
复制 `CcdiStaffFmyRelationServiceImpl.java`,修改:
|
|
||||||
- 类名: `CcdiCustFmyRelationServiceImpl`
|
|
||||||
- Mapper注入: `CcdiCustFmyRelationMapper`
|
|
||||||
- ImportService注入: `ICcdiCustFmyRelationImportService`
|
|
||||||
- 泛型: `CcdiCustFmyRelationVO`, `CcdiCustFmyRelationQueryDTO` 等
|
|
||||||
- **关键修改**:
|
|
||||||
- `relation.setIsEmpFamily(false);`
|
|
||||||
- `relation.setIsCustFamily(true);`
|
|
||||||
- Redis Key: `import:custFmyRelation:`
|
|
||||||
|
|
||||||
**Step 2: 创建导入Service实现类**
|
|
||||||
|
|
||||||
复制 `CcdiStaffFmyRelationImportServiceImpl.java`,修改:
|
|
||||||
- 类名: `CcdiCustFmyRelationImportServiceImpl`
|
|
||||||
- Mapper注入: `CcdiCustFmyRelationMapper`
|
|
||||||
- 泛型: `CcdiCustFmyRelationExcel`, `CustFmyRelationImportFailureVO`
|
|
||||||
- Redis Key: `import:custFmyRelation:`
|
|
||||||
- 错误消息: "信贷客户身份证号"
|
|
||||||
|
|
||||||
**Step 3: Compile**
|
|
||||||
|
|
||||||
Run: `mvn compile -pl ruoyi-ccdi`
|
|
||||||
Expected: BUILD SUCCESS
|
|
||||||
|
|
||||||
**Step 4: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/
|
|
||||||
git commit -m "feat: 添加信贷客户家庭关系Service实现类"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 9: 创建Controller
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/controller/CcdiCustFmyRelationController.java`
|
|
||||||
- Reference: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/controller/CcdiStaffFmyRelationController.java`
|
|
||||||
|
|
||||||
**Step 1: 创建Controller**
|
|
||||||
|
|
||||||
复制 `CcdiStaffFmyRelationController.java`,修改:
|
|
||||||
- 类名: `CcdiCustFmyRelationController`
|
|
||||||
- Tag: `@Tag(name = "信贷客户家庭关系管理")`
|
|
||||||
- RequestMapping: `/ccdi/custFmyRelation`
|
|
||||||
- Service注入: `ICcdiCustFmyRelationService`, `ICcdiCustFmyRelationImportService`
|
|
||||||
- DTO/VO: 对应的 `CcdiCust...` 类型
|
|
||||||
- 权限标识: `ccdi:custFmyRelation:*`
|
|
||||||
- 注释: "员工" → "信贷客户"
|
|
||||||
|
|
||||||
**Step 2: Compile**
|
|
||||||
|
|
||||||
Run: `mvn compile -pl ruoyi-ccdi`
|
|
||||||
Expected: BUILD SUCCESS
|
|
||||||
|
|
||||||
**Step 3: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/controller/CcdiCustFmyRelationController.java
|
|
||||||
git commit -m "feat: 添加信贷客户家庭关系Controller"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 前端开发
|
|
||||||
|
|
||||||
### Task 10: 创建API接口文件
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `ruoyi-ui/src/api/ccdiCustFmyRelation.js`
|
|
||||||
- Reference: `ruoyi-ui/src/api/ccdiStaffFmyRelation.js`
|
|
||||||
|
|
||||||
**Step 1: 创建API文件**
|
|
||||||
|
|
||||||
复制 `ccdiStaffFmyRelation.js`,修改:
|
|
||||||
- url路径: `/ccdi/custFmyRelation`
|
|
||||||
- 移除 `getStaffList` 方法(不需要)
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// 查询信贷客户家庭关系列表
|
|
||||||
export function listRelation(query) {
|
|
||||||
return request({
|
|
||||||
url: '/ccdi/custFmyRelation/list',
|
|
||||||
method: 'get',
|
|
||||||
params: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询信贷客户家庭关系详细
|
|
||||||
export function getRelation(id) {
|
|
||||||
return request({
|
|
||||||
url: '/ccdi/custFmyRelation/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增信贷客户家庭关系
|
|
||||||
export function addRelation(data) {
|
|
||||||
return request({
|
|
||||||
url: '/ccdi/custFmyRelation',
|
|
||||||
method: 'post',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改信贷客户家庭关系
|
|
||||||
export function updateRelation(data) {
|
|
||||||
return request({
|
|
||||||
url: '/ccdi/custFmyRelation',
|
|
||||||
method: 'put',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除信贷客户家庭关系
|
|
||||||
export function delRelation(ids) {
|
|
||||||
return request({
|
|
||||||
url: '/ccdi/custFmyRelation/' + ids,
|
|
||||||
method: 'delete'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 导出信贷客户家庭关系
|
|
||||||
export function exportRelation(query) {
|
|
||||||
return request({
|
|
||||||
url: '/ccdi/custFmyRelation/export',
|
|
||||||
method: 'post',
|
|
||||||
params: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 下载导入模板
|
|
||||||
export function importTemplate() {
|
|
||||||
return request({
|
|
||||||
url: '/ccdi/custFmyRelation/importTemplate',
|
|
||||||
method: 'post'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 导入信贷客户家庭关系
|
|
||||||
export function importData(file) {
|
|
||||||
const formData = new FormData()
|
|
||||||
formData.append('file', file)
|
|
||||||
return request({
|
|
||||||
url: '/ccdi/custFmyRelation/importData',
|
|
||||||
method: 'post',
|
|
||||||
data: formData
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询导入状态
|
|
||||||
export function getImportStatus(taskId) {
|
|
||||||
return request({
|
|
||||||
url: '/ccdi/custFmyRelation/importStatus/' + taskId,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询导入失败记录
|
|
||||||
export function getImportFailures(taskId, pageNum, pageSize) {
|
|
||||||
return request({
|
|
||||||
url: '/ccdi/custFmyRelation/importFailures/' + taskId,
|
|
||||||
method: 'get',
|
|
||||||
params: { pageNum, pageSize }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 2: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add ruoyi-ui/src/api/ccdiCustFmyRelation.js
|
|
||||||
git commit -m "feat: 添加信贷客户家庭关系API接口"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 11: 创建主页面组件
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `ruoyi-ui/src/views/ccdiCustFmyRelation/index.vue`
|
|
||||||
- Reference: `ruoyi-ui/src/views/ccdiStaffFmyRelation/index.vue`
|
|
||||||
|
|
||||||
**Step 1: 创建页面组件**
|
|
||||||
|
|
||||||
复制 `ccdiStaffFmyRelation/index.vue`,修改:
|
|
||||||
|
|
||||||
1. **查询条件**(简化版):
|
|
||||||
```vue
|
|
||||||
<!-- 移除员工姓名输入框,只保留personId、relationType、relationName -->
|
|
||||||
<el-form-item label="信贷客户身份证号" prop="personId">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.personId"
|
|
||||||
placeholder="请输入信贷客户身份证号"
|
|
||||||
clearable
|
|
||||||
style="width: 240px"
|
|
||||||
@keyup.enter.native="handleQuery"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="关系类型" prop="relationType">
|
|
||||||
<el-select v-model="queryParams.relationType" placeholder="请选择关系类型" clearable style="width: 240px">
|
|
||||||
<el-option
|
|
||||||
v-for="dict in dict.type.ccdi_relation_type"
|
|
||||||
:key="dict.value"
|
|
||||||
:label="dict.label"
|
|
||||||
:value="dict.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="关系人姓名" prop="relationName">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.relationName"
|
|
||||||
placeholder="请输入关系人姓名"
|
|
||||||
clearable
|
|
||||||
style="width: 240px"
|
|
||||||
@keyup.enter.native="handleQuery"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<!-- 移除状态下拉框 -->
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **列表列**(移除personName):
|
|
||||||
```vue
|
|
||||||
<el-table-column label="信贷客户身份证号" align="center" prop="personId" width="180"/>
|
|
||||||
<!-- 移除员工姓名列 -->
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **表单**(使用普通输入框):
|
|
||||||
```vue
|
|
||||||
<!-- 信贷客户身份证号改为普通输入框,不使用远程搜索 -->
|
|
||||||
<el-form-item label="信贷客户身份证号" prop="personId">
|
|
||||||
<el-input
|
|
||||||
v-model="form.personId"
|
|
||||||
placeholder="请输入信贷客户身份证号"
|
|
||||||
:disabled="!isAdd"
|
|
||||||
maxlength="18"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **权限标识**:全部 `staffFmyRelation` → `custFmyRelation`
|
|
||||||
|
|
||||||
5. **导入localStorage**:
|
|
||||||
```javascript
|
|
||||||
const STORAGE_KEY = 'cust_fmy_relation_import_last_task';
|
|
||||||
```
|
|
||||||
|
|
||||||
6. **字典类型**:
|
|
||||||
```vue
|
|
||||||
<dict-tag :options="dict.type.ccdi_relation_type" :value="scope.row.relationType"/>
|
|
||||||
<dict-tag :options="dict.type.ccdi_indiv_gender" :value="scope.row.gender"/>
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 2: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add ruoyi-ui/src/views/ccdiCustFmyRelation/index.vue
|
|
||||||
git commit -m "feat: 添加信贷客户家庭关系页面组件"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 系统配置
|
|
||||||
|
|
||||||
### Task 12: 创建菜单权限SQL
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `sql/ccdi_cust_fmy_relation_menu.sql`
|
|
||||||
- Reference: `sql/ccdi_staff_fmy_relation_menu.sql`
|
|
||||||
|
|
||||||
**Step 1: 创建菜单SQL**
|
|
||||||
|
|
||||||
```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, update_by, update_time, remark)
|
|
||||||
VALUES
|
|
||||||
('信贷客户家庭关系', (SELECT menu_id FROM sys_menu WHERE menu_name = '信息维护' LIMIT 1), 5, 'custFmyRelation', 'ccdiCustFmyRelation/index', 1, 0, 'C', '0', '0', 'ccdi:custFmyRelation:list', 'peoples', 'admin', NOW(), '', NULL, '信贷客户家庭关系菜单');
|
|
||||||
|
|
||||||
-- 获取刚插入的菜单ID
|
|
||||||
SET @parent_id = LAST_INSERT_ID();
|
|
||||||
|
|
||||||
-- 添加按钮权限
|
|
||||||
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, update_by, update_time, remark) VALUES
|
|
||||||
('信贷客户家庭关系查询', @parent_id, 1, '#', '', 1, 0, 'F', '0', '0', 'ccdi:custFmyRelation:query', '#', 'admin', NOW(), '', NULL, ''),
|
|
||||||
('信贷客户家庭关系新增', @parent_id, 2, '#', '', 1, 0, 'F', '0', '0', 'ccdi:custFmyRelation:add', '#', 'admin', NOW(), '', NULL, ''),
|
|
||||||
('信贷客户家庭关系修改', @parent_id, 3, '#', '', 1, 0, 'F', '0', '0', 'ccdi:custFmyRelation:edit', '#', 'admin', NOW(), '', NULL, ''),
|
|
||||||
('信贷客户家庭关系删除', @parent_id, 4, '#', '', 1, 0, 'F', '0', '0', 'ccdi:custFmyRelation:remove', '#', 'admin', NOW(), '', NULL, ''),
|
|
||||||
('信贷客户家庭关系导出', @parent_id, 5, '#', '', 1, 0, 'F', '0', '0', 'ccdi:custFmyRelation:export', '#', 'admin', NOW(), '', NULL, ''),
|
|
||||||
('信贷客户家庭关系导入', @parent_id, 6, '#', '', 1, 0, 'F', '0', '0', 'ccdi:custFmyRelation:import', '#', 'admin', NOW(), '', NULL, '');
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 2: Commit**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git add sql/ccdi_cust_fmy_relation_menu.sql
|
|
||||||
git commit -m "feat: 添加信贷客户家庭关系菜单权限"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 13: 配置字典数据
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Modify: 通过系统管理界面配置
|
|
||||||
|
|
||||||
**Step 1: 确认字典存在**
|
|
||||||
|
|
||||||
登录系统 → 系统管理 → 字典管理,确认以下字典类型已存在:
|
|
||||||
- `ccdi_relation_type`:关系类型
|
|
||||||
- `ccdi_indiv_gender`:性别
|
|
||||||
- `ccdi_certificate_type`:证件类型
|
|
||||||
|
|
||||||
如不存在,参考员工亲属关系的字典数据添加。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 测试验证
|
|
||||||
|
|
||||||
### Task 14: 后端接口测试
|
|
||||||
|
|
||||||
**Files:**
|
|
||||||
- Create: `doc/reviews/cust-fmy-relation-api-test.md`
|
|
||||||
|
|
||||||
**Step 1: 启动后端服务**
|
|
||||||
|
|
||||||
Run: `mvn spring-boot:run -pl ruoyi-admin`
|
|
||||||
Expected: 服务启动成功,访问 http://localhost:8080/swagger-ui/index.html
|
|
||||||
|
|
||||||
**Step 2: 测试登录获取token**
|
|
||||||
|
|
||||||
Run:
|
|
||||||
```bash
|
|
||||||
curl -X POST "http://localhost:8080/login" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{"username":"admin","password":"admin123"}'
|
|
||||||
```
|
|
||||||
Expected: 返回token
|
|
||||||
|
|
||||||
**Step 3: 测试查询列表接口**
|
|
||||||
|
|
||||||
Run:
|
|
||||||
```bash
|
|
||||||
curl -X GET "http://localhost:8080/ccdi/custFmyRelation/list?pageNum=1&pageSize=10" \
|
|
||||||
-H "Authorization: Bearer <token>"
|
|
||||||
```
|
|
||||||
Expected: 返回空列表(无数据)
|
|
||||||
|
|
||||||
**Step 4: 测试新增接口**
|
|
||||||
|
|
||||||
Run:
|
|
||||||
```bash
|
|
||||||
curl -X POST "http://localhost:8080/ccdi/custFmyRelation" \
|
|
||||||
-H "Authorization: Bearer <token>" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{
|
|
||||||
"personId": "110101199001011234",
|
|
||||||
"relationType": "配偶",
|
|
||||||
"relationName": "张三",
|
|
||||||
"gender": "M",
|
|
||||||
"relationCertType": "身份证",
|
|
||||||
"relationCertNo": "110101199001015678"
|
|
||||||
}'
|
|
||||||
```
|
|
||||||
Expected: 返回成功
|
|
||||||
|
|
||||||
**Step 5: 测试查询详情接口**
|
|
||||||
|
|
||||||
Run:
|
|
||||||
```bash
|
|
||||||
curl -X GET "http://localhost:8080/ccdi/custFmyRelation/1" \
|
|
||||||
-H "Authorization: Bearer <token>"
|
|
||||||
```
|
|
||||||
Expected: 返回刚插入的记录
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 15: 前端功能测试
|
|
||||||
|
|
||||||
**Step 1: 启动前端服务**
|
|
||||||
|
|
||||||
Run: `cd ruoyi-ui && npm run dev`
|
|
||||||
Expected: 服务启动成功,访问 http://localhost
|
|
||||||
|
|
||||||
**Step 2: 登录系统**
|
|
||||||
|
|
||||||
用户名: admin
|
|
||||||
密码: admin123
|
|
||||||
|
|
||||||
**Step 3: 导航到信贷客户家庭关系页面**
|
|
||||||
|
|
||||||
路径: 信息维护 → 信贷客户家庭关系
|
|
||||||
|
|
||||||
**Step 4: 测试新增功能**
|
|
||||||
|
|
||||||
1. 点击"新增"按钮
|
|
||||||
2. 填写表单:
|
|
||||||
- 信贷客户身份证号: `110101199001011234`
|
|
||||||
- 关系类型: `配偶`
|
|
||||||
- 关系人姓名: `张三`
|
|
||||||
- 性别: `男`
|
|
||||||
- 证件类型: `身份证`
|
|
||||||
- 证件号码: `110101199001015678`
|
|
||||||
3. 点击"确定"
|
|
||||||
Expected: 新增成功,列表显示新记录
|
|
||||||
|
|
||||||
**Step 5: 测试编辑功能**
|
|
||||||
|
|
||||||
1. 点击"编辑"按钮
|
|
||||||
2. 修改关系人姓名为 `张三丰`
|
|
||||||
3. 点击"确定"
|
|
||||||
Expected: 修改成功,列表显示更新
|
|
||||||
|
|
||||||
**Step 6: 测试删除功能**
|
|
||||||
|
|
||||||
1. 勾选记录
|
|
||||||
2. 点击"删除"按钮
|
|
||||||
3. 确认删除
|
|
||||||
Expected: 删除成功,列表不再显示该记录
|
|
||||||
|
|
||||||
**Step 7: 测试导出功能**
|
|
||||||
|
|
||||||
1. 添加几条测试数据
|
|
||||||
2. 点击"导出"按钮
|
|
||||||
Expected: 下载Excel文件,数据正确
|
|
||||||
|
|
||||||
**Step 8: 测试导入功能**
|
|
||||||
|
|
||||||
1. 点击"导入"按钮
|
|
||||||
2. 下载模板
|
|
||||||
3. 填写数据后上传
|
|
||||||
4. 等待异步导入完成
|
|
||||||
Expected: 导入成功,显示结果通知
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 16: API文档生成
|
|
||||||
|
|
||||||
**Step 1: 访问Swagger文档**
|
|
||||||
|
|
||||||
URL: http://localhost:8080/swagger-ui/index.html
|
|
||||||
Expected: 看到"信贷客户家庭关系管理"分组,所有接口正常显示
|
|
||||||
|
|
||||||
**Step 2: 导出API文档**
|
|
||||||
|
|
||||||
使用 Swagger 导出功能,保存到: `doc/api-docs/cust-fmy-relation-api.md`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 完成检查清单
|
|
||||||
|
|
||||||
- [ ] 数据库表创建成功
|
|
||||||
- [ ] 后端所有类编译通过
|
|
||||||
- [ ] Controller所有接口在Swagger正常显示
|
|
||||||
- [ ] 前端页面正常加载
|
|
||||||
- [ ] 增删改查功能正常
|
|
||||||
- [ ] 导入导出功能正常
|
|
||||||
- [ ] 权限控制生效
|
|
||||||
- [ ] 字典数据正确显示
|
|
||||||
- [ ] 测试文档完整
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 预期结果
|
|
||||||
|
|
||||||
完成后,系统将具备以下功能:
|
|
||||||
|
|
||||||
1. **信贷客户家庭关系管理页面**
|
|
||||||
- 列表展示(分页)
|
|
||||||
- 简化查询(身份证号、关系类型、关系人姓名)
|
|
||||||
- 新增/编辑/删除/详情
|
|
||||||
|
|
||||||
2. **导入导出功能**
|
|
||||||
- 带字典下拉框的Excel模板
|
|
||||||
- 异步导入,实时状态查询
|
|
||||||
- 失败记录查看
|
|
||||||
|
|
||||||
3. **权限控制**
|
|
||||||
- 完整的CRUD权限
|
|
||||||
- 按钮级权限控制
|
|
||||||
|
|
||||||
4. **数据隔离**
|
|
||||||
- 独立表 `ccdi_cust_fmy_relation`
|
|
||||||
- `is_cust_family = 1`
|
|
||||||
@@ -1,373 +0,0 @@
|
|||||||
# 信贷客户家庭关系导入功能对齐方案
|
|
||||||
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
本文档描述了如何将**信贷客户家庭关系**功能的导入实现完全对齐到**员工亲属关系**的成熟模式。
|
|
||||||
|
|
||||||
**参考模板**: `CcdiStaffEnterpriseRelationImportServiceImpl`
|
|
||||||
**修改对象**: `CcdiCustFmyRelationImportServiceImpl`
|
|
||||||
|
|
||||||
## 设计目标
|
|
||||||
|
|
||||||
1. 提升代码质量和可维护性
|
|
||||||
2. 优化性能,避免 N+1 查询问题
|
|
||||||
3. 改善用户体验,提供详细的导入进度和状态反馈
|
|
||||||
4. 统一日志记录和错误处理机制
|
|
||||||
|
|
||||||
## 架构调整
|
|
||||||
|
|
||||||
### 1. 引入导入工具类
|
|
||||||
|
|
||||||
复用 `ImportLogUtils` 进行统一的日志记录:
|
|
||||||
- 导入开始/结束日志
|
|
||||||
- 批量查询日志
|
|
||||||
- 进度跟踪日志
|
|
||||||
- 验证错误日志
|
|
||||||
- 批量操作日志
|
|
||||||
|
|
||||||
### 2. Redis 状态管理升级
|
|
||||||
|
|
||||||
**现状**: 简单 String 值存储状态
|
|
||||||
```
|
|
||||||
"COMPLETED:10:5"
|
|
||||||
```
|
|
||||||
|
|
||||||
**优化**: Hash 结构存储详细状态
|
|
||||||
```java
|
|
||||||
{
|
|
||||||
"taskId": "uuid",
|
|
||||||
"status": "SUCCESS" | "PARTIAL_SUCCESS" | "PROCESSING",
|
|
||||||
"totalCount": 100,
|
|
||||||
"successCount": 95,
|
|
||||||
"failureCount": 5,
|
|
||||||
"progress": 100,
|
|
||||||
"startTime": 1234567890,
|
|
||||||
"endTime": 1234567900,
|
|
||||||
"message": "成功95条,失败5条"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- 过期时间: 7 天
|
|
||||||
- 失败记录: 单独 Key, JSON 序列化, 7 天过期
|
|
||||||
|
|
||||||
### 3. 批量查询优化
|
|
||||||
|
|
||||||
**实现 `batchExistsByCombinations` 方法**:
|
|
||||||
- 提取所有 `person_id + relation_type + relation_cert_no` 组合
|
|
||||||
- 一次性批量查询已存在的组合
|
|
||||||
- 避免循环查询导致的 N+1 问题
|
|
||||||
|
|
||||||
### 4. 导入结果封装
|
|
||||||
|
|
||||||
创建/复用统一的 VO:
|
|
||||||
- `ImportStatusVO`: 导入状态详情
|
|
||||||
- `ImportResultVO`: 导入提交结果
|
|
||||||
- `CustFmyRelationImportFailureVO`: 失败记录详情
|
|
||||||
|
|
||||||
## 数据验证逻辑
|
|
||||||
|
|
||||||
### 唯一性检查
|
|
||||||
|
|
||||||
**优化前**: 每条记录单独查询
|
|
||||||
```java
|
|
||||||
for (excel : excels) {
|
|
||||||
CcdiCustFmyRelation existing = mapper.selectExistingRelations(...);
|
|
||||||
// N 次数据库查询
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**优化后**: 批量查询
|
|
||||||
```java
|
|
||||||
Set<String> existingCombinations = getExistingCombinations(excels);
|
|
||||||
// 1 次数据库查询
|
|
||||||
|
|
||||||
for (excel : excels) {
|
|
||||||
String combination = excel.getPersonId() + "|" + ...;
|
|
||||||
if (existingCombinations.contains(combination)) {
|
|
||||||
throw new RuntimeException("该关系已存在");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Excel 内部重复检查
|
|
||||||
|
|
||||||
```java
|
|
||||||
Set<String> processedCombinations = new HashSet<>();
|
|
||||||
|
|
||||||
for (excel : excels) {
|
|
||||||
String combination = ...;
|
|
||||||
|
|
||||||
if (processedCombinations.contains(combination)) {
|
|
||||||
throw new RuntimeException("该关系在导入文件中重复");
|
|
||||||
}
|
|
||||||
|
|
||||||
processedCombinations.add(combination);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 验证规则
|
|
||||||
|
|
||||||
**必填字段**:
|
|
||||||
- 信贷客户身份证号
|
|
||||||
- 关系类型
|
|
||||||
- 关系人姓名
|
|
||||||
- 关系人证件类型
|
|
||||||
- 关系人证件号码
|
|
||||||
|
|
||||||
**格式验证**:
|
|
||||||
- 身份证号: 18位有效格式
|
|
||||||
- 证件号码: 根据证件类型验证
|
|
||||||
|
|
||||||
**长度限制**:
|
|
||||||
- 关系人姓名: ≤ 50
|
|
||||||
- 关系类型: ≤ 20
|
|
||||||
- 证件号码: ≤ 50
|
|
||||||
|
|
||||||
## 批量操作优化
|
|
||||||
|
|
||||||
### 分批插入策略
|
|
||||||
|
|
||||||
```java
|
|
||||||
private void saveBatch(List<CcdiCustFmyRelation> list, int batchSize) {
|
|
||||||
for (int i = 0; i < list.size(); i += batchSize) {
|
|
||||||
int end = Math.min(i + batchSize, list.size());
|
|
||||||
List<CcdiCustFmyRelation> subList = list.subList(i, end);
|
|
||||||
mapper.insertBatch(subList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 调用: 每 500 条为一批
|
|
||||||
saveBatch(newRecords, 500);
|
|
||||||
```
|
|
||||||
|
|
||||||
### 批量操作日志
|
|
||||||
|
|
||||||
```
|
|
||||||
开始批量插入: 总批次数=5, 每批大小=500
|
|
||||||
批量插入完成: 成功=2500, 耗时=1234ms
|
|
||||||
```
|
|
||||||
|
|
||||||
## 失败记录处理
|
|
||||||
|
|
||||||
### 失败记录数据结构
|
|
||||||
|
|
||||||
```java
|
|
||||||
public class CustFmyRelationImportFailureVO {
|
|
||||||
private Integer rowNum; // Excel 行号
|
|
||||||
private String personId; // 信贷客户身份证号
|
|
||||||
private String relationType; // 关系类型
|
|
||||||
private String relationName; // 关系人姓名
|
|
||||||
private String errorMessage; // 错误消息
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Redis 存储优化
|
|
||||||
|
|
||||||
**Key**: `import:custFmyRelation:{taskId}:failures`
|
|
||||||
**序列化**: JSON
|
|
||||||
**过期时间**: 7 天
|
|
||||||
**反序列化**:
|
|
||||||
```java
|
|
||||||
return JSON.parseArray(
|
|
||||||
JSON.toJSONString(failuresObj),
|
|
||||||
CustFmyRelationImportFailureVO.class
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Controller 层调整
|
|
||||||
|
|
||||||
### 导入接口
|
|
||||||
|
|
||||||
```java
|
|
||||||
@PostMapping("/importData")
|
|
||||||
public AjaxResult importData(@RequestParam("file") MultipartFile file) {
|
|
||||||
List<CcdiCustFmyRelationExcel> excels =
|
|
||||||
EasyExcelUtil.importExcel(file.getInputStream(), ...);
|
|
||||||
|
|
||||||
if (excels == null || excels.isEmpty()) {
|
|
||||||
return error("至少需要一条数据");
|
|
||||||
}
|
|
||||||
|
|
||||||
String taskId = relationService.importRelations(excels);
|
|
||||||
|
|
||||||
ImportResultVO result = new ImportResultVO();
|
|
||||||
result.setTaskId(taskId);
|
|
||||||
result.setStatus("PROCESSING");
|
|
||||||
result.setMessage("导入任务已提交,正在后台处理");
|
|
||||||
|
|
||||||
return AjaxResult.success("导入任务已提交,正在后台处理", result);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 导入状态查询
|
|
||||||
|
|
||||||
```java
|
|
||||||
@GetMapping("/importStatus/{taskId}")
|
|
||||||
public AjaxResult getImportStatus(@PathVariable String taskId) {
|
|
||||||
ImportStatusVO statusVO = relationImportService.getImportStatus(taskId);
|
|
||||||
return success(statusVO);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 失败记录查询
|
|
||||||
|
|
||||||
```java
|
|
||||||
@GetMapping("/importFailures/{taskId}")
|
|
||||||
public TableDataInfo getImportFailures(
|
|
||||||
@PathVariable String taskId,
|
|
||||||
@RequestParam(defaultValue = "1") Integer pageNum,
|
|
||||||
@RequestParam(defaultValue = "10") Integer pageSize
|
|
||||||
) {
|
|
||||||
List<CustFmyRelationImportFailureVO> failures =
|
|
||||||
relationImportService.getImportFailures(taskId);
|
|
||||||
|
|
||||||
// 手动分页
|
|
||||||
int fromIndex = (pageNum - 1) * pageSize;
|
|
||||||
int toIndex = Math.min(fromIndex + pageSize, failures.size());
|
|
||||||
|
|
||||||
if (fromIndex >= failures.size()) {
|
|
||||||
return getDataTable(new ArrayList<>(), failures.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
List<CustFmyRelationImportFailureVO> pageData =
|
|
||||||
failures.subList(fromIndex, toIndex);
|
|
||||||
|
|
||||||
return getDataTable(pageData, failures.size());
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 导入模板改进
|
|
||||||
|
|
||||||
### 使用字典下拉框
|
|
||||||
|
|
||||||
```java
|
|
||||||
@PostMapping("/importTemplate")
|
|
||||||
public void importTemplate(HttpServletResponse response) {
|
|
||||||
EasyExcelUtil.importTemplateWithDictDropdown(
|
|
||||||
response,
|
|
||||||
CcdiCustFmyRelationExcel.class,
|
|
||||||
"信贷客户家庭关系"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Excel 实体注解增强
|
|
||||||
|
|
||||||
```java
|
|
||||||
@DictDropdown(type = "ccdi_relation_type")
|
|
||||||
private String relationType;
|
|
||||||
|
|
||||||
@DictDropdown(type = "ccdi_cert_type")
|
|
||||||
private String relationCertType;
|
|
||||||
```
|
|
||||||
|
|
||||||
## 修改文件清单
|
|
||||||
|
|
||||||
### 1. Service 层
|
|
||||||
- `CcdiCustFmyRelationImportServiceImpl.java` - 核心导入逻辑重构
|
|
||||||
- `CcdiCustFmyRelationServiceImpl.java` - 导入入口方法调整
|
|
||||||
|
|
||||||
### 2. Controller 层
|
|
||||||
- `CcdiCustFmyRelationController.java` - 接口返回值优化
|
|
||||||
|
|
||||||
### 3. Mapper 层
|
|
||||||
- `CcdiCustFmyRelationMapper.java` - 添加批量查询方法
|
|
||||||
- Mapper XML - 实现批量查询 SQL
|
|
||||||
|
|
||||||
### 4. VO 类
|
|
||||||
- 检查/创建 `ImportStatusVO.java`
|
|
||||||
- 检查/创建 `ImportResultVO.java`
|
|
||||||
- 优化 `CustFmyRelationImportFailureVO.java`
|
|
||||||
|
|
||||||
### 5. Excel 实体
|
|
||||||
- `CcdiCustFmyRelationExcel.java` - 添加字典注解
|
|
||||||
|
|
||||||
### 6. 工具类
|
|
||||||
- 复用 `ImportLogUtils.java`
|
|
||||||
- 复用 `EasyExcelUtil.java`
|
|
||||||
|
|
||||||
## 关键代码片段
|
|
||||||
|
|
||||||
### Mapper 批量查询
|
|
||||||
|
|
||||||
```java
|
|
||||||
// Mapper 接口
|
|
||||||
List<String> batchExistsByCombinations(
|
|
||||||
@Param("combinations") List<String> combinations
|
|
||||||
);
|
|
||||||
|
|
||||||
// XML 实现
|
|
||||||
<select id="batchExistsByCombinations" resultType="string">
|
|
||||||
SELECT CONCAT(person_id, '|', relation_type, '|', relation_cert_no)
|
|
||||||
FROM ccdi_cust_fmy_relation
|
|
||||||
WHERE CONCAT(person_id, '|', relation_type, '|', relation_cert_no) IN
|
|
||||||
<foreach collection="combinations" item="combo" open="(" separator="," close=")">
|
|
||||||
#{combo}
|
|
||||||
</foreach>
|
|
||||||
</select>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 异步导入方法
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Async
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public void importRelationsAsync(
|
|
||||||
List<CcdiCustFmyRelationExcel> excels,
|
|
||||||
String taskId,
|
|
||||||
String userName // 新增参数,用于审计
|
|
||||||
) {
|
|
||||||
// 实现逻辑...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 实施步骤
|
|
||||||
|
|
||||||
1. **添加 Mapper 批量查询方法**
|
|
||||||
- 在 Mapper 接口添加 `batchExistsByCombinations`
|
|
||||||
- 在 XML 实现 SQL
|
|
||||||
|
|
||||||
2. **重构 ImportServiceImpl**
|
|
||||||
- 引入 `ImportLogUtils`
|
|
||||||
- 实现批量查询逻辑
|
|
||||||
- 添加 Excel 内部重复检查
|
|
||||||
- 优化 Redis 状态管理
|
|
||||||
- 改进失败记录存储
|
|
||||||
|
|
||||||
3. **创建/优化 VO 类**
|
|
||||||
- 检查并复用已有的 `ImportStatusVO`
|
|
||||||
- 检查并复用已有的 `ImportResultVO`
|
|
||||||
- 优化失败记录 VO
|
|
||||||
|
|
||||||
4. **调整 Controller**
|
|
||||||
- 修改导入接口返回值
|
|
||||||
- 优化状态查询接口
|
|
||||||
- 优化失败记录查询接口
|
|
||||||
|
|
||||||
5. **更新 Excel 实体**
|
|
||||||
- 添加 `@DictDropdown` 注解
|
|
||||||
|
|
||||||
6. **测试验证**
|
|
||||||
- 单元测试
|
|
||||||
- 集成测试
|
|
||||||
- 性能对比测试
|
|
||||||
|
|
||||||
## 预期效果
|
|
||||||
|
|
||||||
### 性能提升
|
|
||||||
- 批量查询: 从 N 次减少到 1 次
|
|
||||||
- 导入 1000 条数据预计提升 50-70%
|
|
||||||
|
|
||||||
### 用户体验
|
|
||||||
- 实时进度反馈
|
|
||||||
- 详细的错误信息
|
|
||||||
- 清晰的成功/失败统计
|
|
||||||
|
|
||||||
### 代码质量
|
|
||||||
- 统一的日志记录
|
|
||||||
- 完善的错误处理
|
|
||||||
- 更好的可维护性
|
|
||||||
|
|
||||||
## 创建日期
|
|
||||||
|
|
||||||
2026-02-11
|
|
||||||
Reference in New Issue
Block a user