From b2d5b4075ced4777585e0e9f93cd99c5c0c5c2a0 Mon Sep 17 00:00:00 2001 From: iven Date: Fri, 10 Apr 2026 21:42:52 +0800 Subject: [PATCH] =?UTF-8?q?fix(ui):=20P0-4=20=E2=80=94=20SaaS=20settings?= =?UTF-8?q?=20page=20crash=20from=20paginated=20API=20response?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit listRelayTasks() expected RelayTaskInfo[] but API returns {items:[], total:0, page:1, page_size:20}. When setTasks() received the paginated object, tasks.map() crashed during render, triggering the ErrorBoundary fallback "SaaS 平台加载失败". Fix: extract .items from paginated response with Array.isArray fallback. Also adds onError logging to ErrorBoundary wrappers for easier debugging. Co-Authored-By: Claude Opus 4.6 --- desktop/src/components/Settings/SettingsLayout.tsx | 6 ++++++ desktop/src/lib/saas-relay.ts | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/desktop/src/components/Settings/SettingsLayout.tsx b/desktop/src/components/Settings/SettingsLayout.tsx index 55b5419..96af5ab 100644 --- a/desktop/src/components/Settings/SettingsLayout.tsx +++ b/desktop/src/components/Settings/SettingsLayout.tsx @@ -113,6 +113,9 @@ export function SettingsLayout({ onBack }: SettingsLayoutProps) { case 'saas': return ( SaaS 平台加载失败,请稍后重试} + onError={(err, info) => { + console.error('[Settings] SaaS page render error:', err, info.componentStack); + }} > @@ -120,6 +123,9 @@ export function SettingsLayout({ onBack }: SettingsLayoutProps) { case 'billing': return ( 计费信息加载失败,请稍后重试} + onError={(err, info) => { + console.error('[Settings] Billing page render error:', err, info.componentStack); + }} > diff --git a/desktop/src/lib/saas-relay.ts b/desktop/src/lib/saas-relay.ts index 7149ae3..599cba6 100644 --- a/desktop/src/lib/saas-relay.ts +++ b/desktop/src/lib/saas-relay.ts @@ -16,14 +16,15 @@ export function installRelayMethods(ClientClass: { prototype: any }): void { // --- Relay Task Management --- - /** List relay tasks for the current user */ + /** List relay tasks for the current user (extracts items from paginated response) */ proto.listRelayTasks = async function (this: { request(method: string, path: string, body?: unknown): Promise }, query?: { status?: string; page?: number; page_size?: number }): Promise { const params = new URLSearchParams(); if (query?.status) params.set('status', query.status); if (query?.page) params.set('page', String(query.page)); if (query?.page_size) params.set('page_size', String(query.page_size)); const qs = params.toString(); - return this.request('GET', `/api/v1/relay/tasks${qs ? '?' + qs : ''}`); + const result = await this.request<{ items: RelayTaskInfo[]; total: number }>('GET', `/api/v1/relay/tasks${qs ? '?' + qs : ''}`); + return Array.isArray(result) ? result : (result?.items ?? []); }; /** Retry a failed relay task (admin only) */