3ac854d74c
Drop 12h from market chart options and storage, and avoid left-pan reload and tail refresh from resetting the viewport while zooming. Co-authored-by: Cursor <cursoragent@cursor.com>
358 lines
19 KiB
HTML
358 lines
19 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN" data-theme="dark">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<script src="/assets/theme.js?v=20260604-hub-inst-theme"></script>
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
||
<meta name="theme-color" content="#0b0e18" />
|
||
<meta name="apple-mobile-web-app-title" content="中控" />
|
||
<link rel="icon" href="/assets/icons/favicon.ico" sizes="32x32" />
|
||
<link rel="icon" href="/assets/icons/icon.svg" type="image/svg+xml" />
|
||
<link rel="apple-touch-icon" href="/assets/icons/apple-touch-icon.png" />
|
||
<link rel="manifest" href="/assets/icons/manifest.webmanifest" />
|
||
<title>复盘系统中控</title>
|
||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Orbitron:wght@500;600;700&display=swap" rel="stylesheet" media="print" onload="this.media='all'" />
|
||
<noscript><link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Orbitron:wght@500;600;700&display=swap" rel="stylesheet" /></noscript>
|
||
<link rel="stylesheet" href="/assets/app.css?v=20260607-hub-archive-v5" />
|
||
</head>
|
||
<body>
|
||
<div class="app-bg" aria-hidden="true"></div>
|
||
<div class="app-shell">
|
||
<header class="app-header">
|
||
<div class="brand">
|
||
<span class="brand-mark" aria-hidden="true"></span>
|
||
<div>
|
||
<div class="brand-title">复盘系统中控</div>
|
||
<div class="brand-sub">MULTI-EXCHANGE · OPS</div>
|
||
</div>
|
||
</div>
|
||
<div class="header-right">
|
||
<div class="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">
|
||
<path fill="currentColor" d="M12.1 3a9 9 0 1 0 8.9 11 6.5 6.5 0 1 1-8.9-11z"/>
|
||
</svg>
|
||
</button>
|
||
<button type="button" class="theme-toggle-btn" data-theme-value="light" aria-pressed="false" title="亮色主题">
|
||
<svg class="theme-icon" viewBox="0 0 24 24" width="18" height="18" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
||
<circle cx="12" cy="12" r="4"/>
|
||
<path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
<span id="sys-status" class="sys-pill" title="系统状态">SYNC</span>
|
||
<nav class="top-nav">
|
||
<a href="/monitor" id="nav-monitor">监控区</a>
|
||
<a href="/market" id="nav-market">行情区</a>
|
||
<a href="/archive" id="nav-archive">币种档案</a>
|
||
<a href="/ai" id="nav-ai">AI 教练</a>
|
||
<a href="/settings" id="nav-settings">系统设置</a>
|
||
</nav>
|
||
<button type="button" id="btn-logout" class="ghost" title="退出登录">退出</button>
|
||
</div>
|
||
</header>
|
||
|
||
<div id="page-monitor" class="page">
|
||
<div class="page-head">
|
||
<h1><span class="head-tag">MON</span> 监控区</h1>
|
||
</div>
|
||
<div id="monitor-alert-summary" class="monitor-alert-summary hidden" aria-live="polite"></div>
|
||
<div class="toolbar">
|
||
<button type="button" id="btn-monitor-refresh" class="primary">立即刷新</button>
|
||
<label class="chk-label">
|
||
<input type="checkbox" id="auto-monitor" checked /> 后台每 5 秒聚合 · SSE 自动更新
|
||
</label>
|
||
<button type="button" id="btn-close-all" class="danger">全局紧急全平</button>
|
||
<span class="toolbar-spacer"></span>
|
||
<span id="monitor-updated" class="toolbar-meta"></span>
|
||
</div>
|
||
<div id="monitor-grid" class="grid-monitor"></div>
|
||
</div>
|
||
|
||
<div id="page-market" class="page hidden">
|
||
<div class="page-head">
|
||
<h1><span class="head-tag">MKT</span> 行情区</h1>
|
||
</div>
|
||
<div class="market-toolbar toolbar">
|
||
<label class="market-field">
|
||
<span>交易所</span>
|
||
<select id="market-exchange"></select>
|
||
</label>
|
||
<label class="market-field">
|
||
<span>币种</span>
|
||
<input id="market-symbol" type="text" value="BTC/USDT" placeholder="BTC/USDT" autocomplete="off" />
|
||
</label>
|
||
<label class="market-field">
|
||
<span>周期</span>
|
||
<select id="market-timeframe">
|
||
<option value="1m">1m</option>
|
||
<option value="5m">5m</option>
|
||
<option value="15m">15m</option>
|
||
<option value="1h">1h</option>
|
||
<option value="2h">2h</option>
|
||
<option value="4h">4h</option>
|
||
<option value="1d" selected>1d</option>
|
||
<option value="1w">1w</option>
|
||
</select>
|
||
</label>
|
||
<button type="button" id="market-load" class="primary">加载</button>
|
||
<button type="button" id="market-refresh" class="ghost">强制刷新</button>
|
||
<span class="toolbar-spacer"></span>
|
||
<span id="market-bar-countdown" class="toolbar-meta market-countdown"></span>
|
||
<span id="market-updated" class="toolbar-meta"></span>
|
||
</div>
|
||
<p id="market-status" class="market-status"></p>
|
||
<div id="market-chart-wrap" class="market-chart-wrap">
|
||
<div class="market-ohlcv-bar" aria-label="K线详情">
|
||
<div class="market-ohlcv-title">
|
||
<span id="mkt-exchange-label" class="mkt-exchange-tag"></span>
|
||
<span id="mkt-symbol-label">—</span>
|
||
<span id="mkt-tf-label">1d</span>
|
||
<div class="market-chart-actions">
|
||
<details class="market-ind-menu">
|
||
<summary>技术指标</summary>
|
||
<div class="market-ind-options">
|
||
<label class="market-ind-opt"><input type="checkbox" id="market-ind-ema" value="ema" /> EMA交叉(21/55)</label>
|
||
<label class="market-ind-opt"><input type="checkbox" id="market-ind-macd" value="macd" /> MACD</label>
|
||
<label class="market-ind-opt"><input type="checkbox" id="market-ind-rsi" value="rsi" /> RSI</label>
|
||
</div>
|
||
</details>
|
||
<button type="button" id="market-chart-fullscreen" class="ghost market-fs-btn" title="K线全屏(按 F)">全屏</button>
|
||
</div>
|
||
</div>
|
||
<div class="market-ohlcv-row">
|
||
<span class="ohlcv-item"><span class="k">开</span><span id="mkt-o">—</span></span>
|
||
<span class="ohlcv-item"><span class="k">高</span><span id="mkt-h">—</span></span>
|
||
<span class="ohlcv-item"><span class="k">低</span><span id="mkt-l">—</span></span>
|
||
<span class="ohlcv-item"><span class="k">收</span><span id="mkt-c">—</span></span>
|
||
<span class="ohlcv-item market-vol"><span class="k">量</span><span id="mkt-v">—</span></span>
|
||
<span class="ohlcv-item"><span class="k">振幅</span><span id="mkt-amp">—</span></span>
|
||
</div>
|
||
<div id="market-div-legend" class="market-div-legend hidden" aria-live="polite"></div>
|
||
<div id="market-fs-toolbar" class="market-fs-toolbar hidden" aria-label="全屏行情控制">
|
||
<label class="market-field market-fs-field">
|
||
<span>交易所</span>
|
||
<select id="market-fs-exchange"></select>
|
||
</label>
|
||
<label class="market-field market-fs-field">
|
||
<span>币种</span>
|
||
<input id="market-fs-symbol" type="text" placeholder="BTC/USDT" autocomplete="off" />
|
||
</label>
|
||
<label class="market-field market-fs-field">
|
||
<span>周期</span>
|
||
<select id="market-fs-timeframe">
|
||
<option value="1m">1m</option>
|
||
<option value="5m">5m</option>
|
||
<option value="15m">15m</option>
|
||
<option value="1h">1h</option>
|
||
<option value="2h">2h</option>
|
||
<option value="4h">4h</option>
|
||
<option value="1d">1d</option>
|
||
<option value="1w">1w</option>
|
||
</select>
|
||
</label>
|
||
<button type="button" id="market-fs-load" class="primary">加载</button>
|
||
</div>
|
||
</div>
|
||
<div id="market-pos-panel" class="market-pos-panel hidden" aria-label="持仓标记">
|
||
<div class="market-pos-row">
|
||
<span id="mkt-pos-side" class="market-pos-side"></span>
|
||
<span class="ohlcv-item"><span class="k">入场</span><span id="mkt-pos-entry">—</span></span>
|
||
<span class="ohlcv-item"><span class="k">止损</span><span id="mkt-pos-sl">—</span></span>
|
||
<span class="ohlcv-item"><span class="k">止盈</span><span id="mkt-pos-tp">—</span></span>
|
||
<span class="ohlcv-item"><span class="k">张数</span><span id="mkt-pos-size">—</span></span>
|
||
<span class="ohlcv-item"><span class="k">浮盈亏</span><span id="mkt-pos-pnl" class="market-pos-pnl">—</span></span>
|
||
<button type="button" id="market-pos-clear" class="ghost market-pos-clear" title="清除 K 线上的持仓价格线">清除标记</button>
|
||
</div>
|
||
<div id="market-pos-orders" class="market-pos-orders"></div>
|
||
</div>
|
||
<div class="market-chart-body">
|
||
<button type="button" id="market-chart-fs-exit" class="ghost market-fs-exit hidden" title="退出全屏 (Esc)">退出全屏</button>
|
||
<div id="market-exchange-badge" class="market-exchange-badge" aria-hidden="true"></div>
|
||
<div id="market-chart" class="market-chart-host"></div>
|
||
<div id="market-price-tag" class="market-price-tag hidden" aria-hidden="true">
|
||
<div class="market-price-tag-head">
|
||
<span class="market-price-tag-label">现价</span>
|
||
<span id="market-price-tag-value" class="market-price-tag-value"></span>
|
||
</div>
|
||
<div id="market-price-tag-time" class="market-price-tag-time"></div>
|
||
</div>
|
||
<button type="button" id="market-price-auto" class="market-price-auto is-on" title="价格轴自动缩放">自动</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="page-archive" class="page hidden">
|
||
<div class="page-head">
|
||
<h1><span class="head-tag">ARC</span> 币种档案</h1>
|
||
<p class="page-desc">一所一币一行 · 交易时间线 · 建档 30 天 K 线可拖动缩放(默认聚焦持仓段,不含拉到「现在」)</p>
|
||
</div>
|
||
<div class="archive-toolbar toolbar">
|
||
<label class="archive-field">
|
||
<span>交易所</span>
|
||
<select id="archive-exchange"><option value="">全部</option></select>
|
||
</label>
|
||
<label class="chk-label"><input type="checkbox" id="archive-filter-profit" /> 有盈利单</label>
|
||
<label class="chk-label"><input type="checkbox" id="archive-filter-loss" /> 有亏损单</label>
|
||
<label class="chk-label"><input type="checkbox" id="archive-filter-sick" /> 犯病</label>
|
||
<label class="chk-label"><input type="checkbox" id="archive-filter-emotion" /> 情绪</label>
|
||
<button type="button" id="archive-btn-refresh" class="primary">刷新列表</button>
|
||
<button type="button" id="archive-btn-sync" class="ghost">同步交易与 K 线</button>
|
||
<span id="archive-status" class="toolbar-meta"></span>
|
||
</div>
|
||
<div class="archive-layout">
|
||
<section class="archive-list-panel">
|
||
<div id="archive-list" class="archive-list" role="list"></div>
|
||
</section>
|
||
<section class="archive-detail-panel hidden" id="archive-detail-panel">
|
||
<div class="archive-detail-head">
|
||
<h2 id="archive-detail-title">—</h2>
|
||
<span id="archive-detail-stats" class="archive-detail-stats"></span>
|
||
</div>
|
||
<div class="archive-chart-toolbar toolbar">
|
||
<div class="archive-tf-tabs" id="archive-tf-tabs" role="tablist">
|
||
<button type="button" class="archive-tf-btn" data-tf="5m">5m</button>
|
||
<button type="button" class="archive-tf-btn is-active" data-tf="15m">15m</button>
|
||
<button type="button" class="archive-tf-btn" data-tf="1h">1h</button>
|
||
<button type="button" class="archive-tf-btn" data-tf="4h">4h</button>
|
||
</div>
|
||
<label class="archive-field">
|
||
<span>视窗</span>
|
||
<select id="archive-view-mode">
|
||
<option value="hold">持仓过程(锚平仓)</option>
|
||
<option value="entry">进场决策(锚开仓)</option>
|
||
</select>
|
||
</label>
|
||
<label class="archive-field">
|
||
<span>跳转时间</span>
|
||
<input id="archive-jump-at" type="text" placeholder="2026-06-07 14:30" autocomplete="off" />
|
||
</label>
|
||
<button type="button" id="archive-btn-jump" class="ghost">跳转</button>
|
||
<button type="button" id="archive-btn-reload-chart" class="primary">重载图表</button>
|
||
</div>
|
||
<div class="archive-chart-wrap">
|
||
<div id="archive-chart" class="archive-chart-host"></div>
|
||
<button type="button" id="archive-mark-auto" class="archive-mark-auto is-on" title="开启:该币种全部交易均标注开/平;关闭:仅当前选中一笔">自动</button>
|
||
</div>
|
||
<div id="archive-trades" class="archive-trades"></div>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="instance-frame-shell" class="instance-frame-shell hidden" aria-hidden="true">
|
||
<div class="instance-frame-toolbar">
|
||
<button type="button" id="instance-frame-back" class="ghost">← 返回监控</button>
|
||
<span id="instance-frame-title" class="instance-frame-title"></span>
|
||
<div class="instance-frame-actions">
|
||
<button type="button" id="instance-frame-refresh" class="ghost">刷新</button>
|
||
<button type="button" id="instance-frame-newtab" class="ghost">新标签打开</button>
|
||
</div>
|
||
</div>
|
||
<iframe id="instance-frame" class="instance-frame" title="交易所实例"></iframe>
|
||
</div>
|
||
|
||
<div id="exchange-fullscreen" class="exchange-fullscreen hidden" aria-hidden="true">
|
||
<button type="button" id="exchange-fullscreen-backdrop" class="exchange-fullscreen-backdrop" aria-label="关闭全屏"></button>
|
||
<div class="exchange-fullscreen-panel">
|
||
<div id="exchange-fullscreen-inner"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="page-ai" class="page hidden">
|
||
<div class="page-head">
|
||
<h1><span class="head-tag">AI</span> 教练</h1>
|
||
<p class="page-desc">四户今日总结 · 口语化陪聊(单会话,点「新开对话」清空上下文)</p>
|
||
</div>
|
||
<div class="ai-layout">
|
||
<section class="ai-panel ai-summary-panel">
|
||
<div class="ai-panel-head">
|
||
<h2>今日总结</h2>
|
||
<div class="ai-panel-actions">
|
||
<button type="button" id="btn-ai-summary" class="primary">生成今日总结</button>
|
||
</div>
|
||
</div>
|
||
<div id="ai-summary-stats" class="ai-stats-row" aria-live="polite"></div>
|
||
<div id="ai-summary-body" class="ai-panel-scroll ai-md-body">
|
||
<p class="ai-placeholder">点击「生成今日总结」聚合四户平仓与持仓数据(未启用账户显示「未监控」)。</p>
|
||
</div>
|
||
</section>
|
||
<section class="ai-panel ai-chat-panel">
|
||
<div class="ai-panel-head">
|
||
<h2 id="ai-chat-title">聊天</h2>
|
||
<div class="ai-panel-actions">
|
||
<button type="button" id="btn-ai-chat-new" class="primary">新开对话</button>
|
||
</div>
|
||
</div>
|
||
<div id="ai-chat-messages" class="ai-panel-scroll ai-chat-messages" aria-live="polite"></div>
|
||
<form id="ai-chat-form" class="ai-chat-form">
|
||
<div class="ai-chat-compose">
|
||
<textarea id="ai-chat-input" rows="2" placeholder="聊聊行情、心态、纪律、执行…" autocomplete="off"></textarea>
|
||
<div class="ai-chat-compose-actions">
|
||
<label class="ai-chat-upload-btn" title="上传图片或 txt/md/json 文档">
|
||
<input type="file" id="ai-chat-files" accept="image/*,.txt,.md,.markdown,.json" multiple hidden />
|
||
附件
|
||
</label>
|
||
<span id="ai-chat-files-label" class="ai-chat-files-label"></span>
|
||
<button type="submit" id="btn-ai-chat-send" class="primary">发送</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="page-settings" class="page hidden">
|
||
<div class="page-head">
|
||
<h1><span class="head-tag">CFG</span> 系统设置</h1>
|
||
<p class="page-desc">交易所地址、启用状态与监控能力</p>
|
||
</div>
|
||
<details class="hint-box">
|
||
<summary>配置说明</summary>
|
||
<div class="hint-body">
|
||
保存后写入 <code>hub_settings.json</code>。Flask / Agent 填本机地址即可;复盘链接可留空(由 Flask 地址自动生成)。<br />
|
||
<code>HUB_DISABLED_IDS</code> 可强制关闭账户;<code>HUB_BRIDGE_TOKEN</code> 与实例一致,或实例 <code>APP_AUTH_DISABLED=true</code>。<br />
|
||
公网反代请在 hub <code>.env</code> 设置 <code>HUB_USERNAME</code> 与 <code>HUB_PASSWORD</code>;HTTPS 反代建议 <code>HUB_COOKIE_SECURE=true</code>。
|
||
</div>
|
||
</details>
|
||
<p id="settings-meta-line" class="settings-meta-line"></p>
|
||
<div class="toolbar">
|
||
<button type="button" id="btn-settings-save" class="primary">保存设置</button>
|
||
<button type="button" id="btn-settings-add">添加交易所</button>
|
||
<button type="button" id="btn-settings-reload">重新加载</button>
|
||
</div>
|
||
<div id="settings-list" class="settings-grid-wrap"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="tpsl-modal" class="modal hidden" aria-hidden="true">
|
||
<div class="modal-backdrop" id="tpsl-modal-backdrop"></div>
|
||
<div class="modal-panel" role="dialog" aria-labelledby="tpsl-modal-title">
|
||
<h3 id="tpsl-modal-title">挂止盈 / 止损</h3>
|
||
<p id="tpsl-modal-meta" class="modal-meta"></p>
|
||
<div class="modal-field">
|
||
<label for="tpsl-sl">止损价</label>
|
||
<input id="tpsl-sl" type="number" step="any" autocomplete="off" />
|
||
</div>
|
||
<div class="modal-field">
|
||
<label for="tpsl-tp">止盈价</label>
|
||
<input id="tpsl-tp" type="number" step="any" autocomplete="off" />
|
||
</div>
|
||
<p class="modal-hint">先撤销该合约全部条件单,再挂新止盈与止损(四所统一)。</p>
|
||
<div class="modal-actions">
|
||
<button type="button" id="tpsl-cancel" class="ghost">取消</button>
|
||
<button type="button" id="tpsl-submit" class="primary">确认挂单</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="toast"></div>
|
||
<script src="https://unpkg.com/lightweight-charts@4.2.0/dist/lightweight-charts.standalone.production.js"></script>
|
||
<script src="/assets/chart.js?v=20260604-upnl-contracts"></script>
|
||
<script src="/assets/archive.js?v=20260607-hub-archive-v6"></script>
|
||
<script src="/assets/ai_review_render.js?v=2"></script>
|
||
<script src="/assets/app.js?v=20260607-hub-archive-v1"></script>
|
||
</body>
|
||
</html>
|