/** * 复盘表单:四周期截图即时上传与状态展示. */ (function (global) { "use strict"; function newDraftId() { if (global.crypto && typeof global.crypto.randomUUID === "function") { return global.crypto.randomUUID().replace(/-/g, ""); } var s = ""; for (var i = 0; i < 32; i++) { s += Math.floor(Math.random() * 16).toString(16); } return s; } function ensureDraftId(root) { var scope = root || document; var el = scope.querySelector("#journal-draft-id"); if (!el) return ""; if (!el.value) { el.value = newDraftId(); } return el.value; } function rowParts(input) { var row = input.closest(".journal-upload-row"); if (!row) return {}; return { row: row, status: row.querySelector(".journal-upload-status"), hidden: row.querySelector(".journal-upload-hidden-file"), }; } function setStatus(statusEl, text, kind) { if (!statusEl) return; statusEl.textContent = text || ""; statusEl.classList.remove( "journal-upload-status--pending", "journal-upload-status--ok", "journal-upload-status--err" ); if (kind) { statusEl.classList.add("journal-upload-status--" + kind); } } function uploadSlotFile(input, file) { var parts = rowParts(input); var draftId = ensureDraftId(input.form || document); if (!draftId || !file) { setStatus(parts.status, "上传失败", "err"); return; } setStatus(parts.status, "上传中…", "pending"); if (parts.hidden) { parts.hidden.value = ""; } var fd = new FormData(); fd.append("journal_draft_id", draftId); fd.append("tf", input.getAttribute("data-tf") || ""); fd.append("file", file); fetch("/api/journal_upload_slot", { method: "POST", body: fd, credentials: "same-origin" }) .then(function (res) { return res.json().then(function (data) { return { ok: res.ok, data: data }; }); }) .then(function (result) { if (!result.ok || !result.data || !result.data.ok) { throw new Error( (result.data && result.data.error) || "upload failed" ); } var fname = String(result.data.file || "").trim(); if (parts.hidden) { parts.hidden.value = fname; } input.value = ""; setStatus(parts.status, "上传成功 " + fname, "ok"); }) .catch(function () { if (parts.hidden) { parts.hidden.value = ""; } setStatus(parts.status, "上传失败", "err"); }); } function isOptionsReviewSlot(input) { if (!input) return false; if (input.classList && input.classList.contains("or-upload-input")) return true; return !!(input.closest && input.closest("#or-upload-slots, #options-review-root")); } function bindInput(input) { if (!input || input.dataset.journalSlotBound === "1") return; // 期权复盘槽位由 options_review.js 处理,勿被合约复盘上传抢走 if (isOptionsReviewSlot(input)) return; input.dataset.journalSlotBound = "1"; input.addEventListener("change", function () { var file = input.files && input.files[0]; if (!file) { var parts = rowParts(input); if (parts.hidden) { parts.hidden.value = ""; } setStatus(parts.status, "", ""); return; } uploadSlotFile(input, file); }); } function resetSlots(root) { var scope = root || document; var draftEl = scope.querySelector("#journal-draft-id"); if (draftEl) { draftEl.value = newDraftId(); } scope.querySelectorAll(".journal-upload-hidden-file").forEach(function (el) { el.value = ""; }); scope.querySelectorAll(".journal-upload-slot-input").forEach(function (el) { el.value = ""; }); scope.querySelectorAll(".journal-upload-status").forEach(function (el) { setStatus(el, "", ""); }); } function init(root) { var scope = root || document; ensureDraftId(scope); scope.querySelectorAll(".journal-upload-slot-input").forEach(bindInput); } global.JournalUploadSlots = { init: init, reset: resetSlots }; if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", function () { init(document); }); } else { init(document); } })(typeof window !== "undefined" ? window : globalThis);