Files
ccdi/doc/信贷客户家庭关系维护功能/设计文档.md
wkc fd9e208fa3 docs(staff-enterprise-relation): 更新API文档,添加员工姓名字段说明
- 新增员工实体关系管理API文档
- 在列表接口和详情接口响应中添加personName字段
- 说明personName通过LEFT JOIN ccdi_base_staff表获取
- 如果personId在员工信息表中不存在,personName为null
2026-02-11 15:27:40 +08:00

23 KiB
Raw Blame History

信贷客户家庭关系维护功能设计文档

一、项目概述

1.1 功能描述

开发信贷客户家庭关系维护功能实现对信贷客户家庭成员信息的新增、修改、删除、查询、导入、导出等完整的CRUD操作。

设计原则:完全复用员工亲属关系维护功能的实现逻辑和前端交互方式,创建独立模块管理。

1.2 技术栈

  • 后端: Spring Boot 3.5.8 + MyBatis Plus 3.5.10 + SpringDoc
  • 前端: Vue 2.6.12 + Element UI 2.15.14
  • 数据库: MySQL 8.2.0
  • Excel处理: EasyExcel
  • 缓存: Redis
  • 异步处理: Spring @Async

1.3 参考标准

本功能完全参考员工亲属关系维护模块的设计与实现,确保代码风格、交互方式、技术实现的一致性。


二、数据库设计

2.1 主表结构

表名: ccdi_cust_fmy_relation(信贷客户家庭关系表)

字段序号 字段名 类型 默认值 是否可为空 主键 注释
1 id BIGINT - 主键,自增
2 person_id VARCHAR - - 信贷客户身份证号
3 relation_type VARCHAR - - 关系类型(配偶、子女、父母、兄弟姐妹等)
4 relation_name VARCHAR - - 关系人姓名
5 gender CHAR - - 性别M/F/O
6 birth_date DATE - - 关系人出生日期
7 relation_cert_type VARCHAR - - 证件类型(必填)
8 relation_cert_no VARCHAR - - 证件号码(必填)
9 mobile_phone1 VARCHAR - - 手机号码1
10 mobile_phone2 VARCHAR - - 手机号码2
11 wechat_no1 VARCHAR - - 微信号1
12 wechat_no2 VARCHAR - - 微信号2
13 wechat_no3 VARCHAR - - 微信号3
14 contact_address VARCHAR - - 详细联系地址
15 relation_desc VARCHAR - - 关系详细描述
16 status INT 1 - 状态0-无效1-有效
17 effective_date DATETIME - - 关系生效日期
18 invalid_date DATETIME - - 关系失效日期
19 remark TEXT - - 备注信息
20 data_source VARCHAR(50) - - 数据来源MANUAL/SYSTEM/IMPORT/API
21 is_emp_family TINYINT(1) 0 - 是否员工家庭关系固定为0
22 is_cust_family TINYINT(1) 1 - 是否信贷客户家庭关系固定为1
23 created_by VARCHAR - - 记录创建人
24 updated_by VARCHAR - - 记录更新人
25 create_time DATETIME - - 记录创建时间
26 update_time DATETIME - - 记录更新时间

2.2 核心差异说明

与员工亲属关系表对比

对比项 员工亲属关系 信贷客户家庭关系
person_id语义 员工身份证号 信贷客户身份证号
is_emp_family 固定为1 固定为0
is_cust_family 固定为0 固定为1
外键关联 关联ccdi_base_staff 暂不关联,独立存储

2.3 唯一键设计

唯一键 = 信贷客户身份证号 + 关系人身份证号

  • 格式:{personId}_{relationCertNo}
  • 示例:110101199001011234_110101199001015678
  • 用于导入时的重复性校验

2.4 建表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='信贷客户家庭关系表';

三、后端设计

3.1 模块命名

模块名称: CustFamilyRelation(信贷客户家庭关系)

包路径: com.ruoyi.ccdi

3.2 类结构设计

3.2.1 实体类Entity

CcdiCustFmyRelation.java

