Administrator
15 hours ago 6e91f4be557aa70a61d941ff13545be373b78608
src/main/resources/static/station-dashboard.html
@@ -415,6 +415,24 @@
    <!-- 事件日志 Tab -->
    <div class="tab-content" data-tab="events">
        <div class="events-panel" style="margin-bottom:16px">
            <div class="events-header">
                <h3>🎯 每轮止损次数</h3>
                <button class="btn btn-outline" onclick="refreshRoundStopLoss()" style="font-size:11px;padding:3px 10px">🔄 刷新</button>
            </div>
            <div style="max-height:300px;overflow-y:auto">
                <table class="events-table">
                    <thead>
                        <tr>
                            <th style="width:120px">轮次</th>
                            <th style="width:120px">多仓止损</th>
                            <th>空仓止损</th>
                        </tr>
                    </thead>
                    <tbody id="roundStopLossBody"></tbody>
                </table>
            </div>
        </div>
        <div class="events-panel">
            <div class="events-header">
                <h3>📋 最近 100 条事件</h3>
@@ -680,6 +698,9 @@
    // 加载事件(内部会渲染事件表格 + PNL 图表)
    await loadEvents(md5);
    // 加载每轮止损次数
    loadRoundStopLoss(md5);
    // 事件加载完成后重算统计卡:账户总权益依赖最新 PNL_SNAPSHOT
    if (selectedMd5 === md5 && instances[md5]) {
        renderStats(instances[md5]);
@@ -833,6 +854,38 @@
    }).join('');
    renderPnlChart();
}
// ==================== 每轮止损次数 ====================
async function loadRoundStopLoss(md5) {
    try {
        const rows = await api(API + '/round-stop-loss?apiKeyMd5=' + encodeURIComponent(md5));
        renderRoundStopLoss(rows || []);
    } catch (e) {
        renderRoundStopLoss([]);
    }
}
function renderRoundStopLoss(rows) {
    const tbody = $('roundStopLossBody');
    if (!tbody) return;
    if (!rows || rows.length === 0) {
        tbody.innerHTML = `<tr><td colspan="3" style="text-align:center;padding:20px;color:var(--dim)">暂无止损记录</td></tr>`;
        return;
    }
    tbody.innerHTML = rows.map(r => {
        const roundLabel = (r.roundNum === null || r.roundNum === undefined) ? '进行中' : ('第 ' + r.roundNum + ' 轮');
        return `
        <tr>
            <td>${esc(roundLabel)}</td>
            <td>${r.longLossCount ?? 0}</td>
            <td>${r.shortLossCount ?? 0}</td>
        </tr>`;
    }).join('');
}
function refreshRoundStopLoss() {
    if (selectedMd5) loadRoundStopLoss(selectedMd5);
}
// ==================== PNL 图表 ====================
@@ -1077,7 +1130,7 @@
    { key: 'quantity', label: '每次下单张数', type: 'number', placeholder: '2', jtype: 'string', group: 'grid' },
    { key: 'maxPositionSize', label: '最大持仓张数', type: 'number', placeholder: '4', jtype: 'int', group: 'grid' },
    { key: 'takeProfitGridSpan', label: '止盈网格跨度', type: 'number', placeholder: '2', jtype: 'int', group: 'grid' },
    { key: 'baseTakeProfitPerGrid', label: '单格止盈张数', type: 'number', placeholder: '0', jtype: 'int', group: 'grid', tip: '基础仓位止盈:每个网格挂的止盈张数' },
    { key: 'baseTakeProfitPerGrid', label: '单格止盈张数', type: 'number', step: 'any', placeholder: '0', jtype: 'decimal', group: 'grid', tip: '基础仓位止盈:每个网格挂的止盈张数(支持小数)' },
    { key: 'baseTakeProfitGridCount', label: '止盈网格数量', type: 'number', placeholder: '0', jtype: 'int', group: 'grid', tip: '基础仓位止盈:挂止盈的网格数量' },
    { key: 'expectedProfit', label: '预期收益 (USDT)', type: 'number', step: '0.01', placeholder: '0.15', jtype: 'decimal', group: 'risk' },