v0.2.0: 全面代码质量优化

- ESLint flat config + Prettier + EditorConfig
- Markdown处理器LRU缓存
- Zustand选择器优化减少重渲染
- CodeMirror Compartment主题热切换
- Preview防抖(150ms) + IndexedDB去抖(500ms)
- 组件拆分: App.tsx 310→104行, Sidebar.tsx 244→90行
- 统一错误处理 errorHandler.ts
- ConfirmDialog替代原生confirm
- LoadingSpinner加载状态
- Toast多条堆叠+类型区分
- 可访问性增强(ARIA属性、键盘导航)
- Vitest测试框架(78个测试用例)
- Git hooks(husky + lint-staged)
- 项目文档(README.md, CONTRIBUTING.md)
This commit is contained in:
thzxx
2026-06-03 22:13:32 +08:00
parent 3cecb0f9eb
commit 7a4e2b0a67
72 changed files with 5103 additions and 894 deletions
@@ -0,0 +1,87 @@
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 {
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
}
return (
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
height: '100vh',
padding: '2rem',
textAlign: 'center',
fontFamily: 'system-ui, -apple-system, sans-serif',
}}
>
<h2 style={{ marginBottom: '1rem', color: '#e74c3c' }}>
</h2>
<pre
style={{
padding: '1rem',
backgroundColor: '#f8f9fa',
borderRadius: '8px',
maxWidth: '600px',
overflow: 'auto',
fontSize: '0.875rem',
color: '#666',
}}
>
{this.state.error?.message}
</pre>
<button
onClick={this.handleReset}
style={{
marginTop: '1rem',
padding: '0.5rem 1.5rem',
border: 'none',
borderRadius: '6px',
backgroundColor: '#3498db',
color: 'white',
cursor: 'pointer',
fontSize: '1rem',
}}
>
</button>
</div>
)
}
return this.props.children
}
}