From 918c7f914d3266eeed03fb1126b102a6343aa0c2 Mon Sep 17 00:00:00 2001 From: aaron <> Date: Mon, 27 Apr 2026 10:59:09 +0800 Subject: [PATCH] 1 --- frontend/console.html | 831 +++++++----------------------------------- 1 file changed, 138 insertions(+), 693 deletions(-) diff --git a/frontend/console.html b/frontend/console.html index a94a1a7..8c91261 100644 --- a/frontend/console.html +++ b/frontend/console.html @@ -2511,23 +2511,15 @@ @@ -2535,10 +2527,10 @@
-
- -

系统健康总览

-
先判断系统活着没有,再判断风险和堵点
+
+ +

交易运营总览

+
先看系统有没有正常工作,再看账户、仓位、订单和最近信号
@@ -2560,84 +2552,79 @@
-
-
-
- -

当前最重要的问题

-
先回答你现在最该关注什么,再决定是否继续下钻
-
-
-
-
-
正在整理当前优先级...
-
-
-
正在汇总运营指标...
-
-
-
-
- -

平台执行概览

-
统一看平台权益、仓位、挂单、停机与自动交易状态
+ +

系统运行状态

+
判断系统是否在持续分析,以及价格与执行链路是否正常
-
-
正在加载平台状态...
+
+
+
价格链路
+
等待刷新
+
状态加载中
+
+
+
执行链路
+
等待刷新
+
状态加载中
+
+
+
+
最近心跳-
+
最近分析-
+
下一次运行-
+
最近信号-
+
+
+
运行摘要
+
正在整理运行状态...
- -

待处理清单

-
保留给人工干预和快速核对的辅助视图
+ +

常用操作与异常

+
自动交易开关、恢复执行,以及需要你马上处理的异常
-
-
正在汇总待处理事项...
+
+
正在读取平台状态...
+
+
+
正在汇总需要处理的事项...
+ +
+
+
+ +

账户总览

+
只保留你日常管理需要看的权益、仓位、订单和自动交易状态
+
+
+
+
正在加载平台状态...
+
+
-
-
-
- -

执行与资产

-
以后不再看 trading 页面,这里承接持仓、挂单和执行状态
-
-
-
-
-
价格链路
-
等待刷新
-
状态加载中
-
-
-
模拟盘执行链路
-
等待刷新
-
状态加载中
-
-
-
-
-

统一持仓视图

-
跨平台持仓合并展示,优先看风险、盈亏和保护完整度
+

当前持仓

+
重点看模拟盘与 Bitget 的持仓、未实现盈亏和保护单情况
@@ -2650,8 +2637,8 @@
-

统一挂单视图

-
入场单、保护单、资金占用和老化状态集中查看
+

当前挂单

+
集中看入场单和保护单,不再用密集表格堆信息
@@ -2664,175 +2651,35 @@
-
-
-
- -

信号与决策

-
把最近信号、生命周期、预览和缓存收敛到一个入口
-
-
-
-
正在整理信号生命周期...
-
-
-
-
-
-
- -

最近决策预览

-
看系统准备做什么,以及不同执行目标如何响应
-
-
-
-
正在读取决策预览...
-
-
-

最近信号流

-
压缩展示最新机会,但保留关键信号细节
+
保留最近 5 条信号的关键内容,便于快速判断系统是否有正常产出
正在读取信号...
-
- -
-
-
-
- -

Crypto Agent 状态

-
最近信号缓存、统计和辅助协同信息
-
-
-
-
正在读取 Agent 状态...
-
-
- -

补充视角

-
保留对照区,避免主区过度堆叠
+ +

信号执行跟踪

+
看最近信号是否已经转成挂单或持仓,足够就好,不展示过多内部决策细节
-
-
- 主视图已集中到本菜单 -
后续如需要补充“信号转执行”专题卡片,可以继续在这里加,不影响总览区。
-
+
+
正在整理信号生命周期...
- -
-
-
-
-
- -

