refactor(settings): 重构设置页面布局和交互
- 优化页面布局,移除侧边栏采用独立页面设计 - 集成 ModelCardSelector 替代下拉选择 - 集成 FontSizePicker 支持字体大小调整 - 顶部导航栏添加主题切换按钮 - 移除冗余的偏好设置和危险区域板块 - 优化整体视觉效果和交互体验
This commit is contained in:
parent
6d1bf7275b
commit
f81a1f0f2d
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { ArrowLeft, Download, Check, Loader2, Eye, EyeOff, RotateCcw } from 'lucide-react';
|
import { ArrowLeft, Download, Check, Loader2, Eye, EyeOff, RotateCcw, Moon, Sun, Sparkles, Trash2 } from 'lucide-react';
|
||||||
import { Sidebar, SidebarToggle } from '@/components/layout/Sidebar';
|
|
||||||
import { Toggle } from '@/components/ui/Toggle';
|
import { Toggle } from '@/components/ui/Toggle';
|
||||||
|
import { ModelCardSelector } from '@/components/ui/ModelCardSelector';
|
||||||
|
import { FontSizePicker } from '@/components/ui/FontSizePicker';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import { currentUser, chatHistories } from '@/data/mock';
|
|
||||||
import { useSettings, useModels, useTools } from '@/hooks/useSettings';
|
import { useSettings, useModels, useTools } from '@/hooks/useSettings';
|
||||||
|
|
||||||
// 默认系统提示词
|
// 默认系统提示词
|
||||||
@ -44,7 +44,6 @@ const DEFAULT_SYSTEM_PROMPT = `你是一个专业、友好的 AI 助手。请遵
|
|||||||
- 承认不确定的地方,不要编造信息`;
|
- 承认不确定的地方,不要编造信息`;
|
||||||
|
|
||||||
export default function SettingsPage() {
|
export default function SettingsPage() {
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(true);
|
|
||||||
const { settings, loading, saving, updateSettings } = useSettings();
|
const { settings, loading, saving, updateSettings } = useSettings();
|
||||||
const { models, loading: modelsLoading } = useModels();
|
const { models, loading: modelsLoading } = useModels();
|
||||||
const { tools, loading: toolsLoading } = useTools();
|
const { tools, loading: toolsLoading } = useTools();
|
||||||
@ -105,6 +104,17 @@ export default function SettingsPage() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 更新字体大小
|
||||||
|
const handleFontSizeChange = async (fontSize: number) => {
|
||||||
|
try {
|
||||||
|
await updateSettings({ fontSize });
|
||||||
|
// 实时应用到页面
|
||||||
|
document.documentElement.style.setProperty('--font-size-base', `${fontSize}px`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to update font size:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 切换工具
|
// 切换工具
|
||||||
const handleToolToggle = async (toolId: string) => {
|
const handleToolToggle = async (toolId: string) => {
|
||||||
const currentTools = settings?.defaultTools || [];
|
const currentTools = settings?.defaultTools || [];
|
||||||
@ -177,6 +187,17 @@ export default function SettingsPage() {
|
|||||||
setTemperature(value);
|
setTemperature(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 切换主题
|
||||||
|
const handleToggleTheme = async () => {
|
||||||
|
const newTheme = settings?.theme === 'dark' ? 'light' : 'dark';
|
||||||
|
try {
|
||||||
|
await updateSettings({ theme: newTheme });
|
||||||
|
document.documentElement.setAttribute('data-theme', newTheme);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to update theme:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
<div className="flex min-h-screen items-center justify-center">
|
<div className="flex min-h-screen items-center justify-center">
|
||||||
@ -185,50 +206,41 @@ export default function SettingsPage() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isDarkMode = settings?.theme === 'dark';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex min-h-screen">
|
<div className="min-h-screen bg-[var(--color-bg-secondary)]">
|
||||||
{/* 侧边栏 */}
|
{/* 顶部导航栏 */}
|
||||||
<Sidebar
|
<header className="sticky top-0 z-10 bg-[var(--color-bg-primary)] border-b border-[var(--color-border-light)]">
|
||||||
user={currentUser}
|
<div className="max-w-[900px] mx-auto px-6 h-16 flex items-center justify-between">
|
||||||
chatHistories={chatHistories}
|
{/* 左侧:返回按钮和标题 */}
|
||||||
isOpen={sidebarOpen}
|
<div className="flex items-center gap-4">
|
||||||
onToggle={() => setSidebarOpen(!sidebarOpen)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* 主内容区 */}
|
|
||||||
<main
|
|
||||||
className={cn(
|
|
||||||
'flex-1 min-h-screen transition-all duration-300',
|
|
||||||
sidebarOpen ? 'ml-[var(--sidebar-width)]' : 'ml-0'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{/* Header */}
|
|
||||||
<header className="h-[var(--header-height)] px-4 flex items-center">
|
|
||||||
<SidebarToggle onClick={() => setSidebarOpen(!sidebarOpen)} />
|
|
||||||
</header>
|
|
||||||
|
|
||||||
{/* Body */}
|
|
||||||
<div className="px-8 pb-8">
|
|
||||||
<div className="max-w-[800px] mx-auto">
|
|
||||||
{/* 返回链接 */}
|
|
||||||
<Link
|
<Link
|
||||||
href="/"
|
href="/"
|
||||||
className="inline-flex items-center gap-2 text-[var(--color-text-secondary)] text-sm mb-4 hover:text-[var(--color-text-primary)] transition-colors"
|
className="p-2 -ml-2 rounded-lg text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] hover:bg-[var(--color-bg-hover)] transition-colors"
|
||||||
|
title="返回聊天"
|
||||||
>
|
>
|
||||||
<ArrowLeft size={16} />
|
<ArrowLeft size={20} />
|
||||||
<span>返回聊天</span>
|
|
||||||
</Link>
|
</Link>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
{/* 页面标题 */}
|
<Sparkles size={24} className="text-[var(--color-primary)]" />
|
||||||
<div className="mb-8">
|
<h1 className="text-xl font-semibold text-[var(--color-text-primary)]">Settings</h1>
|
||||||
<h1 className="text-2xl font-semibold text-[var(--color-text-primary)] mb-2">
|
</div>
|
||||||
设置
|
|
||||||
</h1>
|
|
||||||
<p className="text-sm text-[var(--color-text-secondary)]">
|
|
||||||
管理您的账户设置和偏好
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* 右侧:主题切换 */}
|
||||||
|
<button
|
||||||
|
onClick={handleToggleTheme}
|
||||||
|
className="p-2 rounded-lg text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] hover:bg-[var(--color-bg-hover)] transition-colors"
|
||||||
|
title={isDarkMode ? '切换到浅色模式' : '切换到深色模式'}
|
||||||
|
>
|
||||||
|
{isDarkMode ? <Sun size={20} /> : <Moon size={20} />}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
{/* 主内容区 */}
|
||||||
|
<main className="max-w-[900px] mx-auto px-6 py-8">
|
||||||
{/* CCH 配置 */}
|
{/* CCH 配置 */}
|
||||||
<SettingsSection
|
<SettingsSection
|
||||||
title="CCH 服务配置"
|
title="CCH 服务配置"
|
||||||
@ -315,23 +327,36 @@ export default function SettingsPage() {
|
|||||||
title="AI 配置"
|
title="AI 配置"
|
||||||
description="配置默认模型和工具"
|
description="配置默认模型和工具"
|
||||||
>
|
>
|
||||||
<SettingsItem
|
{/* 模型卡片选择 */}
|
||||||
label="默认模型"
|
<div className="px-5 py-4 border-b border-[var(--color-border-light)]">
|
||||||
description="为新对话选择默认 AI 模型"
|
<div className="text-sm font-medium text-[var(--color-text-primary)] mb-2">
|
||||||
>
|
默认模型
|
||||||
<select
|
</div>
|
||||||
className="settings-select"
|
<div className="text-xs text-[var(--color-text-tertiary)] mb-4">
|
||||||
|
为新对话选择默认 AI 模型
|
||||||
|
</div>
|
||||||
|
<ModelCardSelector
|
||||||
value={settings?.defaultModel || ''}
|
value={settings?.defaultModel || ''}
|
||||||
onChange={(e) => handleModelChange(e.target.value)}
|
onChange={handleModelChange}
|
||||||
disabled={modelsLoading || saving}
|
disabled={modelsLoading || saving}
|
||||||
>
|
models={models}
|
||||||
{models.map((model) => (
|
/>
|
||||||
<option key={model.modelId} value={model.modelId}>
|
</div>
|
||||||
{model.displayName}
|
|
||||||
</option>
|
{/* 字体大小设置 */}
|
||||||
))}
|
<div className="px-5 py-4 border-b border-[var(--color-border-light)]">
|
||||||
</select>
|
<div className="text-sm font-medium text-[var(--color-text-primary)] mb-2">
|
||||||
</SettingsItem>
|
字体大小
|
||||||
|
</div>
|
||||||
|
<div className="text-xs text-[var(--color-text-tertiary)] mb-4">
|
||||||
|
调整全局字体大小,实时预览效果
|
||||||
|
</div>
|
||||||
|
<FontSizePicker
|
||||||
|
value={settings?.fontSize || 15}
|
||||||
|
onChange={handleFontSizeChange}
|
||||||
|
disabled={saving}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<SettingsItem
|
<SettingsItem
|
||||||
label="启用思考模式"
|
label="启用思考模式"
|
||||||
@ -361,7 +386,7 @@ export default function SettingsPage() {
|
|||||||
onClick={() => handleToolToggle(tool.toolId)}
|
onClick={() => handleToolToggle(tool.toolId)}
|
||||||
disabled={saving}
|
disabled={saving}
|
||||||
className={cn(
|
className={cn(
|
||||||
'inline-flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-medium transition-all',
|
'inline-flex items-center gap-2 px-3 py-2 rounded-md text-sm font-medium transition-all',
|
||||||
settings?.defaultTools?.includes(tool.toolId)
|
settings?.defaultTools?.includes(tool.toolId)
|
||||||
? 'bg-[var(--color-primary)] text-white'
|
? 'bg-[var(--color-primary)] text-white'
|
||||||
: 'bg-[var(--color-bg-tertiary)] text-[var(--color-text-secondary)] hover:bg-[var(--color-bg-secondary)]'
|
: 'bg-[var(--color-bg-tertiary)] text-[var(--color-text-secondary)] hover:bg-[var(--color-bg-secondary)]'
|
||||||
@ -465,45 +490,6 @@ export default function SettingsPage() {
|
|||||||
</div>
|
</div>
|
||||||
</SettingsSection>
|
</SettingsSection>
|
||||||
|
|
||||||
{/* 偏好设置 */}
|
|
||||||
<SettingsSection
|
|
||||||
title="偏好设置"
|
|
||||||
description="自定义您的体验"
|
|
||||||
>
|
|
||||||
<SettingsItem
|
|
||||||
label="主题"
|
|
||||||
description="选择您喜欢的主题"
|
|
||||||
>
|
|
||||||
<select
|
|
||||||
className="settings-select"
|
|
||||||
value={settings?.theme || 'light'}
|
|
||||||
onChange={(e) => handleThemeChange(e.target.value)}
|
|
||||||
disabled={saving}
|
|
||||||
>
|
|
||||||
<option value="system">跟随系统</option>
|
|
||||||
<option value="light">浅色</option>
|
|
||||||
<option value="dark">深色</option>
|
|
||||||
</select>
|
|
||||||
</SettingsItem>
|
|
||||||
|
|
||||||
<SettingsItem
|
|
||||||
label="语言"
|
|
||||||
description="选择您的首选语言"
|
|
||||||
>
|
|
||||||
<select
|
|
||||||
className="settings-select"
|
|
||||||
value={settings?.language || 'zh-CN'}
|
|
||||||
onChange={(e) => handleLanguageChange(e.target.value)}
|
|
||||||
disabled={saving}
|
|
||||||
>
|
|
||||||
<option value="en">English</option>
|
|
||||||
<option value="zh-CN">简体中文</option>
|
|
||||||
<option value="zh-TW">繁體中文</option>
|
|
||||||
<option value="ja">日本語</option>
|
|
||||||
</select>
|
|
||||||
</SettingsItem>
|
|
||||||
</SettingsSection>
|
|
||||||
|
|
||||||
{/* 数据与隐私 */}
|
{/* 数据与隐私 */}
|
||||||
<SettingsSection
|
<SettingsSection
|
||||||
title="数据与隐私"
|
title="数据与隐私"
|
||||||
@ -534,27 +520,12 @@ export default function SettingsPage() {
|
|||||||
label="清除所有聊天"
|
label="清除所有聊天"
|
||||||
description="删除所有对话历史"
|
description="删除所有对话历史"
|
||||||
>
|
>
|
||||||
<button className="btn-ghost text-red-600 hover:text-red-700">
|
<button className="btn-ghost text-red-600 hover:text-red-700 inline-flex items-center gap-2">
|
||||||
|
<Trash2 size={16} />
|
||||||
清除
|
清除
|
||||||
</button>
|
</button>
|
||||||
</SettingsItem>
|
</SettingsItem>
|
||||||
</SettingsSection>
|
</SettingsSection>
|
||||||
|
|
||||||
{/* 危险区域 */}
|
|
||||||
<SettingsSection
|
|
||||||
title="危险区域"
|
|
||||||
description="不可逆操作"
|
|
||||||
variant="danger"
|
|
||||||
>
|
|
||||||
<SettingsItem
|
|
||||||
label="删除账户"
|
|
||||||
description="永久删除您的账户和所有数据"
|
|
||||||
>
|
|
||||||
<button className="btn-danger">删除账户</button>
|
|
||||||
</SettingsItem>
|
|
||||||
</SettingsSection>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -572,7 +543,7 @@ function SettingsSection({ title, description, children, variant = 'default' }:
|
|||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
className={cn(
|
className={cn(
|
||||||
'bg-white border rounded-xl mb-6 overflow-hidden',
|
'bg-white border rounded-md mb-6 overflow-hidden',
|
||||||
variant === 'danger' ? 'border-red-200' : 'border-[var(--color-border)]'
|
variant === 'danger' ? 'border-red-200' : 'border-[var(--color-border)]'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user