191 lines
7.9 KiB
Markdown
191 lines
7.9 KiB
Markdown
# 新时空教务管理系统
|
||
|
||
这是一个面向新时空教务业务的综合管理系统。迁移后 VPS 是正式业务数据主机,负责保存 SQLite 数据库 `/data/xsk_education.db`;本机只保留微信群聊天记录采集/识别,并把课程小结批量推送到 VPS。
|
||
|
||
## 目录
|
||
|
||
- `app/`:FastAPI 后端和内置前端页面。
|
||
- `MAINTENANCE.md`:日常检查、部署、数据保护和回滚流程。
|
||
- `Makefile`:常用维护命令入口。
|
||
- `scripts/deploy_to_vps.py`:部署新时空教务管理系统到 VPS。
|
||
- `scripts/migrate_text_to_sqlite.py`:一次性把旧纯文本、JSON、JSONL 和课程小结 Markdown 迁移进 SQLite。
|
||
- `scripts/import_course_summaries.py`:一次性导入历史课程小结 Markdown。
|
||
- `scripts/smoke_test.js`:轻量前端行为烟测。
|
||
- `scripts/install_gitea_backup_hook.py`:安装提交后自动推送到 Gitea 的 Git hook。
|
||
|
||
## 维护入口
|
||
|
||
推荐在仓库根目录 `/root/新时空教务管理系统` 执行日常维护命令:
|
||
|
||
```bash
|
||
make check
|
||
make smoke
|
||
make deploy
|
||
```
|
||
|
||
根目录 `Makefile` 会自动转发到 `app/` 下的实际应用配置,避免在错误目录执行 `docker compose` 或 `make deploy`。需要直接运行 Docker Compose 时,使用:
|
||
|
||
```bash
|
||
docker compose -f app/docker-compose.yml <命令>
|
||
```
|
||
|
||
## 后端结构
|
||
|
||
- `app/main.py`:FastAPI 应用入口,只负责注册路由和全局异常处理。
|
||
- `app/routers/`:按业务入口拆分 API 和页面路由,包括登录页面、课程记录、学生档案、管理后台、课程小结推送和健康检查。
|
||
- `app/config.py`:路径、环境变量、Cookie 名称和进程内写锁。
|
||
- `app/auth.py`:网页登录、Basic Auth、管理后台和课程小结推送鉴权。
|
||
- `app/schemas.py`:请求体 Pydantic 模型。
|
||
- `app/api_utils.py`:API 层通用读取、文件元信息和请求体转换。
|
||
- `app/domain.py`:领域数据结构、学生/科目别名、状态和识别常量。
|
||
- `app/storage.py`:原子写入、权限继承和业务数据备份。
|
||
- `app/data.py`:业务数据解析、登记、审核、课程小结入库和查询逻辑。
|
||
|
||
## 首次部署
|
||
|
||
推荐先配置 SSH key。若临时使用密码,可通过环境变量传入,不要写入仓库文件。
|
||
|
||
```bash
|
||
cd /Users/yangdawei/Desktop/新时空业务源数据/tools/xsk-education-management
|
||
XSK_USE_SSHPASS=1 \
|
||
XSK_SSH_PASSWORD='填写SSH密码' \
|
||
XSK_WEB_PASSWORD='填写网页访问密码' \
|
||
python3 scripts/deploy_to_vps.py --use-sshpass
|
||
```
|
||
|
||
默认访问地址:
|
||
|
||
```text
|
||
http://121.199.172.246:18080/
|
||
```
|
||
|
||
默认网页用户名为 `wolfydw`。网页密码只写入 VPS 的 `/root/新时空教务管理系统/app/.env`,不会提交进 Git。
|
||
|
||
如果 VPS 无法访问 Docker Hub,部署脚本会默认使用 `swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/python:3.12-slim` 作为基础镜像。需要更换时设置:
|
||
|
||
```bash
|
||
XSK_PYTHON_IMAGE='python:3.12-slim'
|
||
```
|
||
|
||
## SQLite 迁移
|
||
|
||
首次迁移先 dry-run:
|
||
|
||
```bash
|
||
cd /root/新时空教务管理系统
|
||
make migrate-sqlite-dry-run
|
||
```
|
||
|
||
确认严格校验通过后执行正式迁移:
|
||
|
||
```bash
|
||
make migrate-sqlite
|
||
```
|
||
|
||
正式迁移会生成:
|
||
|
||
```text
|
||
/root/新时空教务管理系统/data/xsk_education.db
|
||
/root/新时空教务管理系统/data/sqlite_migration_report_<时间>.json
|
||
/root/新时空教务管理系统/archives/text-source-before-sqlite-<时间>.tar.gz
|
||
/root/新时空教务管理系统/archives/text-source-before-sqlite-<时间>.tar.gz.sha256
|
||
```
|
||
|
||
学生表包含 `primary_entry_year` 字段,用于维护“小学一年级入学年份”。排课系统只读该字段并按课程日期动态推算年级。管理后台的学生档案编辑页可以维护该字段;旧 6/7 列 `学生课时账户.md` 仅作为一次性迁移输入兼容。
|
||
|
||
## 课程小结推送
|
||
|
||
VPS 接收接口:
|
||
|
||
```text
|
||
POST /api/ingest/course-summaries
|
||
Header: X-INGEST-TOKEN: <VPS .env 中的 INGEST_AUTH_TOKEN>
|
||
```
|
||
|
||
本机采集脚本默认在 `--write` 时推送到该接口。建议在本机 shell 配置:
|
||
|
||
```bash
|
||
export XSK_INGEST_URL='http://121.199.172.246:18080/api/ingest/course-summaries'
|
||
export XSK_INGEST_TOKEN='填写VPS里的INGEST_AUTH_TOKEN'
|
||
```
|
||
|
||
然后运行:
|
||
|
||
```bash
|
||
python3 /Users/yangdawei/Desktop/新时空业务源数据/新时空课程记录与课时账户/课程小结采集/批量采集微信课程小结.py --write
|
||
```
|
||
|
||
推送成功批次会归档到本机 `课程小结采集/推送归档/`,失败批次会进入 `课程小结采集/推送失败队列/`,可用 `--retry-failed` 重试。需要临时恢复旧流程时再加 `--local-write`。
|
||
|
||
## 历史小结导入
|
||
|
||
把本机历史课程小结目录同步或上传到 VPS 后,可在容器内执行一次性导入。历史导入直接写入 SQLite 课程小结表;历史 `classnotes缺失.txt` 默认转为审核任务,不自动扣课时。
|
||
|
||
```bash
|
||
cd /root/新时空教务管理系统/app
|
||
docker compose exec xsk-education-management python scripts/import_course_summaries.py \
|
||
--source /data/import/课程小结采集 \
|
||
--db-path /data/xsk_education.db \
|
||
--missing-table /data/import/课程小结采集/classnotes缺失.txt
|
||
```
|
||
|
||
## 数据备份
|
||
|
||
通过登记 API、课程小结自动入账或审核批准修改正式课时数据时,服务会以 SQLite 事务写入 `/data/xsk_education.db`。旧纯文本事实源已封存为归档包,不再作为运行时缓存参与读写。
|
||
|
||
备份目录位于:
|
||
|
||
```text
|
||
/root/新时空教务管理系统/data/backups/
|
||
```
|
||
|
||
每次写业务数据前生成一个 SQLite 快照备份目录,目录内包含变更前的数据库快照和 `metadata.json`。系统自动保留最近 50 次备份,超过后删除最旧备份。
|
||
|
||
查看备份:
|
||
|
||
```bash
|
||
ls -lt /root/新时空教务管理系统/data/backups/
|
||
```
|
||
|
||
恢复某次备份优先使用后台“操作记录”里的撤回按钮。手工恢复时先停止服务,再把对应备份目录里的 `xsk_education.db` 作为数据库恢复源,最后重启服务:
|
||
|
||
```bash
|
||
cd /root/新时空教务管理系统/app
|
||
docker compose stop
|
||
cp /root/新时空教务管理系统/data/backups/<备份目录>/xsk_education.db /root/新时空教务管理系统/data/xsk_education.db
|
||
docker compose up -d
|
||
```
|
||
|
||
## 更换网页访问密码
|
||
|
||
登录 VPS 后修改 `/root/新时空教务管理系统/app/.env` 中的 `BASIC_AUTH_PASSWORD`,然后重启:
|
||
|
||
```bash
|
||
cd /root/新时空教务管理系统/app
|
||
docker compose up -d
|
||
```
|
||
|
||
管理后台使用 `ADMIN_AUTH_PASSWORD`。为兼容旧部署,如果未配置 `ADMIN_AUTH_PASSWORD`,系统会继续使用原 `ACCOUNTS_AUTH_PASSWORD` 或 `ACCOUNT_AUTH_PASSWORD`。
|
||
|
||
## API
|
||
|
||
- `GET /api/health`:数据状态。
|
||
- `GET /api/records?q=王鑫鹏5月数学课`:自然语言查询上课记录。
|
||
- `GET /api/students`:学生档案列表。
|
||
- `GET /api/students?q=王鑫鹏`:按学生姓名或学生ID筛选学生档案。
|
||
- `GET /api/students?status=欠费`:按档案状态筛选。
|
||
- `GET /api/students/王鑫鹏`:单个学生档案。
|
||
- `POST /api/admin/students`:管理后台新增学生档案。
|
||
- `PUT /api/admin/students/{student_id}`:管理后台修改学生档案。
|
||
- 学生档案的剩余课时由系统按缴费记录和上课记录自动计算,管理接口不会接受人工修改余额。
|
||
- `GET /api/admin/teachers`:管理后台读取老师档案。
|
||
- `POST /api/admin/teachers`:管理后台新增老师档案。
|
||
- `PUT /api/admin/teachers/{teacher_id}`:管理后台修改老师档案。
|
||
- `POST /api/corrections`:课程记录页提交纠错审核。
|
||
- `GET /api/admin/tasks`:管理后台查看审核任务。
|
||
- `POST /api/admin/tasks/{task_id}/approve`:批准纠错并写入正式上课记录。
|
||
- `POST /api/admin/tasks/{task_id}/reject`:驳回纠错。
|
||
- `POST /api/ingest/course-summaries`:本机采集脚本批量推送课程小结,使用 `X-INGEST-TOKEN` 鉴权。
|
||
- `GET /api/admin/course-summaries`:管理后台只读查询正式课程小结库。
|
||
- `GET /api/admin/operation-logs`:管理后台读取小结接收、自动入账、审核批准和驳回记录。
|