装闭 RenoPit 源码解析(12):从AI分析结果到React避坑报告

设计分析、合同审查、增项预测和跨文档核查分别产生不同结构的数据,报告页却需要一次性展示它们。装闭 RenoPit 在开源仓库 fthux/RenoPit 中通过 /result 接口先统一后端数据,再由 React 按结果内容组合页面。

一、报告页只请求一个聚合接口

AnalysisPage.tsx 从路由参数取得项目 ID,调用:

tsx 复制代码
const res = await fetch(`${API}/projects/${projectId}/result`)
if (res.ok) setResult(await res.json())

页面不直接查询 AnalysisDocumentAnalysis 或交叉核查接口。数据拼装集中在后端,前端只消费 AnalysisResult

get_analysis_result() 先确认项目存在,再按 Analysis.created_at 倒序获取最近一条分析。失败分析也会返回固定结构:评分和各级问题数量为零,summary_texterror_message 保存失败原因,使前端仍能进入统一的状态判断。

二、原始 AI JSON 如何变成 pitfalls

成功记录交给 _build_result_data()。它从 raw_result_json.problems 读取模型问题,再逐条转换成前端的 PitfallItem

python 复制代码
pitfalls.append({
    "id": str(i + 1),
    "category": _infer_category(problem),
    "description": problem.get("title", ""),
    "severity": _infer_severity(problem),
    "location": problem.get("location"),
    "suggestion": problem.get("alternative", ""),
    "critique": problem.get("critique"),
    "trap_explanation": problem.get("trap_explanation"),
    "bbox": problem.get("bbox"),
})

严重程度通过标题和批判文本中的关键词推断。例如安全、坠落、火灾、漏电优先归为 critical;高额、陷阱、浪费归为 high;未命中时默认 medium

类别同样采用关键词映射,依次识别卫生死角、空间压迫、安全健康、隐性成本和实用性伪需求,无法识别时返回"其他"。

三、评分和统计如何生成

如果模型返回的 summary 中带有 score,后端优先使用该值;否则根据问题数计算:

python 复制代码
score = 95 if problem_count == 0 else max(
    0, 100 - problem_count * 8
)

_count_severities() 再统计严重、高、中、低四类数量,组装 summary。因此前端无需遍历问题列表计算顶部统计卡。

页面将评分分为三个显示区间:80 分以上"优秀",60~79 分"待改进",低于 60 分"需重视"。这些标签只负责展示,原始分数仍来自后端结果。

四、文档结果如何合并

接口查询当前项目全部已完成的 DocumentAnalysis,按完成时间倒序交给 _serialize_document_analyses()

序列化结果以 project_file_id 为键。同一文件如果被分析多次,只保留排序后的第一条,也就是最新结果。每条数据包含风险列表、分类置信度、总结、预估风险金额和可选的 extra_item_prediction

最后,接口检查综合分析 JSON 中是否存在 cross_document_checks,存在就直接注入返回值。至此,一次响应已经包含报告页的全部章节。

五、React 如何决定显示哪些章节

AnalysisPage 根据数据动态创建导航项:

  • 总体评价、陷阱数、综合评分始终显示;
  • pitfalls 非空时显示问题详情;
  • 存在文档分析时显示合同与报价单;
  • 任一文档带增项预测时显示增项章节;
  • 存在差异项时显示跨文档核查。

页面使用 IntersectionObserver 观察这些章节,选择可见比例最高的部分更新 activeSection。桌面端显示可折叠的固定侧栏,移动端使用单独导航,点击后按照顶部偏移量平滑滚动。

六、问题详情如何渲染

每个 PitfallCard 根据 severityConfig 选择图标、颜色、背景和中文标签。卡片展示分类、位置、问题分析、套路说明与替代建议;后端没有提供的可选字段不会渲染空区域。

合同结果由文档风险区块展示,增项预测交给 ExtraPredictionPanel,跨文档结果交给 CrossCheckPanel。这些组件不再请求后端,只处理已经聚合到 result 中的数据。

加载、接口失败和分析失败也分别有独立页面状态。这样报告页不会在数据未准备好时尝试解构 summarypitfalls

七、报告数据链小结

RenoPit 的报告展示分成两层:后端把模型原始 JSON 转换为稳定的 AnalysisResult,React 再根据字段是否存在组合页面。评分、严重程度、最新文档结果和交叉核查都在 /result 这一条边界上汇合。

结果聚合函数、TypeScript 类型和报告组件可以在 fthux/RenoPit 中查看。下一篇将继续复用同一份结果数据,分析 RenoPit 如何使用 ReportLab 生成可下载的中文 PDF 报告。

相关推荐
海鸥813 小时前
AIOps(智能运维)理解
运维·人工智能
weixin_468466853 小时前
从“建模城市”到“按需查询”:D4RT如何用200+FPS重新定义动态3D世界
人工智能·3d·具身智能·d4rt·4d重建
广州硅基技术官方3 小时前
AIGK外贸工厂社媒引流实战教程:海外自媒体短视频AI矩阵获客玩法解析
人工智能·音视频·媒体
额鹅恶饿呃3 小时前
算力计算核心前提:分清GPU两套独立计算硬件
人工智能
Dream-Y.ocean3 小时前
基于具身交互智能数字人,我用Flask搭了一个AI教学平台:课代表AI全流程实战
人工智能·flask·交互
Canace3 小时前
最新版 Codex 工作流的问题
前端·人工智能·agent
月华路3 小时前
《模型不玄学》第20章 两种评估视角
人工智能·算法·机器学习
AI棒棒牛3 小时前
YOLO26最新创新改进系列:融合 MVIGGraphFusionBlock,构建互视信息图注意力 Neck,嘎嘎创新!
人工智能·计算机视觉·yolo26
底层信号4 小时前
沙箱管得住 Agent 的手,管不住它的目标 —— 从 OpenAI 7 月逃逸事件看 Agent 安全的真正瓶颈
人工智能·安全
桃西西呀4 小时前
同一个模型 30% 到 100%?拆解 Harness 工程的 5 个机制,附 8 个坑的自检清单
人工智能·llm·ai编程