修复持仓监控页长时间空白:品种推荐改为异步加载。

页面先渲染三卡片,推荐表并行拉行情,持仓与推荐分别通过 API 加载。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-24 10:34:34 +08:00
parent 55d95b4c39
commit 38a38cb51d
4 changed files with 68 additions and 21 deletions
+57 -2
View File
@@ -1,7 +1,16 @@
(function () {
var list = document.getElementById('position-live-list');
var recommendList = document.getElementById('recommend-list');
var pollTimer = null;
function runWhenReady(fn) {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', fn);
} else {
fn();
}
}
function fmtNum(v, digits) {
if (v === null || v === undefined) return '--';
return Number(v).toFixed(digits === undefined ? 2 : digits);
@@ -110,7 +119,10 @@
function pollPositions() {
if (!list) return;
fetch('/api/trading/live')
.then(function (r) { return r.json(); })
.then(function (r) {
if (!r.ok) throw new Error('HTTP ' + r.status);
return r.json();
})
.then(function (data) {
var cap = document.getElementById('cap-display');
if (cap && data.capital != null) cap.textContent = Number(data.capital).toFixed(2);
@@ -145,6 +157,48 @@
});
}
function badgeClass(status) {
if (status === 'ok') return 'profit';
if (status === 'blocked') return 'loss';
return 'planned';
}
function buildRecommendRow(r) {
return (
'<tr class="rec-' + (r.status || '') + '">' +
'<td><strong>' + (r.name || '') + '</strong> <span class="text-muted">' + (r.ths || '') + '</span></td>' +
'<td>' + (r.exchange || '') + '</td>' +
'<td>' + (r.price != null ? r.price : '—') + '</td>' +
'<td>' + (r.margin_one_lot != null ? r.margin_one_lot : '—') + '</td>' +
'<td>' + (r.min_capital_one_lot != null ? r.min_capital_one_lot : '—') + '</td>' +
'<td><span class="badge ' + badgeClass(r.status) + '">' + (r.status_label || '') + '</span></td>' +
'</tr>'
);
}
function loadRecommendations() {
if (!recommendList) return;
fetch('/api/recommend/list')
.then(function (r) {
if (!r.ok) throw new Error('HTTP ' + r.status);
return r.json();
})
.then(function (data) {
if (!data.ok) throw new Error(data.error || 'load failed');
var recCap = document.getElementById('rec-capital');
if (recCap && data.capital != null) recCap.textContent = Number(data.capital).toFixed(2);
var rows = data.rows || [];
if (!rows.length) {
recommendList.innerHTML = '<tr><td colspan="6" class="empty-hint">暂无推荐数据</td></tr>';
return;
}
recommendList.innerHTML = rows.map(buildRecommendRow).join('');
})
.catch(function () {
recommendList.innerHTML = '<tr><td colspan="6" class="empty-hint text-loss">品种推荐加载失败,请刷新页面</td></tr>';
});
}
var btnConnect = document.getElementById('btn-ctp-connect');
if (btnConnect) {
btnConnect.addEventListener('click', function () {
@@ -163,8 +217,9 @@
});
}
document.addEventListener('DOMContentLoaded', function () {
runWhenReady(function () {
pollPositions();
loadRecommendations();
pollTimer = setInterval(pollPositions, 3000);
});
})();