中控手机端使用独立底栏与卡片总览,电脑端布局保持不变。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-10-05 19:19:56 +08:00
parent 2dcb191c2f
commit cf347e7b6b
7 changed files with 554 additions and 19 deletions
+103 -5
View File
@@ -298,6 +298,104 @@
);
}
function isHubPhone() {
return (
document.documentElement.classList.contains("hub-phone-html") ||
!!(document.body && document.body.classList.contains("hub-phone"))
);
}
function openClient(instanceId) {
if (!instanceId) return;
fetch("/api/instances/" + encodeURIComponent(instanceId) + "/open_url")
.then(function (r) {
return r.json();
})
.then(function (d) {
if (d && d.url) {
window.location.href = d.url;
return;
}
window.location.href = "/desk?id=" + encodeURIComponent(instanceId);
})
.catch(function () {
window.location.href = "/desk?id=" + encodeURIComponent(instanceId);
});
}
function bindOverviewActions(root) {
if (!root) return;
root.querySelectorAll("[data-close-opt]").forEach(function (btn) {
btn.addEventListener("click", function () {
requestClose(btn);
});
});
root.querySelectorAll("[data-open-inst]").forEach(function (btn) {
btn.addEventListener("click", function () {
openClient(btn.getAttribute("data-open-inst"));
});
});
}
function renderPhoneCard(row) {
const snap = row.snapshot || {};
const inst = snap.instance || {};
const pnl =
snap.pnl && snap.pnl.unrealized_usdt != null
? snap.pnl.unrealized_usdt
: snap.upl_total_usdc;
const brief = snap.positions_brief || snap.positions || [];
const cond = activeCondOrder(snap);
const online = !!row.online;
const m = String(inst.mode || "").toLowerCase();
const modeHtml =
m === "sim" || m === "live"
? '<span class="overview-mode-tag overview-mode-tag--' + m + '">' + escapeHtml(m) + "</span>"
: '<span class="muted">' + escapeHtml(inst.mode || "—") + "</span>";
const err = row.error
? '<div class="muted hub-phone-card-err">错误: ' + escapeHtml(row.error) + "</div>"
: "";
return (
'<article class="hub-phone-card">' +
'<div class="hub-phone-card-head">' +
"<strong>" +
escapeHtml(row.name || "") +
"</strong>" +
(online ? '<span class="status-on">在线</span>' : '<span class="status-off">离线</span>') +
modeHtml +
condTagHtml(cond) +
"</div>" +
err +
'<div class="hub-phone-card-kpis">' +
'<div><span class="muted">浮盈</span>' +
fmtPnlHtml(pnl) +
"</div>" +
'<div><span class="muted">权利金</span>' +
premiumCell(snap) +
"</div>" +
'<div><span class="muted">占比</span>' +
premiumRatioCell(snap) +
"</div>" +
"</div>" +
'<div class="hub-phone-card-pos">' +
positionSummary(brief, cond) +
"</div>" +
'<div class="hub-phone-card-exit muted">出场 ' +
(brief.length ? escapeHtml(formatExitBrief(brief[0])) : "—") +
"</div>" +
'<div class="hub-phone-card-liq">' +
bidLiquiditySummary(brief) +
"</div>" +
'<div class="hub-phone-card-actions">' +
'<button type="button" class="btn" data-open-inst="' +
escapeHtml(String(row.id || "")) +
'">打开</button>' +
closeActionButtons(brief, row.id, online) +
"</div>" +
"</article>"
);
}
function renderRow(row) {
const snap = row.snapshot || {};
const inst = snap.instance || {};
@@ -594,6 +692,10 @@
if (!list.length) {
grid.innerHTML =
'<p class="muted">暂无启用实例,请先到「实例」添加.</p>';
} else if (isHubPhone()) {
grid.innerHTML =
'<div class="hub-phone-cards">' + list.map(renderPhoneCard).join("") + "</div>";
bindOverviewActions(grid);
} else {
grid.innerHTML =
'<div class="overview-table-wrap"><table class="overview-table">' +
@@ -602,11 +704,7 @@
"</tr></thead><tbody>" +
list.map(renderRow).join("") +
"</tbody></table></div>";
grid.querySelectorAll("[data-close-opt]").forEach(function (btn) {
btn.addEventListener("click", function () {
requestClose(btn);
});
});
bindOverviewActions(grid);
}
if (status) {
const s = summarizeOverview(list);