@Data
@TableName("ccdi_cust_fmy_relation")
public class CcdiCustFmyRelation implements Serializable {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String personId;
    private String relationType;
    private String relationName;
    private String gender;
    private Date birthDate;
    private String relationCertType;
    private String relationCertNo;
    private String mobilePhone1;
    private String mobilePhone2;
    private String wechatNo1;
    private String wechatNo2;
    private String wechatNo3;
    private String contactAddress;
    private String relationDesc;
    private Integer status;
    private Date effectiveDate;
    private Date invalidDate;
    private String remark;
    private String dataSource;
    private Boolean isEmpFamily;  // 固定为false
    private Boolean isCustFamily;  // 固定为true

    @TableField(fill = FieldFill.INSERT)
    private String createdBy;

    @TableField(fill = FieldFill.INSERT)
    private Date createTime;

    @TableField(fill = FieldFill.INSERT_UPDATE)
    private String updatedBy;

    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
}

3.2.2 DTO设计

CcdiCustFmyRelationAddDTO.java新增DTO

  • 必填字段:
    • personId - 信贷客户身份证号
    • relationType - 关系类型
    • relationName - 关系人姓名
    • relationCertType - 证件类型
    • relationCertNo - 证件号码
  • 可选字段:其他所有字段
  • 校验规则:
    • 身份证号格式验证18位
    • 手机号格式验证11位
    • 性别值验证M/F/O
    • 字段长度验证
  • 差异:无需验证员工是否存在,直接作为文本字段处理

CcdiCustFmyRelationEditDTO.java编辑DTO

  • 包含所有字段(除审计字段)
  • 同样的校验规则

CcdiCustFmyRelationQueryDTO.java查询DTO

  • 简化版查询条件
    • personId - 信贷客户身份证号(精确)
    • relationType - 关系类型
    • relationName - 关系人姓名(模糊)
  • 移除字段personName、status、dataSource、日期范围等

3.2.3 VO设计

