Show tablet trade records as close-record table with action column.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-30 00:12:10 +08:00
parent a6b3c4a657
commit 92c222584e
4 changed files with 249 additions and 135 deletions
+109 -49
View File
@@ -5,6 +5,75 @@
<link rel="stylesheet" href="{{ url_for('static', filename='css/records.css') }}?v={{ asset_v }}">
{% endblock %}
{% block content %}
{% macro trade_detail_json(t) -%}
{{ {
"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,
"close_price": t.close_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 }}
{%- endmacro %}
{% macro trade_symbol_cell(t) %}
<div class="dash-symbol-cell">
<div class="dash-symbol-title">
{{ t.symbol_name or t.symbol }}
{% if t.symbol_exchange %}<span class="dash-symbol-ex text-muted">{{ t.symbol_exchange }}</span>{% endif %}
{% if t.symbol_is_main %}<span class="badge planned dash-main-badge">主力</span>{% endif %}
{% if t.symbol and (t.symbol_name or '')|lower != (t.symbol or '')|lower %}
<span class="text-accent">{{ t.symbol }}</span>
{% endif %}
</div>
</div>
{% endmacro %}
{% macro trade_pnl_cell(v) %}
{% if v is not none %}{% set n = v|float %}<span class="{% if n > 0 %}pnl-pos{% elif n < 0 %}pnl-neg{% endif %}">{{ ('+' if n > 0 else '') ~ ('%.2f'|format(n)) }} 元</span>{% else %}—{% endif %}
{% endmacro %}
{% macro trade_verify_form(t) %}
<form method="post" action="{{ url_for('update_trade', tid=t.id) }}" class="records-trade-verify-form">
<input type="hidden" name="symbol_name" value="{{ t.symbol_name or t.symbol }}">
<input type="hidden" name="monitor_type" value="{{ t.monitor_type }}">
<input type="hidden" name="direction" value="{{ t.direction }}">
<input type="hidden" name="entry_price" value="{{ t.entry_price }}">
<input type="hidden" name="stop_loss" value="{{ t.stop_loss }}">
<input type="hidden" name="take_profit" value="{{ t.take_profit }}">
<input type="hidden" name="close_price" value="{{ t.close_price or '' }}">
<input type="hidden" name="lots" value="{{ t.lots }}">
<input type="hidden" name="margin" value="{{ t.margin or '' }}">
<input type="hidden" name="holding_minutes" value="{{ t.holding_minutes or 0 }}">
<input type="hidden" name="open_time" value="{{ t.open_time or '' }}">
<input type="hidden" name="close_time" value="{{ t.close_time or '' }}">
<input type="hidden" name="pnl" value="{{ t.pnl or '' }}">
<input type="hidden" name="result" value="{{ t.result }}">
<button type="submit" class="btn-verify" {% if t.verified %}disabled{% endif %}>核对修改</button>
</form>
{% endmacro %}
{% macro trade_row_actions(t, detail_class) %}
<div class="trade-actions records-trade-row-actions">
<button type="button" class="btn-link {{ detail_class }}">详情</button>
<a href="{{ url_for('fill_review_from_trade', tid=t.id) }}" class="btn-fill">填入复盘</a>
{{ trade_verify_form(t) }}
<a href="{{ url_for('del_trade', tid=t.id) }}" class="btn-del" onclick="return confirm('删除?')">删除</a>
</div>
{% endmacro %}
<div class="records-page">
<div class="card records-equity-card" style="margin-bottom:1.25rem">
<h2>资金曲线</h2>
@@ -28,37 +97,12 @@
<input type="checkbox" id="trade-edit-switch">
<span>修改/核对开关(开启后可编辑关键字段)</span>
</label>
<div class="records-mobile-list" id="records-trade-mobile">
<div class="records-mobile-list records-phone-only" id="records-trade-mobile">
{% for t in trades %}
{% set trade_pnl = t.pnl_net if t.pnl_net is not none else t.pnl %}
{% set trade_px = t.close_price if t.close_price else t.entry_price %}
{% set pnl_cls = 'is-profit' if trade_pnl and trade_pnl > 0 else ('is-loss' if trade_pnl and trade_pnl < 0 else 'is-flat') %}
<div class="records-trade-row" data-trade-id="{{ t.id }}" 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,
"close_price": t.close_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),
"verify_url": url_for("update_trade", tid=t.id)
} | tojson }}'>
<div class="records-trade-row" data-trade-id="{{ t.id }}" data-trade='{{ trade_detail_json(t)|trim }}'>
<div class="records-trade-main">
<div class="records-trade-head">
<span class="records-trade-title">
@@ -75,28 +119,6 @@
盈亏 <span class="records-mobile-pnl {{ pnl_cls }}">{{ trade_pnl if trade_pnl is not none else '-' }}</span>
</div>
</div>
<div class="records-trade-actions">
<button type="button" class="btn-link records-trade-detail-btn">详情</button>
<a href="{{ url_for('fill_review_from_trade', tid=t.id) }}" class="btn-fill">复盘</a>
<form method="post" action="{{ url_for('update_trade', tid=t.id) }}" class="records-trade-verify-form">
<input type="hidden" name="symbol_name" value="{{ t.symbol_name or t.symbol }}">
<input type="hidden" name="monitor_type" value="{{ t.monitor_type }}">
<input type="hidden" name="direction" value="{{ t.direction }}">
<input type="hidden" name="entry_price" value="{{ t.entry_price }}">
<input type="hidden" name="stop_loss" value="{{ t.stop_loss }}">
<input type="hidden" name="take_profit" value="{{ t.take_profit }}">
<input type="hidden" name="close_price" value="{{ t.close_price or '' }}">
<input type="hidden" name="lots" value="{{ t.lots }}">
<input type="hidden" name="margin" value="{{ t.margin or '' }}">
<input type="hidden" name="holding_minutes" value="{{ t.holding_minutes or 0 }}">
<input type="hidden" name="open_time" value="{{ t.open_time or '' }}">
<input type="hidden" name="close_time" value="{{ t.close_time or '' }}">
<input type="hidden" name="pnl" value="{{ t.pnl or '' }}">
<input type="hidden" name="result" value="{{ t.result }}">
<button type="submit" class="btn-verify" {% if t.verified %}disabled{% endif %}>{% if t.verified %}已核对{% else %}核对{% endif %}</button>
</form>
<a href="{{ url_for('del_trade', tid=t.id) }}" class="btn-del" onclick="return confirm('删除?')">删除</a>
</div>
<div class="records-trade-phone-foot">
<span class="records-mobile-chevron">详情 </span>
</div>
@@ -105,6 +127,44 @@
<p class="records-mobile-empty">暂无交易记录</p>
{% endfor %}
</div>
<div class="card-scroll records-trade-table-wrap records-tablet-only">
<table class="dashboard-table records-trade-table">
<thead>
<tr>
<th>品种</th>
<th>方向</th>
<th>手数</th>
<th>开仓</th>
<th>平仓</th>
<th>盈亏</th>
<th>净盈亏</th>
<th>平仓时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for t in trades %}
<tr data-trade-id="{{ t.id }}" data-trade='{{ trade_detail_json(t)|trim }}'>
<td>{{ trade_symbol_cell(t) }}</td>
<td>
<span class="badge dir {% if t.direction == 'long' %}dir-long{% else %}dir-short{% endif %}">
{{ '做多' if t.direction == 'long' else '做空' }}
</span>
</td>
<td>{% if t.lots is not none %}{{ '%.2f'|format(t.lots|float) }}{% else %}—{% endif %}</td>
<td>{% if t.entry_price is not none %}{{ '%.2f'|format(t.entry_price|float) }}{% else %}—{% endif %}</td>
<td>{% if t.close_price is not none %}{{ '%.2f'|format(t.close_price|float) }}{% elif t.entry_price is not none %}{{ '%.2f'|format(t.entry_price|float) }}{% else %}—{% endif %}</td>
<td>{{ trade_pnl_cell(t.pnl) }}</td>
<td>{{ trade_pnl_cell(t.pnl_net) }}</td>
<td>{{ (t.close_time or '')[:16].replace('T', ' ') or '—' }}</td>
<td>{{ trade_row_actions(t, 'records-tablet-detail-btn') }}</td>
</tr>
{% else %}
<tr><td colspan="9" class="text-muted">暂无交易记录</td></tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="trade-table-wrap records-desktop-only">
<table class="trade-table">
<thead>