diff --git a/src/renderer/src/components/common/AppErrorBoundary.tsx b/src/renderer/src/components/common/AppErrorBoundary.tsx
new file mode 100644
index 0000000..d5620db
--- /dev/null
+++ b/src/renderer/src/components/common/AppErrorBoundary.tsx
@@ -0,0 +1,63 @@
+import { Component, type ErrorInfo, type ReactNode } from 'react'
+import i18n from '../../i18n'
+
+interface AppErrorBoundaryProps {
+ children: ReactNode
+}
+
+interface AppErrorBoundaryState {
+ error: Error | null
+}
+
+/**
+ * 顶层错误边界。
+ *
+ * 没有它时,任何渲染期异常都会让 React 卸载整棵组件树,窗口直接变白,用户和日志都
+ * 拿不到线索。这里把异常收敛成一个可恢复的错误页,并把原始错误写进控制台。
+ *
+ * 用 i18n 实例而不是 useTranslation:错误页必须能在 React 上下文之外渲染。
+ */
+export default class AppErrorBoundary extends Component<
+ AppErrorBoundaryProps,
+ AppErrorBoundaryState
+> {
+ state: AppErrorBoundaryState = { error: null }
+
+ static getDerivedStateFromError(error: Error): AppErrorBoundaryState {
+ return { error }
+ }
+
+ componentDidCatch(error: Error, info: ErrorInfo): void {
+ console.error('[AppErrorBoundary] Uncaught render error:', error, info.componentStack)
+ }
+
+ private handleReload = (): void => {
+ window.location.reload()
+ }
+
+ render(): ReactNode {
+ const { error } = this.state
+ if (!error) {
+ return this.props.children
+ }
+
+ return (
+
+
{i18n.t('common:errorTitle')}
+
+ {i18n.t('common:errorDescription')}
+
+
+ {error.message}
+
+
+
+ )
+ }
+}
diff --git a/src/renderer/src/locales/en-US/common.json b/src/renderer/src/locales/en-US/common.json
index 4cb23e4..d812378 100644
--- a/src/renderer/src/locales/en-US/common.json
+++ b/src/renderer/src/locales/en-US/common.json
@@ -32,6 +32,9 @@
"about": "About",
"version": "Version",
"error": "Error",
+ "errorTitle": "Something went wrong",
+ "errorDescription": "An unexpected error occurred. Reload to continue.",
+ "reload": "Reload",
"warning": "Warning",
"info": "Info",
"success": "Success"
diff --git a/src/renderer/src/locales/zh-CN/common.json b/src/renderer/src/locales/zh-CN/common.json
index 9b2633c..6b425e9 100644
--- a/src/renderer/src/locales/zh-CN/common.json
+++ b/src/renderer/src/locales/zh-CN/common.json
@@ -8,5 +8,8 @@
"edit": "编辑",
"loading": "加载中...",
"error": "错误",
+ "errorTitle": "出错了",
+ "errorDescription": "发生了意外错误,请重新加载以继续。",
+ "reload": "重新加载",
"success": "成功"
}
diff --git a/src/renderer/src/main.tsx b/src/renderer/src/main.tsx
index 799f35d..21f6ac2 100644
--- a/src/renderer/src/main.tsx
+++ b/src/renderer/src/main.tsx
@@ -3,10 +3,13 @@ import './assets/theme.css'
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App'
+import AppErrorBoundary from './components/common/AppErrorBoundary'
import './i18n'
createRoot(document.getElementById('root')!).render(
-
+
+
+
)