2026-03-27 22:20:25 +08:00
|
|
|
|
# 学校模块数据库设计文档
|
|
|
|
|
|
|
|
|
|
|
|
## 概述
|
|
|
|
|
|
|
|
|
|
|
|
本文档描述了学校管理系统的数据库表设计,包括学校信息、年级、班级、部门、教师和学生等核心实体。
|
|
|
|
|
|
|
|
|
|
|
|
## 设计原则
|
|
|
|
|
|
|
|
|
|
|
|
1. **租户隔离**:所有表都通过 `tenantId` 关联到 `Tenant` 表,实现多租户数据隔离
|
|
|
|
|
|
2. **用户统一**:教师和学生都基于 `User` 表,通过一对一关系扩展特定信息
|
|
|
|
|
|
3. **数据完整性**:使用外键约束和级联删除保证数据一致性
|
|
|
|
|
|
4. **审计追踪**:所有表都包含创建人、修改人、创建时间、修改时间字段
|
|
|
|
|
|
|
|
|
|
|
|
## 表结构设计
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 学校信息表 (School)
|
|
|
|
|
|
|
|
|
|
|
|
**说明**:扩展租户信息,存储学校的详细资料。与 `Tenant` 表一对一关系。
|
|
|
|
|
|
|
|
|
|
|
|
**字段说明**:
|
|
|
|
|
|
- `id`: 主键
|
|
|
|
|
|
- `tenantId`: 租户ID(唯一,一对一关联Tenant)
|
|
|
|
|
|
- `address`: 学校地址
|
|
|
|
|
|
- `phone`: 联系电话
|
|
|
|
|
|
- `principal`: 校长姓名
|
|
|
|
|
|
- `established`: 建校时间
|
|
|
|
|
|
- `description`: 学校描述
|
|
|
|
|
|
- `logo`: 学校Logo URL
|
|
|
|
|
|
- `website`: 学校网站
|
|
|
|
|
|
- `creator/modifier`: 创建人/修改人ID
|
|
|
|
|
|
- `createTime/modifyTime`: 创建/修改时间
|
|
|
|
|
|
|
|
|
|
|
|
**关系**:
|
|
|
|
|
|
- 一对一关联 `Tenant`
|
|
|
|
|
|
- 多对一关联 `User` (创建人/修改人)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 年级表 (Grade)
|
|
|
|
|
|
|
|
|
|
|
|
**说明**:管理学校的年级信息,如一年级、二年级等。
|
|
|
|
|
|
|
|
|
|
|
|
**字段说明**:
|
|
|
|
|
|
- `id`: 主键
|
|
|
|
|
|
- `tenantId`: 租户ID
|
|
|
|
|
|
- `name`: 年级名称(如:一年级、二年级)
|
|
|
|
|
|
- `code`: 年级编码(在租户内唯一,如:grade_1, grade_2)
|
|
|
|
|
|
- `level`: 年级级别(用于排序,如:1, 2, 3)
|
|
|
|
|
|
- `description`: 年级描述
|
|
|
|
|
|
- `validState`: 有效状态(1-有效,2-失效)
|
|
|
|
|
|
- `creator/modifier`: 创建人/修改人ID
|
|
|
|
|
|
- `createTime/modifyTime`: 创建/修改时间
|
|
|
|
|
|
|
|
|
|
|
|
**唯一约束**:
|
|
|
|
|
|
- `[tenantId, code]`: 租户内年级编码唯一
|
|
|
|
|
|
- `[tenantId, level]`: 租户内年级级别唯一
|
|
|
|
|
|
|
|
|
|
|
|
**关系**:
|
|
|
|
|
|
- 多对一关联 `Tenant`
|
|
|
|
|
|
- 一对多关联 `Class` (班级)
|
|
|
|
|
|
- 多对一关联 `User` (创建人/修改人)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 部门表 (Department)
|
|
|
|
|
|
|
|
|
|
|
|
**说明**:管理学校的部门信息,支持树形结构(如:教务处 > 语文组)。
|
|
|
|
|
|
|
|
|
|
|
|
**字段说明**:
|
|
|
|
|
|
- `id`: 主键
|
|
|
|
|
|
- `tenantId`: 租户ID
|
|
|
|
|
|
- `name`: 部门名称
|
|
|
|
|
|
- `code`: 部门编码(在租户内唯一)
|
|
|
|
|
|
- `parentId`: 父部门ID(支持树形结构)
|
|
|
|
|
|
- `description`: 部门描述
|
|
|
|
|
|
- `sort`: 排序
|
|
|
|
|
|
- `validState`: 有效状态(1-有效,2-失效)
|
|
|
|
|
|
- `creator/modifier`: 创建人/修改人ID
|
|
|
|
|
|
- `createTime/modifyTime`: 创建/修改时间
|
|
|
|
|
|
|
|
|
|
|
|
**唯一约束**:
|
|
|
|
|
|
- `[tenantId, code]`: 租户内部门编码唯一
|
|
|
|
|
|
|
|
|
|
|
|
**关系**:
|
|
|
|
|
|
- 多对一关联 `Tenant`
|
|
|
|
|
|
- 自关联(树形结构):`parent` 和 `children`
|
|
|
|
|
|
- 一对多关联 `Teacher` (教师)
|
|
|
|
|
|
- 多对一关联 `User` (创建人/修改人)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 4. 班级表 (Class)
|
|
|
|
|
|
|
|
|
|
|
|
**说明**:管理班级信息,支持行政班级(教学班级)和兴趣班两种类型。
|
|
|
|
|
|
|
|
|
|
|
|
**字段说明**:
|
|
|
|
|
|
- `id`: 主键
|
|
|
|
|
|
- `tenantId`: 租户ID
|
|
|
|
|
|
- `gradeId`: 年级ID
|
|
|
|
|
|
- `name`: 班级名称(如:一年级1班、二年级2班)
|
|
|
|
|
|
- `code`: 班级编码(在租户内唯一)
|
|
|
|
|
|
- `type`: 班级类型(1-行政班级/教学班级,2-兴趣班)
|
|
|
|
|
|
- `capacity`: 班级容量(可选)
|
|
|
|
|
|
- `description`: 班级描述
|
|
|
|
|
|
- `validState`: 有效状态(1-有效,2-失效)
|
|
|
|
|
|
- `creator/modifier`: 创建人/修改人ID
|
|
|
|
|
|
- `createTime/modifyTime`: 创建/修改时间
|
|
|
|
|
|
|
|
|
|
|
|
**唯一约束**:
|
|
|
|
|
|
- `[tenantId, code]`: 租户内班级编码唯一
|
|
|
|
|
|
|
|
|
|
|
|
**关系**:
|
|
|
|
|
|
- 多对一关联 `Tenant`
|
|
|
|
|
|
- 多对一关联 `Grade` (年级)
|
|
|
|
|
|
- 一对多关联 `Student` (学生,仅行政班级)
|
|
|
|
|
|
- 一对多关联 `StudentInterestClass` (学生兴趣班关联)
|
|
|
|
|
|
- 多对一关联 `User` (创建人/修改人)
|
|
|
|
|
|
|
|
|
|
|
|
**注意事项**:
|
|
|
|
|
|
- `students` 关系仅用于行政班级(type=1),需要在应用层验证
|
|
|
|
|
|
- 兴趣班通过 `StudentInterestClass` 表关联学生
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 5. 教师表 (Teacher)
|
|
|
|
|
|
|
|
|
|
|
|
**说明**:存储教师的详细信息,与 `User` 表一对一关系。
|
|
|
|
|
|
|
|
|
|
|
|
**字段说明**:
|
|
|
|
|
|
- `id`: 主键
|
|
|
|
|
|
- `userId`: 用户ID(唯一,一对一关联User)
|
|
|
|
|
|
- `tenantId`: 租户ID
|
|
|
|
|
|
- `departmentId`: 部门ID
|
|
|
|
|
|
- `employeeNo`: 工号(在租户内唯一)
|
|
|
|
|
|
- `phone`: 联系电话
|
|
|
|
|
|
- `idCard`: 身份证号
|
|
|
|
|
|
- `gender`: 性别(1-男,2-女)
|
|
|
|
|
|
- `birthDate`: 出生日期
|
|
|
|
|
|
- `hireDate`: 入职日期
|
|
|
|
|
|
- `subject`: 任教科目(可选,如:语文、数学)
|
|
|
|
|
|
- `title`: 职称(可选,如:高级教师、一级教师)
|
|
|
|
|
|
- `description`: 教师描述
|
|
|
|
|
|
- `validState`: 有效状态(1-有效,2-失效)
|
|
|
|
|
|
- `creator/modifier`: 创建人/修改人ID
|
|
|
|
|
|
- `createTime/modifyTime`: 创建/修改时间
|
|
|
|
|
|
|
|
|
|
|
|
**唯一约束**:
|
|
|
|
|
|
- `userId`: 用户ID唯一(一对一)
|
|
|
|
|
|
- `[tenantId, employeeNo]`: 租户内工号唯一
|
|
|
|
|
|
|
|
|
|
|
|
**关系**:
|
|
|
|
|
|
- 一对一关联 `User`
|
|
|
|
|
|
- 多对一关联 `Tenant`
|
|
|
|
|
|
- 多对一关联 `Department` (部门)
|
|
|
|
|
|
- 多对一关联 `User` (创建人/修改人)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 6. 学生表 (Student)
|
|
|
|
|
|
|
|
|
|
|
|
**说明**:存储学生的详细信息,与 `User` 表一对一关系。
|
|
|
|
|
|
|
|
|
|
|
|
**字段说明**:
|
|
|
|
|
|
- `id`: 主键
|
|
|
|
|
|
- `userId`: 用户ID(唯一,一对一关联User)
|
|
|
|
|
|
- `tenantId`: 租户ID
|
|
|
|
|
|
- `classId`: 行政班级ID
|
|
|
|
|
|
- `studentNo`: 学号(在租户内唯一)
|
|
|
|
|
|
- `phone`: 联系电话
|
|
|
|
|
|
- `idCard`: 身份证号
|
|
|
|
|
|
- `gender`: 性别(1-男,2-女)
|
|
|
|
|
|
- `birthDate`: 出生日期
|
|
|
|
|
|
- `enrollmentDate`: 入学日期
|
|
|
|
|
|
- `parentName`: 家长姓名
|
|
|
|
|
|
- `parentPhone`: 家长电话
|
|
|
|
|
|
- `address`: 家庭地址
|
|
|
|
|
|
- `description`: 学生描述
|
|
|
|
|
|
- `validState`: 有效状态(1-有效,2-失效)
|
|
|
|
|
|
- `creator/modifier`: 创建人/修改人ID
|
|
|
|
|
|
- `createTime/modifyTime`: 创建/修改时间
|
|
|
|
|
|
|
|
|
|
|
|
**唯一约束**:
|
|
|
|
|
|
- `userId`: 用户ID唯一(一对一)
|
|
|
|
|
|
- `[tenantId, studentNo]`: 租户内学号唯一
|
|
|
|
|
|
|
|
|
|
|
|
**关系**:
|
|
|
|
|
|
- 一对一关联 `User`
|
|
|
|
|
|
- 多对一关联 `Tenant`
|
|
|
|
|
|
- 多对一关联 `Class` (行政班级)
|
|
|
|
|
|
- 一对多关联 `StudentInterestClass` (兴趣班关联)
|
|
|
|
|
|
- 多对一关联 `User` (创建人/修改人)
|
|
|
|
|
|
|
|
|
|
|
|
**注意事项**:
|
|
|
|
|
|
- `classId` 必须关联行政班级(type=1),需要在应用层验证
|
|
|
|
|
|
- 兴趣班通过 `StudentInterestClass` 表关联
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 7. 学生兴趣班关联表 (StudentInterestClass)
|
|
|
|
|
|
|
|
|
|
|
|
**说明**:学生和兴趣班的多对多关联表。
|
|
|
|
|
|
|
|
|
|
|
|
**字段说明**:
|
|
|
|
|
|
- `id`: 主键
|
|
|
|
|
|
- `studentId`: 学生ID
|
|
|
|
|
|
- `classId`: 兴趣班ID(type=2的Class)
|
|
|
|
|
|
|
|
|
|
|
|
**唯一约束**:
|
|
|
|
|
|
- `[studentId, classId]`: 学生和兴趣班组合唯一
|
|
|
|
|
|
|
|
|
|
|
|
**关系**:
|
|
|
|
|
|
- 多对一关联 `Student`
|
|
|
|
|
|
- 多对一关联 `Class` (兴趣班)
|
|
|
|
|
|
|
|
|
|
|
|
**注意事项**:
|
|
|
|
|
|
- `classId` 必须关联兴趣班(type=2),需要在应用层验证
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 数据关系图
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
Tenant (租户/学校)
|
|
|
|
|
|
├── School (学校信息) [1:1]
|
|
|
|
|
|
├── Grade (年级) [1:N]
|
|
|
|
|
|
│ └── Class (班级) [1:N]
|
|
|
|
|
|
│ ├── Student (学生) [1:N, 仅行政班级]
|
|
|
|
|
|
│ └── StudentInterestClass [N:M, 仅兴趣班]
|
|
|
|
|
|
├── Department (部门) [1:N, 树形结构]
|
|
|
|
|
|
│ └── Teacher (教师) [1:N]
|
|
|
|
|
|
└── User (用户) [1:N]
|
|
|
|
|
|
├── Teacher [1:1]
|
|
|
|
|
|
└── Student [1:1]
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 业务规则
|
|
|
|
|
|
|
|
|
|
|
|
1. **学校与租户**:每个租户对应一个学校,通过 `School` 表扩展学校信息
|
|
|
|
|
|
2. **年级管理**:年级按 `level` 排序,每个租户内级别唯一
|
|
|
|
|
|
3. **班级类型**:
|
|
|
|
|
|
- 行政班级(type=1):学生必须属于一个行政班级
|
|
|
|
|
|
- 兴趣班(type=2):学生可以加入多个兴趣班
|
|
|
|
|
|
4. **部门树形结构**:部门支持多级嵌套,通过 `parentId` 实现
|
|
|
|
|
|
5. **教师归属**:教师必须归属于一个部门
|
|
|
|
|
|
6. **学生归属**:学生必须属于一个行政班级,可以加入多个兴趣班
|
|
|
|
|
|
|
|
|
|
|
|
## 数据完整性约束
|
|
|
|
|
|
|
|
|
|
|
|
1. **级联删除**:
|
|
|
|
|
|
- 删除租户时,级联删除所有相关数据
|
|
|
|
|
|
- 删除年级时,级联删除所有班级
|
|
|
|
|
|
- 删除用户时,级联删除教师/学生信息
|
|
|
|
|
|
- 删除班级时,级联删除学生兴趣班关联
|
|
|
|
|
|
|
|
|
|
|
|
2. **限制删除**:
|
|
|
|
|
|
- 删除部门时,如果存在教师,不允许删除(Restrict)
|
|
|
|
|
|
- 删除班级时,如果存在学生,不允许删除(Restrict)
|
|
|
|
|
|
|
|
|
|
|
|
3. **唯一性约束**:
|
|
|
|
|
|
- 租户内年级编码唯一
|
|
|
|
|
|
- 租户内年级级别唯一
|
|
|
|
|
|
- 租户内部门编码唯一
|
|
|
|
|
|
- 租户内班级编码唯一
|
|
|
|
|
|
- 租户内教师工号唯一
|
|
|
|
|
|
- 租户内学生学号唯一
|
|
|
|
|
|
|
|
|
|
|
|
## 应用层验证建议
|
|
|
|
|
|
|
|
|
|
|
|
1. **班级类型验证**:
|
|
|
|
|
|
- 创建学生时,`classId` 必须关联 `type=1` 的班级
|
|
|
|
|
|
- 创建学生兴趣班关联时,`classId` 必须关联 `type=2` 的班级
|
|
|
|
|
|
|
|
|
|
|
|
2. **数据一致性**:
|
|
|
|
|
|
- 教师/学生的 `tenantId` 必须与关联的 `User.tenantId` 一致
|
|
|
|
|
|
- 班级的 `tenantId` 必须与关联的 `Grade.tenantId` 一致
|
|
|
|
|
|
|
|
|
|
|
|
3. **业务逻辑**:
|
|
|
|
|
|
- 删除部门前,需要先转移或删除该部门下的所有教师
|
|
|
|
|
|
- 删除班级前,需要先转移或删除该班级下的所有学生
|
|
|
|
|
|
|
|
|
|
|
|
## 迁移建议
|
|
|
|
|
|
|
|
|
|
|
|
1. 运行 Prisma 迁移生成 SQL:
|
|
|
|
|
|
```bash
|
|
|
|
|
|
npx prisma migrate dev --name add_school_module
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
2. 数据初始化:
|
|
|
|
|
|
- 为现有租户创建对应的 `School` 记录
|
|
|
|
|
|
- 根据业务需求初始化年级数据
|
|
|
|
|
|
|
|
|
|
|
|
3. 数据迁移(如需要):
|
|
|
|
|
|
- 如果已有教师/学生数据,需要创建对应的 `User` 记录并关联
|
|
|
|
|
|
|
|
|
|
|
|
## 后续扩展建议
|
|
|
|
|
|
|
|
|
|
|
|
1. **课程管理**:可以添加课程表、课程安排等
|
|
|
|
|
|
2. **成绩管理**:可以添加成绩表、考试表等
|
|
|
|
|
|
3. **考勤管理**:可以添加考勤记录表
|
|
|
|
|
|
4. **通知公告**:可以添加通知表、公告表等
|
|
|
|
|
|
|