mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-07-27 08:48:45 +08:00
🐛 fix(ai-panel): 隔离面板与消息级渲染异常避免整块白屏
- 为 AI 面板保留本地错误边界与重新加载兜底 - 为单条消息增加渲染隔离,异常消息不再拖垮整段对话 - 补充面板与消息渲染错误上下文,便于后续定位
This commit is contained in:
@@ -12,6 +12,7 @@ import DataSyncModal from './components/DataSyncModal';
|
||||
import DriverManagerModal from './components/DriverManagerModal';
|
||||
import LogPanel from './components/LogPanel';
|
||||
import AISettingsModal from './components/AISettingsModal';
|
||||
import AIChatPanel from './components/AIChatPanel';
|
||||
import SecurityUpdateBanner from './components/SecurityUpdateBanner';
|
||||
import SecurityUpdateIntroModal from './components/SecurityUpdateIntroModal';
|
||||
import SecurityUpdateProgressModal from './components/SecurityUpdateProgressModal';
|
||||
@@ -189,8 +190,6 @@ const createClosedConnectionPackageDialogState = (): ConnectionPackageDialogStat
|
||||
confirmLoading: false,
|
||||
});
|
||||
|
||||
const createLazyAIChatPanel = () => React.lazy(() => import('./components/AIChatPanel'));
|
||||
|
||||
interface AIPanelErrorBoundaryProps {
|
||||
children: React.ReactNode;
|
||||
fallback: (error: Error | null) => React.ReactNode;
|
||||
@@ -328,7 +327,6 @@ function App() {
|
||||
const windowDiagLastSignatureRef = React.useRef('');
|
||||
const windowDiagLastAtRef = React.useRef(0);
|
||||
const connectionWorkbenchState = getConnectionWorkbenchState(isStoreHydrated, hasLoadedSecureConfig);
|
||||
const LazyAIChatPanel = useMemo(() => createLazyAIChatPanel(), [aiPanelRenderNonce]);
|
||||
const securityUpdateStatusMeta = useMemo(
|
||||
() => getSecurityUpdateStatusMeta(securityUpdateStatus),
|
||||
[securityUpdateStatus],
|
||||
@@ -2352,12 +2350,26 @@ function App() {
|
||||
setIsModalOpen(true);
|
||||
}, []);
|
||||
|
||||
const handleEditConnection = (conn: SavedConnection) => {
|
||||
const handleEditConnection = useCallback((conn: SavedConnection) => {
|
||||
setSecurityUpdateRepairSource(null);
|
||||
setEditingConnection(conn);
|
||||
setIsConnectionModalMounted(true);
|
||||
setIsModalOpen(true);
|
||||
};
|
||||
void (async () => {
|
||||
const backendApp = (window as any).go?.app?.App;
|
||||
let nextConnection = conn;
|
||||
if (typeof backendApp?.GetEditableSavedConnection === 'function') {
|
||||
try {
|
||||
const editableConnection = await backendApp.GetEditableSavedConnection(conn.id);
|
||||
if (editableConnection) {
|
||||
nextConnection = editableConnection;
|
||||
}
|
||||
} catch (error: any) {
|
||||
message.warning(error?.message || '读取已保存连接详情失败,当前将打开脱敏配置');
|
||||
}
|
||||
}
|
||||
setEditingConnection(nextConnection);
|
||||
setIsModalOpen(true);
|
||||
})();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (connectionModalWarmupDoneRef.current) {
|
||||
@@ -2489,6 +2501,15 @@ function App() {
|
||||
}, []);
|
||||
|
||||
const handleAIPanelRenderError = useCallback((error: Error, errorInfo: React.ErrorInfo) => {
|
||||
try {
|
||||
(window as any).__gonaviLastAIPanelRenderError = {
|
||||
message: error?.message || '',
|
||||
stack: error?.stack || '',
|
||||
componentStack: errorInfo?.componentStack || '',
|
||||
};
|
||||
} catch {
|
||||
// ignore debug capture failures
|
||||
}
|
||||
console.error('AIChatPanel render error:', error, errorInfo);
|
||||
}, []);
|
||||
|
||||
@@ -3394,6 +3415,7 @@ function App() {
|
||||
</>
|
||||
)}
|
||||
<AIPanelErrorBoundary
|
||||
key={aiPanelRenderNonce}
|
||||
onError={handleAIPanelRenderError}
|
||||
fallback={(error) => (
|
||||
<div
|
||||
@@ -3449,11 +3471,9 @@ function App() {
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
<React.Suspense fallback={<div style={{ width: aiPanelRenderWidth, display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Spin size="small" /></div>}>
|
||||
<LazyAIChatPanel width={aiPanelRenderWidth} darkMode={darkMode} bgColor={bgContent} onClose={() => setAIPanelVisible(false)} onOpenSettings={() => {
|
||||
handleOpenAISettings();
|
||||
}} overlayTheme={overlayTheme} />
|
||||
</React.Suspense>
|
||||
<AIChatPanel width={aiPanelRenderWidth} darkMode={darkMode} bgColor={bgContent} onClose={() => setAIPanelVisible(false)} onOpenSettings={() => {
|
||||
handleOpenAISettings();
|
||||
}} overlayTheme={overlayTheme} />
|
||||
</AIPanelErrorBoundary>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user