// File: frontend/app/chat/page.tsx (更新以使用 API) // Description: 对接后端 API 实现助手和会话的加载与管理 'use client'; import React, { useState, useRef, useEffect, useCallback } from 'react'; import { SendHorizontal, Loader2, PanelRightOpen, PanelRightClose, UserPlus, Settings2, Trash2, Edit, RefreshCw } from 'lucide-react'; // 添加刷新图标 import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import * as z from "zod"; // Shadcn UI Components import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, DialogFooter, DialogClose } from "@/components/ui/dialog"; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Slider } from "@/components/ui/slider"; import { Toaster, toast } from "sonner"; import { Skeleton } from "@/components/ui/skeleton"; // 导入骨架屏 // API 函数和类型 import { sendChatMessage, getAssistants, createAssistant, updateAssistant, deleteAssistant, getSessionsByAssistant, deleteSession, Assistant, Session, AssistantCreateData, AssistantUpdateData, ChatApiResponse } from '@/lib/api'; // 确保路径正确 // --- 数据接口定义 --- interface Message { id: string; text: string; sender: 'user' | 'ai'; isError?: boolean; } interface ChatSession { id: string; title: string; createdAt: Date; assistantId: string; isTemporary?: boolean; } // --- Zod Schema for Assistant Form Validation --- const assistantFormSchema = z.object({ name: z.string().min(1, { message: "助手名称不能为空" }).max(50, { message: "名称过长" }), description: z.string().max(200, { message: "描述过长" }).optional(), avatar: z.string().max(5, { message: "头像/Emoji 过长" }).optional(), // 简单限制长度 system_prompt: z.string().min(1, { message: "系统提示不能为空" }).max(4000, { message: "系统提示过长" }), model: z.string({ required_error: "请选择一个模型" }), temperature: z.number().min(0).max(1), }); type AssistantFormData = z.infer; // 可选的模型列表 const availableModels = [ { value: "gpt-3.5-turbo", label: "GPT-3.5 Turbo" }, { value: "gpt-4", label: "GPT-4" }, { value: "gpt-4-turbo", label: "GPT-4 Turbo" }, { value: "gemini-2.0-flash", label: "Gemini 2.0 Flash" }, { value: "deepseek-coder", label: "DeepSeek Coder" }, // 示例 // 添加更多模型... ]; // --- Helper Function --- const findLastSession = (sessions: ChatSession[], assistantId: string): ChatSession | undefined => { return sessions .filter(s => s.assistantId === assistantId && !s.isTemporary) .sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())[0]; }; // --- Assistant Form Component --- interface AssistantFormProps { assistant?: Assistant | null; // 传入表示编辑,否则是创建 onSave: (data: AssistantFormData, id?: string) => void; // 保存回调 onClose: () => void; // 关闭 Dialog 的回调 } function AssistantForm({ assistant, onSave, onClose }: AssistantFormProps) { const form = useForm({ resolver: zodResolver(assistantFormSchema), defaultValues: { name: assistant?.name || "", description: assistant?.description || "", avatar: assistant?.avatar || "", system_prompt: assistant?.system_prompt || "", model: assistant?.model || availableModels[0].value, // 默认第一个模型 temperature: assistant?.temperature ?? 0.7, // 默认 0.7 }, }); const [isSaving, setIsSaving] = useState(false); // 添加保存状态 async function onSubmit(data: AssistantFormData) { setIsSaving(true); try { await onSave(data, assistant?.id); // 调用异步保存函数 onClose(); // 成功后关闭 } catch (error) { // 错误已在 onSave 中处理并 toast } finally { setIsSaving(false); } } return (
{/* Name */} ( 助手名称 )} /> {/* Description */} ( 描述 (可选) )} /> {/* Avatar */} ( 头像 (可选) 建议使用单个 Emoji。 )} /> {/* System Prompt */} ( 系统提示 (System Prompt)