# 员工调动记录管理 API 文档

## 概述

员工调动记录管理模块提供员工调动信息的增删改查、批量导入导出功能。

**基础路径**: `/ccdi/staffTransfer`

**权限标识前缀**: `ccdi:staffTransfer`

**数据表**: `ccdi_staff_transfer`

**关联表**:

- `ccdi_base_staff` - 员工基础信息表(通过staff_id关联)
- `sys_dept` - 部门表(通过dept_id_before/after关联)

---

## API 接口列表

### 1. 查询调动记录列表

**接口地址**: `GET /ccdi/staffTransfer/list`

**权限要求**: `ccdi:staffTransfer:list`

**请求参数**:

| 参数名               | 类型      | 必填 | 说明                 |
|-------------------|---------|----|--------------------|
| staffId           | Long    | 否  | 员工ID(精确查询)         |
| staffName         | String  | 否  | 员工姓名(模糊查询)         |
| transferType      | String  | 否  | 调动类型(精确查询)         |
| deptIdBefore      | Long    | 否  | 调动前部门ID            |
| deptIdAfter       | Long    | 否  | 调动后部门ID            |
| transferDateStart | Date    | 否  | 调动开始日期(yyyy-MM-dd) |
| transferDateEnd   | Date    | 否  | 调动结束日期(yyyy-MM-dd) |
| pageNum           | Integer | 否  | 页码(默认1)            |
| pageSize          | Integer | 否  | 每页数量(默认10)         |

**响应示例**:

```json
{
  "code": 200,
  "msg": "查询成功",
  "rows": [
    {
      "id": 1,
      "staffId": 1000001,
      "staffName": "张三",
      "transferType": "PROMOTION",
      "transferTypeDesc": "升职",
      "transferSubType": "正常晋升",
      "deptIdBefore": 100,
      "deptNameBefore": "技术部",
      "gradeBefore": "P5",
      "positionBefore": "工程师",
      "salaryLevelBefore": "L1",
      "deptIdAfter": 101,
      "deptNameAfter": "研发部",
      "gradeAfter": "P6",
      "positionAfter": "高级工程师",
      "salaryLevelAfter": "L2",
      "transferDate": "2026-02-10",
      "createTime": "2026-02-10 10:00:00"
    }
  ],
  "total": 1
}
```

**响应字段说明**:

| 字段名               | 类型     | 说明         |
|-------------------|--------|------------|
| id                | Long   | 主键ID       |
| staffId           | Long   | 员工ID       |
| staffName         | String | 员工姓名(关联查询) |
| transferType      | String | 调动类型代码     |
| transferTypeDesc  | String | 调动类型描述     |
| transferSubType   | String | 调动子类型      |
| deptIdBefore      | Long   | 调动前部门ID    |
| deptNameBefore    | String | 调动前部门名称    |
| gradeBefore       | String | 调动前职级      |
| positionBefore    | String | 调动前岗位      |
| salaryLevelBefore | String | 调动前薪酬等级    |
| deptIdAfter       | Long   | 调动后部门ID    |
| deptNameAfter     | String | 调动后部门名称    |
| gradeAfter        | String | 调动后职级      |
| positionAfter     | String | 调动后岗位      |
| salaryLevelAfter  | String | 调动后薪酬等级    |
| transferDate      | Date   | 调动日期       |
| createTime        | Date   | 创建时间       |

---

### 2. 查询调动记录详情

**接口地址**: `GET /ccdi/staffTransfer/{id}`

**权限要求**: `ccdi:staffTransfer:query`

**路径参数**:

| 参数名 | 类型   | 必填 | 说明     |
|-----|------|----|--------|
| id  | Long | 是  | 调动记录ID |

**响应示例**:

```json
{
  "code": 200,
  "msg": "查询成功",
  "data": {
    "id": 1,
    "staffId": 1000001,
    "staffName": "张三",
    "transferType": "PROMOTION",
    "transferSubType": "正常晋升",
    "deptIdBefore": 100,
    "deptNameBefore": "技术部",
    "gradeBefore": "P5",
    "positionBefore": "工程师",
    "salaryLevelBefore": "L1",
    "deptIdAfter": 101,
    "deptNameAfter": "研发部",
    "gradeAfter": "P6",
    "positionAfter": "高级工程师",
    "salaryLevelAfter": "L2",
    "transferDate": "2026-02-10",
    "createdBy": "admin",
    "createTime": "2026-02-10 10:00:00",
    "updatedBy": "admin",
    "updateTime": "2026-02-10 10:00:00"
  }
}
```

---

### 3. 新增调动记录

**接口地址**: `POST /ccdi/staffTransfer`

**权限要求**: `ccdi:staffTransfer:add`

**请求体** (Content-Type: application/json):

