# 组织同步重构：Student 独立实体 + Drawer 批量操作

**日期**：2026-07-09  
**范围**：数据模型、同步、导入、前端 Drawer

## 背景

Student 是独立业务实体，不参与 RBAC，不与 User 挂钩。当前同步链路 `dingUserId → User → Student.userId` 应改为 `dingUserId → Student`。

## 需求

### 数据模型

- **新增** `StudentDingMapping`：`ding_user_id`(UNIQUE) + `student_id`(UNIQUE) + `created_at`
- **废弃** `UserDingMapping`：删 entity、删所有引用、删表

### 同步 (`syncAll`)

不再创建 User，直接创建 Student + StudentDingMapping。同步进来的全是学生。

### 组织树 (`fetchOrgTreeWithUsers`)

恢复全量返回，去掉最深两层过滤，去掉 `getDeptDepthMap`。

### 批量导入 (`POST /classes/:id/students/import`)

接收 `{ dingUserIds: string[] }`，逐个：无则创建 Student + StudentDingMapping，有则跳过 → 创建 ClassStudent。

### 班级创建

`POST /classes` 扩展可选 `dingUserIds`，创建班级后自动导入。

### 前端 Drawer（IntegrationConfig 同步用户 tab）

左右分栏：
- **左栏**：Ant Design `<Tree checkable>`，完整钉钉组织树，部门+用户均可勾选，级联
- **右栏**：已有班级列表（名称+班型），选中高亮 + "创建班级"按钮
- **底部**："加入选中的班级" / "创建班级"

两个操作：
| 操作 | 前提 | 动作 |
|---|---|---|
| 加入班级 | 勾选用户 + 选中班级 | POST /classes/:id/students/import |
| 创建班级 | 勾选用户 + 勾选部门 | 弹出班级表单 → POST /classes + 关联学生 |

### 删除

- 逐用户 teacher/student toggle
- "标记为班级" modal
- 最深两层过滤

## 不受影响

- `fetchOrgTree`（dept picker）
- 考勤导入（`DingAttendanceRaw.dingUserId` → `StudentDingMapping`）
- 排班同步（教师逻辑后续处理，本轮不碰）
