Files
ccdi/openspec/changes/add-employee-info/design.md
2026-01-30 14:15:21 +08:00

253 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Context
员工信息维护是纪检初核系统的核心基础功能。系统需要管理银行内部员工的基础信息及其亲属关系,以便在进行纪检初核工作时能够快速查询相关人员信息。
**约束条件:**
- 必须遵循若依框架的代码规范
- 必须使用项目已定义的命名规范(模块前缀 `ccdi_`
- 必须支持 Excel 导入导出功能
- 亲属信息需要与员工信息关联管理
**相关方:**
- 纪检人员:查询员工及亲属信息
- 系统管理员:批量导入员工数据
- 人事部门:维护员工基础信息
## Goals / Non-Goals
### Goals
1. 提供完整的员工信息 CRUD 接口
2. 支持员工亲属信息的关联管理(一对多关系)
3. 支持 Excel 批量导入导出,导入时可同时导入亲属信息
4. 遵循现有代码模式(参考 `ccdi_intermediary_blacklist` 模块)
### Non-Goals
- 不涉及前端页面的实现(本次仅实现后端接口)
- 不涉及员工组织架构的复杂层级管理
- 不涉及员工权限、角色管理(使用若依现有系统)
- 不涉及亲属关系的高级查询功能
## Decisions
### 1. 数据模型设计
**决策:使用两张表存储员工和亲属信息**
```
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)
ccdi_employee_relative (员工亲属表)
├── relative_id (主键)
├── 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. 字典数据
**决策:使用字典管理"与员工关系"字段和"员工状态"字段**
```
字典类型: ccdi_relative_relationship
字典数据: 配偶、父亲、母亲、子女、兄弟姐妹、其他
字典类型: ccdi_employee_status
字典数据: 在职(0)、离职(1)
```
**理由:**
- 符合若依框架设计模式
- 便于后续扩展关系类型
- 统一管理枚举值
### 5. 数据库约束
**决策:柜员号和身份证号添加唯一约束**
```sql
UNIQUE KEY `uk_teller_no` (`teller_no`),
UNIQUE KEY `uk_id_card` (`id_card`)
```
**理由:**
- 柜员号是员工的唯一标识,不允许重复
- 身份证号具有唯一性,不允许重复
- 防止数据重复和业务逻辑错误
### 6. 命名规范
**决策:遵循项目规范**
- 表名: `ccdi_employee`, `ccdi_employee_relative`
- 实体类: `CcdiEmployee`, `CcdiEmployeeRelative`
- Controller: `CcdiEmployeeController`
- 权限标识: `dpc:employee:*`
- **所有实体类、DTO、VO 类统一使用 @Data 注解**
**理由:**
- 与现有 `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);
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. ~~**身份证号和柜员号是否需要唯一性约束?**~~
- **已确认**: 两者都需要唯一约束