fix(web): keep the settings dialog one size and move billing into it (BUG-554)

The four account panes now share a fixed frame, chart profiles open as list then detail, and membership lives in the homepage dialog instead of a separate page.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-09-06 18:28:32 +08:00
parent 40bd0e9372
commit dc6598d7e4
48 changed files with 1962 additions and 1411 deletions
+16
View File
@@ -8565,6 +8565,22 @@
- 复发自:无
- 修复版本:`a1956deb`
## BUG-554 | 设置弹窗随分区跳变,星盘资料铺开整张表单,账户与点数离开首页
- 状态:resolved
- 首次发现:2026-09-06
- 最近更新:2026-09-06
- 影响面:设置弹窗、`chart-library-panel``billing-panel`、首页 `page.tsx``/membership` 路由
- 用户现象:三个设置分区弹窗尺寸不同;星盘资料列表下面无条件铺开添加表单;点「账户与点数」会离开首页打开整页会员。
- 触发条件:登录后打开设置弹窗,切换个人资料 / 星盘资料 / 通用设置,或从余额、头像菜单、余额不足进入充值。
- 根因:`accountDialogClasses` 给每个分区不同宽度,高度随内容撑开。星盘资料没有列表/详情视图,添加表单始终渲染。第四个导航项直接 `router.push``/membership`
- 修复:四个分区共用 `.settings-modal` 固定尺寸。星盘资料改为列表→详情。账户与点数成为弹窗第四分区;删除 `/membership``/membership/orders`,旧链接重定向到 `/?settings=billing`。七处入口改为 `openAccountDialog("billing")`
- 验证:`frontend/tests/account-dialog-overlay.test.ts``billing-panel.test.ts``membership-page.test.ts``membership-navigation-contract.test.ts``chart-library-other-profile.test.ts``settings-url.test.ts``beam-avatar.test.ts``class-name-definition-contract.test.ts``tests/test_api_server_security.py -k capability_audit``next build --webpack``/` 为 Static,无 `/membership` 页面。
- 防复发:设置弹窗必须同时声明 width 与 height;星盘资料默认视图不得无条件渲染 `<form``/` 保持 Static,不得 `useSearchParams`;收银台仍 `window.open`;硬跳转清单不得因本单变长。
- 相关记录:BUG-434、BUG-251、BUG-143
- 复发自:无
- 修复版本:待发布
## BUG-555 | 普通咨询历史只留每条开头 4000 字,下一轮看不到应期和审计表
- 状态:resolved
@@ -0,0 +1,74 @@
# PROGRESS · 设置弹窗重排与账户与点数入弹窗(2026-09-06)
工作树:`.worktrees/settings-dialog-and-billing-pane-20260906`
分支:`codex/settings-dialog-and-billing-pane-20260906`
基线:任务书写 `origin/staging` @ `985c3258`;开工时 `origin/staging` 已到 `9ce7a374`(含 composer 与会话列表),以当时远端为准。
`page.tsx` 开工 **2035** 行,收尾 **1976** 行(净减 59,上限 1995)。未改迁移、未 bump Skill、未改支付 API。
| 任务 | 状态 | BUG |
| --- | --- | --- |
| 5.1 弹窗壳固定尺寸 + 四分区 | 完成 | BUG-554 |
| 5.2 个人资料搬出 `page.tsx` | 完成 | — |
| 5.4 账户与点数入弹窗,删除 `/membership` | 完成 | BUG-554 |
| 5.3 星盘资料列表→详情 | 完成 | BUG-554 |
| 5.5 BUG_HISTORY / CHANGELOG / DESIGN / VOICE | 完成 | — |
## 实现要点
- `.settings-modal`:桌面 `width: min(100vw - 32px, 880px); height: min(84dvh, 640px)`;四分区共用;退出仍是 400px `logout-modal`
- `AccountDialog` 增加 `"billing"`。导航顺序:个人资料 → 星盘资料 → 账户与点数 → 通用设置。
- `profile-panel.tsx`:48px 头像一行;删除「管理星盘资料」。
- `chart-library-panel.tsx`:内部视图 `list | self | other | add`;列表条可点 + chevron;合盘操作只在其他人详情。
- `billing-panel.tsx` + `use-billing-panel.ts``next/dynamic` `{ ssr: false }`。页签含订单;兑换码行内表单。无 spinner / 「正在加载」。
- 删除 `frontend/src/app/membership/page.tsx``orders/page.tsx``next.config.ts` 临时重定向到 `/?settings=billing`
- `settings-url.ts` 在 hydrate / popstate 解析后 `history.replaceState` 抹掉参数;`/` 不用 `useSearchParams`
- 七处入口改为 `openAccountDialog("billing", { source, plan, tab })`。生时校正 402 不再 `window.location.assign`
## 既有断言改动
| 文件 | 原值 | 新值 | 原因 |
| --- | --- | --- | --- |
| `account-dialog-overlay` | `openRedeem``profile-modal` / `chart-library-modal` | `renderBilling`;四导航;`.settings-modal` 同时有 width 与 height | 5.1 固定尺寸四分区 |
| `page.tsx` `renderProfile` | 约 50 行 JSX + 「管理星盘资料」 | `<ProfilePanel />`,头像 48px | 5.2 净减行;去掉重复入口 |
| `chart-library-panel` | 无条件 `<form``setEditingSelfChart(true)` | 列表默认;`setView({ kind: "add" })` 后才出表单 | 决策 4 |
| 本人详情标题 | 编辑本人资料 | 编辑本人星盘 | 详情视图文案 |
| 合盘 pending 文案 | `synastryPendingId === record.id` | `selectedOther.id` | 操作只在详情 |
| `membership-page` 26 条支付/兑换/订单 | 读 `app/membership/page.tsx` | 读 `billing-panel.tsx` + `use-billing-panel.ts` | 页面删除 |
| 会员页存在 / Suspense / loading | 页面必须存在 | 页面不存在;无 spinner | 决策 6、8 |
| 兑换码 | `redeemOpen` 子弹窗 | `value="redeem"` 页签 | 决策 5 |
| `goBack` / `history.back` | 整页返回 | 无;`stripSettingsQuery` | 账单在首页 |
| 订单 | 独立页 + 「正在加载订单…」 | 页签 idle/ready/unavailable,无加载句 | AGENTS §6 |
| 页签「点数充值」 | 点数充值 | 点数包 | VOICE |
| 主标题「套餐与会员」 | `<h1 className="membership-title">` | 弹窗标题「账户与点数」+ `billing-summary` | 不再是整页 |
| `.membership-page` / `.membership-shell` / `.membership-hero` | 整页壳 CSS | 删除;卡片/页签 CSS 保留 | 只删整页 chrome |
| `membershipHref` | `/membership?source=` | `/?settings=billing&source=` | 深链接 |
| `chat-navigation` 4 条软跳 | `router.push(membershipHref(...))` | `openAccountDialog("billing", { source })` | 决策 7 |
| 校正 402 | `window.location.assign(membershipHref("rectification"))` | `onOpenBilling({ source: "rectification" })` | 硬跳转清单缩小 1 |
| 会员 401 | membership 页 3 次 + 订单页 1 次 | billing hook 4 次 `assign("/login")` | 认证仍硬跳 |
| `test_api_server_security` `app_routes` | 含 `membership``membership/orders` | 去掉这两条 | BUG-143 路由集合 |
| 付费墙 | `<Link href={membershipHref("onboarding-paywall")}>` | `onOpenBilling` 按钮 | 关掉墙后打开 billing |
| `beam-avatar` | 头像编辑 JSX 在 `page.tsx` | 读 `profile-panel.tsx``page.tsx` 只挂 `ProfilePanel` | 5.2 搬出 |
| `knownUnstyled` | 允许 `membership-orders` / `membership-segment` | 从白名单删除 | 整页删除后不再渲染 |
`git grep -n "/membership" frontend/src` 还会命中 `@/lib/membership` 模块 import,不是路由。路由字符串只出现在 `next.config.ts` 重定向。
## 测试
| 命令 | 结果 |
| --- | --- |
| 任务书收尾 tsx 合同(overlay / chart-library / membership / billing / settings-url / profile-panel / chat-navigation / epay / redeem-orders / starter / settings-mvp / consultation / rectification-surface | **168 pass / 0 fail** |
| `beam-avatar` + `class-name-definition-contract` + `profile-panel` | **10 pass / 0 fail** |
| `./node_modules/.bin/tsc --noEmit` | 0 错 |
| 改动文件 `eslint --quiet``npm run lint` | **0 error**(全仓 79 条既有 warning |
| `page.tsx` | 1976 行(开工 2035,净减 59 |
| `/opt/anaconda3/bin/python3.12 -m pytest tests/test_api_server_security.py -k capability_audit` | 2 passed |
| `npm run build -- --webpack` | `/``○` Static;产物无 `/membership` 页面;`routes-manifest` 有两条 307 重定向。首页 `page-*.js` gzip **181103** 字节;账单文案在按需 chunk `773.*.js`gzip **4994**),未打进首屏合同路径。 |
| 默认 `npm run build`Turbopack | 本工作树 `frontend/node_modules` 是指向主仓的 symlinkTurbopack 报 `points out of the filesystem root`。验收用 webpack 构建。 |
| `npm test` 全量 | 产品合同已绿。其余失败均走 `startPostgresFixture` / `docker compose up postgres`,本机 compose 起不来,与本单无关。 |
Next.js 16 typed routes 不允许 `route.ts` 额外 export。`dossierResponse` 去掉 `export`(仍只给同文件 GET 用),否则 `next build --webpack` 的生成类型检查失败。不是产品改动。
分支相对当前 `origin/staging` 落后 2 个提交(BUG-555/556)。未在脏树上合并,避免和本单的 `CHANGELOG` / `BUG_HISTORY` 撞车。
浏览器走查见 `docs/testing/settings-dialog-and-billing-pane-20260906.md`。本机未起登录会话,真实四分区切换留给 staging 验收。
+1 -1
View File
@@ -57,7 +57,7 @@
| `TASK-rectification-probe-answer-covers-domain-20260905.md` | `PROGRESS-rectification-probe-answer-covers-domain-20260905.md` | 区分卡答 A/B 后紧接着又问同领域"哪年…"采集题:点选答案只进推断层不写账本,计划层领域覆盖只看账本;改为 yes/weak_yes 视为该领域采集已覆盖(不写账本、不动门) | 待验收 | `988d97ae`BUG-549 |
| `TASK-composer-live-input-and-stop-20260906.md` | `PROGRESS-composer-live-input-and-stop-20260906.md` | 生成中输入框整个禁用致焦点丢失、回车丢消息(改为永不禁用 + 排队发送);生时校正停止呈现为红色告警且选择题等待中停止无效(改为中性停止态、所有 fetch 挂 abort | 待执行 | `codex/composer-live-input-and-stop-20260906`BUG-551、552 |
| `TASK-session-list-title-and-order-20260906.md` | `PROGRESS-session-list-title-and-order-20260906.md` | 历史对话标题改为首轮模型总结(一次、不扣点数、校正/今日运势保持日期标题)、侧栏去资料前缀;排序只按置顶排且元数据 PATCH 推进 `updated_at`(改为置顶 + 活动时间,改名/收藏/换模型不动顺序);历史区加 今天/昨天/7天/30天/更早 分组;列表按游标分页(每页 40、置顶首页全量、滚到底静默续取) | 待执行(串行:在 composer 单之后) | `codex/session-list-title-and-order-20260906`BUG-553 |
| `TASK-settings-dialog-and-billing-pane-20260906.md` | `PROGRESS-settings-dialog-and-billing-pane-20260906.md` | 设置弹窗尺寸随分区跳变、星盘资料格无条件铺开整张添加表单(改为固定尺寸四分区、列表→详情);「账户与点数」成为弹窗分区,删除 `/membership``/membership/orders` 页面并重定向,七处入口改回调 | 待执行(串行:在会话列表单之后) | `codex/settings-dialog-and-billing-pane-20260906`BUG-554 |
| `TASK-settings-dialog-and-billing-pane-20260906.md` | `PROGRESS-settings-dialog-and-billing-pane-20260906.md` | 设置弹窗尺寸随分区跳变、星盘资料格无条件铺开整张添加表单(改为固定尺寸四分区、列表→详情);「账户与点数」成为弹窗分区,删除 `/membership``/membership/orders` 页面并重定向,七处入口改回调 | 待验收 | `codex/settings-dialog-and-billing-pane-20260906`BUG-554 |
| `TASK-consultation-context-and-cache-20260906.md` | `PROGRESS-consultation-context-and-cache-20260906.md` | 普通对话历史只取每条前 4,000 字(报告结论被砍、无标记)、历史窗口不看模型 `context_window`、无溢出识别;改为检查点式会话摘要 + append-only 尾巴 + 按模型预算 + 一次降级重试;Anthropic 历史断点;共享方法段进系统块;后台用量页显示缓存命中率 | 待执行(串行:在会话列表单之后;动表需迁移) | `codex/consultation-context-and-cache-20260906`BUG-555/556 |
| `TASK-rectification-collect-vs-offer-consistency-20260905.md` | `PROGRESS-rectification-collect-vs-offer-consistency-20260905.md` | 带年份采集没问完就出采用卡 + 报告,同一轮又被搬家采集题把卡挤掉:决策层判 `adopt_representative` 而计划层仍有 dated 采集(BUG-546 只修了一半);改为剩余采集未完保持 `collect_evidence`,出牌轮才出卡写报告 | 已验收通过 `ca4e2408`2026-09-05staging 部署仍停在 `afd14948``deploy-staging``c295b853` 起连续失败,先解决 `bab07187` 的待迁移) | `codex/rectification-collect-vs-offer-consistency-20260905`BUG-550 |
| `TASK-api-not-configured-mislabel-20260904.md` | `PROGRESS-api-not-configured-mislabel-20260904.md` | 16 处路由把数据库瞬断(部署切换窗口)兜底翻译成 503「服务尚未配置」;改为仅配置错误用该文案,其余 `service_unavailable`,收敛为共享 helper | 待验收 | `codex/api-not-configured-mislabel-20260904`BUG-542 |
@@ -0,0 +1,68 @@
# Staging 人肉复核 · 设置弹窗与账户与点数(2026-09-06)
给产品负责人。不要把真实出生资料、真实用户问题或对话正文写进任何记录。试用问题时用虚构句,例如「半年内换工作时机」。
对应 BUG-554。测之前先做第 0 条。
## 0. 确认测的是新版本
浏览器打开 `https://staging.jyotisha.chat/api/health`,看 `deployment.gitCommit` 前 8 位是否等于本单合入 staging 后的提交。不一致 = 先别测。
## 1. 四个分区外框不动(P0
1. 登录后点头像,打开「个人资料」。
2. 依次点左侧 星盘资料、账户与点数、通用设置,再点回个人资料。
- ✅ 预期:弹窗外框宽高不变;只有右侧内容换。退出登录仍是小确认窗。
- ❌ 失败:换分区时窗口变大变小,或主题格缩成小盒子。
## 2. 星盘资料默认只有列表(P0)
1. 打开「星盘资料」。
- ✅ 预期:先看到「我的星盘」一条和「其他人」列表(可空),底部「添加其他人」。看不到关系下拉、出生表单铺在列表下面。
- ❌ 失败:一打开就出现整张「添加其他人的星盘」表单。
## 3. 添加 → 保存 → 回列表(P0)
1. 点「添加其他人」,用虚构资料保存。
2. 看是否回到列表,新的一行出现。
3. 点那一行进入详情:有 设为默认 / 删除 / 用于合盘;点「← 星盘资料」返回。
4. 点本人那一行:有编辑表单,没有删除。
- ✅ 预期:表单只在详情/添加视图;保存后回列表。
- ❌ 失败:保存后仍停在铺开的表单,或本人详情能删除。
## 4. 余额 / 头像菜单 / 402 / 付费墙都在当前页打开账单(P0)
1. 点顶栏余额。
2. 点头像菜单「账户与点数」。
3. 用一个余额不足的账户发一条虚构问题(或看 402)。
4. 若出现入门付费墙,点「查看套餐与会员」。
- ✅ 预期:都打开同一设置弹窗的「账户与点数」,对话还在,不跳到 `/membership`
- ❌ 失败:整页刷新或地址变成 `/membership`
## 5. 下单打开新标签,回来余额刷新(P0)
1. 在会员套餐或点数包点购买。
2. 看是否新标签打开收银台,按钮短暂显示「跳转收银台…」,区内显示「等待支付结果」。
3. 支付完成后回到原标签(可用测试单)。
- ✅ 预期:当前页还在;余额更新。不要出现 spinner 或「正在加载」。
- ❌ 失败:当前页被收银台顶掉,或一直转圈。
## 6. 旧链接落到首页并打开分区(P1)
1. 浏览器打开 `https://staging.jyotisha.chat/membership`
2. 再打开 `https://staging.jyotisha.chat/membership/orders`
- ✅ 预期:落在首页,设置弹窗打开账户与点数;订单链接打开订单记录页签。地址栏随后不再带 `settings=`
- ❌ 失败:404,或停在旧会员整页。
## 7. 手机端全屏四页签可滚(P1)
1. 把窗口缩到手机宽度,打开设置。
- ✅ 预期:全屏;顶部四格页签;内容区自己滚,外框不动。
- ❌ 失败:页签把内容顶没,或整页跟着内容一起撑高。