3.2 KiB
3.2 KiB
DingTalk 导入链路修复 — 设计文档
日期:2026-07-09
状态:已确认
关联:PRD 钉钉集成批次 1/2
1. 背景
DingTalk 用户导入 → 班级标记 → 排课 → 考勤 的链路已基本搭建完成,但存在两个阻塞问题:
- 前端: "标为班级"按钮出现在所有部门节点上,包括有子部门的父节点。应该在叶子节点(无子部门、有用户)才显示。
- 后端:
CampusScope按departmentId做数据隔离,但钉钉同步的老师没有UserDepartment关联,导致非超管老师看不到学生和考勤数据。
本设计的核心原则:教学域(班级、学生、考勤、排课)不走部门过滤,权限边界是"老师教的班",不是"老师归哪个部门"。
2. 改动清单
2.1 前端:叶子节点判断
文件: apps/admin/src/pages/IntegrationConfig/index.tsx
位置: buildTreeData 回调函数,第 371–431 行
改动: 部门节点的标题渲染逻辑改为:
if (node.children.length === 0 && node.users.length > 0) {
// 叶子节点:显示"标为班级"按钮 或 "班级: xxx [已标记]"
} else {
// 非叶子节点:只显示部门名称
}
非叶子节点(有子部门)不显示任何班级标记入口。
2.2 后端:移除教学域 CampusScope
原则: CampusScope 保留给管理域(宿舍 OccupanciesService、房间 RoomsService、账单 BillsService、费用 ExpensesService)——这些按校区/部门隔离数据是合理的。教学域不走部门过滤。
2.2.1 StudentsService
文件: apps/server/src/students/students.service.ts
改动:
- 移除
CampusScope注入(构造函数参数private readonly scope: CampusScope) - 移除
findAll方法中的await this.scope.filter(where)调用 findAll直接使用原始where条件查询
影响: 有 student:view 权限的用户可以看到所有学生,不再按部门隔离。
2.2.2 AttendanceService
文件: apps/server/src/attendance/attendance.service.ts
改动:
- 移除
CampusScope注入 - 移除所有
scope.filter()/scope.getScopeDepartmentIds()调用 - 考勤记录查询不再按部门过滤
影响: 有 attendance:view 权限的用户可以看到所有考勤数据。
3. 不改的
| 模块 | 原因 |
|---|---|
ClassesService |
已不使用 CampusScope |
SchedulesService |
已不使用 CampusScope |
OccupanciesService |
宿舍管理需要部门隔离,保留 |
RoomsService |
房间管理需要部门隔离,保留 |
BillsService |
财务管理需要部门隔离,保留 |
ExpensesService |
费用管理需要部门隔离,保留 |
DingTalkService.syncAll |
同步逻辑不变 |
SyncService.importDingTalkUsers |
导入逻辑不变 |
| RBAC 权限码 | 不动 |
4. 验收标准
- 钉钉组织架构树中,父部门节点不显示"标为班级"按钮,叶子节点正常显示
- 非超管老师登录后,学生列表正常显示所有学生
- 非超管老师登录后,考勤页面正常显示所有考勤记录
- 宿舍、财务等管理域功能不受影响(部门过滤仍然生效)
tsc --noEmit编译通过