diff --git a/docs/BUG_HISTORY.md b/docs/BUG_HISTORY.md index 59907665..e838a1e6 100644 --- a/docs/BUG_HISTORY.md +++ b/docs/BUG_HISTORY.md @@ -22240,3 +22240,18 @@ - 关联记录:BUG-1628(打开期间的幕布)、BUG-1516(入口「继续 / 新建一次」)、issue #124(校正界面代码与开案并行下载)。 - 复发自:无 - 修复版本:分支 `feat/global-boot-loader`。 + +## BUG-1630 | 点「生成报告」没有任何反应;年运页遮罩下面多出一块黑色 + +- 状态:fixed-pending-verify(代码 + 回归测试;登录态真机未测) +- 首次发现 / 最近更新:2026-11-05(产品负责人截图反馈)/ 2026-11-05 +- 影响面:`frontend/src/components/personal-report/generate-personal-report-button.tsx`、`personal-report-center.tsx`、`app/annual-report.css`。 +- 现象:① 我的报告页点「完整本命报告 · 生成报告」,看不到任何动画、提示或跳转(报告其实已创建并写完,列表里出现了当天的「已完成」)。② 年运页开始前的半透明遮罩只盖到内容高度,下面露出一条更深的底色。 +- 触发条件:① 报告中心点生成报告且创建成功。② 年运页内容高度小于窗口。 +- 根因:① 报告中心给按钮传了 `onCreated={() => void load()}`,成功后不跳转、不提示,只悄悄重读下面的列表;等待中只有按钮文字变成浅色「正在创建…」。② `.secondary-page` 是 `align-content: start` 的网格,`.annual-page` 的 `height: 100%` 只取到内容高度,绝对定位的遮罩随之变短。 +- 修复:① 按钮在提交期间立即持有整窗页面幕布(「正在创建报告」),成功后跳到该报告页(报告页自己显示写作进度),幕布一直留到报告页接手;失败照旧弹出原因并撤下幕布。报告中心不再传 `onCreated`。② `.secondary-page:has(> .annual-page)` 改为单行 `minmax(0, 1fr)` 并拉伸,年运页填满页面主体。 +- 验证:新增 `frontend/tests/report-create-feedback-1630.test.ts` 2 条;报告与年运相关测试 212 条全绿;`tsc --noEmit` 0 错;改动文件 eslint 0 error。 +- 防复发:任何「创建 / 提交」按钮成功后必须有可见结果(跳转或提示),不得只静默刷新;等待期间用页面幕布或按钮内的同一动画,不只改按钮文字。 +- 关联记录:BUG-1613(页面幕布)、BUG-1611(年运写一半失败)。 +- 复发自:无 +- 修复版本:分支 `feat/global-boot-loader`。 diff --git a/frontend/src/app/annual-report.css b/frontend/src/app/annual-report.css index 3f839047..cc911d31 100644 --- a/frontend/src/app/annual-report.css +++ b/frontend/src/app/annual-report.css @@ -8,6 +8,10 @@ padding: var(--space-10) var(--space-8) var(--space-16); } .annual-page.is-veiled { overflow: hidden; } +/* The page body's grid lines content up at the top, so `height: 100%` above + resolved to the content's height and the veil stopped short of the window + bottom, leaving a bare band under it (BUG-1630). The annual page fills the cell. */ +.secondary-page:has(> .annual-page) { grid-template-rows: minmax(0, 1fr); align-content: stretch; } @media (max-width: 720px) { .annual-page { padding: var(--space-6) var(--space-4) var(--space-12); } } .annual-report { diff --git a/frontend/src/components/personal-report/generate-personal-report-button.tsx b/frontend/src/components/personal-report/generate-personal-report-button.tsx index 13bf2ed5..67a6ae25 100644 --- a/frontend/src/components/personal-report/generate-personal-report-button.tsx +++ b/frontend/src/components/personal-report/generate-personal-report-button.tsx @@ -26,6 +26,7 @@ import { navigateAppPath } from "@/lib/app-navigation"; import { notifyError } from "@/lib/notify"; import { Button } from "@/components/ui/button"; +import { usePageCurtain } from "@/hooks/use-page-curtain"; export { DEFAULT_REPORT_THEMES }; @@ -146,6 +147,10 @@ export function GeneratePersonalReportButton({ const router = useRouter(); const [submitting, setSubmitting] = useState(false); const inFlight = useRef(false); + // The click shows at once (BUG-1630, product: 「点击生成报告没有任何反应也没有动画」): + // the page curtain covers the create request and the move to the report, + // whose own page then shows the writing progress. An error drops it and says why. + usePageCurtain(submitting, { title: "正在创建报告", detail: "提交给报告服务", immediate: true }); async function handleGenerate() { if (inFlight.current || submitting) { @@ -153,6 +158,7 @@ export function GeneratePersonalReportButton({ } inFlight.current = true; setSubmitting(true); + let navigating = false; try { const requestId = createReportRequestId(); if (requestId === null) { @@ -177,6 +183,8 @@ export function GeneratePersonalReportButton({ if (onCreated) { onCreated(outcome.reportId); } else { + // Leaving for the report: the curtain stays up until its page holds it. + navigating = true; navigateAppPath( `/reports/${encodeURIComponent(outcome.reportId)}`, (href) => router.push(href), @@ -189,7 +197,7 @@ export function GeneratePersonalReportButton({ notifyError("网络异常,请检查连接后重试。"); } finally { inFlight.current = false; - setSubmitting(false); + if (!navigating) setSubmitting(false); } } diff --git a/frontend/src/components/personal-report/personal-report-center.tsx b/frontend/src/components/personal-report/personal-report-center.tsx index 22d42c72..434b6a81 100644 --- a/frontend/src/components/personal-report/personal-report-center.tsx +++ b/frontend/src/components/personal-report/personal-report-center.tsx @@ -293,7 +293,10 @@ export function PersonalReportCenter() {