分析心跳与调度

-
确认系统持续在分析,而不是单纯没有信号
-
-
-
-
最近心跳-
-
最近轮次-
-
当前进度-
-
下一次运行-
-
-
-
-
运行摘要
-
正在整理分析状态...
-
-
-
执行监管器
-
正在整理执行监管状态...
-
-
-
- -
-
-
- -

执行监管目标

-
监管 target、保护单补救和持仓管理能力集中展示
-
-
-
-
正在读取执行监管目标...
-
-
-
-
- -
-
-
-
-
- -

风险与阻塞

-
停机、熔断、执行阻塞统一在这里看,不再散落在各处
-
-
-
-
-
正在读取平台停机状态...
-
-
-
正在读取未落单汇总...
-
-
-
- -
-
-
- -

运行与执行日志

-
日志保留在独立菜单,按需查看
-
-
- - -
-
-
-
- - - - - -
-
-
正在读取执行事件...
-
-
-
-
-
正在读取分析日志...
-
-
-
-
-
@@ -3196,7 +3043,9 @@ cachedConsoleData.crypto_agent?.platform_halts, cachedConsoleData.crypto_agent?.target_execution_controls || {} ); - renderOpsKpis(cachedConsoleData); + renderFocusSummary(cachedConsoleData); + renderUnifiedPositions(cachedConsoleData.management?.positions || []); + renderUnifiedOrders(cachedConsoleData.management?.orders || []); renderSignalLifecycle(cachedConsoleData); } } @@ -3309,23 +3158,22 @@ const cryptoAgent = data.crypto_agent || {}; const monitor = cryptoAgent.analysis_monitor || {}; - const previews = Object.values(cryptoAgent.last_execution_preview || {}); const management = data.management || {}; const positions = management.positions || []; + const orders = management.orders || []; const attentionItems = management.attention_items || []; const haltedCount = countHalted(cryptoAgent.platform_halts || {}); - const blockedEvents = (data.execution_events || []).filter((event) => event.event_type === 'execution_blocked_summary'); - const actionablePreviewCount = previews.filter((preview) => { - const paperDecision = preview.paper?.decision; - const bitgetDecision = preview.bitget?.decision; - return ['OPEN', 'ADD', 'CLOSE', 'CANCEL_PENDING'].includes(paperDecision) || - ['OPEN', 'ADD', 'CLOSE', 'CANCEL_PENDING'].includes(bitgetDecision); - }).length; + const latestSignals = data.signals?.latest || []; const heartbeatHeadline = monitor.last_heartbeat_at ? relativeTime(monitor.last_heartbeat_at) : '无心跳'; const heartbeatTone = toneClassForHealth(cryptoAgent.running ? (monitor.last_cycle_status || monitor.last_analysis_status) : 'stopped'); - const exposureNotional = positions.reduce((sum, item) => sum + Number(item.notional || item.size || 0), 0); + const exposureNotional = positions.reduce((sum, item) => { + const margin = Number(item.margin || 0); + const leverage = Math.max(Number(item.leverage || 0), 1); + return sum + margin * leverage; + }, 0); const riskTone = haltedCount > 0 ? 'danger' : (positions.length > 0 ? 'warn' : 'good'); - const blockedTone = blockedEvents.length > 0 || attentionItems.length > 0 ? 'warn' : 'good'; + const signalTone = latestSignals.length > 0 ? 'good' : 'warn'; + const orderTone = orders.length > 0 ? 'warn' : 'good'; container.innerHTML = `
@@ -3334,19 +3182,19 @@
状态 ${String(monitor.last_cycle_status || monitor.last_analysis_status || 'idle').toUpperCase()} / 下次 ${monitor.next_scheduled_run_at ? formatTime(monitor.next_scheduled_run_at) : '-'}
-
待执行机会
-
${actionablePreviewCount}
-
最近预览中可执行动作 ${actionablePreviewCount} 个
+
最近信号
+
${latestSignals.length}
+
最新 ${latestSignals[0]?.symbol || '-'} / ${latestSignals[0]?.signal_type || '-'}
-
风险暴露
+
持仓暴露
${positions.length} 仓
名义暴露 ${formatSensitiveMoney(exposureNotional)} / 停机 ${haltedCount}
-
阻塞状态
-
${blockedEvents.length}
-
阻塞事件 ${blockedEvents.length} / 待处理 ${attentionItems.length}
+
挂单与异常
+
${orders.length}
+
挂单 ${orders.length} / 待处理 ${attentionItems.length}
`; } @@ -3417,27 +3265,12 @@ function syncTabState(data) { const recentSignals = data.signals?.latest || []; - const executionEvents = data.execution_events || []; const positions = data.management?.positions || []; const orders = data.management?.orders || []; - const runtimeCount = (data.crypto_agent?.recent_analysis_events || []).length + (data.crypto_agent?.analysis_monitor?.last_heartbeat_at ? 1 : 0); - updateTabButton('logs', 'logsExecution', '执行事件', executionEvents.length, executionEvents.length > 0); - updateTabButton('logs', 'logsAnalysis', '分析日志', runtimeCount, runtimeCount > 0); - - const logsCurrent = getActiveTabTarget('logs'); - const logsChoices = [ - { target: 'logsExecution', hasData: executionEvents.length > 0 }, - { target: 'logsAnalysis', hasData: runtimeCount > 0 }, - ]; - if (!logsChoices.find((item) => item.target === logsCurrent && item.hasData)) { - setActiveTab('logs', logsChoices.find((item) => item.hasData)?.target || 'logsExecution'); - } updateSidebarBadge('sidebarBadgeOverview', String((data.management?.attention_items || []).length)); updateSidebarBadge('sidebarBadgeExecution', `${positions.length}/${orders.length}`); updateSidebarBadge('sidebarBadgeSignals', String(recentSignals.length)); - updateSidebarBadge('sidebarBadgeRuntime', data.crypto_agent?.analysis_monitor?.last_heartbeat_at ? 'live' : 'idle'); - updateSidebarBadge('sidebarBadgeLogs', String(executionEvents.length)); } function toneClassForHealth(status) { @@ -3694,70 +3527,6 @@ }); } - function renderTopPriority(data) { - const container = document.getElementById('topPriority'); - if (!container) return; - - const priorities = deriveTopPriorities(data); - const primary = priorities[0]; - const rest = priorities.slice(1, 4); - - container.innerHTML = ` -
-
top priority
-
${primary.title}
-
${primary.detail}
-
建议动作: ${primary.action}
-
- ${(primary.badges || []).map((badge) => `${badge}`).join('')} -
-
-
- ${rest.length ? rest.map((item) => ` -
-
-
${item.title}
- ${item.tone} -
-
${item.detail}
-
- `).join('') : compactEmpty('没有其他更高优先级事项', '当前首要问题已经覆盖了最需要处理的点。')} -
- `; - } - - function renderOpsKpis(data) { - const container = document.getElementById('opsKpis'); - if (!container) return; - - const snapshot = inferOpsSnapshot(data); - const halts = countHalted(data.crypto_agent?.platform_halts || {}); - const disabled = Object.values(data.crypto_agent?.target_execution_controls || {}).filter((item) => item?.enabled === false).length; - - container.innerHTML = ` -
-
24h 分析产出
-
${snapshot.recentSignal24h}
-
最近 24 小时写入的信号数。若长期为 0,需要先看运行心跳。
-
-
-
24h 执行成功率
-
${formatPercent(snapshot.conversionRate, 1)}
-
成功 ${snapshot.success24h} / 信号 ${snapshot.recentSignal24h || 0},阻塞 ${snapshot.blocked24h}。
-
-
-
持仓保护完整率
-
${formatPercent(snapshot.protectionCoverage, 0)}
-
持仓 ${snapshot.positions.length} / 已完整 TP+SL ${snapshot.positions.filter((item) => item.take_profit && item.stop_loss).length}。
-
-
-
停机与陈旧挂单
-
${halts + disabled + snapshot.staleEntryOrders}
-
停机 ${halts} / 关闭 ${disabled} / 超 30m 未成交入场单 ${snapshot.staleEntryOrders}。
-
- `; - } - function renderSignalLifecycle(data) { const container = document.getElementById('signalLifecycle'); if (!container) return; @@ -3866,71 +3635,17 @@ `; } - function renderAgentSignals(cryptoAgent, signalStats) { - const container = document.getElementById('agentSignals'); - const lastSignals = cryptoAgent?.last_signals || {}; - const entries = Object.entries(lastSignals); - const cards = []; - - cards.push(` -
-
-
-
7D 信号统计
-
crypto
-
- stats -
-
-
Crypto${signalStats?.stats_7d?.crypto?.total || 0}
-
Buy${signalStats?.stats_7d?.crypto?.buy || 0}
-
Sell${signalStats?.stats_7d?.crypto?.sell || 0}
-
-
- `); - - if (entries.length === 0) { - cards.push(compactEmpty('Crypto Agent 暂无最近信号缓存', '当前没有缓存到最近信号,可切到信号流或执行流继续查看。')); - } else { - entries.slice(0, 5).forEach(([symbol, sig]) => { - cards.push(` -
-
-
-
${symbol}
-
${sig.type || '-'} / ${sig.grade || '-'}
-
- ${sig.action || 'wait'} -
-
-
动作${sig.action || '-'}
-
置信度${formatPercent(sig.confidence || 0, 1)}
-
等级${sig.grade || '-'}
-
-
- `); - }); - } - - container.innerHTML = cards.join(''); - } - function renderAnalysisHeartbeat(analysisMonitor, analysisEvents) { const heartbeat = document.getElementById('analysisHeartbeat'); - const logList = document.getElementById('analysisLogList'); const summaryCard = document.getElementById('runtimeSummaryCard'); - const guardianCard = document.getElementById('guardianSummaryCard'); - const guardianTargetList = document.getElementById('guardianTargetList'); const monitor = analysisMonitor || {}; const notifications = cachedConsoleData?.crypto_agent?.analysis_notifications || {}; const schedule = cachedConsoleData?.crypto_agent?.llm_schedule || {}; - const laneState = cachedConsoleData?.crypto_agent?.lane_analysis_state || {}; - const eventState = cachedConsoleData?.crypto_agent?.event_analysis_state || {}; - const guardian = cachedConsoleData?.crypto_agent?.execution_guardian || {}; const cycleStatus = monitor.last_cycle_status || 'idle'; - const progressText = monitor.current_cycle_total - ? `${monitor.current_cycle_index || 0}/${monitor.current_cycle_total} ${monitor.current_cycle_symbol || ''}` - : '-'; + const lastSignalAt = notifications.last_signal_at; + const lastSignalSymbol = notifications.last_signal_symbol || '-'; + + if (!heartbeat || !summaryCard) return; heartbeat.innerHTML = `
@@ -3938,242 +3653,29 @@ ${monitor.last_heartbeat_at ? `${relativeTime(monitor.last_heartbeat_at)} / ${formatTime(monitor.last_heartbeat_at)}` : '-'}
- 最近轮次 - ${cycleStatus}${monitor.last_cycle_completed_at ? ` / ${relativeTime(monitor.last_cycle_completed_at)}` : ''} -
-
- 当前进度 - ${progressText} + 最近分析 + ${monitor.last_analysis_symbol || '-'} / ${monitor.last_analysis_status || '-'}
下一次运行 ${monitor.next_scheduled_run_at ? formatTime(monitor.next_scheduled_run_at) : '-'}
+
+ 最近信号 + ${lastSignalAt ? `${lastSignalSymbol} / ${relativeTime(lastSignalAt)}` : '暂无'} +
`; - const heartbeatSentAt = notifications.last_heartbeat_notified_at; - const lastSignalAt = notifications.last_signal_at; - const lastSignalSymbol = notifications.last_signal_symbol || '-'; - const laneRows = Object.entries(laneState).slice(0, 4).map(([symbol, state]) => ` -
-
${symbol}
-
- 日内 ${state.last_intraday_at ? relativeTime(state.last_intraday_at) : '-'} / - 趋势 ${state.last_trend_at ? relativeTime(state.last_trend_at) : '-'} - ${state.last_force_reason ? `
强触发: ${state.last_force_reason}` : ''} -
-
- `).join(''); - const latestEventTrigger = Object.entries(eventState) - .map(([symbol, state]) => ({ symbol, ...state })) - .filter((state) => state.last_triggered_at) - .sort((a, b) => new Date(b.last_triggered_at) - new Date(a.last_triggered_at))[0]; summaryCard.innerHTML = `
运行摘要
-
${monitor.last_analysis_status || 'idle'} / ${monitor.last_analysis_symbol || '-'}
+
${cycleStatus.toUpperCase()} / ${monitor.last_analysis_symbol || '-'}
最近分析说明${monitor.last_analysis_detail || '-'}
-
最近信号${lastSignalAt ? `${lastSignalSymbol} / ${relativeTime(lastSignalAt)}` : '近 60 分钟无信号'}
-
上次心跳通知${heartbeatSentAt ? `${relativeTime(heartbeatSentAt)} / ${formatTime(heartbeatSentAt)}` : '尚未发送'}
-
LLM 冷却日内 ${schedule.intraday_cooldown_minutes || '-'}m / 趋势 ${schedule.trend_cooldown_minutes || '-'}m
-
事件触发${schedule.event_analysis_enabled ? `${schedule.event_analysis_window_minutes || '-'}m / ${formatPercent(schedule.event_analysis_price_change_percent || 0, 1)} / 冷却${schedule.event_analysis_cooldown_minutes || '-'}m` : '关闭'}
-
最近异动分析${latestEventTrigger ? `${latestEventTrigger.symbol} / ${relativeTime(latestEventTrigger.last_triggered_at)}` : '暂无'}
+
最近完成轮次${monitor.last_cycle_completed_at ? `${relativeTime(monitor.last_cycle_completed_at)} / ${formatTime(monitor.last_cycle_completed_at)}` : '暂无'}
+
日内 / 趋势冷却${schedule.intraday_cooldown_minutes || '-'}m / ${schedule.trend_cooldown_minutes || '-'}m
+
事件分析${schedule.event_analysis_enabled ? '开启' : '关闭'}
-
${laneRows || '
暂无 lane 状态,等待下一轮分析。
'}
`; - - const guardianTargets = Array.isArray(guardian.targets) ? guardian.targets : []; - const guardianActions = Array.isArray(guardian.last_actions) ? guardian.last_actions : []; - const guardianTargetRows = guardianTargets.slice(0, 4).map((target) => ` -
- ${target.target_key} - ${target.supports_tpsl_repair ? '监管 + 保护单' : '监管'} -
- `).join(''); - const latestGuardianAction = guardianActions[0]; - if (guardianCard) { - guardianCard.innerHTML = ` -
执行监管器
-
${guardian.last_status || 'idle'} / ${guardian.last_run_at ? relativeTime(guardian.last_run_at) : '-'}
-
-
监管目标${guardianTargets.length}
-
最近错误${guardian.last_error || '无'}
-
最近动作${latestGuardianAction ? `${latestGuardianAction.action_type} / ${latestGuardianAction.symbol || latestGuardianAction.platform}` : '暂无'}
-
-
${guardianTargetRows || '
暂无已注册监管目标。
'}
- `; - } - if (guardianTargetList) { - const bitgetAccounts = cachedConsoleData?.platforms?.bitget?.accounts || []; - const bitgetAccountMap = Object.fromEntries(bitgetAccounts.map((account) => [String(account.account_id), account])); - guardianTargetList.innerHTML = guardianTargets.length - ? guardianTargets.map((target) => { - const account = target.platform === 'Bitget' ? (bitgetAccountMap[String(target.account_id)] || {}) : {}; - const positionsCount = account.positions?.count || 0; - const ordersCount = account.orders?.count || 0; - const isHalted = !!(cachedConsoleData?.crypto_agent?.platform_halts?.[target.target_key]?.halted); - return ` -
-
-
${target.target_key}
-
${target.platform} / account=${target.account_id}
-
-
-
挂单超时${target.supports_pending_timeout ? 'on' : 'off'}
-
持仓管理${target.supports_position_management ? 'on' : 'off'}
-
保护单补救${target.supports_tpsl_repair ? 'on' : 'off'}
-
仓位 / 挂单${positionsCount} / ${ordersCount}
-
-
- `; - }).join('') - : compactEmpty('暂无执行监管目标', '注册多个交易所或多个账号后,这里会展开显示每个 target。'); - } - - if (!analysisEvents || analysisEvents.length === 0) { - logList.innerHTML = compactEmpty('最近还没有分析日志', '等待下一轮分析或新的运行事件写入。'); - return; - } - - logList.innerHTML = analysisEvents.map((event) => ` -
-
- ${event.symbol || 'SYSTEM'} · ${event.event_type || '-'} - ${relativeTime(event.timestamp)} / ${formatTime(event.timestamp)} -
-
${event.detail || '-'}
-
- `).join(''); - } - - function renderBlockedSummaries(events = cachedExecutionEvents) { - const container = document.getElementById('blockedSummaryList'); - const blockedEvents = (Array.isArray(events) ? events : []) - .filter((event) => event.event_type === 'execution_blocked_summary') - .slice(0, 3); - - if (!blockedEvents.length) { - container.innerHTML = compactEmpty('最近没有未落单阻塞', '出现执行阻塞时,这里会按平台归类展示原因。'); - return; - } - - container.innerHTML = blockedEvents.map((event) => { - const blockedPlatforms = event.blocked_platforms || []; - return ` -
-
-
${event.symbol || '-'} · ${event.signal_action_text || '-'} / ${event.signal_timeframe_text || '-'}
-
${relativeTime(event.timestamp)} / ${formatTime(event.timestamp)}
-
-
建议价 ${formatMoney(event.entry_price)} / 现价 ${formatMoney(event.current_price)} / 信心 ${formatPercent(event.confidence || 0, 1)}
-
- ${blockedPlatforms.map((item) => ` -
- ${item.target_key || item.platform} - ${item.tag} | ${item.detail} -
- `).join('')} -
-
- `; - }).join(''); - } - - function summarizeDecision(decision) { - if (!decision) return { label: '-', detail: '无数据', tone: 'hold' }; - const decisionType = decision.decision || decision.action || 'HOLD'; - let tone = 'hold'; - if (['OPEN', 'ADD', 'CLOSE'].includes(decisionType)) { - tone = 'success'; - } else if (['CANCEL_PENDING', 'FLIP', 'ROLL', 'CLOSE_OPPOSITE', 'CANCEL_AND_OPEN'].includes(decisionType)) { - tone = 'warning'; - } else if (['ERROR', 'FAILED'].includes(decisionType)) { - tone = 'error'; - } - return { - label: decisionType, - detail: decision.reason || decision.reasoning || '无说明', - tone, - }; - } - - function renderDecisionPreview(previewMap) { - const container = document.getElementById('decisionPreview'); - const entries = Object.entries(previewMap || {}); - - if (entries.length === 0) { - container.innerHTML = compactEmpty('暂无最近决策预览', '还没有形成最近一轮执行预览,通常意味着还没出现可执行信号。'); - return; - } - - const cards = []; - entries.slice(0, 4).forEach(([symbol, preview]) => { - const paper = summarizeDecision(preview.paper); - const bitget = summarizeDecision(preview.bitget); - const bitgetAccounts = Object.entries(preview.bitget_accounts || {}); - const bitgetAccountDetails = bitgetAccounts.length - ? bitgetAccounts.map(([accountId, decision]) => { - const summary = summarizeDecision(decision); - return ` - - `; - }).join('') - : ` - - `; - - cards.push(` -
-
-
-
${symbol}
-
${formatTime(preview.timestamp)} | 现价 ${formatMoney(preview.current_price)}
-
- preview -
-
-
模拟盘${paper.label}
-
Bitget${bitget.label}
-
- ${(preview.paper?.setup_type || preview.bitget?.setup_type) - ? ` -
- ${preview.paper?.setup_type ? `Paper ${preview.paper.setup_type}` : ''} - ${preview.bitget?.setup_type ? `Bitget ${preview.bitget.setup_type}` : ''} -
- ` - : ''} - ${(preview.paper?.entry_basis || preview.paper?.setup_basis || preview.bitget?.entry_basis || preview.bitget?.setup_basis) - ? ` -
- ${preview.paper?.entry_basis || preview.paper?.setup_basis ? `
模拟盘: ${preview.paper.entry_basis || preview.paper.setup_basis}
` : ''} - ${preview.bitget?.entry_basis || preview.bitget?.setup_basis ? `
Bitget: ${preview.bitget.entry_basis || preview.bitget.setup_basis}
` : ''} -
- ` - : ''} -
- 模拟盘: ${paper.detail} -
- -
- `); - }); - - container.innerHTML = cards.join(''); } function renderHalts(platformHalts, executionControls) { @@ -4231,57 +3733,6 @@ }); } - function renderExecutionEvents(events = cachedExecutionEvents) { - const container = document.getElementById('eventStream'); - cachedExecutionEvents = Array.isArray(events) ? events : []; - const filtered = cachedExecutionEvents.filter((event) => currentEventFilter === 'all' || event.status === currentEventFilter); - if (!filtered || filtered.length === 0) { - container.innerHTML = compactEmpty('最近没有匹配的执行事件', currentEventFilter === 'all' ? '当前没有新的执行结果或异常事件。' : `筛选条件为 ${currentEventFilter.toUpperCase()},当前暂无匹配记录。`); - return; - } - - container.innerHTML = filtered.map((event) => ` -
-
${relativeTime(event.timestamp)}
${formatTime(event.timestamp)}
-
${event.platform || '-'}
${event.event_type || '-'}
-
-
- ${event.symbol || '-'} - ${event.account_id ? `acct ${event.account_id}` : ''} - ${event.target_key ? `${event.target_key}` : ''} - ${event.decision ? `${event.decision}` : ''} - ${event.action ? `${event.action}` : ''} - ${event.signal_timeframe_text ? `${event.signal_timeframe_text}` : ''} - ${event.setup_type ? `${event.setup_type}` : ''} -
- ${event.reason || '无说明'} - ${event.setup_basis || event.entry_basis ? ` -
- ${event.setup_basis ? `
Setup: ${event.setup_basis}
` : ''} - ${event.entry_basis ? `
Entry: ${event.entry_basis}
` : ''} -
- ` : ''} - ${event.event_type === 'execution_blocked_summary' && Array.isArray(event.blocked_platforms) && event.blocked_platforms.length > 0 ? ` -
- ${event.blocked_platforms.map((item) => ` -
- ${item.platform} - ${item.tag} | ${item.detail} -
- `).join('')} -
- ` : ''} - ${(event.reason || '').length > 90 ? ` -
- 查看完整详情 -
${String(event.reason || '无说明')}
-
- ` : ''} -
-
- `).join(''); - } - function renderAttentionItems(items) { const container = document.getElementById('attentionList'); if (!items || items.length === 0) { @@ -4376,38 +3827,47 @@ } container.innerHTML = ` - - - - - - - - - - - - - - - - - ${total.map((item) => ` - - - - - - - - - - - - - `).join('')} - -
平台账号交易对方向类别价格数量 / 杠杆信号Setup时间
${item.platform}${item.account_id || '-'}${item.symbol || '-'}${item.side === 'long' ? 'long' : 'short'}${item.category === 'tp_sl' ? 'TP/SL' : 'ENTRY'}${formatMoney(item.price)}${formatNumber(item.size, 4)} / ${item.leverage ? `${formatNumber(item.leverage, 1)}x` : '-'}${item.signal_grade || '-'} ${item.signal_type || ''} ${item.confidence ? `/ ${formatPercent(item.confidence, 1)}` : ''}${item.setup_type ? `
${item.setup_type}
${item.entry_basis || item.setup_basis || '-'}
` : '-'}
${item.created_at ? relativeTime(item.created_at) : '-'}
+
+ ${total.map((item) => ` +
+
+
+
${item.symbol || '-'}
+
${item.platform || '-'} / ${item.account_id || '-'} / ${item.created_at ? `${relativeTime(item.created_at)} / ${formatTime(item.created_at)}` : '-'}
+
+
+
${formatMoney(item.price)}
+
${item.category === 'tp_sl' ? 'TP/SL' : 'ENTRY'}
+
+
+
+ ${item.platform} + ${item.side === 'long' ? 'long' : 'short'} + ${item.signal_grade ? `${item.signal_grade}` : ''} + ${item.signal_type ? `${item.signal_type}` : ''} + ${item.setup_type ? `${item.setup_type}` : ''} +
+
+
+ 价格 / 数量 + ${formatMoney(item.price)} / ${formatNumber(item.size, 4)} +
+
+ 杠杆 / 信心度 + ${item.leverage ? `${formatNumber(item.leverage, 1)}x` : '-'} / ${item.confidence ? formatPercent(item.confidence, 1) : '-'} +
+
+ 止盈 / 止损 + ${item.take_profit ? formatMoney(item.take_profit) : '-'} / ${item.stop_loss ? formatMoney(item.stop_loss) : '-'} +
+
+ Setup + ${item.entry_basis || item.setup_basis || '-'} +
+
+
+ `).join('')} +
`; } @@ -4490,21 +3950,15 @@ renderHealthRibbon(data); renderFocusSummary(data); renderAlertStrip(data); - renderTopPriority(data); - renderOpsKpis(data); renderExecutionMonitor(data); renderSignalLifecycle(data); renderPlatforms(data.platforms, data.crypto_agent?.platform_halts, data.crypto_agent?.target_execution_controls || {}); renderSignalStream(data.signals?.latest || []); - renderAgentSignals(data.crypto_agent, data.signals); renderAnalysisHeartbeat( data.crypto_agent?.analysis_monitor || {}, data.crypto_agent?.recent_analysis_events || [] ); - renderDecisionPreview(data.crypto_agent?.last_execution_preview || {}); renderHalts(data.crypto_agent?.platform_halts || {}, data.crypto_agent?.target_execution_controls || {}); - renderExecutionEvents(data.execution_events || []); - renderBlockedSummaries(data.execution_events || []); renderAttentionItems(data.management?.attention_items || []); renderUnifiedPositions(data.management?.positions || []); renderUnifiedOrders(data.management?.orders || []); @@ -4534,15 +3988,6 @@ applyAutoRefreshState(); }); document.getElementById('toggleSensitiveBtn').addEventListener('click', toggleSensitiveData); - document.getElementById('eventFilters').querySelectorAll('[data-filter]').forEach((button) => { - button.addEventListener('click', () => { - currentEventFilter = button.getAttribute('data-filter'); - document.getElementById('eventFilters').querySelectorAll('[data-filter]').forEach((item) => { - item.classList.toggle('active', item === button); - }); - renderExecutionEvents(); - }); - }); loadSensitivePreference(); initTabs();