增加导航栏

This commit is contained in:
dekun
2026-05-25 17:12:49 +08:00
parent 2fbb3dd45a
commit 8117a1d71d
3 changed files with 172 additions and 40 deletions
+50 -20
View File
@@ -721,28 +721,59 @@ function syncKeySlTpFields() {
if (tpEl) tpEl.style.display = mode === "trend_manual" ? "" : "none"; if (tpEl) tpEl.style.display = mode === "trend_manual" ? "" : "none";
} }
function wireKeyMonitorSegGroup(groupId, hiddenInputId, onChange) {
const group = document.getElementById(groupId);
const hidden = document.getElementById(hiddenInputId);
if (!group || !hidden) return;
group.addEventListener("click", (ev) => {
const btn = ev.target.closest && ev.target.closest(".matrix-seg-btn");
if (!btn) return;
group.querySelectorAll(".matrix-seg-btn").forEach((b) => b.classList.remove("is-active"));
btn.classList.add("is-active");
hidden.value = btn.getAttribute("data-value") || "";
if (onChange) onChange();
});
}
function initKeyMonitorSegGroups() {
wireKeyMonitorSegGroup("keyMonitorTypeSeg", "keyMonitorTypeInput");
wireKeyMonitorSegGroup("keyDirectionSeg", "keyDirectionInput");
wireKeyMonitorSegGroup("keySlTpModeSeg", "keySlTpModeInput", syncKeySlTpFields);
}
function renderKeyMonitorActiveList(rows) {
const target = document.getElementById("keyMonitorActive");
if (!target) return;
target.innerHTML = "";
if (!rows.length) {
target.innerHTML = '<div class="matrix-dim">暂无监控中的关键位</div>';
return;
}
rows.forEach((row) => {
const prev = row.preview || {};
const checks = prev.checks || {};
const gateOk = prev.gate_ok ? "门控通过" : "门控未过";
const gateClass = prev.gate_ok ? "key-gate-ok" : "key-gate-pending";
const dir = row.direction === "long" ? "多" : "空";
const modeLabel = row.sl_tp_mode === "trend_manual" ? "趋势" : "标准";
const el = document.createElement("div");
el.className = "item matrix-list-item key-monitor-row";
el.innerHTML = `
<div class="key-monitor-row-body">
<div><strong>${row.symbol}</strong> ${dir} · ${row.monitor_type} · ${modeLabel}</div>
<div class="matrix-dim">上 ${row.upper} / 下 ${row.lower} · <span class="${gateClass}">${gateOk}</span> · 确认 ${checks.confirm_close != null ? checks.confirm_close : "—"}</div>
</div>
<button type="button" class="matrix-btn ghost key-del-btn key-monitor-del" data-id="${row.id}">删除并归档</button>
`;
target.appendChild(el);
});
}
function renderKeyMonitors(data) { function renderKeyMonitors(data) {
const rule = document.getElementById("keyMonitorRule"); const rule = document.getElementById("keyMonitorRule");
if (rule && data.rule_text) rule.textContent = `// ${data.rule_text}`; if (rule && data.rule_text) rule.textContent = `// ${data.rule_text}`;
const active = data.active || []; renderKeyMonitorActiveList(data.active || []);
renderItems("keyMonitorActive", active, (row) => {
const prev = row.preview || {};
const checks = prev.checks || {};
const gateOk = prev.gate_ok ? '<span style="color:#4cd97f">门控通过</span>' : '<span style="color:#8892b0">门控未过</span>';
const dir = row.direction === "long" ? "做多" : "做空";
const modeLabel = row.sl_tp_mode === "trend_manual" ? "趋势突破" : "标准突破";
return `
<div class="matrix-list-item-head"><strong>${row.symbol}</strong> ${dir} · ${row.monitor_type} · ${modeLabel}</div>
<div class="matrix-dim">上 ${row.upper} / 下 ${row.lower} · 保本 ${row.breakeven_enabled ? "开" : "关"}</div>
<div class="matrix-dim">${gateOk} · 确认收盘 ${checks.confirm_close != null ? checks.confirm_close : "—"}</div>
<button type="button" class="matrix-btn ghost key-del-btn" data-id="${row.id}" style="margin-top:6px">删除并归档</button>
`;
});
if (!active.length) {
const t = document.getElementById("keyMonitorActive");
if (t) t.innerHTML = '<div class="matrix-dim">暂无监控中的关键位</div>';
}
const hist = data.history || []; const hist = data.history || [];
renderItems("keyMonitorHistory", hist.slice(0, 80), (h) => { renderItems("keyMonitorHistory", hist.slice(0, 80), (h) => {
@@ -804,8 +835,7 @@ async function addKeyMonitor() {
} }
function wireKeyMonitorPanel() { function wireKeyMonitorPanel() {
const modeSel = document.getElementById("keySlTpModeInput"); initKeyMonitorSegGroups();
if (modeSel) modeSel.addEventListener("change", syncKeySlTpFields);
syncKeySlTpFields(); syncKeySlTpFields();
const addBtn = document.getElementById("keyAddBtn"); const addBtn = document.getElementById("keyAddBtn");
if (addBtn) addBtn.addEventListener("click", addKeyMonitor); if (addBtn) addBtn.addEventListener("click", addKeyMonitor);
+100
View File
@@ -1249,6 +1249,87 @@ pre {
box-shadow: -6px 0 20px rgba(255, 0, 170, 0.12); box-shadow: -6px 0 20px rgba(255, 0, 170, 0.12);
} }
/* Key monitor — segmented toggles + compact active rows */
.matrix-seg-group {
display: inline-flex;
flex-shrink: 0;
border: 1px solid rgba(0, 255, 213, 0.28);
border-radius: 2px;
overflow: hidden;
}
.matrix-seg-btn {
border: none;
background: rgba(0, 12, 10, 0.75);
color: #3d8f7a;
font-family: inherit;
font-size: 10px;
letter-spacing: 0.06em;
padding: 8px 10px;
cursor: pointer;
transition: background 0.15s ease, color 0.15s ease;
}
.matrix-seg-btn:not(:last-child) {
border-right: 1px solid rgba(0, 255, 213, 0.2);
}
.matrix-seg-btn:hover {
color: #00ffd5;
background: rgba(0, 255, 213, 0.08);
}
.matrix-seg-btn.is-active {
color: #0a1512;
background: rgba(0, 255, 213, 0.85);
font-weight: 600;
}
.key-monitor-form .key-monitor-field {
min-width: 5.5rem;
flex: 0 1 auto;
}
.key-monitor-form .key-monitor-tp {
min-width: 5rem;
}
.key-monitor-form .key-monitor-check {
flex-shrink: 0;
}
.key-monitor-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
padding: 8px 10px !important;
}
.key-monitor-row-body {
flex: 1;
min-width: 0;
line-height: 1.35;
}
.key-monitor-row .key-monitor-del {
flex-shrink: 0;
margin: 0;
padding: 5px 8px;
font-size: 9px;
letter-spacing: 0.04em;
white-space: nowrap;
min-height: auto;
}
.key-gate-ok {
color: #4cd97f;
}
.key-gate-pending {
color: #8892b0;
}
.matrix-card { .matrix-card {
transition: transform 0.2s ease, box-shadow 0.2s ease; transition: transform 0.2s ease, box-shadow 0.2s ease;
} }
@@ -1681,6 +1762,25 @@ body.matrix-theme {
min-height: 44px; min-height: 44px;
} }
.key-monitor-form .matrix-seg-group {
width: fit-content;
align-self: flex-start;
}
.key-monitor-form .matrix-seg-btn {
min-height: 36px;
padding: 8px 12px;
}
.key-monitor-form .key-monitor-add {
width: 100%;
}
.key-monitor-row .key-monitor-del {
padding: 4px 6px;
font-size: 8px;
}
.matrix-grid { .matrix-grid {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
+22 -20
View File
@@ -134,28 +134,30 @@
<div class="matrix-panel-body"> <div class="matrix-panel-body">
<p class="matrix-hint">GEMMA 漏斗仅供参考;在此录入上/下沿。箱体突破与收敛突破均支持「标准突破」或「趋势突破」(无 1.5H 方案)。</p> <p class="matrix-hint">GEMMA 漏斗仅供参考;在此录入上/下沿。箱体突破与收敛突破均支持「标准突破」或「趋势突破」(无 1.5H 方案)。</p>
<p id="keyMonitorRule" class="matrix-hint matrix-dim">// 规则加载中…</p> <p id="keyMonitorRule" class="matrix-hint matrix-dim">// 规则加载中…</p>
<div class="matrix-form-row matrix-form-row-wrap"> <div class="matrix-form-row matrix-form-row-wrap key-monitor-form">
<input id="keySymbolInput" class="matrix-input" type="text" placeholder="BTC 或 BTC/USDT" style="min-width:7rem" /> <input id="keySymbolInput" class="matrix-input key-monitor-field" type="text" placeholder="BTC 或 BTC/USDT" />
<select id="keyMonitorTypeInput" class="matrix-input"> <div class="matrix-seg-group" id="keyMonitorTypeSeg" aria-label="结构类型">
<option value="箱体突破">箱体突破</option> <button type="button" class="matrix-seg-btn is-active" data-value="箱体突破">箱体</button>
<option value="收敛突破">收敛突破</option> <button type="button" class="matrix-seg-btn" data-value="收敛突破">收敛</button>
</select> </div>
<select id="keyDirectionInput" class="matrix-input"> <input type="hidden" id="keyMonitorTypeInput" value="箱体突破" />
<option value="">方向</option> <div class="matrix-seg-group" id="keyDirectionSeg" aria-label="方向">
<option value="long">做多</option> <button type="button" class="matrix-seg-btn" data-value="long">做多</button>
<option value="short">做空</option> <button type="button" class="matrix-seg-btn" data-value="short">做空</button>
</select> </div>
<input id="keyUpperInput" class="matrix-input" type="number" step="any" placeholder="上沿/阻力" style="min-width:6rem" /> <input type="hidden" id="keyDirectionInput" value="" />
<input id="keyLowerInput" class="matrix-input" type="number" step="any" placeholder="沿/支撑" style="min-width:6rem" /> <input id="keyUpperInput" class="matrix-input key-monitor-field" type="number" step="any" placeholder="沿/阻力" />
<select id="keySlTpModeInput" class="matrix-input" title="止盈止损方案"> <input id="keyLowerInput" class="matrix-input key-monitor-field" type="number" step="any" placeholder="下沿/支撑" />
<option value="standard">标准突破</option> <div class="matrix-seg-group" id="keySlTpModeSeg" aria-label="突破方案">
<option value="trend_manual">趋势突破</option> <button type="button" class="matrix-seg-btn is-active" data-value="standard">标准</button>
</select> <button type="button" class="matrix-seg-btn" data-value="trend_manual">趋势</button>
<input id="keyManualTpInput" class="matrix-input" type="number" step="any" placeholder="趋势止盈价" style="min-width:6rem;display:none" /> </div>
<label class="matrix-hint" style="display:inline-flex;align-items:center;gap:4px"> <input type="hidden" id="keySlTpModeInput" value="standard" />
<input id="keyManualTpInput" class="matrix-input key-monitor-field key-monitor-tp" type="number" step="any" placeholder="趋势止盈价" style="display:none" />
<label class="matrix-hint key-monitor-check" style="display:inline-flex;align-items:center;gap:4px">
<input id="keyBreakevenInput" type="checkbox" /> 移动保本 <input id="keyBreakevenInput" type="checkbox" /> 移动保本
</label> </label>
<button type="button" id="keyAddBtn" class="matrix-btn matrix-btn-pulse">添加监控</button> <button type="button" id="keyAddBtn" class="matrix-btn matrix-btn-pulse key-monitor-add">添加监控</button>
</div> </div>
<p id="keyMonitorSaveMsg" class="matrix-msg"></p> <p id="keyMonitorSaveMsg" class="matrix-msg"></p>
<div class="matrix-two-col" style="margin-top:12px"> <div class="matrix-two-col" style="margin-top:12px">