From ebacf8601f4e4feacefb5a63a64a21cef21c4c38 Mon Sep 17 00:00:00 2001 From: wangziqi Date: Sun, 5 Jul 2026 18:34:42 +0800 Subject: [PATCH] docs: add P0 design spec and project APPEND_SYSTEM.md --- .omp/APPEND_SYSTEM.md | 47 +++ .../specs/2026-07-05-gongxue-p0-design.md | 302 ++++++++++++++++++ 2 files changed, 349 insertions(+) create mode 100644 .omp/APPEND_SYSTEM.md create mode 100644 docs/superpowers/specs/2026-07-05-gongxue-p0-design.md diff --git a/.omp/APPEND_SYSTEM.md b/.omp/APPEND_SYSTEM.md new file mode 100644 index 0000000..a978455 --- /dev/null +++ b/.omp/APPEND_SYSTEM.md @@ -0,0 +1,47 @@ +# 恭学教育学生管理系统 — 项目约束 + +完整 PRD 文档:`../../Downloads/PRD-恭学教育学生管理系统.md`(相对项目根目录) + +## 技术栈 + +| 层级 | 技术 | +|------|------| +| 架构 | Monorepo (Turborepo) | +| 前端 | React 19 + Vite + Ant Design 6 + ECharts | +| 后端 | NestJS 11 + TypeORM 0.3 + JWT + Passport | +| 数据库 | 开发 SQLite / 生产 MySQL 8 | +| 部署 | Docker Compose (MySQL + NestJS + Nginx) | + +## 核心用户角色 + +- 超级管理员:系统配置、账号管理、全部数据 +- 教职工(宿管+财务):宿舍管理、费用录入、账单生成、指定部门 +- 班主任:本班学生信息、档案、费用、考勤 +- 学生:仅本人数据 + +## 业务域 + +- 学员管理域:学生管理、学生档案、考勤管理 +- 教务管理域:班级管理(新)、排课管理(新)、教师管理、教室管理 +- 住宿管理域:宿舍管理、入住管理 +- 财务运营域:费用管理、账单管理、押金管理、租赁方管理、数据面板 + +## 横切关注点 + +- RBAC 权限控制 +- 操作日志(所有关键写操作) +- 钉钉/企业微信集成 +- 报表导出、批量导入 + +## 上线优先级 + +**P0(阻塞上线)**:班级管理、排课管理、宿舍管理增强、账单管理(长租)、操作日志 +**P1(上线前完成)**:考勤管理前端、数据面板、RBAC 扩展、教室管理增强、organization→tenant_id +**P2(可迭代)**:报表导出、教师档案增强、多班型对比、押金分期、第三方集成 + +## 编码规范 + +- 所有涉及大量数据的列表/表单页面必须有详细的筛选方案 +- 敏感信息(手机号、身份证)需脱敏展示,查看时二次确认+记录日志 +- 遵循现有 NestJS 模块结构:每个业务模块独立目录,含 entity/dto/service/controller +- 前端页面放在 `apps/admin/src/pages/` 下,每个模块独立目录 diff --git a/docs/superpowers/specs/2026-07-05-gongxue-p0-design.md b/docs/superpowers/specs/2026-07-05-gongxue-p0-design.md new file mode 100644 index 0000000..0f8216b --- /dev/null +++ b/docs/superpowers/specs/2026-07-05-gongxue-p0-design.md @@ -0,0 +1,302 @@ +# 恭学教育学生管理系统 P0 批次 — 设计规格 + +> 版本:v1.0 +> 日期:2026-07-05 +> 基于 PRD:`../../Downloads/PRD-恭学教育学生管理系统.md`(commit `59f75bb`) + +## 目标 + +按 PRD 优先级分批实施,本批次覆盖 P0(阻塞上线)的全部 5 项 + 部分 P1(上线前完成),打通班级→排课→宿舍增强→操作日志→RBAC→考勤前端→数据面板的完整链路。 + +## 架构 + +Monorepo (Turborepo),后端 NestJS 11 + TypeORM 0.3 + SQLite/MySQL,前端 React 19 + Vite + Ant Design 6 + ECharts。新增 `classes`、`schedules` 两个独立 NestJS 模块,在现有 `rooms`/`occupancies`/`bills` 模块上增量增强,考勤前端新建页面。遵循现有模块结构:每个业务模块独立目录,含 `entity`/`dto`/`service`/`controller`/`module`。 + +## 技术栈 + +| 层级 | 技术 | +|------|------| +| 架构 | Monorepo (Turborepo) | +| 前端 | React 19 + Vite + Ant Design 6 + ECharts | +| 后端 | NestJS 11 + TypeORM 0.3 + JWT + Passport | +| 数据库 | 开发 SQLite / 生产 MySQL 8 | +| 测试 | Jest (后端) + Playwright (前端 E2E) | + +## 全局约束 + +- 所有涉及大量数据的列表/表单页面必须有详细的筛选方案 +- 敏感信息(手机号、身份证)需脱敏展示,查看时二次确认+记录操作日志 +- 遵循现有 NestJS 模块结构,每个业务模块独立目录 +- 前端页面放在 `apps/admin/src/pages/` 下,每个模块独立目录 +- 表名使用复数形式(与现有 `students`、`rooms`、`classrooms`、`bills` 一致) +- 冲突检测使用数据库唯一约束 + 应用层双重保障 + +--- + +## 模块 1:班级管理(Class) + +### 实体 + +**`classes`**:班级主表,含 name/code/class_type/status/日期/教师/人数上限,通过 `department_id` 关联校区。 + +**`class_student`**:班级-学员关联,`UNIQUE(class_id, student_id)`,含 enroll_id/join_date/leave_date/status。 + +**`class_teacher`**:班级-教师关联,`UNIQUE(class_id, user_id, role_type)`,含 role_type(任课老师/班主任/生活老师/学服老师)+ subject。 + +Class 自身的 `head_teacher_id`/`life_teacher_id`/`academic_teacher_id` 与 `class_teacher` 表保持同步——创建/编辑班级时,若传了 head_teacher_id 等字段,同时写入 class_teacher 表对应记录。 + +### API + +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | `/classes` | 班级列表(筛选:department_id/status/class_type/keyword) | +| POST | `/classes` | 创建班级(含初始教师/学员分配) | +| GET | `/classes/:id` | 班级详情(教师列表+学员统计) | +| PUT | `/classes/:id` | 编辑班级 | +| DELETE | `/classes/:id` | 删除班级(CASCADE 删除关联) | +| GET | `/classes/:id/students` | 班级学员列表 | +| POST | `/classes/:id/students` | 批量添加学员 `{ studentIds: number[] }` | +| DELETE | `/classes/:id/students/:studentId` | 移除学员 | +| GET | `/classes/:id/teachers` | 班级教师列表 | +| POST | `/classes/:id/teachers` | 添加教师 `{ userId, roleType, subject? }` | +| DELETE | `/classes/:id/teachers/:userId` | 移除教师 | + +### 前端 + +**列表页 `Classes/index.tsx`**:筛选栏(校区下拉/班型下拉/状态下拉/搜索输入)+ 表格(名称/编码/校区/班型/日期/学员数/班主任/状态Tag/操作)+ 分页。 + +**详情页 `Classes/Detail.tsx`**:3 Tab — 基本信息(可编辑表单)、花名册(学员表格+批量添加/移除)、教师(教师表格+添加/移除)。 + +--- + +## 模块 2:排课管理(ClassSchedule) + +### 实体 + +**`class_schedule`**:排课记录,含 class_id/classroom_id/week_day/start_time/end_time/start_date/end_date/subject/teacher_id/schedule_type(INTERNAL/RENTAL)/rental_id/status。 + +唯一约束:同教室 + 同 week_day + 时间段重叠 + status=active 拒绝写入(应用层检测 + 数据库层面依赖应用层保证,SQLite 不支持排他约束)。 + +### 核心规则 + +1. INTERNAL 排课:按班级维度,展示科目+教师,关联 class_id +2. RENTAL 排课:仅标记教室占用,关联 rental_id(classroom_rentals) +3. 冲突检测:新增/编辑时检查同教室同星期同时段是否已有 active 排课 +4. 时段定义:预设 PRD 作息表(早自习 7:30-8:40、上午 9:00-12:00、下午 14:00-17:00、晚自习 18:30-21:00),管理员可在系统设置中调整 + +### API + +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | `/class-schedules` | 排课列表(筛选:classroom_id/class_id/week_day/date_range) | +| POST | `/class-schedules` | 创建排课(含冲突检测) | +| PUT | `/class-schedules/:id` | 编辑排课(含冲突检测) | +| DELETE | `/class-schedules/:id` | 删除排课 | +| GET | `/class-schedules/weekly` | 周视图数据(按教室+week_day聚合) | +| GET | `/class-schedules/classroom/:id/occupancy` | 教室占用时间线(合并内部+外部) | + +### 前端 + +**周视图 `Schedules/index.tsx`**:顶部周切换 + 教室/班级筛选,主体 7列×N行矩阵(列=周一~周日,行=教室),每格显示科目/教师/时间。点击格子弹出排课表单 Modal(班级/科目/教师/教室/星期/时段/日期范围)。冲突时 Modal 内红色提示。 + +--- + +## 模块 3:宿舍/入住/账单增强 + +### 数据变更 + +**rooms**:新增 `rental_category`(VARCHAR(10),long/short)、`monthly_rate`(DECIMAL(10,2))。 + +**occupancies**:新增 `rental_type`(VARCHAR(10),long/short)、`tenant_id`(FK → tenants.id)。 + +**students**:新增 `tenant_id`(FK → tenants.id),替代原 `organization` 文本字段。迁移时根据 `organization` 匹配 `tenants.name`。 + +### 账单逻辑 + +`POST /bills/generate` 内部:遍历宿舍的 occupancy 记录,`rental_type === 'long'` 的长租学生走固定月费独立生成(不参与分摊),`short` 学生走原人天数加权分摊。 + +### 前端 + +Rooms 表单增加 `rental_category` Select + `monthly_rate` InputNumber。Occupancies 表单增加 `rental_type` Select + `tenant_id` Select。 + +--- + +## 模块 4:操作日志全量接入 + +### 覆盖范围 + +在以下 controller 的每个写操作中统一调用 `OperationLogsService.log()`: + +| 模块 | 审计操作 | +|------|---------| +| Classes | 创建/编辑/删除班级、添加/移除学员、添加/移除教师 | +| ClassSchedules | 创建/编辑/删除排课 | +| Students | 新增/编辑/删除学生、导入/导出、查看敏感信息 | +| Occupancies | 新增/编辑/退住 | +| Expenses | 新增/编辑/删除费用 | +| Bills | 生成账单、确认账单、标记已付、导出 | +| Deposits | 收取/退还押金 | +| Attendance | 补录/编辑考勤、匹配钉钉数据 | +| RBAC | 角色变更、权限变更 | + +### 调用模式 + +```typescript +this.operationLogsService.log({ + userId: req.user.id, + username: req.user.username, + module: 'CLASS', + action: 'CREATE', + targetId: result.id, + targetType: 'class', + detail: { name: result.name }, + ipAddress: req.ip, + status: 'success', +}); +``` + +--- + +## 模块 5:RBAC 权限扩展 + +`permission.json` 新增以下节点: + +| 权限节点 | super_admin | staff | class_teacher | student | +|----------|:---:|:---:|:---:|:---:| +| CLASS:READ | ✅ | ✅ | ✅ | - | +| CLASS:ADD | ✅ | ✅ | - | - | +| CLASS:UPDATE | ✅ | ✅ | - | - | +| CLASS:DELETE | ✅ | - | - | - | +| SCHEDULE:READ | ✅ | ✅ | ✅ | - | +| SCHEDULE:ADD | ✅ | ✅ | - | - | +| SCHEDULE:UPDATE | ✅ | ✅ | - | - | +| SCHEDULE:DELETE | ✅ | - | - | - | +| ATTENDANCE:READ | ✅ | ✅ | ✅ | ✅ | +| ATTENDANCE:ADD | ✅ | ✅ | - | - | +| ATTENDANCE:UPDATE | ✅ | ✅ | - | - | + +--- + +## 模块 6:考勤管理前端 + +### 页面 + +**列表页 `Attendance/index.tsx`**:筛选栏(班级/日期范围/时段/状态/来源)+ 表格(姓名/班级/日期/时段/状态Tag/来源/打卡时间/备注/操作)+ 批量补录按钮 + 切换到日历视图按钮。 + +**日历视图**:切换模式,行=学生、列=日期+时段,格=状态色块(绿=出勤、黄=迟到、红=缺勤、蓝=请假)。 + +### API + +增强现有 `/attendance-records` 筛选参数,新增: + +| 方法 | 路径 | 说明 | +|------|------|------| +| POST | `/attendance-records/batch` | 批量补录 | +| GET | `/attendance-records/summary` | 考勤汇总统计(按班级/日期范围) | +| GET | `/attendance-records/calendar` | 日历视图数据 | +| GET | `/ding-attendance-raw` | 钉钉原始数据列表(筛选match_status) | +| POST | `/ding-attendance-raw/:id/match` | 手动匹配钉钉数据到学生 | + +--- + +## 模块 7:数据面板增强 + +在现有 Dashboard 的基础上: + +- **第二行指标卡**:教室总数/占用率、今日出勤率、本月收入总额、教室占用率 +- **新增图表**:考勤趋势折线图(近30天)、近6月收入趋势图 +- **权限控制**:不同角色看到不同指标——班主任只看本班考勤,超管看全局 + +### API + +`GET /dashboard` 返回数据增加字段:`classroomCount`/`classroomOccupancyRate`/`todayAttendanceRate`/`monthlyIncome`/`attendanceTrend`/`incomeTrend`。 + +--- + +## 数据库迁移 + +### 新增表 + +`classes`、`class_student`、`class_teacher`、`class_schedule` — TypeORM `synchronize: true` 自动建表。 + +### 现有表变更 + +```sql +ALTER TABLE rooms ADD COLUMN rental_category VARCHAR(10) DEFAULT 'short'; +ALTER TABLE rooms ADD COLUMN monthly_rate DECIMAL(10,2) DEFAULT 0; +ALTER TABLE occupancies ADD COLUMN rental_type VARCHAR(10) DEFAULT 'short'; +ALTER TABLE occupancies ADD COLUMN tenant_id INTEGER REFERENCES tenants(id); +ALTER TABLE students ADD COLUMN tenant_id INTEGER REFERENCES tenants(id); +``` + +### 数据迁移 + +`students.organization` → `students.tenant_id`:遍历 students 表,根据 `organization` 文本匹配 `tenants.name`,匹配到的写入 tenant_id,未匹配的置 NULL。原 `organization` 列保留不删,待后续迭代清理。 + +--- + +## 文件结构 + +``` +apps/server/src/ +├── entities/ +│ ├── class.entity.ts 🆕 +│ ├── class-student.entity.ts 🆕 +│ ├── class-teacher.entity.ts 🆕 +│ ├── class-schedule.entity.ts 🆕 +│ ├── room.entity.ts ✏️ +│ ├── occupancy.entity.ts ✏️ +│ ├── student.entity.ts ✏️ +│ └── index.ts ✏️ +├── classes/ 🆕 +│ ├── classes.module.ts +│ ├── classes.controller.ts +│ ├── classes.service.ts +│ └── dto/ +├── schedules/ 🆕 +│ ├── schedules.module.ts +│ ├── schedules.controller.ts +│ ├── schedules.service.ts +│ └── dto/ +├── rooms/ ✏️ dto +├── occupancies/ ✏️ dto + service +├── bills/ ✏️ service +├── operation-logs/ ✏️ 注入各模块 +├── rbac/ ✏️ permission.json +├── dashboard/ ✏️ service + controller +└── app.module.ts ✏️ 注册新模块 + +apps/admin/src/pages/ +├── Classes/ 🆕 +│ ├── index.tsx +│ └── Detail.tsx +├── Schedules/ 🆕 +│ └── index.tsx +├── Attendance/ 🆕 +│ └── index.tsx +├── Dashboard/ ✏️ index.tsx +├── Rooms/ ✏️ index.tsx +└── Occupancies/ ✏️ index.tsx +``` + +--- + +## 开发顺序 + +``` +Phase 1 班级管理(无上游依赖) + │ +Phase 2 排课管理(依赖班级+教室) + │ +Phase 3 宿舍/入住/账单增强(独立,可与1/2并行) + │ +Phase 4 操作日志全量接入(依赖1/2/3的controller就绪) + │ +Phase 5 RBAC权限扩展(依赖1/2模块存在) + │ +Phase 6 考勤管理前端(后端API已有,独立开发) + │ +Phase 7 数据面板增强(依赖各方面数据) +``` + +Phase 1-3 可部分并行,Phase 4-5 需等 1-3 完成,Phase 6-7 可在 1-5 完成后并行。