# 员工亲属资产维护设计

## 背景

现有员工亲属关系维护页面 `http://localhost/maintain/staffFmyRelation` 已支持员工亲属关系的新增、编辑、删除、详情、导入导出，但尚不支持维护亲属名下资产信息。

当前仓库中已有员工资产维护设计文档 [2026-03-12-employee-asset-maintenance-design.md](/D:/ccdi/ccdi/docs/design/2026-03-12-employee-asset-maintenance-design.md)，其核心约束是通过 `family_id` 表示归属员工，通过 `person_id` 表示资产实际持有人。本次需求需要将该能力调整到“员工亲属关系维护页面”中，并明确仅维护亲属资产，不包含员工本人资产。

本次设计于 2026-03-12 确认以下业务口径：

- 维护入口为员工亲属关系页面 `staffFmyRelation`
- 仅维护当前亲属关系对应的亲属资产，不包含员工本人资产
- 不新增独立的亲属资产菜单页面
- 不新增 `relation_id` 等额外资产归属字段
- `family_id` 存员工证件号，对应亲属关系中的 `person_id`
- `person_id` 存亲属证件号，对应亲属关系中的 `relation_cert_no`
- 亲属资产中的 `person_id` 不强制要求为身份证号，存证件号即可
- 编辑亲属关系时，`relationCertType` 与 `relationCertNo` 禁止修改

## 目标

- 在员工亲属关系维护页中新增亲属资产维护能力
- 在亲属关系新增/编辑弹窗中支持维护当前亲属名下资产
- 在亲属关系详情弹窗中展示当前亲属全部资产
- 在亲属关系列表页新增亲属资产导入入口，并复用现有异步导入交互
- 删除亲属关系时同步删除该亲属名下资产

## 非目标

- 不维护员工本人资产
- 不新增独立“亲属资产维护”菜单
- 不新增 `relation_id`
- 不在列表页直接展开显示资产明细
- 不改造现有亲属关系查询条件和分页结构

## 现状

当前员工亲属关系维护能力主要集中在以下位置：

- 前端页面：`ruoyi-ui/src/views/ccdiStaffFmyRelation/index.vue`
- 前端接口：`ruoyi-ui/src/api/ccdiStaffFmyRelation.js`
- 后端控制器：`ccdi-info-collection/src/main/java/com/ruoyi/info/collection/controller/CcdiStaffFmyRelationController.java`
- 后端服务：`ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiStaffFmyRelationServiceImpl.java`
- 后端映射：`ccdi-info-collection/src/main/resources/mapper/info/collection/CcdiStaffFmyRelationMapper.xml`

当前一条亲属关系记录的关键字段如下：

- `person_id`：员工证件号
- `relation_cert_type`：亲属证件类型
- `relation_cert_no`：亲属证件号

数据库对 `ccdi_staff_fmy_relation` 设有唯一约束 `uk_person_cert(person_id, relation_cert_no)`，因此一条亲属关系在业务上可以稳定地通过“员工证件号 + 亲属证件号”定位，这也正好可以复用为亲属资产的归属键。

## 方案对比

### 方案一：在亲属关系弹窗内嵌资产子表聚合维护

- 亲属关系详情接口聚合返回 `assetInfoList`
- 亲属关系新增、编辑时同步保存资产列表
- 亲属资产导入采用独立接口，但交互复用现有导入模式

优点：

- 最符合“在亲属关系维护页面维护亲属资产”的使用预期
- 页面上下文最完整，用户不需要在多个弹窗间切换
- 删除亲属关系时级联删除资产最直接

缺点：

- 需要扩展 DTO、VO、Service 和前端弹窗结构

### 方案二：在亲属关系页增加“维护资产”二级弹窗

- 亲属关系页保留现状
- 通过“维护资产”按钮打开独立二级弹窗编辑资产

优点：

- 对现有亲属关系表单侵入较小

缺点：

- 交互割裂
- 用户维护一条亲属关系时无法同时看到关系信息与资产信息

### 方案三：只新增资产查看与导入，不支持页面内编辑

优点：

- 开发量最小

缺点：

- 不满足“添加维护功能”的核心诉求

## 最终方案

采用方案一：在员工亲属关系维护页的新增、编辑、详情弹窗中内嵌“亲属资产信息”分区，由亲属关系接口作为聚合接口返回和保存 `assetInfoList`；同时新增“亲属资产导入”独立接口，并沿用现有亲属关系导入的异步处理与失败记录交互。

