"use client"; import { useState } from "react"; import { safetyApi } from "@/lib/api"; import type { PendingApproval } from "@/types/api"; import { PERMISSION_POLICY_LABEL, RISK_LEVEL_LABEL, } from "@/lib/constants/labels"; import { cn } from "@/lib/utils/cn"; type Phase = "pending" | "loading" | "approved" | "denied"; /** * 朱批裁定卡 —— 司命台动作签名(铜镜鉴心 v2)。 * 待裁定项以朱漆描边浮前:左缘 3px 朱漆 + 朱漆辐射底晕 + 鎏金"朱批待定"印文, * 右缘 RISK mono 印鉴;裁定后卡片转为低饱和留档态。动效克制,仅在交互瞬间触发。 */ export function VermilionAction({ approval }: { approval: PendingApproval }) { const [phase, setPhase] = useState("pending"); const [error, setError] = useState(null); async function decide(action: "approve" | "deny") { setPhase("loading"); setError(null); try { if (action === "approve") { await safetyApi.approveConfirmation(approval.confirmation_id); setPhase("approved"); } else { await safetyApi.denyConfirmation(approval.confirmation_id); setPhase("denied"); } } catch (e) { setError(e instanceof Error ? e.message : "裁定失败,请重试。"); setPhase("pending"); } } const decided = phase === "approved" || phase === "denied"; return (
{!decided && ( 朱批待定 )} {approval.tool} {PERMISSION_POLICY_LABEL[approval.permission_policy]} {RISK_LEVEL_LABEL[approval.risk_level]}

{approval.action_summary}

{approval.possible_impact && (

影响:{approval.possible_impact}

)} {approval.reason && (

{approval.reason}

)} {error &&

{error}

} {phase === "approved" && (

已朱批放行

)} {phase === "denied" && (

已驳回

)} {phase === "pending" || phase === "loading" ? (
) : null}
); }