From b732324d631fa7894f8bd6bf6f14c349a4474058 Mon Sep 17 00:00:00 2001
From: aaron <>
Date: Mon, 18 May 2026 08:25:56 +0800
Subject: [PATCH] 1fix
---
static/app.html | 34 ++++++++++++++--------------------
1 file changed, 14 insertions(+), 20 deletions(-)
diff --git a/static/app.html b/static/app.html
index f53fb78..e4420b8 100644
--- a/static/app.html
+++ b/static/app.html
@@ -106,7 +106,7 @@
.level-badge.short_swing { color: #187574; background: rgba(15,188,176,.12); border-color: rgba(15,188,176,.20); }
.level-badge.structure_watch { color: var(--yellow-dark); background: var(--yellow-light); border-color: rgba(252,185,0,.22); }
.level-badge.theme_trend { color: var(--blue); background: rgba(66,98,255,.07); border-color: rgba(66,98,255,.12); }
-.signal-level-strip { margin: 0 18px 10px; border: 1px solid var(--hairline-soft); background: linear-gradient(180deg, rgba(248,250,252,.96), rgba(255,255,255,.98)); border-radius: var(--radius-lg); padding: 10px 12px; display: grid; grid-template-columns: minmax(118px,.78fr) minmax(150px,1fr) minmax(150px,1fr); gap: 10px; align-items: center; }
+.signal-level-strip { margin: 0 18px 10px; border: 1px solid var(--hairline-soft); background: linear-gradient(180deg, rgba(248,250,252,.96), rgba(255,255,255,.98)); border-radius: var(--radius-lg); padding: 10px 12px; display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr); gap: 10px; align-items: center; }
.signal-level-title { display:flex; align-items:center; gap:7px; min-width:0; }
.signal-level-dot { width:8px; height:8px; border-radius:50%; background: var(--blue); box-shadow: 0 0 0 4px rgba(66,98,255,.08); flex-shrink:0; }
.signal-level-strip.intraday_breakout .signal-level-dot { background: var(--green); box-shadow:0 0 0 4px rgba(0,180,115,.10); }
@@ -658,14 +658,6 @@ function renderRecCard(r) {
var chgSinceRec = r.current_price && r.entry_price && r.entry_price > 0 ? ((r.current_price - r.entry_price) / r.entry_price * 100) : 0;
var isOld = ageHours > 12;
var hasSurged = chgSinceRec > 3;
- var actionBadge = '';
- if (isBuy && isOld && hasSurged) actionBadge = '追高风险(+'+chgSinceRec.toFixed(1)+'%)';
- else if (isBuy && isOld) actionBadge = '信号偏弱';
- else if (!isOld && hasSurged && isBuy) actionBadge = '追高风险(+'+chgSinceRec.toFixed(1)+'%)';
- else if (!isOld && (r.rec_score||0) < 50 && isBuy) actionBadge = '信号偏弱';
- else if (isBuy) actionBadge = '入场窗口';
- else actionBadge = ''+phase.label+'';
- if (isWeakObserve) actionBadge = '弱观察';
var ePrice = r.entry_price||'';
var sl = (r.stop_loss&&r.stop_loss>0) ? r.stop_loss : '';
var tp = (r.tp1&&r.tp1>0) ? r.tp1 : '';
@@ -717,10 +709,10 @@ function renderRecCard(r) {
}
var weakNoteHtml = isWeakObserve ? '
'+cleanDisplayText(r.observe_reason || '信号强度不足,仅保留为低优先级观察,不构成实时机会。')+'
' : '';
var decisionCls = isBuy ? 'buy' : (isWait ? 'wait' : (isWeakObserve ? 'weak' : 'observe'));
- var decisionTitle = cleanDisplayText(r.execution_label || phase.label);
- var decisionFocus = isBuy ? ('现价 '+fmtP(price)) : (isWait ? ('等 '+fmtP(entryRef)) : (isWeakObserve ? '低优先级观察' : '等待确认'));
- var decisionReason = cleanDisplayText(isBuy ? (entryWindowSummary() || r.execution_reason || '入场窗口有效') : (r.execution_reason || (isWait ? '现价不追,等回踩价附近再评估' : (r.observe_reason || r.state_reason || '未形成入场窗口'))));
- var decisionHtml = '最终建议'+decisionTitle+'
'+decisionFocus+''+decisionReason+'
';
+ var decisionTitle = isBuy ? '现在可买' : (isWait ? '等回踩,不追高' : (isWeakObserve ? '弱观察' : '观察'));
+ var decisionFocus = isBuy ? ('现价 '+fmtP(price)) : (isWait ? ('参考 '+fmtP(entryRef)) : (isWeakObserve ? '低优先级观察' : '等待确认'));
+ var decisionReason = cleanDisplayText(isBuy ? (entryWindowSummary() || r.execution_reason || '入场窗口有效') : (r.execution_reason || (isWait ? '当前不追,等待回踩价附近再评估' : (r.observe_reason || r.state_reason || '未形成入场窗口'))));
+ var decisionHtml = '当前结论'+decisionTitle+'
'+decisionFocus+''+decisionReason+'
';
var aiInsightHtml = '';
var aiInsight = r.llm_insight && r.llm_insight.content ? r.llm_insight.content : null;
function hasAiText(v) {
@@ -751,14 +743,14 @@ function renderRecCard(r) {
return '多周期';
}
var levelBasis = Array.isArray(ep.plan_basis) ? ep.plan_basis.slice(0,2).join(' · ') : '';
- var signalLevelHtml = '信号级别'+cleanDisplayText(levelLabel)+'
捕捉周期'+cleanDisplayText(horizon || levelFrameText(levelKey))+''+cleanDisplayText(levelFrameText(levelKey))+'
确认方式'+cleanDisplayText(entryModel || '等待当前触发')+''+cleanDisplayText(levelBasis || phase.label)+'
';
+ var signalLevelHtml = '机会级别'+cleanDisplayText(levelLabel)+''+cleanDisplayText(horizon || levelFrameText(levelKey))+'
触发门槛'+cleanDisplayText(entryModel || '等待当前触发')+''+cleanDisplayText(levelBasis || phase.short || '当前触发 + 风险边界')+'
';
var entryPlanHtml = '';
if (isTradePlan) {
- entryPlanHtml = '机会级别'+cleanDisplayText(levelLabel)+''+cleanDisplayText(horizon || phase.short)+'
'+entryLabel+''+fmtP(entryRef)+''+cleanDisplayText(entryModel || '触发/计划价')+'
风险边界'+fmtP(riskLine)+''+cleanDisplayText(stopModel)+'
上方空间'+(upsidePct?('+'+upsidePct.toFixed(1)+'%'):'--')+''+cleanDisplayText(tpModel)+' · '+fmtP(spaceRef)+'
';
+ entryPlanHtml = '入场参考'+fmtP(entryRef)+''+cleanDisplayText(entryLabel+' · '+(entryModel || '触发/计划价'))+'
风险边界'+fmtP(riskLine)+''+cleanDisplayText(stopModel)+'
上方空间'+(upsidePct?('+'+upsidePct.toFixed(1)+'%'):'--')+''+cleanDisplayText(tpModel)+' · '+fmtP(spaceRef)+'
持有阶段'+cleanDisplayText(horizon || phase.short)+''+cleanDisplayText(levelLabel)+'
';
} else {
- entryPlanHtml = '机会级别'+cleanDisplayText(levelLabel)+''+cleanDisplayText(horizon || '观察池候选')+'
当前参考'+fmtP(price)+'不是入场价
确认条件待触发'+cleanDisplayText(entryModel || '需15m/1H当前信号')+'
绩效口径不计入未成交易推荐
';
+ entryPlanHtml = '当前参考'+fmtP(price)+'不是入场价
观察重点待触发'+cleanDisplayText(entryModel || '需15m/1H当前信号')+'
绩效口径不计入未成交易推荐
观察阶段'+cleanDisplayText(horizon || '观察池候选')+''+cleanDisplayText(levelLabel)+'
';
}
- return ''+base.slice(0,2).toUpperCase()+'
'+base+'
'+cleanDisplayText(levelLabel)+''+actionBadge+''+score+''+st.label+'
$'+priceFmt+''+changeHtml+'
'+decisionHtml+signalLevelHtml+onchainHtml+aiInsightHtml+'
'+(isWeakObserve ? weakNoteHtml : entryPlanHtml)+(sigHtml?'
'+sigHtml+'
':'')+'
';
+ return ''+base.slice(0,2).toUpperCase()+'
'+base+'
'+score+''+st.label+'
$'+priceFmt+''+changeHtml+'
'+decisionHtml+signalLevelHtml+onchainHtml+aiInsightHtml+'
'+(isWeakObserve ? weakNoteHtml : entryPlanHtml)+(sigHtml?'
'+sigHtml+'
':'')+'
';
} catch (e) {
console.error('renderRecCard hard fail', r && r.symbol, e);
return renderLiveFallbackCard(r);
@@ -1002,12 +994,14 @@ async function loadHistoryRecommendations(reset) {
var sigs = Array.isArray(r.signals)?r.signals:[];
var sigHtml = sigs.slice(0,4).map(function(s){ return ''+cleanDisplayText(s).replace(/^(\\d+H|\\d+m|日线|周线)\\s*/,'').slice(0,12)+''; }).join('');
var duration = daysBetween(r.rec_time, r.last_track_time||r.hit_tp1_time||r.stopped_out_time);
- var execText = hasPaper ? (paper.status === 'closed' ? '已模拟交易完成' : '模拟交易持有中') : (Number(r.entry_triggered || 0) ? '已触发执行' : '未执行');
+ var execText = hasPaper ? (paper.status === 'closed' ? '模拟交易已完成' : '模拟交易持有中') : (Number(r.entry_triggered || 0) ? '已触发执行' : '未执行');
var signalStateText = hasPaper ? '已执行归档' : (historyArchiveFilter === 'invalid' ? '失效归档' : '未执行归档');
+ var outcomeText = outcome.label;
+ var outcomeDetail = outcome.detail;
return ''+
- '
'+base.slice(0,2).toUpperCase()+'
'+base+'
'+outcome.label+''+
+ '
'+base.slice(0,2).toUpperCase()+'
'+base+'
'+outcomeText+''+
'
'+(hasPaper ? '$'+fmtN(entryP)+'→'+(paper.status === 'closed' ? '$'+fmtN(exitP) : '持有中')+'' : '未执行→失效/归档')+'评分 '+score+' · '+st.label+''+duration+'
'+
- '
归档状态'+signalStateText+'
执行状态'+execText+'
归档原因'+exitMode+'
'+
+ '
交易阶段'+(hasPaper ? (paper.status === 'closed' ? '已完成模拟交易' : '模拟交易持有中') : '未执行归档')+'
结果说明'+outcomeDetail+'
执行状态'+execText+'
'+
'
'+
(sigHtml?'
'+sigHtml+'
':'')+
'
';