```json
{
  "staffId": 1000001,
  "transferType": "PROMOTION",
  "transferSubType": "正常晋升",
  "deptIdBefore": 100,
  "deptNameBefore": "技术部",
  "gradeBefore": "P5",
  "positionBefore": "工程师",
  "salaryLevelBefore": "L1",
  "deptIdAfter": 101,
  "deptNameAfter": "研发部",
  "gradeAfter": "P6",
  "positionAfter": "高级工程师",
  "salaryLevelAfter": "L2",
  "transferDate": "2026-02-10"
}
```

**请求字段说明**:

| 字段名               | 类型     | 必填 | 说明               |
|-------------------|--------|----|------------------|
| staffId           | Long   | 是  | 员工ID             |
| transferType      | String | 是  | 调动类型             |
| transferSubType   | String | 否  | 调动子类型            |
| deptIdBefore      | Long   | 否  | 调动前部门ID          |
| deptNameBefore    | String | 否  | 调动前部门名称          |
| gradeBefore       | String | 否  | 调动前职级            |
| positionBefore    | String | 否  | 调动前岗位            |
| salaryLevelBefore | String | 否  | 调动前薪酬等级          |
| deptIdAfter       | Long   | 否  | 调动后部门ID          |
| deptNameAfter     | String | 否  | 调动后部门名称          |
| gradeAfter        | String | 否  | 调动后职级            |
| positionAfter     | String | 否  | 调动后岗位            |
| salaryLevelAfter  | String | 否  | 调动后薪酬等级          |
| transferDate      | Date   | 是  | 调动日期(yyyy-MM-dd) |

**响应示例**:

```json
{
  "code": 200,
  "msg": "新增成功"
}
```

---

### 4. 修改调动记录

**接口地址**: `PUT /ccdi/staffTransfer`

**权限要求**: `ccdi:staffTransfer:edit`

**请求体** (Content-Type: application/json):

```json
{
  "id": 1,
  "staffId": 1000001,
  "transferType": "PROMOTION",
  "transferSubType": "破格晋升",
  "deptIdAfter": 101,
  "deptNameAfter": "研发部",
  "gradeAfter": "P6",
  "positionAfter": "高级工程师",
  "salaryLevelAfter": "L2",
  "transferDate": "2026-02-10"
}
```

**请求字段说明**:

| 字段名  | 类型   | 必填 | 说明             |
|------|------|----|----------------|
| id   | Long | 是  | 调动记录ID         |
| 其他字段 | -    | 否  | 同新增接口,所有字段均为可选 |

**响应示例**:

```json
{
  "code": 200,
  "msg": "修改成功"
}
```

---

### 5. 删除调动记录

**接口地址**: `DELETE /ccdi/staffTransfer/{ids}`

**权限要求**: `ccdi:staffTransfer:remove`

**路径参数**:

| 参数名 | 类型     | 必填 | 说明                      |
|-----|--------|----|-------------------------|
| ids | String | 是  | 调动记录ID数组,逗号分隔(例: 1,2,3) |

**响应示例**:

```json
{
  "code": 200,
  "msg": "删除成功"
}
```

---

### 6. 导出调动记录

**接口地址**: `POST /ccdi/staffTransfer/export`

**权限要求**: `ccdi:staffTransfer:export`

**请求参数**: 同查询接口(支持按条件筛选导出)

**响应**: Excel文件(attachment)

---

### 7. 下载导入模板

**接口地址**: `POST /ccdi/staffTransfer/importTemplate`

**权限要求**: 无特殊要求

**响应**: Excel模板文件(带字典下拉框)

**模板字段说明**:

| 字段名     | 是否必填 | 说明             |
|---------|------|----------------|
| 员工工号    | 是    | 员工ID           |
| 调动类型    | 是    | 下拉选择字典         |
| 调动子类型   | 否    | 自由输入           |
| 调动前部门   | 否    | 自由输入           |
| 调动前职级   | 否    | 自由输入           |
| 调动前岗位   | 否    | 自由输入           |
| 调动前薪酬等级 | 否    | 自由输入           |
| 调动后部门   | 否    | 自由输入           |
| 调动后职级   | 否    | 自由输入           |
| 调动后岗位   | 否    | 自由输入           |
| 调动后薪酬等级 | 否    | 自由输入           |
| 调动日期    | 是    | 格式: yyyy-MM-dd |

---

### 8. 异步导入调动记录

**接口地址**: `POST /ccdi/staffTransfer/importData`

**权限要求**: `ccdi:staffTransfer:import`

**请求参数**: FormData

| 参数名           | 类型      | 必填 | 说明                  |
|---------------|---------|----|---------------------|
| file          | File    | 是  | Excel文件             |
| updateSupport | Boolean | 否  | 是否更新已存在的记录(默认false) |

**响应示例**:

```json
{
  "code": 200,
  "msg": "导入任务已提交,正在后台处理",
  "data": {
    "taskId": "abc123-def456-ghi789",
    "status": "PROCESSING",
    "message": "导入任务已提交,正在后台处理"
  }
}
```

**导入流程**:

1. 上传Excel文件
2. 后台立即返回taskId
3. 使用taskId轮询查询导入状态
4. 导入完成后查看失败记录(如有)

**导入验证规则**:

