AgentCPM深度研报助手JavaScript前端集成:实现实时报告预览与交互

📅 发布时间:2026/7/14 4:59:27 👁️ 浏览次数:
AgentCPM深度研报助手JavaScript前端集成:实现实时报告预览与交互
AgentCPM深度研报助手JavaScript前端集成实现实时报告预览与交互最近在做一个金融数据分析平台需要集成一个能自动生成深度研报的功能。我们团队评估了几个方案最终选择了AgentCPM深度研报助手因为它生成的报告逻辑清晰、数据支撑也比较扎实。但问题来了怎么把这个后端服务的能力平滑地搬到前端页面上让用户能实时看到报告生成进度并且还能和生成的图表互动呢这篇文章我就来聊聊我们是怎么用JavaScript搞定这件事的。整个过程不复杂核心就是处理好前后端的通信让用户从提交任务到拿到一份可交互的漂亮报告体验足够流畅。如果你也在做类似的数据可视化或者AI应用集成希望这些经验能给你一些参考。1. 项目场景与核心需求我们的平台用户主要是分析师和投资经理。他们经常需要针对某个行业或公司快速生成一份初步的分析报告作为研究起点。以前的做法是用户填写一堆表单提交到后台等个几分钟甚至更久然后收到一封带PDF附件的邮件。这个流程体验很割裂用户不知道进度也无法在报告生成过程中进行任何干预或预览。所以我们定了几个核心目标 第一实时性。用户提交任务后不能让他干等着。前端得能实时反馈生成进度比如“正在收集数据”、“正在撰写分析章节”这样的状态。 第二可预览。报告生成后不应该只是一个下载链接。最好能在页面内直接渲染出报告的主要内容特别是图表让用户快速浏览结论。 第三可交互。生成的图表如果是静态图片就太可惜了。如果图表是动态的比如ECharts或Highcharts生成的用户应该能悬停查看数据详情、切换指标、缩放时间范围这样报告的价值就大得多。 第四集成要轻量。不能因为接入了这个研报助手就让前端页面变得臃肿不堪。调用方式要简单对现有项目结构侵入性要小。AgentCPM的API设计得比较友好为我们实现这些目标提供了基础。接下来我就分步拆解一下前端集成的关键环节。2. 前端技术栈与准备工作我们项目本身是基于Vue 3和TypeScript的但下面讲到的集成思路和代码用原生JavaScript、React或其他任何现代前端框架都能实现原理是相通的。在动手写代码之前需要先准备好几样东西2.1 获取API凭证首先你得有权限调用AgentCPM的服务。这通常意味着你要有一个API Key密钥和一个API Endpoint接口地址。这个密钥就像一把钥匙每次请求都要带上它服务端才知道是你在调用。切记这个密钥要保管好绝对不能直接硬编码在前端代码里否则谁都能看到并滥用你的额度。正确的做法是通过你自己的后端服务器来中转请求或者使用有严格权限控制的云函数。2.2 理解API接口AgentCPM的研报生成通常是一个异步任务。你需要仔细阅读它的API文档重点关注三个接口提交任务接口发送你要分析的标的比如股票代码、分析维度、时间范围等参数启动一个研报生成任务。这个接口会返回一个唯一的task_id。查询任务状态接口根据上一步拿到的task_id不断询问后台“我的报告生成到哪一步了” 它会返回任务状态如“排队中”、“进行中”、“已完成”、“失败”和进度信息。获取结果接口当任务状态变成“已完成”时调用这个接口传入task_id就能拿到最终的研报数据。2.3 规划前端交互界面在UI层面我们设计了一个简单的区域包含一个表单用于输入分析参数。一个进度条或状态提示区域实时显示当前进度。一个报告预览区域最初是空的报告生成后用于渲染内容和图表。可能还需要一个历史任务列表。技术准备上我们主要会用到fetchAPI或者axios库来发送HTTP请求以及WebSocket或Server-Sent Events (SSE)来实现进度的实时推送。为了渲染交互式图表我们选择了ECharts因为它功能强大且文档完善。3. 核心集成步骤详解有了前面的准备我们就可以开始编写核心的JavaScript逻辑了。整个过程可以看作一个状态机驱动着用户界面不断更新。3.1 第一步提交研报生成任务当用户填写好表单并点击“生成报告”按钮时我们需要收集表单数据将其构造成AgentCPM API要求的格式然后发起请求。// 假设我们有一个表单其id为‘reportForm’ const form document.getElementById(reportForm); const submitBtn document.getElementById(generateBtn); const statusDiv document.getElementById(status); submitBtn.addEventListener(click, async (event) { event.preventDefault(); // 阻止表单默认提交行为 // 1. 收集表单数据 const formData { symbol: document.getElementById(stockSymbol).value, analysis_period: document.getElementById(period).value, focus_areas: Array.from(document.querySelectorAll(input[namefocus]:checked)).map(cb cb.value), // ... 其他参数 }; // 2. 禁用按钮防止重复提交并更新状态 submitBtn.disabled true; submitBtn.textContent 提交中...; statusDiv.textContent 正在提交任务...; statusDiv.className status-pending; try { // 3. 调用你自己的后端代理接口而不是直接调用AgentCPM // 你的后端服务会负责添加API Key并转发请求给AgentCPM const response await fetch(/api/agentcpm/submit-task, { method: POST, headers: { Content-Type: application/json, }, body: JSON.stringify(formData) }); if (!response.ok) { throw new Error(提交失败: ${response.status}); } const result await response.json(); // 4. 从响应中获取任务ID if (result.success result.data.task_id) { const taskId result.data.task_id; statusDiv.textContent 任务已提交ID: ${taskId}; statusDiv.className status-submitted; // 5. 启动任务状态轮询或WebSocket监听 startTrackingTask(taskId); } else { throw new Error(result.message || 未知错误); } } catch (error) { // 6. 错误处理 console.error(提交任务时出错:, error); statusDiv.textContent 错误: ${error.message}; statusDiv.className status-error; submitBtn.disabled false; submitBtn.textContent 重新生成报告; } });这里的关键点是所有对AgentCPM的请求都应该通过你自己的后端服务来代理。前端只跟你自己的服务器通信由后端服务器负责携带API Key去调用AgentCPM并处理可能存在的跨域问题。这样最安全。3.2 第二步实时追踪任务状态任务提交后就进入了一个可能持续几十秒甚至几分钟的生成过程。我们需要让用户感知到这个过程。有两种主流方案方案A短轮询这是一种简单粗暴但有效的方法。前端每隔几秒比如3秒就主动发一次请求询问任务状态。let pollInterval; function startPollingTaskStatus(taskId) { statusDiv.textContent 任务已开始处理...; statusDiv.className status-processing; pollInterval setInterval(async () { try { const response await fetch(/api/agentcpm/task-status/${taskId}); const result await response.json(); // 更新UI状态 updateTaskStatusUI(result.data); // 判断任务是否结束 if (result.data.status completed) { clearInterval(pollInterval); onTaskCompleted(taskId); // 任务完成去获取结果 } else if (result.data.status failed) { clearInterval(pollInterval); statusDiv.textContent 任务失败: ${result.data.error_message}; statusDiv.className status-error; submitBtn.disabled false; submitBtn.textContent 重新生成报告; } // 如果状态是 ‘processing’继续轮询并可以显示更细的进度信息 } catch (error) { console.error(轮询状态出错:, error); // 可以考虑加入重试逻辑 } }, 3000); // 每3秒轮询一次 } function updateTaskStatusUI(statusData) { // 根据后端返回的状态数据更新界面 // 例如statusData.stage 可能是 “data_collecting”, “analyzing”, “writing” const stageMap { data_collecting: 正在收集市场数据..., analyzing: 正在分析财务指标..., writing: 正在撰写报告内容..., formatting: 正在生成最终文档... }; const message stageMap[statusData.stage] || 正在处理中...; const progress statusData.progress || 0; // 假设有0-100的进度值 statusDiv.innerHTML p${message}/p div classprogress-bar div classprogress-fill stylewidth: ${progress}%;/div /div p进度: ${progress}%/p ; }方案BWebSocket长连接对于实时性要求更高、或任务状态变更很频繁的场景WebSocket是更好的选择。它允许服务端主动向前端推送消息。// 前端建立WebSocket连接 const socket new WebSocket(wss://your-backend.com/ws/task-updates); socket.addEventListener(open, (event) { console.log(WebSocket连接已建立); // 连接建立后发送消息告知服务器要监听哪个taskId socket.send(JSON.stringify({ action: subscribe, task_id: taskId })); }); socket.addEventListener(message, (event) { const message JSON.parse(event.data); if (message.task_id taskId) { // 更新任务状态UI updateTaskStatusUI(message.data); if (message.data.status completed) { socket.close(); // 任务完成关闭连接 onTaskCompleted(taskId); } else if (message.data.status failed) { socket.close(); // ... 错误处理 } } }); socket.addEventListener(error, (error) { console.error(WebSocket错误:, error); // 可以降级为轮询 startPollingTaskStatus(taskId); });短轮询实现简单兼容性好但在无状态更新时会产生大量无效请求。WebSocket更高效、实时但需要后端支持并且要考虑连接稳定性。在我们的项目里因为任务状态更新没那么频繁几十秒更新一次为了快速上线先用了短轮询效果也不错。3.3 第三步渲染与交互式报告预览当收到任务完成的通知后我们就调用获取结果的接口拿到最终的研报数据。async function onTaskCompleted(taskId) { statusDiv.textContent 报告生成成功正在加载...; statusDiv.className status-success; try { const response await fetch(/api/agentcpm/task-result/${taskId}); const result await response.json(); if (result.success) { const reportData result.data.report; // 渲染报告到页面 renderReportPreview(reportData); // 恢复按钮状态 submitBtn.disabled false; submitBtn.textContent 生成新报告; } } catch (error) { console.error(获取结果失败:, error); statusDiv.textContent 加载报告失败: ${error.message}; statusDiv.className status-error; } }reportData的结构可能包含标题、章节文本、关键数据点和图表配置。渲染文本内容相对简单挑战在于交互式图表。假设AgentCPM返回的图表数据是ECharts兼容的配置项option我们可以这样渲染import * as echarts from echarts; // 假设已引入ECharts库 function renderReportPreview(reportData) { const previewContainer document.getElementById(reportPreview); previewContainer.innerHTML ; // 清空旧内容 // 1. 渲染文本内容 const textSection document.createElement(div); textSection.className report-text; textSection.innerHTML h2${reportData.title}/h2 pstrong生成时间/strong${new Date(reportData.generated_at).toLocaleString()}/p div${reportData.summary}/div !-- 循环渲染各个章节 -- ${reportData.sections.map(section h3${section.title}/h3 p${section.content}/p ).join()} ; previewContainer.appendChild(textSection); // 2. 渲染交互式图表 if (reportData.charts reportData.charts.length 0) { const chartsSection document.createElement(div); chartsSection.className report-charts; chartsSection.innerHTML h3关键图表/h3; previewContainer.appendChild(chartsSection); reportData.charts.forEach((chartConfig, index) { const chartDiv document.createElement(div); chartDiv.id chart-${index}; chartDiv.style.width 100%; chartDiv.style.height 400px; chartsSection.appendChild(chartDiv); // 初始化ECharts实例 const chartInstance echarts.init(chartDiv); // 使用API返回的配置项渲染图表 chartInstance.setOption(chartConfig); // 3. 添加图表交互事件示例点击图例筛选 chartInstance.on(legendselectchanged, function(params) { console.log(图例被点击筛选:, params.selected); // 这里可以触发其他数据更新比如关联表格 updateRelatedTable(params.selected, chartConfig.chartId); }); // 窗口大小变化时重绘图表 window.addEventListener(resize, () chartInstance.resize()); }); } } // 一个简单的关联更新函数示例 function updateRelatedTable(selectedLegends, chartId) { // 根据选中的图例去过滤或高亮页面中关联的数据表格 console.log(图表 ${chartId} 的筛选状态变化影响相关表格); // ... 具体的表格更新逻辑 }这样一份包含可交互图表的研报就在前端页面里生动地展示出来了。用户不仅可以阅读文字分析还可以通过点击、悬停图表来探索数据细节报告的价值和体验感得到了极大提升。4. 总结把AgentCPM深度研报助手集成到前端项目里听起来技术点不少但拆解开来无非就是“提交-等待-展示”三步。核心在于选择一个合适的实时状态同步方案轮询或WebSocket以及用一个强大的图表库如ECharts来承接后端的数据并赋予其交互生命。我们实际做下来感觉最需要花心思的不是代码本身而是用户体验的设计。比如进度提示的文案要友好网络异常或任务失败时要给出清晰的错误引导图表加载时可以考虑用骨架屏占位等等。这些细节做好了整个功能才会显得流畅、专业。代码层面一定要记住API密钥的安全问题务必通过后端中转。错误处理也要做得完备毕竟网络请求和AI服务都有不稳定的可能。最后前端集成只是第一步如何将生成的报告进一步支持导出、分享、与平台其他功能联动还有很大的想象空间。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。