Fix header funds flicker and unify settings page top bar.

Preserve SSR fund values when account_snapshot returns null, retry on failure, and show the same instance header panel on system settings.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-08 19:08:08 +08:00
parent 279648de56
commit 0d27e13275
8 changed files with 236 additions and 190 deletions
+104 -76
View File
@@ -1039,18 +1039,23 @@ function refreshOrderDefaults(){
}
function paintRealtimePnl(v){
const pnlEl = document.getElementById("realtime-pnl");
if(!pnlEl) return;
const nodes = document.querySelectorAll('[data-funds-field="realtime-pnl"]');
if(!nodes.length) return;
if(v === null || v === undefined || Number.isNaN(Number(v))){
pnlEl.innerText = "—";
pnlEl.classList.remove("pnl-pos", "pnl-neg");
nodes.forEach((pnlEl) => {
pnlEl.innerText = "—";
pnlEl.classList.remove("pnl-pos", "pnl-neg");
});
return;
}
const n = Number(v);
const sign = n > 0 ? "+" : "";
pnlEl.innerText = `${sign}${n.toFixed(2)}U`;
pnlEl.classList.toggle("pnl-pos", n > 0);
pnlEl.classList.toggle("pnl-neg", n < 0);
const text = `${sign}${n.toFixed(2)}U`;
nodes.forEach((pnlEl) => {
pnlEl.innerText = text;
pnlEl.classList.toggle("pnl-pos", n > 0);
pnlEl.classList.toggle("pnl-neg", n < 0);
});
}
function sumOrdersFloatPnl(orders){
if(!orders || !orders.length) return null;
@@ -1091,81 +1096,104 @@ function formatOptionsFundingLabel(usdc, usdt) {
return parts.length ? parts.join(" · ") : "—";
}
function setFundsFieldText(field, text){
if(text == null || text === "") return;
document.querySelectorAll(`[data-funds-field="${field}"]`).forEach((el) => {
el.innerText = text;
});
}
function accountSnapshotFundingMissing(data){
if(!data || typeof data !== "object") return true;
const hasFunding = data.funding_usdt != null && data.funding_usdt !== "";
const hasTotal = data.total_funds != null && data.total_funds !== "";
const hasTrading = data.current_capital != null && data.current_capital !== "";
return !hasFunding && !hasTotal && !hasTrading;
}
let accountSnapshotRetryCount = 0;
function applyAccountSnapshot(data){
if(!data || typeof data !== "object") return;
if(data.funding_usdt != null && data.funding_usdt !== ""){
setFundsFieldText("total-capital", `${Number(data.funding_usdt).toFixed(2)}U`);
}
if(data.total_funds != null && data.total_funds !== ""){
setFundsFieldText("total-funds", `${Number(data.total_funds).toFixed(2)}U`);
}
if(data.current_capital != null && data.current_capital !== "" && !Number.isNaN(Number(data.current_capital))){
setFundsFieldText("current-capital", `${Number(data.current_capital).toFixed(2)}U`);
}
if(data.options_funding_usdc != null || data.options_funding_usdt != null){
const optFunding = formatOptionsFundingLabel(data.options_funding_usdc, data.options_funding_usdt);
if(optFunding !== "—") setFundsFieldText("options-funding-usdc", optFunding);
}
if(data.options_trading_usdc != null && data.options_trading_usdc !== ""){
setFundsFieldText("options-trading-usdc", `${Number(data.options_trading_usdc).toFixed(2)} USDC`);
}
if(typeof data.unrealized_pnl !== "undefined"){
paintRealtimePnl(data.unrealized_pnl);
}
if(typeof data.available_trading_usdt !== "undefined" && data.available_trading_usdt !== null){
latestAvailableUsdt = Number(data.available_trading_usdt);
}
if(data.risk_status){
document.querySelectorAll("#account-risk-badge").forEach((badge) => {
if(window.AccountRiskBadge){
AccountRiskBadge.applyToElement(badge, data.risk_status);
}else{
const st = data.risk_status.status || "normal";
badge.className = "risk-status-badge risk-status-" + st;
badge.innerText = data.risk_status.status_label || "正常";
badge.title = data.risk_status.reason || "";
}
});
}
if(data.force_close && window.TimeCloseUI && TimeCloseUI.paintForceCloseHeader){
TimeCloseUI.paintForceCloseHeader(data.force_close);
}
let canTradeText = "可开仓";
if(!data.can_trade){
const parts = [];
if(data.risk_status && data.risk_status.can_trade === false && data.risk_status.reason){
parts.push(data.risk_status.reason);
}
const ac = Number(data.active_count || 0);
const max = Number(data.max_active_positions || {{ max_active_positions }});
if(ac >= max) parts.push(`持仓 ${ac}/${max}`);
const hard = Number(data.daily_open_hard_limit != null ? data.daily_open_hard_limit : {{ daily_open_hard_limit }});
const opens = Number(data.opens_today);
if(hard > 0 && !Number.isNaN(opens) && opens >= hard) parts.push(`本交易日开仓 ${opens}/${hard} 已达上限`);
if(!parts.length) parts.push(`未到北京时间 {{ reset_hour }}:00`);
else parts.push(`或未到北京时间 {{ reset_hour }}:00`);
canTradeText = `不可开仓(${parts.join("")}`;
}
const opensToday = Number(data.opens_today);
const hardLim = Number(data.daily_open_hard_limit != null ? data.daily_open_hard_limit : {{ daily_open_hard_limit }});
const alertLim = Number(data.daily_open_alert_threshold != null ? data.daily_open_alert_threshold : {{ daily_open_alert_threshold }});
const openCntTxt = !Number.isNaN(opensToday)
? `本交易日开仓 ${opensToday}${hardLim > 0 ? ` / 硬上限 ${hardLim}` : ""}AI 提醒 ${alertLim}`
: "";
const tip = document.getElementById("order-rule-tip");
const avail = (latestAvailableUsdt !== null && !Number.isNaN(latestAvailableUsdt)) ? `;交易账户可用约${latestAvailableUsdt.toFixed(2)}U` : "";
if(tip){
tip.innerText = `规则:最多 ${data.max_active_positions || {{ max_active_positions }}} 仓;BTC {{ btc_leverage }}x / 山寨 {{ alt_leverage }}x${openCntTxt ? openCntTxt + "" : ""}${canTradeText}${avail};人工开仓盈亏比不得低于 {{ manual_min_planned_rr }}:1`;
}
}
function refreshAccountSnapshot(opts){
const options = opts || {};
const qs = options.force ? "?force=1" : "";
fetch("/api/account_snapshot" + qs).then(r=>r.json()).then(data=>{
if (typeof data.funding_usdt !== "undefined") {
const el = document.getElementById("total-capital");
if(el) el.innerText = (data.funding_usdt === null || data.funding_usdt === undefined) ? "—" : `${Number(data.funding_usdt).toFixed(2)}U`;
applyAccountSnapshot(data);
if(accountSnapshotFundingMissing(data) && !options.force && accountSnapshotRetryCount < 3){
accountSnapshotRetryCount += 1;
setTimeout(() => refreshAccountSnapshot({ silent: true, force: accountSnapshotRetryCount >= 2 }), 1200 * accountSnapshotRetryCount);
}else if(!accountSnapshotFundingMissing(data)){
accountSnapshotRetryCount = 0;
}
if (typeof data.total_funds !== "undefined") {
const el = document.getElementById("total-funds");
if(el) el.innerText = (data.total_funds === null || data.total_funds === undefined) ? "—" : `${Number(data.total_funds).toFixed(2)}U`;
}).catch(()=>{
if(!options.silent && accountSnapshotRetryCount < 3){
accountSnapshotRetryCount += 1;
setTimeout(() => refreshAccountSnapshot({ silent: true }), 1200 * accountSnapshotRetryCount);
}
if (typeof data.current_capital !== "undefined") {
const el = document.getElementById("current-capital");
if(el) el.innerText = `${Number(data.current_capital).toFixed(2)}U`;
}
if (typeof data.options_funding_usdc !== "undefined" || typeof data.options_funding_usdt !== "undefined") {
const el = document.getElementById("options-funding-usdc");
if (el) el.innerText = formatOptionsFundingLabel(data.options_funding_usdc, data.options_funding_usdt);
}
if (typeof data.options_trading_usdc !== "undefined") {
const el = document.getElementById("options-trading-usdc");
if (el) el.innerText = (data.options_trading_usdc === null || data.options_trading_usdc === undefined)
? "—" : `${Number(data.options_trading_usdc).toFixed(2)} USDC`;
}
if (typeof data.unrealized_pnl !== "undefined") {
paintRealtimePnl(data.unrealized_pnl);
}
if (typeof data.available_trading_usdt !== "undefined" && data.available_trading_usdt !== null) {
latestAvailableUsdt = Number(data.available_trading_usdt);
}
if (data.risk_status) {
const badge = document.getElementById("account-risk-badge");
if (badge) {
if (window.AccountRiskBadge) {
AccountRiskBadge.applyToElement(badge, data.risk_status);
} else {
const st = data.risk_status.status || "normal";
badge.className = "risk-status-badge risk-status-" + st;
badge.innerText = data.risk_status.status_label || "正常";
badge.title = data.risk_status.reason || "";
}
}
}
if (data.force_close && window.TimeCloseUI && TimeCloseUI.paintForceCloseHeader) {
TimeCloseUI.paintForceCloseHeader(data.force_close);
}
let canTradeText = "可开仓";
if (!data.can_trade) {
const parts = [];
if (data.risk_status && data.risk_status.can_trade === false && data.risk_status.reason) {
parts.push(data.risk_status.reason);
}
const ac = Number(data.active_count || 0);
const max = Number(data.max_active_positions || {{ max_active_positions }});
if (ac >= max) parts.push(`持仓 ${ac}/${max}`);
const hard = Number(data.daily_open_hard_limit != null ? data.daily_open_hard_limit : {{ daily_open_hard_limit }});
const opens = Number(data.opens_today);
if (hard > 0 && !Number.isNaN(opens) && opens >= hard) parts.push(`本交易日开仓 ${opens}/${hard} 已达上限`);
if (!parts.length) parts.push(`未到北京时间 {{ reset_hour }}:00`);
else parts.push(`或未到北京时间 {{ reset_hour }}:00`);
canTradeText = `不可开仓(${parts.join("")}`;
}
const opensToday = Number(data.opens_today);
const hardLim = Number(data.daily_open_hard_limit != null ? data.daily_open_hard_limit : {{ daily_open_hard_limit }});
const alertLim = Number(data.daily_open_alert_threshold != null ? data.daily_open_alert_threshold : {{ daily_open_alert_threshold }});
const openCntTxt = !Number.isNaN(opensToday)
? `本交易日开仓 ${opensToday}${hardLim > 0 ? ` / 硬上限 ${hardLim}` : ""}AI 提醒 ${alertLim}`
: "";
const tip = document.getElementById("order-rule-tip");
const avail = (latestAvailableUsdt !== null && !Number.isNaN(latestAvailableUsdt)) ? `;交易账户可用约${latestAvailableUsdt.toFixed(2)}U` : "";
if(tip){
tip.innerText = `规则:最多 ${data.max_active_positions || {{ max_active_positions }}} 仓;BTC {{ btc_leverage }}x / 山寨 {{ alt_leverage }}x${openCntTxt ? openCntTxt + "" : ""}${canTradeText}${avail};人工开仓盈亏比不得低于 {{ manual_min_planned_rr }}:1`;
}
}).catch(()=>{});
});
}
const orderSymbolEl = document.getElementById("order-symbol");
+1 -3
View File
@@ -43,9 +43,7 @@
</nav>
<div id="embed-flash" class="flash" style="display:none" role="status"></div>
{% if initial_tab != 'settings' %}
{% include 'instance_header_panel.html' %}
{% endif %}
{% if initial_tab != 'settings' and include_transfer_block %}
{% include 'instance_top_bar.html' %}
{% endif %}
@@ -91,6 +89,6 @@ const ORDER_ENTRY_MODEL_CODE_TO_CATEGORY = {{ entry_model_code_to_category | toj
<script src="/static/key_monitor_form.js?v=2"></script>
{% include 'embed_boot_scripts.html' %}
<script src="/static/instance_live.js?v=3"></script>
<script src="/static/instance_embed.js?v=13"></script>
<script src="/static/instance_embed.js?v=15"></script>
</body>
</html>
+115 -87
View File
@@ -68,9 +68,7 @@
</div>
{% with msg=get_flashed_messages() %}{% if msg %}<div class="flash">{{ msg[0] }}</div>{% endif %}{% endwith %}
{% if page != 'settings' %}
{% include 'instance_header_panel.html' %}
{% endif %}
{% if page != 'settings' and page != 'options' %}
{% include 'instance_top_bar.html' %}
{% endif %}
@@ -1593,18 +1591,23 @@ function refreshOrderDefaults(){
}
function paintRealtimePnl(v){
const pnlEl = document.getElementById("realtime-pnl");
if(!pnlEl) return;
const nodes = document.querySelectorAll('[data-funds-field="realtime-pnl"]');
if(!nodes.length) return;
if(v === null || v === undefined || Number.isNaN(Number(v))){
pnlEl.innerText = "—";
pnlEl.classList.remove("pnl-pos", "pnl-neg");
nodes.forEach((pnlEl) => {
pnlEl.innerText = "—";
pnlEl.classList.remove("pnl-pos", "pnl-neg");
});
return;
}
const n = Number(v);
const sign = n > 0 ? "+" : "";
pnlEl.innerText = `${sign}${n.toFixed(2)}U`;
pnlEl.classList.toggle("pnl-pos", n > 0);
pnlEl.classList.toggle("pnl-neg", n < 0);
const text = `${sign}${n.toFixed(2)}U`;
nodes.forEach((pnlEl) => {
pnlEl.innerText = text;
pnlEl.classList.toggle("pnl-pos", n > 0);
pnlEl.classList.toggle("pnl-neg", n < 0);
});
}
function sumOrdersFloatPnl(orders){
if(!orders || !orders.length) return null;
@@ -1645,87 +1648,112 @@ function formatOptionsFundingLabel(usdc, usdt) {
return parts.length ? parts.join(" · ") : "—";
}
function refreshAccountSnapshot(){
fetch("/api/account_snapshot").then(r=>r.json()).then(data=>{
if (typeof data.funding_usdt !== "undefined") {
const el = document.getElementById("total-capital");
if(el) el.innerText = (data.funding_usdt === null || data.funding_usdt === undefined) ? "—" : `${Number(data.funding_usdt).toFixed(2)}U`;
}
if (typeof data.total_funds !== "undefined") {
const el = document.getElementById("total-funds");
if(el) el.innerText = (data.total_funds === null || data.total_funds === undefined) ? "" : `${Number(data.total_funds).toFixed(2)}U`;
}
if (typeof data.current_capital !== "undefined") {
const el = document.getElementById("current-capital");
if(el) el.innerText = `${Number(data.current_capital).toFixed(2)}U`;
}
if (typeof data.options_funding_usdc !== "undefined" || typeof data.options_funding_usdt !== "undefined") {
const el = document.getElementById("options-funding-usdc");
if (el) el.innerText = formatOptionsFundingLabel(data.options_funding_usdc, data.options_funding_usdt);
}
if (typeof data.options_trading_usdc !== "undefined") {
const el = document.getElementById("options-trading-usdc");
if (el) el.innerText = (data.options_trading_usdc === null || data.options_trading_usdc === undefined)
? "—" : `${Number(data.options_trading_usdc).toFixed(2)} USDC`;
}
if (typeof data.unrealized_pnl !== "undefined") {
paintRealtimePnl(data.unrealized_pnl);
}
if (typeof data.available_trading_usdt !== "undefined" && data.available_trading_usdt !== null) {
latestAvailableUsdt = Number(data.available_trading_usdt);
}
if (data.risk_status) {
const badge = document.getElementById("account-risk-badge");
if (badge) {
if (window.AccountRiskBadge) {
AccountRiskBadge.applyToElement(badge, data.risk_status);
} else {
const st = data.risk_status.status || "normal";
badge.className = "risk-status-badge risk-status-" + st;
badge.innerText = data.risk_status.status_label || "正常";
badge.title = data.risk_status.reason || "";
}
function setFundsFieldText(field, text){
if(text == null || text === "") return;
document.querySelectorAll(`[data-funds-field="${field}"]`).forEach((el) => {
el.innerText = text;
});
}
function accountSnapshotFundingMissing(data){
if(!data || typeof data !== "object") return true;
const hasFunding = data.funding_usdt != null && data.funding_usdt !== "";
const hasTotal = data.total_funds != null && data.total_funds !== "";
const hasTrading = data.current_capital != null && data.current_capital !== "";
return !hasFunding && !hasTotal && !hasTrading;
}
let accountSnapshotRetryCount = 0;
function applyAccountSnapshot(data){
if(!data || typeof data !== "object") return;
if(data.funding_usdt != null && data.funding_usdt !== ""){
setFundsFieldText("total-capital", `${Number(data.funding_usdt).toFixed(2)}U`);
}
if(data.total_funds != null && data.total_funds !== ""){
setFundsFieldText("total-funds", `${Number(data.total_funds).toFixed(2)}U`);
}
if(data.current_capital != null && data.current_capital !== "" && !Number.isNaN(Number(data.current_capital))){
setFundsFieldText("current-capital", `${Number(data.current_capital).toFixed(2)}U`);
}
if(data.options_funding_usdc != null || data.options_funding_usdt != null){
const optFunding = formatOptionsFundingLabel(data.options_funding_usdc, data.options_funding_usdt);
if(optFunding !== "—") setFundsFieldText("options-funding-usdc", optFunding);
}
if(data.options_trading_usdc != null && data.options_trading_usdc !== ""){
setFundsFieldText("options-trading-usdc", `${Number(data.options_trading_usdc).toFixed(2)} USDC`);
}
if(typeof data.unrealized_pnl !== "undefined"){
paintRealtimePnl(data.unrealized_pnl);
}
if(typeof data.available_trading_usdt !== "undefined" && data.available_trading_usdt !== null){
latestAvailableUsdt = Number(data.available_trading_usdt);
}
if(data.risk_status){
document.querySelectorAll("#account-risk-badge").forEach((badge) => {
if(window.AccountRiskBadge){
AccountRiskBadge.applyToElement(badge, data.risk_status);
}else{
const st = data.risk_status.status || "normal";
badge.className = "risk-status-badge risk-status-" + st;
badge.innerText = data.risk_status.status_label || "正常";
badge.title = data.risk_status.reason || "";
}
});
}
if(data.force_close && window.TimeCloseUI && TimeCloseUI.paintForceCloseHeader){
TimeCloseUI.paintForceCloseHeader(data.force_close);
}
let canTradeText = "可开仓";
if(!data.can_trade){
const parts = [];
if(data.risk_status && data.risk_status.can_trade === false && data.risk_status.reason){
parts.push(data.risk_status.reason);
}
if (data.force_close && window.TimeCloseUI && TimeCloseUI.paintForceCloseHeader) {
TimeCloseUI.paintForceCloseHeader(data.force_close);
if((data.active_count||0) >= (data.max_active_positions||{{ max_active_positions }})) parts.push(`持仓 ${data.active_count}/${data.max_active_positions}`);
const hard = Number(data.daily_open_hard_limit != null ? data.daily_open_hard_limit : {{ daily_open_hard_limit }});
const opens = Number(data.opens_today);
if(hard > 0 && !Number.isNaN(opens) && opens >= hard) parts.push(`本交易日开仓 ${opens}/${hard} 已达上限`);
if(data.open_guard_blocks_now) parts.push(`未到北京时间 ${data.reset_hour||{{ reset_hour }}}:00`);
canTradeText = parts.length ? `不可开仓(${parts.join("")}` : "不可开仓";
}
const opensToday = Number(data.opens_today);
const hardLim = Number(data.daily_open_hard_limit != null ? data.daily_open_hard_limit : {{ daily_open_hard_limit }});
const alertLim = Number(data.daily_open_alert_threshold != null ? data.daily_open_alert_threshold : {{ daily_open_alert_threshold }});
const openCntTxt = !Number.isNaN(opensToday)
? `本交易日开仓 ${opensToday}${hardLim > 0 ? ` / 硬上限 ${hardLim}` : ""}AI 提醒 ${alertLim}`
: "";
const tip = document.getElementById("order-rule-tip");
const avail = (latestAvailableUsdt !== null && !Number.isNaN(latestAvailableUsdt)) ? `;交易账户可用约${latestAvailableUsdt.toFixed(2)}U` : "";
if(tip){
tip.innerText = `规则:最多 ${data.max_active_positions || {{ max_active_positions }}} 仓;BTC {{ btc_leverage }}x / 山寨 {{ alt_leverage }}x${openCntTxt ? openCntTxt + "" : ""}${canTradeText}${avail};人工开仓盈亏比不得低于 {{ manual_min_planned_rr }}:1`;
}
const allowEl = document.getElementById("allow-open-before-reset");
const guardStatus = document.getElementById("open-guard-status");
const resetH = data.reset_hour != null ? data.reset_hour : {{ reset_hour }};
if(allowEl && typeof data.open_guard_enabled !== "undefined"){
allowEl.checked = !data.open_guard_enabled;
}
if(guardStatus && typeof data.open_guard_enabled !== "undefined"){
guardStatus.innerText = data.open_guard_enabled
? `已限制:${resetH}:00 前不可开仓`
: `已放开:${resetH}:00 前允许开仓`;
}
}
function refreshAccountSnapshot(opts){
const options = opts || {};
const qs = options.force ? "?force=1" : "";
fetch("/api/account_snapshot" + qs).then(r=>r.json()).then(data=>{
applyAccountSnapshot(data);
if(accountSnapshotFundingMissing(data) && !options.force && accountSnapshotRetryCount < 3){
accountSnapshotRetryCount += 1;
setTimeout(() => refreshAccountSnapshot({ silent: true, force: accountSnapshotRetryCount >= 2 }), 1200 * accountSnapshotRetryCount);
}else if(!accountSnapshotFundingMissing(data)){
accountSnapshotRetryCount = 0;
}
let canTradeText = "可开仓";
if(!data.can_trade){
const parts = [];
if (data.risk_status && data.risk_status.can_trade === false && data.risk_status.reason) {
parts.push(data.risk_status.reason);
}
if((data.active_count||0) >= (data.max_active_positions||{{ max_active_positions }})) parts.push(`持仓 ${data.active_count}/${data.max_active_positions}`);
const hard = Number(data.daily_open_hard_limit != null ? data.daily_open_hard_limit : {{ daily_open_hard_limit }});
const opens = Number(data.opens_today);
if (hard > 0 && !Number.isNaN(opens) && opens >= hard) parts.push(`本交易日开仓 ${opens}/${hard} 已达上限`);
if(data.open_guard_blocks_now) parts.push(`未到北京时间 ${data.reset_hour||{{ reset_hour }}}:00`);
canTradeText = parts.length ? `不可开仓(${parts.join("")}` : "不可开仓";
}).catch(()=>{
if(!options.silent && accountSnapshotRetryCount < 3){
accountSnapshotRetryCount += 1;
setTimeout(() => refreshAccountSnapshot({ silent: true }), 1200 * accountSnapshotRetryCount);
}
const opensToday = Number(data.opens_today);
const hardLim = Number(data.daily_open_hard_limit != null ? data.daily_open_hard_limit : {{ daily_open_hard_limit }});
const alertLim = Number(data.daily_open_alert_threshold != null ? data.daily_open_alert_threshold : {{ daily_open_alert_threshold }});
const openCntTxt = !Number.isNaN(opensToday)
? `本交易日开仓 ${opensToday}${hardLim > 0 ? ` / 硬上限 ${hardLim}` : ""}AI 提醒 ${alertLim}`
: "";
const tip = document.getElementById("order-rule-tip");
const avail = (latestAvailableUsdt !== null && !Number.isNaN(latestAvailableUsdt)) ? `;交易账户可用约${latestAvailableUsdt.toFixed(2)}U` : "";
if(tip){
tip.innerText = `规则:最多 ${data.max_active_positions || {{ max_active_positions }}} 仓;BTC {{ btc_leverage }}x / 山寨 {{ alt_leverage }}x${openCntTxt ? openCntTxt + "" : ""}${canTradeText}${avail};人工开仓盈亏比不得低于 {{ manual_min_planned_rr }}:1`;
}
const allowEl = document.getElementById("allow-open-before-reset");
const guardStatus = document.getElementById("open-guard-status");
const resetH = data.reset_hour != null ? data.reset_hour : {{ reset_hour }};
if(allowEl && typeof data.open_guard_enabled !== "undefined"){
allowEl.checked = !data.open_guard_enabled;
}
if(guardStatus && typeof data.open_guard_enabled !== "undefined"){
guardStatus.innerText = data.open_guard_enabled
? `已限制:${resetH}:00 前不可开仓`
: `已放开:${resetH}:00 前允许开仓`;
}
}).catch(()=>{});
});
}
{% if ui_open_guard_enabled %}
@@ -1801,7 +1829,7 @@ if(window.ManualOrderRrPreview){
refreshAccountSnapshot();
const settingsRefreshFunds = document.getElementById("settings-refresh-funds");
if (settingsRefreshFunds) settingsRefreshFunds.addEventListener("click", refreshAccountSnapshot);
if (settingsRefreshFunds) settingsRefreshFunds.addEventListener("click", function(){ refreshAccountSnapshot({ force: true }); });
if (window.AccountRiskBadge) AccountRiskBadge.startTicker();
const _journalFormEl = document.getElementById("journal-form");
if(_journalFormEl){
@@ -32,6 +32,7 @@
<span class="risk-status-badge risk-status-{{ risk_status.status|default('normal') }}" id="account-risk-badge" role="status" title="{{ risk_status.reason|default('', true) }}" data-status-label="{{ risk_status.status_label|default('正常') }}"{% if risk_status.freeze_until_ms %} data-freeze-until-ms="{{ risk_status.freeze_until_ms }}"{% endif %}>{{ risk_status.status_label|default('正常') }}</span>
</div>
{% include 'instance_theme_toggle.html' %}
<button type="button" class="btn-secondary btn-sm instance-header-refresh-funds" id="settings-refresh-funds" title="从交易所拉取最新资金">刷新资金</button>
</div>
</div>
<div class="instance-header-stats-wrap instance-desktop-only">
@@ -10,40 +10,40 @@
</div>
<div class="stat-strip-item stat-strip-item--primary">
<div class="label">总交易</div>
<div class="value" id="stat-total">{{ total }}</div>
<div class="value" id="stat-total" data-funds-field="stat-total">{{ total }}</div>
</div>
<div class="stat-strip-item">
<div class="label">胜率</div>
<div class="value" id="stat-rate">{{ rate }}%</div>
<div class="value" id="stat-rate" data-funds-field="stat-rate">{{ rate }}%</div>
</div>
<div class="stat-strip-item" title="平均盈利 ÷ 平均亏损(当前列表窗口)">
<div class="label">盈亏比</div>
<div class="value" id="stat-pl-ratio">{% if profit_loss_ratio is not none %}{{ profit_loss_ratio }}{% else %}—{% endif %}</div>
<div class="value" id="stat-pl-ratio" data-funds-field="stat-pl-ratio">{% if profit_loss_ratio is not none %}{{ profit_loss_ratio }}{% else %}—{% endif %}</div>
</div>
<div class="stat-strip-item">
<div class="label">总资金</div>
<div class="value" id="total-funds">{% if total_funds is not none %}{{ funds_fmt(total_funds) }}U{% else %}—{% endif %}</div>
<div class="value" id="total-funds" data-funds-field="total-funds">{% if total_funds is not none %}{{ funds_fmt(total_funds) }}U{% else %}—{% endif %}</div>
</div>
<div class="stat-strip-item">
<div class="label">资金账户</div>
<div class="value" id="total-capital">{% if funding_usdt is not none %}{{ funds_fmt(funding_usdt) }}U{% else %}—{% endif %}</div>
<div class="value" id="total-capital" data-funds-field="total-capital">{% if funding_usdt is not none %}{{ funds_fmt(funding_usdt) }}U{% else %}—{% endif %}</div>
</div>
<div class="stat-strip-item">
<div class="label">交易账户</div>
<div class="value" id="current-capital">{{ funds_fmt(current_capital) }}U</div>
<div class="value" id="current-capital" data-funds-field="current-capital">{{ funds_fmt(current_capital) }}U</div>
</div>
{% if options_enabled %}
<div class="stat-strip-item">
<div class="label">期权资金账户</div>
<div class="value" id="options-funding-usdc">{{ options_funding_label(options_funding_usdc, options_funding_usdt) }}</div>
<div class="value" id="options-funding-usdc" data-funds-field="options-funding-usdc">{{ options_funding_label(options_funding_usdc, options_funding_usdt) }}</div>
</div>
<div class="stat-strip-item">
<div class="label">期权交易账户</div>
<div class="value" id="options-trading-usdc">{% if options_trading_usdc is not none %}{{ funds_fmt(options_trading_usdc) }} USDC{% else %}—{% endif %}</div>
<div class="value" id="options-trading-usdc" data-funds-field="options-trading-usdc">{% if options_trading_usdc is not none %}{{ funds_fmt(options_trading_usdc) }} USDC{% else %}—{% endif %}</div>
</div>
{% endif %}
<div class="stat-strip-item stat-strip-item--pnl">
<div class="label">实时盈亏</div>
<div class="value" id="realtime-pnl"></div>
<div class="value" id="realtime-pnl" data-funds-field="realtime-pnl"></div>
</div>
</div>
+1 -14
View File
@@ -1,18 +1,5 @@
{# 系统设置:左风控说明 · 右资金划转 + 数据导出 #}
{# 系统设置:左风控说明 · 右资金划转 + 数据导出(顶栏资金与统计见 instance_header_panel #}
<div class="settings-page">
<div class="card settings-account-summary">
<div class="settings-account-summary-head">
<div class="instance-toolbar-status">
<div class="exchange-tag">{{ exchange_display }}</div>
<span class="risk-status-badge risk-status-{{ risk_status.status|default('normal') }}" role="status">{{ risk_status.status_label|default('正常') }}</span>
</div>
<div class="settings-account-summary-actions">
{% include 'instance_theme_toggle.html' %}
<button type="button" class="btn-secondary btn-sm" id="settings-refresh-funds">刷新资金</button>
</div>
</div>
{% include 'instance_header_stats.html' %}
</div>
<div class="settings-cards-grid">
<div class="card settings-card settings-card--risk">
<h2>风控说明</h2>