diff --git a/src/components/ErrorBoundary.tsx b/src/components/ErrorBoundary.tsx new file mode 100644 index 0000000..6d02c86 --- /dev/null +++ b/src/components/ErrorBoundary.tsx @@ -0,0 +1,41 @@ +import { Component, ReactNode } from 'react' + +interface Props { + children: ReactNode + fallback?: ReactNode +} + +interface State { + hasError: boolean + error?: Error +} + +export class ErrorBoundary extends Component { + constructor(props: Props) { + super(props) + this.state = { hasError: false } + } + + static getDerivedStateFromError(error: Error): State { + return { hasError: true, error } + } + + componentDidCatch(error: Error, errorInfo: any) { + console.error('ErrorBoundary caught:', error, errorInfo) + } + + render() { + if (this.state.hasError) { + return this.props.fallback || ( +
+

消息渲染出错

+

+ {this.state.error?.message || '未知错误'} +

+
+ ) + } + + return this.props.children + } +} diff --git a/src/pages/ChatHistoryPage.scss b/src/pages/ChatHistoryPage.scss index 74c2af6..c108394 100644 --- a/src/pages/ChatHistoryPage.scss +++ b/src/pages/ChatHistoryPage.scss @@ -33,6 +33,16 @@ gap: 12px; align-items: flex-start; + &.error-item { + padding: 12px; + background: var(--bg-secondary); + border-radius: 8px; + color: var(--text-tertiary); + font-size: 13px; + text-align: center; + justify-content: center; + } + .avatar { width: 40px; height: 40px; diff --git a/src/pages/ChatHistoryPage.tsx b/src/pages/ChatHistoryPage.tsx index 45404e8..18c4f56 100644 --- a/src/pages/ChatHistoryPage.tsx +++ b/src/pages/ChatHistoryPage.tsx @@ -2,6 +2,7 @@ import { useEffect, useState } from 'react' import { useParams, useLocation } from 'react-router-dom' import { ChatRecordItem } from '../types/models' import TitleBar from '../components/TitleBar' +import { ErrorBoundary } from '../components/ErrorBoundary' import './ChatHistoryPage.scss' export default function ChatHistoryPage() { @@ -166,7 +167,9 @@ export default function ChatHistoryPage() {
暂无可显示的聊天记录
) : ( recordList.map((item, i) => ( - + 消息解析失败}> + + )) )} @@ -175,6 +178,8 @@ export default function ChatHistoryPage() { } function HistoryItem({ item }: { item: ChatRecordItem }) { + const [imageError, setImageError] = useState(false) + // sourcetime 在合并转发里有两种格式: // 1) 时间戳(秒) 2) 已格式化的字符串 "2026-01-21 09:56:46" let time = '' @@ -197,19 +202,16 @@ function HistoryItem({ item }: { item: ChatRecordItem }) { if (src) { return (
- 图片 { - const target = e.target as HTMLImageElement - target.style.display = 'none' - const placeholder = document.createElement('div') - placeholder.className = 'media-tip' - placeholder.textContent = '图片无法加载' - target.parentElement?.appendChild(placeholder) - }} - /> + {imageError ? ( +
图片无法加载
+ ) : ( + 图片 setImageError(true)} + /> + )}
) }