nonvioce 9edacd5653 docs: update server README — backup strategy, import queue, admin APIs 3 месяцев назад
..
app 72d9a9fe75 fix: export numbering — use unique numId to avoid conflict with python-docx defaults 3 месяцев назад
src f21733d0ab Initial commit: 题库PLUS C/S架构数学题库管理系统 3 месяцев назад
web f21733d0ab Initial commit: 题库PLUS C/S架构数学题库管理系统 3 месяцев назад
README.md 9edacd5653 docs: update server README — backup strategy, import queue, admin APIs 3 месяцев назад
config.yaml f21733d0ab Initial commit: 题库PLUS C/S架构数学题库管理系统 3 месяцев назад
install.sh c344f4a98a refactor: merge run.sh into tiku-server serve --restart 3 месяцев назад
requirements.txt f21733d0ab Initial commit: 题库PLUS C/S架构数学题库管理系统 3 месяцев назад
tiku-server f21733d0ab Initial commit: 题库PLUS C/S架构数学题库管理系统 3 месяцев назад

README.md

题库PLUS 服务端

C/S 架构数学题库管理系统 — 服务端。Python + FastAPI + SQLite,以 docx 原生格式存储题目。

快速部署

git clone ssh://git@xn--48s96u.top:10022/nonvioce/tiku.git /opt/tiku-server
cd /opt/tiku-server/tiku-server
bash install.sh                                    # 安装依赖、构建知识点
nohup ./tiku-server serve --restart > tiku.log 2>&1 &  # 后台启动(崩溃/更新自动重启)

部署后打开 http://<服务器IP>:8765,Token 首次启动自动生成(./tiku-server token 查看)。

目录结构

tiku-server/
├── app/
│   ├── config.py           # YAML 配置加载(路径、端口、Token)
│   ├── database.py         # SQLite 连接、建表、CRUD、FTS5
│   ├── models.py           # Pydantic 请求/响应模型
│   ├── main.py             # FastAPI 入口 + CLI 入口
│   ├── routers/            # API 路由层(仅参数校验和 HTTP 返回)
│   │   ├── auth.py         # Token + HMAC 签名认证
│   │   ├── problems.py     # 题目 CRUD、搜索、渲染、标注
│   │   ├── import_.py      # 整卷 docx 上传拆分导入
│   │   ├── export_.py      # 按章节/试题篮导出 docx
│   │   ├── knowledge.py    # 知识点树浏览和搜索
│   │   ├── carts.py        # 试题篮 CRUD
│   │   └── admin.py        # 备份、索引重建、知识点构建、Git 更新
│   └── services/           # 业务逻辑层
│       ├── knowledge.py    # 5层知识点树解析(Markdown → 编码映射)
│       ├── docx_parser.py  # 整卷 docx 拆分 + 单题 docx 生成
│       ├── docx_builder.py # 多题 docx 合并导出
│       ├── indexer.py      # 增量索引(mtime+checksum 检测变更)
│       ├── renderer.py     # pandoc docx→HTML+MathJax 渲染管线
│       ├── backup.py       # 本地备份 + WebDAV 远程推送
│       └── search.py       # FTS5 全文搜索封装
├── data/                   # 运行时数据(不提交 Git)
│   ├── problems/           # 单题 docx(<sha256-8>.docx)
│   ├── bank.db             # SQLite 数据库
│   ├── papers/             # 导出试卷
│   ├── backups/            # 自动备份(保留 30 个)
│   └── uploads/            # 上传临时文件
├── src/
│   ├── 知识点树.md          # 5层 Markdown 知识树(1811 叶)
│   └── knowledge_map.json  # 编码→路径映射(knowledge build 生成)
├── web/                    # Flutter Web 构建产物(可选)
├── config.yaml             # 配置文件
├── install.sh              # 安装脚本
├── tiku-server             # CLI 入口
└── requirements.txt        # Python 依赖

CLI 命令

命令 说明
./tiku-server serve 启动 FastAPI 服务
./tiku-server serve --restart 启动服务(崩溃/git-update 后自动重启)
./tiku-server knowledge build 解析 src/知识点树.md 生成编码映射
./tiku-server rebuild-index 手动增量扫描 problems/ 目录
./tiku-server stats 终端显示题库统计
./tiku-server backup 创建本地备份快照
./tiku-server backup --remote 备份并推送到 WebDAV
./tiku-server token 显示 API Token
./tiku-server token regenerate 重新生成 Token

API 参考

认证

