# 组织同步重构: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 ``,完整钉钉组织树,部门+用户均可勾选,级联 - **右栏**:已有班级列表(名称+班型),选中高亮 + "创建班级"按钮 - **底部**:"加入选中的班级" / "创建班级" 两个操作: | 操作 | 前提 | 动作 | |---|---|---| | 加入班级 | 勾选用户 + 选中班级 | POST /classes/:id/students/import | | 创建班级 | 勾选用户 + 勾选部门 | 弹出班级表单 → POST /classes + 关联学生 | ### 删除 - 逐用户 teacher/student toggle - "标记为班级" modal - 最深两层过滤 ## 不受影响 - `fetchOrgTree`(dept picker) - 考勤导入(`DingAttendanceRaw.dingUserId` → `StudentDingMapping`) - 排班同步(教师逻辑后续处理,本轮不碰)