mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-24 23:06:51 +00:00
fix: 修复聊天记录页面崩溃问题并添加错误边界保护
This commit is contained in:
41
src/components/ErrorBoundary.tsx
Normal file
41
src/components/ErrorBoundary.tsx
Normal file
@@ -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<Props, State> {
|
||||||
|
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 || (
|
||||||
|
<div style={{ padding: '20px', textAlign: 'center', color: '#999' }}>
|
||||||
|
<p>消息渲染出错</p>
|
||||||
|
<p style={{ fontSize: '12px', marginTop: '8px' }}>
|
||||||
|
{this.state.error?.message || '未知错误'}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.props.children
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,6 +33,16 @@
|
|||||||
gap: 12px;
|
gap: 12px;
|
||||||
align-items: flex-start;
|
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 {
|
.avatar {
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { useEffect, useState } from 'react'
|
|||||||
import { useParams, useLocation } from 'react-router-dom'
|
import { useParams, useLocation } from 'react-router-dom'
|
||||||
import { ChatRecordItem } from '../types/models'
|
import { ChatRecordItem } from '../types/models'
|
||||||
import TitleBar from '../components/TitleBar'
|
import TitleBar from '../components/TitleBar'
|
||||||
|
import { ErrorBoundary } from '../components/ErrorBoundary'
|
||||||
import './ChatHistoryPage.scss'
|
import './ChatHistoryPage.scss'
|
||||||
|
|
||||||
export default function ChatHistoryPage() {
|
export default function ChatHistoryPage() {
|
||||||
@@ -166,7 +167,9 @@ export default function ChatHistoryPage() {
|
|||||||
<div className="status-msg empty">暂无可显示的聊天记录</div>
|
<div className="status-msg empty">暂无可显示的聊天记录</div>
|
||||||
) : (
|
) : (
|
||||||
recordList.map((item, i) => (
|
recordList.map((item, i) => (
|
||||||
<HistoryItem key={i} item={item} />
|
<ErrorBoundary key={i} fallback={<div className="history-item error-item">消息解析失败</div>}>
|
||||||
|
<HistoryItem item={item} />
|
||||||
|
</ErrorBoundary>
|
||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -175,6 +178,8 @@ export default function ChatHistoryPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function HistoryItem({ item }: { item: ChatRecordItem }) {
|
function HistoryItem({ item }: { item: ChatRecordItem }) {
|
||||||
|
const [imageError, setImageError] = useState(false)
|
||||||
|
|
||||||
// sourcetime 在合并转发里有两种格式:
|
// sourcetime 在合并转发里有两种格式:
|
||||||
// 1) 时间戳(秒) 2) 已格式化的字符串 "2026-01-21 09:56:46"
|
// 1) 时间戳(秒) 2) 已格式化的字符串 "2026-01-21 09:56:46"
|
||||||
let time = ''
|
let time = ''
|
||||||
@@ -197,19 +202,16 @@ function HistoryItem({ item }: { item: ChatRecordItem }) {
|
|||||||
if (src) {
|
if (src) {
|
||||||
return (
|
return (
|
||||||
<div className="media-content">
|
<div className="media-content">
|
||||||
<img
|
{imageError ? (
|
||||||
src={src}
|
<div className="media-tip">图片无法加载</div>
|
||||||
alt="图片"
|
) : (
|
||||||
referrerPolicy="no-referrer"
|
<img
|
||||||
onError={(e) => {
|
src={src}
|
||||||
const target = e.target as HTMLImageElement
|
alt="图片"
|
||||||
target.style.display = 'none'
|
referrerPolicy="no-referrer"
|
||||||
const placeholder = document.createElement('div')
|
onError={() => setImageError(true)}
|
||||||
placeholder.className = 'media-tip'
|
/>
|
||||||
placeholder.textContent = '图片无法加载'
|
)}
|
||||||
target.parentElement?.appendChild(placeholder)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user