From 02cdba834de0dd156cdd619ed6525f523356bda3 Mon Sep 17 00:00:00 2001 From: kris Date: Sat, 4 Apr 2026 11:38:01 +0800 Subject: [PATCH] feat: refocus assistant and tracking follow-ups --- CHANGELOG.md | 6 ++++++ web/storyforge-web-v4/assets/app.js | 3 ++- web/storyforge-web-v4/tests/workbench-pages.test.mjs | 4 ++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6542708..e5326eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -317,3 +317,9 @@ - `租户额度` 保存后,现在会自动回到 `额度` 工作区的策略区域,不再只留一条成功提示。 - `运维扫描 / 事件审计 / 修复计划生成 / 修复计划审计` 完成后,会统一回到 `管理员配置台 -> 运维审计`,方便连续处理下一条事件。 - 前端回归新增了这批动作的 refocus 断言,并锁住了 `credits-quota-anchor` 与 `admin-ops-anchor` 两个工作区锚点。 + +### 跟踪与 Agent 切换顺手度补齐 + +- `跟踪摘要 -> 标记已读` 完成后,会自动回到 `跟踪账号` 工作区,方便继续处理当天的下一条跟踪任务。 +- `切换当前 Agent` 后,会自动回到 `Agent -> 当前 Agent 工作台`,并聚焦到当前选中的 Agent,而不是只在原地刷新一句提示。 +- 前端回归新增了这两条断言,锁住“切换完成后继续工作”的落点体验。 diff --git a/web/storyforge-web-v4/assets/app.js b/web/storyforge-web-v4/assets/app.js index 2362de0..e73c410 100644 --- a/web/storyforge-web-v4/assets/app.js +++ b/web/storyforge-web-v4/assets/app.js @@ -11369,6 +11369,7 @@ document.addEventListener("click", async (event) => { await markTrackingDigestRead(); rememberAction("日报已标记", "当前跟踪摘要已更新为已读,下次会从新的时间点继续汇总。", "green"); await bootstrap(); + focusTrackingWorkspace(); } catch (error) { presentActionFailure(error, "标记日报已读失败"); } @@ -11634,7 +11635,7 @@ document.addEventListener("click", async (event) => { if (name === "select-assistant") { appState.selectedAssistantId = action.dataset.assistantId || ""; rememberAction("已切换当前 Agent", `当前默认 Agent 已更新为「${getSelectedAssistant()?.name || "未选择"}」。`, "green"); - renderAll(); + focusPlaybookWorkspace(appState.selectedAssistantId); return; } if (name === "open-edit-assistant") { diff --git a/web/storyforge-web-v4/tests/workbench-pages.test.mjs b/web/storyforge-web-v4/tests/workbench-pages.test.mjs index 5ad5d60..c7960fe 100644 --- a/web/storyforge-web-v4/tests/workbench-pages.test.mjs +++ b/web/storyforge-web-v4/tests/workbench-pages.test.mjs @@ -989,11 +989,13 @@ test("tracking and benchmark actions land on the most relevant workbench area af const trackSelected = extractBetween(APP, "function openTrackSelectedAccountAction()", "function openImportVideoLinkAction()"); const saveCandidate = extractBetween(APP, "async function saveCandidateAsBenchmark(candidateIndex, relationType = \"benchmark\")", "function screenShell(title, subtitle, actionsHtml, bodyHtml)"); const openBenchmark = extractBetween(APP, "function openBenchmarkLinkAction(defaults = {})", "async function scanAdminOpsAction()"); + const clickHandler = extractBetween(APP, "document.addEventListener(\"click\", async (event) => {", "document.addEventListener(\"submit\", async (event) => {"); assert.match(APP, /function focusTrackingWorkspace\(\)/); assert.match(APP, /function focusDiscoveryRelations\(\)/); assert.match(trackSelected, /focusTrackingWorkspace\(\)/); assert.match(saveCandidate, /focusDiscoveryRelations\(\)/); assert.match(openBenchmark, /focusDiscoveryRelations\(\)/); + assert.match(clickHandler, /name === "mark-tracking-read"[\s\S]*focusTrackingWorkspace\(\)/); }); test("recovery and copy actions continue into the most useful result view", () => { @@ -1038,9 +1040,11 @@ test("quota and admin ops mutations refocus the user into the most relevant work test("assistant actions return to the playbook workspace with the saved assistant in focus", () => { const createAssistant = extractBetween(APP, "function openCreateAssistantAction()", "function openEditAssistantAction(assistantId = \"\")"); const editAssistant = extractBetween(APP, "function openEditAssistantAction(assistantId = \"\")", "function openAnalyzeSelectedAccountAction()"); + const clickHandler = extractBetween(APP, "document.addEventListener(\"click\", async (event) => {", "document.addEventListener(\"submit\", async (event) => {"); assert.match(APP, /function focusPlaybookWorkspace\(assistantId = ""\)/); assert.match(createAssistant, /focusPlaybookWorkspace\(assistant\.id\)/); assert.match(editAssistant, /focusPlaybookWorkspace\(updated\.id\)/); + assert.match(clickHandler, /name === "select-assistant"[\s\S]*focusPlaybookWorkspace\(appState\.selectedAssistantId\)/); assert.match(APP, /id="current-agent-anchor"/); assert.match(APP, /data-assistant-id="\$\{escapeHtml\(assistant\.id\)\}"/); });