# 员工实体关系信息维护功能设计文档

## 一、功能概述

### 1.1 功能描述

员工实体关系信息维护功能用于管理员工与企业之间的关联关系，记录员工（或员工家庭关联人）在不同企业中担任的职务信息。该功能支持增删改查、批量导入导出等操作，完全参照采购交易管理和招聘信息功能的业务逻辑和UI交互。

### 1.2 参照标准

- 后端业务逻辑：完全参照 `CcdiPurchaseTransaction`（采购交易管理）
- 前端UI交互：完全参照 `ccdiPurchaseTransaction/index.vue`
- 异步导入机制：完全参照采购交易的异步导入流程

## 二、数据库设计

### 2.1 表结构

基于 `ccdi_staff_enterprise_relation.csv` 定义：

| 序号 | 字段名                  | 类型          | 默认值 | 是否可为空 | 是否主键 | 注释                         |
|----|----------------------|-------------|-----|-------|------|----------------------------|
| 1  | id                   | BIGINT      | 自增  | 否     | 是    | 主键，唯一标识                    |
| 2  | person_id            | VARCHAR     | -   | 否     | 否    | 身份证号，关联员工表的外键              |
| 3  | relation_person_post | VARCHAR     | -   | 是     | 否    | 关联人在企业的职务：股东、法人、高管、实际控制人等  |
| 4  | social_credit_code   | VARCHAR     | -   | 否     | 否    | 统一社会信用代码，关联企业主体信息表的外键      |
| 5  | enterprise_name      | VARCHAR     | -   | 是     | 否    | 企业名称（冗余存储，便于快速查询）          |
| 6  | status               | INT         | 1   | 否     | 否    | 关系是否有效：0 - 无效、1 - 有效（默认有效） |
| 7  | remark               | TEXT        | -   | 是     | 否    | 补充说明                       |
| 8  | data_source          | VARCHAR(50) | -   | 是     | 否    | 数据来源                       |
| 9  | is_employee          | TINYINT(1)  | 0   | 否     | 否    | 是否是员工：0-否 1-是              |
| 10 | is_emp_family        | TINYINT(1)  | 1   | 否     | 否    | 是否是员工家庭关联人：0-否 1-是         |
| 11 | is_customer          | TINYINT(1)  | 0   | 否     | 否    | 是否是信贷客户：0-否 1-是            |
| 12 | is_cust_family       | TINYINT(1)  | 0   | 否     | 否    | 是否是信贷客户关联人：0-否 1-是         |
| 13 | created_by           | VARCHAR     | -   | 否     | 否    | 记录创建人                      |
| 14 | updated_by           | VARCHAR     | -   | 是     | 否    | 记录更新人                      |
| 15 | create_time          | DATETIME    | -   | 否     | 否    | 记录创建时间                     |
| 16 | update_time          | DATETIME    | -   | 否     | 否    | 记录更新时间                     |

### 2.2 唯一性约束

- 业务唯一性：`person_id + social_credit_code` 组合必须唯一
- 包含所有status值（0和1）的记录
- 新增和导入时需要校验唯一性

## 三、后端设计

### 3.1 模块结构

```
com.ruoyi.ccdi
├── controller
│   └── CcdiStaffEnterpriseRelationController.java
├── service
│   ├── ICcdiStaffEnterpriseRelationService.java
│   ├── ICcdiStaffEnterpriseRelationImportService.java
│   └── impl
│       ├── CcdiStaffEnterpriseRelationServiceImpl.java
│       └── CcdiStaffEnterpriseRelationImportServiceImpl.java
├── mapper
│   └── CcdiStaffEnterpriseRelationMapper.java
└── domain
    ├── CcdiStaffEnterpriseRelation.java (实体类)
    ├── vo
    │   ├── CcdiStaffEnterpriseRelationVO.java (查询返回)
    │   ├── ImportResultVO.java (导入结果)
    │   ├── ImportStatusVO.java (导入状态)
    │   └── StaffEnterpriseRelationImportFailureVO.java (导入失败记录)
    ├── dto
    │   ├── CcdiStaffEnterpriseRelationAddDTO.java (新增)
    │   ├── CcdiStaffEnterpriseRelationEditDTO.java (编辑)
    │   └── CcdiStaffEnterpriseRelationQueryDTO.java (查询)
    └── excel
        └── CcdiStaffEnterpriseRelationExcel.java (导入导出)
```

### 3.2 Controller接口定义

**基础路径：** `/ccdi/staffEnterpriseRelation`

