/** * 账户风控徽章倒计时 — 四所实例 + 中控共用。 */ (function (global) { "use strict"; function formatRemaining(totalSec) { const sec = Math.max(0, Math.floor(Number(totalSec) || 0)); if (sec <= 0) return ""; const h = Math.floor(sec / 3600); const m = Math.floor((sec % 3600) / 60); const s = sec % 60; if (h > 0) return `${h}h ${String(m).padStart(2, "0")}m`; if (m > 0) return `${m}m ${String(s).padStart(2, "0")}s`; return `${s}s`; } function baseLabel(riskStatus, el) { if (riskStatus && riskStatus.status_label) return String(riskStatus.status_label); if (el && el.dataset && el.dataset.statusLabel) return String(el.dataset.statusLabel); return "正常"; } function resolveFreezeUntilMs(riskStatus) { if (!riskStatus) return null; const sec = Number(riskStatus.freeze_remaining_sec); if (Number.isFinite(sec) && sec > 0) { return Date.now() + sec * 1000; } const until = Number(riskStatus.freeze_until_ms); return Number.isFinite(until) && until > 0 ? until : null; } function badgeText(riskStatus) { const label = baseLabel(riskStatus, null); const until = resolveFreezeUntilMs(riskStatus); if (!until || until <= Date.now()) return label; const cd = formatRemaining((until - Date.now()) / 1000); return cd ? `${label} · ${cd}` : label; } function setNormalBadge(el) { el.className = "risk-status-badge risk-status-normal"; el.dataset.statusLabel = "正常"; el.textContent = "正常"; el.title = ""; if (el.dataset) delete el.dataset.freezeUntilMs; } function refreshElement(el) { if (!el) return; const label = baseLabel(null, el); const until = Number(el.dataset && el.dataset.freezeUntilMs); if (!Number.isFinite(until) || until <= Date.now()) { if (el.dataset && el.dataset.freezeUntilMs) { setNormalBadge(el); } else { el.textContent = label; } return; } const cd = formatRemaining((until - Date.now()) / 1000); el.textContent = cd ? `${label} · ${cd}` : label; } function applyToElement(el, riskStatus) { if (!el || !riskStatus) return; const st = riskStatus.status || "normal"; el.className = "risk-status-badge risk-status-" + st; el.dataset.statusLabel = baseLabel(riskStatus, el); const until = resolveFreezeUntilMs(riskStatus); if (until) { el.dataset.freezeUntilMs = String(until); } else if (el.dataset) { delete el.dataset.freezeUntilMs; } el.textContent = badgeText(riskStatus); el.title = riskStatus.reason || ""; } function formatBadgeHtml(riskStatus, esc) { if (!riskStatus || typeof riskStatus !== "object") return ""; const safe = typeof esc === "function" ? esc : (s) => String(s); const st = riskStatus.status || "normal"; const label = safe(riskStatus.status_label || "正常"); const title = safe(riskStatus.reason || ""); const text = safe(badgeText(riskStatus)); const until = resolveFreezeUntilMs(riskStatus); const untilAttr = until != null ? ` data-freeze-until-ms="${safe(String(Math.floor(until)))}"` : ""; return ( `${text}` ); } function tickAll(root) { const scope = root || document; scope.querySelectorAll(".risk-status-badge[data-freeze-until-ms]").forEach(refreshElement); } let timer = null; function startTicker() { if (timer) return; tickAll(); timer = setInterval(() => tickAll(), 1000); } global.AccountRiskBadge = { formatRemaining, badgeText, refreshElement, applyToElement, formatBadgeHtml, tickAll, startTicker, }; })(typeof window !== "undefined" ? window : globalThis);