Files
openclaw-memory/frontend/src/components/FileDiff.js

152 lines
3.7 KiB
JavaScript
Raw Normal View History

import React, { useState, useEffect } from 'react';
import { Spin, Alert, Tabs } from 'antd';
import ReactDiffViewer from 'react-diff-viewer-continued';
import api from '../api';
export default function FileDiff({ filePath, lobsterId }) {
const [loading, setLoading] = useState(false);
const [diffData, setDiffData] = useState(null);
const [error, setError] = useState(null);
const loadDiff = async () => {
setLoading(true);
setError(null);
try {
const response = await api.get('/diff/', {
params: { file_path: filePath, lobster_id: lobsterId }
});
if (response.success) {
setDiffData(response.data);
} else {
setError(response.error || '加载失败');
}
} catch (err) {
setError(err.message || '网络错误');
} finally {
setLoading(false);
}
};
useEffect(() => {
if (filePath) {
loadDiff();
}
}, [filePath]);
if (loading) {
return <Spin tip="加载中..." />;
}
if (error) {
return <Alert message={error} type="error" />;
}
if (!diffData) {
return <Alert message="请选择文件" type="info" />;
}
const { local_content, db_content, status, diff } = diffData;
// 文件不存在的情况
if (!local_content && !db_content) {
return <Alert message="文件不存在" type="warning" />;
}
if (!local_content) {
return (
<Alert
message="文件仅存在于数据库"
description="点击「同步到本地」将文件恢复到本地"
type="info"
showIcon
/>
);
}
if (!db_content) {
return (
<Alert
message="文件仅存在于本地"
description="点击「同步到数据库」将文件备份到数据库"
type="warning"
showIcon
/>
);
}
const STATUS_MESSAGES = {
consistent: '文件内容一致',
local_newer: '本地文件有更新',
db_newer: '数据库版本更新',
conflict: '文件内容冲突',
};
return (
<div>
<Alert
message={STATUS_MESSAGES[status] || '未知状态'}
type={status === 'consistent' ? 'success' : 'warning'}
style={{ marginBottom: 16 }}
showIcon
/>
<Tabs
defaultActiveKey="diff"
items={[
{
key: 'diff',
label: '差异对比',
children: (
<div style={{ overflowX: 'auto' }}>
<ReactDiffViewer
oldValue={db_content || ''}
newValue={local_content || ''}
splitView={true}
useDarkTheme={false}
leftTitle="数据库版本"
rightTitle="本地版本"
/>
</div>
),
},
{
key: 'local',
label: '本地内容',
children: (
<pre style={{
padding: '16px',
background: '#f5f5f5',
borderRadius: '4px',
maxHeight: '500px',
overflow: 'auto',
whiteSpace: 'pre-wrap',
wordBreak: 'break-word'
}}>
{local_content}
</pre>
),
},
{
key: 'db',
label: '数据库内容',
children: (
<pre style={{
padding: '16px',
background: '#f5f5f5',
borderRadius: '4px',
maxHeight: '500px',
overflow: 'auto',
whiteSpace: 'pre-wrap',
wordBreak: 'break-word'
}}>
{db_content}
</pre>
),
},
]}
/>
</div>
);
}