diff --git a/apps/presentation/dashboard/src/features/personal-workspace/personal-workspace-page.tsx b/apps/presentation/dashboard/src/features/personal-workspace/personal-workspace-page.tsx index bfa7ffbd66..4c643f5443 100644 --- a/apps/presentation/dashboard/src/features/personal-workspace/personal-workspace-page.tsx +++ b/apps/presentation/dashboard/src/features/personal-workspace/personal-workspace-page.tsx @@ -3101,7 +3101,8 @@ export function PersonalWorkspacePage({ : undefined} onOpenCommands={() => {setMobileSidebarOpen(false); setPaletteScope(paletteContext);}} onOpenSettings={readOnly ? undefined : () => openSettings({ kind: "settings" })} - onSelectGoal={selectGoal} + onSelectGoal={(goalId) => selectGoal(goalId, + goalId && selectedGoalId && selectedGoalTab === "research" ? "research" : "overview")} selectedGoalId={selectedGoalId} statusSourceControl={statusSourceControl} /> diff --git a/docs/development/assets/research-navigation/after-desktop.png b/docs/development/assets/research-navigation/after-desktop.png new file mode 100644 index 0000000000..2bbc6b00a8 Binary files /dev/null and b/docs/development/assets/research-navigation/after-desktop.png differ diff --git a/docs/development/assets/research-navigation/after-mobile.png b/docs/development/assets/research-navigation/after-mobile.png new file mode 100644 index 0000000000..583830bb7f Binary files /dev/null and b/docs/development/assets/research-navigation/after-mobile.png differ diff --git a/docs/development/assets/research-navigation/before-desktop.png b/docs/development/assets/research-navigation/before-desktop.png new file mode 100644 index 0000000000..376ff879e8 Binary files /dev/null and b/docs/development/assets/research-navigation/before-desktop.png differ diff --git a/docs/development/design.md b/docs/development/design.md index 6bac8efc3f..a323ba4383 100644 --- a/docs/development/design.md +++ b/docs/development/design.md @@ -180,13 +180,18 @@ Goal 统计集中在概览,完整工作放在任务,输出放在成果。阅 Keep the selected view, time group and evidence focus on reload and browser Back/Forward. Keep scroll position across tabs. Scope every selection to its Goal and source; a same-named Goal from another source must not inherit it. +While reading Research, choosing another Goal in the sidebar stays in Research. +The destination loads its own evidence; Back restores the prior Goal's selection. +Home and explicit task, conversation or output links keep their own destinations. Saved findings lead with readable observations, interpretations and decisions. Put references, applicability, revisions and full original text behind one expansion. Clamp repeated titles only in the selection list, never the selected finding's full content. Do not invent short titles or infer findings from prose. 刷新和前进后退保留视图、时间分组与证据焦点;标签之间保留阅读位置。选择状态按 -Goal 和来源隔离。结论正文以正常字号呈现观察、解读与决策;来源、适用范围、版本 +Goal 和来源隔离。研究中从侧栏切换 Goal 仍停留在研究页,读取新 Goal 自身证据; +返回恢复原 Goal 的选择。首页及任务、会话、成果的明确链接保留各自目的地。 +结论正文以正常字号呈现观察、解读与决策;来源、适用范围、版本 和完整原文按需展开。仅列表中的重复长标题可收起,选中后的正文须完整可读。 ### Explanations On Demand diff --git a/examples/personal-workspace-browser/research-history.mjs b/examples/personal-workspace-browser/research-history.mjs index e7bf712212..475b23a0f6 100644 --- a/examples/personal-workspace-browser/research-history.mjs +++ b/examples/personal-workspace-browser/research-history.mjs @@ -275,13 +275,21 @@ export const researchHistoryScenario = { const checkpoints=[]; for(const [file,label] of [['edgebench-graph-checkpoint-history.json','graph'],['edgebench-ad-checkpoint-history.json','ad']]) { const other=JSON.parse(await readFile(resolve(repoRoot,'apps/presentation/dashboard/src/data/fixtures',file))); + const previousUrl = page.url(); + const previousSelection = selectedNodes(); pages.length=0; await page.locator('.personal-goal-link',{hasText:other.display_name}).click(); - await tabs.getByRole("button", {name: "研究", exact: true}).click(); + assert.equal(new URL(page.url()).searchParams.get('view'), 'research', 'Comparing Goals must keep the research reading context'); await history.getByRole('status').filter({hasText:`${other.events.length} / ${other.events.length}`}).waitFor(); assert.deepEqual(pages.flatMap(value=>value.items).map(row=>row.event_id),other.events.map(row=>row.event_id),`${label}: all original pages, without cross-Goal records`); assert.equal(await history.locator('.research-history-detail').count(),0, 'A different Goal must not adopt the prior evidence selection'); assert.equal(await history.locator('.research-route').count(),0); + await page.goBack(); + assert.equal(page.url(), previousUrl, 'Back restores the prior Goal and its own evidence URL'); + assert.deepEqual(selectedNodes(), previousSelection); + await page.goForward(); + await history.getByRole('status').filter({hasText:`${other.events.length} / ${other.events.length}`}).waitFor(); + assert.equal(await history.locator('.research-history-detail').count(),0); await history.evaluate(element=>element.scrollIntoView({block:'start'})); await page.screenshot({path:resolve(outputDir,`research-history-${label}-timeline.png`),animations:'disabled'}); await history.locator('.research-unlinked-days button').first().click();