/* Copyright (c) 2025-2026 马建军. All rights reserved. * 专有软件 — 未经授权禁止复制、传播、转售。 * 详见 LICENSE.zh-CN.txt */ (function () { var trendPayload = null; function jsonPost(url, body) { return fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body || {}) }).then(function (r) { return r.json(); }); } function formData(form) { var fd = new FormData(form); var o = {}; fd.forEach(function (v, k) { o[k] = v; }); return o; } function showPreview(el, text, ok) { if (!el) return; if (!text) { el.hidden = true; el.textContent = ''; return; } el.hidden = false; el.textContent = text; el.style.color = ok === false ? 'var(--loss)' : ''; } function formatPlan(plan) { if (!plan) return ''; var lines = []; if (plan.symbol) lines.push('品种:' + plan.symbol); if (plan.target_lots != null) lines.push('目标手数:' + plan.target_lots); if (plan.first_lots != null) lines.push('首仓:' + plan.first_lots + ' 手'); if (plan.grid && plan.grid.length) { lines.push('补仓档位:' + plan.grid.map(function (g) { return g.price; }).join(' → ')); } if (plan.message) lines.push(plan.message); return lines.length ? lines.join('\n') : JSON.stringify(plan, null, 2); } function formatRoll(preview) { if (!preview) return ''; var lines = []; if (preview.add_lots != null) lines.push('加仓手数:' + preview.add_lots); if (preview.new_stop_loss != null) lines.push('新止损:' + preview.new_stop_loss); if (preview.total_lots != null) lines.push('合计手数:' + preview.total_lots); if (preview.worst_loss != null) lines.push('最坏亏损:' + preview.worst_loss + ' 元'); if (preview.message) lines.push(preview.message); return lines.length ? lines.join('\n') : JSON.stringify(preview, null, 2); } var trendForm = document.getElementById('trend-form'); var btnPreview = document.getElementById('btn-trend-preview'); var btnExec = document.getElementById('btn-trend-exec'); var previewEl = document.getElementById('trend-preview'); if (btnPreview && trendForm) { btnPreview.addEventListener('click', function () { btnPreview.disabled = true; jsonPost('/api/strategy/trend/preview', formData(trendForm)).then(function (d) { if (!d.ok) { showPreview(previewEl, d.error || '预览失败', false); btnExec.hidden = true; return; } trendPayload = formData(trendForm); showPreview(previewEl, formatPlan(d.plan), true); btnExec.hidden = false; }).finally(function () { btnPreview.disabled = false; }); }); } if (btnExec) { btnExec.addEventListener('click', function () { if (!trendPayload) return; btnExec.disabled = true; btnExec.textContent = '执行中…'; jsonPost('/api/strategy/trend/execute', trendPayload).then(function (d) { if (!d.ok) { alert(d.error); return; } location.reload(); }).finally(function () { btnExec.disabled = false; btnExec.textContent = '确认执行首仓'; }); }); } var rollForm = document.getElementById('roll-form'); var btnRollP = document.getElementById('btn-roll-preview'); var btnRollE = document.getElementById('btn-roll-exec'); var rollPrev = document.getElementById('roll-preview'); if (btnRollP && rollForm) { btnRollP.addEventListener('click', function () { btnRollP.disabled = true; jsonPost('/api/strategy/roll/preview', formData(rollForm)).then(function (d) { if (!d.ok) { showPreview(rollPrev, d.error, false); btnRollE.hidden = true; return; } showPreview(rollPrev, formatRoll(d.preview), true); btnRollE.hidden = false; }).finally(function () { btnRollP.disabled = false; }); }); } if (btnRollE && rollForm) { btnRollE.addEventListener('click', function () { btnRollE.disabled = true; btnRollE.textContent = '执行中…'; jsonPost('/api/strategy/roll/execute', formData(rollForm)).then(function (d) { if (!d.ok) { alert(d.error); return; } location.reload(); }).finally(function () { btnRollE.disabled = false; btnRollE.textContent = '执行滚仓'; }); }); } var btnStop = document.getElementById('btn-trend-stop'); if (btnStop) { btnStop.addEventListener('click', function () { var pid = document.querySelector('#trend-stop-form input[name=plan_id]'); jsonPost('/api/strategy/trend/stop', { plan_id: pid ? pid.value : 0 }).then(function (d) { if (!d.ok) { alert(d.error); return; } location.reload(); }); }); } })();