"use client"; import { Eye, RefreshCw, Search } from "lucide-react"; import { useCallback, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { getAgentNodes } from "@/api/admin-agents"; import { AdminPageCard } from "@/components/admin/admin-page-card"; import { AdminTableLoadingRow } from "@/components/admin/admin-loading-state"; import { AdminTableNoResourceRow } from "@/components/admin/admin-no-resource-state"; import { AdminRowActionsMenu } from "@/components/admin/admin-row-actions-menu"; import { AdminStatusBadge } from "@/components/admin/admin-status-badge"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { formatAdminCreditMajorDecimal } from "@/lib/money"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { useAsyncEffect } from "@/hooks/use-async-effect"; import { useTranslationRef } from "@/hooks/use-translation-ref"; import type { AgentNodeRow } from "@/types/api/admin-agent"; function formatPercent(value: number | null | undefined): string { if (value == null || Number.isNaN(value)) { return "-"; } return `${Number(value).toFixed(2).replace(/\.?0+$/, "")}%`; } function formatCredit(value: number | null | undefined): string { if (value == null || Number.isNaN(value)) { return "-"; } return formatAdminCreditMajorDecimal(value); } function statusLabel(status: number, t: (key: string, options?: { defaultValue?: string }) => string): string { return status === 1 ? t("statusEnabled", { defaultValue: "启用" }) : t("statusDisabled", { defaultValue: "停用" }); } type DirectoryStatusFilter = "all" | "enabled" | "disabled"; function directoryStatusLabel( value: DirectoryStatusFilter, t: (key: string, options?: { defaultValue?: string }) => string, ): string { switch (value) { case "enabled": return t("directoryStatus.enabled", { defaultValue: "仅启用" }); case "disabled": return t("directoryStatus.disabled", { defaultValue: "仅停用" }); default: return t("directoryStatus.all", { defaultValue: "全部状态" }); } } export function AgentsDirectoryConsole(): React.ReactElement { const { t } = useTranslation(["agents", "common"]); const tRef = useTranslationRef(["agents", "common"]); const [items, setItems] = useState([]); const [loading, setLoading] = useState(true); const [err, setErr] = useState(null); const [keyword, setKeyword] = useState(""); const [status, setStatus] = useState("all"); const [reloadKey, setReloadKey] = useState(0); const parentNameMap = useMemo( () => new Map(items.map((item) => [item.id, item.name])), [items], ); const load = useCallback(async () => { setLoading(true); setErr(null); try { const data = await getAgentNodes(); setItems(data.items); } catch (error) { const message = error instanceof Error ? error.message : tRef.current("agents:loadFailed", { defaultValue: "加载代理列表失败" }); setErr(message); } finally { setLoading(false); } }, [tRef]); useAsyncEffect(load, [load, reloadKey]); const filteredItems = useMemo(() => { const normalized = keyword.trim().toLowerCase(); return items.filter((item) => { if (status === "enabled" && item.status !== 1) { return false; } if (status === "disabled" && item.status === 1) { return false; } if (!normalized) { return true; } const parentName = item.parent_id != null ? parentNameMap.get(item.parent_id) ?? "" : ""; return [item.name, item.code, item.username ?? "", item.email ?? "", parentName] .join(" ") .toLowerCase() .includes(normalized); }); }, [items, keyword, parentNameMap, status]); const totalOperatingAgents = useMemo( () => items.filter((item) => !item.is_root).length, [items], ); const enabledOperatingAgents = useMemo( () => items.filter((item) => !item.is_root && item.status === 1).length, [items], ); return (

{t("summary.visibleAgents", { defaultValue: "当前可见经营代理数" })}

{totalOperatingAgents}

{t("summary.enabledAgents", { defaultValue: "启用中的经营代理数" })}

{enabledOperatingAgents}

{t("summary.visibleList", { defaultValue: "当前平铺列表条数" })}

{filteredItems.length}

setReloadKey((value) => value + 1)} disabled={loading} > {t("common:actions.refresh", { defaultValue: "刷新" })} } >
setKeyword(event.target.value)} placeholder={t("listSearch", { defaultValue: "搜索代理名称 / 编码 / 登录名" })} className="pl-9" />
{err ? (
{err}
) : null}
{t("name", { defaultValue: "名称" })} {t("code", { defaultValue: "编码" })} {t("depth", { defaultValue: "层级" })} {t("status", { defaultValue: "状态" })} {t("parentAgent", { defaultValue: "上级代理" })} {t("username", { defaultValue: "登录名" })} {t("profile.totalShareRate", { defaultValue: "占成比例 (%)" })} {t("profile.rebateLimit", { defaultValue: "回水上限 (%)" })} {t("profile.creditLimit", { defaultValue: "授信额度" })} {t("lineUi.availableCredit", { defaultValue: "可下发" })} {t("common:table.actions", { defaultValue: "操作" })} {loading ? ( ) : filteredItems.length === 0 ? ( ) : ( filteredItems.map((item) => { const parentName = item.parent_id != null ? parentNameMap.get(item.parent_id) ?? "-" : "-"; const profile = item.profile_summary; return (
{item.name}
{item.code} {item.depth} {item.is_root ? ( {t("isRoot", { defaultValue: "根节点" })} ) : ( {statusLabel(item.status, t)} )} {parentName} {item.username ?? "-"} {formatPercent(profile?.total_share_rate)} {formatPercent(profile?.rebate_limit)} {formatCredit(profile?.credit_limit)} {formatCredit(profile?.available_credit)}
); }) )}
); }