Add shared records review pagination for all three exchanges.
Paginate trade records, journals, and AI history at 5 per page with soft in-card flips; hide the journal form until 填入复盘. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -95,6 +95,8 @@ function openAiInlineResultFullscreen(title, elementId){
|
||||
|
||||
const journalCache = {};
|
||||
const reviewCache = {};
|
||||
window.journalCache = journalCache;
|
||||
window.reviewCache = reviewCache;
|
||||
|
||||
function formatJournalExitOneLine(o){
|
||||
const t = (o.early_exit_trigger || "").trim();
|
||||
@@ -579,7 +581,6 @@ function fillJournalFromTrade(t){
|
||||
}
|
||||
recomputeJournalRealRr();
|
||||
if(typeof syncEarlyExitNoteRequired === "function") syncEarlyExitNoteRequired();
|
||||
alert("已填入下方复盘表单,请手动补充主观原因.");
|
||||
}
|
||||
|
||||
function recomputeJournalRealRr(){
|
||||
|
||||
@@ -302,185 +302,8 @@
|
||||
|
||||
|
||||
{% if page == 'records' %}
|
||||
<div class="card full records-card">
|
||||
<h2>交易记录</h2>
|
||||
<div class="form-row" style="margin-bottom:10px;gap:8px">
|
||||
<label style="display:flex;align-items:center;gap:6px;font-size:.82rem;color:#cfd3ef">
|
||||
<input id="review-mode-toggle" type="checkbox">
|
||||
修改/核对开关(开启后可编辑关键字段)
|
||||
</label>
|
||||
</div>
|
||||
<div class="table-wrap">
|
||||
<table>
|
||||
<tr><th>品种</th><th>下单类型</th><th>开仓类型</th><th>方向</th><th>成交</th><th>止损(开仓)</th><th>止盈</th><th>基数</th><th>杠杆</th><th>持仓分钟</th><th>开仓时间(北京)</th><th>平仓时间(北京)</th><th>盈亏U</th><th>结果</th><th>操作</th></tr>
|
||||
{% for r in record %}
|
||||
<tr id="trade-row-{{ r.id }}">
|
||||
{% set pnl_val = (r.pnl_amount or 0)|float %}
|
||||
<td>{{ r.symbol }}</td>
|
||||
<td>{{ r.monitor_type }}{% if r.key_signal_type %} · {{ r.key_signal_type }}{% endif %}</td>
|
||||
<td>{{ r.effective_entry_reason or '-' }}</td>
|
||||
<td><span class="badge {{ 'direction-long' if r.direction == 'long' else 'direction-short' }}">{{ '做多' if r.direction == 'long' else '做空' }}</span></td>
|
||||
<td>{{ price_fmt(r.symbol, r.trigger_price) }}</td>
|
||||
{% set stop_show = r.display_open_stop_loss or r.initial_stop_loss or r.stop_loss %}
|
||||
{% set tp_show = r.effective_take_profit or r.take_profit %}
|
||||
<td>{{ price_fmt(r.symbol, stop_show) }}</td>
|
||||
<td>{{ price_fmt(r.symbol, tp_show) }}</td>
|
||||
<td>{% if r.margin_capital is not none and r.margin_capital != '' %}{{ funds_fmt(r.margin_capital) }}{% else %}-{% endif %}</td>
|
||||
<td>{{ r.leverage or '-' }}</td>
|
||||
<td>{{ r.effective_hold_minutes or 0 }}</td>
|
||||
<td>{{ (r.effective_opened_at or '-')[:16] }}</td>
|
||||
<td>{{ (r.effective_closed_at or r.created_at or '-')[:16] }}</td>
|
||||
{% set pnl_val = (r.effective_pnl_amount or 0)|float %}
|
||||
<td><span class="{{ 'pnl-profit' if pnl_val > 0 else ('pnl-loss' if pnl_val < 0 else '') }}">{{ funds_fmt(r.effective_pnl_amount or 0) }}</span>{% if r.display_pnl_source == 'exchange' %}<span style="font-size:.68rem;color:#6ab88a">所</span>{% elif r.display_pnl_source != 'reviewed' %}<span style="font-size:.68rem;color:#8892b0">估</span>{% endif %}</td>
|
||||
<td>
|
||||
{% set effective_result = r.effective_result %}
|
||||
{% if effective_result in ["止盈","保本止盈","移动止盈"] %}<span class="badge profit">{{ effective_result }}</span>
|
||||
{% elif effective_result in ["止损","强制清仓","手动平仓"] %}<span class="badge loss">{{ effective_result }}</span>
|
||||
{% elif effective_result == "时间平仓" %}<span class="badge miss">{{ effective_result }}</span>
|
||||
{% else %}<span class="badge">{{ effective_result or '-' }}</span>{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
type="button"
|
||||
class="table-del"
|
||||
style="background:#1f3a5a;color:#8fc8ff;margin-right:6px"
|
||||
onclick='fillJournalFromTrade({{ {
|
||||
"symbol": r.symbol,
|
||||
"monitor_type": r.monitor_type,
|
||||
"key_signal_type": r.key_signal_type or "",
|
||||
"direction": r.direction,
|
||||
"trigger_price": r.trigger_price,
|
||||
"stop_loss": r.display_open_stop_loss or r.initial_stop_loss or r.stop_loss,
|
||||
"take_profit": r.effective_take_profit or r.take_profit,
|
||||
"opened_at": r.effective_opened_at,
|
||||
"closed_at": r.effective_closed_at,
|
||||
"pnl_amount": r.effective_pnl_amount,
|
||||
"result": r.effective_result,
|
||||
"risk_amount": r.risk_amount,
|
||||
"effective_entry_reason": r.effective_entry_reason or ""
|
||||
}|tojson|safe }})'
|
||||
>填入复盘</button>
|
||||
<button
|
||||
type="button"
|
||||
class="table-del review-edit-btn"
|
||||
style="background:#1f3a5a;color:#8fc8ff;margin-right:6px"
|
||||
onclick='editTradeRecordReview({{ {
|
||||
"id": r.id,
|
||||
"opened_at": r.effective_opened_at,
|
||||
"closed_at": r.effective_closed_at,
|
||||
"stop_loss": r.effective_stop_loss or r.initial_stop_loss or r.stop_loss,
|
||||
"take_profit": r.effective_take_profit or r.take_profit,
|
||||
"pnl_amount": r.effective_pnl_amount,
|
||||
"result": r.effective_result,
|
||||
"miss_reason": r.effective_miss_reason,
|
||||
"effective_entry_reason": r.effective_entry_reason or ""
|
||||
}|tojson|safe }})'
|
||||
disabled
|
||||
>核对修改</button>
|
||||
<button type="button" class="table-del" onclick="deleteTradeRecord({{ r.id }})">删除</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card full journal-card">
|
||||
<h2>交易复盘记录上传(含截图)</h2>
|
||||
<form id="journal-form" action="/add_journal" method="post" enctype="multipart/form-data">
|
||||
<input type="hidden" name="risk_amount_hint" id="risk-amount-hint">
|
||||
<input type="hidden" name="entry_price_hint" id="entry-price-hint">
|
||||
<input type="hidden" name="stop_loss_hint" id="stop-loss-hint">
|
||||
<input type="hidden" name="exit_price_hint" id="exit-price-hint">
|
||||
<input type="hidden" name="direction_hint" id="direction-hint">
|
||||
{% from 'journal_form_fields.html' import journal_form_fields %}
|
||||
{{ journal_form_fields(entry_reason_options, order_type_options) }}
|
||||
{% from 'journal_upload_slots.html' import journal_upload_slots %}
|
||||
{{ journal_upload_slots() }}
|
||||
<div class="form-row journal-chart-options" style="flex-wrap:wrap;align-items:center">
|
||||
<label style="display:flex;align-items:center;gap:6px;font-size:.82rem;color:#cfd3ef">
|
||||
<input type="checkbox" name="journal_exchange_chart" value="true">
|
||||
保存时自动生成 K 线图并作为截图
|
||||
</label>
|
||||
<label style="font-size:.82rem;color:#9aa">周期1</label>
|
||||
<select name="journal_chart_tf1" style="min-width:72px">
|
||||
{% for tf in journal_chart_tf_choices %}
|
||||
<option value="{{ tf }}" {% if tf == journal_chart_default_tf1 %}selected{% endif %}>{{ tf }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<label style="font-size:.82rem;color:#9aa">周期2</label>
|
||||
<select name="journal_chart_tf2" style="min-width:72px">
|
||||
{% for tf in journal_chart_tf_choices %}
|
||||
<option value="{{ tf }}" {% if tf == journal_chart_default_tf2 %}selected{% endif %}>{{ tf }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<label style="font-size:.82rem;color:#9aa">K线数</label>
|
||||
<select name="journal_chart_limit" style="min-width:72px">
|
||||
{% for n in [100, 150, 200, 250, 300, 400, 500] %}
|
||||
<option value="{{ n }}" {% if n == journal_chart_default_limit %}selected{% endif %}>{{ n }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<label style="font-size:.82rem;color:#9aa">K线截止</label>
|
||||
<select name="journal_chart_anchor" id="journal-chart-anchor" style="min-width:96px" title="K线窗口右端对齐的时间">
|
||||
<option value="close" {% if journal_chart_default_anchor == 'close' %}selected{% endif %}>平仓时间</option>
|
||||
<option value="now" {% if journal_chart_default_anchor == 'now' %}selected{% endif %}>当前时间</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="sub" id="journal-chart-anchor-hint" style="font-size:.72rem;color:#8892b0;margin-top:2px;margin-bottom:0">双周期上下排列;截止=平仓时间:开仓前背景至平仓;截止=当前时间:最近 N 根至此刻(可看平仓后走势);标注开仓,平仓与止损位</div>
|
||||
<div class="mood-grid">
|
||||
<label><input type="checkbox" name="mood_issues" value="怕踏空">怕踏空</label>
|
||||
<label><input type="checkbox" name="mood_issues" value="报复开仓">报复开仓</label>
|
||||
<label><input type="checkbox" name="mood_issues" value="盈利飘了">盈利飘了</label>
|
||||
<label><input type="checkbox" name="mood_issues" value="拿不住单">拿不住单</label>
|
||||
<label><input type="checkbox" name="mood_issues" value="扛单">扛单</label>
|
||||
<label><input type="checkbox" name="mood_issues" value="重仓违规">重仓违规</label>
|
||||
</div>
|
||||
<textarea name="note" rows="2" placeholder="备注"></textarea>
|
||||
<button type="submit" style="margin-top:8px">保存复盘记录</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="card full review-card" id="review-card">
|
||||
<div class="review-card-head">
|
||||
<h2>AI复盘(按交易记录)</h2>
|
||||
<button type="button" class="review-card-fs-btn" id="review-card-fs-btn" onclick="toggleReviewCardFullscreen()">全屏</button>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<input type="date" id="day_date">
|
||||
<button type="button" id="gen-daily-btn" onclick="genDaily()">生成日复盘</button>
|
||||
<button type="button" onclick="exportDailyBundleMd()" style="background:#1f3a5a">导出当日日复盘MD</button>
|
||||
<input type="date" id="week_start">
|
||||
<input type="date" id="week_end">
|
||||
<button type="button" id="gen-weekly-btn" onclick="genWeekly()">生成周复盘</button>
|
||||
<button type="button" onclick="exportWeeklyBundleMd()" style="background:#1f3a5a">导出当周复盘MD</button>
|
||||
</div>
|
||||
<div class="ai-result-wrap" id="daily_result_wrap" style="display:none">
|
||||
<div id="daily_result" class="ai-result"></div>
|
||||
<div class="ai-result-toolbar">
|
||||
<button type="button" class="btn-fs" onclick="openAiInlineResultFullscreen('日复盘结果', 'daily_result')">全屏查看</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ai-result-wrap" id="weekly_result_wrap" style="display:none">
|
||||
<div id="weekly_result" class="ai-result"></div>
|
||||
<div class="ai-result-toolbar">
|
||||
<button type="button" class="btn-fs" onclick="openAiInlineResultFullscreen('周复盘结果', 'weekly_result')">全屏查看</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-list" style="margin-top:10px">
|
||||
<div class="panel-item">
|
||||
<strong>交易复盘记录</strong>
|
||||
<div id="journal-list"></div>
|
||||
</div>
|
||||
<div class="panel-item">
|
||||
<strong>AI历史复盘</strong>
|
||||
<div id="review-list"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include 'records_panel.html' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if page == 'env_config' %}
|
||||
{% include 'env_config_panel.html' %}
|
||||
{% endif %}
|
||||
@@ -529,3 +352,4 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
@@ -108,11 +108,12 @@ const ORDER_ENTRY_MODEL_CODE_TO_CATEGORY = {{ entry_model_code_to_category | toj
|
||||
<script src="/static/key_monitor_form.js?v=2"></script>
|
||||
<script src="/static/instance_stats.js?v=4"></script>
|
||||
{% include 'embed_boot_scripts.html' %}
|
||||
<script src="/static/records_review_page.js?v=1"></script>
|
||||
<script>
|
||||
window.__INSTANCE_DISPLAY__ = {{ display | tojson }};
|
||||
</script>
|
||||
<script src="/static/instance_settings_prefs.js?v=13"></script>
|
||||
<script src="/static/instance_live.js?v=5"></script>
|
||||
<script src="/static/instance_embed.js?v=23"></script>
|
||||
<script src="/static/instance_embed.js?v=24"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -376,185 +376,8 @@
|
||||
|
||||
|
||||
{% if page == 'records' %}
|
||||
<div class="card full records-card">
|
||||
<h2>交易记录</h2>
|
||||
<div class="form-row" style="margin-bottom:10px;gap:8px">
|
||||
<label style="display:flex;align-items:center;gap:6px;font-size:.82rem;color:#cfd3ef">
|
||||
<input id="review-mode-toggle" type="checkbox">
|
||||
修改/核对开关(开启后可编辑关键字段)
|
||||
</label>
|
||||
</div>
|
||||
<div class="table-wrap">
|
||||
<table>
|
||||
<tr><th>品种</th><th>下单类型</th><th>开仓类型</th><th>方向</th><th>成交</th><th>止损(开仓)</th><th>止盈</th><th>基数</th><th>杠杆</th><th>持仓分钟</th><th>开仓时间(北京)</th><th>平仓时间(北京)</th><th>盈亏U</th><th>结果</th><th>操作</th></tr>
|
||||
{% for r in record %}
|
||||
<tr id="trade-row-{{ r.id }}">
|
||||
{% set pnl_val = (r.pnl_amount or 0)|float %}
|
||||
<td>{{ r.symbol }}</td>
|
||||
<td>{{ r.monitor_type }}{% if r.key_signal_type %} · {{ r.key_signal_type }}{% endif %}</td>
|
||||
<td>{{ r.effective_entry_reason or '-' }}</td>
|
||||
<td><span class="badge {{ 'direction-long' if r.direction == 'long' else 'direction-short' }}">{{ '做多' if r.direction == 'long' else '做空' }}</span></td>
|
||||
<td>{{ price_fmt(r.symbol, r.trigger_price) }}</td>
|
||||
{% set stop_show = r.display_open_stop_loss or r.initial_stop_loss or r.stop_loss %}
|
||||
{% set tp_show = r.effective_take_profit or r.take_profit %}
|
||||
<td>{{ price_fmt(r.symbol, stop_show) }}</td>
|
||||
<td>{{ price_fmt(r.symbol, tp_show) }}</td>
|
||||
<td>{% if r.margin_capital is not none and r.margin_capital != '' %}{{ funds_fmt(r.margin_capital) }}{% else %}-{% endif %}</td>
|
||||
<td>{{ r.leverage or '-' }}</td>
|
||||
<td>{{ r.effective_hold_minutes or 0 }}</td>
|
||||
<td>{{ (r.effective_opened_at or '-')[:16] }}</td>
|
||||
<td>{{ (r.effective_closed_at or r.created_at or '-')[:16] }}</td>
|
||||
{% set pnl_val = (r.effective_pnl_amount or 0)|float %}
|
||||
<td><span class="{{ 'pnl-profit' if pnl_val > 0 else ('pnl-loss' if pnl_val < 0 else '') }}">{{ funds_fmt(r.effective_pnl_amount or 0) }}</span>{% if r.display_pnl_source == 'exchange' %}<span style="font-size:.68rem;color:#6ab88a">所</span>{% elif r.display_pnl_source != 'reviewed' %}<span style="font-size:.68rem;color:#8892b0">估</span>{% endif %}</td>
|
||||
<td>
|
||||
{% set effective_result = r.effective_result %}
|
||||
{% if effective_result in ["止盈","保本止盈","移动止盈"] %}<span class="badge profit">{{ effective_result }}</span>
|
||||
{% elif effective_result in ["止损","强制清仓","手动平仓"] %}<span class="badge loss">{{ effective_result }}</span>
|
||||
{% elif effective_result == "时间平仓" %}<span class="badge miss">{{ effective_result }}</span>
|
||||
{% else %}<span class="badge">{{ effective_result or '-' }}</span>{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
type="button"
|
||||
class="table-del"
|
||||
style="background:#1f3a5a;color:#8fc8ff;margin-right:6px"
|
||||
onclick='fillJournalFromTrade({{ {
|
||||
"symbol": r.symbol,
|
||||
"monitor_type": r.monitor_type,
|
||||
"key_signal_type": r.key_signal_type or "",
|
||||
"direction": r.direction,
|
||||
"trigger_price": r.trigger_price,
|
||||
"stop_loss": r.display_open_stop_loss or r.initial_stop_loss or r.stop_loss,
|
||||
"take_profit": r.effective_take_profit or r.take_profit,
|
||||
"opened_at": r.effective_opened_at,
|
||||
"closed_at": r.effective_closed_at,
|
||||
"pnl_amount": r.effective_pnl_amount,
|
||||
"result": r.effective_result,
|
||||
"risk_amount": r.risk_amount,
|
||||
"effective_entry_reason": r.effective_entry_reason or ""
|
||||
}|tojson|safe }})'
|
||||
>填入复盘</button>
|
||||
<button
|
||||
type="button"
|
||||
class="table-del review-edit-btn"
|
||||
style="background:#1f3a5a;color:#8fc8ff;margin-right:6px"
|
||||
onclick='editTradeRecordReview({{ {
|
||||
"id": r.id,
|
||||
"opened_at": r.effective_opened_at,
|
||||
"closed_at": r.effective_closed_at,
|
||||
"stop_loss": r.effective_stop_loss or r.initial_stop_loss or r.stop_loss,
|
||||
"take_profit": r.effective_take_profit or r.take_profit,
|
||||
"pnl_amount": r.effective_pnl_amount,
|
||||
"result": r.effective_result,
|
||||
"miss_reason": r.effective_miss_reason,
|
||||
"effective_entry_reason": r.effective_entry_reason or ""
|
||||
}|tojson|safe }})'
|
||||
disabled
|
||||
>核对修改</button>
|
||||
<button type="button" class="table-del" onclick="deleteTradeRecord({{ r.id }})">删除</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card full journal-card">
|
||||
<h2>交易复盘记录上传(含截图)</h2>
|
||||
<form id="journal-form" action="/add_journal" method="post" enctype="multipart/form-data">
|
||||
<input type="hidden" name="risk_amount_hint" id="risk-amount-hint">
|
||||
<input type="hidden" name="entry_price_hint" id="entry-price-hint">
|
||||
<input type="hidden" name="stop_loss_hint" id="stop-loss-hint">
|
||||
<input type="hidden" name="exit_price_hint" id="exit-price-hint">
|
||||
<input type="hidden" name="direction_hint" id="direction-hint">
|
||||
{% from 'journal_form_fields.html' import journal_form_fields %}
|
||||
{{ journal_form_fields(entry_reason_options, order_type_options) }}
|
||||
{% from 'journal_upload_slots.html' import journal_upload_slots %}
|
||||
{{ journal_upload_slots() }}
|
||||
<div class="form-row journal-chart-options" style="flex-wrap:wrap;align-items:center">
|
||||
<label style="display:flex;align-items:center;gap:6px;font-size:.82rem;color:#cfd3ef">
|
||||
<input type="checkbox" name="journal_exchange_chart" value="true">
|
||||
保存时自动生成 K 线图并作为截图
|
||||
</label>
|
||||
<label style="font-size:.82rem;color:#9aa">周期1</label>
|
||||
<select name="journal_chart_tf1" style="min-width:72px">
|
||||
{% for tf in journal_chart_tf_choices %}
|
||||
<option value="{{ tf }}" {% if tf == journal_chart_default_tf1 %}selected{% endif %}>{{ tf }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<label style="font-size:.82rem;color:#9aa">周期2</label>
|
||||
<select name="journal_chart_tf2" style="min-width:72px">
|
||||
{% for tf in journal_chart_tf_choices %}
|
||||
<option value="{{ tf }}" {% if tf == journal_chart_default_tf2 %}selected{% endif %}>{{ tf }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<label style="font-size:.82rem;color:#9aa">K线数</label>
|
||||
<select name="journal_chart_limit" style="min-width:72px">
|
||||
{% for n in [100, 150, 200, 250, 300, 400, 500] %}
|
||||
<option value="{{ n }}" {% if n == journal_chart_default_limit %}selected{% endif %}>{{ n }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<label style="font-size:.82rem;color:#9aa">K线截止</label>
|
||||
<select name="journal_chart_anchor" id="journal-chart-anchor" style="min-width:96px" title="K线窗口右端对齐的时间">
|
||||
<option value="close" {% if journal_chart_default_anchor == 'close' %}selected{% endif %}>平仓时间</option>
|
||||
<option value="now" {% if journal_chart_default_anchor == 'now' %}selected{% endif %}>当前时间</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="sub" id="journal-chart-anchor-hint" style="font-size:.72rem;color:#8892b0;margin-top:2px;margin-bottom:0">双周期上下排列;截止=平仓时间:开仓前背景至平仓;截止=当前时间:最近 N 根至此刻(可看平仓后走势);标注开仓,平仓与止损位</div>
|
||||
<div class="mood-grid">
|
||||
<label><input type="checkbox" name="mood_issues" value="怕踏空">怕踏空</label>
|
||||
<label><input type="checkbox" name="mood_issues" value="报复开仓">报复开仓</label>
|
||||
<label><input type="checkbox" name="mood_issues" value="盈利飘了">盈利飘了</label>
|
||||
<label><input type="checkbox" name="mood_issues" value="拿不住单">拿不住单</label>
|
||||
<label><input type="checkbox" name="mood_issues" value="扛单">扛单</label>
|
||||
<label><input type="checkbox" name="mood_issues" value="重仓违规">重仓违规</label>
|
||||
</div>
|
||||
<textarea name="note" rows="2" placeholder="备注"></textarea>
|
||||
<button type="submit" style="margin-top:8px">保存复盘记录</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="card full review-card" id="review-card">
|
||||
<div class="review-card-head">
|
||||
<h2>AI复盘(按交易记录)</h2>
|
||||
<button type="button" class="review-card-fs-btn" id="review-card-fs-btn" onclick="toggleReviewCardFullscreen()">全屏</button>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<input type="date" id="day_date">
|
||||
<button type="button" id="gen-daily-btn" onclick="genDaily()">生成日复盘</button>
|
||||
<button type="button" onclick="exportDailyBundleMd()" style="background:#1f3a5a">导出当日日复盘MD</button>
|
||||
<input type="date" id="week_start">
|
||||
<input type="date" id="week_end">
|
||||
<button type="button" id="gen-weekly-btn" onclick="genWeekly()">生成周复盘</button>
|
||||
<button type="button" onclick="exportWeeklyBundleMd()" style="background:#1f3a5a">导出当周复盘MD</button>
|
||||
</div>
|
||||
<div class="ai-result-wrap" id="daily_result_wrap" style="display:none">
|
||||
<div id="daily_result" class="ai-result"></div>
|
||||
<div class="ai-result-toolbar">
|
||||
<button type="button" class="btn-fs" onclick="openAiInlineResultFullscreen('日复盘结果', 'daily_result')">全屏查看</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ai-result-wrap" id="weekly_result_wrap" style="display:none">
|
||||
<div id="weekly_result" class="ai-result"></div>
|
||||
<div class="ai-result-toolbar">
|
||||
<button type="button" class="btn-fs" onclick="openAiInlineResultFullscreen('周复盘结果', 'weekly_result')">全屏查看</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-list" style="margin-top:10px">
|
||||
<div class="panel-item">
|
||||
<strong>交易复盘记录</strong>
|
||||
<div id="journal-list"></div>
|
||||
</div>
|
||||
<div class="panel-item">
|
||||
<strong>AI历史复盘</strong>
|
||||
<div id="review-list"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include 'records_panel.html' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if page == 'env_config' %}
|
||||
{% include 'env_config_panel.html' %}
|
||||
@@ -729,6 +552,8 @@ function openAiInlineResultFullscreen(title, elementId){
|
||||
|
||||
const journalCache = {};
|
||||
const reviewCache = {};
|
||||
window.journalCache = journalCache;
|
||||
window.reviewCache = reviewCache;
|
||||
|
||||
function formatJournalExitOneLine(o){
|
||||
const t = (o.early_exit_trigger || "").trim();
|
||||
@@ -1213,7 +1038,6 @@ function fillJournalFromTrade(t){
|
||||
}
|
||||
recomputeJournalRealRr();
|
||||
if(typeof syncEarlyExitNoteRequired === "function") syncEarlyExitNoteRequired();
|
||||
alert("已填入下方复盘表单,请手动补充主观原因.");
|
||||
}
|
||||
|
||||
function recomputeJournalRealRr(){
|
||||
@@ -2162,6 +1986,7 @@ setInterval(tickOrderHoldDurations, 1000);
|
||||
tickOrderHoldDurations();
|
||||
setInterval(refreshPriceSnapshotConditional, {{ price_refresh_seconds * 1000 }});
|
||||
</script>
|
||||
<script src="/static/records_review_page.js?v=1"></script>
|
||||
<script>
|
||||
window.__INSTANCE_DISPLAY__ = {{ display | tojson }};
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
{# 三所共用:交易记录(5/页) → 填入复盘出表单 → 交易复盘记录 / AI历史复盘 #}
|
||||
<style>
|
||||
.records-panel-wrap .rr-pager{display:flex;align-items:center;gap:8px;margin-top:8px;font-size:.74rem}
|
||||
.records-panel-wrap .rr-list-loading{opacity:.55;pointer-events:none;transition:opacity .12s ease}
|
||||
.records-panel-wrap .rr-trades-wrap{min-height:9.5rem}
|
||||
.records-panel-wrap .journal-card.hidden{display:none!important}
|
||||
.records-panel-wrap .rr-hint{font-size:.72rem;color:#8892b0;margin:0 0 8px}
|
||||
</style>
|
||||
<div class="records-panel-wrap" id="records-panel-root" style="grid-column:1/-1">
|
||||
<div class="card full records-card">
|
||||
<h2>交易记录</h2>
|
||||
<p class="rr-hint">每页5条.点「填入复盘」打开下方复盘表单.</p>
|
||||
<div class="form-row" style="margin-bottom:10px;gap:8px">
|
||||
<label style="display:flex;align-items:center;gap:6px;font-size:.82rem;color:#cfd3ef">
|
||||
<input id="review-mode-toggle" type="checkbox">
|
||||
修改/核对开关(开启后可编辑关键字段)
|
||||
</label>
|
||||
</div>
|
||||
<div class="table-wrap rr-trades-wrap" id="rr-trades-wrap">
|
||||
<table id="rr-trades-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>品种</th><th>下单类型</th><th>开仓类型</th><th>方向</th><th>成交</th>
|
||||
<th>止损(开仓)</th><th>止盈</th><th>基数</th><th>杠杆</th><th>持仓分钟</th>
|
||||
<th>开仓时间(北京)</th><th>平仓时间(北京)</th><th>盈亏U</th><th>结果</th><th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="rr-trades-tbody">
|
||||
<tr><td colspan="15" class="muted">加载中…</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="rr-pager" id="rr-trades-pager">
|
||||
<button type="button" class="btn-secondary" id="rr-trades-prev" style="font-size:.72rem;padding:2px 8px">上一页</button>
|
||||
<span class="muted" id="rr-trades-page-label">第 1 / 1 页</span>
|
||||
<button type="button" class="btn-secondary" id="rr-trades-next" style="font-size:.72rem;padding:2px 8px">下一页</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card full journal-card hidden" id="journal-card">
|
||||
<div class="form-row" style="align-items:center;gap:8px;margin-bottom:6px">
|
||||
<h2 style="margin:0;margin-right:auto">交易复盘记录上传(含截图)</h2>
|
||||
<button type="button" class="btn-secondary" id="rr-journal-hide-btn" style="font-size:.76rem;padding:4px 10px">收起</button>
|
||||
</div>
|
||||
<p class="rr-hint" id="rr-journal-fill-hint" style="display:none">已从交易记录填入,请补充主观原因后保存.</p>
|
||||
<form id="journal-form" action="/add_journal" method="post" enctype="multipart/form-data">
|
||||
<input type="hidden" name="risk_amount_hint" id="risk-amount-hint">
|
||||
<input type="hidden" name="entry_price_hint" id="entry-price-hint">
|
||||
<input type="hidden" name="stop_loss_hint" id="stop-loss-hint">
|
||||
<input type="hidden" name="exit_price_hint" id="exit-price-hint">
|
||||
<input type="hidden" name="direction_hint" id="direction-hint">
|
||||
{% from 'journal_form_fields.html' import journal_form_fields %}
|
||||
{{ journal_form_fields(entry_reason_options, order_type_options) }}
|
||||
{% from 'journal_upload_slots.html' import journal_upload_slots %}
|
||||
{{ journal_upload_slots() }}
|
||||
<div class="form-row journal-chart-options" style="flex-wrap:wrap;align-items:center">
|
||||
<label style="display:flex;align-items:center;gap:6px;font-size:.82rem;color:#cfd3ef">
|
||||
<input type="checkbox" name="journal_exchange_chart" value="true">
|
||||
保存时自动生成 K 线图并作为截图
|
||||
</label>
|
||||
<label style="font-size:.82rem;color:#9aa">周期1</label>
|
||||
<select name="journal_chart_tf1" style="min-width:72px">
|
||||
{% for tf in journal_chart_tf_choices %}
|
||||
<option value="{{ tf }}" {% if tf == journal_chart_default_tf1 %}selected{% endif %}>{{ tf }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<label style="font-size:.82rem;color:#9aa">周期2</label>
|
||||
<select name="journal_chart_tf2" style="min-width:72px">
|
||||
{% for tf in journal_chart_tf_choices %}
|
||||
<option value="{{ tf }}" {% if tf == journal_chart_default_tf2 %}selected{% endif %}>{{ tf }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<label style="font-size:.82rem;color:#9aa">K线数</label>
|
||||
<select name="journal_chart_limit" style="min-width:72px">
|
||||
{% for n in [100, 150, 200, 250, 300, 400, 500] %}
|
||||
<option value="{{ n }}" {% if n == journal_chart_default_limit %}selected{% endif %}>{{ n }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<label style="font-size:.82rem;color:#9aa">K线截止</label>
|
||||
<select name="journal_chart_anchor" id="journal-chart-anchor" style="min-width:96px" title="K线窗口右端对齐的时间">
|
||||
<option value="close" {% if journal_chart_default_anchor == 'close' %}selected{% endif %}>平仓时间</option>
|
||||
<option value="now" {% if journal_chart_default_anchor == 'now' %}selected{% endif %}>当前时间</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="sub" id="journal-chart-anchor-hint" style="font-size:.72rem;color:#8892b0;margin-top:2px;margin-bottom:0">双周期上下排列;截止=平仓时间:开仓前背景至平仓;截止=当前时间:最近 N 根至此刻(可看平仓后走势);标注开仓,平仓与止损位</div>
|
||||
<div class="mood-grid">
|
||||
<label><input type="checkbox" name="mood_issues" value="怕踏空">怕踏空</label>
|
||||
<label><input type="checkbox" name="mood_issues" value="报复开仓">报复开仓</label>
|
||||
<label><input type="checkbox" name="mood_issues" value="盈利飘了">盈利飘了</label>
|
||||
<label><input type="checkbox" name="mood_issues" value="拿不住单">拿不住单</label>
|
||||
<label><input type="checkbox" name="mood_issues" value="扛单">扛单</label>
|
||||
<label><input type="checkbox" name="mood_issues" value="重仓违规">重仓违规</label>
|
||||
</div>
|
||||
<textarea name="note" rows="2" placeholder="备注"></textarea>
|
||||
<button type="submit" style="margin-top:8px">保存复盘记录</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="card full review-card" id="review-card">
|
||||
<div class="review-card-head">
|
||||
<h2>AI复盘(按交易记录)</h2>
|
||||
<button type="button" class="review-card-fs-btn" id="review-card-fs-btn" onclick="toggleReviewCardFullscreen()">全屏</button>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<input type="date" id="day_date">
|
||||
<button type="button" id="gen-daily-btn" onclick="genDaily()">生成日复盘</button>
|
||||
<button type="button" onclick="exportDailyBundleMd()" style="background:#1f3a5a">导出当日日复盘MD</button>
|
||||
<input type="date" id="week_start">
|
||||
<input type="date" id="week_end">
|
||||
<button type="button" id="gen-weekly-btn" onclick="genWeekly()">生成周复盘</button>
|
||||
<button type="button" onclick="exportWeeklyBundleMd()" style="background:#1f3a5a">导出当周复盘MD</button>
|
||||
</div>
|
||||
<div class="ai-result-wrap" id="daily_result_wrap" style="display:none">
|
||||
<div id="daily_result" class="ai-result"></div>
|
||||
<div class="ai-result-toolbar">
|
||||
<button type="button" class="btn-fs" onclick="openAiInlineResultFullscreen('日复盘结果', 'daily_result')">全屏查看</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ai-result-wrap" id="weekly_result_wrap" style="display:none">
|
||||
<div id="weekly_result" class="ai-result"></div>
|
||||
<div class="ai-result-toolbar">
|
||||
<button type="button" class="btn-fs" onclick="openAiInlineResultFullscreen('周复盘结果', 'weekly_result')">全屏查看</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card full" id="rr-journals-card">
|
||||
<h3 style="margin-top:0">交易复盘记录</h3>
|
||||
<p class="rr-hint">已保存的复盘(每页5条).</p>
|
||||
<div id="journal-list-wrap" class="rr-list-wrap">
|
||||
<div id="journal-list"></div>
|
||||
</div>
|
||||
<div class="rr-pager" id="rr-journals-pager">
|
||||
<button type="button" class="btn-secondary" id="rr-journals-prev" style="font-size:.72rem;padding:2px 8px">上一页</button>
|
||||
<span class="muted" id="rr-journals-page-label">第 1 / 1 页</span>
|
||||
<button type="button" class="btn-secondary" id="rr-journals-next" style="font-size:.72rem;padding:2px 8px">下一页</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card full" id="rr-ai-history-card">
|
||||
<h3 style="margin-top:0">AI历史复盘</h3>
|
||||
<p class="rr-hint">日/周 AI 复盘历史(每页5条).</p>
|
||||
<div id="review-list-wrap" class="rr-list-wrap">
|
||||
<div id="review-list"></div>
|
||||
</div>
|
||||
<div class="rr-pager" id="rr-reviews-pager">
|
||||
<button type="button" class="btn-secondary" id="rr-reviews-prev" style="font-size:.72rem;padding:2px 8px">上一页</button>
|
||||
<span class="muted" id="rr-reviews-page-label">第 1 / 1 页</span>
|
||||
<button type="button" class="btn-secondary" id="rr-reviews-next" style="font-size:.72rem;padding:2px 8px">下一页</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user