# 新时空教务管理系统 这是一个面向新时空教务业务的综合管理系统。迁移后 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/sync_to_vps.py`:旧版正式数据同步脚本,迁移后不要继续常驻运行。 - `scripts/smoke_test.js`:轻量前端行为烟测。 - `scripts/install_gitea_backup_hook.py`:安装提交后自动推送到 Gitea 的 Git hook。 - `scripts/install_launch_agent.py`:安装 Mac 开机常驻同步任务。 - `launchd/com.xsk.education-management.sync.plist.template`:LaunchAgent 模板。 ## 维护入口 推荐在仓库根目录 `/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' ``` ## 手动同步数据 迁移完成后不要再用本机 `classnotes.txt` 和 `学生课时账户.md` 覆盖 VPS。SQLite 数据库 `/data/xsk_education.db` 是唯一事实源;运行时生成的 `/data/runtime_text_cache/` 只是兼容旧业务逻辑的缓存。下面命令只保留给迁移前或灾难恢复时使用,日常新增课程小结应走 `POST /api/ingest/course-summaries`。 ```bash XSK_USE_SSHPASS=1 \ XSK_SSH_PASSWORD='填写SSH密码' \ python3 scripts/sync_to_vps.py --once --use-sshpass ``` 同步文件: - `/Users/yangdawei/Desktop/新时空业务源数据/新时空课程记录与课时账户/classnotes.txt` - `/Users/yangdawei/Desktop/新时空业务源数据/新时空课程记录与课时账户/学生课时账户.md` 远端数据目录: ```text /root/新时空教务管理系统/data/xsk_education.db ``` ## 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` 字段,用于维护“小学一年级入学年份”。排课系统只读该字段并按课程日期动态推算年级。管理后台的学生档案编辑页可以维护该字段;运行时 `学生课时账户.md` 缓存会导出为 7 列格式,同时仍兼容旧 6 列缓存导入。 ## 课程小结推送 VPS 接收接口: ```text POST /api/ingest/course-summaries Header: X-INGEST-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 后,可在容器内执行一次性导入。历史导入只重建小结库和状态;历史 `classnotes缺失.txt` 默认转为审核任务,不自动扣课时。 ```bash cd /root/新时空教务管理系统/app docker compose exec xsk-education-management python scripts/import_course_summaries.py \ --source /data/import/课程小结采集 \ --target /data/course_summaries \ --state /data/course_summary_state.json \ --tasks /data/admin_tasks.json \ --operation-logs /data/operation_logs.jsonl \ --missing-table /data/import/课程小结采集/classnotes缺失.txt ``` ## 数据备份 通过登记 API、课程小结自动入账或审核批准修改正式课时数据时,服务会以 SQLite 事务写入 `/data/xsk_education.db`。旧纯文本事实源已封存为归档包;运行时文本缓存位于: ```text /root/新时空教务管理系统/data/runtime_text_cache/ ``` 备份目录位于: ```text /root/新时空教务管理系统/data/backups/ ``` 每次登记生成一个事务备份目录,目录内包含变更前的业务文件副本和 `metadata.json`。系统自动保留最近 50 次备份,超过后删除最旧备份。 查看备份: ```bash ls -lt /root/新时空教务管理系统/data/backups/ ``` 恢复某次备份时,先停止服务,再把对应备份目录里的文件复制回数据目录,最后重启服务: ```bash cd /root/新时空教务管理系统/app docker compose stop cp /root/新时空教务管理系统/data/backups/<备份目录>/classnotes.txt /root/新时空教务管理系统/data/classnotes.txt 2>/dev/null || true cp /root/新时空教务管理系统/data/backups/<备份目录>/学生课时账户.md /root/新时空教务管理系统/data/学生课时账户.md 2>/dev/null || true docker compose up -d ``` ## 安装自动同步 ```bash XSK_USE_SSHPASS=1 \ XSK_SSH_PASSWORD='填写SSH密码' \ python3 scripts/install_launch_agent.py --use-sshpass ``` 日志位置: ```text ~/Library/Logs/xsk-education-management/sync.log ~/Library/Logs/xsk-education-management/sync.err.log ``` 查看任务: ```bash launchctl list | grep com.xsk.education-management.sync ``` 卸载任务: ```bash launchctl unload ~/Library/LaunchAgents/com.xsk.education-management.sync.plist rm ~/Library/LaunchAgents/com.xsk.education-management.sync.plist ``` ## 更换网页访问密码 登录 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`:管理后台读取小结接收、自动入账、审核批准和驳回记录。