From 0b5b67174f669fd1a70ad9ea242edfc3312344e5 Mon Sep 17 00:00:00 2001 From: gaoziman <2942894660@qq.com> Date: Fri, 19 Dec 2025 15:57:50 +0800 Subject: [PATCH] =?UTF-8?q?feat(settings):=20=E5=AE=9E=E7=8E=B0=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=AF=BC=E5=87=BA=E5=92=8C=E6=B8=85=E9=99=A4=E8=81=8A?= =?UTF-8?q?=E5=A4=A9=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加导出聊天数据功能,支持 JSON 格式下载 - 添加清除所有聊天功能,带确认对话框 - 显示待删除对话和消息数量统计 - 优化 SettingsSection 组件支持暗色主题 --- src/app/settings/page.tsx | 134 +++++++++++++++++++++++++++++++++++--- 1 file changed, 125 insertions(+), 9 deletions(-) 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 (