"use client"; import { ShieldAlert } from "lucide-react"; import { useCallback, useEffect, useState } from "react"; import { adminApi, errMessage, type RiskAlert } from "@/lib/admin-api"; import { Badge, Button, Card, EmptyState, ErrorState, LoadingBlock, Modal, Pagination, Select, StatCard, TableWrap, Td, Th, formatPercent, formatTime, statusTone, useToast, } from "@/components/admin/ui"; const STATUS_OPTIONS = [ { value: "", label: "全部状态" }, { value: "未处理", label: "未处理" }, { value: "已确认", label: "已确认" }, { value: "已排除", label: "已排除" }, ]; type Action = "release" | "block" | "freeze"; const ACTION_META: Record< Action, { label: string; tone: "primary" | "danger"; impact: string[]; confirmText: string } > = { release: { label: "放行", tone: "primary", confirmText: "确认放行", impact: [ "该笔交易订单将完成落账并生成交易流水", "预警状态变更为「已排除」", "若客户余额不足,订单将转为失败", ], }, block: { label: "拦截", tone: "danger", confirmText: "确认拦截", impact: [ "该笔交易订单将作废", "系统将向客户发送「交易被拦截」站内信", "自动生成一张「可疑交易上报」工单", ], }, freeze: { label: "冻结", tone: "danger", confirmText: "确认冻结", impact: [ "该笔交易订单将作废", "客户账号状态将变更为「冻结」", "系统将向客户发送「账户已被冻结」站内信", "自动生成一张「冻结复核」工单", ], }, }; export function RiskSection() { const toast = useToast(); const [items, setItems] = useState([]); const [total, setTotal] = useState(0); const [totalPages, setTotalPages] = useState(0); const [page, setPage] = useState(1); const [status, setStatus] = useState("未处理"); const [loading, setLoading] = useState(true); const [error, setError] = useState(""); const [pending, setPending] = useState<{ alert: RiskAlert; action: Action } | null>(null); const [submitting, setSubmitting] = useState(false); const load = useCallback(async () => { setLoading(true); setError(""); try { const result = await adminApi.alerts({ status: status || undefined, page, page_size: 10 }); setItems(result.items ?? []); setTotal(result.total ?? 0); setTotalPages(result.total_pages ?? 0); } catch (e) { setError(errMessage(e, "预警列表加载失败")); } finally { setLoading(false); } }, [status, page]); useEffect(() => { void load(); }, [load]); async function confirmAction() { if (!pending) return; setSubmitting(true); try { const result = await adminApi.alertAction(pending.alert.id, pending.action); const message = typeof result?.message === "string" ? result.message : `${ACTION_META[pending.action].label}成功`; toast(message); setPending(null); await load(); } catch (e) { toast(errMessage(e, "处置失败"), "error"); } finally { setSubmitting(false); } } const highRisk = items.filter((item) => item.alert_level === "高").length; return ( <>
} label="当前预警" value={total} hint={status ? `筛选:${status}` : "全部状态"} /> 0 ? "需优先处置" : "暂无高风险预警"} hintTone={highRisk > 0 ? "danger" : "muted"} />
{ setStatus(event.target.value); setPage(1); }}> {STATUS_OPTIONS.map((option) => ( ))} } > {loading ? ( ) : error ? ( void load()} /> ) : items.length === 0 ? ( ) : ( <> 预警类型 客户 / 订单 触发详情 级别 置信度 状态 创建时间 处置 {items.map((alert) => { const done = alert.status !== "未处理"; return ( {alert.alert_type} 客户 #{alert.customer_id}
订单 #{alert.order_id} {alert.trigger_detail ?? "--"} {alert.alert_level} {alert.confidence !== null ? formatPercent(alert.confidence, 0) : "--"} {alert.status} {formatTime(alert.create_time)} {done ? ( 已处置 · {alert.handle_result ?? "--"} ) : (
{(["release", "block", "freeze"] as Action[]).map((action) => ( ))}
)} ); })}
)}
(submitting ? undefined : setPending(null))} footer={ <> } > {pending && (

你即将对 预警 #{pending.alert.id} 执行 「{ACTION_META[pending.action].label}」 操作。

预警类型:{pending.alert.alert_type}

风险级别:{pending.alert.alert_level}

关联客户:#{pending.alert.customer_id}

关联订单:#{pending.alert.order_id}

该操作将产生以下影响:

    {ACTION_META[pending.action].impact.map((line) => (
  • • {line}
  • ))}
)}
); }