完整本命报告

星盘、力量、大运和瑜伽,中英两版

- void load()} /> + {/* BUG-1630: a created report opens at once (its page shows the writing + progress) behind the page curtain; it used to only re-read this list, + so the click looked like it did nothing. */} + {/* #154: the annual entry opens the annual report page directly (no entry page). */}
diff --git a/frontend/tests/report-create-feedback-1630.test.ts b/frontend/tests/report-create-feedback-1630.test.ts new file mode 100644 index 00000000..7d5a31e2 --- /dev/null +++ b/frontend/tests/report-create-feedback-1630.test.ts @@ -0,0 +1,23 @@ +import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; +import test from "node:test"; + +// BUG-1630(2026-11-05 产品:「点击生成报告没有任何反应也没有动画,也没有提醒」;「年运下面怎么还多一块黑色」)。 + +const read = (path: string) => readFileSync(new URL(path, import.meta.url), "utf8"); + +test("生成报告 holds the page curtain at once and opens the created report", () => { + const button = read("../src/components/personal-report/generate-personal-report-button.tsx"); + assert.match(button, /usePageCurtain\(submitting, \{ title: "正在创建报告", detail: "提交给报告服务", immediate: true \}\);/); + assert.match(button, /navigating = true;\n\s+navigateAppPath\(/); + assert.match(button, /if \(!navigating\) setSubmitting\(false\);/); + const center = read("../src/components/personal-report/personal-report-center.tsx"); + // 原值: void load()} />(成功后只重读列表,看起来没反应) + assert.match(center, //); + assert.doesNotMatch(center, /onCreated=\{/); +}); + +test("the 年运 page fills the page body, so its veil reaches the window bottom", () => { + const css = read("../src/app/annual-report.css"); + assert.match(css, /\.secondary-page:has\(> \.annual-page\) \{ grid-template-rows: minmax\(0, 1fr\); align-content: stretch; \}/); +});