首页 (page.tsx): - 集成 useConversations 和 useSettings hooks - 实现快捷操作创建新会话 - 添加加载状态处理 聊天页 (chat/[id]/page.tsx): - 集成 useStreamChat 实现流式对话 - 支持 AI 思考内容展示 - 优化消息发送和模型切换 - 添加错误处理和重试机制 设置页 (settings/page.tsx): - 重构为完整的设置管理界面 - 支持 API 配置(URL、密钥) - 支持默认模型和工具选择 - 支持主题和语言设置 - 添加设置保存和同步功能
140 lines
4.2 KiB
TypeScript
140 lines
4.2 KiB
TypeScript
'use client';
|
|
|
|
import { useState, useEffect } from 'react';
|
|
import { useRouter } from 'next/navigation';
|
|
import { AppLayout } from '@/components/layout/AppLayout';
|
|
import { Welcome } from '@/components/features/Welcome';
|
|
import { ChatInput } from '@/components/features/ChatInput';
|
|
import { QuickActions } from '@/components/features/QuickActions';
|
|
import { currentUser, getGreeting } from '@/data/mock';
|
|
import { useConversations } from '@/hooks/useConversations';
|
|
import { useModels, useTools, useSettings } from '@/hooks/useSettings';
|
|
import type { QuickAction } from '@/types';
|
|
|
|
export default function HomePage() {
|
|
const router = useRouter();
|
|
const { createConversation } = useConversations();
|
|
const { models, loading: modelsLoading } = useModels();
|
|
const { tools: availableTools, loading: toolsLoading } = useTools();
|
|
const { settings } = useSettings();
|
|
|
|
const [selectedModelId, setSelectedModelId] = useState<string>('');
|
|
const [enabledTools, setEnabledTools] = useState<string[]>([]);
|
|
const [isSending, setIsSending] = useState(false);
|
|
|
|
const greeting = getGreeting(currentUser.name);
|
|
|
|
// 初始化默认设置
|
|
useEffect(() => {
|
|
if (settings) {
|
|
setSelectedModelId(settings.defaultModel);
|
|
setEnabledTools(settings.defaultTools || []);
|
|
}
|
|
}, [settings]);
|
|
|
|
// 转换模型格式
|
|
const modelOptions = models.map((m) => ({
|
|
id: m.modelId,
|
|
name: m.displayName,
|
|
tag: m.supportsThinking ? 'Thinking' : '',
|
|
}));
|
|
|
|
const selectedModel = modelOptions.find((m) => m.id === selectedModelId) || modelOptions[0];
|
|
|
|
// 转换工具格式
|
|
const toolOptions = availableTools.map((t) => ({
|
|
id: t.toolId,
|
|
name: t.displayName,
|
|
icon: t.icon || 'Tool',
|
|
enabled: enabledTools.includes(t.toolId),
|
|
}));
|
|
|
|
const handleToolToggle = (toolId: string) => {
|
|
setEnabledTools((prev) =>
|
|
prev.includes(toolId)
|
|
? prev.filter((t) => t !== toolId)
|
|
: [...prev, toolId]
|
|
);
|
|
};
|
|
|
|
const handleEnableAllTools = (enabled: boolean) => {
|
|
if (enabled) {
|
|
setEnabledTools(availableTools.map((t) => t.toolId));
|
|
} else {
|
|
setEnabledTools([]);
|
|
}
|
|
};
|
|
|
|
const handleSend = async (message: string) => {
|
|
if (isSending) return;
|
|
|
|
setIsSending(true);
|
|
try {
|
|
// 创建新对话
|
|
const newConversation = await createConversation({
|
|
title: message.slice(0, 50),
|
|
model: selectedModelId || 'default',
|
|
tools: enabledTools,
|
|
enableThinking: settings?.enableThinking || false,
|
|
});
|
|
|
|
// 跳转到新对话页面并携带初始消息
|
|
router.push(`/chat/${newConversation.conversationId}?message=${encodeURIComponent(message)}`);
|
|
} catch (error) {
|
|
console.error('Failed to create conversation:', error);
|
|
} finally {
|
|
setIsSending(false);
|
|
}
|
|
};
|
|
|
|
const handleQuickAction = (action: QuickAction) => {
|
|
if (action.prompt) {
|
|
handleSend(action.prompt);
|
|
}
|
|
};
|
|
|
|
// 快捷操作
|
|
const quickActions: QuickAction[] = [
|
|
{ id: '1', label: '写代码', prompt: '帮我写一段代码', icon: 'Code' },
|
|
{ id: '2', label: '解释概念', prompt: '解释一下什么是', icon: 'BookOpen' },
|
|
{ id: '3', label: '调试代码', prompt: '帮我调试这段代码', icon: 'Bug' },
|
|
{ id: '4', label: '代码审查', prompt: '请审查这段代码', icon: 'Search' },
|
|
];
|
|
|
|
if (modelsLoading || toolsLoading) {
|
|
return (
|
|
<AppLayout>
|
|
<div className="flex items-center justify-center min-h-[400px]">
|
|
<div className="text-[var(--color-text-tertiary)]">加载中...</div>
|
|
</div>
|
|
</AppLayout>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<AppLayout>
|
|
<div className="w-full max-w-[900px] mx-auto">
|
|
{/* 欢迎区域 */}
|
|
<Welcome greeting={greeting} className="mb-8" />
|
|
|
|
{/* 聊天输入框 */}
|
|
<ChatInput
|
|
models={modelOptions}
|
|
selectedModel={selectedModel}
|
|
onModelSelect={(model) => setSelectedModelId(model.id)}
|
|
tools={toolOptions}
|
|
onToolToggle={handleToolToggle}
|
|
onEnableAllTools={handleEnableAllTools}
|
|
onSend={handleSend}
|
|
/>
|
|
|
|
{/* 快捷操作 */}
|
|
<QuickActions
|
|
actions={quickActions}
|
|
onSelect={handleQuickAction}
|
|
/>
|
|
</div>
|
|
</AppLayout>
|
|
);
|
|
}
|