# 员工资产导入与亲属资产导入拆分设计

## 背景

当前员工信息维护页 [ccdiBaseStaff/index.vue](/D:/ccdi/ccdi/ruoyi-ui/src/views/ccdiBaseStaff/index.vue) 与员工亲属关系维护页 [ccdiStaffFmyRelation/index.vue](/D:/ccdi/ccdi/ruoyi-ui/src/views/ccdiStaffFmyRelation/index.vue) 共用了 `/ccdi/assetInfo/*` 资产导入接口，导致两类业务边界混淆：

- 员工页的“导入资产信息”应只导入员工本人资产
- 亲属页的“导入亲属资产信息”应只导入员工亲属资产
- 当前共享接口无法同时满足这两条规则，模板、权限、失败文案也容易串用

用户已确认：

- 保留员工页“导入资产信息”按钮
- 员工资产导入与亲属资产导入必须彻底拆分
- 员工亲属资产导入功能只能导入员工亲属的资产信息，不能更新员工的

## 目标

- 将员工资产导入与亲属资产导入拆成两条独立链路
- 员工页只支持员工本人资产导入
- 亲属页只支持亲属资产导入
- 模板、接口、权限、失败提示、任务状态缓存全部分离

## 非目标

- 不改造员工资产手工维护功能
- 不改造亲属资产手工维护功能
- 不新增独立资产菜单页面
- 不调整 `ccdi_asset_info` 表结构

## 现状

当前共用资产导入能力集中在：

- 前端 API：[ccdiAssetInfo.js](/D:/ccdi/ccdi/ruoyi-ui/src/api/ccdiAssetInfo.js)
- 员工页调用点：[ccdiBaseStaff/index.vue](/D:/ccdi/ccdi/ruoyi-ui/src/views/ccdiBaseStaff/index.vue)
- 亲属页调用点：[ccdiStaffFmyRelation/index.vue](/D:/ccdi/ccdi/ruoyi-ui/src/views/ccdiStaffFmyRelation/index.vue)
- 后端控制器：[CcdiAssetInfoController.java](/D:/ccdi/ccdi/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/controller/CcdiAssetInfoController.java)
- 后端导入服务：[CcdiAssetInfoImportServiceImpl.java](/D:/ccdi/ccdi/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiAssetInfoImportServiceImpl.java)

问题点：

- 员工页与亲属页共用同一上传地址 `/ccdi/assetInfo/importData`
- 共用同一模板下载地址 `/ccdi/assetInfo/importTemplate`
- 共用同一任务状态与失败记录查询入口
- 共用同一导入匹配规则，无法表达“员工页仅员工本人、亲属页仅亲属”

## 方案对比

### 方案一：员工资产导入、亲属资产导入完全拆分

- 员工页新增一套独立导入接口
- 亲属页保留现有 `/ccdi/assetInfo/*`
- 两边各自使用独立模板、权限、校验和失败文案

优点：

- 业务边界最清晰
- 后续维护风险最低
- 模板与前端交互不再串用

缺点：

- 需要新增一套员工资产导入 controller/service/api

### 方案二：继续共用接口，通过 `mode` 区分

- 前端调用同一接口
- 后端通过 `mode=employee/family` 分支处理

优点：

- 代码新增较少

缺点：

- 控制器和 service 内分支复杂
- 模板、权限、提示文案仍容易混淆
- 后续扩展时回归风险高

### 方案三：仅修前端入口文案

优点：

- 改动最小

缺点：

- 业务问题未解决
- 实际导入规则仍然混乱

## 最终方案

采用方案一：员工资产导入与亲属资产导入完全拆分。

### 员工资产导入

- 页面入口：员工信息维护页
- 独立接口：
  - `POST /ccdi/baseStaff/asset/importTemplate`
  - `POST /ccdi/baseStaff/asset/importData`
  - `GET /ccdi/baseStaff/asset/importStatus/{taskId}`
  - `GET /ccdi/baseStaff/asset/importFailures/{taskId}`
- 独立前端 API 文件：`ruoyi-ui/src/api/ccdiBaseStaffAsset.js`
- 仅允许导入员工本人资产
- 模板第一列要求填写员工身份证号
- 导入成功后强制写入：
  - `family_id = 员工身份证号`
  - `person_id = 员工身份证号`

### 亲属资产导入

- 页面入口：员工亲属关系维护页
- 保留现有接口：
  - `POST /ccdi/assetInfo/importTemplate`
  - `POST /ccdi/assetInfo/importData`
  - `GET /ccdi/assetInfo/importStatus/{taskId}`
  - `GET /ccdi/assetInfo/importFailures/{taskId}`
- 仅允许导入员工亲属资产
- 模板第一列要求填写亲属证件号
- 导入成功后强制写入：
  - `family_id = 关联员工证件号`
  - `person_id = 亲属证件号`