所有需要认证的端点必须携带:

  • Authorization: Bearer <token>
  • X-Timestamp: <unix_timestamp>(5 分钟内有效)
  • X-Signature: HMAC-SHA256(token, METHOD+PATH+timestamp)(hex 编码)
方法 路径 认证 说明
GET /api/health 否 健康检查
POST /api/auth/verify 否 验证 Token

题库查询

方法 路径 参数 说明
GET /api/stats — 仪表盘统计(总数、按题型/类型/章节分布)
GET /api/problems page, page_size, chapter, question_type, import_type, annotated 题目列表(分页+筛选)
GET /api/problems/{id} — 题目详情(含渲染 HTML)
GET /api/problems/{id}/render include_answer 题目 HTML 渲染片段(JSON)
GET /api/problems/{id}/view token, include_answer 题目完整 HTML 页面(IFrame 用,Token 在 URL 中)
GET /api/problems/next-unannotated current_id, direction 连续标注导航
GET /api/search q, page, page_size 全文搜索(FTS5 trigram)

元数据编辑

方法 路径 说明
PUT /api/problems/{id}/metadata 更新元数据(难度、题型、类型、评语)
PUT /api/problems/{id}/knowledge 更新知识点编码

导入导出

方法 路径 说明
POST /api/import 上传整卷 docx(multipart: file + import_type)
GET /api/import/{task_id}/status 轮询导入进度
POST /api/export/chapter 按章节+类型导出(JSON body: chapter, import_type, title)
POST /api/export/cart/{id} 按试题篮导出
GET /api/exports/{filename} 下载导出 docx 文件

知识点

方法 路径 说明
GET /api/knowledge/tree 完整知识树(5层嵌套 JSON)
GET /api/knowledge/search 搜索知识点(q 参数)

试题篮

方法 路径 说明
GET /api/carts 篮子列表(含题目数量)
POST /api/carts 创建篮子(JSON: name)
DELETE /api/carts/{id} 删除篮子
GET /api/carts/{id} 篮子详情(含题目列表)
POST /api/carts/{id}/items 添加题目(JSON: problem_id)
DELETE /api/carts/{id}/items/{pid} 移除题目

管理

方法 路径 说明
GET /api/admin/backup-config 查看 WebDAV 配置
PUT /api/admin/backup-config 设置 WebDAV(JSON: url, username, password)
POST /api/admin/backup/trigger 增量备份(bank.db + 变更的 docx)
POST /api/admin/full-backup 全量备份(bank.db + 全部 docx)
GET /api/admin/backup/history 备份历史
POST /api/admin/clear-all 清空题库(删除所有题目)
POST /api/admin/rebuild-index 增量重建索引
POST /api/admin/knowledge-build 重建知识点编码
POST /api/admin/git-update git pull + 自动重启

备份策略

  • 增量备份:导入/编辑元数据时自动备份 bank.db + 被修改的 docx
  • 全量备份:POST /api/admin/full-backup,备份全部 docx
  • WebDAV:配置后每次本地备份自动推送到远程(坚果云/NextCloud)
  • 保留 30 个快照,自动清理旧备份

导入队列

导入使用单线程队列处理,避免并发写入 SQLite 导致数据库损坏。/api/health 返回 queue_depth 可查看队列长度。

单题 docx 格式

[题目正文段落(含 OMML 公式、图片、选项)]
【答案】X                         ← 分割线
【分析】解题思路...                (可选)
【详解】详细步骤...                (可选)
【点睛】...                       (可选)

自定义属性(custom.xml,Word 不可见):

  • question_type:单选题 / 多选题 / 填空题 / 解答题
  • difficulty:0~1 浮点数,越大越容易
  • knowledge_codes:JSON 数组,如 ["01.01.03.02.01"]
  • import_type:精选题 / 经典题 / 高考题
  • comment:评语
  • source:来源文件名

数据库结构

problems (id, file_path, mtime, checksum, chapters, difficulty,
          question_type, import_type, knowledge_codes, comment, source, ...)

problems_fts (problem_id, body) — FTS5 trigram 全文索引

knowledge_points (code, path, leaf_name, chapter_code, chapter_name)

carts (id, name, created_at)

cart_items (cart_id, problem_id, added_at) — 联合主键

import_tasks (id, status, total, completed, message, result)

域名转换

中文域名 数学.top 的 punycode 编码为 xn--48s96u.top,在 Git remote 等处使用:

ssh://git@xn--48s96u.top:10022/nonvioce/tiku.git