Fix position flicker, drop futures cooloff, prioritize startup display.
Preserve trading state when CTP memory is empty, bootstrap equity/positions on page load, stabilize risk status from DB monitors, and remove app-layer manual close cooling periods. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -422,10 +422,7 @@
|
||||
{ label: '持仓限制', value: active + ' / ' + (maxPos != null ? maxPos : '—') },
|
||||
{ label: '日持仓限制', value: dailyOpens + ' / ' + (dailyPosLim != null ? dailyPosLim : '—') },
|
||||
{ label: '日交易风险', value: dailyRiskText },
|
||||
{ label: '手动平仓(冷静期触发)', value: manualCnt + ' / ' + (manualLim != null ? manualLim : '—') },
|
||||
{ label: '冷静期(默认)', value: fmtHours(lim.cooling_hours_manual) },
|
||||
{ label: '复盘后冷静', value: fmtHours(lim.cooling_hours_manual_journal) },
|
||||
{ label: '冷静剩余', value: fmtRemainSec(st.freeze_remaining_sec) },
|
||||
{ label: '手动平仓次数', value: manualCnt + ' / ' + (manualLim != null ? manualLim : '—') },
|
||||
{
|
||||
label: '综合保证金占比',
|
||||
valueHtml: riskMarginPctHtml(marginPct, rollMaxPct),
|
||||
@@ -862,6 +859,9 @@
|
||||
equityEl.textContent = fmtMoney(data.capital);
|
||||
}
|
||||
var rows = positionRows(data);
|
||||
if (!rows.length && data.sync_state === 'syncing' && lastPosRows.length) {
|
||||
rows = lastPosRows;
|
||||
}
|
||||
var sig = rows.map(function (r) {
|
||||
var key = r.key || r.position_key || ((r.symbol_code || '') + ':' + (r.direction || ''));
|
||||
return key + '|' + (isBreakevenLocked(r) ? '1' : '0') + '|' + slText(r) + '|' + tpText(r) + '|' + String(r.lots);
|
||||
|
||||
+51
-25
@@ -34,6 +34,7 @@
|
||||
var ctpConnecting = false;
|
||||
var ctpAutoConnectEnabled = true;
|
||||
var positionsRendered = false;
|
||||
var lastPosRowCount = 0;
|
||||
var selectedMaxLots = null;
|
||||
var recommendMaxByProduct = {};
|
||||
var recommendMaxByCode = {};
|
||||
@@ -63,6 +64,13 @@
|
||||
window.TRADE_FIXED_AMOUNT = cfg.fixed_amount;
|
||||
window.__RECOMMEND_ROWS__ = cfg.recommend_rows || [];
|
||||
if (cfg.session_clock) applySessionClock(cfg.session_clock);
|
||||
if (cfg.capital != null) {
|
||||
var capEl = document.getElementById('cap-display');
|
||||
if (capEl) capEl.textContent = Number(cfg.capital).toFixed(2);
|
||||
}
|
||||
if (cfg.bootstrap_live && (cfg.bootstrap_live.rows || cfg.bootstrap_live.capital != null)) {
|
||||
window.__BOOTSTRAP_LIVE__ = cfg.bootstrap_live;
|
||||
}
|
||||
} catch (e) { /* ignore */ }
|
||||
}
|
||||
|
||||
@@ -149,15 +157,15 @@
|
||||
function savePosCache(data) {
|
||||
try {
|
||||
if (!data) return;
|
||||
var connected = data.ctp_status && data.ctp_status.connected;
|
||||
if (!connected) {
|
||||
sessionStorage.removeItem(POS_CACHE_KEY);
|
||||
var hasRows = data.rows && data.rows.length;
|
||||
var hasOrders = data.active_orders && data.active_orders.length;
|
||||
if (!hasRows && !hasOrders && data.capital == null) {
|
||||
return;
|
||||
}
|
||||
if (!data.rows || !data.rows.length) {
|
||||
if (!data.active_orders || !data.active_orders.length) {
|
||||
sessionStorage.removeItem(POS_CACHE_KEY);
|
||||
return;
|
||||
if (!hasRows && lastPosRowCount > 0) {
|
||||
var prev = loadPosCache();
|
||||
if (prev && prev.rows && prev.rows.length) {
|
||||
data = Object.assign({}, data, { rows: prev.rows });
|
||||
}
|
||||
}
|
||||
sessionStorage.setItem(POS_CACHE_KEY, JSON.stringify(data));
|
||||
@@ -321,10 +329,22 @@
|
||||
if (ctpAutoConnectEnabled) tryAutoCtpReconnect();
|
||||
return;
|
||||
}
|
||||
var syncing = data.sync_state === 'syncing';
|
||||
var hadPos = lastPosRowCount > 0 || !!list.querySelector('.pos-card');
|
||||
if (syncing || hadPos) {
|
||||
if (syncBadge) {
|
||||
syncBadge.hidden = false;
|
||||
syncBadge.textContent = data.sync_label || '持仓同步中…';
|
||||
syncBadge.className = 'sync-badge text-accent';
|
||||
}
|
||||
return;
|
||||
}
|
||||
list.innerHTML = '<div class="empty-hint">暂无持仓。</div>';
|
||||
lastPosRowCount = 0;
|
||||
syncPositionListScroll(0);
|
||||
return;
|
||||
}
|
||||
lastPosRowCount = rows.length;
|
||||
if (!connected && ctpAutoConnectEnabled) {
|
||||
tryAutoCtpReconnect();
|
||||
}
|
||||
@@ -1926,12 +1946,16 @@
|
||||
lotsCalc.value = String(window.TRADE_FIXED_LOTS || 1);
|
||||
if (lotsInput) lotsInput.value = lotsCalc.value;
|
||||
}
|
||||
var cached = loadPosCache();
|
||||
if (cached) {
|
||||
if (cached.ctp_status) {
|
||||
cached.ctp_status = Object.assign({}, cached.ctp_status, { connecting: false });
|
||||
}
|
||||
if (cached.ctp_status && cached.ctp_status.connected) {
|
||||
var bootData = window.__BOOTSTRAP_LIVE__;
|
||||
if (bootData) {
|
||||
applyPositionsData(bootData);
|
||||
savePosCache(bootData);
|
||||
} else {
|
||||
var cached = loadPosCache();
|
||||
if (cached && ((cached.rows && cached.rows.length) || cached.capital != null)) {
|
||||
if (cached.ctp_status) {
|
||||
cached.ctp_status = Object.assign({}, cached.ctp_status, { connecting: false });
|
||||
}
|
||||
applyPositionsData(cached);
|
||||
}
|
||||
}
|
||||
@@ -1939,20 +1963,22 @@
|
||||
connectPositionStream();
|
||||
bindSlTpModal();
|
||||
initCtpOnLoad();
|
||||
connectRecommendStream();
|
||||
initRecommendSortControls();
|
||||
if (window.__RECOMMEND_ROWS__ && window.__RECOMMEND_ROWS__.length) {
|
||||
recRowsRaw = window.__RECOMMEND_ROWS__.slice();
|
||||
renderRecommendTable();
|
||||
}
|
||||
fetch('/api/recommend/list')
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (data) { if (data.ok) renderRecommendations(data); })
|
||||
.catch(function () {});
|
||||
updateSessionUi();
|
||||
updateRRDisplay();
|
||||
scheduleQuote();
|
||||
scheduleAutoCalc();
|
||||
setTimeout(function () {
|
||||
connectRecommendStream();
|
||||
initRecommendSortControls();
|
||||
if (window.__RECOMMEND_ROWS__ && window.__RECOMMEND_ROWS__.length) {
|
||||
recRowsRaw = window.__RECOMMEND_ROWS__.slice();
|
||||
renderRecommendTable();
|
||||
}
|
||||
fetch('/api/recommend/list')
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (data) { if (data.ok) renderRecommendations(data); })
|
||||
.catch(function () {});
|
||||
scheduleQuote();
|
||||
scheduleAutoCalc();
|
||||
}, 400);
|
||||
}
|
||||
|
||||
document.addEventListener('visibilitychange', function () {
|
||||
|
||||
Reference in New Issue
Block a user