## 数据模型设计

### 资产归属规则

亲属资产的归属键定义如下：

- `family_id = 当前亲属关系.person_id`
- `person_id = 当前亲属关系.relation_cert_no`

含义如下：

- `family_id` 表示归属员工
- `person_id` 表示亲属资产实际持有人
- 当前页面只查询和保存满足 `family_id = 员工证件号` 且 `person_id = 亲属证件号` 的资产

### 数据表

新增 `ccdi_asset_info` 表，字段来源参考资产设计文档和 `assets/资产信息表.csv`，本次继续沿用以下关键字段：

- `asset_id`：`BIGINT` 自增主键
- `family_id`：`VARCHAR(100)`，保存员工证件号
- `person_id`：`VARCHAR(100)`，保存亲属证件号
- `asset_main_type`
- `asset_sub_type`
- `asset_name`
- `ownership_ratio`
- `purchase_eval_date`
- `original_value`
- `current_value`
- `valuation_date`
- `asset_status`
- `remarks`
- `create_by`
- `create_time`
- `update_by`
- `update_time`

建议索引：

- `idx_family_id(family_id)`
- `idx_person_id(person_id)`
- `idx_family_person(family_id, person_id)`

## 后端设计

### 新增资产模块对象

在 `ccdi-info-collection` 中新增：

- `domain/CcdiAssetInfo.java`
- `domain/dto/CcdiAssetInfoDTO.java`
- `domain/vo/CcdiAssetInfoVO.java`
- `domain/excel/CcdiAssetInfoExcel.java`
- `domain/vo/AssetImportFailureVO.java`
- `mapper/CcdiAssetInfoMapper.java`
- `service/ICcdiAssetInfoService.java`
- `service/ICcdiAssetInfoImportService.java`
- `service/impl/CcdiAssetInfoServiceImpl.java`
- `service/impl/CcdiAssetInfoImportServiceImpl.java`
- `controller/CcdiAssetInfoController.java`
- `resources/mapper/info/collection/CcdiAssetInfoMapper.xml`

### 扩展亲属关系聚合接口

扩展现有亲属关系 DTO 和 VO：

- `CcdiStaffFmyRelationAddDTO.assetInfoList`
- `CcdiStaffFmyRelationEditDTO.assetInfoList`
- `CcdiStaffFmyRelationVO.assetInfoList`

聚合规则：

- 查询详情时，按当前亲属关系的 `personId + relationCertNo` 查询资产列表并组装到 `assetInfoList`
- 新增亲属关系时，先保存关系，再为资产统一回填 `family_id`、`person_id`
- 编辑亲属关系时，更新关系主信息，再按当前固定归属键重建资产列表
- 删除亲属关系时，先删资产再删亲属关系，整体使用事务

### 编辑时的特殊约束

编辑亲属关系时：

- 前端禁止修改 `relationCertType`
- 前端禁止修改 `relationCertNo`
- 后端读取旧记录后做防御校验
- 若请求中的 `relationCertType` 或 `relationCertNo` 与旧值不一致，直接拒绝保存并提示“关系人证件类型/证件号码不允许修改”

### 资产保存策略

编辑当前亲属关系时不要求前端传资产行状态，直接按“当前完整列表覆盖”处理：

- 查询当前亲属关系旧记录
- 校验亲属证件类型、亲属证件号未被修改
- 更新亲属关系主信息
- 按 `family_id = personId` 且 `person_id = relationCertNo` 删除旧资产
- 将当前提交的 `assetInfoList` 统一回填归属键后批量插入

由于编辑时禁止修改亲属证件类型和证件号，因此不需要处理资产跨亲属迁移问题。

### 资产导入接口

新增独立资产导入接口：

- `POST /ccdi/assetInfo/importTemplate`
- `POST /ccdi/assetInfo/importData`
- `GET /ccdi/assetInfo/importStatus/{taskId}`
- `GET /ccdi/assetInfo/importFailures/{taskId}`

导入归属规则：

- 模板中 `person_id` 填亲属证件号
- 模板中不要求填写 `family_id`
- 系统通过 `ccdi_staff_fmy_relation.relation_cert_no = person_id` 反查亲属关系
- 若能唯一匹配，则自动回填对应记录的 `person_id` 到 `family_id`
- 若找不到匹配关系，导入失败
- 若匹配到多条不同员工关系，导入失败，原因记为“亲属资产归属员工不唯一”