## 后端设计

### 新增员工资产导入控制面

新增：

- `controller/CcdiBaseStaffAssetImportController.java`
- `service/ICcdiBaseStaffAssetImportService.java`
- `service/impl/CcdiBaseStaffAssetImportServiceImpl.java`
- `domain/excel/CcdiBaseStaffAssetInfoExcel.java`
- `domain/vo/BaseStaffAssetImportFailureVO.java`

员工资产导入匹配规则：

- 仅根据 `ccdi_base_staff.id_card` 匹配
- 若未匹配到员工，导入失败
- 不再兜底匹配亲属关系表
- 若命中员工，则写入 `family_id = person_id = id_card`

亲属资产导入规则调整：

- [CcdiAssetInfoImportServiceImpl.java](/D:/ccdi/ccdi/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiAssetInfoImportServiceImpl.java) 只保留亲属资产逻辑
- 仅根据 `ccdi_staff_fmy_relation.relation_cert_no` 匹配
- 不再匹配员工本人身份证号

### 权限设计

- 员工资产导入接口：`ccdi:employee:import`
- 亲属资产导入接口：`ccdi:staffFmyRelation:import`

禁止再使用同时兼容两个权限的写法，以免接口语义再次混淆。

## 前端设计

### 员工页

[ccdiBaseStaff/index.vue](/D:/ccdi/ccdi/ruoyi-ui/src/views/ccdiBaseStaff/index.vue) 改为：

- 上传地址改为员工资产专用接口
- 模板下载改为员工资产模板
- 任务状态和失败记录查询改为员工资产专用接口
- 提示文案明确为“员工资产数据导入”

### 亲属页

[ccdiStaffFmyRelation/index.vue](/D:/ccdi/ccdi/ruoyi-ui/src/views/ccdiStaffFmyRelation/index.vue) 保持：

- 上传地址仍为 `/ccdi/assetInfo/importData`
- 模板下载仍为亲属资产模板
- 文案继续强调“亲属资产”

## 模板设计

员工资产模板：

- 文件名：`员工资产信息模板_xxx.xlsx`
- 首列表头：`员工身份证号*`

亲属资产模板：

- 文件名：`亲属资产信息模板_xxx.xlsx`
- 首列表头：`亲属证件号*`

## 校验规则

### 员工资产导入

- 员工身份证号不能为空
- 资产必填字段不能为空
- 员工身份证号必须存在于 `ccdi_base_staff.id_card`
- 若填写的是亲属证件号或其他未命中的证件号，直接失败

建议失败文案：

- `未找到员工资产归属员工`
- 或更明确的 `员工资产导入仅支持员工本人证件号`

### 亲属资产导入

- 亲属证件号不能为空
- 资产必填字段不能为空
- 亲属证件号必须存在于 `ccdi_staff_fmy_relation.relation_cert_no`
- 若填写员工本人身份证号且不存在亲属关系映射，直接失败
- 若同一亲属证件号匹配多个员工关系，失败并提示归属不唯一

## 测试要求

后端：

- 员工资产导入：员工本人证件号成功
- 员工资产导入：亲属证件号失败
- 亲属资产导入：亲属证件号成功
- 亲属资产导入：员工本人证件号失败
- 两套模板标题和首列表头不同
- 两套接口权限分别正确

前端：

- 员工页使用员工资产专用上传地址
- 亲属页继续使用 `/ccdi/assetInfo/*`
- 员工页下载员工资产模板
- 亲属页下载亲属资产模板
- 员工页和亲属页的失败记录弹窗文案不混淆

## 风险与回滚

风险：

- 当前仓库内已有共享资产导入代码，拆分时容易遗漏某一处调用
- 若只拆后端不拆前端，页面会继续指向旧接口
- 若模板文案未同步，用户仍可能误用模板

回滚策略：

- 独立提交员工资产导入新增改动
- 独立提交亲属资产导入收敛改动
- 任一阶段出现回归，可按提交粒度回退

## 实现状态

- 2026-03-13 已完成后端拆分实现
- 已新增员工资产独立导入接口 `/ccdi/baseStaff/asset/*`
- 已将 `/ccdi/assetInfo/*` 收敛为亲属资产专用接口
- 已通过后端定向测试验证员工与亲属两套导入链路、模板名称和失败文案拆分生效
- 2026-03-13 已完成前端拆分实现
- 员工页已切换为员工资产专用前端 API `ruoyi-ui/src/api/ccdiBaseStaffAsset.js`
- 员工页上传地址、模板下载、状态轮询与失败记录查询已全部改为 `/ccdi/baseStaff/asset/*`
- 亲属页继续保持 `/ccdi/assetInfo/*` 导入链路与“亲属资产”提示文案
- 已通过 4 个前端静态契约测试验证员工页与亲属页导入交互隔离生效
