/** * 时间平仓 + 整点强制清仓:表单开关 + 持仓/顶栏倒计时. */ (function (global) { "use strict"; function pad2(n) { return n < 10 ? "0" + n : String(n); } function formatCountdown(sec) { const s = Math.max(0, parseInt(sec, 10) || 0); const h = Math.floor(s / 3600); const m = Math.floor((s % 3600) / 60); const r = s % 60; return pad2(h) + ":" + pad2(m) + ":" + pad2(r); } function isForceCloseActive(wrap) { if (!wrap) return false; const raw = wrap.dataset.forceCloseActive || wrap.getAttribute("data-force-close-active") || ""; return raw === "1" || raw === "true"; } function bindTimeCloseForm(checkboxId, selectId, wrapId) { const cb = document.getElementById(checkboxId); const sel = document.getElementById(selectId); const wrap = wrapId ? document.getElementById(wrapId) : null; if (!cb || !sel) return; function sync() { const on = !!cb.checked; sel.disabled = false; sel.tabIndex = 0; if (wrap) wrap.classList.toggle("is-disabled", !on); } sel.addEventListener("mousedown", function (ev) { ev.stopPropagation(); }); sel.addEventListener("click", function (ev) { ev.stopPropagation(); }); cb.addEventListener("change", sync); sync(); } function paintCountdownEl(cd, rem, active) { if (!cd) return; if (active) { cd.textContent = "执行中"; return; } cd.textContent = Number.isFinite(rem) ? formatCountdown(rem) : "--:--:--"; } function paintOrderTimeClose(order) { if (!order || order.id == null) return; const wrap = document.getElementById("order-time-close-wrap-" + order.id); const cd = document.getElementById("order-time-close-cd-" + order.id); if (!wrap || !cd) return; const enabled = !!(order.time_close_enabled || order.time_close_at_ms); if (!enabled) { wrap.style.display = "none"; return; } wrap.style.display = ""; const hours = order.time_close_hours; const label = order.time_close_label || (hours ? "时间平仓 " + hours + "h" : "时间平仓"); const labelEl = wrap.querySelector(".pos-time-close-label"); if (labelEl) labelEl.textContent = label; let rem = order.time_close_remaining_sec != null ? Number(order.time_close_remaining_sec) : null; if ((rem == null || !Number.isFinite(rem)) && order.time_close_at_ms) { rem = Math.max(0, Math.floor((Number(order.time_close_at_ms) - Date.now()) / 1000)); } paintCountdownEl(cd, rem, false); wrap.dataset.closeAtMs = order.time_close_at_ms ? String(order.time_close_at_ms) : ""; } function paintOrderForceClose(order) { if (!order || order.id == null) return; const wrap = document.getElementById("order-force-close-wrap-" + order.id); const cd = document.getElementById("order-force-close-cd-" + order.id); if (!wrap || !cd) return; const enabled = !!order.force_close_enabled; if (!enabled) { wrap.style.display = "none"; return; } wrap.style.display = ""; const label = order.force_close_label || "强制清仓"; const labelEl = wrap.querySelector(".pos-force-close-label"); if (labelEl) labelEl.textContent = label; let rem = order.force_close_remaining_sec != null ? Number(order.force_close_remaining_sec) : null; const atMs = order.force_close_at_ms; if ((rem == null || !Number.isFinite(rem)) && atMs) { rem = Math.max(0, Math.floor((Number(atMs) - Date.now()) / 1000)); } const active = !!order.force_close_active; paintCountdownEl(cd, rem, active); wrap.dataset.forceCloseAtMs = atMs ? String(atMs) : ""; wrap.dataset.forceCloseActive = active ? "1" : "0"; } function paintForceCloseHeader(state) { const wrap = document.getElementById("force-close-header-badge"); if (!wrap) return; if (!state || !state.enabled) { wrap.style.display = "none"; return; } wrap.style.display = ""; const label = state.label || "强制清仓"; const labelPrefix = label + " 已开启 · "; let prefixNode = wrap.querySelector(".force-close-header-prefix"); if (!prefixNode) { wrap.textContent = ""; prefixNode = document.createElement("span"); prefixNode.className = "force-close-header-prefix"; prefixNode.textContent = labelPrefix; wrap.appendChild(prefixNode); const cd = document.createElement("span"); cd.className = "force-close-header-cd"; wrap.appendChild(cd); } else { prefixNode.textContent = labelPrefix; } const cd = wrap.querySelector(".force-close-header-cd"); let rem = state.remaining_sec != null ? Number(state.remaining_sec) : null; if ((rem == null || !Number.isFinite(rem)) && state.next_at_ms) { rem = Math.max(0, Math.floor((Number(state.next_at_ms) - Date.now()) / 1000)); } paintCountdownEl(cd, rem, !!state.active); wrap.dataset.forceCloseAtMs = state.next_at_ms ? String(state.next_at_ms) : ""; wrap.dataset.forceCloseActive = state.active ? "1" : "0"; } function tickLocalCountdowns() { document.querySelectorAll("[data-close-at-ms]").forEach(function (wrap) { const closeAtRaw = wrap.dataset.closeAtMs || wrap.getAttribute("data-close-at-ms") || ""; const cd = wrap.querySelector(".pos-time-close-cd"); if (!cd) return; const closeAt = Number(closeAtRaw); if (!closeAt) return; const rem = Math.max(0, Math.floor((closeAt - Date.now()) / 1000)); cd.textContent = formatCountdown(rem); }); document.querySelectorAll("[data-force-close-at-ms]").forEach(function (wrap) { const closeAtRaw = wrap.dataset.forceCloseAtMs || wrap.getAttribute("data-force-close-at-ms") || ""; const cd = wrap.querySelector(".pos-force-close-cd, .force-close-header-cd"); if (!cd) return; const closeAt = Number(closeAtRaw); if (!closeAt) return; const rem = Math.max(0, Math.floor((closeAt - Date.now()) / 1000)); paintCountdownEl(cd, rem, isForceCloseActive(wrap)); }); } function paintOrders(orders) { (orders || []).forEach(function (order) { paintOrderTimeClose(order); paintOrderForceClose(order); }); } function syncKeyTimeCloseVisibility(show) { const wrap = document.getElementById("key-time-close-wrap"); if (!wrap) return; wrap.style.display = show ? "inline-flex" : "none"; } global.TimeCloseUI = { bindTimeCloseForm: bindTimeCloseForm, paintOrderTimeClose: paintOrderTimeClose, paintOrderForceClose: paintOrderForceClose, paintForceCloseHeader: paintForceCloseHeader, paintOrders: paintOrders, tickLocalCountdowns: tickLocalCountdowns, syncKeyTimeCloseVisibility: syncKeyTimeCloseVisibility, formatCountdown: formatCountdown, }; if (!global.__timeCloseCountdownTimer) { global.__timeCloseCountdownTimer = setInterval(tickLocalCountdowns, 1000); } })(typeof window !== "undefined" ? window : globalThis);