Add responsive mobile layout, records cards, and tablet settings fold fix.
Mobile gets compact trade/records UI with detail modals; static assets are cache-busted and settings cards fold correctly on tablet grid layout. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+107
-5
@@ -1,7 +1,11 @@
|
||||
{# Copyright (c) 2025-2026 马建军. All rights reserved. 专有软件,详见 LICENSE.zh-CN.txt #}
|
||||
{% extends "base.html" %}
|
||||
{% block title %}交易记录与复盘 - 国内期货 · 交易复盘系统{% endblock %}
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/records.css') }}?v={{ asset_v }}">
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="records-page">
|
||||
<div class="card records-equity-card" style="margin-bottom:1.25rem">
|
||||
<h2>资金曲线</h2>
|
||||
<div class="card-body">
|
||||
@@ -20,11 +24,61 @@
|
||||
{% else %}
|
||||
<p class="hint" style="margin-top:0">CTP 未连接时仅显示本地数据库记录;连接后打开本页会自动同步柜台成交。</p>
|
||||
{% endif %}
|
||||
<label class="trade-switch-label">
|
||||
<label class="trade-switch-label records-desktop-only">
|
||||
<input type="checkbox" id="trade-edit-switch">
|
||||
<span>修改/核对开关(开启后可编辑关键字段)</span>
|
||||
</label>
|
||||
<div class="trade-table-wrap">
|
||||
<div class="records-mobile-list" id="records-trade-mobile">
|
||||
{% for t in trades %}
|
||||
<button type="button" class="records-mobile-item records-trade-item" data-trade='{{ {
|
||||
"symbol": t.symbol_name or t.symbol,
|
||||
"symbol_code": t.symbol,
|
||||
"monitor_type": t.monitor_type,
|
||||
"source": "柜台" if t.source == "ctp" else "本地",
|
||||
"direction": "做多" if t.direction == "long" else "做空",
|
||||
"entry_price": t.entry_price,
|
||||
"stop_loss": t.stop_loss,
|
||||
"take_profit": t.take_profit,
|
||||
"lots": t.lots,
|
||||
"margin": t.margin,
|
||||
"margin_pct": t.margin_pct,
|
||||
"holding_minutes": t.holding_minutes or 0,
|
||||
"open_time": t.open_time,
|
||||
"close_time": t.close_time,
|
||||
"pnl": t.pnl,
|
||||
"fee": t.fee,
|
||||
"pnl_net": t.pnl_net,
|
||||
"equity_after": t.equity_after,
|
||||
"result": t.result,
|
||||
"verified": t.verified,
|
||||
"fill_review_url": url_for("fill_review_from_trade", tid=t.id),
|
||||
"del_url": url_for("del_trade", tid=t.id)
|
||||
} | tojson }}'>
|
||||
<div class="records-mobile-item-head">
|
||||
<span class="records-mobile-symbol">{{ t.symbol_name or t.symbol }}</span>
|
||||
<span class="badge dir">{{ '做多' if t.direction == 'long' else '做空' }}</span>
|
||||
</div>
|
||||
<div class="records-mobile-item-meta">
|
||||
<span>{{ (t.close_time or t.open_time or '')[:16].replace('T', ' ') }}</span>
|
||||
{% if t.result == '止盈' %}<span class="badge profit">{{ t.result }}</span>
|
||||
{% elif t.result == '止损' %}<span class="badge loss">{{ t.result }}</span>
|
||||
{% elif t.result in ('移动止盈', '保本止盈') %}<span class="badge profit">{{ t.result }}</span>
|
||||
{% elif t.result == '手动平仓' %}<span class="badge result-manual">{{ t.result }}</span>
|
||||
{% else %}<span class="badge result-external">{{ t.result }}</span>{% endif %}
|
||||
<span>{{ '柜台' if t.source == 'ctp' else '本地' }}</span>
|
||||
</div>
|
||||
<div class="records-mobile-item-foot">
|
||||
<span class="records-mobile-pnl {{ 'is-profit' if t.pnl_net and t.pnl_net > 0 else ('is-loss' if t.pnl_net and t.pnl_net < 0 else 'is-flat') }}">
|
||||
净盈亏 {{ t.pnl_net if t.pnl_net is not none else '-' }}
|
||||
</span>
|
||||
<span class="records-mobile-chevron">查看详情 ›</span>
|
||||
</div>
|
||||
</button>
|
||||
{% else %}
|
||||
<p class="records-mobile-empty">暂无交易记录</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="trade-table-wrap records-desktop-only">
|
||||
<table class="trade-table">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -243,7 +297,45 @@
|
||||
<button type="submit" class="btn-primary">筛选</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
<div class="card-scroll">
|
||||
<div class="records-mobile-list records-review-mobile">
|
||||
{% for r in reviews %}
|
||||
<button type="button" class="records-mobile-item review-view-btn{% if r.is_emotion %} is-emotion{% endif %}" data-review='{{ {
|
||||
"symbol": r.symbol_name or r.symbol, "symbol_code": r.symbol,
|
||||
"direction": "做多" if r.direction=="long" else "做空",
|
||||
"lots": r.lots, "timeframe": r.timeframe,
|
||||
"entry_price": r.entry_price, "stop_loss": r.stop_loss, "take_profit": r.take_profit,
|
||||
"close_price": r.close_price,
|
||||
"open_time": r.open_time, "close_time": r.close_time,
|
||||
"holding_duration": r.holding_duration,
|
||||
"initial_pnl": r.initial_pnl, "actual_pnl": r.actual_pnl, "pnl": r.pnl,
|
||||
"fee": r.fee, "pnl_net": r.pnl_net,
|
||||
"open_type": r.open_type,
|
||||
"exit_trigger": r.exit_trigger, "exit_supplement": r.exit_supplement,
|
||||
"watch_after_breakeven": r.watch_after_breakeven,
|
||||
"new_position_while_occupied": r.new_position_while_occupied,
|
||||
"is_emotion": r.is_emotion, "behavior_tags": r.behavior_tags,
|
||||
"notes": r.notes, "screenshot": r.screenshot
|
||||
} | tojson }}'>
|
||||
<div class="records-mobile-item-head">
|
||||
<span class="records-mobile-symbol">{{ r.symbol_name or r.symbol }}</span>
|
||||
<span class="badge dir">{{ '多' if r.direction == 'long' else '空' }}</span>
|
||||
</div>
|
||||
<div class="records-mobile-item-meta">
|
||||
<span>{{ r.close_time[:16].replace('T', ' ') if r.close_time else '' }}</span>
|
||||
{% if r.is_emotion %}<span class="badge emotion">情绪单</span>{% endif %}
|
||||
</div>
|
||||
<div class="records-mobile-item-foot">
|
||||
<span class="records-mobile-pnl {{ 'is-profit' if r.pnl_net and r.pnl_net > 0 else ('is-loss' if r.pnl_net and r.pnl_net < 0 else 'is-flat') }}">
|
||||
净盈亏 {{ r.pnl_net if r.pnl_net is not none else '-' }}
|
||||
</span>
|
||||
<span class="records-mobile-chevron">查看详情 ›</span>
|
||||
</div>
|
||||
</button>
|
||||
{% else %}
|
||||
<p class="records-mobile-empty">暂无复盘记录</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="card-scroll records-desktop-only">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -307,6 +399,14 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="trade-detail-modal" class="modal-mask">
|
||||
<div class="modal-box review-modal-fullscreen">
|
||||
<span class="modal-close">✕</span>
|
||||
<h3>交易详情</h3>
|
||||
<div id="trade-detail-modal-body" class="review-modal-body"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if auto_records %}
|
||||
<div class="card" style="margin-top:1rem">
|
||||
<h2>系统自动记录(止盈/止损)</h2>
|
||||
@@ -327,13 +427,15 @@
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block extra_js %}
|
||||
<script src="https://unpkg.com/lightweight-charts@4.2.0/dist/lightweight-charts.standalone.production.js"></script>
|
||||
<script>window.__EQUITY_CURVE__ = {{ equity_curve | default([]) | tojson }};</script>
|
||||
<script src="{{ url_for('static', filename='js/equity_curve.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/review.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/trades.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/review.js') }}?v={{ asset_v }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/records.js') }}?v={{ asset_v }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/trades.js') }}?v={{ asset_v }}"></script>
|
||||
{% if prefill %}
|
||||
<script>
|
||||
function bootReviewPrefill() {
|
||||
|
||||
Reference in New Issue
Block a user