fix(frontend): stop chart svg height warnings and idle consult status 404s
This commit is contained in:
@@ -67,7 +67,11 @@ export async function GET(request: Request) {
|
||||
if (error) {
|
||||
return NextResponse.json({ error: "暂时无法读取咨询状态" }, { status: 503 });
|
||||
}
|
||||
if (!data || typeof data.session_id !== "string") {
|
||||
if (activeLookup) {
|
||||
if (!data || typeof data.session_id !== "string") {
|
||||
return new NextResponse(null, { status: 204 });
|
||||
}
|
||||
} else if (!data || typeof data.session_id !== "string") {
|
||||
return NextResponse.json({ error: "咨询请求不存在" }, { status: 404 });
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ export function WesternWheelSvg({ western: suppliedWestern, skeleton = false }:
|
||||
<svg
|
||||
viewBox={`0 0 ${SIZE} ${SIZE}`}
|
||||
width="100%"
|
||||
height="auto"
|
||||
role="img"
|
||||
aria-label={skeleton ? undefined : "回归黄道本命盘,上升在左,宫位按 Placidus"}
|
||||
aria-hidden={skeleton || undefined}
|
||||
|
||||
@@ -299,7 +299,6 @@ export function VedicChartSvgDrawing({ chart: suppliedChart, ariaLabel, highligh
|
||||
<svg
|
||||
viewBox={`0 0 ${CHART_VIEWBOX_WIDTH} ${viewBoxHeight}`}
|
||||
width="100%"
|
||||
height="auto"
|
||||
role="img"
|
||||
aria-label={ariaLabel}
|
||||
data-skeleton={skeleton ? "true" : undefined}
|
||||
|
||||
@@ -585,8 +585,8 @@ export async function fetchConsultationStatus(sessionId: string, requestId: stri
|
||||
|
||||
export async function fetchActiveConsultationStatus(signal?: AbortSignal): Promise<ConsultationStatus | null> {
|
||||
const response = await fetch("/api/consult/status", { signal, cache: "no-store" });
|
||||
if (response.status === 204 || response.status === 404) return null;
|
||||
const payload: unknown = await response.json().catch(() => null);
|
||||
if (response.status === 404) return null;
|
||||
if (!response.ok) throw new Error(payloadMessage(payload, "暂时无法恢复后台回答"));
|
||||
const status = parseConsultationStatus(payload);
|
||||
if (status.status !== "reserved") throw new Error("后台回答状态无效");
|
||||
|
||||
@@ -34,8 +34,7 @@ export function reportChartExportSvg(chart: NorthIndianChartModel, ariaLabel: st
|
||||
const rendered = serializeSvgNode(VedicChartSvgDrawing({ chart, ariaLabel, chartId: "export-chart" }))
|
||||
.replace(/<defs>[\s\S]*?<\/defs>/g, "")
|
||||
.replace(/ clip-path="[^"]*"/g, "")
|
||||
.replace(/<svg\b/, '<svg xmlns="http://www.w3.org/2000/svg"')
|
||||
.replace(/height="auto"/, 'height="452"')
|
||||
.replace(/<svg\b/, '<svg xmlns="http://www.w3.org/2000/svg" height="452"')
|
||||
.replace(/class="([^"]*)"/g, (_match, classes: string) => {
|
||||
if (classes.includes("personal-report-chart-cell")) return 'fill="none" stroke="currentColor" stroke-width="1.25"';
|
||||
if (classes.includes("personal-report-chart-retrograde")) return 'stroke="currentColor" stroke-width="1.9"';
|
||||
|
||||
@@ -330,6 +330,15 @@ test("chart skeleton has one scoped breath rule and reduced motion is static", (
|
||||
assert.match(globalStyles, /@media \(prefers-reduced-motion: reduce\)\s*\{\s*\.chart-page-skeleton \{ animation: none; opacity: 0\.5; \}/);
|
||||
});
|
||||
|
||||
test("chart svgs omit the invalid height attribute and western height stays in css", () => {
|
||||
const westernSvg = readFileSync(new URL("../src/components/chart-page/western-wheel-svg.tsx", import.meta.url), "utf8");
|
||||
assert.doesNotMatch(vedicSvg, /height="auto"/);
|
||||
assert.doesNotMatch(westernSvg, /height="auto"/);
|
||||
assert.match(westernSvg, /width="100%"/);
|
||||
assert.match(vedicSvg, /width="100%"/);
|
||||
assert.match(globalStyles, /\.chart-page-western-svg \{[^}]*height: auto/);
|
||||
});
|
||||
|
||||
test("the (app) layout mounts one sidebar for home and the four secondary routes", () => {
|
||||
// 原值:`(secondary)/layout.tsx` 挂只读侧栏,`useSidebarData` 另拉一份列表
|
||||
// 新值:`(app)/layout.tsx` 一份 SessionListProvider + SidebarProvider,首页也在里面
|
||||
|
||||
@@ -152,3 +152,26 @@ test("status expires stale reservations after fifteen minutes but leaves fresh r
|
||||
assert.match(leaseBlock, /\.eq\("session_id", statusData\.session_id\)[\s\S]*\.eq\("request_id", statusData\.request_id\)/);
|
||||
assert.doesNotMatch(statusRoute.slice(0, statusRoute.indexOf('if (statusData.status === "reserved"')), /cancel_consultation_credit/);
|
||||
});
|
||||
|
||||
test("an empty active consultation lookup is 204 and a missing bound request stays 404", () => {
|
||||
const activeEmpty = statusRoute.slice(
|
||||
statusRoute.lastIndexOf("if (activeLookup)"),
|
||||
statusRoute.indexOf("咨询请求不存在"),
|
||||
);
|
||||
assert.match(activeEmpty, /!data \|\| typeof data\.session_id !== "string"/);
|
||||
assert.match(activeEmpty, /new NextResponse\(null, \{ status: 204 \}\)/);
|
||||
assert.doesNotMatch(activeEmpty, /咨询请求不存在|status: 404/);
|
||||
assert.match(statusRoute, /return NextResponse\.json\(\{ error: "咨询请求不存在" \}, \{ status: 404 \}\)/);
|
||||
const cloud = read("src/lib/home-cloud-sync.ts");
|
||||
const activeFn = cloud.slice(
|
||||
cloud.indexOf("export async function fetchActiveConsultationStatus"),
|
||||
cloud.indexOf("export async function patchSessionModel"),
|
||||
);
|
||||
const boundFn = cloud.slice(
|
||||
cloud.indexOf("export async function fetchConsultationStatus"),
|
||||
cloud.indexOf("export async function fetchActiveConsultationStatus"),
|
||||
);
|
||||
const statusGuard = activeFn.indexOf("if (response.status === 204 || response.status === 404) return null;");
|
||||
assert.ok(statusGuard >= 0 && statusGuard < activeFn.indexOf("response.json()"));
|
||||
assert.doesNotMatch(boundFn, /status === 204/);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user