docs: add DingTalk import fix design spec

This commit is contained in:
2026-07-09 15:15:56 +08:00
parent 7666baceff
commit a568d9a871

View File

@@ -0,0 +1,90 @@
# DingTalk 导入链路修复 — 设计文档
> 日期2026-07-09
> 状态:已确认
> 关联PRD 钉钉集成批次 1/2
---
## 1. 背景
DingTalk 用户导入 → 班级标记 → 排课 → 考勤 的链路已基本搭建完成,但存在两个阻塞问题:
1. **前端:** "标为班级"按钮出现在所有部门节点上,包括有子部门的父节点。应该在叶子节点(无子部门、有用户)才显示。
2. **后端:** `CampusScope``departmentId` 做数据隔离,但钉钉同步的老师没有 `UserDepartment` 关联,导致非超管老师看不到学生和考勤数据。
本设计的核心原则:**教学域(班级、学生、考勤、排课)不走部门过滤,权限边界是"老师教的班",不是"老师归哪个部门"。**
---
## 2. 改动清单
### 2.1 前端:叶子节点判断
**文件:** `apps/admin/src/pages/IntegrationConfig/index.tsx`
**位置:** `buildTreeData` 回调函数,第 371431 行
**改动:** 部门节点的标题渲染逻辑改为:
```
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. 验收标准
1. 钉钉组织架构树中,父部门节点不显示"标为班级"按钮,叶子节点正常显示
2. 非超管老师登录后,学生列表正常显示所有学生
3. 非超管老师登录后,考勤页面正常显示所有考勤记录
4. 宿舍、财务等管理域功能不受影响(部门过滤仍然生效)
5. `tsc --noEmit` 编译通过