"use client"; import { useCallback, useEffect, useState } from "react"; import { AdminLayout } from "@/components/layout/admin-layout"; import { PageHeader } from "@/components/layout/page-header"; import { Skeleton } from "@/components/ui/skeleton"; import { ErrorBanner } from "@/components/ui/error-banner"; import { SecondaryButton } from "@/components/ui/primary-button"; import { SelectField } from "@/components/ui/select-field"; import { Card } from "@/components/ui/card"; import { formatDateTime } from "@/lib/frontend/format"; import { adminGetQueryLogs } from "@/lib/frontend/api-client"; import { useAuth } from "@/hooks/use-auth"; import type { DataPageStatus, QuoteQueryLogRecord, QuoteQueryOutcome, } from "@/lib/frontend/types"; const PAGE_SIZE = 20; const OUTCOME_OPTIONS = [ { value: "", label: "全部结果" }, { value: "success", label: "成功" }, { value: "failed", label: "失败" }, { value: "stale", label: "降级缓存" }, { value: "processing", label: "进行中" }, ]; const OUTCOME_LABEL: Record = { success: "成功", failed: "失败", stale: "降级缓存", processing: "进行中", }; function outcomeClass(outcome: QuoteQueryOutcome): string { if (outcome === "success") return "text-success"; if (outcome === "failed") return "text-error"; if (outcome === "stale") return "text-warning"; return "text-text-secondary"; } export default function QueryLogsPage() { const { token } = useAuth(); const [status, setStatus] = useState("loading"); const [rows, setRows] = useState([]); const [total, setTotal] = useState(0); const [page, setPage] = useState(1); const [outcomeFilter, setOutcomeFilter] = useState(""); const load = useCallback( async (p: number, outcome: string) => { if (!token) return; setStatus("loading"); const res = await adminGetQueryLogs( "", token, p, PAGE_SIZE, undefined, outcome || undefined, ); if (res.code !== 0) { setStatus("error"); return; } setRows(res.data.list); setTotal(res.data.total); setStatus(res.data.total === 0 ? "empty" : "success"); }, [token], ); useEffect(() => { void load(page, outcomeFilter); }, [load, page, outcomeFilter]); const totalPages = Math.max(1, Math.ceil(total / PAGE_SIZE)); return ( { setPage(1); setOutcomeFilter(e.target.value); }} /> } /> {status === "loading" && (
{Array.from({ length: 6 }).map((_, i) => ( ))}
)} {status === "error" && ( void load(page, outcomeFilter)}>重试} > 加载查价记录失败 )} {status === "empty" && (

暂无查价记录

)} {status === "success" && (
{rows.map((row) => ( ))}
查询时间 客户 提货(联想) 派送(联想) 货物 结果 完成时间
{formatDateTime(row.created_at)} {row.customer_id} {row.pickup_selected} {row.delivery_selected} {row.cargo_summary} {OUTCOME_LABEL[row.outcome]} {row.failure_reason && row.outcome !== "success" && (

{row.failure_reason}

)}
{row.completed_at ? formatDateTime(row.completed_at) : "—"}
共 {total} 条(系统最多保留 1000 条)
setPage((p) => p - 1)} > 上一页 {page} / {totalPages} = totalPages} onClick={() => setPage((p) => p + 1)} > 下一页
)}
); }