## 前端设计

### 列表页

在 `ruoyi-ui/src/views/ccdiStaffFmyRelation/index.vue` 按钮区新增：

- “导入亲属资产信息”按钮
- “查看亲属资产导入失败记录”按钮

资产导入状态全部独立维护：

- 独立上传弹窗状态
- 独立轮询定时器
- 独立任务 ID
- 独立 `localStorage key`
- 独立失败记录弹窗和分页状态

### 新增和编辑弹窗

在现有亲属关系弹窗的“基本信息”下方新增“亲属资产信息”分区，采用可编辑子表。

子表字段：

- 资产大类
- 资产小类
- 资产名称
- 产权占比
- 购买/评估日期
- 资产原值
- 当前估值
- 估值截止日期
- 资产状态
- 备注
- 操作

交互规则：

- 分区右侧提供“新增资产”按钮
- 每行支持删除
- 编辑时回显 `assetInfoList`
- 前端不展示 `asset_id`、`family_id`、`person_id`
- 新增资产前若当前尚未录入亲属证件类型或证件号码，则禁用新增资产并提示“请先填写关系人证件信息”
- 编辑时 `relationCertType`、`relationCertNo` 置灰禁用

### 详情弹窗

在详情弹窗中新增“亲属资产信息”区域，使用只读表格展示当前亲属名下资产。

若无资产数据，显示“暂无亲属资产信息”。

## 数据流

### 新增亲属关系

前端提交亲属关系基础信息和 `assetInfoList`，后端保存亲属关系后，按当前记录的 `personId` 与 `relationCertNo` 为每条资产回填 `family_id`、`person_id`，再批量保存。

### 编辑亲属关系

前端拉取详情回显基础信息和资产列表，用户修改后提交完整列表。后端校验证件类型、证件号码未变更后，按当前亲属关系归属键重建资产明细。

### 查询详情

后端查询亲属关系主信息，再按 `family_id = personId` 且 `person_id = relationCertNo` 查询资产列表并一并返回。

### 删除亲属关系

后端先删除当前亲属名下资产，再删除亲属关系主记录。

### 导入亲属资产

前端上传亲属资产 Excel，后端根据 `person_id = 亲属证件号` 识别归属亲属关系并自动回填 `family_id`，异步校验并批量插入资产数据，失败记录通过独立入口查看。

## 校验规则

### 亲属关系保存时

- 沿用现有亲属关系校验规则
- 编辑时禁止修改 `relationCertType`
- 编辑时禁止修改 `relationCertNo`
- `assetInfoList` 中整行为空的数据自动过滤

### 亲属资产保存时

- 资产必填项：`assetMainType`、`assetSubType`、`assetName`、`currentValue`、`assetStatus`
- 数值字段必须合法
- 日期字段必须合法
- 后端不信任前端传入的归属字段，统一强制回填：
  - `family_id = 当前亲属关系.personId`
  - `person_id = 当前亲属关系.relationCertNo`

## 异常处理

- 编辑亲属关系时，若请求试图修改 `relationCertType` 或 `relationCertNo`，后端直接报错
- 删除亲属关系与删除资产使用同一事务，避免数据不一致
- 查询详情时若资产查询异常，整体接口返回失败，避免前端收到半残数据
- 亲属资产导入时，若亲属证件号无法匹配亲属关系，记录失败原因
- 亲属资产导入时，若一个亲属证件号匹配多个员工关系，记录“亲属资产归属员工不唯一”
- 前端提示文案中明确区分“亲属关系导入”和“亲属资产导入”

## 验收标准

- `staffFmyRelation` 新增/编辑弹窗中可新增、编辑、删除亲属资产
- 编辑亲属关系时，关系人证件类型和证件号码不可修改
- 详情弹窗中可查看该亲属全部资产信息
- 删除亲属关系后，对应亲属资产同步删除
- 亲属资产支持独立导入，并可查看亲属资产导入失败记录
- 亲属资产导入模板不要求填写 `family_id`
- 系统根据 `person_id = 亲属证件号` 自动回填归属员工证件号到 `family_id`

## 测试建议

- 新增亲属关系但不维护资产
- 新增亲属关系并维护单条、多条资产
- 编辑亲属关系时新增、修改、删除资产
- 验证编辑时不能修改亲属证件类型与证件号码
- 删除亲属关系时资产级联删除
- 亲属资产导入成功、无法匹配、匹配不唯一三类场景
