Files
CyyNote/cyynote-frontend/src/components/modals/NoteHistoryModal.tsx
T
2026-05-15 19:01:10 +08:00

106 lines
3.2 KiB
TypeScript

import { useState, useEffect, useCallback } from 'react';
import { Modal, List, Button, Toast, Typography, Spin, Popconfirm } from '@douyinfe/semi-ui';
import { IconHistory, IconRotate } from '@douyinfe/semi-icons';
import { useNoteStore } from '../../stores/useNoteStore';
import noteService from '../../services/note.service';
import type { IHistory } from '../../types';
const { Text } = Typography;
interface Props {
visible: boolean;
onClose: () => void;
}
export default function NoteHistoryModal({ visible, onClose }: Props) {
const { currentNoteId, setCurrentNote } = useNoteStore();
const [list, setList] = useState<IHistory[]>([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
if (!visible || !currentNoteId) return;
setLoading(true);
noteService
.getHistory(currentNoteId)
.then((res) => setList(res.data ?? []))
.catch(() => Toast.error('加载历史版本失败'))
.finally(() => setLoading(false));
}, [visible, currentNoteId]);
const handleRestore = useCallback(
async (item: IHistory) => {
try {
const res = await noteService.getHistoryContent(item.id);
const h = res.data;
// Restore: update note with history content
await noteService.update(h.nid, h.title, h.context);
// Reload the current note into the editor
const noteRes = await noteService.get(h.nid);
const note = noteRes.data;
setCurrentNote(note.id, note.title, note.context);
Toast.success(`已恢复到 ${h.createtime} 的版本`);
onClose();
} catch {
Toast.error('恢复失败');
}
},
[setCurrentNote, onClose],
);
return (
<Modal
title={
<span>
<IconHistory style={{ marginRight: 8 }} />
</span>
}
visible={visible}
onCancel={onClose}
footer={null}
width={520}
>
{loading ? (
<div style={{ textAlign: 'center', padding: 32 }}>
<Spin size="large" />
</div>
) : list.length === 0 ? (
<div style={{ textAlign: 'center', padding: 32, color: 'var(--semi-color-text-2)' }}>
</div>
) : (
<List
dataSource={list}
renderItem={(item: IHistory) => (
<List.Item
main={
<div>
<Text strong style={{ display: 'block' }}>{item.title}</Text>
<Text type="tertiary" size="small">{item.createtime}</Text>
</div>
}
extra={
<Popconfirm
title="确认恢复"
content="恢复后当前内容将被该版本覆盖,确定吗?"
onConfirm={() => void handleRestore(item)}
okText="确定"
cancelText="取消"
>
<Button
size="small"
type="secondary"
icon={<IconRotate />}
>
</Button>
</Popconfirm>
}
/>
)}
/>
)}
</Modal>
);
}