feat: hub setting to hide account balances and PnL in monitor
Persist show_account_pnl in hub_settings.json; refine key monitor panel layout with right-aligned live stats and scrollable history (max 8 rows). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -67,6 +67,7 @@ from settings_store import (
|
|||||||
enabled_exchanges,
|
enabled_exchanges,
|
||||||
env_force_disabled_ids,
|
env_force_disabled_ids,
|
||||||
load_settings,
|
load_settings,
|
||||||
|
normalize_display_prefs,
|
||||||
save_settings,
|
save_settings,
|
||||||
)
|
)
|
||||||
from hub_web_auth import (
|
from hub_web_auth import (
|
||||||
@@ -676,8 +677,13 @@ def api_get_settings():
|
|||||||
return load_settings()
|
return load_settings()
|
||||||
|
|
||||||
|
|
||||||
|
class SettingsDisplayBody(BaseModel):
|
||||||
|
show_account_pnl: bool = True
|
||||||
|
|
||||||
|
|
||||||
class SettingsBody(BaseModel):
|
class SettingsBody(BaseModel):
|
||||||
exchanges: list[dict] = Field(default_factory=list)
|
exchanges: list[dict] = Field(default_factory=list)
|
||||||
|
display: SettingsDisplayBody | None = None
|
||||||
|
|
||||||
|
|
||||||
@app.post("/api/settings")
|
@app.post("/api/settings")
|
||||||
@@ -691,7 +697,11 @@ def api_save_settings(body: SettingsBody):
|
|||||||
row["enabled"] = False
|
row["enabled"] = False
|
||||||
row.pop("env_disabled", None)
|
row.pop("env_disabled", None)
|
||||||
to_save.append(row)
|
to_save.append(row)
|
||||||
save_settings({"version": 1, "exchanges": to_save})
|
existing = load_settings()
|
||||||
|
display = normalize_display_prefs(existing.get("display"))
|
||||||
|
if body.display is not None:
|
||||||
|
display = normalize_display_prefs(body.display.model_dump())
|
||||||
|
save_settings({"version": 1, "exchanges": to_save, "display": display})
|
||||||
return {"ok": True, "settings": load_settings()}
|
return {"ok": True, "settings": load_settings()}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ from pathlib import Path
|
|||||||
DIR = Path(__file__).resolve().parent
|
DIR = Path(__file__).resolve().parent
|
||||||
SETTINGS_PATH = DIR / "hub_settings.json"
|
SETTINGS_PATH = DIR / "hub_settings.json"
|
||||||
|
|
||||||
|
DEFAULT_DISPLAY = {
|
||||||
|
"show_account_pnl": True,
|
||||||
|
}
|
||||||
|
|
||||||
DEFAULT_EXCHANGES = [
|
DEFAULT_EXCHANGES = [
|
||||||
{
|
{
|
||||||
"id": "0",
|
"id": "0",
|
||||||
@@ -65,8 +69,20 @@ def env_force_disabled_ids() -> set[str]:
|
|||||||
return _ids_from_csv(raw)
|
return _ids_from_csv(raw)
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_display_prefs(raw: dict | None) -> dict:
|
||||||
|
out = dict(DEFAULT_DISPLAY)
|
||||||
|
if isinstance(raw, dict):
|
||||||
|
if "show_account_pnl" in raw:
|
||||||
|
out["show_account_pnl"] = bool(raw.get("show_account_pnl"))
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
def load_settings() -> dict:
|
def load_settings() -> dict:
|
||||||
data = {"exchanges": [dict(x) for x in DEFAULT_EXCHANGES], "version": 1}
|
data = {
|
||||||
|
"exchanges": [dict(x) for x in DEFAULT_EXCHANGES],
|
||||||
|
"version": 1,
|
||||||
|
"display": dict(DEFAULT_DISPLAY),
|
||||||
|
}
|
||||||
if SETTINGS_PATH.is_file():
|
if SETTINGS_PATH.is_file():
|
||||||
try:
|
try:
|
||||||
loaded = json.loads(SETTINGS_PATH.read_text(encoding="utf-8"))
|
loaded = json.loads(SETTINGS_PATH.read_text(encoding="utf-8"))
|
||||||
@@ -74,6 +90,7 @@ def load_settings() -> dict:
|
|||||||
data = loaded
|
data = loaded
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
data["display"] = normalize_display_prefs(data.get("display"))
|
||||||
force_off = env_force_disabled_ids()
|
force_off = env_force_disabled_ids()
|
||||||
for ex in data.get("exchanges") or []:
|
for ex in data.get("exchanges") or []:
|
||||||
if str(ex.get("id")) in force_off:
|
if str(ex.get("id")) in force_off:
|
||||||
|
|||||||
@@ -2164,6 +2164,28 @@ button.btn-sm {
|
|||||||
text-transform: none;
|
text-transform: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.settings-display-panel {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding: 14px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-display-title {
|
||||||
|
margin: 0 0 10px;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-display-chk {
|
||||||
|
font-size: 0.88rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-display-hint {
|
||||||
|
margin: 8px 0 0;
|
||||||
|
font-size: 0.78rem;
|
||||||
|
color: var(--muted);
|
||||||
|
line-height: 1.45;
|
||||||
|
}
|
||||||
|
|
||||||
.settings-card {
|
.settings-card {
|
||||||
background: var(--panel);
|
background: var(--panel);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
|
|||||||
@@ -2,6 +2,25 @@
|
|||||||
const toast = document.getElementById("toast");
|
const toast = document.getElementById("toast");
|
||||||
let settingsCache = null;
|
let settingsCache = null;
|
||||||
let authState = { required: false, logged_in: true };
|
let authState = { required: false, logged_in: true };
|
||||||
|
|
||||||
|
function showAccountPnlPref() {
|
||||||
|
const d = settingsCache && settingsCache.display;
|
||||||
|
if (!d || d.show_account_pnl === undefined) return true;
|
||||||
|
return !!d.show_account_pnl;
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncDisplayPrefsUI(data) {
|
||||||
|
const cb = document.getElementById("pref-show-account-pnl");
|
||||||
|
if (!cb) return;
|
||||||
|
const show = data && data.display ? data.display.show_account_pnl : true;
|
||||||
|
cb.checked = show !== false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function positionTableHeadHtml(compact) {
|
||||||
|
const pnlTh = showAccountPnlPref() ? "<th>浮盈</th>" : "";
|
||||||
|
const cls = compact ? " data-table data-table-positions" : "";
|
||||||
|
return `<table class="data-table${cls}"><thead><tr><th>合约</th><th>方向</th><th>开仓价</th><th>标记价</th><th>张数</th>${pnlTh}<th>操作</th></tr></thead><tbody>`;
|
||||||
|
}
|
||||||
let tpslPending = null;
|
let tpslPending = null;
|
||||||
let lastMonitorRows = [];
|
let lastMonitorRows = [];
|
||||||
let expandedExchangeId = sessionStorage.getItem("hub_expanded_ex") || "";
|
let expandedExchangeId = sessionStorage.getItem("hub_expanded_ex") || "";
|
||||||
@@ -2218,7 +2237,11 @@
|
|||||||
<div class="pos-cell"><span class="pos-label">止盈</span><span class="pos-value${tpMonitored ? " pos-tp-program" : ""}">${formatTpCellValue(tp, tpMonitored, symbol, tickMap)}</span></div>
|
<div class="pos-cell"><span class="pos-label">止盈</span><span class="pos-value${tpMonitored ? " pos-tp-program" : ""}">${formatTpCellValue(tp, tpMonitored, symbol, tickMap)}</span></div>
|
||||||
<div class="pos-cell"><span class="pos-label">盈亏比</span><span class="pos-value">${rr != null ? fmt(rr, 2) + ":1" : "—"}</span></div>
|
<div class="pos-cell"><span class="pos-label">盈亏比</span><span class="pos-value">${rr != null ? fmt(rr, 2) + ":1" : "—"}</span></div>
|
||||||
<div class="pos-cell"><span class="pos-label">张数</span><span class="pos-value">${fmt(pos.contracts, 4)}</span></div>
|
<div class="pos-cell"><span class="pos-label">张数</span><span class="pos-value">${fmt(pos.contracts, 4)}</span></div>
|
||||||
<div class="pos-cell"><span class="pos-label">浮盈亏</span><span class="pos-value ${pnlFmt.cls}">${pnlText}</span></div>
|
${
|
||||||
|
showAccountPnlPref()
|
||||||
|
? `<div class="pos-cell"><span class="pos-label">浮盈亏</span><span class="pos-value ${pnlFmt.cls}">${pnlText}</span></div>`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="pos-footer">
|
<div class="pos-footer">
|
||||||
<span>杠杆: ${sizingFoot.leverage != null && sizingFoot.leverage !== "" ? esc(sizingFoot.leverage) + "x" : "—"}</span>
|
<span>杠杆: ${sizingFoot.leverage != null && sizingFoot.leverage !== "" ? esc(sizingFoot.leverage) + "x" : "—"}</span>
|
||||||
@@ -2324,13 +2347,16 @@
|
|||||||
<button type="button" class="btn-place-tpsl btn-sm ghost" data-ex-id="${esc(exchangeId)}" data-symbol="${symAttr}" data-side="${sideAttr}" data-contracts="${contractsAttr}" data-sl="${slAttr}" data-tp="${tpAttr}">委托</button>
|
<button type="button" class="btn-place-tpsl btn-sm ghost" data-ex-id="${esc(exchangeId)}" data-symbol="${symAttr}" data-side="${sideAttr}" data-contracts="${contractsAttr}" data-sl="${slAttr}" data-tp="${tpAttr}">委托</button>
|
||||||
<button type="button" class="btn-close-pos btn-sm danger" data-ex-id="${esc(exchangeId)}" data-symbol="${symAttr}" data-side="${sideAttr}">平仓</button>
|
<button type="button" class="btn-close-pos btn-sm danger" data-ex-id="${esc(exchangeId)}" data-symbol="${symAttr}" data-side="${sideAttr}">平仓</button>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
const pnlTd = showAccountPnlPref()
|
||||||
|
? `<td class="${pnlCls(x.unrealized_pnl)}">${fmt(x.unrealized_pnl, 2)}</td>`
|
||||||
|
: "";
|
||||||
return `<tr>
|
return `<tr>
|
||||||
<td class="td-symbol"><button type="button" class="btn-open-market sym-link" ${mktAttrs} title="打开行情区(含入场/止盈止损)">${esc(x.symbol)}</button>${symBeBadge}</td>
|
<td class="td-symbol"><button type="button" class="btn-open-market sym-link" ${mktAttrs} title="打开行情区(含入场/止盈止损)">${esc(x.symbol)}</button>${symBeBadge}</td>
|
||||||
<td class="${sideDirCls(x.side)}">${renderDirectionHtml(x.side)}</td>
|
<td class="${sideDirCls(x.side)}">${renderDirectionHtml(x.side)}</td>
|
||||||
<td class="td-entry">${fmtEntryPrice(x, tickMap)}</td>
|
<td class="td-entry">${fmtEntryPrice(x, tickMap)}</td>
|
||||||
<td>${fmtMarkPrice(x, tickMap)}</td>
|
<td>${fmtMarkPrice(x, tickMap)}</td>
|
||||||
<td>${fmt(x.contracts, 4)}</td>
|
<td>${fmt(x.contracts, 4)}</td>
|
||||||
<td class="${pnlCls(x.unrealized_pnl)}">${fmt(x.unrealized_pnl, 2)}</td>
|
${pnlTd}
|
||||||
<td class="td-actions">${actionCell}</td>
|
<td class="td-actions">${actionCell}</td>
|
||||||
</tr>`;
|
</tr>`;
|
||||||
}
|
}
|
||||||
@@ -2354,7 +2380,7 @@
|
|||||||
);
|
);
|
||||||
return `<div class="pos-block">
|
return `<div class="pos-block">
|
||||||
<div class="table-scroll">
|
<div class="table-scroll">
|
||||||
<table class="data-table"><thead><tr><th>合约</th><th>方向</th><th>开仓价</th><th>标记价</th><th>张数</th><th>浮盈</th><th>操作</th></tr></thead><tbody>
|
${positionTableHeadHtml(false)}
|
||||||
${rowHtml}
|
${rowHtml}
|
||||||
</tbody></table>
|
</tbody></table>
|
||||||
</div>
|
</div>
|
||||||
@@ -2442,13 +2468,14 @@
|
|||||||
)
|
)
|
||||||
.join("");
|
.join("");
|
||||||
return `<div class="pos-table-wrap table-scroll">
|
return `<div class="pos-table-wrap table-scroll">
|
||||||
<table class="data-table data-table-positions"><thead><tr><th>合约</th><th>方向</th><th>开仓价</th><th>标记价</th><th>张数</th><th>浮盈</th><th>操作</th></tr></thead><tbody>
|
${positionTableHeadHtml(true)}
|
||||||
${rows}
|
${rows}
|
||||||
</tbody></table>
|
</tbody></table>
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderAccountStatRow(row, ag) {
|
function renderAccountStatRow(row, ag) {
|
||||||
|
if (!showAccountPnlPref()) return "";
|
||||||
const upnl = ag.total_unrealized_pnl;
|
const upnl = ag.total_unrealized_pnl;
|
||||||
return `<div class="stat-row">
|
return `<div class="stat-row">
|
||||||
<div class="stat-box"><div class="stat-label">资金账户</div><div class="stat-value">${fmt(row.funding_usdt, 2)} <small style="font-size:12px;color:var(--muted)">U</small></div></div>
|
<div class="stat-box"><div class="stat-label">资金账户</div><div class="stat-value">${fmt(row.funding_usdt, 2)} <small style="font-size:12px;color:var(--muted)">U</small></div></div>
|
||||||
@@ -2763,7 +2790,11 @@
|
|||||||
<span class="status-dot ${dotCls}" aria-hidden="true"></span>
|
<span class="status-dot ${dotCls}" aria-hidden="true"></span>
|
||||||
<span class="hub-tile-name">${esc(row.name)}</span>
|
<span class="hub-tile-name">${esc(row.name)}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="hub-tile-pnl ${pnlCls(upnl)}">${fmt(upnl, 2)} <small>U</small></div>
|
${
|
||||||
|
showAccountPnlPref()
|
||||||
|
? `<div class="hub-tile-pnl ${pnlCls(upnl)}">${fmt(upnl, 2)} <small>U</small></div>`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
<div class="hub-tile-meta">${esc(posLine)}</div>
|
<div class="hub-tile-meta">${esc(posLine)}</div>
|
||||||
${strategyStats}
|
${strategyStats}
|
||||||
<div class="hub-tile-foot">UPD ${esc(tsShort)}</div>
|
<div class="hub-tile-foot">UPD ${esc(tsShort)}</div>
|
||||||
@@ -2977,6 +3008,7 @@
|
|||||||
function loadSettingsUI() {
|
function loadSettingsUI() {
|
||||||
loadSettingsMetaLine();
|
loadSettingsMetaLine();
|
||||||
loadSettings().then((data) => {
|
loadSettings().then((data) => {
|
||||||
|
syncDisplayPrefsUI(data);
|
||||||
renderSettingsList(data);
|
renderSettingsList(data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -3010,8 +3042,12 @@
|
|||||||
|
|
||||||
function collectSettingsFromUI() {
|
function collectSettingsFromUI() {
|
||||||
const rows = [...document.querySelectorAll("#settings-list .settings-card")];
|
const rows = [...document.querySelectorAll("#settings-list .settings-card")];
|
||||||
|
const pnlCb = document.getElementById("pref-show-account-pnl");
|
||||||
return {
|
return {
|
||||||
version: 1,
|
version: 1,
|
||||||
|
display: {
|
||||||
|
show_account_pnl: pnlCb ? !!pnlCb.checked : true,
|
||||||
|
},
|
||||||
exchanges: rows.map((card) => {
|
exchanges: rows.map((card) => {
|
||||||
const caps = [];
|
const caps = [];
|
||||||
if (card.querySelector(".cap-key").checked) caps.push("key");
|
if (card.querySelector(".cap-key").checked) caps.push("key");
|
||||||
@@ -3045,11 +3081,13 @@
|
|||||||
showToast("设置已保存(已写入 hub_settings.json)");
|
showToast("设置已保存(已写入 hub_settings.json)");
|
||||||
if (j.settings) {
|
if (j.settings) {
|
||||||
settingsCache = j.settings;
|
settingsCache = j.settings;
|
||||||
|
syncDisplayPrefsUI(j.settings);
|
||||||
renderSettingsList(j.settings);
|
renderSettingsList(j.settings);
|
||||||
loadSettingsMetaLine();
|
loadSettingsMetaLine();
|
||||||
} else {
|
} else {
|
||||||
await loadSettingsUI();
|
await loadSettingsUI();
|
||||||
}
|
}
|
||||||
|
if (lastMonitorRows.length) renderMonitorGrid(lastMonitorRows);
|
||||||
} else showToast("保存失败", true);
|
} else showToast("保存失败", true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
showToast(String(e), true);
|
showToast(String(e), true);
|
||||||
@@ -3526,9 +3564,13 @@
|
|||||||
initAuth().then((ok) => {
|
initAuth().then((ok) => {
|
||||||
if (!ok) return;
|
if (!ok) return;
|
||||||
initShellNav();
|
initShellNav();
|
||||||
|
loadSettings()
|
||||||
|
.then((data) => {
|
||||||
|
syncDisplayPrefsUI(data);
|
||||||
|
})
|
||||||
|
.catch(() => {})
|
||||||
|
.finally(() => {
|
||||||
setActiveNav();
|
setActiveNav();
|
||||||
if (currentPage() === "settings") {
|
});
|
||||||
loadSettings().catch(() => {});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -466,6 +466,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
<p id="settings-meta-line" class="settings-meta-line"></p>
|
<p id="settings-meta-line" class="settings-meta-line"></p>
|
||||||
|
<div class="settings-display-panel card">
|
||||||
|
<h3 class="settings-display-title">监控区显示</h3>
|
||||||
|
<label class="chk-label settings-display-chk">
|
||||||
|
<input type="checkbox" id="pref-show-account-pnl" checked />
|
||||||
|
显示资金账户、交易账户与浮动盈亏
|
||||||
|
</label>
|
||||||
|
<p class="settings-display-hint">关闭后监控区不显示上述数值;保存至 hub_settings.json,换浏览器同样生效。</p>
|
||||||
|
</div>
|
||||||
<div class="toolbar">
|
<div class="toolbar">
|
||||||
<button type="button" id="btn-settings-save" class="primary">保存设置</button>
|
<button type="button" id="btn-settings-save" class="primary">保存设置</button>
|
||||||
<button type="button" id="btn-settings-add">添加交易所</button>
|
<button type="button" id="btn-settings-add">添加交易所</button>
|
||||||
|
|||||||
@@ -9,14 +9,19 @@
|
|||||||
.key-panel-scroll.panel-scroll.pos-list{
|
.key-panel-scroll.panel-scroll.pos-list{
|
||||||
display:block;
|
display:block;
|
||||||
flex:1 1 auto;
|
flex:1 1 auto;
|
||||||
min-height:200px;
|
min-height:0;
|
||||||
max-height:none;
|
|
||||||
overflow-x:hidden;
|
overflow-x:hidden;
|
||||||
overflow-y:auto;
|
overflow-y:auto;
|
||||||
padding-bottom:6px;
|
padding-bottom:6px;
|
||||||
-webkit-overflow-scrolling:touch;
|
-webkit-overflow-scrolling:touch;
|
||||||
scrollbar-gutter:stable;
|
scrollbar-gutter:stable;
|
||||||
}
|
}
|
||||||
|
.key-monitor-panel-scroll{min-height:200px}
|
||||||
|
.key-history-panel-scroll{
|
||||||
|
flex:0 0 auto;
|
||||||
|
max-height:calc(8 * 42px + 7 * 8px);
|
||||||
|
min-height:calc(3 * 42px + 2 * 8px);
|
||||||
|
}
|
||||||
.key-panel-scroll.panel-scroll.pos-list .key-row-collapse{flex-shrink:0}
|
.key-panel-scroll.panel-scroll.pos-list .key-row-collapse{flex-shrink:0}
|
||||||
.key-panel-scroll.panel-scroll.pos-list::-webkit-scrollbar{width:8px}
|
.key-panel-scroll.panel-scroll.pos-list::-webkit-scrollbar{width:8px}
|
||||||
.key-panel-scroll.panel-scroll.pos-list::-webkit-scrollbar-thumb{background:#3a4660;border-radius:4px}
|
.key-panel-scroll.panel-scroll.pos-list::-webkit-scrollbar-thumb{background:#3a4660;border-radius:4px}
|
||||||
@@ -25,16 +30,26 @@
|
|||||||
.key-row-collapse:not([open]){overflow:hidden}
|
.key-row-collapse:not([open]){overflow:hidden}
|
||||||
.key-row-collapse[open]{overflow:visible}
|
.key-row-collapse[open]{overflow:visible}
|
||||||
.key-row-collapse+.key-row-collapse{margin-top:8px}
|
.key-row-collapse+.key-row-collapse{margin-top:8px}
|
||||||
.key-row-collapse-summary{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;padding:10px 12px;cursor:pointer;list-style:none;font-size:.8rem;color:#c5cde0;line-height:1.45}
|
.key-row-collapse-summary{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 12px;cursor:pointer;list-style:none;font-size:.8rem;color:#c5cde0;line-height:1.45}
|
||||||
.key-row-collapse-summary::-webkit-details-marker{display:none}
|
.key-row-collapse-summary::-webkit-details-marker{display:none}
|
||||||
.key-row-collapse-summary::before{content:"▸";flex:0 0 auto;color:#6d7a99;margin-top:1px;transition:transform .15s ease}
|
.key-row-collapse-summary::before{content:"▸";flex:0 0 auto;color:#6d7a99;transition:transform .15s ease}
|
||||||
.key-row-collapse[open]>.key-row-collapse-summary::before{transform:rotate(90deg)}
|
.key-row-collapse[open]>.key-row-collapse-summary::before{transform:rotate(90deg)}
|
||||||
.key-row-summary-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px}
|
.key-row-summary-main{flex:1;min-width:0;display:flex;align-items:center;justify-content:space-between;gap:10px}
|
||||||
.key-row-summary-title{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
|
.key-row-summary-title{display:flex;align-items:center;gap:6px;flex:0 1 auto;flex-wrap:wrap;min-width:0}
|
||||||
.key-row-summary-title strong{font-size:.88rem;color:#fff}
|
.key-row-summary-title strong{font-size:.88rem;color:#fff}
|
||||||
.key-row-summary-line{color:#9aa8c4;font-size:.76rem;word-break:break-word}
|
.key-row-summary-line{color:#9aa8c4;font-size:.76rem;word-break:break-word}
|
||||||
.key-row-summary-live{color:#8fc8ff;font-size:.74rem}
|
.key-row-summary-live{
|
||||||
|
flex:1 1 auto;
|
||||||
|
min-width:0;
|
||||||
|
color:#8fc8ff;
|
||||||
|
font-size:.72rem;
|
||||||
|
text-align:right;
|
||||||
|
white-space:nowrap;
|
||||||
|
overflow:hidden;
|
||||||
|
text-overflow:ellipsis;
|
||||||
|
}
|
||||||
.key-row-summary-live.key-row-summary-pending{color:#4cd97f;font-weight:600}
|
.key-row-summary-live.key-row-summary-pending{color:#4cd97f;font-weight:600}
|
||||||
|
.key-history-panel-scroll .key-row-summary-main{justify-content:flex-start}
|
||||||
.key-row-summary-actions{flex:0 0 auto;display:flex;gap:6px;align-items:center}
|
.key-row-summary-actions{flex:0 0 auto;display:flex;gap:6px;align-items:center}
|
||||||
.key-row-collapse-body{padding:0 12px 16px;border-top:1px solid #232b3d}
|
.key-row-collapse-body{padding:0 12px 16px;border-top:1px solid #232b3d}
|
||||||
.key-row-collapse-body .pos-meta{margin-top:10px;margin-bottom:10px}
|
.key-row-collapse-body .pos-meta{margin-top:10px;margin-bottom:10px}
|
||||||
@@ -150,7 +165,7 @@
|
|||||||
{% include 'key_monitor_rule_tips.html' %}
|
{% include 'key_monitor_rule_tips.html' %}
|
||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
<div class="panel-scroll pos-list key-panel-scroll">
|
<div class="panel-scroll pos-list key-panel-scroll key-monitor-panel-scroll">
|
||||||
{% for k in key %}
|
{% for k in key %}
|
||||||
<details class="key-row-collapse" id="key-row-{{ k.id }}">
|
<details class="key-row-collapse" id="key-row-{{ k.id }}">
|
||||||
<summary class="key-row-collapse-summary">
|
<summary class="key-row-collapse-summary">
|
||||||
@@ -200,7 +215,7 @@
|
|||||||
<div class="card">
|
<div class="card">
|
||||||
<h2 style="margin-bottom:8px">关键位历史</h2>
|
<h2 style="margin-bottom:8px">关键位历史</h2>
|
||||||
<div class="sub" style="font-size:.72rem;color:#8892b0;margin-bottom:8px">失效或已结案的关键位 · 点击展开详情</div>
|
<div class="sub" style="font-size:.72rem;color:#8892b0;margin-bottom:8px">失效或已结案的关键位 · 点击展开详情</div>
|
||||||
<div class="panel-scroll pos-list key-panel-scroll">
|
<div class="panel-scroll pos-list key-panel-scroll key-history-panel-scroll">
|
||||||
{% for h in key_history %}
|
{% for h in key_history %}
|
||||||
<details class="key-row-collapse key-history-{{ key_history_outcome_kind(h) }}">
|
<details class="key-row-collapse key-history-{{ key_history_outcome_kind(h) }}">
|
||||||
<summary class="key-row-collapse-summary">
|
<summary class="key-row-collapse-summary">
|
||||||
|
|||||||
Reference in New Issue
Block a user