Backend API design¶
Author: Zhenyu Yang yangzhenyu@sust.edu.cn, Sixu Wei reisa@sust.edu.cn
Last updated: Feb 4, 2026
The API documentation is written for the developer to read and does not include the machine-readable OpenAPI format.
0. 统一返回格式¶
除少数文件上传 API 外,所有 API 返回结构如下:
成功
{
"code": 0,
"message": "success",
"data": { ... }
}
失败
{
"code": 40001,
"message": "User not found"
}
1. 认证与用户账号¶
1.1 登录¶
微信用户扫码绑定后登录
POST /api/v1/auth/login/wechat
Body
{
"wxid": "xxxx"
}
邮箱/学号/工号 + 密码登录
POST /api/v1/auth/login/email
Body
{
"email": "teacher@school.edu", // 支持邮箱或 user_code
"password": "your_password",
"totp_code": "123456" // 当账号启用 TOTP 时必填
}
已启用 TOTP 的账号在使用微信登录时,同样需要在请求体中携带
totp_code字段。
1.1.1 双因素认证(TOTP)¶
为账号启用基于时间的一次性密码:
POST /api/v1/auth/totp/setup
返回值示例:
{
"code": 0,
"message": "success",
"data": {
"secret": "BASE32SECRET",
"provisioning_uri": "otpauth://totp/Classroom%20Manager:tester%40school.edu?..."
}
}
完成扫描后提交验证码以启用:
POST /api/v1/auth/totp/enable
Body
{
"totp_code": "123456"
}
1.1.2 无密码登录(WebAuthn)¶
本系统支持使用安全密钥 / 平台设备进行 WebAuthn 认证,流程分为「注册密钥」和「登录」两步。所有接口均遵循统一 success/error 返回结构。
注册安全密钥(需登录后操作)¶
请求注册参数(传递可选
device_name便于备注设备):
POST /api/v1/auth/webauthn/options/register
返回值包含浏览器 navigator.credentials.create 所需的 publicKey 参数。
提交浏览器生成的凭证:
POST /api/v1/auth/webauthn/register
Body 示例:
{
"credential": { ... },
"device_name": "MacBook Touch ID"
}
使用安全密钥登录(匿名可访问)¶
请求登录参数:
POST /api/v1/auth/webauthn/options/login
Body
{ "identifier": "teacher@school.edu" }
提交认证结果以换取 JWT:
POST /api/v1/auth/webauthn/login
Body
{ "credential": { ... } }
关闭 TOTP 认证:
POST /api/v1/auth/totp/disable
Body(如当前已启用,需带上验证码确认):
{
"totp_code": "123456"
}
1.2 管理员(superadmin / secretary)邀请外方教师注册¶
POST /api/v1/users/invite-foreign
Body
{
"email": "teacher@school.edu",
"full_name": "John Smith"
}
1.3 邮箱注册(外方教师)¶
POST /api/v1/auth/register/email
Body
{
"email": "teacher@school.edu",
"password": "12345678",
"full_name": "John Smith"
}
1.4 获取当前登录用户信息¶
GET /api/v1/auth/me
1.5 用户列表(管理员)¶
GET /api/v1/users
Query
role(可选)
status(可选)
search(可选,匹配姓名/学号/工号)
page, page_size(兼容 size)
1.6 创建用户(superadmin)¶
POST /api/v1/users
1.7 更新用户信息(superadmin / secretary)¶
PUT /api/v1/users/{id}
1.8 修改角色(superadmin)¶
PUT /api/v1/users/{id}/role
Body:
{ "role": "assistant" }
1.9 禁用/启用账户¶
PUT /api/v1/users/{id}/status
1.10 导入人员 Excel¶
POST /api/v1/users/import
Content-Type: multipart/form-data
字段:file
2. 教室管理 API¶
2.1 获取教室列表(所有人可见,但字段不同)¶
未登录用户
GET /api/v1/classrooms/public
返回字段(隐藏敏感信息):
building
room_number
status
当前时间段是否占用(不含占用人信息)
登录用户(带设备信息)
GET /api/v1/classrooms
Query:
building
capacity_min
status
page, page_size(兼容 size)
2.2 教室详情¶
(登录用户)
GET /api/v1/classrooms/{id}
2.3 创建教室(superadmin)¶
POST /api/v1/classrooms
2.4 更新教室信息(superadmin / assistant)¶
PUT /api/v1/classrooms/{id}
2.5 删除教室(superadmin)¶
DELETE /api/v1/classrooms/{id}
2.6 导入教室 Excel(superadmin)¶
POST /api/v1/classrooms/import
Content-Type: multipart/form-data
2.7 教室课表¶
获取某一教室在指定日期范围内的占用时间段。
课表由 已批准(approved) 的人工借用记录(source_type=manual)与课程表(CourseSession,通常由课程导入生成)共同生成,并按照时间顺序返回一组时间块。空闲时段也会以 occupied=false 的块返回,便于前端直接绘制时间轴。
GET /api/v1/classrooms/{id}/schedule
Query:
start_date(yyyy-mm-dd)
end_date(yyyy-mm-dd)
Response
{
"code": 0,
"message": "success",
"data": [
{
"start_time": "2025-04-12T00:00:00+08:00",
"end_time": "2025-04-12T08:00:00+08:00",
"occupied": false,
"reason": null
},
{
"start_time": "2025-04-12T08:00:00+08:00",
"end_time": "2025-04-12T09:40:00+08:00",
"occupied": true,
"reason": "Calculus"
}
]
}
未登录用户也可访问此接口,reason 字段在未登录时返回 null。
2.7.1 班牌课程(公开)¶
班牌端获取某教室在日期范围内的课程安排(公开访问,返回课程详情)。
GET /api/v1/signage/classrooms/{id}/schedule
Query:
start_date(yyyy-mm-dd)
end_date(yyyy-mm-dd)
Response
{
"code": 0,
"message": "success",
"data": {
"items": [
{
"start_time": "2026-02-04T08:00:00+08:00",
"end_time": "2026-02-04T09:40:00+08:00",
"course_id": 12,
"course_name": "Calculus",
"course_code": "MATH101",
"teacher_name": "张三",
"class_name": "计科2024",
"sections": [1, 2],
"source": "course"
}
]
}
}
班牌端可拉取教室配置:
GET /api/v1/signage/classrooms/{id}
返回字段包含 signage_enabled、signage_title、signage_subtitle、signage_config,
来自班牌设备表记录。
2.8 课程 API¶
2.8.1 课程列表(登录可用)¶
GET /api/v1/courses
Query(可选):
teacher_id:教师查询自己的课程
class_name:学生按班级查询课程
返回:课程基础信息 + sessions(包含 weekday、sections、week_list 等字段)。
说明:
sessions.weekday为字符串枚举:MONDAY、TUESDAY、WEDNESDAY、THURSDAY、FRIDAY、SATURDAY、SUNDAYWeb / 小程序等 API 调用方应基于该枚举值做判断,不应依赖后端内部数据库的整数编码
不提供旧
0-6整数 weekday 协议兼容
2.8.2 导入课程表 Excel(superadmin / secretary)¶
POST /api/v1/courses/import
Content-Type: multipart/form-data
字段:
file:Excel 文件(
.xlsx/.xls)semester_start_date:学期开始日期(
YYYY-MM-DD)
说明:
权限:仅
superadmin/secretary文件格式:
.xlsx/.xls,最大 50MBExcel 中
星期列沿用教务系统导入格式:1-7(1=周一,7=周日),也支持周一/星期一等中文写法导入模板必须包含
课程序号列,缺失会直接报错错误列表最多返回 20 条,超过时
error_report_available = true
返回(示例):
{
"code": 0,
"message": "导入完成:成功 85 条,跳过 10 条",
"data": {
"total_rows": 100,
"processed": 85,
"skipped": 10,
"created": 50,
"updated": 35,
"errors": [],
"error_report_available": false
}
}
3. 教室借用流程 API¶
3.1 发起借用申请(3 类用户权限不同)¶
所有登录用户均可申请:
student → counselor
chinese_teacher → assistant
foreign_teacher → assistant
POST /api/v1/borrow
Body
{
"classroom_id": 121,
"start_time": "2025-04-12T09:00:00",
"end_time": "2025-04-12T11:00:00",
"reason": "Lecture",
"expected_students": 30,
"activity_type": "student_activity" | "teaching_activity",
"is_urgent": true | false,
"source_type": "manual" | "course",
"auto_generated": true | false,
"applicant_id": 12,
"applicant_code": "2024123456"
}
说明:
applicant_id/applicant_code仅superadmin/secretary/assistant可用,用于代用户提交申请;普通用户忽略该字段。source_type/auto_generated为后端字段,手动申请时由后端固定为manual/false。
业务规则:
时间限制(与
is_urgent、申请人角色有关):assistant/superadmin:不受时间限制student:仅允许申请未来 +1 到 +7 天chinese_teacher/foreign_teacher/counselor/secretary:仅允许申请未来 至少 +1 天is_urgent=true(加急):只能选择 当天
时间冲突:
与已有手动借用冲突:
time conflict with existing borrow application与课程表冲突:
time conflict with course schedule
3.2 借用申请列表(按角色查看)¶
GET /api/v1/borrow
Query:
status
reviewer
applicant
mine(可选,
true/1时只看自己的申请)source_type(可选,
manual/course)review_level(可选,
first_review/second_review)activity_type(可选,
student_activity/teaching_activity)start_date / end_date
page, page_size(兼容 size)
3.3 申请详情¶
GET /api/v1/borrow/{id}
3.4 审核申请(assistant / counselor / superadmin)¶
PUT /api/v1/borrow/{id}/review
Body
{
"action": "approve" | "reject" | "forward",
"remark": "理由",
"forward_to": "superadmin"
}
forward_to: only when action=forward
系统自动触发:
微信推送(中方教师/学生)
邮件推送(外方教师) 说明:
当申请处于
first_review,action=approve会将申请流转到second_review(状态仍为pending)。当申请处于
second_review,action=approve才会最终approved。assistant/superadmin允许自审自己的申请,其余角色禁止自审。
3.5 申请者主动取消(诚信扣分)¶
PUT /api/v1/borrow/{id}/cancel
自动检查:
是否超过课程开始 6 小时
若违反 → 扣信用分
信用分低于 3 → 禁止借用(分数记录接口在用户模块)
3.6 获取同时段空闲教室(紧急换教室用)¶
GET /api/v1/classrooms/free
Query:
start_time
end_time
3.7 课程借用改期(申请人或管理员)¶
仅支持对 source_type=course 且 status=approved 的记录改期:原记录会被取消(cancelled),同时创建一条新的 course 记录并直接 approved。
POST /api/v1/borrow/{id}/reschedule
Body:
{
"classroom_id": 121,
"start_time": "2026-01-20T08:00:00+08:00",
"end_time": "2026-01-20T09:50:00+08:00"
}
权限:申请人本人,或 superadmin/secretary/assistant。
4. 报修流程 API¶
4.1 普通报修(所有登录用户)¶
POST /api/v1/repairs
Body:
{
"classroom_id": 121,
"description": "投影仪无法开机",
"images": ["url1", "url2"]
}
限制:
同一教室存在未完成工单 → 禁止重复提交
4.2 紧急报修¶
POST /api/v1/repairs/emergency
返回内容:
当日值班 assistant 的电话号码
同时创建工单
4.3 工单列表(assistant/superadmin 查看全部)¶
GET /api/v1/repairs
权限:
assistant/superadmin/counselor:查看全部其他角色:仅查看自己创建的工单
4.4 更新工单(assistant/superadmin/counselor)¶
PUT /api/v1/repairs/{id}
Body:
{
"status": "processing" | "completed",
"remark": "处理说明"
}
4.5 报修人确认维修完成¶
PUT /api/v1/repairs/{id}/confirm
5. 举报滥用 API¶
5.1 提交举报(所有登录用户)¶
POST /api/v1/abuse
Body:
{
"classroom_id": 121,
"description": "发现教室被外人占用",
"images": []
}
5.2 管理员查看举报(superadmin)¶
GET /api/v1/abuse
5.3 举报处理¶
PUT /api/v1/abuse/{id}
6. 公共工具 API¶
6.1 附件上传¶
POST /api/v1/upload
Content-Type: multipart/form-data
返回:
{
"code": 0,
"message": "success",
"data": { "url": "/media/uploads/<uuid>.<ext>" }
}
说明:
支持两种后端:本地磁盘与 S3 兼容对象存储,可通过环境变量
FILE_STORAGE_BACKEND(local/s3)切换。本地模式默认将文件保存到服务器的
/var/www/classroom-manager/uploads/,可用LOCAL_UPLOAD_DIR和LOCAL_UPLOAD_URL_PREFIX覆盖存储路径与访问前缀。S3 模式需要提供
S3_BUCKET_NAME、S3_ACCESS_KEY_ID、S3_SECRET_ACCESS_KEY,可选S3_ENDPOINT_URL或S3_BASE_URL用于自定义访问域名(适配任意 S3 兼容服务)。需要登录(
Authorization: Bearer <token>)。当前实现为本地磁盘上传,返回值为站内可访问的相对路径。
6.2 获取系统配置¶
GET /api/v1/config
返回:
{
"code": 0,
"message": "success",
"data": {
"season": "winter",
"season_display": "冬季作息",
"updated_at": "2026-01-20T10:00:00+08:00"
}
}
6.3 设置季节作息(仅 superadmin)¶
POST /api/v1/config/season
Body:
{ "season": "winter" }
7. 常用数据结构(模型)¶
7.1 User¶
基于原始需求文档直接映射:
{
"id": 1,
"user_code": "2024123456",
"username": "2024123456",
"full_name": "张三",
"email": "123@school.edu",
"wxid": "wx_xxxxx",
"role": "student",
"roles": ["student"],
"current_role": "student",
"status": "active",
"student_class": "计uc24x班",
"date_joined": "2025-01-01T10:00:00",
"last_login": "2025-03-10T09:00:00",
"is_totp_enabled": false
}
7.2 Classroom¶
来自数据库模板
{
"id": 88,
"building": "A楼",
"room_number": "A101",
"capacity": 60,
"equipment": {
"air_conditioner": true,
"projector": true
},
"status": "available"
}
7.3 Borrow Application¶
{
"id": 103,
"applicant_id": 12,
"reviewer_role": "assistant",
"classroom_id": 88,
"start_time": "...",
"end_time": "...",
"reason": "lecture",
"status": "pending"
}
约束说明:
start_time必须晚于当前时间至少 6 小时,且end_time必须晚于start_time。同一教室在相交时间段内只能存在待审核或已批准的唯一申请,提交时会校验时间冲突。
申请时间限制与申请人角色、
is_urgent有关(详见3.1)。冲突校验同时检查:
已有手动借用(
pending/approved且source_type=manual)课程表(
CourseSession)
8. 操作审计日志¶
仅超级管理员、秘书、助理(或 Django 后台管理员)可以访问日志接口,所有数据均由后端记录,前端传参仅用于过滤。日志以追加写入的形式保存。
8.1 获取日志列表¶
GET /api/v1/logs/
查询参数:
start_date/end_date:时间范围,支持日期(2025-12-14)或 ISO 时间字符串。user:用户 ID。role:用户角色标识,如superadmin、assistant。module:业务模块名称。action:动作名称。
返回值使用默认分页结构,每条记录包含用户、角色、模块、动作、目标类型/ID、请求 IP、UA、附加信息以及创建时间等字段。
8.2 导出 CSV¶
GET /api/v1/logs/export/
支持与列表相同的过滤参数,返回 text/csv 文件,字段顺序与列表保持一致,便于审计归档。
9. 课堂签到 API¶
9.1 开启课程签到(教师开关)¶
POST /api/v1/checkin-configs/enable
Body:
{
"course_id": 12,
"start_date": "2026-02-01",
"end_date": "2026-06-30"
}
说明:
任课教师或
superadmin/secretary/assistant可调用未传
start_date/end_date时,默认按课程起止日期生成只写入
CheckinSession.sections(节次),不落地具体时间
响应示例:
{
"code": 0,
"message": "checkin enabled",
"data": {
"course_id": 12,
"enabled": true,
"start_date": "2026-02-01",
"end_date": "2026-06-30",
"created": 32,
"skipped": 0
}
}
9.2 关闭课程签到¶
POST /api/v1/checkin-configs/disable
Body:
{
"course_id": 12
}
9.3 签到场次列表¶
GET /api/v1/checkin-sessions
Query(可选):
course_id
classroom_id
status
date(单日)
start_date / end_date
9.4 签到记录列表¶
GET /api/v1/checkin-records
Query(可选):
session_id
student_id
status
9.5 教师手动签到¶
POST /api/v1/checkin-records/manual
Body:
{
"session_id": 101,
"student_id": 2001,
"status": "present",
"remark": ""
}
说明:
仅任课教师或
superadmin/secretary/assistant可调用status支持present/late/absent/leave