拓冰建站拓冰建站
首页 / 资讯中心 / 正文

TradingAgents-CN 股票详情页分析报告展示方案:从后端数据核验到前端报告渲染与导出

TradingAgents-CN 股票详情页分析报告展示方案从后端数据核验到前端报告渲染与导出【免费下载链接】TradingAgents-CN基于多智能体LLM的中文金融交易框架 - TradingAgents中文增强版项目地址: https://gitcode.com/GitHub_Trending/tr/TradingAgents-CN本篇技术文章围绕 TradingAgents-CN基于多智能体 LLM 的中文金融交易框架中股票详情页分析报告不展示问题的完整解决过程展开先通过后端 API 核验确认reports字段数据格式正确再从前端 Detail.vue 的缺口定位入手详解报告预览区、标签页对话框、Markdown 渲染与报告导出四块功能的实现方式。读完本文你可以掌握前后端数据不一致类问题的排查路径以及该框架多智能体分析结果7~13 份报告在前端的完整展示方案。问题背景报告能获取到却看不到用户反馈的现象是前端股票详情页可以获取到该股票的分析报告但页面上没有展示出来。初步怀疑是前后端数据格式不一致。原始文档记录了完整的诊断过程其结论值得所有排查类似问题的开发者参考——最终确认问题根源不是前后端数据格式不一致而是前端根本没有实现报告展示功能。下面按先证伪、再定位、后实现的顺序还原整个过程。第一步核验后端数据格式API 端点分析结果通过以下两个端点获取GET /api/analysis/tasks/{task_id}/result GET /api/analysis/user/history?stock_code002475page1page_size1statuscompleted对应后端实现位于 app/routers/analysis.py其中GET /tasks/{task_id}/result端点第 221 行起的get_task_result采用内存优先、MongoDB 兜底的双层读取策略任务状态为completed时先从内存取result_data内存中没有例如服务重启后则回落到 MongoDB 的analysis_reports集合按task_id匹配并对旧数据无task_id字段按analysis_id兜底查询。这解释了为什么详情页刷新后历史报告依然可以展示。返回数据结构data字段中与分析展示相关的核心结构如下示例数据取自原始文档中002475立讯精密的真实响应{ success: true, data: { analysis_id: ..., stock_symbol: 002475, stock_code: 002475, analysis_date: 2025-09-30, summary: 基于事实纠错、逻辑重构、风险评估与历史教训后的负责任投资判断。, recommendation: 操作: sell目标价: 48.0置信度: 0.75, confidence_score: 0.9, risk_level: 高, key_points: [], analysts: [market, fundamentals, investment_team, trader, risk_manager], research_depth: 快速, reports: { market_report: # 002475 股票技术分析报告\n\n## 一、价格趋势分析\n\n..., fundamentals_report: ### 1. **公司基本信息分析立讯精密股票代码002475**\n\n..., investment_plan: 我们来一场真正意义上的投资决策辩论——不是走形式而是基于事实、逻辑和经验..., trader_investment_plan: 最终交易建议: **卖出**\n\n### 投资建议**卖出**\n\n..., final_trade_decision: ---\n\n## **最终决策明确建议 —— 卖出Sell**\n\n..., research_team_decision: 我们来一场真正意义上的投资决策辩论——不是走形式..., risk_management_decision: ---\n\n## **最终决策明确建议 —— 卖出Sell**\n\n... }, decision: {}, state: {} }, message: 分析结果获取成功 }核验得到四个关键事实reports字段存在且格式正确reports是一个字典包含 7 个详细报告每个报告都是 Markdown 格式的字符串报告内容完整且有意义。后端被排除嫌疑。第二步定位前端展示缺口检查前端 frontend/src/views/Stocks/Detail.vue 的分析结果卡片修复前的展示逻辑只有div v-else classdetail div classrow el-tag :typelastAnalysisTagType sizesmall{{ lastAnalysis?.recommendation || - }}/el-tag span classconf信心度 {{ fmtConf(lastAnalysis?.confidence_score ?? lastAnalysis?.overall_score) }}/span span classdate{{ lastAnalysis?.analysis_date || - }}/span /div div classsummary-text{{ lastAnalysis?.summary || - }}/div /div问题一目了然只展示了recommendation投资建议只展示了confidence_score信心度只展示了summary分析摘要完全没有展示reports字段中的详细报告内容。解决方案在前端补齐完整的报告展示链路核心思路是在详情页分析结果卡片中新增四块能力报告预览区域报告数量与标签列表、查看完整报告按钮、标签页组织的报告对话框、Markdown 渲染外加报告导出功能。整体数据流为后端API (/api/analysis/tasks/{task_id}/result) ↓ 前端API调用 (analysisApi.getTaskResult) ↓ 存储到 lastAnalysis.value ↓ 模板渲染 (v-iflastAnalysis?.reports) ↓ 用户交互 (查看/导出)对应到源码Detail.vue中通过analysisApi.getTaskResult(latestTask.task_id)拉取结果后写入lastAnalysis响应式状态第 996 行附近模板再基于该状态条件渲染。报告预览区域在分析结果卡片中于分析摘要下方追加报告区块仅当reports非空时渲染保证对没有reports字段的旧数据兼容!-- 详细报告展示 -- div v-iflastAnalysis?.reports Object.keys(lastAnalysis.reports).length 0 classreports-section el-divider / div classreports-header span classreports-title详细分析报告 ({{ Object.keys(lastAnalysis.reports).length }})/span el-button typeprimary plain clickshowReportsDialog true :iconDocument 查看完整报告 /el-button /div !-- 报告列表预览 -- div classreports-preview el-tag v-forreportKey in reportKeys :keyreportKey sizesmall effectplain classreport-tag clickopenReport(reportKey) {{ formatReportName(reportKey) }} /el-tag /div /div实际实现比方案稿更进一步报告标签不只是静态预览绑定了clickopenReport(reportKey)点击任意标签可直接打开对话框并定位到对应标签页。reportKeys是一个计算属性从lastAnalysis.reports动态提取键列表第 1163-1166 行因此报告数量与类型完全由后端数据驱动前端无需硬编码。报告对话框使用 Element Plus 的el-dialogel-tabs承载多份报告el-scrollbar固定 500px 高度支持长内容滚动close-on-click-modal设为false防止误触关闭!-- 详细报告对话框 -- el-dialog v-modelshowReportsDialog title详细分析报告 width80% :close-on-click-modalfalse classreports-dialog el-tabs v-modelactiveReportTab typeborder-card el-tab-pane v-forreportKey in reportKeys :keyreportKey :labelformatReportName(reportKey) :namereportKey div classreport-content el-scrollbar height500px div classmarkdown-body v-htmlrenderMarkdown(lastAnalysis?.reports?.[reportKey] || )/div /el-scrollbar /div /el-tab-pane /el-tabs template #footer el-button clickshowReportsDialog false关闭/el-button el-button typeprimary clickexportReport导出报告/el-button /template /el-dialog对话框与预览区共用showReportsDialog、activeReportTab两个响应式状态第 394-395 行openReport函数同时置位两者实现点标签直达目标页签第 1169-1172 行。报告名称映射覆盖全部 13 类报告方案稿最初只映射了 9 个报告键实际落地版本在 Detail.vue 第 1118-1150 行 扩展为完整的 13 键映射与该框架多智能体团队的分工一一对应function formatReportName(key: string): string { const nameMap: Recordstring, string { // 分析师团队 (4个) market_report: 市场技术分析, sentiment_report: 市场情绪分析, news_report: 新闻事件分析, fundamentals_report: 基本面分析, // 研究团队 (3个) bull_researcher: 多头研究员, bear_researcher: 空头研究员, research_team_decision: 研究经理决策, // 交易团队 (1个) trader_investment_plan: 交易员计划, // 风险管理团队 (4个) risky_analyst: 激进分析师, safe_analyst: 保守分析师, neutral_analyst: 中性分析师, risk_management_decision: 投资组合经理, // 最终决策 (1个) final_trade_decision: 最终交易决策, // 兼容旧字段 investment_plan: 投资建议, investment_debate_state: 研究团队决策旧, risk_debate_state: 风险管理团队旧 } return nameMap[key] || key.replace(/_/g, ).replace(/\b\w/g, l l.toUpperCase()) }从源码结构看这套映射恰好对应该框架分析师团队市场/情绪/新闻/基本面→ 研究团队多空研究员 研究经理→ 交易团队 → 风险管理团队激进/保守/中性分析师 组合经理→ 最终决策的辩论式工作流未命中的键走通用格式化兜底下划线转空格、首字母大写因此即便后端新增报告类型前端也能降级展示而不会白屏。Markdown 渲染与容错import { marked } from marked // 渲染Markdown function renderMarkdown(content: string): string { if (!content) return p暂无内容/p try { return String(marked.parse(content)) } catch (e) { console.error(Markdown渲染失败:, e) return pre${content}/pre } }实现上有三层容错空内容返回占位文本marked解析异常时回退为pre原文输出保证任何报告都看得见。marked已在 frontend/package.json 中声明marked: ^16.2.0无需额外安装。同一函数也用于分析摘要卡片的渲染第 167 行保证摘要与报告的 Markdown 风格一致。报告导出导出功能将全部报告拼装为一份 Markdown 文档并触发浏览器下载Detail.vue 第 1175-1223 行function exportReport() { if (!lastAnalysis.value?.reports) { ElMessage.warning(暂无报告可导出) return } // 生成Markdown格式的完整报告 let fullReport # ${code.value} 股票分析报告\n\n // 优先使用任务结束时间Asia/Shanghai 时区否则退回分析日期 const reportTime lastTaskInfo.value?.end_time ? new Date(lastTaskInfo.value.end_time).toLocaleString(zh-CN, { timeZone: Asia/Shanghai, year: numeric, month: 2-digit, day: 2-digit, hour: 2-digit, minute: 2-digit, hour12: false }) : lastAnalysis.value?.analysis_date fullReport **分析时间**: ${reportTime}\n fullReport **投资建议**: ${lastAnalysis.value.recommendation}\n fullReport **信心度**: ${fmtConf(lastAnalysis.value.confidence_score)}\n\n fullReport ---\n\n for (const [key, content] of Object.entries(lastAnalysis.value.reports)) { fullReport ## ${formatReportName(key)}\n\n fullReport ${content}\n\n fullReport ---\n\n } // 通过 Blob 临时 a 触发下载 const blob new Blob([fullReport], { type: text/markdown;charsetutf-8 }) const url URL.createObjectURL(blob) const link document.createElement(a) link.href url const fileDate lastAnalysis.value.analysis_date || new Date().toISOString().slice(0, 10) link.download ${code.value}_分析报告_${fileDate}.md document.body.appendChild(link) link.click() document.body.removeChild(link) URL.revokeObjectURL(url) ElMessage.success(报告已导出) }细节上报告头部带分析时间优先取任务end_time并转换到Asia/Shanghai时区保证与页面展示一致、投资建议与信心度每份报告以二级标题分隔文件自动命名为股票代码_分析报告_分析日期.md。Markdown 渲染样式Detail.vue的 scoped 样式中定义了.markdown-body完整排版规则第 1336 行起覆盖标题字号、段落行距、列表缩进、行内/块级代码、引用块和表格边框等.reports-section { margin-top: 16px; } .reports-header { display: flex; justify-content: space-between; align-items: center; } .reports-preview { display: flex; flex-wrap: wrap; gap: 8px; } .markdown-body { font-size: 14px; line-height: 1.8; h1 { font-size: 24px; font-weight: 700; } h2 { font-size: 20px; font-weight: 600; } h3 { font-size: 16px; font-weight: 600; } /* 另有 p / ul / ol / li / code / pre / blockquote / table 等规则 */ }功能特性汇总报告预览显示报告数量如详细分析报告 (7)、所有报告标签列表点击标签直达对应页签也可通过查看完整报告按钮一键打开对话框报告展示标签页组织多份报告Markdown 完整渲染标题、列表、表格、代码块等500px 滚动区支持长内容报告导出Markdown 格式、包含全部报告内容、按股票代码_分析报告_日期.md自动命名样式统一的markdown-body排版摘要与报告渲染风格一致。兼容性设计方案在三个维度保持了向后兼容兼容旧数据v-iflastAnalysis?.reports Object.keys(lastAnalysis.reports).length 0确保没有reports字段的历史记录不渲染报告区块页面行为与修复前一致兼容不同报告类型reportKeys计算属性 formatReportName的兜底格式化使报告数量与类型对前端透明兼容空报告内容renderMarkdown对空字符串返回暂无内容占位渲染失败回退pre。测试验证原始文档记录了两个层面的验证后端数据测试通过测试脚本请求GET /api/analysis/tasks/{task_id}/result与GET /api/analysis/user/history断言reports字典存在、含 7 个报告键、每份报告为 Markdown 字符串且内容非空结果全部通过。前端功能测试访问http://localhost:5173/stocks/002475逐项验证显示分析结果卡片显示详细分析报告 (7)显示 7 个报告标签点击查看完整报告弹出对话框7 个标签页都能正常切换Markdown 渲染正确可以导出报告。仓库中保留了配套的手动验证指南 scripts/verify_reports_display.md可用于对该功能做回归检查。技术要点小结排查方法论先用 API 直接核验后端返回结构确认reports字段完整把数据格式不一致假设证伪再转向前端渲染层定位缺口——问题根源是前端未实现功能而非数据问题数据流后端 analysis.py 的 result 端点内存优先、MongoDBanalysis_reports兜底→analysisApi.getTaskResult→lastAnalysis响应式状态 → 模板条件渲染 → 用户查看/导出关键依赖markedMarkdown 渲染见 frontend/package.json、Element PlusUI 组件库、Vue 3 响应式系统修改范围核心改动集中在 frontend/src/views/Stocks/Detail.vue 单文件内新增预览区、对话框、formatReportName/renderMarkdown/openReport/exportReport四个函数及markdown-body样式未改动后端接口。原始方案总结文档见 docs/archive/SOLUTION_SUMMARY.md。该案例也提示在多智能体分析类系统中当数据拿到了但页面没有时优先用 API 请求把前后端责任边界切清楚往往能省去大量无谓的双向排查。【免费下载链接】TradingAgents-CN基于多智能体LLM的中文金融交易框架 - TradingAgents中文增强版项目地址: https://gitcode.com/GitHub_Trending/tr/TradingAgents-CN创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门