diff --git a/app/canvas/[id]/page.tsx b/app/canvas/[id]/page.tsx index f1c5e90cb..c0587bfb3 100644 --- a/app/canvas/[id]/page.tsx +++ b/app/canvas/[id]/page.tsx @@ -70,6 +70,7 @@ import { CanvasChatPanel } from "@/components/canvas/CanvasChatPanel"; import { CanvasFileListPanel } from "@/components/canvas/CanvasFileListPanel"; import { ObjectPickerOverlay } from "@/components/canvas/ObjectPickerOverlay"; import { SceneFusionDialog } from "@/components/scene-fusion-dialog"; +import { ClientErrorBoundary } from "@/components/ui/client-error-boundary"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { cn, fetcher } from "@/lib/utils"; import { @@ -1041,12 +1042,39 @@ export default function CanvasEditorPage({ params }: PageProps) {
- + {selectedAgentPresetId ? ( + +
+
工作台加载失败
+
+ 当前生图工作台发生了前端异常,我已经切换到安全兜底状态。你可以先返回上一步再重新进入,或者告诉我继续修复。 +
+
+
+ } + > + + + ) : ( +
+
+
+ +
+
请先选择左侧生图模式
+
+ 选择生图模式后,这里才会加载独立的生图工作台,并显示图片槽位、补充要求和生成结果。 +
+
+
+ )} diff --git a/components/ui/client-error-boundary.tsx b/components/ui/client-error-boundary.tsx new file mode 100644 index 000000000..b4dd2f632 --- /dev/null +++ b/components/ui/client-error-boundary.tsx @@ -0,0 +1,38 @@ +"use client"; + +import React from "react"; + +interface ClientErrorBoundaryProps { + children: React.ReactNode; + fallback: React.ReactNode; +} + +interface ClientErrorBoundaryState { + hasError: boolean; +} + +export class ClientErrorBoundary extends React.Component< + ClientErrorBoundaryProps, + ClientErrorBoundaryState +> { + constructor(props: ClientErrorBoundaryProps) { + super(props); + this.state = { hasError: false }; + } + + static getDerivedStateFromError() { + return { hasError: true }; + } + + componentDidCatch(error: Error, errorInfo: React.ErrorInfo) { + console.error("[ClientErrorBoundary] Caught client error:", error, errorInfo); + } + + render() { + if (this.state.hasError) { + return this.props.fallback; + } + + return this.props.children; + } +}