Files
ccdi/openspec/changes/add-employee-info/design.md

253 lines
8.0 KiB
Markdown
Raw Normal View History

## Context
员工信息维护是纪检初核系统的核心基础功能。系统需要管理银行内部员工的基础信息及其亲属关系,以便在进行纪检初核工作时能够快速查询相关人员信息。
**约束条件:**
- 必须遵循若依框架的代码规范
2026-01-30 14:15:21 +08:00
- 必须使用项目已定义的命名规范(模块前缀 `ccdi_`
- 必须支持 Excel 导入导出功能
- 亲属信息需要与员工信息关联管理
**相关方:**
- 纪检人员:查询员工及亲属信息
- 系统管理员:批量导入员工数据
- 人事部门:维护员工基础信息
## Goals / Non-Goals
### Goals
1. 提供完整的员工信息 CRUD 接口
2. 支持员工亲属信息的关联管理(一对多关系)
3. 支持 Excel 批量导入导出,导入时可同时导入亲属信息
2026-01-30 14:15:21 +08:00
4. 遵循现有代码模式(参考 `ccdi_intermediary_blacklist` 模块)
### Non-Goals
- 不涉及前端页面的实现(本次仅实现后端接口)
- 不涉及员工组织架构的复杂层级管理
- 不涉及员工权限、角色管理(使用若依现有系统)
- 不涉及亲属关系的高级查询功能
## Decisions
### 1. 数据模型设计
**决策:使用两张表存储员工和亲属信息**
```
2026-01-30 14:15:21 +08:00
ccdi_employee (员工主表)
├── employee_id (主键)
├── name (姓名)
├── teller_no (柜员号, UNIQUE)
├── org_no (所属机构号)
├── id_card (身份证号, UNIQUE)
├── phone (电话)
├── hire_date (入职时间)
├── status (状态: 0=在职, 1=离职)
└── 审计字段 (create_by, create_time, update_by, update_time)
2026-01-30 14:15:21 +08:00
ccdi_employee_relative (员工亲属表)
├── relative_id (主键)
2026-01-30 14:15:21 +08:00
├── employee_id (外键 → ccdi_employee.employee_id)
├── relative_name (亲属姓名)
├── relative_id_card (亲属身份证号)
├── relative_phone (亲属手机号)
├── relationship (与员工关系)
└── 审计字段
```
**理由:**
- 符合数据库范式设计,避免数据冗余
- 支持一对多关系(一个员工可以有多个亲属)
- 便于查询和维护
**替代方案考虑:**
- 方案2将亲属信息存储为 JSON 字段
- 优点:单表存储,查询简单
- 缺点:无法对亲属信息建索引,不支持复杂查询
- **拒绝原因**:未来可能需要按亲属信息查询
### 2. 亲属信息维护方式
**决策:在员工的新增/编辑接口中同时支持亲属信息**
```
POST /dpc/employee
{
"name": "张三",
"tellerNo": "001",
"orgNo": "1001",
"idCard": "110101199001011234",
"phone": "13800138000",
"hireDate": "2020-01-01",
"relatives": [
{
"relativeName": "李四",
"relativeIdCard": "110101199001011235",
"relativePhone": "13800138001",
"relationship": "配偶"
}
]
}
```
**理由:**
- 减少接口数量,简化前端调用
- 保证员工与亲属信息的原子性操作
- 符合业务场景(新增员工时同时录入亲属信息)
### 3. Excel 导入格式
**决策:使用多 Sheet 导入方式**
```
Sheet1: 员工信息
| 姓名 | 柜员号 | 所属机构号 | 身份证号 | 电话 | 入职时间 |
|------|--------|------------|----------|------|----------|
| 张三 | 001 | 1001 | ... | ... | 2020-01-01 |
Sheet2: 亲属信息 (可选)
| 员工身份证号 | 亲属姓名 | 亲属身份证号 | 亲属手机号 | 与员工关系 |
|--------------|----------|--------------|------------|------------|
| 110101... | 李四 | 110101... | 138... | 配偶 |
```
**理由:**
- 清晰分离员工和亲属数据
- 支持仅导入员工信息(亲属信息为可选)
- 通过员工身份证号关联两张表
**替代方案考虑:**
- 方案2单 Sheet 导入,亲属信息嵌套在员工行中
- 缺点格式复杂Excel 难以编辑
- **拒绝原因**:用户体验差
### 4. 字典数据
**决策:使用字典管理"与员工关系"字段和"员工状态"字段**
```
2026-01-30 14:15:21 +08:00
字典类型: ccdi_relative_relationship
字典数据: 配偶、父亲、母亲、子女、兄弟姐妹、其他
2026-01-30 14:15:21 +08:00
字典类型: ccdi_employee_status
字典数据: 在职(0)、离职(1)
```
**理由:**
- 符合若依框架设计模式
- 便于后续扩展关系类型
- 统一管理枚举值
### 5. 数据库约束
**决策:柜员号和身份证号添加唯一约束**
```sql
UNIQUE KEY `uk_teller_no` (`teller_no`),
UNIQUE KEY `uk_id_card` (`id_card`)
```
**理由:**
- 柜员号是员工的唯一标识,不允许重复
- 身份证号具有唯一性,不允许重复
- 防止数据重复和业务逻辑错误
### 6. 命名规范
**决策:遵循项目规范**
2026-01-30 14:15:21 +08:00
- 表名: `ccdi_employee`, `ccdi_employee_relative`
- 实体类: `CcdiEmployee`, `CcdiEmployeeRelative`
- Controller: `CcdiEmployeeController`
- 权限标识: `dpc:employee:*`
- **所有实体类、DTO、VO 类统一使用 @Data 注解**
**理由:**
2026-01-30 14:15:21 +08:00
- 与现有 `ccdi_intermediary_blacklist` 模块保持一致
- 符合项目编码规范
- @Data 注解自动生成 getter/setter代码简洁
### 7. MyBatis Plus 使用策略
**决策:区分简单 CRUD 和复杂查询的实现方式**
**简单 CRUD 操作(使用 MyBatis Plus 方法):**
- BaseMapper 提供的方法:`insert`, `deleteById`, `deleteByIds`, `updateById`, `selectById`, `selectList`, `selectCount`
- 条件构造器:`QueryWrapper`, `LambdaQueryWrapper` 用于简单条件查询
- 适用场景:单表增删改查、简单条件筛选
**复杂查询操作(使用 XML 映射):**
- 多表关联查询(员工 + 亲属信息)
- 复杂条件组合查询
- 需要自定义结果映射的查询
- 适用场景:关联查询、复杂业务查询
**示例:**
```java
// 简单查询 - 使用 MyBatis Plus
employeeMapper.selectById(id);
2026-01-30 14:15:21 +08:00
employeeMapper.selectList(new LambdaQueryWrapper<CcdiEmployee>()
.eq(CcdiEmployee::getTellerNo, tellerNo));
// 复杂查询 - 使用 XML
EmployeeWithRelativesVO selectEmployeeWithRelatives(Long id);
```
**理由:**
- 简单 CRUD 使用 MyBatis Plus 减少代码量,提高开发效率
- 复杂查询使用 XML 保持 SQL 可读性和可维护性
- 符合项目技术规范MyBatis Plus 3.5.10Spring Boot 3 适配版)
## Risks / Trade-offs
### 风险1: Excel 导入时亲属数据关联失败
**风险描述**: 导入员工和亲属信息时,若员工身份证号填写错误,亲属信息无法关联。
**缓解措施**:
- 导入时进行数据校验
- 提供详细的导入错误报告
- 支持"仅导入员工"模式,亲属信息可后续补录
### 风险2: 亲属信息数据量过大
**风险描述**: 某些员工可能有大量亲属记录,影响查询性能。
**缓解措施**:
- 建立适当的数据库索引
- 列表查询时默认不返回亲属详情
- 提供单独的亲属查询接口
### 权衡: 简化 vs 完整性
- **当前方案**: 使用两表设计,支持完整的一对多关系
- **简化方案**: 将亲属信息存储为 JSON
- **选择**: 当前方案,因为纪检场景可能需要按亲属信息查询
## Migration Plan
### 后端部署步骤
1. 执行数据库脚本,创建表和字典数据
2. 部署后端代码
3. (前端开发阶段)配置菜单和权限数据
### 回滚计划
1. 从数据库中删除新增的表和字典数据
2. 移除后端代码部署
### 前端开发注意事项
- 开发前端页面时需同步在 `sys_menu` 表中插入菜单及权限数据
- 菜单路径:信息维护 → 员工信息管理
- 权限标识:`dpc:employee:list`, `dpc:employee:query`, `dpc:employee:add`, `dpc:employee:edit`, `dpc:employee:remove`, `dpc:employee:export`, `dpc:employee:import`
## Open Questions
1. **亲属关系是否需要支持多层级?** (如:亲属的亲属)
- **当前决策**: 否,仅支持员工的直接亲属
2. **导入时是否需要支持"更新已有员工"模式?**
- **当前决策**: 是,通过柜员号或身份证号判断
3. ~~**员工离职后如何处理?**~~
- **已确认**: 增加状态字段0=在职, 1=离职)
4. ~~**身份证号和柜员号是否需要唯一性约束?**~~
- **已确认**: 两者都需要唯一约束