From 49bc4a8ba1b92351e5b4e34aab17e7a8c9bae871 Mon Sep 17 00:00:00 2001 From: Jesse_Chen Date: Wed, 16 Sep 2026 08:06:12 +0000 Subject: [PATCH] =?UTF-8?q?fix(ui):=20=E7=A9=BA=E6=80=81=E5=B1=85=E4=B8=AD?= =?UTF-8?q?=E3=80=81=E5=A4=A7=E8=BF=90=E9=A1=B5=E5=8E=BB=E9=87=8D=E3=80=81?= =?UTF-8?q?=E6=98=9F=E5=8E=86=E5=8A=A0=E6=97=A5=E5=8E=86=E3=80=81=E9=A1=B6?= =?UTF-8?q?=E6=A0=8F=E5=8A=A8=E4=BD=9C=E6=8C=89=2046px=20=E6=94=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 真机走查四条: 1. 空态不居中——问候+输入框+pill 整组贴在屏幕底部。加一个可压缩的 配重行,让 chat-panel 变成 46px/1fr/auto/1fr,两个 1fr 抵消, 整组居中;composer 仍是同一个 DOM 位置,不重挂载。 2. 大运页「Vimshottari」出现两遍、「当前 当前 Chara 段…」两个当前。 两条轨道的 method 与自身 title 同字符串,method 只在不同时才渲染; 兜底文案自带的「当前」去掉——它同时被参数表当「当前大运」的值用, 不能把前缀塞进数据。 3. 星历只能一天一天点。日期改成可点的日历弹层,复用出生日期字段 同一套 Calendar+Popover。新增 parseEphemerisDate/toEphemerisDate, 都走本地日历字段、不经 UTC,避免跨时区差一天。 4. 「生成完整报告」在 46px 顶栏里是 44px 实心大按钮,像个横幅 CTA。 顶栏作用域内动作统一 32px + outline,触摸目标靠 ::after 扩热区补。 测试 3372,fail 仍 31 且与基线逐条一致;四个路由标记不变; CSS gzip 40,080。 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P --- frontend/src/app/globals.css | 26 ++++++++++- frontend/src/app/page.tsx | 6 +++ .../components/chart-page/chart-dasha-tab.tsx | 8 +++- .../components/ephemeris/ephemeris-page.tsx | 46 ++++++++++++++++++- .../generate-personal-report-button.tsx | 7 ++- frontend/src/lib/chart-view-mapper.ts | 4 +- frontend/src/lib/ephemeris-view.ts | 18 ++++++++ frontend/tests/ephemeris-page.test.tsx | 1 + 8 files changed, 109 insertions(+), 7 deletions(-) diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css index d86c3a5a..caf0c2ef 100644 --- a/frontend/src/app/globals.css +++ b/frontend/src/app/globals.css @@ -853,6 +853,24 @@ button:disabled { cursor: default; opacity: .45; } .chat-header-chart { flex: 0 1 auto; min-width: 0; overflow: hidden; color: var(--color-ink-tertiary); font-size: var(--type-caption); text-overflow: ellipsis; white-space: nowrap; } .chat-header-actions { min-width: max-content; display: flex; flex: 0 0 auto; align-items: center; gap: var(--space-2); white-space: nowrap; } .chat-header-actions > * { flex: 0 0 auto; } +/* The page header is 46px tall, so its actions are 32px — the button primitives + default to 44px, which is why 「生成完整报告」 read as a banner CTA parked in + the corner. The touch target comes back through the hit expansion below, the + same trade the message actions and the starter pills make. */ +.chat-header-actions button { + position: relative; + min-height: 32px; + height: 32px; + padding-inline: var(--space-3); + border-radius: var(--radius-md); + font-size: var(--type-caption); +} +.chat-header-actions button::after { + position: absolute; + inset: -6px; + content: ""; +} +.chat-header-actions button > svg { width: 14px; height: 14px; } .credit-button { min-height: 44px; display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2); padding: 0 var(--space-3); cursor: pointer; font-size: var(--type-caption); font-variant-numeric: tabular-nums; transition: background-color 120ms ease-out, transform 120ms ease-out; min-width: 64px; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-canvas-soft); color: var(--color-ink-secondary); font-weight: 500; } .conversation { min-width: 0; min-height: 0; overflow-x: hidden; overflow-y: auto; overscroll-behavior: contain; padding-bottom: var(--composer-reserve); background: var(--color-canvas); } @@ -861,6 +879,12 @@ button:disabled { cursor: default; opacity: .45; } stack reads as one centred group while the composer keeps the single DOM position it has in a live session. */ .conversation.is-empty { display: grid; align-content: end; justify-items: center; padding: var(--space-8) var(--space-8) 0; } +/* With the balance row present the panel has four rows: header, the conversation + (1fr, greeting bottom-aligned), the composer (auto), and an equal 1fr below. + The two 1fr rows cancel out, so the group is vertically centred while the + composer keeps the single DOM position it holds in a live session. */ +.chat-panel:has(.starter-balance) { grid-template-rows: 46px minmax(0, 1fr) auto minmax(0, 1fr); } +.starter-balance { min-height: 0; } .welcome { width: min(820px, 100%); padding: var(--space-10) 0 var(--space-16); } .welcome > .onboarding-message:first-child { padding-bottom: var(--space-8); } .welcome > .onboarding-message:first-child .message-bubble p { @@ -2208,7 +2232,7 @@ button.nav-rail-identity:hover { background: var(--sidebar-accent); } .composer-wrap-starter { border-top-color: transparent; - padding-bottom: var(--space-16); + padding-bottom: var(--space-4); background: transparent; backdrop-filter: none; } diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx index 3acc6e47..160445c7 100644 --- a/frontend/src/app/page.tsx +++ b/frontend/src/app/page.tsx @@ -1807,6 +1807,12 @@ export default function Home() { /> )} } + {/* Balances the 1fr row above the composer so the greeting / composer / + pills group sits in the middle of the panel instead of resting on the + bottom edge. It collapses to 0 on short viewports. */} + {starterHomeVisible && !rectificationSurfaceOpen && !onboardingFormActive + ?