docs: add P3b PR report

This commit is contained in:
potaser
2026-10-13 11:23:01 +08:00
parent e036301e1a
commit 4e19350115
@@ -0,0 +1,69 @@
# PR 报告:P3b 编译 PDF Tab(论文重排版面板)
- 日期:2026-10-13
- 分支:`feature/p3b-compile-ui`(自最新 main 新开;未 commit,按用户约定统一处理)
- 范围:`ui/` 面板 + store/api 扩展;`review_service/` 仅 restart.sh 调起预热脚本 + 新增
scripts/prewarm_tectonic.sh。**后端 compile.py / latex_compile.py(P3a)零改动**;
无 sdk/、agent/、vstore/ 改动;无新增依赖。
## 概要
P3b:论文重排版面板启用"编译 PDF" Tab,实现"上传 .tex → 服务器编译 → 下载 PDF"的完整闭环。
## 修改内容
| 文件 | 变更 |
|---|---|
| ui/src/components/edu/panels/ReformatPanel.vue | 编译 Tab 状态机:无 job_id 引导 / 编译按钮 / loading 动画 + 首次 1-3 分钟黄条(可关闭)/ 成功 blob URL iframe 预览 + 下载 + 耗时 + 重新编译 / 失败错误摘要 + log 尾 200 行折叠 + 完整 log 下载;按钮不 await,状态全由 store 驱动(切 Tab/切面板编译继续) |
| ui/src/stores/edu.js | compileStatus/compileResult/compileError/compileLogTail + compilePdfUrl(blob URL,fetch 失败静默回退 pdf_url 直链)+ compileFirstHint;submitCompile(loading 重入保护)/ clearCompile(revoke blob);重新排版自动 clearCompile |
| ui/src/api/review.js | CODE_HINTS 增 QUEUE_FULL 固定文案"编译队列已满(最多 5 个任务),请稍后重试"(后端 message 带动态 pending 数,规范统一口径);compileTex() 为 P3a 已有封装 |
| review_service/restart.sh | 启动后后台调起 prewarm_tectonic.sh(nohup 非阻塞,日志 prewarm.log) |
| review_service/scripts/prewarm_tectonic.sh(新增) | 最小 hello.tex 实编译以缓存 TeX 环境。**注**:tectonic v0.17.0 无 `download` 子命令(实测 `no subcommand download`),改用 tools/README 的最小 .tex 预编译法;失败仅告警不影响服务启动 |
| tests/frontend/unit/edu/reformat.compile.test.js(新增) | 6 个用例(真实 reviewErrorMessage 经 importOriginal 保留,QUEUE_FULL 走 CODE_HINTS) |
## 关键实现决策
1. **无异步轮询**:后端编译同步阻塞返回(单槽队列,常规 10-30s,上限 `compile_queue_limit=5`),
无 stage 可显示 → loading 只做不确定时长旋转动画 + 文案说明。
2. **QUEUE_FULL**:HTTP 429 + 同款信封,http.js 抛 ApiError(code=QUEUE_FULL);
前端 CODE_HINTS 固定文案,报错后"重新编译"按钮立即可用(store finally 解锁)。
3. **PDF blob URL**:成功后异步 `fetch(pdf_url) → blob → createObjectURL`,
预览/下载不暴露后端路径;jsdom/网络失败回退 pdf_url 直链,不阻塞渲染。
4. **失败 log**:信封 detail = log 尾 200 行(折叠 `<pre>`);完整 log 下载兜底拼
`/api/review/compile/{job_id}/log`(失败信封不带 log_url,但 job_id 即 anchor_id)。
5. **首次编译提示条**:`compileFirstHint` 在首次 submitCompile 置位,loading 期间显示,
可手动关闭;`clearCompile`(重新排版)复位。
6. **预热命令修正**:任务原文 `./tools/tectonic -X download default` 在钉死版本
v0.17.0 不存在——实测后改为最小 .tex 实编译预热(同 tools/README.md 建议)。
## 测试结果
- 后端 pytest(review_service,后端未动):**113 passed**
- 前端 vitest 全量:**403 passed / 5 failed**(5F = 既有 labels.js 基线失败
benchpanel×4 + Composer pill×1,与本 PR 无关)
- vitest 新增 reformat.compile.test.js:**6/6 passed**
(无 job_id 引导 / 按钮可点 / 编译中+黄条+重入保护 / 成功 iframe+下载+耗时 /
失败 log 折叠 / QUEUE_FULL 文案+重试可用)
- npm run build:✓ 3.12s
## 手工冒烟(8100 真实链路)
- reformat /tmp/opencode/reformat_sample.tex → ok=True job_id=b3631727af68
- POST /compile {job_id=b3631727af68} → ok=True seconds=0.61 pdf_bytes=3596
- GET /compile/{cid}/pdf → 200,3596 bytes,application/pdf(file: PDF 1.5)
- GET /compile/{cid}/log → 200,3533 bytes
- job_id 不存在 / 格式非法 → VALIDATION 信封
- 坏 tex(\thisCommandDoesNotExist)→ COMPILE_FAILED + detail 尾 200 行
(含 "! Undefined control sequence")
- QUEUE_FULL → 429 + 信封(后端路径实测于 P3a;前端文案 vitest 6/6 覆盖)
- scripts/prewarm_tectonic.sh → exit=0 OK,宏包缓存就绪
## 部署验证(部署后执行)
```bash
bash review_service/restart.sh
# 观察日志:prewarm_tectonic.sh 后台跑(非阻塞),prewarm.log 出现 "[prewarm] OK"
# 浏览器 → 教育科研 → 论文自动重排版 → 上传 .tex → 选期刊 → 重排版
# → 切"编译 PDF" → 点编译
# 期望:首次 1-3 分钟(若预热已完成则秒级)、后续秒回;失败可见 log 尾 200 行
```