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

## 一、项目概述

### 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

```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**

```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.java**（Excel导入导出）

- 使用`@DictDropdown`注解添加字典下拉框：
    - `relationType` → `ccdi_relation_type`
    - `gender` → `ccdi_indiv_gender`
    - `relationCertType` → `ccdi_certificate_type`
- 使用`@Required`注解标记必填字段
- 字段索引：0-16

**CustFmyRelationImportFailureVO.java**（导入失败记录）

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

#### 3.2.4 Mapper层

**CcdiCustFmyRelationMapper.java**

```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**（主服务接口）

```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**（导入服务接口）

```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**

```javascript
// 查询列表
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持久化

**存储内容**：

```javascript
{
  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 = 0`，`is_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 远程搜索

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