feat: 改写工作台体验优化 — 中文对照翻译 + 字数控制提示 + 复检历史/按建议再次改写 + 输入法组合期不误发送

- 新增 POST /api/translate(build_translate_prompt): 英文改写稿忠实直译成中文,供顾问自查改写后原意是否保留
- 改写区「译成中文对照」按钮 + 译文展开/收起;改写稿变化后旧译文自动过期(缓存按文本比对)
- 每段字数控制提示: rewrite-meta 显示「原文 X 词 · 当前 Y 词」,偏差过大黄色提醒;
  顶部进度加「全文 X / wordLimit 词」,超出题目字数限制标红
- 复检汇总建议历史: 每次复检入历史(状态/未通过检查项/返工目标/绑定版本,上限 10 条);
  Workbench 提交区 + 复检卡两处入口;历史条目「按此建议再次改写」回到目标段并显示返工 banner
- 对话输入框: 中文输入法组合期(isComposing/keyCode 229)回车不再误发送
- 测试: 新增 /api/translate 3 个 hermetic 测试(31 passed);浏览器实测 18/18 通过
This commit is contained in:
LuminousRuoxi
2026-09-10 14:09:31 +08:00
parent 36b7e601e7
commit 85a2eb720a
5 changed files with 269 additions and 11 deletions
+26
View File
@@ -510,6 +510,32 @@ def test_api_scaffold_shape():
assert "liked" in r.json()["scaffold"]
def test_api_translate_shape():
payload = {"translation": "我不断回到这个问题上。"}
r = api_client(payload).post(
"/api/translate",
json={"text": "I kept coming back to the problem.", "paragraph_id": "p3"},
)
assert r.status_code == 200
assert r.json()["translation"].startswith("我不断回到")
assert r.json()["paragraph_id"] == "p3"
def test_api_translate_coerces_list_translation():
"""模型偶发把 translation 返回成数组 —— 归并为一个字符串,不 502。"""
r = api_client({"translation": ["第一句。", "第二句。"]}).post(
"/api/translate", json={"text": "One. Two."}
)
assert r.status_code == 200
assert r.json()["translation"] == "第一句。第二句。"
def test_api_translate_empty_translation_502():
r = api_client({"translation": " "}).post("/api/translate", json={"text": "Hello."})
assert r.status_code == 502
assert "翻译结果为空" in r.json()["detail"]
def test_complete_json_paragraph_count_mismatch_retries_once():
"""语义校验:段落数不匹配视为一次失败并自动重试,重试成功返回完整结果。
真实 LLM 偶发返回合法 JSON 但段落条目不全(AI 初审"4 段只显示 1 段"),