c7aae67881
Read-only overview of live orders, key monitors, and strategy; show options/hedge only when present. Toggle via system settings nav prefs. Co-authored-by: Cursor <cursoragent@cursor.com>
358 lines
25 KiB
HTML
358 lines
25 KiB
HTML
{# Hub iframe tab fragment — shared via embed_templates #}
|
|
{% macro period_stats_pane(period_key, s) %}
|
|
{% set win_pct = s.win_rate_pct if s.win_rate_pct is not none else 0 %}
|
|
{% set profit_sum = (s.net_pnl_u + s.loss_sum_u) if s.closed_count else 0 %}
|
|
{% set loss_sum = s.loss_sum_u %}
|
|
{% set pnl_total = profit_sum + loss_sum %}
|
|
{% set profit_bar_w = (profit_sum / pnl_total * 100) if pnl_total > 0 else 0 %}
|
|
{% set loss_bar_w = (loss_sum / pnl_total * 100) if pnl_total > 0 else 0 %}
|
|
{% set net_cls = 'pos-pnl-profit' if s.net_pnl_u > 0 else ('pos-pnl-loss' if s.net_pnl_u < 0 else '') %}
|
|
<div class="stats-period-pane" data-stats-period="{{ period_key }}" role="tabpanel"{% if period_key != 'day' %} hidden{% endif %}>
|
|
<div class="stats-period-range">{{ s.range_label }}</div>
|
|
<div class="inst-stats-viz">
|
|
{% if s.closed_count %}
|
|
<div class="inst-stats-kpis">
|
|
<div class="inst-stats-kpi inst-stats-kpi--pnl">
|
|
<span class="inst-stats-kpi-val {{ net_cls }}">{% if s.net_pnl_u > 0 %}+{% endif %}{{ funds_fmt(s.net_pnl_u) }}U</span>
|
|
<span class="inst-stats-kpi-lbl">净盈亏</span>
|
|
</div>
|
|
<div class="inst-stats-kpi inst-stats-kpi--win">
|
|
<div class="inst-stats-ring" style="--win-pct: {{ win_pct }}">
|
|
<span class="inst-stats-ring-label">{% if s.win_rate_pct is not none %}{{ win_pct|round(0)|int }}%{% else %}—{% endif %}</span>
|
|
</div>
|
|
<span class="inst-stats-kpi-lbl">{{ s.win_count }}胜 {{ s.loss_count }}负</span>
|
|
</div>
|
|
<div class="inst-stats-kpi inst-stats-kpi--trades">
|
|
<span class="inst-stats-kpi-val">{{ s.opens_count }} / {{ s.closed_count }}</span>
|
|
<span class="inst-stats-kpi-lbl">开单 / 平仓</span>
|
|
</div>
|
|
</div>
|
|
<div class="inst-stats-block">
|
|
<div class="inst-stats-block-title">盈亏构成</div>
|
|
<div class="inst-stats-stacked-bar">
|
|
<div class="inst-stats-stacked-fill inst-stats-stacked-fill--profit" style="width: {{ '%.1f'|format(profit_bar_w) }}%"></div>
|
|
<div class="inst-stats-stacked-fill inst-stats-stacked-fill--loss" style="width: {{ '%.1f'|format(loss_bar_w) }}%"></div>
|
|
</div>
|
|
<div class="inst-stats-bar-labels">
|
|
<span class="pos-pnl-profit">盈利 {{ funds_fmt(profit_sum) }}U</span>
|
|
<span class="pos-pnl-loss">亏损 {{ funds_fmt(loss_sum) }}U</span>
|
|
</div>
|
|
</div>
|
|
<div class="inst-stats-block inst-stats-block--risk">
|
|
<div class="inst-stats-risk-grid">
|
|
<div class="inst-stats-risk-item">
|
|
<span class="k">最大回撤</span>
|
|
<span class="v pos-pnl-loss">{{ funds_fmt(s.max_drawdown_u) }}U</span>
|
|
</div>
|
|
<div class="inst-stats-risk-item">
|
|
<span class="k">连续亏损</span>
|
|
<span class="v">{{ s.consecutive_losses }} 笔</span>
|
|
</div>
|
|
<div class="inst-stats-risk-item">
|
|
<span class="k">最长连亏日</span>
|
|
<span class="v">{{ s.max_loss_streak_days }} 天</span>
|
|
</div>
|
|
<div class="inst-stats-risk-item">
|
|
<span class="k">最大亏损日</span>
|
|
<span class="v">{% if s.worst_day %}{{ s.worst_day }} ({{ funds_fmt(s.worst_day_pnl) }}U){% else %}—{% endif %}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% else %}
|
|
<p class="inst-stats-empty">当前区间暂无平仓数据</p>
|
|
{% endif %}
|
|
</div>
|
|
<details class="inst-stats-details" open>
|
|
<summary>详细指标</summary>
|
|
<div class="stats-detail">
|
|
<div class="stat-item"><div class="label">开单次数</div><div class="value">{{ s.opens_count }}</div></div>
|
|
<div class="stat-item"><div class="label">平仓笔数</div><div class="value">{{ s.closed_count }}</div></div>
|
|
<div class="stat-item"><div class="label">胜率</div><div class="value">{% if s.win_rate_pct is not none %}{{ s.win_rate_pct }}%{% else %}-{% endif %}</div></div>
|
|
<div class="stat-item"><div class="label">净盈亏(U)</div><div class="value">{{ funds_fmt(s.net_pnl_u) }}</div></div>
|
|
<div class="stat-item"><div class="label">亏损额合计(U)</div><div class="value">{{ funds_fmt(s.loss_sum_u) }}</div></div>
|
|
<div class="stat-item"><div class="label">单笔最大亏损(U)</div><div class="value">{% if s.max_single_loss is not none %}{{ funds_fmt(s.max_single_loss) }}{% else %}-{% endif %}</div></div>
|
|
<div class="stat-item"><div class="label">单笔最大盈利(U)</div><div class="value">{% if s.max_single_profit is not none %}{{ funds_fmt(s.max_single_profit) }}{% else %}-{% endif %}</div></div>
|
|
<div class="stat-item"><div class="label">最大回撤(U)</div><div class="value">{{ funds_fmt(s.max_drawdown_u) }}</div></div>
|
|
<div class="stat-item"><div class="label">当前连续亏损笔数</div><div class="value">{{ s.consecutive_losses }}</div></div>
|
|
<div class="stat-item"><div class="label">最长连续亏损(交易日)</div><div class="value">{{ s.max_loss_streak_days }} 天</div></div>
|
|
<div class="stat-item"><div class="label">期内最大亏损日</div><div class="value">{% if s.worst_day %}{{ s.worst_day }}({{ funds_fmt(s.worst_day_pnl) }}U){% else %}-{% endif %}</div></div>
|
|
</div>
|
|
</details>
|
|
</div>
|
|
{% endmacro %}
|
|
<div class="grid">
|
|
{% if page == 'dashboard' %}
|
|
{% include 'dashboard_panel.html' %}
|
|
{% elif page == 'key_monitor' %}
|
|
{% include 'key_monitor_panel.html' %}
|
|
{% elif page == 'trade' %}
|
|
<div class="dual-panel-grid" style="grid-column:1/-1">
|
|
<div class="card">
|
|
<div style="display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap;margin-bottom:8px">
|
|
<h2 style="margin-bottom:0">实盘下单监控</h2>
|
|
{% if focus_order_id %}
|
|
<a href="/order_focus?order_id={{ focus_order_id }}" class="btn-del" style="text-decoration:none;background:#1f3a5a;color:#8fc8ff">放大查看K线(100根)</a>
|
|
{% else %}
|
|
<span class="btn-del" style="background:#2f2f44;color:#9aa;cursor:not-allowed">暂无持仓可放大</span>
|
|
{% endif %}
|
|
</div>
|
|
{% include order_rule_tips_tpl %}
|
|
<form id="add-order-form" action="/add_order" method="post" class="form-row" data-risk-percent="{{ risk_percent }}">
|
|
{% from 'trade_policy_fields.html' import trade_policy_symbol, trade_policy_direction with context %}
|
|
{{ trade_policy_symbol('symbol', 'order-symbol') }}
|
|
{{ trade_policy_direction('direction', 'order-direction') }}
|
|
<select id="sltp-mode" name="sltp_mode">
|
|
<option value="fixed_rr" selected>止盈止损:固定盈亏比</option>
|
|
<option value="price">止盈止损:价格模式</option>
|
|
<option value="pct">止盈止损:百分比模式</option>
|
|
</select>
|
|
{% from 'order_entry_model_fields.html' import order_entry_type_fields with context %}
|
|
{{ order_entry_type_fields() }}
|
|
{% from 'order_leverage_fields.html' import order_leverage_fields with context %}
|
|
{{ order_leverage_fields() }}
|
|
{% if not intraday_discipline %}
|
|
<label style="display:flex;align-items:center;gap:4px;font-size:.82rem;color:#cfd3ef">
|
|
<input type="checkbox" name="breakeven_enabled" value="1" checked> 启用移动保本(关闭则仅保留初始止损与交易所挂单)
|
|
</label>
|
|
<span id="order-time-close-wrap" class="order-time-close-wrap" style="display:inline-flex;align-items:center;gap:4px;font-size:.82rem;color:#cfd3ef">
|
|
<label style="display:inline-flex;align-items:center;gap:4px;margin:0;cursor:pointer">
|
|
<input type="checkbox" name="time_close_enabled" value="1" id="order-time-close-cb"> 时间平仓
|
|
</label>
|
|
<select name="time_close_hours" id="order-time-close-hours" title="持仓满该时长后自动平仓">
|
|
<option value="1">1h</option>
|
|
<option value="2">2h</option>
|
|
<option value="4" selected>4h</option>
|
|
</select>
|
|
</span>
|
|
{% else %}
|
|
<input type="hidden" name="breakeven_enabled" value="0">
|
|
{% endif %}
|
|
<label style="display:flex;align-items:center;gap:4px;font-size:.82rem;color:#cfd3ef">
|
|
<input type="checkbox" name="order_chart" value="true"> 开仓后生成多周期K线图(各周期100根,含开平仓标记)
|
|
</label>
|
|
{% from 'symbol_live_price_snippet.html' import symbol_live_price_hint %}
|
|
{{ symbol_live_price_hint('order-symbol-live-price', 'order-symbol', 'order-direction') }}
|
|
<span class="symbol-live-price-note">下单成交价以交易所成交回报为准</span>
|
|
<input id="order-sl" name="sl" step="any" placeholder="止损价格" required>
|
|
<input id="order-fixed-rr" name="fixed_rr" type="number" min="0.01" step="0.01" placeholder="盈亏比(默认1.5)" value="1.5" title="止盈距离=止损距离×盈亏比">
|
|
<input id="order-tp" name="tgt" step="any" placeholder="止盈价格" style="display:none">
|
|
<input id="order-sl-pct" name="sl_pct" type="number" min="0.01" step="0.01" placeholder="止损%" style="display:none">
|
|
<input id="order-tp-pct" name="tp_pct" type="number" min="0.01" step="0.01" placeholder="止盈%" style="display:none">
|
|
<button type="submit">{{ open_position_button_label }}</button>
|
|
</form>
|
|
{% include 'order_plan_preview_bar.html' %}
|
|
</div>
|
|
<div class="card">
|
|
<h2 style="margin-bottom:8px">实时持仓</h2>
|
|
{% if ui_orphan_recovery_enabled %}
|
|
{% if not order and orphan_live_positions %}
|
|
{% set o = orphan_live_positions[0] %}
|
|
<div id="orphan-position-recover" class="orphan-recover-banner" style="display:block;margin-bottom:10px;padding:10px 12px;background:#2a2210;border:1px solid #6b5420;border-radius:6px;font-size:.9rem;color:#e8d5a8">
|
|
检测到交易所仍有 <strong>{{ o.symbol }}</strong> {{ '空' if o.direction == 'short' else '多' }}仓,但本地监控已中断(误同步时可能无交易记录).
|
|
{% if o.recoverable_monitor_id %}
|
|
<button type="button" class="pos-entrust-btn" onclick="recoverLivePosition({{ o.recoverable_monitor_id }})">恢复监控{% if o.plan_stop_loss and o.plan_take_profit %}并挂止盈止损{% endif %}</button>
|
|
{% else %}
|
|
未找到可恢复的监控记录,需在服务器数据库处理.
|
|
{% endif %}
|
|
</div>
|
|
{% else %}
|
|
<div id="orphan-position-recover" class="orphan-recover-banner" style="display:none;margin-bottom:10px;padding:10px 12px;background:#2a2210;border:1px solid #6b5420;border-radius:6px;font-size:.9rem;color:#e8d5a8"></div>
|
|
{% endif %}
|
|
{% endif %}
|
|
<div class="panel-scroll pos-list pos-list-live">
|
|
{% for o in order %}
|
|
<div class="pos-card" id="order-row-{{ o.id }}"
|
|
data-monitor-id="{{ o.id }}"
|
|
data-symbol="{{ o.symbol }}"
|
|
data-direction="{{ o.direction }}"
|
|
data-plan-sl="{% if o.stop_loss %}{{ price_fmt(o.symbol, o.stop_loss) }}{% endif %}"
|
|
data-plan-tp="{% if o.take_profit %}{{ price_fmt(o.symbol, o.take_profit) }}{% endif %}"
|
|
data-entry="{% if o.trigger_price %}{{ price_fmt(o.symbol, o.trigger_price) }}{% endif %}">
|
|
<div class="pos-card-head">
|
|
<div class="pos-card-symbol">
|
|
<strong>{{ o.exchange_symbol or o.symbol }}</strong>
|
|
{% if o.time_close_enabled %}
|
|
<span class="pos-symbol-time-close pos-meta-on pos-time-close-meta" id="order-time-close-wrap-{{ o.id }}"
|
|
data-close-at-ms="{{ o.time_close_at_ms or '' }}">
|
|
<span class="pos-time-close-label">时间平仓 {{ o.time_close_hours or '' }}h</span>
|
|
· <span class="pos-time-close-cd" id="order-time-close-cd-{{ o.id }}">--:--:--</span>
|
|
</span>
|
|
{% endif %}
|
|
{% include 'force_close_order_badge.html' %}
|
|
<span class="pos-side-badge {{ 'pos-side-long' if o.direction == 'long' else 'pos-side-short' }}">{{ '做多' if o.direction == 'long' else '做空' }}</span>
|
|
</div>
|
|
<div class="pos-head-actions">
|
|
{% if not intraday_discipline %}
|
|
<button type="button" class="pos-entrust-btn" onclick="openTpslEntrustModal({{ o.id }})">委托</button>
|
|
<a href="/del_order/{{ o.id }}" class="pos-close-btn" onclick="return confirm('删除会触发手动平仓,继续?')">平仓</a>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="pos-meta">
|
|
<span class="pos-meta-item">来源: {{ o.monitor_type|default('下单监控', true) }}{% if o.key_signal_type %} · {{ o.key_signal_type }}{% endif %}</span>
|
|
<span class="pos-meta-item">{% if o.entry_model_label %}开仓: {{ o.entry_model_label }}{% elif intraday_discipline %}开仓: —{% else %}风格: {{ '波段单' if o.trade_style == 'swing' else '趋势单' }}{% endif %}</span>
|
|
<span class="pos-meta-item">风险: {% if position_sizing_mode == 'full_margin' %}{{ funds_fmt(o.risk_amount) if o.risk_amount is not none else '-' }}U{% else %}{{ o.risk_percent or '-' }}%≈{{ funds_fmt(o.risk_amount) if o.risk_amount is not none else '-' }}U{% endif %}</span>
|
|
<span class="pos-meta-item" id="order-latest-risk-wrap-{{ o.id }}" style="display:none">最新风险: —</span>
|
|
<span class="pos-meta-item {% if not intraday_discipline %}{% if o.breakeven_enabled %}pos-meta-on{% else %}pos-meta-off{% endif %}{% endif %}">
|
|
{% if intraday_discipline %}
|
|
{% elif o.breakeven_enabled %}移动保本:开 {{ o.breakeven_rr_trigger or '-' }}R→{{ price_fmt(o.symbol, o.breakeven_price) }}{% else %}移动保本:关{% endif %}
|
|
</span>
|
|
<span class="pos-meta-item" id="order-be-wrap-{{ o.id }}" style="display:none"><span class="pos-breakeven-badge">已保本</span></span>
|
|
</div>
|
|
<div class="pos-grid">
|
|
<div class="pos-cell">
|
|
<span class="pos-label">成交价</span>
|
|
<span class="pos-value">{{ price_fmt(o.symbol, o.trigger_price) }}</span>
|
|
</div>
|
|
<div class="pos-cell">
|
|
<span class="pos-label">止损</span>
|
|
<span class="pos-value" id="order-plan-sl-{{ o.id }}">{{ price_fmt(o.symbol, o.stop_loss) if o.stop_loss else '—' }}</span>
|
|
</div>
|
|
<div class="pos-cell">
|
|
<span class="pos-label">止盈</span>
|
|
<span class="pos-value" id="order-plan-tp-{{ o.id }}">{{ price_fmt(o.symbol, o.take_profit) if o.take_profit else '—' }}</span>
|
|
</div>
|
|
<div class="pos-cell">
|
|
<span class="pos-label">盈亏比</span>
|
|
<span class="pos-value" id="order-rr-{{ o.id }}">{% if o.rr_ratio is not none %}{{ '%g'|format(o.rr_ratio) }}:1{% else %}-:1{% endif %}</span>
|
|
</div>
|
|
<div class="pos-cell">
|
|
<span class="pos-label">张数</span>
|
|
<span class="pos-value" id="order-contracts-{{ o.id }}">{% if o.order_amount is not none %}{{ '%.2f'|format(o.order_amount) }}{% else %}—{% endif %}</span>
|
|
</div>
|
|
<div class="pos-cell">
|
|
<span class="pos-label">盈利金额</span>
|
|
<span class="pos-value pos-tp-profit" id="order-tp-profit-{{ o.id }}">—</span>
|
|
</div>
|
|
<div class="pos-cell">
|
|
<span class="pos-label">标记价</span>
|
|
<span class="pos-value" id="order-price-{{ o.id }}">-</span>
|
|
</div>
|
|
<div class="pos-cell">
|
|
<span class="pos-label">浮盈亏</span>
|
|
<span class="pos-value" id="order-pnl-{{ o.id }}">-</span>
|
|
</div>
|
|
</div>
|
|
<div class="pos-footer">
|
|
<span>保证金: <span id="order-ex-margin-{{ o.id }}">-</span></span>
|
|
<span>计划基数: {{ funds_fmt(o.margin_capital) if o.margin_capital is not none else '-' }}U</span>
|
|
<span>杠杆: {{ o.leverage or '-' }}x</span>
|
|
<span>仓位占比: {{ o.position_ratio if o.position_ratio is not none else '-' }}%</span>
|
|
<span>开仓时间: {{ (o.opened_at or '-')[:16] }}</span>
|
|
<span>持仓时长: <span class="order-hold-duration" id="order-hold-duration-{{ o.id }}" data-order-opened-ms="{{ o.opened_at_ms or '' }}">—</span></span>
|
|
</div>
|
|
<div class="pos-ex-orders">
|
|
<div class="pos-ex-orders-title">交易所止盈止损</div>
|
|
<div class="pos-ex-order-row">
|
|
<span class="pos-ex-order-main" id="ex-sl-text-{{ o.id }}">止损:加载中…</span>
|
|
{% if not intraday_discipline %}
|
|
<button type="button" class="pos-ex-cancel-btn" id="ex-sl-cancel-{{ o.id }}" disabled onclick="cancelExchangeTpsl({{ o.id }}, 'sl')">撤单</button>
|
|
{% endif %}
|
|
</div>
|
|
<div class="pos-ex-order-row">
|
|
<span class="pos-ex-order-main" id="ex-tp-text-{{ o.id }}">止盈:加载中…</span>
|
|
{% if not intraday_discipline %}
|
|
<button type="button" class="pos-ex-cancel-btn" id="ex-tp-cancel-{{ o.id }}" disabled onclick="cancelExchangeTpsl({{ o.id }}, 'tp')">撤单</button>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% else %}
|
|
<div class="pos-empty">暂无持仓</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
|
|
<div id="tpsl-modal" class="tpsl-modal-backdrop" onclick="if(event.target===this)closeTpslEntrustModal()">
|
|
<div class="tpsl-modal" onclick="event.stopPropagation()">
|
|
<h3 id="tpsl-modal-title">挂止盈止损</h3>
|
|
<p style="font-size:.78rem;color:#8892b0;margin:0 0 10px">将先撤销该合约已有 TP/SL,再按下列价格重挂.</p>
|
|
<div class="form-row">
|
|
<select id="tpsl-modal-mode" onchange="toggleTpslModalMode()">
|
|
<option value="price">价格模式</option>
|
|
<option value="pct">百分比模式</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-row">
|
|
<input id="tpsl-modal-sl" step="any" placeholder="止损价格">
|
|
<input id="tpsl-modal-tp" step="any" placeholder="止盈价格">
|
|
</div>
|
|
<div class="form-row">
|
|
<input id="tpsl-modal-sl-pct" type="number" min="0.01" step="0.01" placeholder="止损%" style="display:none">
|
|
<input id="tpsl-modal-tp-pct" type="number" min="0.01" step="0.01" placeholder="止盈%" style="display:none">
|
|
</div>
|
|
<div class="tpsl-modal-actions">
|
|
<button type="button" class="tpsl-modal-cancel" onclick="closeTpslEntrustModal()">取消</button>
|
|
<button type="button" class="tpsl-modal-submit" onclick="submitTpslEntrust()">先撤后挂</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
{% elif page in ('strategy', 'strategy_trend', 'strategy_roll') %}
|
|
{% include 'strategy_trading_page.html' %}
|
|
{% elif page == 'strategy_records' %}
|
|
{% include 'strategy_records_page.html' %}
|
|
{% elif page == 'options' %}
|
|
{% include 'options_panel.html' %}
|
|
{% elif page == 'options_review' %}
|
|
{% include 'options_review_panel.html' %}
|
|
{% elif page == 'hedge_plan' %}
|
|
{% include 'hedge_plan_panel.html' %}
|
|
{% endif %}
|
|
|
|
|
|
|
|
{% if page == 'records' %}
|
|
{% include 'records_panel.html' %}
|
|
{% endif %}
|
|
{% if page == 'env_config' %}
|
|
{% include 'env_config_panel.html' %}
|
|
{% endif %}
|
|
|
|
{% if page == 'risk_policy' %}
|
|
{% include 'risk_policy_panel.html' %}
|
|
{% endif %}
|
|
|
|
{% if page == 'settings' %}
|
|
{% include 'settings_panel.html' %}
|
|
{% endif %}
|
|
|
|
{% if page == 'stats' %}
|
|
<div class="card stats-card full" id="stats-card">
|
|
<div style="display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap">
|
|
<h2 style="margin-bottom:0">数据统计</h2>
|
|
<button type="button" class="stats-toggle" id="stats-toggle-btn" onclick="toggleStatsCard()">折叠</button>
|
|
</div>
|
|
<div class="stats-content" id="stats-content">
|
|
<div class="sub" style="margin-bottom:12px;color:#8892b0;font-size:.82rem">
|
|
统计分析按<strong>北京时间 {{ stats_bundle.stats_reset_hour }}:00</strong>切日计入(与顶栏 UTC 列表窗无关).历史总开仓(累计):
|
|
<strong style="color:#cfd3ef">{{ stats_bundle.total_opens_all }}</strong> 次
|
|
</div>
|
|
<div class="form-row" style="margin-bottom:14px;align-items:center">
|
|
<label style="display:flex;align-items:center;gap:8px;font-size:.88rem;color:#cfd3ef">
|
|
统计品类
|
|
<select id="stats-segment-select" onchange="switchStatsSegment()" style="min-width:200px">
|
|
{% for seg in stats_bundle.segments %}
|
|
<option value="{{ seg.key }}">{{ seg.title }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</label>
|
|
</div>
|
|
{% for seg in stats_bundle.segments %}
|
|
<div class="stats-segment-block stats-segment-panel" data-stats-segment="{{ seg.key }}"{% if not loop.first %} style="display:none"{% endif %}>
|
|
<div class="stats-period-tabs" role="tablist" aria-label="统计周期">
|
|
<button type="button" class="stats-period-tab active" data-stats-period="day" role="tab" aria-selected="true" onclick="switchStatsPeriod('day')">日统计</button>
|
|
<button type="button" class="stats-period-tab" data-stats-period="week" role="tab" aria-selected="false" onclick="switchStatsPeriod('week')">周统计</button>
|
|
<button type="button" class="stats-period-tab" data-stats-period="month" role="tab" aria-selected="false" onclick="switchStatsPeriod('month')">月统计</button>
|
|
</div>
|
|
{{ period_stats_pane("day", seg.day) }}
|
|
{{ period_stats_pane("week", seg.week) }}
|
|
{{ period_stats_pane("month", seg.month) }}
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|