Skip to content

Commit c103fcd

Browse files
committed
fix(ui): 全局错误边界——渲染异常显示错误卡片不再整树白屏(真机反馈定位用)
1 parent 8f7dce3 commit c103fcd

2 files changed

Lines changed: 81 additions & 2 deletions

File tree

‎app/src/App.tsx‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { getCurrentWindow } from "@tauri-apps/api/window";
1616
import ClassroomPage from "./pages/ClassroomPage";
1717
import NotesPage from "./pages/NotesPage";
1818
import SessionsPage from "./pages/SessionsPage";
19+
import AppErrorBoundary from "./components/AppErrorBoundary";
1920

2021
type Page = "classroom" | "sessions" | "notes";
2122

@@ -111,7 +112,10 @@ function App() {
111112
}, []);
112113

113114
return (
114-
<div style={{ height: "100vh", display: "flex", flexDirection: "column", fontFamily: "system-ui, sans-serif" }}>
115+
// v0.8.0 真机白屏防御(2026-08-21):全局错误边界——渲染异常显示错误
116+
// 卡片而非整树卸载白屏;console 打印调用栈便于定位(AppErrorBoundary)
117+
<AppErrorBoundary>
118+
<div style={{ height: "100vh", display: "flex", flexDirection: "column", fontFamily: "system-ui, sans-serif" }}>
115119
{/* 顶部导航 */}
116120
<nav
117121
style={{
@@ -197,7 +201,8 @@ function App() {
197201
/>
198202
</div>
199203
</main>
200-
</div>
204+
</div>
205+
</AppErrorBoundary>
201206
);
202207
}
203208

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/**
2+
* AppErrorBoundary — 全局错误边界(真机白屏防御,2026-08-21 用户反馈"启用
3+
* AI 精修后界面白屏")。
4+
*
5+
* @ai-context: React 无错误边界时,任何组件渲染异常都会卸载整棵组件树 →
6+
* 全窗口白屏且无任何线索。本边界把白屏变为错误卡片(显示
7+
* error.message + 重试/重载按钮),并 console.error 打印调用栈
8+
* ——dev 模式可查,定位根因后修复即移除或保留为兜底。
9+
*/
10+
import { Component, type ReactNode } from "react";
11+
12+
interface Props {
13+
children: ReactNode;
14+
}
15+
16+
interface State {
17+
error: Error | null;
18+
}
19+
20+
export default class AppErrorBoundary extends Component<Props, State> {
21+
state: State = { error: null };
22+
23+
static getDerivedStateFromError(error: Error): State {
24+
return { error };
25+
}
26+
27+
componentDidCatch(error: Error, info: unknown) {
28+
// dev 模式 WebView 控制台可见(tauri dev 窗口 F12 / Ctrl+Shift+I)
29+
console.error("[AppErrorBoundary] 渲染异常:", error, info);
30+
}
31+
32+
render() {
33+
if (this.state.error) {
34+
return (
35+
<div style={{ padding: 32, fontFamily: "system-ui, sans-serif", maxWidth: 640, margin: "0 auto" }}>
36+
<h2 style={{ color: "#b91c1c", fontSize: 16, marginBottom: 8 }}>
37+
⚠️ 界面出错了(已捕获,不再白屏)
38+
</h2>
39+
<pre
40+
style={{
41+
whiteSpace: "pre-wrap",
42+
fontSize: 12,
43+
color: "#374151",
44+
background: "#f9fafb",
45+
border: "1px solid #e5e7eb",
46+
padding: 12,
47+
borderRadius: 8,
48+
marginBottom: 12,
49+
}}
50+
>
51+
{this.state.error.message || String(this.state.error)}
52+
{"\n\n"}
53+
{this.state.error.stack}
54+
</pre>
55+
<div style={{ display: "flex", gap: 8 }}>
56+
<button
57+
onClick={() => this.setState({ error: null })}
58+
style={{ padding: "6px 14px", fontSize: 12, borderRadius: 6, cursor: "pointer", border: "1px solid #d1d5db", background: "#fff" }}
59+
>
60+
重试渲染
61+
</button>
62+
<button
63+
onClick={() => location.reload()}
64+
style={{ padding: "6px 14px", fontSize: 12, borderRadius: 6, cursor: "pointer", border: "none", background: "#0d9488", color: "#fff" }}
65+
>
66+
重新加载应用
67+
</button>
68+
</div>
69+
</div>
70+
);
71+
}
72+
return this.props.children;
73+
}
74+
}

0 commit comments

Comments
 (0)