feat(ui): 星盘/星历/报告中心并入 app 外壳,侧栏不再消失
三个页面此前各是脱离外壳的独立全屏路由,各写了一套一样的 *-shell / *-topbar(只有一个「返回对话」链接)/ *-hero 骨架, 侧栏在打开它们的瞬间整个消失。 新增 AppNavRail(只读:两个 GET,零写操作)与 SecondaryShell。 会话行走 sessionHref → /?c=<uuid>,跳转复用现有侧栏的 persistLoginSessionReturn + location.assign,行为完全一致。 刻意不带重命名/收藏/归档/删除与账户菜单:那套连着 Home() 的乐观更新与 回滚层,为四个路由把它整体上提远超需要,且会撞 useState 增长门禁。 四个路由渲染标记完全不变:/ ○、/chart ○、/ephemeris ○、/reports ƒ。 CSS gzip 39,825→39,727(−0.25%);per-route JS 体积构建不输出, 已作为口径缺口记录。 两处自身问题被测试抓到并修复:usePathname() 在 app-router 上下文外 返回 null(类型说是 string)、fetch 在 jsdom 里可能不存在。 另差点随 hero 一起丢掉 BUG-717 的 eyebrow 文案(成本与速度承诺, 会印在失败页上),已放回 tab 行下方。 /reports/[reportId] 留给 R6 与目录一起做;根边界页保留「返回对话」, 它们不得 import globals.css,挂不了外壳。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P
This commit is contained in:
co-authored by
Claude Opus 5
parent
b3ea8c336e
commit
50ce02c837
+29
-2
@@ -373,12 +373,39 @@ Every assistant reply moves through the same states on both chat surfaces, and e
|
||||
|
||||
Text release is paced, not animated: the frame buffer commits at most once per animation frame and reveals `max(2, ⌈backlog ÷ 12⌉)` characters per frame, so a burst catches up in about twelve frames and a slow model never reads as stalled. The reader's own toggle on the timeline always wins over the state default. Under `prefers-reduced-motion: reduce` the collapse and the label fade are instant; the pacing stays, because it is content arrival rather than decoration.
|
||||
|
||||
### Secondary page shell
|
||||
|
||||
`/chart`, `/ephemeris` and `/reports` share the chat shell through
|
||||
`SecondaryShell`. Each used to own a full-screen layout — a `*-shell` root, a
|
||||
`*-topbar` with one 「返回对话」 link, and a `*-hero` with a page-sized h1 —
|
||||
three copies of one skeleton, none of them carrying the sidebar.
|
||||
|
||||
- **Composition:** `SidebarProvider` → `AppNavRail` → `SidebarInset.chat-panel.secondary-panel`.
|
||||
The header is the same 46px row the chat page uses: sidebar trigger, page name,
|
||||
an optional quiet note chip, and up to two right-aligned actions. The body is
|
||||
the only thing that scrolls, and it owns the page floor (`--color-canvas-soft`).
|
||||
- **The rail is read-only.** It carries the brand, 新建对话, the three page
|
||||
actions, and one flat 「最近」 list whose rows navigate to `/?c=<uuid>`.
|
||||
Renaming, pinning, archiving, deleting and the account menu stay on `/`: they
|
||||
are backed by `Home()`'s optimistic-update and rollback layer, and lifting that
|
||||
so four routes can share it is far more than these pages need. The footer shows
|
||||
identity and balance as text, not as a menu trigger.
|
||||
- **Loading:** the rail renders its nav immediately and fills the list when
|
||||
`/api/sessions` returns. While that is in flight the list area carries static
|
||||
copy — never a skeleton, per the unified-loading ruling.
|
||||
- **Signed out:** the rail degrades to brand, nav, a 「登录后可以看到你的对话」
|
||||
line, and a 去登录 footer. It never renders an error state of its own.
|
||||
- **Page name:** lives in the header, so none of these pages carries an `h1` any
|
||||
more. A page's own reassurance copy (the chart page's cost-and-speed eyebrow,
|
||||
for one) stays in the body; it is content, not chrome.
|
||||
|
||||
### Personal report centre
|
||||
|
||||
- **Structure:** full-page archive on the page floor. A compact back control, serif page title, supporting copy, one generate action, then a list of report cards.
|
||||
- **Structure:** inside the app shell, not a page of its own. The name 「我的报告」 sits in the 46px header with 「生成完整报告」 as the header's one action; the body is supporting copy, the overview line, then the list of report cards.
|
||||
It used to be a standalone full-screen route with a `report-center-shell` root, a `report-center-topbar` holding one 「返回对话」 link, and a `report-center-hero` with a page-sized h1 — the sidebar vanished the moment you opened it, and the only way back was that link.
|
||||
- **Surface:** `--color-canvas-soft` floor; cards use `--color-canvas`, a warm hairline, and `--radius-lg`. No drop shadow. Status is a caption badge, not a colored block.
|
||||
- **Typography:** page title uses `--type-display-lg` / `--font-display` at weight 400 with `text-wrap: balance`. Card titles are `--type-title-md` at weight 500. Body stays `--type-body-md` or `--type-body-sm`.
|
||||
- **Width:** 900px centered, matching long-form chat reading. Cards stack below 720px.
|
||||
- **Width:** 900px centered, matching long-form chat reading. Cards stack at the global 767px cut.
|
||||
- **Actions:** “生成完整报告” is the one filled action. A ready report keeps “查看报告” as the primary document action and “导出报告(.md)” beside it. The export downloads the same longform Markdown the detail page renders. Generating copy is one-step (“正在生成报告,大约 10–30 秒”); there is no chapter-count progress. Card summary is a deterministic excerpt of the Markdown 「摘要」 section, stored on the cover document at generation time.
|
||||
- **States:** loading, empty, populated, generating, ready, failed, unauthorized, list error. Export work uses the shared inline spinner inside the initiating button, reports a short row-local error, and never starts a second writing flow. A missing Markdown appendix is an old report: the detail page asks the reader to regenerate.
|
||||
- **Accessibility:** back, generate, refresh, and row actions are 44px. Status text uses a live region while a report is generating.
|
||||
|
||||
Reference in New Issue
Block a user