diff --git a/src/app/settings/page.tsx b/src/app/settings/page.tsx index a9d5a1d..2d5b200 100644 --- a/src/app/settings/page.tsx +++ b/src/app/settings/page.tsx @@ -2,10 +2,11 @@ import { useState, useEffect } from 'react'; import Link from 'next/link'; -import { ArrowLeft, Download, Check, Loader2, Eye, EyeOff, RotateCcw, Moon, Sun, Sparkles, Trash2 } from 'lucide-react'; +import { ArrowLeft, Download, Check, Loader2, Eye, EyeOff, RotateCcw, Moon, Sun, Sparkles, Trash2, AlertTriangle } from 'lucide-react'; import { Toggle } from '@/components/ui/Toggle'; import { ModelCardSelector } from '@/components/ui/ModelCardSelector'; import { FontSizePicker } from '@/components/ui/FontSizePicker'; +import { ConfirmDialog } from '@/components/ui/ConfirmDialog'; import { cn } from '@/lib/utils'; import { useSettings, useModels, useTools } from '@/hooks/useSettings'; @@ -59,6 +60,12 @@ export default function SettingsPage() { const [temperature, setTemperature] = useState('0.7'); const [promptSaveStatus, setPromptSaveStatus] = useState<'idle' | 'saving' | 'saved' | 'error'>('idle'); + // 导出和清除状态 + const [exportLoading, setExportLoading] = useState(false); + const [clearDialogOpen, setClearDialogOpen] = useState(false); + const [clearLoading, setClearLoading] = useState(false); + const [chatStats, setChatStats] = useState<{ conversationCount: number; messageCount: number } | null>(null); + // 当设置加载完成后,更新本地状态 useEffect(() => { if (settings) { @@ -198,6 +205,70 @@ export default function SettingsPage() { } }; + // 导出聊天数据 + const handleExportData = async () => { + setExportLoading(true); + try { + const response = await fetch('/api/conversations/export'); + if (!response.ok) { + throw new Error('Export failed'); + } + const data = await response.json(); + + // 创建 Blob 并下载 + const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + const date = new Date().toISOString().split('T')[0]; + a.download = `cchcode-chat-export-${date}.json`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + } catch (error) { + console.error('Failed to export data:', error); + alert('导出失败,请稍后重试'); + } finally { + setExportLoading(false); + } + }; + + // 打开清除对话框(获取统计信息) + const handleOpenClearDialog = async () => { + try { + const response = await fetch('/api/conversations/all'); + if (response.ok) { + const stats = await response.json(); + setChatStats(stats); + } + } catch (error) { + console.error('Failed to get stats:', error); + } + setClearDialogOpen(true); + }; + + // 清除所有聊天 + const handleClearAllChats = async () => { + setClearLoading(true); + try { + const response = await fetch('/api/conversations/all', { + method: 'DELETE', + }); + if (!response.ok) { + throw new Error('Delete failed'); + } + setClearDialogOpen(false); + // 跳转到首页 + window.location.href = '/'; + } catch (error) { + console.error('Failed to clear chats:', error); + alert('清除失败,请稍后重试'); + } finally { + setClearLoading(false); + } + }; + if (loading) { return (
@@ -510,9 +581,17 @@ export default function SettingsPage() { label="导出数据" description="下载所有聊天历史" > - @@ -520,12 +599,49 @@ export default function SettingsPage() { label="清除所有聊天" description="删除所有对话历史" > - + + {/* 清除确认对话框 */} + setClearDialogOpen(false)} + onConfirm={handleClearAllChats} + title="确认清除所有聊天记录?" + variant="danger" + confirmText="确认清除" + cancelText="取消" + loading={clearLoading} + > +
+

+ 此操作将永久删除: +

+
    +
  • + + {chatStats?.conversationCount || 0} 个对话 +
  • +
  • + + {chatStats?.messageCount || 0} 条消息 +
  • +
+
+ +

+ 此操作不可撤销!建议先导出数据备份。 +

+
+
+
); @@ -543,22 +659,22 @@ function SettingsSection({ title, description, children, variant = 'default' }: return (

{title}