CcdiCustFmyRelationVO.java(列表/详情VO

  • 包含所有展示字段
  • 扩展字段:
    • genderName - 性别名称(转换)
    • statusName - 状态名称(转换)
    • dataSourceName - 数据来源名称
  • 差异无需personName不关联其他表

CcdiCustFmyRelationExcel.javaExcel导入导出

  • 使用@DictDropdown注解添加字典下拉框:
    • relationTypeccdi_relation_type
    • genderccdi_indiv_gender
    • relationCertTypeccdi_certificate_type
  • 使用@Required注解标记必填字段
  • 字段索引0-16

CustFmyRelationImportFailureVO.java(导入失败记录)

  • rowNum - 行号
  • personId - 信贷客户身份证号
  • relationName - 关系人姓名
  • errorMessage - 错误信息

3.2.4 Mapper层

CcdiCustFmyRelationMapper.java

@Mapper
public interface CcdiCustFmyRelationMapper extends BaseMapper<CcdiCustFmyRelation> {
    Page<CcdiCustFmyRelationVO> selectRelationPage(
        Page<CcdiCustFmyRelationVO> page,
        @Param("query") CcdiCustFmyRelationQueryDTO queryDTO
    );

    List<CcdiCustFmyRelationExcel> selectRelationListForExport(
        @Param("query") CcdiCustFmyRelationQueryDTO queryDTO
    );
}

XML映射要点

  • WHERE条件is_cust_family = 1
  • 无需LEFT JOIN(不关联客户表)
  • 支持多条件动态查询
  • 按创建时间倒序排列

3.2.5 Service层

ICcdiCustFmyRelationService.java(主服务接口)

public interface ICcdiCustFmyRelationService {
    List<CcdiCustFmyRelationVO> selectRelationList(CcdiCustFmyRelationQueryDTO queryDTO);
    Page<CcdiCustFmyRelationVO> selectRelationPage(Page<CcdiCustFmyRelationVO> page, CcdiCustFmyRelationQueryDTO queryDTO);
    List<CcdiCustFmyRelationExcel> selectRelationListForExport(CcdiCustFmyRelationQueryDTO queryDTO);
    CcdiCustFmyRelationVO selectRelationById(Long id);
    int insertRelation(CcdiCustFmyRelationAddDTO addDTO);
    int updateRelation(CcdiCustFmyRelationEditDTO editDTO);
    int deleteRelationByIds(Long[] ids);
    String importRelation(List<CcdiCustFmyRelationExcel> excelList);
}

ICcdiCustFmyRelationImportService.java(导入服务接口)

public interface ICcdiCustFmyRelationImportService {
    void importRelationAsync(List<CcdiCustFmyRelationExcel> excelList, String taskId, String userName);
    ImportStatusVO getImportStatus(String taskId);
    List<CustFmyRelationImportFailureVO> getImportFailures(String taskId);
}

3.2.6 Controller层

CcdiCustFmyRelationController.java

接口清单

接口路径 方法 功能 权限标识
/ccdi/custFmyRelation/list GET 查询列表 ccdi:custFmyRelation:list
/ccdi/custFmyRelation/{id} GET 查询详情 ccdi:custFmyRelation:query
/ccdi/custFmyRelation POST 新增 ccdi:custFmyRelation:add
/ccdi/custFmyRelation PUT 修改 ccdi:custFmyRelation:edit
/ccdi/custFmyRelation/{ids} DELETE 删除 ccdi:custFmyRelation:remove
/ccdi/custFmyRelation/export POST 导出 ccdi:custFmyRelation:export
/ccdi/custFmyRelation/importTemplate POST 下载模板 -
/ccdi/custFmyRelation/importData POST 导入 ccdi:custFmyRelation:import
/ccdi/custFmyRelation/importStatus/{taskId} GET 导入状态 ccdi:custFmyRelation:import
/ccdi/custFmyRelation/importFailures/{taskId} GET 失败记录 ccdi:custFmyRelation:import

3.3 异步导入机制

完全复用员工亲属关系的异步导入逻辑,仅调整以下内容:

3.3.1 唯一键校验

唯一键 = 信贷客户身份证号 + 关系人身份证号

  • 用于检测Excel文件内部的重复记录
  • 重复时跳过并记录到失败列表
  • 错误提示:信贷客户身份证号[xxx]与关系人身份证号[xxx]的关系在导入文件中重复

3.3.2 Redis存储结构

状态存储Hash

Key: import:custFmyRelation:{taskId}
Fields:
  - taskId: 任务ID
  - status: PROCESSING/SUCCESS/PARTIAL_SUCCESS
  - totalCount: 总数
  - successCount: 成功数
  - failureCount: 失败数
  - progress: 进度0-100
  - startTime: 开始时间戳
  - endTime: 结束时间戳
  - message: 状态消息
TTL: 7天

失败记录存储List

Key: import:custFmyRelation:{taskId}:failures
Value: JSON数组包含所有失败记录
TTL: 7天

3.3.3 数据验证规则

必填字段验证

  1. 信贷客户身份证号 - 非空 + 18位格式
  2. 关系类型 - 非空
  3. 关系人姓名 - 非空
  4. 证件类型 - 非空
  5. 证件号码 - 非空

格式验证

  • 身份证号:^[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[0-9Xx]$
  • 手机号:^1[3-9]\\d{9}$
  • 性别:^[MFO]$

四、前端设计

4.1 目录结构

ruoyi-ui/src/
├── api/
│   └── ccdiCustFmyRelation.js     # API接口定义
└── views/
    └── ccdiCustFmyRelation/
        └── index.vue                # 主页面组件

4.2 API接口设计

ccdiCustFmyRelation.js

// 查询列表
export function listRelation(query)
export function getRelation(id)
export function addRelation(data)
export function updateRelation(data)
export function delRelation(ids)
export function exportRelation(query)
export function importTemplate()
export function importData(file)
export function getImportStatus(taskId)
export function getImportFailures(taskId, pageNum, pageSize)

4.3 页面功能设计

4.3.1 列表页面

查询条件(简化版):

  • 信贷客户身份证号:文本输入框
  • 关系类型:下拉选择(字典:ccdi_relation_type
  • 关系人姓名:文本输入框
  • 搜索/重置按钮

操作按钮

  • 新增
  • 导入
  • 导出
  • 查看导入失败记录(有失败数据时显示)

列表列

  • 选择框
  • 信贷客户身份证号
  • 关系类型
  • 关系人姓名
  • 性别
  • 联系电话
  • 联系地址
  • 状态(标签显示)
  • 创建时间
  • 操作(详情/编辑/删除)

差异

  • 移除"员工姓名"列
  • "person_id"列标题改为"信贷客户身份证号"

4.3.2 新增/编辑表单

表单分组

  1. 基本信息

    • 信贷客户身份证号:文本输入框(普通输入,非远程搜索)
    • 关系类型:下拉选择
    • 关系人姓名:文本输入
    • 性别:下拉选择(男/女/其他)
    • 出生日期:日期选择
  2. 证件信息

    • 证件类型:文本输入
    • 证件号码:文本输入
  3. 联系方式

    • 手机号码1/2文本输入
    • 微信号1/2/3文本输入
    • 联系地址:文本域
  4. 其他信息

    • 关系描述:文本域
    • 生效日期:日期选择
    • 失效日期:日期选择
    • 备注:文本域

表单验证

  • 必填字段标记
  • 格式验证(手机号、身份证号)
  • 长度限制

差异

  • "信贷客户身份证号"使用普通文本输入,而非远程搜索下拉选择器

4.3.3 详情页面

使用el-descriptions组件展示所有字段信息,分组显示:

  • 基本信息
  • 证件信息
  • 联系方式
  • 其他信息
  • 审计信息

4.3.4 导入功能

导入对话框

  • 拖拽上传
  • 仅支持.xlsx/.xls格式
  • 下载模板链接
  • 上传后立即返回任务ID

导入结果轮询

  • 每2秒查询一次状态
  • 最多轮询150次5分钟
  • 完成后显示通知:
    • 全部成功:绿色通知,显示总数
    • 部分失败:橙色通知,显示成功/失败数
    • 显示"查看导入失败记录"按钮

失败记录对话框

  • 显示导入统计信息
  • 表格展示失败记录:
    • 行号
    • 信贷客户身份证号
    • 关系人姓名
    • 失败原因
  • 支持分页
  • 清除历史记录按钮

4.3.5 localStorage持久化

存储内容

{
  taskId: "uuid",
  status: "SUCCESS/PARTIAL_SUCCESS",
  hasFailures: true/false,
  totalCount: 100,
  successCount: 95,
  failureCount: 5,
  saveTime: 1707456000000
}

Key名称

cust_fmy_relation_import_last_task

4.4 文案替换清单

原文案(员工亲属关系) 新文案(信贷客户家庭关系)
员工亲属关系维护 信贷客户家庭关系维护
员工亲属关系列表 信贷客户家庭关系列表
员工身份证号 信贷客户身份证号
员工 信贷客户
新增员工亲属关系 新增信贷客户家庭关系

五、与员工亲属关系对比验证

5.1 架构对比

对比项 员工亲属关系 信贷客户家庭关系 一致性
模块命名 StaffFmyRelation CustFmyRelation 遵循规范
包结构 com.ruoyi.ccdi com.ruoyi.ccdi 一致
分层架构 Controller-Service-Mapper Controller-Service-Mapper 一致
DTO/VO分离 一致
MyBatis Plus 使用 使用 一致

5.2 Controller接口对比

接口功能 员工亲属关系 信贷客户家庭关系 一致性
查询列表 /list /list 一致
查询详情 /{id} /{id} 一致
新增 POST POST 一致
修改 PUT PUT 一致
删除 /{ids} /{ids} 一致
导出 /export /export 一致
下载模板 /importTemplate /importTemplate 一致
导入数据 /importData /importData 一致
导入状态 /importStatus/{id} /importStatus/{id} 一致
失败记录 /importFailures/{id} /importFailures/{id} 一致

5.3 查询功能对比

对比项 员工亲属关系 信贷客户家庭关系 差异说明
personId字段 员工身份证号 信贷客户身份证号 字段语义不同
personName 有(关联查询) 不关联其他表
查询条件 6个 3个简化版 简化查询

5.4 数据对比

对比项 员工亲属关系 信贷客户家庭关系 一致性
异步注解 @Async @Async 一致
状态存储 Redis Hash Redis Hash 一致
失败记录存储 Redis List Redis List 一致
过期时间 7天 7天 一致
批量插入大小 500条/批 500条/批 一致
唯一键校验 员工身份证号+关系人身份证号 信贷客户身份证号+关系人身份证号 逻辑一致
数据验证 validateRelationData() validateRelationData() 结构一致

5.5 前端交互对比

对比项 员工亲属关系 信贷客户家庭关系 一致性
轮询间隔 2秒 2秒 一致
最大轮询次数 150次 150次 一致
localStorage Key staff_fmy_relation_import_last_task cust_fmy_relation_import_last_task 命名规范一致
失败记录展示 表格+分页 表格+分页 一致
导入结果通知 $notify $notify 一致
清除历史记录 一致

5.6 差异说明

信贷客户家庭关系的核心差异

  1. 表结构差异

    • is_emp_family = 0is_cust_family = 1
    • person_id 语义为信贷客户身份证号
  2. 查询简化

    • 仅保留3个查询条件身份证号、关系类型、关系人姓名
    • 移除员工姓名关联查询
  3. 前端输入方式

    • 信贷客户身份证号:普通文本输入
    • 员工身份证号:远程搜索下拉选择
  4. 文案替换

    • 全部"员工"替换为"信贷客户"
    • 全部"亲属关系"保持不变

5.7 对比结论

信贷客户家庭关系维护功能的设计与实现完全遵循员工亲属关系维护的标准

  • 代码结构一致
  • 接口风格一致
  • 异步导入机制一致
  • 前端交互一致
  • 技术栈一致

差异仅在于

  • 业务语义调整(信贷客户 vs 员工)
  • 查询条件简化
  • person_id 输入方式调整

六、实施计划

6.1 开发任务清单

后端开发

  1. 创建实体类 CcdiCustFmyRelation.java
  2. 创建DTO类Add/Edit/Query
  3. 创建VO类List/Detail/ImportFailure
  4. 创建Excel类 CcdiCustFmyRelationExcel.java
  5. 创建Mapper接口和XML映射
  6. 创建Service接口和实现类
  7. 创建ImportService接口和实现类
  8. 创建Controller控制器
  9. 配置权限标识

前端开发

  1. 创建API接口文件 ccdiCustFmyRelation.js
  2. 创建主页面组件 index.vue
  3. 实现查询列表功能
  4. 实现新增/编辑功能
  5. 实现详情查看功能
  6. 实现删除功能
  7. 实现导入功能(含异步轮询)
  8. 实现导出功能

系统配置

  1. 创建数据库表
  2. 配置菜单权限
  3. 分配角色权限
  4. 配置按钮权限

6.2 测试计划

单元测试

  • Service层数据验证
  • Mapper层SQL查询
  • 导入重复校验

功能测试

  • CRUD基本操作
  • 导入导出功能
  • 异步导入状态查询
  • 失败记录查看

集成测试

  • 前后端联调
  • 权限控制测试
  • Excel模板测试

性能测试

  • 大数据量导入1000+条)
  • 并发导入测试
  • 分页查询性能

6.3 部署清单

  1. 数据库表创建
  2. 后端代码部署
  3. 前端代码部署
  4. 菜单权限配置
  5. 功能测试验证

七、附录

7.1 字典配置

复用现有字典

  • ccdi_relation_type:关系类型(配偶、子女、父母、兄弟姐妹、其他)
  • ccdi_indiv_gender:性别(男、女、其他)
  • ccdi_certificate_type:证件类型(身份证、护照、军官证等)

7.2 权限配置

菜单标识ccdi:custFmyRelation

权限标识清单

  • ccdi:custFmyRelation:list - 查询列表
  • ccdi:custFmyRelation:query - 查询详情
  • ccdi:custFmyRelation:add - 新增
  • ccdi:custFmyRelation:edit - 修改
  • ccdi:custFmyRelation:remove - 删除
  • ccdi:custFmyRelation:export - 导出
  • ccdi:custFmyRelation:import - 导入

7.3 API文档生成

使用SpringDoc自动生成Swagger文档

  • 访问地址:/swagger-ui/index.html
  • 接口分组:信贷客户家庭关系管理
  • 所有接口包含完整的参数说明和响应示例

八、设计总结

本设计方案完全遵循若依框架规范和员工亲属关系维护的实现标准,确保:

代码一致性:命名规范、包结构、分层架构完全一致 技术一致性:技术栈、组件选型、实现方式完全一致 交互一致性:前端交互、导入导出、异步处理完全一致 功能完整性CRUD、导入导出、权限控制一应俱全

核心差异

  • 业务语义:信贷客户 vs 员工
  • 查询简化3个条件 vs 6个条件
  • 输入方式:文本输入 vs 远程搜索

该设计方案可以直接进入开发实施阶段,开发完成后将与员工亲属关系维护功能进行最终对比验证,确保实现效果完全一致。