From 671783eb1e6561e566552a9f144f6556461de06d Mon Sep 17 00:00:00 2001 From: admin Date: Thu, 10 Sep 2026 16:17:11 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix(ui):=20r3=20=E5=89=8D=E7=AB=AF=2010=20?= =?UTF-8?q?=E9=A1=B9=E7=BC=BA=E9=99=B7=E4=BF=AE=E5=A4=8D(#7/#27/#28/#31/#3?= =?UTF-8?q?9/#40/#42/#47b/#52/#55)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - #7a reveal 超时:长文按总时长 ≤8s 反推 interval(下限 12ms),短路径 30ms/字符不变(step=1);跳过按钮与 reduced-motion 行为不变 - #7b 标题编号:heading_open 注入 h1「一、」/h2「1.1」/h3「1.2.3」, 层级变化归零、自带编号跳过、md-hN class 恒挂、计数器逐次渲染重置; DocPane md 回退预览与私有参考块用 renderMarkdownPlain 关闭注入 (防止编号被序列化写回正本) - #27 会话聚合:删除前端二次聚合,会话域直接以后端 sources 为准; SourcesPane/SourceRow 以 paper_id/id 为 key 与高亮依据,徽标显示 真实 paper_id(截断+悬浮),无 paper_id 退 index+1; setHighlightSource 参数 index→key,chip 编号契约保持 - #31 节点详情:KgEntityDetail fetchExtra 序号守卫;KgPane :key 强制 重建;KgGraphView pointer 事件重构(pointerdown 不捕获、位移>4px 才捕获+标记 dragging、pointerup release、onClickNode dragging 拦截) - #39 日志刷新:打开总是重拉+「刷新日志」按钮+有 running 时 5s 独立 轮询(onBeforeUnmount 清理) - #40 轮询暂停:任何离开 extract 的切换 pausePolling;详情/日志展开态 提升到 store(detailOpenId/logOpen/runLog/logError),切 TAB 保留 - #42 模板选择:Composer docgen 模式模板下拉(自动推荐+内置+as_template 懒加载,失败降级),template_id 经 sendDocgen 传入 - #47b 会话切换 resetSession(selectSession 动态 import,只清不丢) - #55 文档 TAB:docgen store viewMode + DocPane「资料库」/「关闭文档」/ 「返回文档」按钮 - #28 检索文案:searchNoAnswer/searchTimeoutEmpty;200 降级体按 payload.degraded 分流,不再走 _errorMarker TIMEOUT 报错 - #52 异步轮询:api getTask/listTasks;sendDocgen 兼容 200/202, 202 后释放 busy 锁(生成期间可继续对话)、消息块记录 task_id、 2s 轮询 getTask、progress 驱动「生成中 x/y 节」、done 复用现有 artifact 挂块+落库+adoptArtifact+切 TAB、error 可重试; 会话恢复时 running 块含 task_id 续轮询(不误标「已中断」) 自测:29 个新增 r3debug 单测 + 23 个既有 private_docs 测试全绿; npm run build 通过;playwright 冒烟(dev server 5199)无 JS 错误, 模板下拉/提取面板/日志刷新按钮渲染正常。 未 push;Debug-2 9090 未就绪,#52/#28 联调留待 9090 就绪后执行。 Co-Authored-By: Claude Fable 5 --- ui/src/api/docgen.js | 21 +- ui/src/components/bench/DocPane.vue | 33 +- ui/src/components/bench/ExtractionPane.vue | 80 +++- ui/src/components/bench/KgEntityDetail.vue | 6 +- ui/src/components/bench/KgGraphView.vue | 25 +- ui/src/components/bench/KgPane.vue | 12 +- ui/src/components/bench/SourceRow.vue | 15 +- ui/src/components/bench/SourcesPane.vue | 16 +- ui/src/components/chat/AssistantMessage.vue | 27 +- ui/src/components/chat/ChatPanel.vue | 9 +- ui/src/components/chat/Composer.vue | 95 ++++- ui/src/components/chat/markdown.js | 99 ++++- ui/src/i18n/docgen.js | 5 + ui/src/i18n/labels.js | 4 + ui/src/stores/bench.js | 46 ++- ui/src/stores/chat.js | 396 ++++++++++++++++---- ui/src/stores/docgen.js | 9 +- ui/tests/r3debug/bench.test.js | 137 +++++++ ui/tests/r3debug/docgenPoll.test.js | 242 ++++++++++++ ui/tests/r3debug/markdown.test.js | 57 +++ ui/tests/r3debug/reveal.test.js | 116 ++++++ ui/tests/r3debug/vitest.config.js | 19 + 22 files changed, 1341 insertions(+), 128 deletions(-) create mode 100644 ui/tests/r3debug/bench.test.js create mode 100644 ui/tests/r3debug/docgenPoll.test.js create mode 100644 ui/tests/r3debug/markdown.test.js create mode 100644 ui/tests/r3debug/reveal.test.js create mode 100644 ui/tests/r3debug/vitest.config.js diff --git a/ui/src/api/docgen.js b/ui/src/api/docgen.js index c056e26..97b4f10 100644 --- a/ui/src/api/docgen.js +++ b/ui/src/api/docgen.js @@ -3,6 +3,11 @@ // 全部经 http.js 封装;默认读超时 600s 兜底(生成/编辑最长路径不早于 BFF 超时自断)。 import { get, post, patch, del } from './http.js'; +// 缺陷 #52:generate 兼容 200(旧同步契约)/202(新异步契约)两种响应形态。 +// 202 由 http.js 返回 payload(202 在 fetch 语义下非错误,body 直接透传); +// 旧 BFF 无 202 时直接返回同步产物——两者统一经 generate() 归一, +// chat.sendDocgen 按 `payload.task_id` 有无区分走轮询还是直接落块。 + /** * 上传入库(用户拖拽即走此路):multipart → vstore /ingest,入库主向量库持久可用。 * @param {File} file @@ -23,13 +28,25 @@ export function uploadLibrary(file, meta = {}, opts = {}) { } /** - * 同步生成(600s 兜底):前端落库消息与骨架后阻塞等待产物。 - * @returns {Promise<{ok:boolean, artifact:{artifact_id, title, template_name, status, ...}}>} + * 生成(600s 兜底读超时;兼容 200 同步 / 202 异步两种响应)。 + * @returns {Promise<{ok, task_id?, status?, artifact?, progress?, markdown?}>} + * 202 → {ok, task_id, status:"queued"};200 → 旧同步产物(artifact 内嵌)。 */ export function generate(payload) { return post('/api/docgen/generate', payload); } +/** 缺陷 #52:任务状态轮询(GET /api/docgen/tasks/{task_id}) + * → 200 {ok, task:{id, session_id, status, progress:[{section,title,state}], artifact|null, error}} */ +export function getTask(taskId) { + return get(`/api/docgen/tasks/${encodeURIComponent(taskId)}`); +} + +/** 缺陷 #52:会话级任务列表(GET /api/docgen/tasks?session_id=)——会话恢复时兜底查询 */ +export function listTasks(sessionId) { + return get('/api/docgen/tasks', { session_id: sessionId }); +} + /** 取 artifact 的 md 原文 */ export function getArtifactContent(artifactId) { return get(`/api/docgen/artifacts/${encodeURIComponent(artifactId)}/content`); diff --git a/ui/src/components/bench/DocPane.vue b/ui/src/components/bench/DocPane.vue index 35de946..3f3c74c 100644 --- a/ui/src/components/bench/DocPane.vue +++ b/ui/src/components/bench/DocPane.vue @@ -14,7 +14,7 @@ import { ref, computed, watch, nextTick, onMounted, onBeforeUnmount } from 'vue'; import { useDocgenStore } from '../../stores/docgen.js'; import { DG, BUILTIN_TEMPLATES } from '../../i18n/docgen.js'; -import { renderMarkdown, sanitizeHtml } from '../chat/markdown.js'; +import { renderMarkdownPlain, sanitizeHtml } from '../chat/markdown.js'; // FR-PRIV-006:「我的资料」管理面板(挂空态区顶部,UI_SPEC §9.2) import PrivateLibraryPane from './PrivateLibraryPane.vue'; @@ -67,7 +67,8 @@ function mountShadow() { inner = `
${sanitizeHtml(bodyFragment(docgen.html))}
`; } else { // 回退:客户端 md 渲染(旧制品/拉取失败) - inner = `
${renderMarkdown(docgen.md)}
`; + // 缺陷 #7b:md 回退预览不注入标题编号——序列化会把标题写回正本,编号不得进源文 + inner = `
${renderMarkdownPlain(docgen.md)}
`; } root.innerHTML = inner; if (editing.value) activateEditDom(); @@ -327,11 +328,17 @@ onBeforeUnmount(() => {