import Link from "next/link"; import type { SubscriptionRiskEvent } from "@prisma/client"; import { ChevronDown } from "lucide-react"; import { SubscriptionStatusBadge, SubscriptionTypeBadge, UserStatusBadge, } from "@/components/shared/domain-badges"; import { EmptyState } from "@/components/shared/page-shell"; import { StatusBadge, type StatusTone } from "@/components/shared/status-badge"; import { SubscriptionRiskReviewActions } from "@/components/subscriptions/subscription-risk-review-actions"; import { formatDate, formatDateShort } from "@/lib/utils"; import { SubscriptionRiskGeoDetails } from "./subscription-risk-geo-details"; import type { SubscriptionRiskEventRow } from "../risk-data"; function kindLabel(kind: SubscriptionRiskEvent["kind"]) { return kind === "AGGREGATE" ? "总订阅" : "单订阅"; } function reasonLabel(reason: SubscriptionRiskEvent["reason"]) { switch (reason) { case "CITY_VARIANCE_WARNING": return "城市异常警告"; case "CITY_VARIANCE_SUSPEND": return "城市异常暂停"; case "REGION_VARIANCE_WARNING": return "省/地区异常警告"; case "REGION_VARIANCE_SUSPEND": return "省/地区异常暂停"; case "COUNTRY_VARIANCE_WARNING": return "国家异常警告"; case "COUNTRY_VARIANCE_SUSPEND": return "国家异常暂停"; } } function reviewStatusLabel(status: SubscriptionRiskEvent["reviewStatus"]) { switch (status) { case "OPEN": return "待处理"; case "ACKNOWLEDGED": return "已确认"; case "RESOLVED": return "已解决"; } } function reviewStatusTone(status: SubscriptionRiskEvent["reviewStatus"]): StatusTone { if (status === "RESOLVED") return "success"; if (status === "ACKNOWLEDGED") return "info"; return "warning"; } function finalActionLabel(action: SubscriptionRiskEvent["finalAction"]) { switch (action) { case "RESTORE_ACCESS": return "已解除限制"; case "KEEP_RESTRICTED": return "保持封禁/暂停"; default: return null; } } function finalActionTone(action: SubscriptionRiskEvent["finalAction"]): StatusTone { if (action === "RESTORE_ACCESS") return "success"; if (action === "KEEP_RESTRICTED") return "warning"; return "neutral"; } function MetricStrip({ events }: { events: SubscriptionRiskEventRow[] }) { const open = events.filter((event) => event.reviewStatus === "OPEN").length; const suspended = events.filter((event) => event.level === "SUSPENDED").length; const restricted = events.filter((event) => event.userRestrictionActive).length; const reports = events.filter((event) => event.reportSentAt).length; return (
{[ ["本页待处理", open], ["已暂停事件", suspended], ["用户端限制", restricted], ["已发送报告", reports], ].map(([label, value]) => (

{label}

{value}

))}
); } function EventScope({ event }: { event: SubscriptionRiskEventRow }) { if (!event.subscription) { return (
{kindLabel(event.kind)}

按用户总订阅统计,自动处置时会影响名下可暂停代理订阅。

); } return (
{event.subscription.plan.name}

到期:{formatDateShort(event.subscription.endDate)}

); } function UserBlock({ event }: { event: SubscriptionRiskEventRow }) { if (!event.user) { return

未知用户

; } return (
{event.user.email}

{event.user.name || "未设置昵称"}

); } function ReviewState({ event }: { event: SubscriptionRiskEventRow }) { const finalLabel = finalActionLabel(event.finalAction); return (
{reviewStatusLabel(event.reviewStatus)} {event.reportSentAt && 已发送报告} {event.userRestrictionActive && 用户端限制中} {finalLabel && {finalLabel}}
{(event.reviewedByEmail || event.reviewNote) && (
{event.reviewedByEmail &&

{event.reviewedByEmail}

} {event.reviewedAt &&

{formatDate(event.reviewedAt)}

} {event.reviewNote &&

{event.reviewNote}

}
)}
); } function RiskStat({ label, value }: { label: string; value: string | number }) { return ( {label} {value} ); } function RiskEventCard({ event }: { event: SubscriptionRiskEventRow }) { const summary = event.geoSummary; const userLabel = event.user?.email ?? "未知用户"; const scopeLabel = event.subscription?.plan.name ?? "总订阅"; return (
{reasonLabel(event.reason)} {kindLabel(event.kind)} {reviewStatusLabel(event.reviewStatus)} {event.userRestrictionActive && 用户端限制中} {event.reportSentAt && 已发送报告} {formatDate(event.createdAt)}

{event.message}

{userLabel} · {scopeLabel} · 最近 IP:{event.ip || "未知 IP"}

详情

关联用户

影响范围

); } export function SubscriptionRiskTable({ events }: { events: SubscriptionRiskEventRow[] }) { if (events.length === 0) { return ( ); } return (
{events.map((event) => ( ))}
); }