feat(reports): 我的报告 enters on a static shell and joins the prefetch; 过往的报告 pages 10 at a time with 加载更多 (BUG-1123, BUG-1124)
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
90b1b6fba9
commit
9a616107c2
@@ -44,6 +44,7 @@ import {
|
||||
subjectIdFromQuery,
|
||||
} from "@/lib/subject-birth";
|
||||
import { consultationSubjectFailureResponse } from "@/lib/consultation-subject-resolver";
|
||||
import { clampReportLimit, nextReportCursor, parseReportCursor, reportCursorFilter } from "@/lib/report-cursor";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
export const maxDuration = 120;
|
||||
@@ -107,7 +108,16 @@ export async function GET(request: Request) {
|
||||
if (authError || !user) {
|
||||
return NextResponse.json({ error: "请先登录" }, { status: 401 });
|
||||
}
|
||||
const subjectId = subjectIdFromQuery(new URL(request.url).searchParams.get("subject"));
|
||||
const url = new URL(request.url);
|
||||
// Keyset pages of 10 (BUG-1124). No `limit` is the first page, so an old
|
||||
// client that never sends one gets the newest 10 (was a fixed 20).
|
||||
const limit = clampReportLimit(url.searchParams.get("limit"));
|
||||
const beforeRaw = url.searchParams.get("before");
|
||||
const cursor = parseReportCursor(beforeRaw);
|
||||
if (beforeRaw && !cursor) {
|
||||
return NextResponse.json({ error: "报告列表请求无效" }, { status: 400 });
|
||||
}
|
||||
const subjectId = subjectIdFromQuery(url.searchParams.get("subject"));
|
||||
if (subjectId !== "self" && !isChartSubjectId(subjectId)) {
|
||||
return NextResponse.json({ error: "星盘不存在", code: "subject_not_found" }, { status: 404 });
|
||||
}
|
||||
@@ -118,11 +128,16 @@ export async function GET(request: Request) {
|
||||
listQuery = subjectId === "self"
|
||||
? listQuery.is("chart_profile_id", null)
|
||||
: listQuery.eq("chart_profile_id", subjectId);
|
||||
const { data, error } = await listQuery
|
||||
listQuery = listQuery
|
||||
.order("created_at", { ascending: false })
|
||||
.limit(20);
|
||||
.order("id", { ascending: false })
|
||||
.limit(limit + 1);
|
||||
if (cursor) listQuery = listQuery.or(reportCursorFilter(cursor));
|
||||
const { data: pageRows, error } = await listQuery;
|
||||
if (error) throw error;
|
||||
const reports = Array.isArray(data) ? data.map((row) => listReportView(row)).filter((report) => report.id) : [];
|
||||
const nextCursor = nextReportCursor(Array.isArray(pageRows) ? pageRows : [], limit);
|
||||
const data = Array.isArray(pageRows) ? pageRows.slice(0, limit) : [];
|
||||
const reports = data.map((row) => listReportView(row)).filter((report) => report.id);
|
||||
const failed = reports.filter((report) => report.status === "failed" && report.requestId);
|
||||
if (failed.length > 0) {
|
||||
const { data: sections, error: sectionError } = await supabase
|
||||
@@ -144,9 +159,9 @@ export async function GET(request: Request) {
|
||||
}
|
||||
for (const [index, report] of reports.entries()) {
|
||||
if (report.status !== "failed") continue;
|
||||
const source = Array.isArray(data) ? data.find((row) => (
|
||||
const source = data.find((row) => (
|
||||
row && typeof row === "object" && (row as { id?: unknown }).id === report.id
|
||||
)) : null;
|
||||
)) ?? null;
|
||||
reports[index] = listReportView(source, summarizePersonalReportFailure({
|
||||
themeCount: report.themes.length,
|
||||
sections: grouped.get(report.requestId) ?? [],
|
||||
@@ -154,7 +169,7 @@ export async function GET(request: Request) {
|
||||
}));
|
||||
}
|
||||
}
|
||||
return NextResponse.json({ reports });
|
||||
return NextResponse.json({ reports, nextCursor });
|
||||
} catch (error) {
|
||||
if (isSupabaseConfigurationError(error)) {
|
||||
return NextResponse.json(
|
||||
|
||||
Reference in New Issue
Block a user