# Backend API design Author: Zhenyu Yang , Sixu Wei 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 返回结构如下: 成功 ```text { "code": 0, "message": "success", "data": { ... } } ``` 失败 ```json { "code": 40001, "message": "User not found" } ``` ## 1. 认证与用户账号 ### 1.1 登录 微信用户扫码绑定后登录 ```bash POST /api/v1/auth/login/wechat ``` Body ```json { "wxid": "xxxx" } ``` 邮箱/学号/工号 + 密码登录 ```bash POST /api/v1/auth/login/email ``` Body ```text { "email": "teacher@school.edu", // 支持邮箱或 user_code "password": "your_password", "totp_code": "123456" // 当账号启用 TOTP 时必填 } ``` > 已启用 TOTP 的账号在使用微信登录时,同样需要在请求体中携带 `totp_code` 字段。 #### 1.1.1 双因素认证(TOTP) 为账号启用基于时间的一次性密码: ```bash POST /api/v1/auth/totp/setup ``` 返回值示例: ```json { "code": 0, "message": "success", "data": { "secret": "BASE32SECRET", "provisioning_uri": "otpauth://totp/Classroom%20Manager:tester%40school.edu?..." } } ``` 完成扫描后提交验证码以启用: ```bash POST /api/v1/auth/totp/enable ``` Body ```json { "totp_code": "123456" } ``` #### 1.1.2 无密码登录(WebAuthn) 本系统支持使用安全密钥 / 平台设备进行 WebAuthn 认证,流程分为「注册密钥」和「登录」两步。所有接口均遵循统一 `success/error` 返回结构。 ##### 注册安全密钥(需登录后操作) 1) 请求注册参数(传递可选 `device_name` 便于备注设备): ```bash POST /api/v1/auth/webauthn/options/register ``` 返回值包含浏览器 `navigator.credentials.create` 所需的 `publicKey` 参数。 2) 提交浏览器生成的凭证: ```bash POST /api/v1/auth/webauthn/register ``` Body 示例: ```text { "credential": { ... }, "device_name": "MacBook Touch ID" } ``` ##### 使用安全密钥登录(匿名可访问) 1) 请求登录参数: ```bash POST /api/v1/auth/webauthn/options/login ``` Body ```json { "identifier": "teacher@school.edu" } ``` 2) 提交认证结果以换取 JWT: ```bash POST /api/v1/auth/webauthn/login ``` Body ```text { "credential": { ... } } ``` 关闭 TOTP 认证: ```bash POST /api/v1/auth/totp/disable ``` Body(如当前已启用,需带上验证码确认): ```json { "totp_code": "123456" } ``` ### 1.2 管理员(superadmin / secretary)邀请外方教师注册 ```bash POST /api/v1/users/invite-foreign ``` Body ```json { "email": "teacher@school.edu", "full_name": "John Smith" } ``` ### 1.3 邮箱注册(外方教师) ```bash POST /api/v1/auth/register/email ``` Body ```json { "email": "teacher@school.edu", "password": "12345678", "full_name": "John Smith" } ``` ### 1.4 获取当前登录用户信息 ```bash GET /api/v1/auth/me ``` ### 1.5 用户列表(管理员) ```bash GET /api/v1/users ``` Query - role(可选) - status(可选) - search(可选,匹配姓名/学号/工号) - page, page_size(兼容 size) ### 1.6 创建用户(superadmin) ```bash POST /api/v1/users ``` ### 1.7 更新用户信息(superadmin / secretary) ```bash PUT /api/v1/users/{id} ``` ### 1.8 修改角色(superadmin) ```bash PUT /api/v1/users/{id}/role ``` Body: ```json { "role": "assistant" } ``` ### 1.9 禁用/启用账户 ```bash PUT /api/v1/users/{id}/status ``` ### 1.10 导入人员 Excel ```bash POST /api/v1/users/import Content-Type: multipart/form-data ``` 字段:file ## 2. 教室管理 API ### 2.1 获取教室列表(所有人可见,但字段不同) 未登录用户 ```bash GET /api/v1/classrooms/public ``` 返回字段(隐藏敏感信息): - building - room_number - status - 当前时间段是否占用(不含占用人信息) 登录用户(带设备信息) ```bash GET /api/v1/classrooms ``` Query: - building - capacity_min - status - page, page_size(兼容 size) ### 2.2 教室详情 (登录用户) ```bash GET /api/v1/classrooms/{id} ``` ### 2.3 创建教室(superadmin) ```bash POST /api/v1/classrooms ``` ### 2.4 更新教室信息(superadmin / assistant) ```bash PUT /api/v1/classrooms/{id} ``` ### 2.5 删除教室(superadmin) ```bash DELETE /api/v1/classrooms/{id} ``` ### 2.6 导入教室 Excel(superadmin) ```bash POST /api/v1/classrooms/import Content-Type: multipart/form-data ``` ### 2.7 教室课表 获取某一教室在指定日期范围内的占用时间段。 课表由 **已批准(approved)** 的人工借用记录(`source_type=manual`)与课程表(`CourseSession`,通常由课程导入生成)共同生成,并按照时间顺序返回一组时间块。空闲时段也会以 `occupied=false` 的块返回,便于前端直接绘制时间轴。 ```bash GET /api/v1/classrooms/{id}/schedule ``` Query: - start_date(yyyy-mm-dd) - end_date(yyyy-mm-dd) Response ```json { "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 班牌课程(公开) 班牌端获取某教室在日期范围内的课程安排(公开访问,返回课程详情)。 ```bash GET /api/v1/signage/classrooms/{id}/schedule ``` Query: - start_date(yyyy-mm-dd) - end_date(yyyy-mm-dd) Response ```json { "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" } ] } } ``` 班牌端可拉取教室配置: ```bash GET /api/v1/signage/classrooms/{id} ``` 返回字段包含 `signage_enabled`、`signage_title`、`signage_subtitle`、`signage_config`, 来自班牌设备表记录。 ## 2.8 课程 API ### 2.8.1 课程列表(登录可用) ```bash GET /api/v1/courses ``` Query(可选): - teacher_id:教师查询自己的课程 - class_name:学生按班级查询课程 返回:课程基础信息 + `sessions`(包含 `weekday`、`sections`、`week_list` 等字段)。 说明: - `sessions.weekday` 为字符串枚举:`MONDAY`、`TUESDAY`、`WEDNESDAY`、`THURSDAY`、`FRIDAY`、`SATURDAY`、`SUNDAY` - Web / 小程序等 API 调用方应基于该枚举值做判断,不应依赖后端内部数据库的整数编码 - 不提供旧 `0-6` 整数 weekday 协议兼容 ### 2.8.2 导入课程表 Excel(superadmin / secretary) ```bash POST /api/v1/courses/import Content-Type: multipart/form-data ``` 字段: - file:Excel 文件(`.xlsx`/`.xls`) - semester_start_date:学期开始日期(`YYYY-MM-DD`) 说明: - 权限:仅 `superadmin` / `secretary` - 文件格式:`.xlsx` / `.xls`,最大 50MB - Excel 中 `星期` 列沿用教务系统导入格式:`1-7`(`1=周一`,`7=周日`),也支持 `周一` / `星期一` 等中文写法 - 导入模板必须包含 `课程序号` 列,缺失会直接报错 - 错误列表最多返回 20 条,超过时 `error_report_available = true` 返回(示例): ```json { "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 ```bash POST /api/v1/borrow ``` Body ```bash { "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 借用申请列表(按角色查看) ```bash 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 申请详情 ```bash GET /api/v1/borrow/{id} ``` ### 3.4 审核申请(assistant / counselor / superadmin) ```bash PUT /api/v1/borrow/{id}/review ``` Body ```text { "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 申请者主动取消(诚信扣分) ```bash PUT /api/v1/borrow/{id}/cancel ``` 自动检查: - 是否超过课程开始 6 小时 - 若违反 → 扣信用分 - 信用分低于 3 → 禁止借用(分数记录接口在用户模块) ### 3.6 获取同时段空闲教室(紧急换教室用) ```bash GET /api/v1/classrooms/free ``` Query: - start_time - end_time ### 3.7 课程借用改期(申请人或管理员) 仅支持对 `source_type=course` 且 `status=approved` 的记录改期:原记录会被取消(`cancelled`),同时创建一条新的 `course` 记录并直接 `approved`。 ```bash POST /api/v1/borrow/{id}/reschedule ``` Body: ```json { "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 普通报修(所有登录用户) ```bash POST /api/v1/repairs ``` Body: ```json { "classroom_id": 121, "description": "投影仪无法开机", "images": ["url1", "url2"] } ``` 限制: - 同一教室存在未完成工单 → 禁止重复提交 ### 4.2 紧急报修 ```bash POST /api/v1/repairs/emergency ``` 返回内容: - 当日值班 assistant 的电话号码 - 同时创建工单 ### 4.3 工单列表(assistant/superadmin 查看全部) ```bash GET /api/v1/repairs ``` 权限: - `assistant` / `superadmin` / `counselor`:查看全部 - 其他角色:仅查看自己创建的工单 ### 4.4 更新工单(assistant/superadmin/counselor) ```bash PUT /api/v1/repairs/{id} ``` Body: ```text { "status": "processing" | "completed", "remark": "处理说明" } ``` ### 4.5 报修人确认维修完成 ```bash PUT /api/v1/repairs/{id}/confirm ``` ## 5. 举报滥用 API ### 5.1 提交举报(所有登录用户) ```bash POST /api/v1/abuse ``` Body: ```json { "classroom_id": 121, "description": "发现教室被外人占用", "images": [] } ``` ### 5.2 管理员查看举报(superadmin) ```bash GET /api/v1/abuse ``` ### 5.3 举报处理 ```bash PUT /api/v1/abuse/{id} ``` ## 6. 公共工具 API ### 6.1 附件上传 ```bash POST /api/v1/upload Content-Type: multipart/form-data ``` 返回: ```json { "code": 0, "message": "success", "data": { "url": "/media/uploads/." } } ``` 说明: - 支持两种后端:本地磁盘与 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 `)。 - 当前实现为本地磁盘上传,返回值为站内可访问的相对路径。 ### 6.2 获取系统配置 ```bash GET /api/v1/config ``` 返回: ```json { "code": 0, "message": "success", "data": { "season": "winter", "season_display": "冬季作息", "updated_at": "2026-01-20T10:00:00+08:00" } } ``` ### 6.3 设置季节作息(仅 superadmin) ```bash POST /api/v1/config/season ``` Body: ```json { "season": "winter" } ``` ## 7. 常用数据结构(模型) ### 7.1 User 基于原始需求文档直接映射: ```json { "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 来自数据库模板 ```json { "id": 88, "building": "A楼", "room_number": "A101", "capacity": 60, "equipment": { "air_conditioner": true, "projector": true }, "status": "available" } ``` ### 7.3 Borrow Application ```json { "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 获取日志列表 ```bash 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 ```bash GET /api/v1/logs/export/ ``` 支持与列表相同的过滤参数,返回 `text/csv` 文件,字段顺序与列表保持一致,便于审计归档。 ## 9. 课堂签到 API ### 9.1 开启课程签到(教师开关) ```bash POST /api/v1/checkin-configs/enable ``` Body: ```json { "course_id": 12, "start_date": "2026-02-01", "end_date": "2026-06-30" } ``` 说明: - 任课教师或 `superadmin/secretary/assistant` 可调用 - 未传 `start_date/end_date` 时,默认按课程起止日期生成 - 只写入 `CheckinSession.sections`(节次),不落地具体时间 响应示例: ```json { "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 关闭课程签到 ```bash POST /api/v1/checkin-configs/disable ``` Body: ```json { "course_id": 12 } ``` ### 9.3 签到场次列表 ```bash GET /api/v1/checkin-sessions ``` Query(可选): - course_id - classroom_id - status - date(单日) - start_date / end_date ### 9.4 签到记录列表 ```bash GET /api/v1/checkin-records ``` Query(可选): - session_id - student_id - status ### 9.5 教师手动签到 ```bash POST /api/v1/checkin-records/manual ``` Body: ```json { "session_id": 101, "student_id": 2001, "status": "present", "remark": "" } ``` 说明: - 仅任课教师或 `superadmin/secretary/assistant` 可调用 - `status` 支持 `present/late/absent/leave`