feat: enhance subscription risk review workflow

This commit is contained in:
JetSprow
2026-04-29 16:12:51 +10:00
parent 086934198a
commit 823b31363a
20 changed files with 1866 additions and 138 deletions

View File

@@ -0,0 +1,106 @@
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { AlertTriangle, FileText, LifeBuoy } from "lucide-react";
import { buttonVariants } from "@/components/ui/button";
export type SubscriptionRiskRestrictionNotice = {
id: string;
level: "WARNING" | "SUSPENDED";
reasonLabel: string;
message: string;
riskReport: string | null;
reportSentAt: string | null;
};
function supportHref(id: string) {
return "/support?riskEventId=" + encodeURIComponent(id);
}
export function SubscriptionRiskRestrictionGate({
restriction,
}: {
restriction: SubscriptionRiskRestrictionNotice | null;
}) {
const pathname = usePathname();
if (!restriction) return null;
const isSupportPath = pathname === "/support" || pathname.startsWith("/support/");
if (isSupportPath) {
return (
<section className="mb-5 rounded-xl border border-destructive/25 bg-destructive/8 p-4 text-sm leading-6">
<div className="flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between">
<div className="flex items-start gap-3">
<span className="flex size-9 shrink-0 items-center justify-center rounded-lg bg-destructive/10 text-destructive">
<AlertTriangle className="size-4" />
</span>
<div>
<p className="font-semibold text-destructive"></p>
<p className="mt-1 text-muted-foreground">
访
</p>
</div>
</div>
<span className="rounded-full border border-destructive/20 px-2.5 py-1 text-xs font-medium text-destructive">
{restriction.reasonLabel}
</span>
</div>
</section>
);
}
return (
<div className="fixed inset-0 z-[80] flex items-center justify-center overflow-y-auto bg-background/96 p-4 backdrop-blur-md">
<div className="w-full max-w-3xl overflow-hidden rounded-2xl border border-destructive/25 bg-card shadow-2xl">
<div className="border-b border-border/70 bg-destructive/8 p-5 sm:p-6">
<div className="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
<div className="flex items-start gap-3">
<span className="flex size-11 shrink-0 items-center justify-center rounded-xl bg-destructive/10 text-destructive">
<AlertTriangle className="size-5" />
</span>
<div>
<p className="text-xs font-medium text-destructive"></p>
<h2 className="mt-1 text-xl font-semibold tracking-[-0.02em]"></h2>
<p className="mt-2 max-w-2xl text-sm leading-6 text-muted-foreground">
IP 访
</p>
</div>
</div>
<span className="w-fit rounded-full border border-destructive/20 px-3 py-1 text-xs font-medium text-destructive">
{restriction.reasonLabel}
</span>
</div>
</div>
<div className="space-y-4 p-5 sm:p-6">
<div className="rounded-xl border border-border/70 bg-muted/25 p-4">
<div className="mb-2 flex items-center gap-2 text-sm font-semibold">
<FileText className="size-4 text-primary" />
</div>
<p className="text-sm leading-6 text-muted-foreground">{restriction.message}</p>
</div>
{restriction.riskReport && (
<pre className="max-h-72 overflow-auto whitespace-pre-wrap rounded-xl border border-border/70 bg-muted/30 p-4 text-xs leading-6 text-foreground">
{restriction.riskReport}
</pre>
)}
<div className="flex flex-col gap-3 rounded-xl border border-primary/20 bg-primary/8 p-4 sm:flex-row sm:items-center sm:justify-between">
<div className="text-sm leading-6">
<p className="font-semibold text-primary"></p>
<p className="text-muted-foreground">访</p>
</div>
<Link href={supportHref(restriction.id)} className={buttonVariants({ size: "lg" })}>
<LifeBuoy className="size-4" />
</Link>
</div>
</div>
</div>
</div>
);
}