docs(staff-enterprise-relation): 更新API文档,添加员工姓名字段说明

- 新增员工实体关系管理API文档
- 在列表接口和详情接口响应中添加personName字段
- 说明personName通过LEFT JOIN ccdi_base_staff表获取
- 如果personId在员工信息表中不存在,personName为null
This commit is contained in:
wkc
2026-02-11 15:27:40 +08:00
parent 51efb477d8
commit fd9e208fa3
8 changed files with 3901 additions and 0 deletions

View File

@@ -0,0 +1,962 @@
# 信贷客户家庭关系维护功能实施计划
> **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
<!-- 移除员工姓名输入框只保留personIdrelationTyperelationName -->
<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`