P0 致命Bug修复: - A1: openFolderDialog 类型/运行时崩溃(文件夹打开功能完全失效) - A2: SourceEditor 受控textarea手动改DOM反模式 - A3: tabStore.updateTabContent 内容相同时误标isModified 死代码清理: - B1: 删除menu:*/save/as/viewMode 三个永不触发的IPC通道 健壮性修复: - E1: rehypeFixImages 路径规范化+防越界加固 - E2: getFileName 尾斜杠返回正确文件名 - E3: EditorToolbar 行内代码按钮改用toggleInlineCodeCommand - E4: ErrorBoundary 内联样式抽为CSS类 功能增强: - D1: 标签页拖拽排序(tabStore.moveTab + TabBar DnD + CSS) - D2: Milkdown自动配对括号/引号(ProseMirror插件) - D3: 状态栏自动保存开关可点击 - D4: 文档大纲活跃标题高亮(useActiveHeading hook) - D5: 关闭窗口前flush防抖数据(flushSaveToDB) - D6: 搜索替换支持正则表达式 类型/架构: - C2: preload类型集中定义(ElectronAPI契约) - __pycache__ typo修复 文档/版本: - README/DESIGN同步为Milkdown + v0.3.10 - 项目结构树/技术栈/快捷键表更新 验证: typecheck(仅7预存), lint✅, test 96/96, vite build✅
61 lines
1.5 KiB
TypeScript
61 lines
1.5 KiB
TypeScript
import { Component, ErrorInfo, ReactNode } from 'react'
|
|
|
|
interface Props {
|
|
children: ReactNode
|
|
fallback?: ReactNode
|
|
}
|
|
|
|
interface State {
|
|
hasError: boolean
|
|
error: Error | null
|
|
}
|
|
|
|
export class ErrorBoundary extends Component<Props, State> {
|
|
constructor(props: Props) {
|
|
super(props)
|
|
this.state = { hasError: false, error: null }
|
|
}
|
|
|
|
static getDerivedStateFromError(error: Error): State {
|
|
return { hasError: true, error }
|
|
}
|
|
|
|
componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
|
|
// eslint-disable-next-line no-console -- React error boundary standard pattern
|
|
console.error('ErrorBoundary caught an error:', error, errorInfo)
|
|
}
|
|
|
|
handleReset = (): void => {
|
|
this.setState({ hasError: false, error: null })
|
|
}
|
|
|
|
render(): ReactNode {
|
|
if (this.state.hasError) {
|
|
if (this.props.fallback) {
|
|
return this.props.fallback
|
|
}
|
|
|
|
const isDev =
|
|
(typeof import.meta !== 'undefined' &&
|
|
(import.meta as { env?: { DEV?: boolean } }).env?.DEV) ??
|
|
false
|
|
|
|
return (
|
|
<div className="error-boundary-root" role="alert">
|
|
<h2 className="error-boundary-title">应用遇到了错误</h2>
|
|
{isDev && (
|
|
<pre className="error-boundary-detail">
|
|
{this.state.error?.message}
|
|
</pre>
|
|
)}
|
|
<button className="error-boundary-reset" onClick={this.handleReset}>
|
|
重试
|
|
</button>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return this.props.children
|
|
}
|
|
}
|