fix: sync live TP/SL to position cards after entrust changes

Use exchange TP/SL for display and DB sync on price_snapshot polls, refresh instance UI cells on each tick, and merge live values into hub monitor board.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-09 11:06:27 +08:00
parent 7cb55f6557
commit f7d94f67d7
12 changed files with 291 additions and 89 deletions
+22 -10
View File
@@ -541,19 +541,11 @@
</div>
<div class="pos-cell">
<span class="pos-label">止损</span>
{% if o.stop_loss %}
<span class="pos-value">{{ price_fmt(o.symbol, o.stop_loss) }}</span>
{% else %}
<span class="pos-value pos-val-dash"></span>
{% endif %}
<span class="pos-value" id="order-plan-sl-{{ o.id }}">{{ price_fmt(o.symbol, o.stop_loss) if o.stop_loss else '—' }}</span>
</div>
<div class="pos-cell">
<span class="pos-label">止盈</span>
{% if o.take_profit %}
<span class="pos-value">{{ price_fmt(o.symbol, o.take_profit) }}</span>
{% else %}
<span class="pos-value pos-val-dash"></span>
{% endif %}
<span class="pos-value" id="order-plan-tp-{{ o.id }}">{{ price_fmt(o.symbol, o.take_profit) if o.take_profit else '—' }}</span>
</div>
<div class="pos-cell">
<span class="pos-label">盈亏比</span>
@@ -1914,6 +1906,24 @@ function paintBreakevenBadge(orderId, secured){
if(!wrap) return;
wrap.style.display = secured ? "inline-flex" : "none";
}
function paintPlanTpslDisplay(orderId, snap){
if(!snap) return;
const card = document.getElementById(`order-row-${orderId}`);
const slEl = document.getElementById(`order-plan-sl-${orderId}`);
const tpEl = document.getElementById(`order-plan-tp-${orderId}`);
const slRaw = snap.stop_loss_raw != null && snap.stop_loss_raw !== "" ? snap.stop_loss_raw : snap.stop_loss;
const tpRaw = snap.take_profit_raw != null && snap.take_profit_raw !== "" ? snap.take_profit_raw : snap.take_profit;
const slDisp = snap.stop_loss_display || (slRaw != null && slRaw !== "" ? formatPriceForInput(slRaw) : null);
const tpDisp = snap.take_profit_display || (tpRaw != null && tpRaw !== "" ? formatPriceForInput(tpRaw) : null);
if(slEl) slEl.innerText = slDisp || "—";
if(tpEl) tpEl.innerText = tpDisp || "—";
if(card){
if(slRaw != null && slRaw !== "") card.setAttribute("data-plan-sl", formatPriceForInput(slRaw));
else if(slDisp) card.setAttribute("data-plan-sl", slDisp);
if(tpRaw != null && tpRaw !== "") card.setAttribute("data-plan-tp", formatPriceForInput(tpRaw));
else if(tpDisp) card.setAttribute("data-plan-tp", tpDisp);
}
}
function paintPriceTrend(el, key, value){
if(!el) return;
@@ -2001,6 +2011,7 @@ function refreshPriceSnapshot(){
}
paintBreakevenBadge(o.id, o.sl_breakeven_secured);
if(o.exchange_tpsl) paintExchangeTpslRow(o.id, o.exchange_tpsl);
paintPlanTpslDisplay(o.id, o);
});
}).catch(()=>{});
}
@@ -2239,6 +2250,7 @@ function refreshPriceSnapshotConditional(){
if(rrEl) rrEl.innerText = formatRrRatio(o.rr_ratio);
paintBreakevenBadge(o.id, o.sl_breakeven_secured);
paintExchangeTpslRow(o.id, o.exchange_tpsl || {});
paintPlanTpslDisplay(o.id, o);
});
}
}).catch(()=>{});