feat(risk): show live countdown on freeze status badges

Expose freeze_until_ms from risk API and tick hub/instance badges with remaining 1h/4h/daily time.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-18 17:41:04 +08:00
parent 0280b4f065
commit 97370926d6
15 changed files with 272 additions and 41 deletions
+9 -3
View File
@@ -1538,15 +1538,21 @@ def get_db():
def hub_account_risk_status(conn):
from account_risk_lib import compute_account_risk_status, ensure_account_risk_schema
from account_risk_lib import (
compute_account_risk_status,
enrich_risk_status_countdown,
ensure_account_risk_schema,
)
ensure_account_risk_schema(conn)
return compute_account_risk_status(
now = app_now()
st = compute_account_risk_status(
conn,
trading_day=get_trading_day(),
now=app_now(),
now=now,
fmt_local_ms=ms_to_app_local_str,
)
return enrich_risk_status_countdown(st, now=now, daily_reset_hour=TRADING_DAY_RESET_HOUR)
def hub_user_initiated_close(
+12 -6
View File
@@ -5,7 +5,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<script src="/static/instance_theme.js?v=9"></script>
<link rel="stylesheet" href="/static/instance_theme_early.css?v=4">
<link rel="stylesheet" href="/static/account_risk_badge.css?v=2">
<link rel="stylesheet" href="/static/account_risk_badge.css?v=3">
<script src="/static/account_risk_badge.js?v=1"></script>
<meta name="theme-color" content="#0b0d14">
<meta name="apple-mobile-web-app-title" content="监控">
@@ -264,7 +265,7 @@
<h1>加密货币|交易监控 + AI复盘一体化</h1>
<div class="header-row">
<div class="exchange-tag">{{ exchange_display }}</div>
<span class="risk-status-badge risk-status-{{ risk_status.status|default('normal') }}" id="account-risk-badge" role="status" title="{{ risk_status.reason|default('', true) }}">{{ risk_status.status_label|default('正常') }}</span>
<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 class="theme-toggle instance-theme-toggle" role="group" aria-label="界面主题">
<button type="button" class="theme-toggle-btn is-active" data-theme-value="dark" aria-pressed="true" title="暗色主题">
<svg class="theme-icon" viewBox="0 0 24 24" width="18" height="18" aria-hidden="true">
@@ -2047,10 +2048,14 @@ function refreshAccountSnapshot(){
if (data.risk_status) {
const badge = document.getElementById("account-risk-badge");
if (badge) {
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 (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 || "";
}
}
}
let canTradeText = "可开仓";
@@ -2138,6 +2143,7 @@ if(window.ManualOrderRrPreview){
});
refreshAccountSnapshot();
if (window.AccountRiskBadge) AccountRiskBadge.startTicker();
const _journalFormEl = document.getElementById("journal-form");
if(_journalFormEl){
_journalFormEl.addEventListener("submit", function(ev){