feat: unify key monitor UI with one-line summary and expandable details across all exchanges
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -322,6 +322,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="top-nav">
|
||||
<a href="/key_monitor" class="{% if page == 'key_monitor' %}active{% endif %}">关键位监控</a>
|
||||
<a href="/trade" class="{% if page == 'trade' %}active{% endif %}">交易执行</a>
|
||||
<a href="/strategy" class="{% if page in ('strategy', 'strategy_trend', 'strategy_roll') %}active{% endif %}">策略交易</a>
|
||||
<a href="/strategy/records" class="{% if page == 'strategy_records' %}active{% endif %}">策略交易记录</a>
|
||||
@@ -354,6 +355,8 @@
|
||||
<div class="export-bar">
|
||||
<span style="color:#9aa">数据导出(v{{ data_export_version }} CSV,UTF-8;交易记录含开仓类型列及交易所对齐字段):</span>
|
||||
<a href="/export/trade_records">交易记录</a>
|
||||
<a href="/export/key_monitors">关键位(当前)</a>
|
||||
<a href="/export/key_monitor_history">关键位历史</a>
|
||||
</div>
|
||||
<div class="stat-box">
|
||||
<div class="stat-item"><div class="label">交易所</div><div class="value">{{ exchange_display }}</div></div>
|
||||
@@ -368,7 +371,9 @@
|
||||
{% include 'gate_transfer_block.html' %}
|
||||
|
||||
<div class="grid">
|
||||
{% if page == 'trade' %}
|
||||
{% if page == 'key_monitor' %}
|
||||
{% include 'key_monitor_panel.html' %}
|
||||
{% elif page == 'trade' %}
|
||||
<div class="dual-panel-grid" style="grid-column:1/-1">
|
||||
<div class="card">
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap;margin-bottom:8px">
|
||||
@@ -1577,6 +1582,62 @@ if(journalForm){
|
||||
}
|
||||
}
|
||||
|
||||
function syncKeyMonitorFormFields(){
|
||||
const typeEl = document.querySelector('#key-form [name="type"]');
|
||||
const dirEl = document.getElementById("key-direction");
|
||||
const modeEl = document.getElementById("key-sl-tp-mode");
|
||||
const manualTp = document.getElementById("key-manual-tp");
|
||||
const beWrap = document.getElementById("key-breakeven-wrap");
|
||||
if(!typeEl) return;
|
||||
const t = (typeEl.value || "").trim();
|
||||
const autoTypes = new Set(["箱体突破","收敛突破"]);
|
||||
const fibTypes = new Set(["斐波回调0.618","斐波回调0.786"]);
|
||||
const fbTypes = new Set(["假突破"]);
|
||||
const rsTypes = new Set(["关键阻力位","关键支撑位"]);
|
||||
const showAuto = autoTypes.has(t);
|
||||
const showFb = fbTypes.has(t);
|
||||
const showBe = showAuto || fibTypes.has(t) || showFb;
|
||||
const showDir = !rsTypes.has(t);
|
||||
const upperEl = document.getElementById("key-upper");
|
||||
const lowerEl = document.getElementById("key-lower");
|
||||
const fbPriceEl = document.getElementById("key-fb-price");
|
||||
if(dirEl){
|
||||
dirEl.style.display = showDir ? "" : "none";
|
||||
dirEl.required = showDir;
|
||||
if(!showDir) dirEl.value = "";
|
||||
}
|
||||
if(modeEl) modeEl.style.display = showAuto ? "" : "none";
|
||||
if(manualTp){
|
||||
const trend = showAuto && modeEl && modeEl.value === "trend_manual";
|
||||
manualTp.style.display = trend ? "" : "none";
|
||||
manualTp.required = !!trend;
|
||||
}
|
||||
if(beWrap) beWrap.style.display = showBe ? "inline-flex" : "none";
|
||||
if(upperEl){
|
||||
upperEl.style.display = showFb ? "none" : "";
|
||||
upperEl.required = !showFb;
|
||||
if(showFb) upperEl.value = "";
|
||||
}
|
||||
if(lowerEl){
|
||||
lowerEl.style.display = showFb ? "none" : "";
|
||||
lowerEl.required = !showFb;
|
||||
if(showFb) lowerEl.value = "";
|
||||
}
|
||||
if(fbPriceEl){
|
||||
fbPriceEl.style.display = showFb ? "" : "none";
|
||||
fbPriceEl.required = showFb;
|
||||
if(!showFb) fbPriceEl.value = "";
|
||||
fbPriceEl.placeholder = (dirEl && dirEl.value === "short") ? "高点(阻力)" : ((dirEl && dirEl.value === "long") ? "低点(支撑)" : "做空填高点/做多填低点");
|
||||
}
|
||||
}
|
||||
const keyTypeSel = document.querySelector('#key-form [name="type"]');
|
||||
const keyModeSel = document.getElementById("key-sl-tp-mode");
|
||||
const keyDirSel = document.getElementById("key-direction");
|
||||
if(keyTypeSel) keyTypeSel.addEventListener("change", syncKeyMonitorFormFields);
|
||||
if(keyModeSel) keyModeSel.addEventListener("change", syncKeyMonitorFormFields);
|
||||
if(keyDirSel) keyDirSel.addEventListener("change", syncKeyMonitorFormFields);
|
||||
syncKeyMonitorFormFields();
|
||||
|
||||
const keyForm = document.getElementById("key-form");
|
||||
if(keyForm){
|
||||
keyForm.addEventListener("submit", (e)=>{
|
||||
@@ -1874,7 +1935,7 @@ function refreshPriceSnapshotConditional(){
|
||||
(data.key_prices || []).forEach(k=>{
|
||||
const pEl = document.getElementById(`key-price-${k.id}`);
|
||||
if(pEl){
|
||||
pEl.innerText = Number(k.price).toFixed(6);
|
||||
pEl.innerText = k.price_display || (Number.isFinite(Number(k.price)) ? Number(k.price).toFixed(6) : "-");
|
||||
paintPriceTrend(pEl, `k-${k.id}`, Number(k.price));
|
||||
}
|
||||
const upEl = document.getElementById(`key-up-diff-${k.id}`);
|
||||
@@ -1888,6 +1949,7 @@ function refreshPriceSnapshotConditional(){
|
||||
}
|
||||
const gateMetricEl = document.getElementById(`key-gate-metrics-${k.id}`);
|
||||
if(gateMetricEl) gateMetricEl.innerText = k.gate_metrics || "";
|
||||
if(typeof paintKeyMonitorSummary === "function") paintKeyMonitorSummary(k.id, k);
|
||||
});
|
||||
}
|
||||
if(page === "trade"){
|
||||
|
||||
Reference in New Issue
Block a user