Dashboard: 信号tab + API(signals + xiaoguo-scan),前端展示

This commit is contained in:
知微
2026-06-21 02:44:05 +08:00
parent aa1f621b03
commit 70514bf542
2 changed files with 117 additions and 1 deletions
+64
View File
@@ -50,6 +50,7 @@ body { background: #0f0f13; color: #e2e8f0; }
<button class="tab-btn px-4 py-2 text-sm rounded-lg" data-tab="evaluation">📊 评估</button>
<button class="tab-btn px-4 py-2 text-sm rounded-lg" data-tab="prompts">📝 提示词</button>
<button class="tab-btn px-4 py-2 text-sm rounded-lg" data-tab="market">🌐 市场</button>
<button class="tab-btn px-4 py-2 text-sm rounded-lg" data-tab="signals">🔍 信号</button>
<a href="/upload" class="tab-btn px-4 py-2 text-sm rounded-lg" style="text-decoration:none;color:#fbbf24;border-color:#fbbf24">📸 上传</a>
</div>
@@ -62,6 +63,7 @@ body { background: #0f0f13; color: #e2e8f0; }
<div id="tab-evaluation" class="tab-content hidden"></div>
<div id="tab-prompts" class="tab-content hidden"></div>
<div id="tab-market" class="tab-content hidden"></div>
<div id="tab-signals" class="tab-content hidden"></div>
</div>
<!-- Stock Detail Modal -->
@@ -144,6 +146,7 @@ function renderTab(name) {
else if (name === 'evaluation') renderEvaluation();
else if (name === 'prompts') renderPrompts();
else if (name === 'market') renderMarket();
else if (name === 'signals') renderSignals();
}
// ── Data Fetching ──
@@ -1101,6 +1104,67 @@ function closePromptModal() {
document.getElementById('promptModal').classList.add('hidden');
document.getElementById('promptModal').classList.remove('flex');
}
// ── 信号页 ──
async function renderSignals() {
const el = document.getElementById('tab-signals');
el.innerHTML = '<div class="text-slate-400 text-sm">加载中…</div>';
try {
const [signals, scan] = await Promise.all([
fetchJSON('/api/signals'),
fetchJSON('/api/xiaoguo-scan')
]);
const sourceToday = scan.source_today || {};
let html = `
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4 mb-4">
<div class="card p-4">
<div class="text-xs text-slate-500 mb-1">今日信号来源</div>
<div class="flex gap-4 text-sm">
<span class="text-blue-400">📡 趋势: ${sourceToday.trend || 0}</span>
<span class="text-green-400">🔍 小果扫描: ${sourceToday.xiaoguo || 0}</span>
</div>
</div>
<div class="card p-4">
<div class="text-xs text-slate-500 mb-1">小果扫描统计</div>
<div class="flex gap-4 text-sm">
<span class="text-slate-300">📋 累计扫描: ${scan.total_scanned || 0} 只</span>
<span class="text-yellow-400">🏆 发现信号: ${scan.found_signals || 0} 只</span>
</div>
</div>
</div>`;
if (!signals || signals.length === 0) {
html += '<div class="card p-6 text-center text-slate-500 text-sm">暂无信号</div>';
el.innerHTML = html;
return;
}
html += '<div class="space-y-3">';
for (const s of signals) {
const sev = s.severity || '-';
const sevColor = sev === 'high' ? 'text-red-400' : sev === 'medium' ? 'text-yellow-400' : 'text-green-400';
const sent = s.overall_sentiment || '-';
const sentColor = sent === '利好' ? 'text-green-400' : sent === '利空' ? 'text-red-400' : 'text-slate-400';
const source = s.source || 'trend';
const sourceIcon = source === 'xiaoguo' ? '🔍' : '📡';
html += `
<div class="card p-4">
<div class="flex items-center gap-2 mb-1">
<span class="${sevColor} text-xs font-semibold">${sev.toUpperCase()}</span>
<span class="${sentColor} text-sm font-semibold">${sent}</span>
<span class="text-slate-500 text-xs">${sourceIcon} ${source}</span>
<span class="text-slate-600 text-xs ml-auto">${s.created_at ? s.created_at.slice(5,16) : ''}</span>
</div>
<div class="text-sm text-slate-300">${s.sector || '-'}</div>
<div class="text-xs text-slate-500 mt-1">${(s.summary || '').slice(0,120)}</div>
</div>`;
}
html += '</div>';
el.innerHTML = html;
} catch(e) {
el.innerHTML = `<div class="text-red-400 text-sm">加载失败: ${e.message}</div>`;
}
}
</script>
</body>
</html>