Files
stock-advisor/static/js/analysis_detail.js
T

90 lines
4.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* AI 分析详情页:研报正文 + 数据源 */
const CODE_AID = parseInt(location.pathname.split('/').pop(), 10);
async function load() {
try {
const d = await api('/api/analyses/' + CODE_AID);
const a = d.analysis, stock = d.stock || {};
$('#aStock').textContent = a.stock_name || stock.name || '—';
$('#aCode').textContent = a.code;
$('#aIndustry').textContent = stock ? (stock.name + ' · ' + (stock.industry || '') + ' · ' + (stock.board || '')) : '';
$('#aTime').textContent = a.created_at;
$('#aFocus').textContent = a.focus || '整体投资价值';
$('#reportBox').innerHTML = mdRender(a.report);
renderSources(a.sources || {});
} catch (e) {
$('#reportBox').innerHTML = '<div class="empty">加载失败:' + escapeHtml(e.message) + '</div>';
}
}
function srcBlock(title, icon, inner, count) {
return `<details class="src-block" ${inner ? 'open' : ''}>
<summary>${icon} ${title} ${count !== undefined ? `<span class="src-count">${count}</span>` : ''}</summary>
<div class="src-body">${inner || '<div class="empty">无</div>'}</div>
</details>`;
}
function renderSources(s) {
let html = '';
// 1. RAG 相关资讯
const news = s.news || [];
html += srcBlock('RAG 相关资讯(向量检索命中)', '📰', news.map(n => `
<div class="src-news">
<div class="src-news-title">${escapeHtml(n.title)}</div>
<div class="src-news-meta">
<span>${n.date || '—'}</span>
<span class="tag tag-${n.sentiment > 0 ? '正' : n.sentiment < 0 ? '负' : '平'}">情感 ${Number(n.sentiment).toFixed(2)}</span>
<span style="color:var(--muted)">相似度 ${(1 - (n.distance || 0)).toFixed(3)}</span>
</div>
<div class="src-news-text">${escapeHtml(n.text)}</div>
</div>`).join(''), news.length);
// 2. 公司概况
html += srcBlock('公司概况(RAG 检索)', '🏢', s.profile ? `<p>${escapeHtml(s.profile)}</p>` : '', s.profile ? 1 : 0);
// 3. 技术指标
html += srcBlock('技术指标', '📈', s.indicators ? `<pre class="src-pre">${escapeHtml(s.indicators)}</pre>` : '', s.indicators ? 1 : 0);
// 4. 综合评分
if (s.score) {
const sc = s.score;
html += srcBlock('综合评分', '🎯', `
<div class="mini-stats" style="gap:14px">
<div class="mini-stat"><div class="ms-label">总分</div><div class="ms-value" style="color:${sc.total >= 68 ? '#f59e0b' : '#3b82f6'}">${sc.total}</div></div>
<div class="mini-stat"><div class="ms-label">评级</div><div class="ms-value"><span class="tag tag-${sc.rating}">${sc.rating}</span></div></div>
<div class="mini-stat"><div class="ms-label">趋势</div><div class="ms-value">${sc.trend}</div></div>
<div class="mini-stat"><div class="ms-label">动量</div><div class="ms-value">${sc.momentum}</div></div>
<div class="mini-stat"><div class="ms-label">技术</div><div class="ms-value">${sc.technical}</div></div>
<div class="mini-stat"><div class="ms-label">量能</div><div class="ms-value">${sc.volume}</div></div>
<div class="mini-stat"><div class="ms-label">消息</div><div class="ms-value">${sc.news}</div></div>
<div class="mini-stat"><div class="ms-label">机构</div><div class="ms-value">${sc.institutional}</div></div>
</div>`, 1);
}
// 5. 机构评级
const ratings = s.ratings || [];
html += srcBlock('机构评级', '🏦', ratings.length ? `<table>
<tr><th>机构</th><th>评级</th><th>目标价</th><th>日期</th></tr>
${ratings.map(r => `<tr><td>${escapeHtml(r.inst_name)}</td>
<td><span class="tag tag-${r.rating}">${r.rating}</span></td>
<td class="num">${r.target_price}</td><td>${r.rating_date}</td></tr>`).join('')}
</table>` : '', ratings.length);
// 6. 基金持仓
const holdings = s.holdings || [];
html += srcBlock('基金持仓', '💼', holdings.length ? `<table>
<tr><th>机构</th><th>季度</th><th>持仓市值</th><th>环比</th></tr>
${holdings.map(h => `<tr><td>${escapeHtml(h.inst_name)}</td><td>${h.quarter}</td>
<td class="num">${fmtNum(h.hold_value)}</td>
<td class="num ${pctClass(h.change_pct)}">${fmtPct(h.change_pct)}</td></tr>`).join('')}
</table>` : '', holdings.length);
// 7. 完整提示词
html += srcBlock('完整提示词(Prompt', '🧠', s.prompt ? `<pre class="src-pre">${escapeHtml(s.prompt)}</pre>` : '', s.prompt ? 1 : 0);
$('#sourceBox').innerHTML = html;
}
load();