Merge orders and positions into one card and hide stale pending when CTP is off.

Stop showing DB pending orders while disconnected, invalidate session cache when CTP is down, and add a local DB clear script without embedded credentials.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-26 19:24:24 +08:00
parent 631aa2c0ab
commit ddfe2a52aa
5 changed files with 223 additions and 41 deletions
+10 -1
View File
@@ -2,8 +2,17 @@
/* 持仓监控页 — 与 split-grid(关键位监控)同宽,全端自适应 */
.trade-page{width:100%}
.trade-split{margin-bottom:1.25rem}
.trade-split .card{min-height:320px}
.trade-split .card{min-height:360px}
.trade-split .trade-card#order{margin-bottom:.75rem}
.trading-live-body{gap:0}
.trading-live-section{padding-bottom:.5rem}
.trading-live-section.trading-live-positions{
margin-top:.65rem;padding-top:.75rem;border-top:1px solid var(--card-border);
}
.trading-live-subtitle{
font-size:.82rem;font-weight:600;color:var(--text-muted);
margin:0 0 .45rem .15rem;letter-spacing:.02em;
}
.sync-badge{font-size:.72rem;font-weight:400;margin-left:.35rem}
.trade-top-bar{
display:flex;flex-wrap:wrap;gap:.65rem 1rem;
+24 -7
View File
@@ -47,7 +47,7 @@
var REC_COLSPAN = 18;
var marketNavEnabled = !!window.MARKET_NAV_ENABLED;
var productCategories = window.PRODUCT_CATEGORIES || [];
var POS_CACHE_KEY = 'qihuo_trading_live_v4';
var POS_CACHE_KEY = 'qihuo_trading_live_v5';
function runWhenReady(fn) {
if (document.readyState === 'loading') {
@@ -133,9 +133,17 @@
function savePosCache(data) {
try {
if (!data || !data.rows || !data.rows.length) {
var prev = loadPosCache();
if (prev && prev.rows && prev.rows.length) return;
if (!data) return;
var connected = data.ctp_status && data.ctp_status.connected;
if (!connected) {
sessionStorage.removeItem(POS_CACHE_KEY);
return;
}
if (!data.rows || !data.rows.length) {
if (!data.active_orders || !data.active_orders.length) {
sessionStorage.removeItem(POS_CACHE_KEY);
return;
}
}
sessionStorage.setItem(POS_CACHE_KEY, JSON.stringify(data));
} catch (e) { /* quota */ }
@@ -159,10 +167,17 @@
return !!(msg && (msg.indexOf('不可达') >= 0 || msg.indexOf('Connection refused') >= 0 || msg.indexOf('timed out') >= 0));
}
function applyActiveOrders(orders) {
function applyActiveOrders(orders, data) {
if (!orderList) return;
orders = orders || [];
if (!orders.length) {
var connected = data && data.ctp_status && data.ctp_status.connected;
if (!connected) {
var hint = (data && data.ctp_status && data.ctp_status.disabled_hint) ||
'CTP 未连接,委托以柜台为准';
orderList.innerHTML = '<div class="empty-hint text-muted">' + hint + '</div>';
return;
}
orderList.innerHTML = '<div class="empty-hint">暂无委托。</div>';
return;
}
@@ -213,7 +228,7 @@
riskBadge.textContent = data.risk_status.status_label || '';
riskBadge.className = 'badge ' + (data.risk_status.can_trade ? 'profit' : 'loss');
}
applyActiveOrders(data.active_orders || []);
applyActiveOrders(data.active_orders || [], data);
if (!list) return;
var rows = (data.rows || []).filter(function (row) {
return row.order_state !== 'pending';
@@ -1592,7 +1607,9 @@
if (cached.ctp_status) {
cached.ctp_status = Object.assign({}, cached.ctp_status, { connecting: false });
}
applyPositionsData(cached);
if (cached.ctp_status && cached.ctp_status.connected) {
applyPositionsData(cached);
}
}
pollPositions();
connectPositionStream();