| 方法     | 路径                       | 说明       | 权限                                  |
|--------|--------------------------|----------|-------------------------------------|
| GET    | /list                    | 分页查询列表   | ccdi:staffEnterpriseRelation:list   |
| POST   | /export                  | 导出       | ccdi:staffEnterpriseRelation:export |
| GET    | /{id}                    | 获取详情     | ccdi:staffEnterpriseRelation:query  |
| POST   | /                        | 新增       | ccdi:staffEnterpriseRelation:add    |
| PUT    | /                        | 修改       | ccdi:staffEnterpriseRelation:edit   |
| DELETE | /{ids}                   | 删除       | ccdi:staffEnterpriseRelation:remove |
| POST   | /importTemplate          | 下载导入模板   | -                                   |
| POST   | /importData              | 异步导入     | ccdi:staffEnterpriseRelation:import |
| GET    | /importStatus/{taskId}   | 查询导入状态   | ccdi:staffEnterpriseRelation:import |
| GET    | /importFailures/{taskId} | 查询导入失败记录 | ccdi:staffEnterpriseRelation:import |

### 3.3 核心业务逻辑

#### 3.3.1 唯一性校验

```java
// 新增时校验
if (mapper.existsByPersonIdAndSocialCreditCode(personId, socialCreditCode)) {
    throw new RuntimeException("该员工与企业的关系已存在");
}
```

#### 3.3.2 默认值设置

```java
entity.setStatus(1);  // 有效
entity.setIsEmployee(0);
entity.setIsEmpFamily(1);
entity.setIsCustomer(0);
entity.setIsCustFamily(0);
entity.setDataSource("MANUAL");  // 或 "IMPORT"
```

#### 3.3.3 异步导入流程

1. 接收文件 → 解析Excel → 生成UUID任务ID → 立即返回
2. @Async异步方法：
    - 批量查询已存在的 person_id + social_credit_code 组合
    - 遍历校验，分类成功/失败
    - 批量插入成功数据（500条/批）
    - 失败记录存Redis（7天过期）
    - 更新导入状态到Redis
3. 前端轮询查询状态（2秒/次，最多150次）

#### 3.3.4 Redis存储结构

```
import:staffEnterpriseRelation:{taskId}           // 导入状态（Hash）
import:staffEnterpriseRelation:{taskId}:failures  // 失败记录（List，JSON序列化）
```

## 四、前端设计

### 4.1 文件结构

```
ruoyi-ui/src/
├── views
│   └── ccdiStaffEnterpriseRelation
│       └── index.vue
└── api
    └── ccdiStaffEnterpriseRelation.js
```

### 4.2 列表页设计

#### 4.2.1 查询表单

- 身份证号（模糊查询）
- 统一社会信用代码（模糊查询）
- 企业名称（模糊查询）
- 状态下拉选择（有效/无效）
- 搜索、重置按钮

#### 4.2.2 操作按钮

- 新增
- 导入
- 导出
- 查看导入失败记录（条件显示）
- 右侧工具栏（显示搜索、刷新）

#### 4.2.3 表格列

| 列名        | 字段                 | 说明                    |
|-----------|--------------------|-----------------------|
| 选择框       | -                  | 多选                    |
| 身份证号      | personId           | show-overflow-tooltip |
| 企业名称      | enterpriseName     | show-overflow-tooltip |
| 关联人在企业的职务 | relationPersonPost | -                     |
| 状态        | status             | 字典翻译                  |
| 数据来源      | dataSource         | 字典翻译                  |
| 创建时间      | createTime         | 格式化                   |
| 操作        | -                  | 详情、编辑、删除              |

### 4.3 新增/编辑对话框

**宽度：** 800px

**表单字段：**

- 身份证号：可搜索下拉（el-select + remote + filterable）
- 统一社会信用代码：输入框 + 18位格式校验
- 企业名称：输入框 + 必填
- 关联人在企业的职务：输入框 + 可选
- 状态：下拉选择 + 默认值1（有效）
- 补充说明：textarea + 可选

**不显示字段：**

- data_source（后端自动设置）
- is_employee、is_emp_family、is_customer、is_cust_family（后端自动设置）

### 4.4 导入功能

#### 4.4.1 导入对话框

- 拖拽上传区域
- 模板下载链接
- 仅允许 .xlsx / .xls 格式

#### 4.4.2 导入流程

1. 文件上传成功 → 显示通知"导入任务已提交"
2. 每2秒轮询查询导入状态
3. 完成后显示结果通知：
    - SUCCESS：全部成功！共导入N条数据
    - PARTIAL_SUCCESS：成功N条，失败M条
4. 如果有失败记录，显示"查看导入失败记录"按钮

#### 4.4.3 查看失败记录

- 点击按钮弹窗显示失败列表
- 失败记录包含：personId、socialCreditCode、enterpriseName、errorMessage
- 支持分页
- 支持清除历史记录

## 五、数据字典配置

### 5.1 关系状态字典

**字典类型：** `ccdi_relation_status`

| 字典值 | 字典标签 | 排序 |
|-----|------|----|
| 0   | 无效   | 2  |
| 1   | 有效   | 1  |

### 5.2 数据来源字典

**字典类型：** `ccdi_data_source`

