Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE
103 lines
9.7 KiB
Markdown
103 lines
9.7 KiB
Markdown
# TASK · 星盘档案可编辑本人、各页头像弹账户菜单、我的报告去掉提示(2026-09-28)
|
||
|
||
## 基线与依赖
|
||
|
||
- **串行**:本单改 `frontend/src/app/(app)/page.tsx`,必须等 `TASK-birth-sky-polish-20260928`(分支 `codex/birth-sky-pacing-20260928`)由 Claude 验收并推上 staging 之后再开工。开工时 `git fetch origin --prune`,以当时的 `origin/staging` 为基线,SHA 写进 PROGRESS。
|
||
- 分支 / 工作树:`codex/self-edit-avatar-menu-20260928` / `.worktrees/self-edit-avatar-menu-20260928`。
|
||
- 进度记录:`docs/tasks/PROGRESS-self-edit-avatar-menu-20260928.md`。
|
||
- BUG 编号:开工时核对 `docs/BUG_HISTORY.md` 最大号。polish 单占用 BUG-1080,本单从 **BUG-1081** 起;若开工时已被占用,顺延并在 PROGRESS 写明。
|
||
|
||
## 事实(Claude 2026-09-28 在 `origin/staging` 核实;行号按符号定位)
|
||
|
||
1. **全站没有任何地方能改本人的出生资料**(回归):
|
||
- `ab6c55f8`(星盘档案 P1,2026-09-25)的提交说明写「/people replaces the settings chart pane」:设置弹窗里原来的星盘资料块被 `/people` 取代,首页那块表单(`chart-library-panel.tsx`)随后在 `d08ffdc0` 作为「没有引用」的文件删掉。
|
||
- `components/people/people-page.tsx`:只有 `role === "other"` 有「编辑」按钮;本人那一格只显示「本人不能删除」。常量 `SELF_GENDER_NOTE` 上方注释写「本人 has no edit view here」。
|
||
- 设置 → 个人资料(`components/profile-panel.tsx`)只能改头像和性别。
|
||
- 服务端能力还在:`PATCH /api/account`,由 `lib/account-profile-patch.ts` 的 `accountProfilePatchSchema` 校验,要求改出生资料时必须同时提交 `birth_time_source`。
|
||
- 首页 hook `use-profile-onboarding.ts` 里的 `saveProfile` 已经没有任何 UI 调用。`page.tsx` 只从 hook 里解构出它,并没有用。
|
||
- 能证明这是漏掉而不是有意:生时校正的用户文案 `declaredWindowLockedReply`(`lib/rectification-agentic/user-copy.ts`)里写着「请先到资料里改出生时间」,但用户找不到这个地方。
|
||
- 星盘档案任务书 `TASK-people-archive-p1-20260924` D1 写的是「户主本人也是其中一个,统一列表、统一操作;户主不可删」,并没有说「本人不可编辑」。
|
||
2. **除首页外点头像直接回首页**(是当初的设计,不是代码写错):
|
||
- `components/app-sidebar.tsx` 页脚:只有首页通过 `registerShellControls` 注册了 `controls`,这时才渲染 `Menu.Root` 账户菜单;其他页走只读分支,是一个 `AppLink href="/"`,注释写「The account menu and its dialogs live on `/`」。
|
||
- 出处:侧栏统一单(BUG-744~746);BUG_HISTORY 里写过「次级页点头像应当跳回首页而不是没反应」。
|
||
3. **「我的报告」页顶部有一段说明和一行统计**:`components/personal-report/personal-report-center.tsx` 的 `.report-center-hero`,内容是「有填报到分钟的出生时间即可生成……你无需停留等待。」和「共 N 份 · 已完成 N 份 · ……」。
|
||
|
||
## 决策记录(产品 2026-09-28)
|
||
|
||
1. **本人在 `/people` 可以编辑**:和他人使用同一张 `ChartProfileForm`,保存走本人原来的 `PATCH /api/account`。本人仍然不能删除。
|
||
- 这推翻了 `people-page.tsx` 里「本人 has no edit view here」的做法。
|
||
2. **所有页面点头像都弹出同一个账户菜单**,推翻侧栏统一单里「次级页头像 = 回首页链接」的约定:
|
||
- 切换主题:在当前页直接生效(`ThemePreferenceMenu` 本来就不依赖首页)。
|
||
- 「个人资料」「通用设置」「账户与点数」「退出登录」:在首页照旧直接打开弹窗;在其他页跳到首页,并自动打开对应的弹窗。
|
||
- 不把弹窗搬到每一页(那样首页首屏会多一个加载态,违反 AGENTS §6「揭幕后不得出现加载」),留作以后评估。
|
||
3. **「我的报告」去掉整个顶部说明区**:说明段和统计行都删。页面从「报告记录」列表开始。生成按钮的 `title` 悬停提示不动。
|
||
|
||
## 硬红线
|
||
|
||
1. 本人出生资料只经 `PATCH /api/account` 写入,并照 `accountProfilePatchSchema` 提交 `birth_time_source`。不得把本人写进 `chart_profiles`,不得在客户端伪造 `active_*` 或校正结果字段。
|
||
2. `page.tsx` 行数不增长;`Home()` 的 `useState` / `useRef` 数不增长。新逻辑放进 `hooks/` 或 `lib/` 或组件;删掉 `page.tsx` 里已经没人用的 `saveProfile` 解构。
|
||
3. 首页仍是 `○ Static`;首屏 gzip ±2%;揭幕后不出现 spinner / 骨架。
|
||
4. 账户菜单只有一份实现(同一个 `Menu.Popup`),不准复制出第二份菜单。
|
||
5. 改既有断言写「原值 / 新值 / 原因」三栏;动组件前先 grep `frontend/tests/` 里按源码文本断言的合同测试(`sidebar-contract.test.ts`、`people-archive-view.test.tsx`、`personal-report-entry.test.ts` 等)。
|
||
6. 不改表、不加迁移、不加依赖。隐私:测试只用虚构资料。
|
||
|
||
## 任务分解
|
||
|
||
### S1 · 本人可在星盘档案编辑(BUG-1081)
|
||
|
||
- `people-page.tsx`:本人也有「编辑」按钮,位置同他人;编辑视图复用 `ChartProfileForm`(显示岁差与性别,和他人一致)。本人的编辑视图**没有**删除区。
|
||
- 保存:把 `use-profile-onboarding.ts` 里 `saveProfile` 用到的持久化逻辑(`persistProfile` 及其载荷构造)抽成 `lib/` 里的纯函数或小 hook,供 `/people` 调用;首页若已不再需要 `saveProfile`,从 hook 和 `page.tsx` 一起删掉。
|
||
- 保存成功后,刷新 `/people` 列表里的本人数据,并让用到本人资料的缓存失效(侧栏、当前人物、星盘页),和编辑他人后的做法一致。执行方先查清编辑他人时刷新了哪些,照做。
|
||
- 出生资料一改,照原 `saveProfile` 的做法重置 `birthTimeConsultationConsent` 这类依赖出生资料的本地状态。首页重新挂载时会从 `/api/account` 重新读取,这一点要核实。
|
||
- 失败时在表单里提示,文案对照 VOICE。
|
||
- 「性别在设置 → 个人资料里改」这句小字:表单里已经能改性别,删掉。
|
||
- **验收**:
|
||
- 测试:本人有「编辑」按钮;本人编辑视图无删除;保存调用 `PATCH /api/account` 且带 `birth_time_source`;不写 `chart_profiles`;失败有提示。
|
||
- BUG-1081 写全:现象、触发、根因(`ab6c55f8` 取代设置里的资料块时漏了本人编辑)、修复、验证、防复发(加一条合同测试:全站至少有一个本人出生资料编辑入口),并说明旧测试为什么没拦住。
|
||
|
||
### S2 · 各页头像弹出账户菜单
|
||
|
||
- `app-sidebar.tsx`:只读分支不再渲染 `AppLink href="/"`,改成和首页同一个 `Menu.Root`。菜单项的回调在没有 `controls` 时改成跳转:`/?account=profile|general|billing|logout`。
|
||
- 余额「N 点」:只读模式下若拿不到 `credits`,这一格不显示数字,不要显示 0。
|
||
- 首页:写一个类似 `NewChatDeepLink` 的小组件或 hook,读取一次 `?account=` 意图,在账户就绪后打开对应弹窗,然后用 `history.replaceState` 去掉这个参数(刷新或后退都不会再弹)。放在 `page.tsx` 之外,`page.tsx` 只接一行线。
|
||
- 未登录时参数无效,照常走登录。
|
||
- **验收**:
|
||
- 测试:只读模式渲染菜单而不是链接;四个菜单项在只读模式各自跳到对应的 `?account=`;首页读取意图后打开对应弹窗并清掉参数;非法值忽略。
|
||
- `sidebar-contract.test.ts` 里锁「只读 = 链接到 /」的断言按新行为改写,三栏说明。
|
||
- 无头 Chrome:在 `/people` 视口 1280×800 与 390×844 各截一张菜单展开图,放 scratchpad,路径写进 PROGRESS。
|
||
|
||
### S3 · 我的报告去掉顶部说明区
|
||
|
||
- `personal-report-center.tsx`:删 `.report-center-hero` 整段,以及只给它用的 `hasGenerating` / `latestReady` 计算(先确认没有别处在用)。`globals.css` 里只给它用的样式一并删。
|
||
- `personal-report-entry.test.ts` 的 “global report copy …” 测试:对 `reportCenterSource` 的四条 `match` 改成 `doesNotMatch`(锁住不再出现),三栏说明。对 `componentSource` 的断言不动。
|
||
- **验收**:报告页首屏直接是「报告记录」;测试通过。
|
||
|
||
### S4 · 文档
|
||
|
||
- `frontend/DESIGN.md`:侧栏页脚在各页的行为;`/people` 本人可编辑;报告页顶部。
|
||
- `frontend/docs/VOICE.md`:新增或删除的文案。
|
||
- `CHANGELOG.md`:一条。
|
||
- `docs/BUG_HISTORY.md`:BUG-1081。
|
||
- `docs/testing/self-edit-avatar-menu-20260928.md`(新建真机清单):
|
||
- 在 `/people` 改本人出生时间,回首页,再打开星盘页核对已更新;
|
||
- 在 `/chart`、`/people`、`/reports`、`/ephemeris` 各点一次头像,菜单都弹出;点「账户与点数」跳首页并打开点数弹窗;刷新后不再弹;
|
||
- 在次级页切换主题,立即生效;
|
||
- 我的报告顶部没有说明段。
|
||
|
||
## 验证
|
||
|
||
- `tsc --noEmit` 0 错;`npm run lint` 0 error。
|
||
- `npm test` 全量:与基线比测试名清单,不得有测试名消失;失败清单与基线逐条同名(无 Docker 的 24 条)。
|
||
- `rm -rf .next && next build`:`/` 仍 `○ Static`;首屏 gzip 与基线同口径对比,在 ±2% 内(同一脚本在基线与交付各建一次)。
|
||
- `python3 -m pytest tests/test_repo_privacy_markers.py -q`。
|
||
|
||
## 让步顺序
|
||
|
||
1. S2 的余额数字在只读模式下可以不显示。
|
||
2. S2 跳转后打开弹窗若和首页揭幕时序冲突,可以等揭幕完成后再打开,但不得加等待态。
|
||
3. S1 本人可编辑、S3 删除说明区不可让步。
|
||
|
||
## 交付
|
||
|
||
- 按 S1 / S2 / S3+S4 分提交,**不推送**;由 Claude 独立验收后快进推 staging。
|