import { useEffect } from "react"; import { useWorkspaceStore } from "./store"; import type { ConfirmRequest } from "./store"; import type { NotifyKind, NotifyPayload } from "./notify"; import { OpsModal } from "./OpsModal"; import { settleInputRequest, useInputRequest } from "./dialogs"; // C6:items 字段由 WS-C 在 store.ts 正式补充,此处本地类型扩展先行渲染 type ConfirmRequestWithItems = ConfirmRequest & { items?: string[] }; /** * 分级语义色:统一走 --ops-* 令牌(修 V2,去除 slate 硬编码),亮暗主题随行 * error→danger / warning→warning / info→accent / success→success */ const KIND_META: Record = { error: { color: "var(--ops-danger)", label: "错误" }, warning: { color: "var(--ops-warning)", label: "提示" }, info: { color: "var(--ops-accent)", label: "信息" }, success: { color: "var(--ops-success)", label: "成功" }, }; function KindIcon({ kind }: { kind: NotifyKind }) { const meta = KIND_META[kind]; const glyph = kind === "error" ? "!" : kind === "warning" ? "!" : kind === "success" ? "✓" : "i"; return (
{glyph}
); } /** 通知模态:走 OpsModal info 变体(Esc/遮罩关闭、焦点管理由 OpsModal 负责) */ function ModalCard({ n, onClose }: { n: NotifyPayload; onClose: () => void }) { const meta = KIND_META[n.kind]; return ( {meta.label} {n.title} } onOk={onClose} >

{n.message}

{n.tips && n.tips.length > 0 && (
    {n.tips.map((t) => (
  • • {t}
  • ))}
)} {n.detail && (
技术详情
            {n.detail}
          
)}
); } /** Toast:保留分级图标 + 自动关闭,样式走令牌 */ function ToastCard({ n, onClose }: { n: NotifyPayload; onClose: () => void }) { const meta = KIND_META[n.kind]; useEffect(() => { const ms = n.durationMs ?? 3200; const t = window.setTimeout(onClose, ms); return () => window.clearTimeout(t); }, [n.durationMs, onClose]); return (
{n.title}
{n.message}
); } /** 危险/普通确认框:走 OpsModal confirm 变体;items 语句清单前 3 条 + 折叠其余(修 C2) */ function ConfirmCard() { const confirm = useWorkspaceStore((s) => s.confirm) as ConfirmRequestWithItems | null; const resolveConfirm = useWorkspaceStore((s) => s.resolveConfirm); if (!confirm) return null; const items = confirm.items; return ( resolveConfirm(true)} onCancel={() => resolveConfirm(false)} >

{confirm.message}

{items && items.length > 0 && (
{items.slice(0, 3).map((s, i) => (
{s}
))} {items.length > 3 && (
还有 {items.length - 3} 条,展开查看 {items.slice(3).map((s, i) => (
{s}
))}
)}
)}
); } /** askInput(C6)渲染宿主:队列中的输入请求逐个以 OpsModal input 变体展示 */ function DialogHost() { const req = useInputRequest(); if (!req) return null; return ( settleInputRequest(v ?? null)} onCancel={() => settleInputRequest(null)} /> ); } export function NotifyHost() { const modal = useWorkspaceStore((s) => s.notifyModal); const toasts = useWorkspaceStore((s) => s.notifyToasts); const dismissNotify = useWorkspaceStore((s) => s.dismissNotify); return ( <> {modal && dismissNotify(modal.id)} />}
{toasts.map((n) => ( dismissNotify(n.id)} /> ))}
); }