"use client"; import { useCallback, useEffect, useState } from "react"; import { useRouter } from "next/navigation"; import { useAuth } from "@/features/agent/hooks/useAuth"; import { ResponsiveLayout } from "@/components/layout"; import { fetchFAQs, createFAQ, updateFAQ, deleteFAQ, type FAQSummary, type CreateFAQRequest, type UpdateFAQRequest, } from "@/features/agent/services/faqApi"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, } from "@/components/ui/dialog"; import { Card } from "@/components/ui/card"; import { Label } from "@/components/ui/label"; import { Plus, Edit, Trash2, Search, FileText, Save, X, } from "lucide-react"; import { toast } from "@/hooks/useToast"; import { Textarea } from "@/components/ui/textarea"; import type { I18nKey } from "@/lib/i18n/dict"; import { useI18n } from "@/lib/i18n/provider"; export default function FAQsPage(props: any = {}) { const { embedded = false } = props; const router = useRouter(); const { agent } = useAuth(); const { t, lang } = useI18n(); const tr = (key: I18nKey, vars?: Record) => { let s = t(key); if (!vars) return s; for (const k of Object.keys(vars)) { s = s.replaceAll(`{{${k}}}`, vars[k] ?? ""); } return s; }; const [faqs, setFaqs] = useState([]); const [loading, setLoading] = useState(true); const [searchQuery, setSearchQuery] = useState(""); const [createDialogOpen, setCreateDialogOpen] = useState(false); const [editDialogOpen, setEditDialogOpen] = useState(false); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [selectedFAQ, setSelectedFAQ] = useState(null); const [submitting, setSubmitting] = useState(false); // 创建 FAQ 表单 const [createForm, setCreateForm] = useState({ question: "", answer: "", keywords: "", }); // 编辑 FAQ 表单 const [editForm, setEditForm] = useState({ question: "", answer: "", keywords: "", }); // 加载 FAQ 列表 const loadFAQs = useCallback(async () => { setLoading(true); try { // 如果搜索框有内容,使用关键词搜索;否则加载全部 const query = searchQuery.trim() || undefined; const data = await fetchFAQs(query); setFaqs(data); } catch (error) { console.error("加载 FAQ 列表失败:", error); toast.error((error as Error).message || t("agent.faqs.toast.loadFailed")); } finally { setLoading(false); } }, [searchQuery]); // 初始加载和搜索 useEffect(() => { // 延迟搜索,避免频繁请求 const timer = setTimeout(() => { loadFAQs(); }, 500); return () => clearTimeout(timer); }, [loadFAQs]); // 打开创建对话框 const handleOpenCreate = () => { setCreateForm({ question: "", answer: "", keywords: "", }); setCreateDialogOpen(true); }; // 创建 FAQ const handleCreate = async () => { if (!createForm.question.trim() || !createForm.answer.trim()) { toast.error(t("agent.faqs.toast.emptyRequired")); return; } setSubmitting(true); try { await createFAQ(createForm); setCreateDialogOpen(false); setCreateForm({ question: "", answer: "", keywords: "" }); await loadFAQs(); toast.success(t("agent.faqs.toast.createSuccess")); } catch (error) { toast.error((error as Error).message || t("agent.faqs.toast.createFailed")); } finally { setSubmitting(false); } }; // 打开编辑对话框 const handleOpenEdit = (faq: FAQSummary) => { setSelectedFAQ(faq); setEditForm({ question: faq.question, answer: faq.answer, keywords: faq.keywords || "", }); setEditDialogOpen(true); }; // 更新 FAQ const handleUpdate = async () => { if (!selectedFAQ) { return; } if (!editForm.question?.trim() || !editForm.answer?.trim()) { toast.error(t("agent.faqs.toast.emptyRequired")); return; } setSubmitting(true); try { await updateFAQ(selectedFAQ.id, editForm); setEditDialogOpen(false); setSelectedFAQ(null); await loadFAQs(); toast.success(t("agent.faqs.toast.updateSuccess")); } catch (error) { toast.error((error as Error).message || t("agent.faqs.toast.updateFailed")); } finally { setSubmitting(false); } }; // 打开删除对话框 const handleOpenDelete = (faq: FAQSummary) => { setSelectedFAQ(faq); setDeleteDialogOpen(true); }; // 删除 FAQ const handleDelete = async () => { if (!selectedFAQ) { return; } setSubmitting(true); try { await deleteFAQ(selectedFAQ.id); setDeleteDialogOpen(false); setSelectedFAQ(null); await loadFAQs(); toast.success(t("agent.faqs.toast.deleteSuccess")); } catch (error) { toast.error((error as Error).message || t("agent.faqs.toast.deleteFailed")); } finally { setSubmitting(false); } }; // 格式化时间 const formatTime = (dateStr: string) => { const date = new Date(dateStr); return date.toLocaleString(lang === "en" ? "en-US" : "zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", }); }; // 构建头部内容 const headerContent = (

{t("agent.faqs.title")}

{!embedded && ( )}
{/* 搜索和操作栏 */}
setSearchQuery(e.target.value)} className="pl-10" />
); // 构建主内容区 const mainContent = (
{loading ? (
{t("common.loading")}
) : faqs.length === 0 ? (
{searchQuery ? t("agent.faqs.empty.filtered") : t("agent.faqs.empty")}
) : (
{faqs.map((faq) => (

{faq.question}

{faq.answer}
{faq.keywords && (
{t("agent.faqs.card.keywords")}: {faq.keywords}
)}
{t("agent.faqs.card.createdAt")}: {formatTime(faq.created_at)}
))}
)}
); const faqDialogs = ( <> {t("agent.faqs.dialog.createTitle2")} {t("agent.faqs.dialog.createDesc")}