导入时会验证以下字段：

| 字段名     | 验证规则                         | 错误提示                   |
|---------|------------------------------|------------------------|
| 员工ID    | 必须在员工信息表(ccdi_base_staff)中存在 | "第N行: 员工ID XXX 不存在"    |
| 调动前部门ID | 必须在部门表(sys_dept)中存在          | "第N行: 调动前部门ID XXX 不存在" |
| 调动后部门ID | 必须在部门表(sys_dept)中存在          | "第N行: 调动后部门ID XXX 不存在" |
| 调动日期    | 必须符合yyyy-MM-dd格式             | "第N行: 调动日期格式不正确"       |

**性能优化**:

- 采用批量预验证方式，仅1次数据库查询员工ID存在性
- 从2次遍历优化为1次遍历，提升导入性能

---

### 9. 查询导入状态

**接口地址**: `GET /ccdi/staffTransfer/importStatus/{taskId}`

**权限要求**: `ccdi:staffTransfer:import`

**路径参数**:

| 参数名    | 类型     | 必填 | 说明     |
|--------|--------|----|--------|
| taskId | String | 是  | 导入任务ID |

**响应示例**:

```json
{
  "code": 200,
  "msg": "查询成功",
  "data": {
    "taskId": "abc123-def456-ghi789",
    "status": "COMPLETED",
    "total": 100,
    "successCount": 95,
    "failureCount": 5,
    "message": "导入完成"
  }
}
```

**状态说明**:

| 状态         | 说明   |
|------------|------|
| PENDING    | 等待处理 |
| PROCESSING | 处理中  |
| COMPLETED  | 处理完成 |
| FAILED     | 处理失败 |

---

### 10. 查询导入失败记录

**接口地址**: `GET /ccdi/staffTransfer/importFailures/{taskId}`

**权限要求**: `ccdi:staffTransfer:import`

**路径参数**:

| 参数名    | 类型     | 必填 | 说明     |
|--------|--------|----|--------|
| taskId | String | 是  | 导入任务ID |

**请求参数**:

| 参数名      | 类型      | 必填 | 说明         |
|----------|---------|----|------------|
| pageNum  | Integer | 否  | 页码(默认1)    |
| pageSize | Integer | 否  | 每页数量(默认10) |

**响应示例**:

```json
{
  "code": 200,
  "msg": "查询成功",
  "rows": [
    {
      "rowNum": 5,
      "staffId": "1000001",
      "transferType": "PROMOTION",
      "errorMsg": "员工ID不存在",
      "rawData": "原始数据..."
    }
  ],
  "total": 5
}
```

---

### 11. 获取员工列表(下拉选择)

**接口地址**: `GET /ccdi/staffTransfer/staffList`

**权限要求**: 无特殊要求

**请求参数**:

| 参数名  | 类型     | 必填 | 说明                |
|------|--------|----|-------------------|
| name | String | 否  | 员工姓名(模糊查询,用于下拉搜索) |

**响应示例**:

```json
{
  "code": 200,
  "msg": "查询成功",
  "data": [
    {
      "staffId": 1000001,
      "name": "张三",
      "deptId": 100,
      "deptName": "技术部"
    },
    {
      "staffId": 1000002,
      "name": "李四",
      "deptId": 101,
      "deptName": "研发部"
    }
  ]
}
```

---

## 数据字典

### 调动类型 (ccdi_transfer_type)

| 字典值               | 显示值  | CSS类    |
|-------------------|------|---------|
| PROMOTION         | 升职   | primary |
| DEMOPTION         | 降职   | danger  |
| LATERAL           | 平调   | info    |
| ROTATION          | 轮岗   | warning |
| SECONDMENT        | 借调   | default |
| DEPARTMENT_CHANGE | 部门调动 | success |
| POSITION_CHANGE   | 职位调整 | primary |
| RETURN            | 返岗   | info    |
| TERMINATION       | 离职   | danger  |
| OTHER             | 其他   | default |

---

## 错误码说明

| 错误码 | 说明       |
|-----|----------|
| 200 | 操作成功     |
| 401 | 未授权,请先登录 |
| 403 | 无权限访问    |
| 500 | 服务器内部错误  |

---

## 注意事项

1. **日期格式**: 所有日期字段使用 `yyyy-MM-dd` 格式
2. **分页**: 列表接口支持分页,默认每页10条
3. **权限**: 所有接口(除获取员工列表)都需要登录认证
4. **导入**: 导入功能采用异步处理,需轮询查询状态
5. **字典**: 调动类型字段使用字典管理,便于扩展
6. **关联查询**: 列表接口会自动关联查询员工姓名和部门名称
7. **审计字段**: 创建人、创建时间、更新人、更新时间由系统自动填充

---

## 更新日志

| 版本   | 日期         | 说明                   |
|------|------------|----------------------|
| v1.0 | 2026-02-10 | 初始版本,完成基础CRUD和导入导出功能 |

---

## 联系方式

如有问题,请联系开发团队或提交Issue。
