"use client"; import { useState } from "react"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { fetchWithAuth } from "@/lib/api/client"; import type { QueryListResponse, ApiQueryItem } from "@/lib/api/queries"; import { PLATFORM_MAP, PLATFORMS } from "@/lib/platforms"; import { useApi } from "@/lib/hooks/use-api"; import { LoadingState, ErrorState, EmptyState } from "@/components/ui/api-states"; import { Plus, Pencil, Trash2, Play, Loader2, Search, CheckCircle, } from "lucide-react"; interface QueryFormData { keyword: string; target_brand: string; brand_aliases: string; platforms: string[]; frequency: string; } const FREQUENCY_MAP: Record = { daily: "每日", weekly: "每周", }; const emptyForm: QueryFormData = { keyword: "", target_brand: "", brand_aliases: "", platforms: [], frequency: "weekly", }; export default function QueriesPage() { const { data: queriesResponse, isLoading: loading, error: apiError, refresh: refreshQueries } = useApi("/api/v1/queries/"); const queries: ApiQueryItem[] = (queriesResponse?.items ?? []); const error = apiError?.message ?? null; const [dialogOpen, setDialogOpen] = useState(false); const [editingId, setEditingId] = useState(null); const [formData, setFormData] = useState(emptyForm); const [saving, setSaving] = useState(false); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [deletingId, setDeletingId] = useState(null); const [deleting, setDeleting] = useState(false); const [actionLoading, setActionLoading] = useState(null); const [formErrors, setFormErrors] = useState>({}); const [successMsg, setSuccessMsg] = useState(null); const [mutationError, setMutationError] = useState(null); function showSuccess(msg: string) { setSuccessMsg(msg); setTimeout(() => setSuccessMsg(null), 3000); } function openAddDialog() { setEditingId(null); setFormData(emptyForm); setFormErrors({}); setMutationError(null); setDialogOpen(true); } function openEditDialog(item: ApiQueryItem) { setEditingId(item.id); setFormErrors({}); setMutationError(null); setFormData({ keyword: item.keyword, target_brand: item.target_brand, brand_aliases: item.brand_aliases?.join(", ") || "", platforms: item.platforms || [], frequency: item.frequency, }); setDialogOpen(true); } function validateForm(): boolean { const errors: Record = {}; if (!formData.keyword.trim()) { errors.keyword = "请输入关键词"; } if (!formData.target_brand.trim()) { errors.target_brand = "请输入目标品牌"; } if (formData.platforms.length === 0) { errors.platforms = "请至少选择一个平台"; } setFormErrors(errors); return Object.keys(errors).length === 0; } async function handleSave() { if (!validateForm()) return; try { setSaving(true); setMutationError(null); const payload = { keyword: formData.keyword.trim(), target_brand: formData.target_brand.trim(), brand_aliases: formData.brand_aliases .split(",") .map((s) => s.trim()) .filter(Boolean), platforms: formData.platforms, frequency: formData.frequency, }; if (editingId) { await fetchWithAuth(`/api/v1/queries/${editingId}`, { method: "PUT", body: JSON.stringify(payload), }); } else { await fetchWithAuth("/api/v1/queries/", { method: "POST", body: JSON.stringify(payload), }); } setDialogOpen(false); showSuccess(editingId ? "修改成功" : "添加成功"); refreshQueries(); } catch (err) { setMutationError(err instanceof Error ? err.message : "保存失败"); } finally { setSaving(false); } } function openDeleteDialog(id: string) { setDeletingId(id); setDeleteDialogOpen(true); } async function handleDelete() { if (!deletingId) return; try { setDeleting(true); await fetchWithAuth(`/api/v1/queries/${deletingId}`, { method: "DELETE" }); setDeleteDialogOpen(false); setDeletingId(null); showSuccess("删除成功"); refreshQueries(); } catch (err) { setMutationError(err instanceof Error ? err.message : "删除失败"); } finally { setDeleting(false); } } async function handleRunQuery(id: string) { setActionLoading(id); setMutationError(null); try { await fetchWithAuth(`/api/v1/queries/${id}/run-now`, { method: "POST" }); showSuccess("查询已执行"); refreshQueries(); } catch (err) { setMutationError(err instanceof Error ? err.message : "立即查询失败"); } finally { setActionLoading(null); } } function togglePlatform(platform: string) { setFormData((prev) => { const platforms = prev.platforms.includes(platform) ? prev.platforms.filter((p) => p !== platform) : [...prev.platforms, platform]; return { ...prev, platforms }; }); } if (loading) { return (

查询词管理

管理您的关键词查询任务

); } if (error) { return (

查询词管理

管理您的关键词查询任务

); } return (

查询词管理

管理您的关键词查询任务

{editingId ? "编辑查询词" : "添加查询词"} {editingId ? "修改查询词配置" : "配置新的关键词查询任务"}
{ setFormData((prev) => ({ ...prev, keyword: e.target.value })); if (formErrors.keyword) { setFormErrors((prev) => ({ ...prev, keyword: "" })); } }} /> {formErrors.keyword && (

{formErrors.keyword}

)}
{ setFormData((prev) => ({ ...prev, target_brand: e.target.value, })); if (formErrors.target_brand) { setFormErrors((prev) => ({ ...prev, target_brand: "" })); } }} /> {formErrors.target_brand && (

{formErrors.target_brand}

)}
setFormData((prev) => ({ ...prev, brand_aliases: e.target.value, })) } />
{PLATFORMS.map((p) => ( ))}
{formErrors.platforms && (

{formErrors.platforms}

)}
{mutationError && (

{mutationError}

)}
{successMsg && (
{successMsg}
)} {mutationError && !dialogOpen && (
{mutationError}
)} {queries.length === 0 ? ( } message="暂无查询词" description="点击右上角按钮添加您的第一个查询词" /> ) : ( 查询词列表
关键词 目标品牌 平台 频率 状态 最后查询 操作 {queries.map((item: ApiQueryItem) => ( {item.keyword} {item.target_brand}
{item.platforms.map((p) => ( {PLATFORM_MAP[p] || p} ))}
{FREQUENCY_MAP[item.frequency] || item.frequency} {item.status === "active" ? "运行中" : "已暂停"} {item.last_queried_at ? new Date(item.last_queried_at).toLocaleString("zh-CN") : "从未"}
))}
)} 确认删除 删除后无法恢复,确定要删除这个查询词吗?
); }