Fix dashboard mobile load issues and simplify card layout.
Reduce poll pressure on phone/tablet, cache key prices, and handle live API errors gracefully. Rework mobile position and close cards with inline direction, compact P/L line, and detail modal. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1667,14 +1667,18 @@ def api_dashboard_live():
|
|||||||
from dashboard_lib import build_dashboard_payload
|
from dashboard_lib import build_dashboard_payload
|
||||||
|
|
||||||
_dashboard_sync_tick["n"] += 1
|
_dashboard_sync_tick["n"] += 1
|
||||||
sync_trades = _dashboard_sync_tick["n"] % 5 == 0
|
sync_trades = _dashboard_sync_tick["n"] % 15 == 0
|
||||||
payload = build_dashboard_payload(
|
try:
|
||||||
get_db=get_db,
|
payload = build_dashboard_payload(
|
||||||
get_setting=get_setting,
|
get_db=get_db,
|
||||||
fetch_price=fetch_price,
|
get_setting=get_setting,
|
||||||
sync_ctp_trades=sync_trades,
|
fetch_price=fetch_price,
|
||||||
)
|
sync_ctp_trades=sync_trades,
|
||||||
return jsonify(payload)
|
)
|
||||||
|
return jsonify(payload)
|
||||||
|
except Exception as exc:
|
||||||
|
app.logger.exception("dashboard live: %s", exc)
|
||||||
|
return jsonify({"ok": False, "error": "看板数据暂时不可用"}), 503
|
||||||
|
|
||||||
|
|
||||||
@app.route("/market")
|
@app.route("/market")
|
||||||
|
|||||||
+20
-1
@@ -10,6 +10,25 @@ from typing import Any, Callable, Optional
|
|||||||
from zoneinfo import ZoneInfo
|
from zoneinfo import ZoneInfo
|
||||||
|
|
||||||
_TZ = ZoneInfo("Asia/Shanghai")
|
_TZ = ZoneInfo("Asia/Shanghai")
|
||||||
|
_PRICE_CACHE: dict[str, tuple[float, float]] = {}
|
||||||
|
_PRICE_CACHE_TTL = 2.0
|
||||||
|
|
||||||
|
|
||||||
|
def _cached_fetch_price(
|
||||||
|
fetch_price: Callable[[str, str, str], Optional[float]],
|
||||||
|
sym: str,
|
||||||
|
market: str,
|
||||||
|
sina: str,
|
||||||
|
) -> Optional[float]:
|
||||||
|
key = sym or ""
|
||||||
|
now = datetime.now().timestamp()
|
||||||
|
hit = _PRICE_CACHE.get(key)
|
||||||
|
if hit and (now - hit[1]) < _PRICE_CACHE_TTL:
|
||||||
|
return hit[0]
|
||||||
|
price = fetch_price(sym, market, sina)
|
||||||
|
if price is not None:
|
||||||
|
_PRICE_CACHE[key] = (float(price), now)
|
||||||
|
return price
|
||||||
|
|
||||||
|
|
||||||
def _direction_label(direction: str) -> str:
|
def _direction_label(direction: str) -> str:
|
||||||
@@ -174,7 +193,7 @@ def build_dashboard_payload(
|
|||||||
sina = r["sina_code"] or ""
|
sina = r["sina_code"] or ""
|
||||||
upper = float(r["upper"] or 0)
|
upper = float(r["upper"] or 0)
|
||||||
lower = float(r["lower"] or 0)
|
lower = float(r["lower"] or 0)
|
||||||
price = fetch_price(sym, market, sina)
|
price = _cached_fetch_price(fetch_price, sym, market, sina)
|
||||||
dist_upper = dist_lower = None
|
dist_upper = dist_lower = None
|
||||||
if price is not None:
|
if price is not None:
|
||||||
dist_upper = round(upper - float(price), 2)
|
dist_upper = round(upper - float(price), 2)
|
||||||
|
|||||||
@@ -362,7 +362,8 @@ html:is([data-layout="phone"], .layout-phone) .dash-mobile-list {
|
|||||||
}
|
}
|
||||||
|
|
||||||
html:is([data-layout="phone"], .layout-phone) .dash-pos-table-wrap,
|
html:is([data-layout="phone"], .layout-phone) .dash-pos-table-wrap,
|
||||||
html:is([data-layout="phone"], .layout-phone) .dash-keys-table-wrap {
|
html:is([data-layout="phone"], .layout-phone) .dash-keys-table-wrap,
|
||||||
|
html:is([data-layout="phone"], .layout-phone) .dash-closes-table-wrap {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,6 +417,27 @@ html:is([data-layout="phone"], .layout-phone) .dash-keys-table-wrap {
|
|||||||
font-size: 0.78rem;
|
font-size: 0.78rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dash-mobile-item-summary {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
line-height: 1.45;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dash-mobile-item-summary .pnl-pos {
|
||||||
|
color: var(--profit);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dash-mobile-item-summary .pnl-neg {
|
||||||
|
color: var(--loss);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dash-mobile-item-title .badge {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
.dash-mobile-chevron {
|
.dash-mobile-chevron {
|
||||||
font-size: 0.72rem;
|
font-size: 0.72rem;
|
||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
|
|||||||
+167
-22
@@ -20,17 +20,21 @@
|
|||||||
var riskBodyEl = document.getElementById('dash-risk-body');
|
var riskBodyEl = document.getElementById('dash-risk-body');
|
||||||
var posMobileList = document.getElementById('dash-pos-mobile-list');
|
var posMobileList = document.getElementById('dash-pos-mobile-list');
|
||||||
var keysMobileList = document.getElementById('dash-keys-mobile-list');
|
var keysMobileList = document.getElementById('dash-keys-mobile-list');
|
||||||
|
var closesMobileList = document.getElementById('dash-closes-mobile-list');
|
||||||
var detailModal = document.getElementById('dash-detail-modal');
|
var detailModal = document.getElementById('dash-detail-modal');
|
||||||
var detailTitleEl = document.getElementById('dash-detail-title');
|
var detailTitleEl = document.getElementById('dash-detail-title');
|
||||||
var detailGridEl = document.getElementById('dash-detail-grid');
|
var detailGridEl = document.getElementById('dash-detail-grid');
|
||||||
var detailCloseBtn = document.getElementById('dash-detail-close');
|
var detailCloseBtn = document.getElementById('dash-detail-close');
|
||||||
|
|
||||||
var pollTimer = null;
|
var pollTimer = null;
|
||||||
|
var pollInFlight = false;
|
||||||
|
var pollFailStreak = 0;
|
||||||
var positionSource = null;
|
var positionSource = null;
|
||||||
var posRowCache = {};
|
var posRowCache = {};
|
||||||
var posRenderSig = '';
|
var posRenderSig = '';
|
||||||
var posMobileCache = {};
|
var posMobileCache = {};
|
||||||
var keysMobileCache = {};
|
var keysMobileCache = {};
|
||||||
|
var closesMobileCache = {};
|
||||||
var lastPosRows = [];
|
var lastPosRows = [];
|
||||||
var lastKeyRows = [];
|
var lastKeyRows = [];
|
||||||
var lastKeyIds = '';
|
var lastKeyIds = '';
|
||||||
@@ -181,6 +185,77 @@
|
|||||||
return '—';
|
return '—';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fmtMobileLots(v) {
|
||||||
|
var n = Number(v);
|
||||||
|
if (isNaN(n)) return '—';
|
||||||
|
if (Math.abs(n - Math.round(n)) < 0.001) return Math.round(n) + '手';
|
||||||
|
return fmtNum(n) + '手';
|
||||||
|
}
|
||||||
|
|
||||||
|
function fmtMobilePrice(v) {
|
||||||
|
if (v == null || v === '') return '—';
|
||||||
|
var n = Number(v);
|
||||||
|
if (isNaN(n)) return '—';
|
||||||
|
if (Math.abs(n - Math.round(n)) < 0.001) return String(Math.round(n));
|
||||||
|
return fmtNum(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fmtMobilePnlNum(v) {
|
||||||
|
if (v == null || v === '') return '—';
|
||||||
|
var n = Number(v);
|
||||||
|
if (isNaN(n)) return '—';
|
||||||
|
var abs = Math.abs(n);
|
||||||
|
var s = Math.abs(abs - Math.round(abs)) < 0.01 ? String(Math.round(abs)) : fmtNum(abs);
|
||||||
|
if (n > 0) return s;
|
||||||
|
if (n < 0) return '-' + s;
|
||||||
|
return '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
function mobilePnlSpanHtml(v) {
|
||||||
|
return '<span class="' + pnlClass(v) + '">' + escHtml(fmtMobilePnlNum(v)) + '</span>';
|
||||||
|
}
|
||||||
|
|
||||||
|
function mobileSummaryHtml(lots, priceLabel, price, pnl) {
|
||||||
|
return fmtMobileLots(lots) + ' ' + priceLabel + ' ' + fmtMobilePrice(price) +
|
||||||
|
' 盈亏 ' + mobilePnlSpanHtml(pnl);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mobileSymbolTitleHtml(row) {
|
||||||
|
var name = row.symbol_name || row.symbol || '';
|
||||||
|
var code = row.symbol_code || '';
|
||||||
|
if (!code && row.symbol && String(row.symbol).toLowerCase() !== String(name).toLowerCase()) {
|
||||||
|
code = row.symbol;
|
||||||
|
}
|
||||||
|
var exchange = row.symbol_exchange || '';
|
||||||
|
var mainBadge = row.symbol_is_main
|
||||||
|
? ' <span class="badge planned dash-main-badge">主力</span>' : '';
|
||||||
|
var titleInner = escHtml(name);
|
||||||
|
if (exchange) {
|
||||||
|
titleInner += ' <span class="dash-symbol-ex text-muted">' + escHtml(exchange) + '</span>';
|
||||||
|
}
|
||||||
|
titleInner += mainBadge;
|
||||||
|
titleInner += breakevenBadgeHtml(row);
|
||||||
|
if (code && String(name).toLowerCase() !== String(code).toLowerCase()) {
|
||||||
|
titleInner += ' <span class="text-accent">' + escHtml(code) + '</span> ' + directionBadgeHtml(row);
|
||||||
|
} else if (!name && code) {
|
||||||
|
titleInner = (exchange
|
||||||
|
? '<span class="dash-symbol-ex text-muted">' + escHtml(exchange) + '</span> '
|
||||||
|
: '') + '<span class="text-accent">' + escHtml(code) + '</span> ' + directionBadgeHtml(row);
|
||||||
|
} else {
|
||||||
|
titleInner += ' ' + directionBadgeHtml(row);
|
||||||
|
}
|
||||||
|
return titleInner;
|
||||||
|
}
|
||||||
|
|
||||||
|
function mobileItemFootHtml(summaryHtml) {
|
||||||
|
return (
|
||||||
|
'<div class="dash-mobile-item-foot">' +
|
||||||
|
'<span class="dash-mobile-item-summary">' + summaryHtml + '</span>' +
|
||||||
|
'<span class="dash-mobile-chevron">查看详情 ›</span>' +
|
||||||
|
'</div>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function symbolCellHtml(row) {
|
function symbolCellHtml(row) {
|
||||||
var name = row.symbol_name || row.symbol || '';
|
var name = row.symbol_name || row.symbol || '';
|
||||||
var code = row.symbol_code || '';
|
var code = row.symbol_code || '';
|
||||||
@@ -440,12 +515,40 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderClosesMobile(closes) {
|
||||||
|
if (!closesMobileList) return;
|
||||||
|
if (!closes || !closes.length) {
|
||||||
|
closesMobileList.innerHTML = '<div class="dash-mobile-empty">暂无平仓记录</div>';
|
||||||
|
closesMobileCache = {};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
closesMobileCache = {};
|
||||||
|
closesMobileList.innerHTML = closes.map(function (c) {
|
||||||
|
var net = c.pnl_net != null ? c.pnl_net : c.pnl;
|
||||||
|
closesMobileCache[String(c.id)] = c;
|
||||||
|
var summary = mobileSummaryHtml(c.lots, '平仓', c.close_price, net);
|
||||||
|
return (
|
||||||
|
'<button type="button" class="dash-mobile-item" data-close-id="' + c.id + '">' +
|
||||||
|
'<div class="dash-mobile-item-head">' +
|
||||||
|
'<div class="dash-mobile-item-title">' + mobileSymbolTitleHtml(c) + '</div>' +
|
||||||
|
'</div>' +
|
||||||
|
mobileItemFootHtml(summary) +
|
||||||
|
'</button>'
|
||||||
|
);
|
||||||
|
}).join('');
|
||||||
|
}
|
||||||
|
|
||||||
function renderCloses(closes) {
|
function renderCloses(closes) {
|
||||||
if (!closesBody) return;
|
if (!closesBody) return;
|
||||||
if (!closes || !closes.length) {
|
if (!closes || !closes.length) {
|
||||||
closesBody.innerHTML = '<tr><td colspan="8" class="text-muted">暂无平仓记录</td></tr>';
|
closesBody.innerHTML = '<tr><td colspan="8" class="text-muted">暂无平仓记录</td></tr>';
|
||||||
|
if (isPhoneLayout() && closesMobileList) {
|
||||||
|
closesMobileList.innerHTML = '<div class="dash-mobile-empty">暂无平仓记录</div>';
|
||||||
|
}
|
||||||
|
closesMobileCache = {};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (isPhoneLayout()) renderClosesMobile(closes);
|
||||||
closesBody.innerHTML = closes.map(function (c) {
|
closesBody.innerHTML = closes.map(function (c) {
|
||||||
var pc = pnlClass(c.pnl_net != null ? c.pnl_net : c.pnl);
|
var pc = pnlClass(c.pnl_net != null ? c.pnl_net : c.pnl);
|
||||||
return (
|
return (
|
||||||
@@ -489,6 +592,10 @@
|
|||||||
if (!closes || !closes.length) {
|
if (!closes || !closes.length) {
|
||||||
closesBody.innerHTML = '<tr><td colspan="8" class="text-muted">暂无平仓记录</td></tr>';
|
closesBody.innerHTML = '<tr><td colspan="8" class="text-muted">暂无平仓记录</td></tr>';
|
||||||
lastCloseHeadId = null;
|
lastCloseHeadId = null;
|
||||||
|
if (isPhoneLayout() && closesMobileList) {
|
||||||
|
closesMobileList.innerHTML = '<div class="dash-mobile-empty">暂无平仓记录</div>';
|
||||||
|
}
|
||||||
|
closesMobileCache = {};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var headId = closes[0].id;
|
var headId = closes[0].id;
|
||||||
@@ -531,6 +638,22 @@
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function closeDetailItems(c) {
|
||||||
|
var net = c.pnl_net != null ? c.pnl_net : c.pnl;
|
||||||
|
return [
|
||||||
|
{ label: '品种', value: (c.symbol_name || c.symbol || '') + (c.symbol_code ? ' ' + c.symbol_code : '') },
|
||||||
|
{ label: '方向', html: directionBadgeHtml(c) },
|
||||||
|
{ label: '手数', value: String(c.lots) },
|
||||||
|
{ label: '开仓价', value: fmtNum(c.entry_price) },
|
||||||
|
{ label: '平仓价', value: fmtNum(c.close_price) },
|
||||||
|
{ label: '盈亏', html: '<span class="' + pnlClass(c.pnl) + '">' + fmtPnl(c.pnl) + '</span>' },
|
||||||
|
{ label: '净盈亏', html: '<span class="' + pnlClass(net) + '">' + fmtPnl(net) + '</span>' },
|
||||||
|
{ label: '手续费', value: c.fee != null ? fmtMoney(c.fee) : '—' },
|
||||||
|
{ label: '平仓时间', value: c.close_time || '—' },
|
||||||
|
{ label: '结果', value: c.result || '—' },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
function renderPositionsMobile(rows) {
|
function renderPositionsMobile(rows) {
|
||||||
if (!posMobileList) return;
|
if (!posMobileList) return;
|
||||||
if (!rows.length) {
|
if (!rows.length) {
|
||||||
@@ -542,19 +665,16 @@
|
|||||||
posMobileList.innerHTML = rows.map(function (r) {
|
posMobileList.innerHTML = rows.map(function (r) {
|
||||||
var key = r.key || r.position_key || ((r.symbol_code || '') + ':' + (r.direction || ''));
|
var key = r.key || r.position_key || ((r.symbol_code || '') + ':' + (r.direction || ''));
|
||||||
posMobileCache[key] = r;
|
posMobileCache[key] = r;
|
||||||
var title = symbolCellHtml(r) + ' ' + directionBadgeHtml(r);
|
var summary = mobileSummaryHtml(
|
||||||
var meta = fmtNum(r.lots) + ' 手 · 现价 ' +
|
r.lots, '现价', r.current_price, r.float_pnl
|
||||||
(r.current_price != null ? fmtNum(r.current_price) : '—');
|
);
|
||||||
return (
|
return (
|
||||||
'<button type="button" class="dash-mobile-item" data-pos-key="' + escHtml(key) + '">' +
|
'<button type="button" class="dash-mobile-item" data-pos-key="' + escHtml(key) + '">' +
|
||||||
'<div class="dash-mobile-item-head">' +
|
'<div class="dash-mobile-item-head">' +
|
||||||
'<div class="dash-mobile-item-title">' + title + '</div>' +
|
'<div class="dash-mobile-item-title">' + mobileSymbolTitleHtml(r) + '</div>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<div class="dash-mobile-item-meta">' + escHtml(meta) + '</div>' +
|
mobileItemFootHtml(summary) +
|
||||||
'<div class="dash-mobile-item-foot">' +
|
'</button>'
|
||||||
'<span class="' + pnlClass(r.float_pnl) + '">' + fmtPnl(r.float_pnl) + '</span>' +
|
|
||||||
'<span class="dash-mobile-chevron">查看详情 ›</span>' +
|
|
||||||
'</div></button>'
|
|
||||||
);
|
);
|
||||||
}).join('');
|
}).join('');
|
||||||
}
|
}
|
||||||
@@ -566,15 +686,11 @@
|
|||||||
posMobileCache[key] = r;
|
posMobileCache[key] = r;
|
||||||
var btn = posMobileList.querySelector('[data-pos-key="' + key + '"]');
|
var btn = posMobileList.querySelector('[data-pos-key="' + key + '"]');
|
||||||
if (!btn) return;
|
if (!btn) return;
|
||||||
var metaEl = btn.querySelector('.dash-mobile-item-meta');
|
var summaryEl = btn.querySelector('.dash-mobile-item-summary');
|
||||||
var pnlEl = btn.querySelector('.dash-mobile-item-foot span:first-child');
|
if (summaryEl) {
|
||||||
if (metaEl) {
|
summaryEl.innerHTML = mobileSummaryHtml(
|
||||||
metaEl.textContent = fmtNum(r.lots) + ' 手 · 现价 ' +
|
r.lots, '现价', r.current_price, r.float_pnl
|
||||||
(r.current_price != null ? fmtNum(r.current_price) : '—');
|
);
|
||||||
}
|
|
||||||
if (pnlEl) {
|
|
||||||
pnlEl.textContent = fmtPnl(r.float_pnl);
|
|
||||||
pnlEl.className = pnlClass(r.float_pnl);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -646,6 +762,15 @@
|
|||||||
openDetailModal(k.symbol_name || k.symbol || '关键位', keyDetailItems(k));
|
openDetailModal(k.symbol_name || k.symbol || '关键位', keyDetailItems(k));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (closesMobileList) {
|
||||||
|
closesMobileList.addEventListener('click', function (ev) {
|
||||||
|
var btn = ev.target.closest('[data-close-id]');
|
||||||
|
if (!btn) return;
|
||||||
|
var c = closesMobileCache[btn.getAttribute('data-close-id')];
|
||||||
|
if (!c) return;
|
||||||
|
openDetailModal(c.symbol_name || c.symbol || '平仓记录', closeDetailItems(c));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderPositions(rows) {
|
function renderPositions(rows) {
|
||||||
@@ -760,21 +885,40 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function pollIntervalMs() {
|
||||||
|
if (isPhoneLayout() || isTabletLayout()) return 3000;
|
||||||
|
return 2000;
|
||||||
|
}
|
||||||
|
|
||||||
function pollDashboard() {
|
function pollDashboard() {
|
||||||
|
if (pollInFlight) return;
|
||||||
|
pollInFlight = true;
|
||||||
fetch('/api/dashboard/live')
|
fetch('/api/dashboard/live')
|
||||||
.then(function (r) {
|
.then(function (r) {
|
||||||
if (!r.ok) throw new Error('HTTP ' + r.status);
|
if (!r.ok) throw new Error('HTTP ' + r.status);
|
||||||
return r.json();
|
return r.json();
|
||||||
})
|
})
|
||||||
.then(function (data) {
|
.then(function (data) {
|
||||||
if (!data.ok) return;
|
pollFailStreak = 0;
|
||||||
|
if (!data.ok) {
|
||||||
|
if (updatedEl) updatedEl.textContent = data.error || '看板数据暂不可用';
|
||||||
|
return;
|
||||||
|
}
|
||||||
applyAccount(data);
|
applyAccount(data);
|
||||||
applyRisk(data.risk, data.account);
|
applyRisk(data.risk, data.account);
|
||||||
applyKeys(data.keys || []);
|
applyKeys(data.keys || []);
|
||||||
applyCloses(data.closes || []);
|
applyCloses(data.closes || []);
|
||||||
})
|
})
|
||||||
.catch(function () {
|
.catch(function () {
|
||||||
if (updatedEl) updatedEl.textContent = '看板数据加载失败';
|
pollFailStreak += 1;
|
||||||
|
if (updatedEl) {
|
||||||
|
updatedEl.textContent = pollFailStreak >= 3
|
||||||
|
? '看板连接失败,正在重试…'
|
||||||
|
: '看板数据加载失败';
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(function () {
|
||||||
|
pollInFlight = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -800,14 +944,15 @@
|
|||||||
positionSource.close();
|
positionSource.close();
|
||||||
positionSource = null;
|
positionSource = null;
|
||||||
}
|
}
|
||||||
setTimeout(connectPositionStream, 3000);
|
var delay = (isPhoneLayout() || isTabletLayout()) ? 8000 : 3000;
|
||||||
|
setTimeout(connectPositionStream, delay);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function startPolling() {
|
function startPolling() {
|
||||||
if (pollTimer) clearInterval(pollTimer);
|
if (pollTimer) clearInterval(pollTimer);
|
||||||
pollDashboard();
|
pollDashboard();
|
||||||
pollTimer = setInterval(pollDashboard, 1000);
|
pollTimer = setInterval(pollDashboard, pollIntervalMs());
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopPolling() {
|
function stopPolling() {
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
* 专有软件 — 未经授权禁止复制、传播、转售。
|
* 专有软件 — 未经授权禁止复制、传播、转售。
|
||||||
* 详见 LICENSE.zh-CN.txt
|
* 详见 LICENSE.zh-CN.txt
|
||||||
*/
|
*/
|
||||||
var CACHE_VERSION = 'qihuo-v9';
|
var CACHE_VERSION = 'qihuo-v10';
|
||||||
var STATIC_CACHE = CACHE_VERSION + '-static';
|
var STATIC_CACHE = CACHE_VERSION + '-static';
|
||||||
var STATIC_ASSETS = [
|
var STATIC_ASSETS = [
|
||||||
'/static/css/base.css',
|
'/static/css/base.css',
|
||||||
|
|||||||
@@ -99,7 +99,8 @@
|
|||||||
|
|
||||||
<div class="card dashboard-section">
|
<div class="card dashboard-section">
|
||||||
<h2>平仓记录</h2>
|
<h2>平仓记录</h2>
|
||||||
<div class="card-scroll">
|
<div class="dash-mobile-list" id="dash-closes-mobile-list"></div>
|
||||||
|
<div class="card-scroll dash-closes-table-wrap">
|
||||||
<table class="dashboard-table" id="dash-closes-table">
|
<table class="dashboard-table" id="dash-closes-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
Reference in New Issue
Block a user