Files
xiaobai-review/frontend/index.html
T
c445f19842 fix(HEL-69): serve_static 目录 index 兜底,闸门改跳 /m/
审核通过后部署侧小改:目录请求返回 index.html,避免 /m/ 回退桌面页;分流闸门同步改用干净 /m/ 地址。

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-08-24 01:47:53 +08:00

662 lines
47 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="color-scheme" content="light dark">
<title>小白复盘</title>
<script>
(() => {
const params = new URLSearchParams(window.location.search);
const ui = params.get("ui");
const path = window.location.pathname;
const alreadyMobile = path === "/m" || path.indexOf("/m/") === 0;
const forcedMobile = ui === "mobile";
const forcedDesktop = ui === "desktop";
const autoMobile = window.matchMedia && window.matchMedia("(max-width: 720px)").matches;
const mobileUA = /Android|iPhone|iPad|iPod|Mobile|Windows Phone/i.test(navigator.userAgent || "");
if (!forcedDesktop && !alreadyMobile && (forcedMobile || autoMobile || mobileUA)) {
window.location.replace("/m/" + window.location.search + window.location.hash);
}
})();
</script>
<script>
(() => {
let theme = "light";
try {
theme = localStorage.getItem("xiaobaiTheme") === "dark" ? "dark" : "light";
} catch (_error) {
theme = "light";
}
document.documentElement.dataset.theme = theme;
document.documentElement.style.colorScheme = theme;
})();
</script>
<link rel="stylesheet" href="/shared/tokens.css?v=20260820-3">
<link rel="stylesheet" href="/shared/base.css?v=20260806-1">
<link rel="stylesheet" href="/shared/shell.css?v=20260820-8">
<link rel="stylesheet" href="/shared/auth.css?v=20260820-5">
<link rel="stylesheet" href="/shared/components/controls.css?v=20260820-2">
<link rel="stylesheet" href="/shared/components/navigation.css?v=20260820-1">
<link rel="stylesheet" href="/shared/components/cards.css?v=20260820-1">
<link rel="stylesheet" href="/shared/components/tables.css?v=20260820-1">
<link rel="stylesheet" href="/shared/components/dialogs.css?v=20260820-3">
<link rel="stylesheet" href="/shared/components/feedback.css?v=20260806-1">
<link rel="stylesheet" href="/pages/market/foundation.css?v=20260820-4">
<link rel="stylesheet" href="/pages/sentiment/foundation.css?v=20260820-2">
<link rel="stylesheet" href="/pages/pools/foundation.css?v=20260820-1">
<link rel="stylesheet" href="/pages/ladder/foundation.css?v=20260820-1">
<link rel="stylesheet" href="/pages/rotation/foundation.css?v=20260820-1">
<link rel="stylesheet" href="/pages/auction/foundation.css?v=20260820-1">
<link rel="stylesheet" href="/pages/themes/foundation.css?v=20260820-1">
<link rel="stylesheet" href="/pages/popularity/foundation.css?v=20260820-1">
<link rel="stylesheet" href="/pages/dragon-tiger/foundation.css?v=20260820-1">
<link rel="stylesheet" href="/pages/screener/foundation.css?v=20260820-4">
<link rel="stylesheet" href="/pages/mentor/foundation.css?v=20260820-2">
<link rel="stylesheet" href="/pages/heaven/foundation.css?v=20260806-2">
<link rel="stylesheet" href="/pages/review/foundation.css?v=20260820-4">
</head>
<body>
<section id="authGate" class="auth-gate" aria-label="账号登录">
<div class="auth-shell">
<div class="auth-brand">
<div class="brand-mark" aria-hidden="true"><span class="brand-glyph"></span></div>
<div><h1>小白复盘</h1><span>登录后进入你的复盘空间</span></div>
</div>
<div class="auth-tabs" role="tablist">
<button id="authLoginTab" class="auth-tab active" type="button" data-auth-mode="login">登录</button>
<button id="authRegisterTab" class="auth-tab" type="button" data-auth-mode="register">注册</button>
</div>
<form id="authForm" class="auth-form">
<label class="form-field"><span>账号名</span><input id="authUsername" type="text" minlength="3" maxlength="30" autocomplete="username" required></label>
<label class="form-field"><span>密码</span><input id="authPassword" type="password" minlength="8" maxlength="128" autocomplete="current-password" required></label>
<label id="authConfirmField" class="form-field" hidden><span>确认密码</span><input id="authPasswordConfirm" type="password" minlength="8" maxlength="128" autocomplete="new-password"></label>
<p id="authError" class="auth-error" hidden></p>
<button id="authSubmitButton" class="button primary" type="submit">登录</button>
</form>
</div>
</section>
<div class="main">
<header class="app-header">
<div class="mobile-page-context" aria-live="polite">
<span id="mobilePageGroup">行情</span>
<strong id="mobilePageTitle">情绪周期</strong>
</div>
<div class="app-page-context" aria-live="polite">
<strong id="currentPageTitle">小白复盘</strong>
<span id="currentPageSubtitle"></span>
</div>
<section class="overview-strip" aria-label="当日复盘指标" data-overview-expanded="false">
<div class="market-tape" aria-label="市场概况">
<div class="tape-metric tape-sentiment sentiment-block">
<span class="metric-label">市场情绪</span>
<span class="tape-metric-value">
<strong id="sentimentScore">--</strong>
<em id="sentimentText" class="sentiment-text">等待数据</em>
</span>
<div class="sentiment-gauge" id="sentimentGauge" aria-hidden="true"><span>--</span></div>
</div>
<div class="tape-metric market-item">
<span class="metric-label">涨停</span>
<strong id="limitUpMetric" class="metric-value up">--</strong>
</div>
<div class="tape-metric market-item">
<span class="metric-label">跌停</span>
<strong id="limitDownMetric" class="metric-value down">--</strong>
</div>
<div class="tape-metric tape-optional market-item">
<span class="metric-label">炸板</span>
<strong id="brokenMetric" class="metric-value warning">--</strong>
</div>
<div class="tape-metric tape-optional market-item">
<span class="metric-label">封板率</span>
<strong id="sealRateMetric" class="metric-value">--</strong>
</div>
<div class="tape-metric market-item">
<span class="metric-label">两市成交</span>
<strong id="amountMetric" class="metric-value">--</strong>
</div>
<button id="overviewToggle" class="overview-toggle" type="button" aria-expanded="false" title="展开市场详情">
<span>详情</span><i data-lucide="chevron-down" aria-hidden="true"></i>
</button>
</div>
<div class="tape-detail">
<div class="tape-detail-item market-item"><span>市场情绪</span><strong class="tape-metric-value"><b id="detailSentimentScore">--</b><em id="detailSentimentText" class="sentiment-text">等待数据</em></strong></div>
<div class="tape-detail-item market-item"><span>上涨家数</span><strong id="tapeUp" class="up">--</strong></div>
<div class="tape-detail-item market-item"><span>下跌家数</span><strong id="tapeDown" class="down">--</strong></div>
<div class="tape-detail-item market-item"><span>涨停</span><strong id="tapeLimit" class="up">--</strong></div>
<div class="tape-detail-item market-item"><span>跌停</span><strong id="tapeLimitDown" class="down">--</strong></div>
<div class="tape-detail-item market-item"><span>炸板</span><strong id="detailBroken" class="warning">--</strong></div>
<div class="tape-detail-item market-item"><span>封板率</span><strong id="detailSealRate">--</strong></div>
<div class="tape-detail-item market-item"><span>两市成交</span><strong id="tapeAmount">--</strong></div>
<div class="tape-detail-item tape-detail-date market-item"><span>数据日期</span><strong id="dataDateMetric" class="metric-value small">--</strong></div>
</div>
</section>
<div class="header-actions">
<div class="header-date-group">
<button id="prevDate" class="icon-button" type="button" title="前一个交易日" aria-label="前一个交易日"><i data-lucide="chevron-left"></i></button>
<input id="tradeDate" class="date-input" type="date" aria-label="交易日期">
<button id="nextDate" class="icon-button" type="button" title="后一个交易日" aria-label="后一个交易日"><i data-lucide="chevron-right"></i></button>
</div>
<button id="globalSearchButton" class="icon-button global-search-button" type="button" title="全局搜索(Ctrl+K" aria-label="全局搜索"><i data-lucide="search"></i></button>
<button id="themeToggle" class="icon-button theme-toggle" type="button" title="切换到夜间模式" aria-label="切换到夜间模式" aria-pressed="false"><i data-lucide="moon"></i><span id="themeModeText">日间模式</span></button>
<button id="alertButton" class="icon-button alert-button" type="button" title="提醒中心" aria-label="提醒中心"><i data-lucide="bell"></i><span id="alertBadge" class="alert-badge" hidden>0</span></button>
<button id="assistantButton" class="icon-button assistant-button" type="button" title="复盘助手" aria-label="复盘助手"><i data-lucide="message-circle-more"></i></button>
<button id="headerMenuButton" class="icon-button header-menu-button" type="button" title="打开命令菜单" aria-label="打开命令菜单" aria-expanded="false" aria-controls="headerCommandGroup"><i data-lucide="ellipsis"></i></button>
<div id="headerCommandGroup" class="header-command-group">
<div class="mobile-command-shortcuts" aria-label="快捷工具">
<button class="button mobile-command-shortcut" type="button" data-mobile-command-target="globalSearchButton"><i data-lucide="search"></i><span>搜索</span></button>
<button class="button mobile-command-shortcut" type="button" data-mobile-command-target="themeToggle"><i data-lucide="moon"></i><span>外观</span></button>
<button class="button mobile-command-shortcut" type="button" data-mobile-command-target="alertButton"><i data-lucide="bell"></i><span>提醒</span></button>
<button class="button mobile-command-shortcut" type="button" data-mobile-command-target="assistantButton"><i data-lucide="message-circle-more"></i><span>助手</span></button>
</div>
<button id="refreshButton" class="button command-button" type="button" title="刷新"><i data-lucide="refresh-cw"></i><span>刷新</span></button>
<button id="syncButton" class="button primary command-button" type="button" title="后台刷新" hidden><i data-lucide="cloud-download"></i><span>后台刷新</span></button>
<button id="settingsButton" class="button command-button" type="button" title="系统管理" hidden><i data-lucide="settings-2"></i><span>系统管理</span></button>
<div class="account-menu-shell">
<div id="accountRoleBadges" class="account-role-badges" aria-label="账号身份">
<span id="accountAdminBadge" class="account-role-badge admin-role-badge" title="管理员" hidden><i data-lucide="shield-check"></i><span>管理员</span></span>
<button id="accountVipBadge" class="account-role-badge vip-role-badge" type="button" title="查看会员状态" hidden><b aria-hidden="true">V</b><span id="accountVipLabel">非会员</span></button>
</div>
<button id="accountButton" class="button account-button command-button" type="button" title="账号菜单" aria-haspopup="menu" aria-expanded="false" aria-controls="accountDropdown"><i data-lucide="circle-user-round"></i><span id="accountName">--</span><i class="account-menu-chevron" data-lucide="chevron-down"></i></button>
<div id="accountDropdown" class="account-dropdown" role="menu" hidden>
<div class="account-dropdown-head"><strong id="accountMenuName">--</strong><span id="accountMenuRole">普通用户</span></div>
<button type="button" role="menuitem" data-account-panel="profile"><i data-lucide="user-round"></i><span>个人资料</span><i data-lucide="chevron-right"></i></button>
<button type="button" role="menuitem" data-account-panel="membership"><i data-lucide="badge-check"></i><span>会员状态</span><i data-lucide="chevron-right"></i></button>
<button type="button" role="menuitem" data-account-panel="password"><i data-lucide="key-round"></i><span>修改密码</span><i data-lucide="chevron-right"></i></button>
<div class="account-dropdown-separator"></div>
<button id="switchAccountMenuButton" type="button" role="menuitem"><i data-lucide="repeat-2"></i><span>切换账号</span></button>
<button id="logoutMenuButton" class="account-menu-danger" type="button" role="menuitem"><i data-lucide="log-out"></i><span>退出</span></button>
</div>
</div>
</div>
</div>
</header>
<button id="mobileCommandBackdrop" class="mobile-command-backdrop" type="button" aria-label="关闭命令菜单" hidden></button>
<nav class="module-nav" aria-label="复盘模块">
<div class="sidebar-brand">
<div class="sidebar-brand-mark" aria-hidden="true"></div>
<strong>小白复盘</strong>
</div>
<div class="nav-group market-nav-group">
<div class="nav-group-label">市场复盘</div>
<button class="module-tab market-sub-tab active" type="button" data-view="sentimentCycleView" title="情绪周期"><i data-lucide="activity"></i><span>情绪周期</span></button>
<button class="module-tab mobile-primary-tab" type="button" data-view="limitPool" title="涨停池"><i data-lucide="flame"></i><span class="nav-label-desktop">涨停池</span><span class="nav-label-mobile">行情</span></button>
<button class="module-tab market-sub-tab" type="button" data-view="brokenView" title="炸板池"><i data-lucide="bomb"></i><span>炸板池</span></button>
<button class="module-tab market-sub-tab" type="button" data-view="downView" title="跌停板"><i data-lucide="trending-down"></i><span>跌停板</span></button>
<button class="module-tab market-sub-tab" type="button" data-view="yesterdayView" title="昨日涨停"><i data-lucide="history"></i><span>昨日涨停</span></button>
<button class="module-tab market-sub-tab" type="button" data-view="performanceView" title="涨停表现"><i data-lucide="chart-no-axes-combined"></i><span>涨停表现</span></button>
<button class="module-tab market-sub-tab" type="button" data-view="ladderView" title="市场天梯"><i data-lucide="layers-3"></i><span>市场天梯</span></button>
<button class="module-tab market-sub-tab" type="button" data-view="rotationView" title="板块轮动"><i data-lucide="refresh-cw"></i><span>板块轮动</span></button>
<button class="module-tab market-sub-tab" type="button" data-view="auctionView" title="集合竞价"><i data-lucide="timer-reset"></i><span>集合竞价</span></button>
<button class="module-tab market-sub-tab" type="button" data-view="themeLibraryView" title="题材库"><i data-lucide="library-big"></i><span>题材库</span></button>
<button class="module-tab market-sub-tab" type="button" data-view="popularityView" title="人气热榜"><i data-lucide="chart-no-axes-column-increasing"></i><span>人气热榜</span></button>
<button class="module-tab market-sub-tab" type="button" data-view="dragonView" title="龙虎榜"><i data-lucide="list-tree"></i><span>龙虎榜</span></button>
</div>
<div class="nav-group tool-nav-group">
<div class="nav-group-label">智能工具</div>
<button class="module-tab mobile-primary-tab" type="button" data-view="screenerView" title="智能选股"><i data-lucide="search-check"></i><span class="nav-label-desktop">智能选股</span><span class="nav-label-mobile">选股</span></button>
<button class="module-tab mobile-primary-tab" type="button" data-view="mentorView" title="问师"><i data-lucide="messages-square"></i><span>问师</span></button>
<button class="module-tab mobile-primary-tab" type="button" data-view="heavenView" title="问天"><i data-lucide="sparkles"></i><span>问天</span></button>
</div>
<div class="nav-group personal-nav-group">
<div class="nav-group-label">个人</div>
<button class="module-tab mobile-primary-tab" type="button" data-view="reviewWorkspaceView" title="我的复盘"><i data-lucide="notebook-pen"></i><span class="nav-label-desktop">我的复盘</span><span class="nav-label-mobile">复盘</span></button>
</div>
<button id="sidebarCollapseButton" class="sidebar-collapse-button" type="button" title="收起侧栏" aria-label="收起侧栏" aria-expanded="true"><i data-lucide="panel-left-close"></i><span>收起侧栏</span></button>
</nav>
<main class="app-main">
<label id="mobileMarketSelector" class="mobile-market-selector" hidden>
<span><i data-lucide="layout-dashboard"></i><b>行情视图</b></span>
<select id="mobileMarketViewSelect" aria-label="选择行情视图">
<option value="sentimentCycleView">情绪周期</option>
<option value="limitPool">涨停池</option>
<option value="brokenView">炸板池</option>
<option value="downView">跌停板</option>
<option value="yesterdayView">昨日涨停</option>
<option value="performanceView">涨停表现</option>
<option value="ladderView">市场天梯</option>
<option value="rotationView">板块轮动</option>
<option value="auctionView">集合竞价</option>
<option value="themeLibraryView">题材库</option>
<option value="popularityView">人气热榜</option>
<option value="dragonView">龙虎榜</option>
</select>
<i data-lucide="chevron-down" aria-hidden="true"></i>
</label>
<!-- Registered page fragments mount here. -->
</main>
</div>
<footer class="status-bar">
<span id="statusText">准备就绪</span>
<span class="risk-note">股市有风险,投资需谨慎</span>
<span id="updatedAt">--</span>
</footer>
<dialog id="tradeLogDialog" class="settings-dialog trade-log-dialog" aria-labelledby="tradeLogDialogTitle">
<div class="dialog-header">
<div><span class="dialog-eyebrow">我的复盘</span><h2 id="tradeLogDialogTitle">交易日志</h2></div>
<button id="closeTradeLogDialog" class="icon-button" type="button" aria-label="关闭" title="关闭"><i data-lucide="x"></i></button>
</div>
<form id="tradeLogForm" class="trade-log-form">
<div class="trade-log-form-grid">
<label class="form-field"><span>交易日</span><input id="tradeLogDate" type="date" required></label>
<label class="form-field"><span>股票代码</span><input id="tradeLogCode" inputmode="numeric" pattern="[0-9]{6}" maxlength="6" required placeholder="002141"></label>
<label class="form-field"><span>股票名称</span><input id="tradeLogName" maxlength="40" required placeholder="贤丰控股"></label>
<label class="form-field"><span>动作</span><select id="tradeLogAction"><option value="buy">买入</option><option value="sell">卖出</option><option value="add">加仓</option><option value="trim">减仓</option><option value="watch">观察</option></select></label>
<label class="form-field"><span>成交价格</span><input id="tradeLogPrice" type="number" min="0.001" step="0.001" required></label>
<label class="form-field"><span>数量</span><input id="tradeLogQuantity" type="number" min="0" step="100" value="0"></label>
<label class="form-field"><span>仓位 %</span><input id="tradeLogPosition" type="number" min="0" max="100" step="0.1" value="0"></label>
<label class="form-field"><span>盈亏金额(可选)</span><input id="tradeLogPnlAmount" type="number" step="0.01"></label>
<label class="form-field"><span>盈亏 %(可选)</span><input id="tradeLogPnlPct" type="number" step="0.01"></label>
<label class="form-field"><span>当时情绪</span><select id="tradeLogEmotion"><option value="calm">平静</option><option value="confident">笃定</option><option value="hesitant">犹豫</option><option value="anxious">焦虑</option><option value="impulsive">冲动</option></select></label>
<label class="form-field trade-tags-field"><span>标签</span><input id="tradeLogTags" maxlength="160" placeholder="计划内, 追高, 止损"></label>
</div>
<div class="trade-log-text-grid">
<label class="form-field"><span>交易逻辑</span><textarea id="tradeLogThesis" maxlength="2000" placeholder="为什么在这里采取动作"></textarea></label>
<label class="form-field"><span>执行复核</span><textarea id="tradeLogExecution" maxlength="2000" placeholder="是否按计划执行,偏差在哪里"></textarea></label>
</div>
<div class="dialog-actions"><button id="cancelTradeEdit" class="button" type="button">取消</button><button id="saveTradeLog" class="button primary" type="submit">保存交易</button></div>
</form>
</dialog>
<dialog id="watchlistDialog" class="settings-dialog watchlist-dialog" aria-labelledby="watchlistDialogTitle">
<div class="dialog-header">
<div><span class="dialog-eyebrow">自选跟踪</span><h2 id="watchlistDialogTitle">添加自选</h2></div>
<button id="closeWatchlistDialog" class="icon-button" type="button" aria-label="关闭" title="关闭"><i data-lucide="x"></i></button>
</div>
<form id="watchlistForm" class="watchlist-editor-form">
<div id="watchlistSearchField" class="form-field">
<label for="watchlistSearchInput">搜索股票</label>
<div class="watchlist-search-control"><i data-lucide="search"></i><input id="watchlistSearchInput" type="search" autocomplete="off" placeholder="输入股票代码或名称"></div>
<div id="watchlistSearchResults" class="watchlist-search-results" aria-live="polite"></div>
</div>
<div id="watchlistSelection" class="watchlist-selection" hidden>
<span class="watchlist-selection-icon"><i data-lucide="chart-candlestick"></i></span>
<div><strong id="watchlistSelectionName">--</strong><span><b id="watchlistSelectionCode">--</b><i id="watchlistSelectionSector">--</i></span></div>
<button id="changeWatchlistSelection" class="table-action" type="button">重选</button>
</div>
<label class="form-field" for="watchlistRemark"><span>跟踪备注</span><textarea id="watchlistRemark" maxlength="240" placeholder="记录关注逻辑、观察条件或失效信号"></textarea></label>
<div class="dialog-actions"><button id="cancelWatchlistEdit" class="button" type="button">取消</button><button id="saveWatchlist" class="button primary" type="submit" disabled>保存自选</button></div>
</form>
</dialog>
<dialog id="heavenReadingDialog" class="settings-dialog heaven-reading-dialog wentian-v2-dialog" aria-labelledby="heavenReadingDialogTitle">
<div class="dialog-header">
<div><span id="heavenReadingEyebrow" class="dialog-eyebrow">问天 · 观势</span><h2 id="heavenReadingDialogTitle">解读</h2></div>
<button id="closeHeavenReadingDialog" class="icon-button" type="button" aria-label="关闭" title="关闭"><i data-lucide="x"></i></button>
</div>
<div class="heaven-reading-tabs" role="tablist" aria-label="问天解读">
<button class="active" type="button" role="tab" data-heaven-reading-tab="current" aria-selected="true">本次解读</button>
<button type="button" role="tab" data-heaven-reading-tab="history" aria-selected="false">历史记录</button>
</div>
<section id="heavenReadingCurrent" class="heaven-reading-current" role="tabpanel">
<div id="heavenReadingLoading" class="heaven-reading-loading" hidden>
<canvas id="heavenReadingCanvas" aria-hidden="true"></canvas>
</div>
<div id="heavenReadingEmpty" class="empty-state">尚无本次解读</div>
<article id="heavenReadingResult" class="heaven-reading-result" hidden>
<header><div><span id="heavenReadingResultStatus">势已成</span><h3 id="heavenReadingSubject">--</h3></div><time id="heavenReadingCreatedAt">--</time></header>
<p id="heavenReadingSubjectDetail">--</p>
<div id="heavenReadingAnswer" class="heaven-reading-answer"></div>
</article>
<div id="heavenReadingError" class="inline-notice" hidden></div>
</section>
<section id="heavenReadingHistory" class="heaven-reading-history" role="tabpanel" hidden>
<div class="heaven-reading-history-list-wrap">
<div class="heaven-reading-history-heading"><strong id="heavenReadingHistoryTitle">观势记录</strong><span id="heavenReadingHistoryCount">0 条</span></div>
<div id="heavenReadingHistoryList" class="heaven-reading-history-list"></div>
</div>
<article id="heavenReadingHistoryDetail" class="heaven-reading-history-detail">
<div class="empty-state">选择一条记录查看完整解读</div>
</article>
</section>
</dialog>
<div id="stockPreviewBackdrop" class="stock-preview-backdrop" hidden></div>
<aside id="stockPreview" class="stock-preview" aria-label="行情预览" aria-live="polite" hidden>
<header class="stock-preview-header">
<div class="stock-preview-identity">
<span id="stockPreviewCode">--</span>
<strong id="stockPreviewName">正在加载</strong>
<small id="stockPreviewSector">--</small>
</div>
<div class="stock-preview-quote">
<strong id="stockPreviewPrice">--</strong>
<span id="stockPreviewChange">--</span>
</div>
<button id="closeStockPreview" class="icon-button stock-preview-close" type="button" title="关闭预览" aria-label="关闭预览"><i data-lucide="x"></i></button>
</header>
<div class="stock-preview-tabs" role="tablist" aria-label="行情图表">
<button class="stock-preview-tab" type="button" role="tab" aria-selected="false" data-preview-chart="intraday">分时</button>
<button class="stock-preview-tab active" type="button" role="tab" aria-selected="true" data-preview-chart="daily">日K</button>
<span id="stockPreviewDate">--</span>
</div>
<div class="stock-preview-chart-shell">
<canvas id="stockPreviewChart" width="488" height="232" aria-label="行情图" aria-describedby="stockPreviewSummary"></canvas>
<div id="stockPreviewLoading" class="stock-preview-loading">
<span class="spinner" aria-hidden="true"></span>
<span>正在读取行情</span>
</div>
</div>
<p id="stockPreviewSummary" class="stock-preview-summary">等待行情数据</p>
<footer class="stock-preview-footer">
<span id="stockPreviewSource">--</span>
<button id="openStockDetailFromPreview" class="button" type="button"><i data-lucide="maximize-2"></i><span>完整详情</span></button>
</footer>
</aside>
<dialog id="globalSearchDialog" class="global-search-dialog" aria-labelledby="globalSearchTitle">
<div class="global-search-shell">
<h2 id="globalSearchTitle" class="sr-only">全局搜索</h2>
<div class="global-search-head">
<i data-lucide="search" aria-hidden="true"></i>
<label class="sr-only" for="globalSearchInput">搜索股票、板块、题材或指数</label>
<input id="globalSearchInput" type="search" autocomplete="off" spellcheck="false" placeholder="搜索股票、板块、题材或指数" aria-controls="globalSearchResults" aria-autocomplete="list">
<kbd aria-label="快捷键 Ctrl 加 K">Ctrl K</kbd>
<button id="closeGlobalSearch" class="icon-button" type="button" aria-label="关闭搜索" title="关闭搜索"><i data-lucide="x"></i></button>
</div>
<div id="globalSearchResults" class="global-search-results" role="listbox" aria-labelledby="globalSearchTitle" aria-live="polite">
<div class="global-search-empty"><i data-lucide="corner-down-left"></i><p>输入名称或代码开始搜索</p><span>使用方向键选择,回车打开详情</span></div>
</div>
</div>
</dialog>
<dialog id="entityDetailDialog" class="stock-dialog entity-detail-dialog" aria-labelledby="entityDetailName">
<div class="dialog-header">
<div>
<span id="entityDetailCode" class="detail-code">--</span>
<h2 id="entityDetailName">--</h2>
</div>
<button id="closeEntityDetail" class="icon-button" type="button" aria-label="关闭" title="关闭"><i data-lucide="x"></i></button>
</div>
<div class="detail-price-line">
<strong id="entityDetailValue">--</strong>
<span id="entityDetailChange">--</span>
<span id="entityDetailType" class="streak-pill">--</span>
</div>
<section class="stock-chart-section">
<div class="detail-section-heading">
<h3>行情走势</h3>
<div class="chart-heading-controls">
<div class="segmented chart-mode-toggle" role="group" aria-label="详情图表周期">
<button class="segment active" type="button" data-entity-detail-chart="daily" aria-pressed="true">日K</button>
<button class="segment" type="button" data-entity-detail-chart="intraday" aria-pressed="false">分时</button>
</div>
<span id="entityDetailDate">--</span>
</div>
</div>
<canvas id="entityDetailChart" class="price-chart" width="680" height="300" aria-label="行情走势图"></canvas>
</section>
<section class="detail-section">
<h3>交易数据</h3>
<dl id="entityDetailMetrics" class="detail-grid"></dl>
</section>
</dialog>
<dialog id="stockDialog" class="stock-dialog" aria-labelledby="detailName">
<div class="dialog-header">
<div>
<span id="detailCode" class="detail-code">--</span>
<h2 id="detailName">--</h2>
</div>
<div class="dialog-header-actions">
<button id="stockHeavenButton" class="button stock-heaven-button" type="button"><i data-lucide="sparkles"></i><span>观势</span></button>
<button id="stockReminderButton" class="button" type="button"><i data-lucide="bell-plus"></i><span>设提醒</span></button>
<button id="watchStockButton" class="button" type="button">加入自选</button>
<button id="closeStockDialog" class="icon-button" type="button" aria-label="关闭" title="关闭"><i data-lucide="x"></i></button>
</div>
</div>
<div class="detail-price-line">
<strong id="detailPrice">--</strong>
<span id="detailChange">--</span>
<span id="detailStreak" class="streak-pill">--</span>
</div>
<section class="stock-chart-section">
<div class="detail-section-heading">
<h3>行情走势</h3>
<div class="chart-heading-controls">
<div class="segmented chart-mode-toggle" role="group" aria-label="股票图表周期">
<button class="segment active" type="button" data-stock-detail-chart="daily" aria-pressed="true">日K</button>
<button class="segment" type="button" data-stock-detail-chart="intraday" aria-pressed="false">分时</button>
</div>
<span id="chartSource">--</span>
</div>
</div>
<canvas id="priceChart" class="price-chart" width="680" height="300" aria-label="股票行情走势图"></canvas>
</section>
<section class="detail-section moneyflow-section">
<h3>当日资金流</h3>
<dl class="moneyflow-grid">
<div><dt>主力净额</dt><dd id="flowNet">--</dd></div>
<div><dt>大单净额</dt><dd id="flowLarge">--</dd></div>
<div><dt>中单净额</dt><dd id="flowMedium">--</dd></div>
<div><dt>小单净额</dt><dd id="flowSmall">--</dd></div>
</dl>
</section>
<section class="detail-section">
<h3>事件逻辑</h3>
<p id="detailReason">--</p>
<span id="detailSector" class="sector-chip">--</span>
<form id="reasonForm" class="inline-edit-form" hidden>
<input id="reasonInput" type="text" maxlength="200" placeholder="修订事件逻辑">
<button class="button" type="submit">保存修订</button>
</form>
</section>
<section class="detail-section">
<h3>交易数据</h3>
<dl class="detail-grid">
<div><dt>首次触板</dt><dd id="detailFirst">--</dd></div>
<div><dt>最后触板</dt><dd id="detailLast">--</dd></div>
<div><dt>开板次数</dt><dd id="detailOpen">--</dd></div>
<div><dt>换手率</dt><dd id="detailTurnover">--</dd></div>
<div><dt>成交额</dt><dd id="detailAmount">--</dd></div>
<div><dt>封单额</dt><dd id="detailSeal">--</dd></div>
</dl>
</section>
<section class="detail-section">
<h3>个股复盘笔记</h3>
<form id="stockNoteForm" class="journal-form compact-form">
<label class="form-field"><span>复盘内容</span><textarea id="stockNoteContent" maxlength="5000" placeholder="记录交易逻辑与盘面反馈"></textarea></label>
<label class="form-field"><span>明日计划</span><textarea id="stockNotePlan" maxlength="2000" placeholder="记录观察条件和应对计划"></textarea></label>
<div class="dialog-actions"><button class="button primary" type="submit">保存笔记</button></div>
</form>
<div id="stockNotes" class="notes-history compact-notes"></div>
</section>
</dialog>
<dialog id="alertsDialog" class="settings-dialog alerts-dialog" aria-labelledby="alertsDialogTitle">
<div class="dialog-header">
<div><span class="dialog-eyebrow">当前账号</span><h2 id="alertsDialogTitle">提醒中心</h2></div>
<button id="closeAlertsDialog" class="icon-button" type="button" aria-label="关闭" title="关闭"><i data-lucide="x"></i></button>
</div>
<div class="alerts-toolbar">
<div class="segmented" role="group" aria-label="提醒筛选">
<button class="segment active" type="button" data-alert-filter="all">全部</button>
<button class="segment" type="button" data-alert-filter="unread">未读</button>
</div>
<button id="markAllAlertsRead" class="button" type="button">全部已读</button>
</div>
<form id="alertForm" class="settings-section alert-form">
<div class="settings-section-heading"><h3>新建提醒</h3><span>仅站内</span></div>
<div class="alert-form-grid">
<label class="form-field"><span>标题</span><input id="alertTitle" maxlength="80" required placeholder="例如:复核开盘承接"></label>
<label class="form-field"><span>提醒日期</span><input id="alertDate" type="date" required></label>
<label class="form-field"><span>股票代码(可选)</span><input id="alertCode" maxlength="12" inputmode="numeric" placeholder="002141"></label>
</div>
<label class="form-field"><span>提醒内容(可选)</span><textarea id="alertContent" maxlength="500" placeholder="记录触发条件和应对动作"></textarea></label>
<div class="dialog-actions"><button class="button primary" type="submit">保存提醒</button></div>
</form>
<section class="settings-section alert-list-section">
<div class="settings-section-heading"><h3>提醒记录</h3><span id="alertListCount">0 条</span></div>
<div id="alertList" class="alert-list"></div>
</section>
</dialog>
<dialog id="assistantDialog" class="settings-dialog assistant-dialog" aria-labelledby="assistantDialogTitle">
<div class="dialog-header">
<div><span class="dialog-eyebrow">智能复盘</span><h2 id="assistantDialogTitle">复盘助手</h2></div>
<div class="dialog-header-actions">
<button id="clearAssistantMessages" class="button" type="button">清空对话</button>
<button id="closeAssistantDialog" class="icon-button" type="button" aria-label="关闭" title="关闭"><i data-lucide="x"></i></button>
</div>
</div>
<div id="assistantMemberGate" class="member-gate assistant-member-gate" hidden>
<div class="member-gate-icon"><i data-lucide="lock-keyhole"></i></div>
<div><strong>复盘助手仅对会员开放</strong><span>开通会员后可读取市场统计、策略跟踪与个人复盘记录,进行统一复盘分析。</span></div>
</div>
<div id="assistantMemberContent" class="assistant-member-content">
<div id="assistantMessages" class="assistant-messages" aria-live="polite">
<div class="empty-state">可以从市场、策略或自己的交易记录开始复盘</div>
</div>
<div class="assistant-quick-prompts" aria-label="快捷问题">
<button type="button" data-assistant-prompt="结合近十日情绪和今天的数据,当前市场处于什么位置?">市场位置</button>
<button type="button" data-assistant-prompt="总结当前市场主线,并说明证据和可能的失效条件。">市场主线</button>
<button type="button" data-assistant-prompt="结合我的策略跟踪和交易日志,找出最值得修正的一个行为模式。">交易复盘</button>
<button type="button" data-assistant-prompt="为下一个交易日给出条件化观察清单,不给无条件买卖指令。">明日清单</button>
</div>
<form id="assistantForm" class="assistant-form">
<label class="sr-only" for="assistantQuestion">向复盘助手提问</label>
<textarea id="assistantQuestion" maxlength="2000" placeholder="询问市场位置、主线、策略表现或自己的交易模式" required></textarea>
<div class="assistant-form-actions">
<button id="stopAssistant" class="button" type="button" hidden><i data-lucide="square"></i>停止</button>
<button id="sendAssistant" class="button primary" type="submit"><i data-lucide="send"></i>发送</button>
</div>
</form>
<p class="assistant-disclaimer">助手仅用于复盘与条件化计划,不执行交易,不构成投资建议。</p>
</div>
</dialog>
<dialog id="settingsDialog" class="settings-dialog account-settings-dialog" aria-labelledby="accountDialogTitle">
<div class="dialog-header">
<div>
<span class="dialog-eyebrow">当前账号</span>
<h2 id="accountDialogTitle">个人资料</h2>
</div>
<button id="closeSettingsDialog" class="icon-button" type="button" aria-label="关闭" title="关闭"><i data-lucide="x"></i></button>
</div>
<div id="connectionStatus" class="connection-status" aria-live="polite">正在读取账号状态</div>
<section class="settings-section membership-overview account-settings-panel" data-account-panel-content="membership" hidden>
<div class="settings-section-heading"><h3>会员状态</h3><span id="membershipBadge">普通用户</span></div>
<p id="membershipDetail" class="settings-lead">开通会员后可使用智能选股、问师、问天、复盘助手等智能功能。</p>
<p id="membershipQuotaHint" class="form-hint">会员默认每日智能分析额度 -- 次,由管理员统一设置。</p>
<div id="membershipUsage" class="membership-usage">今日智能分析 -- 次</div>
<div class="membership-status-grid">
<div><span>开通状态</span><strong id="membershipStateValue">未开通</strong></div>
<div><span>剩余时长</span><strong id="membershipRemainingValue">--</strong></div>
<div><span>今日智能分析</span><strong id="membershipUsageSummary">--</strong></div>
<div><span>剩余智能分析</span><strong id="membershipRemainingUsage">--</strong></div>
</div>
<div class="membership-comparison" aria-label="会员权益对比">
<div class="membership-comparison-head"><span>功能</span><span>普通用户</span><span>会员用户</span></div>
<div><span>行情、搜索与个股详情</span><b>可用</b><b>可用</b></div>
<div><span>自选股、复盘记录与交易日志</span><b>可用</b><b>可用</b></div>
<div><span>智能选股</span><b class="muted">不可用</b><b class="available">可用</b></div>
<div><span>问师与问天</span><b class="muted">不可用</b><b class="available">可用</b></div>
<div><span>复盘助手</span><b class="muted">不可用</b><b class="available">可用</b></div>
<div><span>每日智能分析额度</span><b class="muted"></b><b class="available">按会员额度使用</b></div>
</div>
<div class="membership-topup-row"><span><i data-lucide="battery-charging"></i>智能分析加油包</span><button id="membershipTopupButton" class="button" type="button" disabled>暂不可用</button></div>
</section>
<section class="settings-section account-birth-section account-settings-panel" data-account-panel-content="profile">
<div class="settings-section-heading"><h3>个人资料</h3><span id="birthProfileStatus">尚未设置</span></div>
<p class="settings-lead privacy-note"><i data-lucide="lock-keyhole"></i><span>出生信息仅对当前账号可见并加密保存,不会向其他用户公开。</span></p>
<form id="accountBirthForm" class="account-birth-form">
<label class="form-field"><span>出生日期</span><input id="accountBirthDate" type="date" min="1900-01-01" max="2100-12-31" required></label>
<label class="form-field"><span>出生时间</span><input id="accountBirthTime" type="time" required></label>
<label class="form-field"><span>性别</span><select id="accountBirthGender"><option value="unspecified">不指定</option><option value="male"></option><option value="female"></option></select></label>
<div class="dialog-actions">
<button id="deleteBirthProfileButton" class="button danger-button" type="button">删除资料</button>
<button class="button primary" type="submit">保存资料</button>
</div>
</form>
<p class="form-hint">原始信息加密保存且不在观气页回显;智能解读只使用排盘后的派生结果。</p>
</section>
<section class="settings-section password-section account-settings-panel" data-account-panel-content="password" hidden>
<div class="settings-section-heading"><h3>修改密码</h3><span>仅当前账号</span></div>
<form id="passwordForm" class="password-form">
<label class="form-field"><span>当前密码</span><input id="currentPassword" type="password" autocomplete="current-password" required></label>
<label class="form-field"><span>新密码</span><input id="newPassword" type="password" minlength="8" maxlength="128" autocomplete="new-password" required></label>
<label class="form-field"><span>确认新密码</span><input id="confirmPassword" type="password" minlength="8" maxlength="128" autocomplete="new-password" required></label>
<div class="dialog-actions"><button class="button primary" type="submit">更新密码</button></div>
</form>
</section>
</dialog>
<dialog id="adminDialog" class="settings-dialog admin-dialog" aria-labelledby="adminDialogTitle">
<div class="dialog-header">
<div><span class="dialog-eyebrow">管理员</span><h2 id="adminDialogTitle">系统配置</h2></div>
<button id="closeAdminDialog" class="icon-button" type="button" aria-label="关闭" title="关闭"><i data-lucide="x"></i></button>
</div>
<div id="adminConnectionStatus" class="connection-status" aria-live="polite">正在读取系统状态</div>
<div class="admin-section-picker">
<label for="adminSectionSelect">管理项目</label>
<select id="adminSectionSelect">
<option value="market">行情管理</option>
<option value="models">模型池</option>
<option value="members">会员管理</option>
</select>
</div>
<div class="admin-panel" data-admin-panel="market">
<form id="systemMarketForm" class="settings-section">
<div class="settings-section-heading"><h3>公共行情</h3><span id="systemDataStatus">待检查</span></div>
<label class="form-field"><span>Tushare Token</span><input id="systemTokenInput" type="password" autocomplete="off" minlength="20" placeholder="留空保留现有 Token"></label>
<label class="form-field"><span>iFinD Refresh Token</span><input id="systemIfindTokenInput" type="password" autocomplete="off" maxlength="2048" placeholder="留空保留现有 Token"></label>
<label class="switch-control"><input id="systemBackgroundRefresh" type="checkbox"><span>启用交易时段后台刷新</span></label>
<p class="form-hint">所有用户读取同一份后台快照,页面不会随后台任务自动重绘。</p>
<div class="dialog-actions admin-inline-actions"><button id="adminRefreshButton" class="button" type="button"><i data-lucide="refresh-cw"></i>立即后台刷新</button><button class="button primary" type="submit">保存行情配置</button></div>
</form>
<section class="settings-section">
<div class="settings-section-heading"><h3>历史数据回补</h3><span>管理员任务</span></div>
<div class="backfill-controls">
<label class="form-field"><span>开始日期</span><input id="backfillStart" type="date"></label>
<label class="form-field"><span>结束日期</span><input id="backfillEnd" type="date"></label>
</div>
<div class="dialog-actions"><button id="backfillButton" class="button" type="button">开始回补</button></div>
</section>
</div>
<div class="admin-panel" data-admin-panel="models" hidden>
<form id="systemModelsForm" class="settings-section">
<div class="settings-section-heading"><h3>平台模型池</h3><span>会员共享</span></div>
<div class="model-role-selectors">
<label class="form-field"><span>主模型</span><select id="platformPrimaryModelSelect"></select></label>
<label class="form-field"><span>辅助模型</span><select id="platformFallbackModelSelect"><option value="">不启用辅助模型</option></select></label>
</div>
<div id="modelPoolList" class="model-pool-list"></div>
<div class="dialog-actions admin-inline-actions"><button id="addPlatformModel" class="button" type="button"><i data-lucide="plus"></i>添加模型</button><button class="button primary" type="submit">保存模型池</button></div>
</form>
</div>
<div class="admin-panel" data-admin-panel="members" hidden>
<form id="membershipSettingsForm" class="settings-section membership-limit-form">
<div class="settings-section-heading"><h3>会员调用额度</h3><span>每日自动重置</span></div>
<label class="form-field compact-number-field"><span>会员每日智能分析上限</span><input id="memberDailyLimit" type="number" min="1" max="1000" value="50"></label>
<div class="dialog-actions"><button class="button primary" type="submit">保存调用额度</button></div>
</form>
<section class="settings-section">
<div class="settings-section-heading"><h3>会员账号</h3><span>手动开通与续期</span></div>
<div id="adminUsersList" class="admin-users-list"></div>
</section>
</div>
</dialog>
<div id="loadingOverlay" class="loading-overlay" hidden>
<div class="loading-box">
<span class="spinner" aria-hidden="true"></span>
<div class="loading-copy">
<strong id="loadingTitle">正在加载复盘数据</strong>
<small id="loadingHint">请稍候</small>
</div>
<div class="loading-progress" aria-hidden="true"><i></i></div>
</div>
</div>
<div id="toast" class="toast" role="status" hidden></div>
<script src="/bootstrap.js?v=20260803-2" defer></script>
</body>
</html>