| 字典值    | 字典标签 | 排序 |
|--------|------|----|
| MANUAL | 手动录入 | 1  |
| SYSTEM | 系统同步 | 2  |
| IMPORT | 批量导入 | 3  |
| API    | 接口获取 | 4  |

## 六、Excel导入模板

### 6.1 模板列定义

| 列名        | 字段名                | 是否必填 | 校验规则        | 说明          |
|-----------|--------------------|------|-------------|-------------|
| 身份证号      | personId           | 是    | 18位身份证格式    | 关联员工表       |
| 统一社会信用代码  | socialCreditCode   | 是    | 18位统一信用代码格式 | 关联企业表       |
| 企业名称      | enterpriseName     | 是    | 最大长度200     | 冗余存储        |
| 关联人在企业的职务 | relationPersonPost | 否    | 最大长度100     | 如：股东、法人、高管等 |
| 补充说明      | remark             | 否    | TEXT类型      | 可选填写        |

### 6.2 后端自动设置

- status = 1（有效）
- data_source = "IMPORT"
- is_employee = 0
- is_emp_family = 1
- is_customer = 0
- is_cust_family = 0

### 6.3 导入校验规则

1. 唯一性校验：person_id + social_credit_code 组合重复则失败
2. 格式校验：身份证号18位、统一社会信用代码18位
3. 必填校验：personId、socialCreditCode、enterpriseName
4. 失败记录：记录到Redis，返回详细信息

## 七、菜单权限配置

### 7.1 菜单信息

- **菜单名称：** 员工实体关系
- **路由地址：** ccdiStaffEnterpriseRelation
- **组件路径：** ccdiStaffEnterpriseRelation/index
- **上级菜单：** 待定（根据实际菜单结构配置）

### 7.2 权限标识

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

## 八、一致性校验清单

### 8.1 后端一致性

- [ ] Controller接口定义完全一致（路径、参数、返回值）
- [ ] Service层方法命名和逻辑结构一致
- [ ] 异步导入实现方式一致（@Async、Redis存储、轮询机制）
- [ ] 批量插入分批大小一致（500条/批）
- [ ] 唯一性校验逻辑一致（先批量查询，再逐条校验）
- [ ] 失败记录存储方式一致（Redis JSON序列化，7天过期）
- [ ] 导入状态更新逻辑一致（SUCCESS/PARTIAL_SUCCESS）
- [ ] Swagger注解格式一致
- [ ] 权限注解格式一致

### 8.2 前端一致性

- [ ] 列表页布局结构一致（查询表单、按钮栏、表格、分页）
- [ ] 新增/编辑对话框布局一致
- [ ] 详情对话框使用 el-descriptions 展示
- [ ] 导入对话框一致（拖拽上传、模板下载链接）
- [ ] 导入轮询机制一致（2秒间隔、150次上限）
- [ ] 导入结果通知方式一致（$notify、不同类型）
- [ ] localStorage存储任务ID方式一致
- [ ] 查看失败记录弹窗一致
- [ ] API调用方式一致（async/await、错误处理）

## 九、技术要点

### 9.1 关键技术

- **MyBatis Plus 3.5.10**：CRUD操作和分页
- **EasyExcel**：Excel导入导出
- **@Async**：异步导入
- **Redis**：导入状态和失败记录存储
- **Swagger 3**：API文档

### 9.2 性能优化

- 批量插入：500条/批
- 批量查询已存在数据：减少数据库查询次数
- Redis缓存：减少重复查询

### 9.3 安全考虑

- 权限注解：@PreAuthorize
- SQL注入防护：使用MyBatis Plus参数绑定
- XSS防护：前端输入校验

## 十、测试要点

### 10.1 功能测试

- [ ] 新增功能：唯一性校验
- [ ] 编辑功能：修改各个字段
- [ ] 删除功能：单个删除、批量删除
- [ ] 导入功能：正常数据、重复数据、格式错误数据
- [ ] 导出功能：查询条件导出
- [ ] 查询功能：模糊查询、状态筛选

### 10.2 性能测试

- [ ] 导入1000条数据的响应时间
- [ ] 查询10万条数据的分页性能
- [ ] 并发导入的处理能力

### 10.3 兼容性测试

- [ ] 不同浏览器兼容性
- [ ] Excel 2003/2007/2010格式兼容性

## 十一、附录

### 11.1 参照文件

- **后端参照：**
    - `CcdiPurchaseTransactionController.java`
    - `CcdiPurchaseTransactionServiceImpl.java`
    - `CcdiPurchaseTransactionImportServiceImpl.java`
- **前端参照：**
    - `ruoyi-ui/src/views/ccdiPurchaseTransaction/index.vue`
    - `ruoyi-ui/src/api/ccdiPurchaseTransaction.js`

### 11.2 数据库CSV文件

- `doc/database-docs/ccdi_staff_enterprise_relation.csv`
