feat(birth-sky): poster-only dialog, date/time/city caption, slower reveal, paywall on first refused send (P1–P5, BUG-1080)
TASK-birth-sky-polish-20260928. - P1: chart page dialog shows only the picture on a dimmed stage, 「保存图片」 below, icon × in the corner. - P2: BFF returns one server-built `caption` (「1994年5月18日 07:40 · 杭州」); printed under the fact line in all three places; adopted time adds 「 · 校正后」. - P3: convergence 3 s + words 2.5 s + fade 1 s; settled frame still equals the exported cover. - P4: redeem paywall no longer opens when the starter home appears; first send refused for credits opens it, later ones open billing; convergence dialog portalled to <body>. BUG-1080 investigating (Chrome repro rules out the overlay covering the convergence). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
1a4f77584b
commit
dec36bce01
+10
-8
@@ -677,6 +677,7 @@ page. Three parts now, in reading order:
|
||||
### Settings dialog
|
||||
|
||||
- **Placement:** the overlay and the onboarding paywall portal to `document.body`. `SidebarInset` stays `inert` while a dialog is open (the BUG-744~746 focus contract); the dialog itself must not sit inside that subtree (BUG-968). Closing still uses the existing overlay click, the header button, and the window-level Escape listener.
|
||||
- **Redeem paywall timing (2026-09-28, TASK-birth-sky-polish-20260928 P4):** the 「解锁完整咨询」 paywall no longer opens when the starter home appears. The first send on the page refused for lack of credits (the pre-flight balance check or a 402) opens it, and the typed question stays in the composer; every later refusal opens the billing dialog as before. Rectification's own 402 path is unchanged.
|
||||
- **Structure:** one fixed chrome for three panes — 个人资料, 账户与点数, 通用设置. The chart archive is no longer a pane; `?settings=chart` leaves for `/people`. Left nav is 200px, has a hairline boundary, and does not scroll; the title bar stays put; only the right-hand content pane scrolls. The pane menu uses icon + label rows without a trailing chevron because these controls switch content inside the same dialog. Logout stays a separate 400px confirmation.
|
||||
- **Width / height:** desktop `width: min(100vw - 32px, 880px)`, with `height: min(84vh, 640px)` as the base and `min(84dvh, 640px)` applied inside `@supports (height: 1dvh)`. The right content pane uses 32px horizontal and bottom inset on desktop. All four panes share one class (`.settings-modal`), so switching panes cannot change the frame. At ≤767px the dialog is full-screen with four equal tabs along the top and 16px content inset.
|
||||
- **Pane menu states:** default is transparent with secondary ink; hover is a 55% wash of `--color-canvas-muted` keeping secondary ink; current is the solid muted surface with primary ink. No accent bar, no trailing navigation chevron, and no weight change — hierarchy here comes from ink rank and surface, matching “Hierarchy inside the nav comes from ink rank, not hue”. The sidebar's 2px `--sidebar-ring` on the active session is deliberately **not** changed to match; the two surfaces read differently on purpose until that is revisited.
|
||||
@@ -1131,21 +1132,21 @@ D40 / D45 / D60 的表格上方,出生时间不是「已校正」时多一句
|
||||
- **等待:** 揭幕后不得再出现 spinner / 骨架 / 「正在加载」。首屏未到时 `SecondaryPageShell` 写「这一天的星历还没拿到。」,居中在已撑满的内容区里。未登录是静态「请先登录」加去登录,不是转圈。同一会话再次进入直接用模块缓存。
|
||||
- **文案:** 不得写运势结论,不得把三套坐标系换算或叠加。当日总评只来自上面的固定规则。不另印「这是天象本身」这类边界说明。
|
||||
|
||||
## 17. 那一刻的天空(2026-09-28,TASK-birth-sky-cover-20260928)
|
||||
## 17. 那一刻的天空(2026-09-28,TASK-birth-sky-cover-20260928;第三轮 TASK-birth-sky-polish-20260928)
|
||||
|
||||
出生地、出生那一刻头顶的真实天空,画成一张 3:4 封面。不讲运势,不贴标签。产品从三版样稿(`docs/tasks/assets/birth-sky-cover-sample-20260928.html`)里选了 C;A 年轮、B 一笔画不做。
|
||||
|
||||
- **投影与方位:** 天顶在圆心,r = (90 − 高度) / 90 × R;北在上,**东在左**(仰望天空,不是俯视地图)。圆是地平线,另有 30° / 60° 两道虚线高度圈;东南西北四个字在圆外。方位角一律「自正北起、向东为正」(Swiss Ephemeris 的 `azalt` 自正南起算,服务端已换算)。高度是几何高度,不加大气折射。
|
||||
- **画什么:** 地平线以上的太阳、月亮、水金火木土;太阳是赭色空心圆加光晕,其余是小圆点加中文名。V ≤ 4.0 的亮星(耶鲁亮星表,公有领域),点的大小按星等。北斗、仙后座、猎户座三组连线,只连两端都在地平线上的那一段。罗睺、计都不画;月亮在地平线下不画,只进事实句。
|
||||
- **版面(600 × 800 设计格,导出 1080 × 1440):** 顶部小字「JYOTISHA · 那 一 刻」→ 细线 → 主句 → 天空圆 → 细线 → 事实句 → 需要时「按你填写的时间」(出生时间不是已采用的校正时间时)→ 最底「仅供自我探索,不替你做决定。」。主句与顶部小字用 Jyotisha Serif SC(§3);画布绘制前 `document.fonts.load` 最多等 1.5 秒,超时就用黑体画,不出等待态。事实句、方位字、行星名、底部说明用黑体栈。
|
||||
- **版面(600 × 800 设计格,导出 1080 × 1440):** 顶部小字「JYOTISHA · 那 一 刻」→ 细线 → 主句 → 天空圆 → 细线 → 事实句 → 出生资料一行(caption,见下)→ 最底「仅供自我探索,不替你做决定。」。主句与顶部小字用 Jyotisha Serif SC(§3);画布绘制前 `document.fonts.load` 最多等 1.5 秒,超时就用黑体画,不出等待态。事实句、caption、方位字、行星名、底部说明用黑体栈。
|
||||
- **两套 palette,只用现有 token:** `night`(屏幕)= 深色主题的页底 `#1a1a19`、墨色 `#f2f0ea`、二三级墨色、深色细线、深色 action `#d78064` 画太阳;`paper`(报告打印)= `--report-paper`、`--color-ink`、`--report-rule`、`--report-accent` 画太阳。不新增品牌色。
|
||||
- **不印出生资料:** 图上没有姓名、日期、时刻、经纬度、地名;接口响应里也没有。天空本身会透露大致时段,产品已接受。文件名固定 `jyotisha-sky.png`。
|
||||
- **印日期、时刻、城市(2026-09-28 产品推翻「不印出生资料」):** 事实句下一行(原「按你填写的时间」的位置,字号颜色不变)印 `1994年5月18日 07:40 · 杭州`:出生地当地日期、24 小时制时刻、城市。城市只取到市(去「市」字,直辖市与港澳用本名),拿不准(只有省、盟 / 地区 / 自治州、自由文本)就只印到时刻,不猜。采用了校正时间的末尾加「 · 校正后」,按填写时间的不加说明。不印区县、经纬度、时区、名字。这一行由服务端拼好,接口只下发这一个 `caption` 字符串,不下发任何出生资料字段。星盘页图片、报告封面、首次建盘过场三处都印。文件名固定 `jyotisha-sky.png`。
|
||||
- **一个画法:** 预览、保存、打印共用 `lib/birth-sky/draw.ts` 的 `drawBirthSky`(Canvas 2D 纯函数)。预览是这张 PNG 的 `<img>`,手机长按即可存图;不走 SVG 转图片(网页字体会丢)。
|
||||
|
||||
### 位置一:星盘页顶栏按钮
|
||||
|
||||
- 星盘页 `ok` 后立即预取 `/api/birth-sky?subject=<当前人物>` 并在屏外画好 PNG;**画好之后**顶栏右侧才出现一枚描边按钮「那一刻的天空」(`<Button variant="outline" size="sm">`,顶栏里按 `.chat-header-actions button` 收成 32px + 命中区外扩)。预取失败、资料不全、切人物时都不显示按钮,不占位、不报错。切换人物或改出生资料(指纹变)就按新人物重新预取。家人的盘也能生成。
|
||||
- 点按钮打开原生 `<dialog>`:窄屏占满(`100dvh`),≥860px 居中 `min(520px, 92vw)`、最高 92vh,框与报告「分块导出」抽屉同一套描边、圆角、阴影与遮罩。内容只有标题「那一刻的天空」+「关闭」、3:4 等比缩放的图、底部「保存图片」。Esc、点遮罩、关闭都能关,焦点回到按钮。所有按钮 ≥ 44px。
|
||||
- 点按钮打开原生 `<dialog>`,**只放图**(第三轮 P1,原来的灰色面板、标题栏、「关闭」文字按钮都删了):dialog 本身透明、铺满视口,`::backdrop` 是 `night` 页底色 90% 不透明;图 3:4,按视口取最大(宽不超过视口减 32px,高给下方「保存图片」一行留位),圆角 `--radius-md`;图下方居中「保存图片」(night 墨色细描边,透明底);右上角一个只有图标的 ×(读屏名「关闭」)。点图以外的地方、按 Esc、点 × 都能关,焦点回到按钮。所有按钮 ≥ 44px。窄屏和桌面同一套,不再有桌面居中面板。
|
||||
- 「保存图片」:浏览器能分享文件时(iOS Safari)调 `navigator.share({ files })`,系统面板里有「存储图像」;否则 Blob + `a.download`。用户取消分享不算错误、不提示。
|
||||
- 弹层、画布与导出代码都在懒加载 chunk 里(`next/dynamic` + 动态 `import()`),首页 `/` 不带它们。按钮本身是星盘页里的一个普通 `<Button>`(只在数据就绪时渲染)。
|
||||
- 等待:没有等待态。按钮出现时图已就绪;弹层打开就是图。
|
||||
@@ -1164,10 +1165,11 @@ D40 / D45 / D60 的表格上方,出生时间不是「已校正」时多一句
|
||||
|
||||
- **触发不变:** 只有一处——首页 onboarding 里**自己的**出生地保存成功(`saveOnboardingPlace` 成功、下一步已设好之后)。每个账户只发生一次,没有「看过」标记、不写库。星盘档案里新建家人、设置里改资料、平时打开首页都不触发。
|
||||
- **不等待:** 保存成功后 onboarding 照常走到下一步,同时取 `/api/birth-sky?subject=self`、等宋体(最多 1.5 秒)、加载过场代码;三样都在 **3 秒**内到齐才开始放,否则静默跳过:不提示、不重试、不转圈、不骨架(§9)。过场开始时数据已全部就绪。
|
||||
- **时序(约 3 秒):** ① 汇聚约 1.5 秒:地平线以上的恒星与行星从散开的位置 ease-out(三次方)汇聚到真实投影位置;散开位置由这张盘自己的数据做种子,均匀撒在地平线圆内,同一张盘每次一样。地平线圆、30° / 60° 高度圈、方位字、星座连线、行星名同步淡入。整层前 200ms 淡入,避免页面一下变黑。② 显现文字约 1 秒:顶部小字、细线、主句、事实句、底部说明在前 400ms 淡入,然后停留。③ 淡出约 0.5 秒:整层透明度降到 0,露出**原本的下一步**(问候 / 首页,或出生时间校正引导),下一步不因它改变。
|
||||
- **时序(约 6.5 秒,第三轮放慢):** ① 汇聚约 3 秒:地平线以上的恒星与行星从散开的位置 ease-out(三次方)汇聚到真实投影位置;散开位置由这张盘自己的数据做种子,均匀撒在地平线圆内,同一张盘每次一样。地平线圆、30° / 60° 高度圈、方位字、星座连线、行星名同步淡入。整层前 400ms 淡入,避免页面一下变黑。② 显现文字约 2.5 秒:顶部小字、细线、主句、事实句、caption、底部说明在前 600ms 淡入,然后停留。③ 淡出约 1 秒:整层透明度降到 0,露出**原本的下一步**(问候 / 首页,或出生时间校正引导),下一步不因它改变。
|
||||
- **最后一帧就是封面:** 每一帧都是 `drawBirthSky` 画的,只对位置插值(t = 0 散开、t = 1 真实位置,`interpolateSkyPoint`,t = 1 精确返回真实点)、对透明度乘系数;停留阶段的画布调用序列与导出封面逐条相同(单测逐调用比对)。
|
||||
- **全屏、无按钮:** 原生 `<dialog>`(顶层,0 点数账户的兑换弹窗若同时出现,过场在它之上)铺满视口,底色是 `night` 的页底色;画布按视口取最大的 3:4 区域、乘 `devicePixelRatio` 绘制,`requestAnimationFrame` 驱动,卸载时取消。点击、触摸(`pointerdown`)或 Esc 立刻结束,直接进入下一步。
|
||||
- **减少动态效果:** `prefers-reduced-motion: reduce` 时不汇聚:成品画面整体淡入(400ms)、停留、同一时刻淡出,总长同样约 3 秒。
|
||||
- **全屏、无按钮:** 原生 `<dialog>`,`createPortal` 挂到 `document.body`(在 `SidebarInset` 之外,不受弹窗打开时的 `inert` 影响,与账户弹窗、兑换弹窗同一做法,BUG-968 / BUG-1080)铺满视口,底色是 `night` 的页底色;画布按视口取最大的 3:4 区域、乘 `devicePixelRatio` 绘制,`requestAnimationFrame` 驱动,卸载时取消。点击、触摸(`pointerdown`)或 Esc 立刻结束,直接进入下一步。
|
||||
- **减少动态效果:** `prefers-reduced-motion: reduce` 时不汇聚:成品画面整体淡入(600ms)、停留、同一时刻淡出(1 秒),总长同样约 6.5 秒。
|
||||
- **与兑换弹窗不再同时出现:** 0 点数账户的「解锁完整咨询」兑换弹窗不再在首页出现时自动弹出,改为本页第一次因点数不足发不出消息时弹(见 §账户弹窗「Placement」条),所以建盘后首页只有过场。
|
||||
- **结束后的提示:** 过场正常结束或被点掉后,首页用已有的 sonner Toaster 轻提示一次「这片天空在星盘页可以保存。」(VOICE.md)。取数失败、超时时没有过场,也没有提示。
|
||||
- **平时的首页加载动画不改。** 这是用户操作之后的一次性结果展示,不是首页加载等待,不违反 §9「首页只揭幕一次」;轨道环揭幕逻辑不动。
|
||||
- 代码:时序与插值是 `lib/birth-sky/converge.ts` 的纯函数;过场组件 `components/birth-sky/birth-sky-converge.tsx`(懒加载 chunk,含 `draw.ts` 与样式);状态在 `hooks/use-birth-sky-reveal.ts`,`page.tsx` 接线未变(`Home()` 的 `useState` / `useRef` 数不变)。星盘页的「那一刻的天空」弹窗删掉了只给揭幕用的 `is-reveal` 样式与「继续」按钮,其余不动。
|
||||
- 代码:时序与插值是 `lib/birth-sky/converge.ts` 的纯函数;过场组件 `components/birth-sky/birth-sky-converge.tsx`(懒加载 chunk,含 `draw.ts` 与样式);状态在 `hooks/use-birth-sky-reveal.ts`,`page.tsx` 接线未变(`Home()` 的 `useState` / `useRef` 数不变)。星盘页的「那一刻的天空」弹窗删掉了只给揭幕用的 `is-reveal` 样式与「继续」按钮。
|
||||
|
||||
Reference in New Issue
Block a user