feat(ui): 星盘/星历/报告中心并入 app 外壳,侧栏不再消失
Independent Staging Quality Gate / validate (push) Failing after 9m57s
Independent Staging Quality Gate / publish (push) Skipped

三个页面此前各是脱离外壳的独立全屏路由,各写了一套一样的
*-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:
Jesse_Chen
2026-09-16 06:03:30 +00:00
co-authored by Claude Opus 5
parent b3ea8c336e
commit 50ce02c837
15 changed files with 680 additions and 263 deletions
+110 -186
View File
@@ -1973,6 +1973,104 @@ input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class
.conversational-composer-footer button, .conversational-confirmation button, .conversational-original-question button { width: 100%; }
}
/* ── Secondary pages inside the app shell ─────────────────────────────────
/chart, /ephemeris and /reports used to be standalone full-screen routes,
each with its own `*-shell` root, a `*-topbar` holding one 「返回对话」 link,
and a `*-hero` with a page-sized h1. Three copies of one skeleton, none of
them carrying the sidebar. They share the chat panel now; the page name lives
in the 46px header and the body is the only thing that scrolls. */
.secondary-panel { background: var(--color-canvas-soft); }
.secondary-panel > :not(.chat-header) {
min-height: 0;
overflow-x: hidden;
overflow-y: auto;
overscroll-behavior: contain;
-webkit-overflow-scrolling: touch;
}
.chart-page-eyebrow {
width: min(1100px, 100%);
margin: var(--space-4) auto 0;
color: var(--color-ink-tertiary);
font-size: var(--type-caption);
}
.chart-page-body,
.ephemeris-body,
.report-center-body,
.chart-page-message,
.ephemeris-message,
.report-center-message {
padding: 0 var(--space-6) var(--space-16);
}
.chart-page-message,
.ephemeris-message,
.report-center-message {
display: grid;
justify-items: center;
align-content: center;
gap: var(--space-3);
min-height: 60%;
text-align: center;
}
.chart-page-message p,
.ephemeris-message p,
.report-center-message p {
max-width: 44ch;
margin: 0;
color: var(--color-ink-secondary);
font-size: var(--type-body-sm);
line-height: 1.6;
}
.chart-page-message h2,
.ephemeris-message h2,
.report-center-message h2 {
margin: 0;
font-family: var(--font-display);
font-size: var(--type-title-lg);
font-weight: 500;
}
/* The rail is the chat sidebar minus every write action. It reuses the sidebar
surface and row styles; only the identity block differs, because there is no
account menu to open from here. */
.nav-rail-row { width: 100%; }
.nav-rail-identity {
min-height: 44px;
width: 100%;
display: flex;
align-items: center;
gap: var(--space-2);
padding: 0 var(--space-2);
border: 0;
border-radius: var(--radius-md);
background: transparent;
color: var(--sidebar-foreground);
font-size: var(--type-body-sm);
text-align: left;
text-decoration: none;
}
.nav-rail-identity > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-rail-identity > small {
margin-left: auto;
flex: 0 0 auto;
color: var(--color-ink-tertiary);
font-size: var(--type-caption);
font-variant-numeric: tabular-nums;
}
button.nav-rail-identity { cursor: pointer; }
button.nav-rail-identity:hover { background: var(--sidebar-accent); }
@media (max-width: 767px) {
/* Replaces the three `*-shell { padding-inline }` rules the standalone pages
each carried. Same global 767px cut, one rule instead of three. */
.chart-page-body,
.ephemeris-body,
.report-center-body,
.chart-page-message,
.ephemeris-message,
.report-center-message,
.chart-page-eyebrow { padding-inline: var(--space-4); }
}
/* Starter home: greeting, composer, entry pills */
.welcome {
width: min(var(--session-column-width), 100%);
@@ -3278,60 +3376,18 @@ input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class
.payment-qr-badge { position: absolute; top: 50%; left: 50%; display: grid; width: 44px; height: 44px; padding: 4px; transform: translate(-50%, -50%); border: 4px solid #fff; border-radius: 12px; background: #fff; box-shadow: 0 2px 10px rgb(0 0 0 / 18%); }
.payment-qr-badge svg { display: block; width: 100%; height: 100%; }
/* Global report centre — quiet archive, independent from chat sessions. */
.report-center-shell {
width: 100%;
height: 100%;
min-height: 0;
overflow-x: hidden;
overflow-y: auto;
overscroll-behavior: contain;
-webkit-overflow-scrolling: touch;
padding: 0 var(--space-6) var(--space-16);
background: var(--color-canvas-soft);
color: var(--color-ink);
}
.report-center-topbar,
.report-center-hero,
.report-center-section {
/* Global report centre — quiet archive, independent from chat sessions. */.report-center-hero,
.report-center-section{
width: min(900px, 100%);
margin-inline: auto;
}
.report-center-topbar {
min-height: 64px;
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-5);
color: var(--color-ink-tertiary);
font-size: var(--type-overline);
}
.report-center-back {
min-height: 44px;
display: inline-flex;
align-items: center;
gap: var(--space-2);
padding: 0 var(--space-3);
border: 1px solid var(--color-border);
border-radius: var(--radius-sm);
background: var(--color-canvas);
color: var(--color-ink-secondary);
font-size: var(--type-body-sm);
font-weight: 500;
text-decoration: none;
}
.report-center-back:hover { border-color: var(--color-border-strong); color: var(--color-ink); }
.report-center-back:focus-visible,
.report-center-section-heading button:focus-visible,
}.report-center-section-heading button:focus-visible,
.personal-report-back:focus-visible,
.personal-report-disclosure:focus-visible {
.personal-report-disclosure:focus-visible{
outline: 2px solid var(--color-focus);
outline-offset: 2px;
}
.report-center-back svg,
.report-center-section-heading button svg,
}.report-center-section-heading button svg,
.personal-report-back svg,
.personal-report-action-end svg { width: 16px; height: 16px; }
.personal-report-action-end svg{ width: 16px; height: 16px; }
.report-center-hero {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
@@ -3340,16 +3396,6 @@ input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class
padding: var(--space-10) 0 var(--space-8);
}
.report-center-hero > div { max-width: 760px; }
.report-center-hero h1 {
margin: 0;
color: var(--color-ink);
font-family: var(--font-display);
font-size: var(--type-display-lg);
font-weight: 500;
letter-spacing: -1px;
line-height: 1.1;
text-wrap: balance;
}
.report-center-hero > div > p:not(.report-center-meta) {
max-width: 660px;
margin: var(--space-4) 0 0;
@@ -3511,10 +3557,7 @@ input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class
.report-center-message p { margin: 0; color: var(--color-ink-secondary); font-size: var(--type-body-sm); }
@media (max-width: 767px) {
.report-center-shell { padding-inline: var(--space-4); }
.report-center-hero { grid-template-columns: 1fr; align-items: start; gap: var(--space-6); padding-block: var(--space-8) var(--space-6); }
.report-center-hero h1 { font-size: var(--type-display-md); letter-spacing: -.5px; }
.report-center-hero > button { width: 100%; }
.report-center-card { grid-template-columns: 1fr; gap: var(--space-4); }
.report-center-card-actions,
.report-center-card > a,
@@ -4314,84 +4357,15 @@ input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class
.rectification-message-wrap { display: grid; gap: var(--space-1); }
/* Read-only natal chart page. Independent route; does not grow page.tsx. */
.chart-page-shell {
width: 100%;
height: 100%;
min-height: 0;
overflow-x: hidden;
overflow-y: auto;
overscroll-behavior: contain;
-webkit-overflow-scrolling: touch;
padding: 0 var(--space-6) var(--space-16);
background: var(--color-canvas-soft);
color: var(--color-ink);
}
.chart-page-topbar,
.chart-page-hero,
.chart-page-tabs,
.chart-page-panel {
/* Read-only natal chart page. Independent route; does not grow page.tsx. */.chart-page-tabs,
.chart-page-panel{
width: min(1100px, 100%);
margin-inline: auto;
}
.chart-page-topbar {
min-height: 64px;
display: flex;
align-items: center;
}
.chart-page-back {
min-height: 44px;
display: inline-flex;
align-items: center;
gap: var(--space-2);
padding: 0 var(--space-3);
border: 1px solid var(--color-border);
border-radius: var(--radius-sm);
background: var(--color-canvas);
color: var(--color-ink-secondary);
font-size: var(--type-body-sm);
font-weight: 500;
text-decoration: none;
}
.chart-page-back:hover { border-color: var(--color-border-strong); color: var(--color-ink); }
.chart-page-back:focus-visible,
.chart-page-tab:focus-visible,
.chart-page-chip:focus-visible {
}.chart-page-tab:focus-visible,
.chart-page-chip:focus-visible{
outline: 2px solid var(--color-focus);
outline-offset: 2px;
}
.chart-page-back svg { width: 16px; height: 16px; }
.chart-page-hero { padding: var(--space-8) 0 var(--space-6); }
.chart-page-eyebrow {
margin: 0;
color: var(--color-ink-tertiary);
font-size: var(--type-overline);
font-weight: 500;
letter-spacing: 1.5px;
}
.chart-page-hero h1 {
margin: var(--space-3) 0 0;
color: var(--color-ink);
font-family: var(--font-display);
font-size: var(--type-display-lg);
font-weight: 500;
letter-spacing: -1px;
line-height: 1.1;
text-wrap: balance;
}
.chart-page-hero > p:not(.chart-page-eyebrow):not(.chart-page-birthline) {
max-width: 40em;
margin: var(--space-4) 0 0;
color: var(--color-ink-secondary);
font-size: var(--type-body-md);
line-height: 1.65;
text-wrap: pretty;
}
.chart-page-birthline {
margin: var(--space-3) 0 0;
color: var(--color-ink-secondary);
font-size: var(--type-body-sm);
}
.chart-page-tabs {
display: flex;
flex-wrap: wrap;
@@ -4603,7 +4577,6 @@ input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class
.chart-page-unavailable > p { margin: 0 0 var(--space-3); font-size: var(--type-body-md); }
@media (max-width: 767px) {
.chart-page-hero h1 { font-size: var(--type-display-md); }
.chart-page-center-compact { display: block; }
.chart-page-center-extra { display: none; }
.chart-page-params-below { display: block; }
@@ -4640,64 +4613,17 @@ input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class
/* ============================================================
Ephemeris page — facts only, own scroll (html/body overflow hidden)
============================================================ */
.ephemeris-shell {
width: 100%;
height: 100%;
min-height: 0;
overflow-x: hidden;
overflow-y: auto;
overscroll-behavior: contain;
-webkit-overflow-scrolling: touch;
padding: 0 var(--space-6) var(--space-16);
background: var(--color-canvas-soft);
color: var(--color-ink);
}
.ephemeris-topbar,
.ephemeris-hero,
============================================================ */.ephemeris-hero,
.ephemeris-section,
.ephemeris-footer {
.ephemeris-footer{
width: min(900px, 100%);
margin-inline: auto;
}
.ephemeris-topbar {
min-height: 64px;
display: flex;
align-items: center;
}
.ephemeris-back {
min-height: 44px;
display: inline-flex;
align-items: center;
padding: 0 var(--space-3);
border: 1px solid var(--color-border);
border-radius: var(--radius-sm);
background: var(--color-canvas);
color: var(--color-ink-secondary);
font-size: var(--type-body-sm);
font-weight: 500;
text-decoration: none;
}
.ephemeris-back:hover { border-color: var(--color-border-strong); color: var(--color-ink); }
.ephemeris-back:focus-visible {
outline: 2px solid var(--color-focus);
outline-offset: 2px;
}
.ephemeris-hero {
display: grid;
gap: var(--space-4);
padding: var(--space-6) 0 var(--space-8);
}
.ephemeris-hero h1 {
margin: 0;
color: var(--color-ink);
font-family: var(--font-display);
font-size: var(--type-display-lg);
font-weight: 500;
letter-spacing: -1px;
line-height: 1.1;
text-wrap: balance;
}
.ephemeris-date-label {
margin: 0;
color: var(--color-ink-secondary);
@@ -4855,8 +4781,6 @@ input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class
.ephemeris-message p { margin: 0; color: var(--color-ink-secondary); font-size: var(--type-body-sm); }
@media (max-width: 767px) {
.ephemeris-shell { padding-inline: var(--space-4); }
.ephemeris-hero h1 { font-size: var(--type-display-md); letter-spacing: -.5px; }
.ephemeris-date-bar { display: grid; grid-template-columns: 1fr 1fr 1fr; }
.ephemeris-date-button { width: 100%; }
.ephemeris-panchanga {