装闭 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 报告。

相关推荐
老余说AI1 小时前
TikTok Shop东南亚上线“内容授权工具“,搬运内容可合法化
人工智能
o_insist1 小时前
从 Vue 生命周期与 Spring AOP 理解 LangChain Middleware
人工智能·agent
TunerT_TQ1 小时前
Microsoft 微软 AI-For-Beginners 静态评测:一套 AI 入门课程,为什么不能只按代码仓库来评价?
microsoft·开源·github
o_insist1 小时前
AI Agent 如何动态选择工具:Skill 匹配与三种筛选模式
人工智能·agent
l1258651 小时前
# RAG重排序实战:硅基流动bge-reranker-v2-m3在线API vs 本地CrossEncoder,一篇讲透两种方案
数据库·人工智能·python·深度学习·算法·机器学习·langchain
u1301301 小时前
GitHub 热榜项目:日榜(2026-08-17)
github
yingyuecom1 小时前
Seedance 2.5正式发布:映悦AI迎来“更长、更可控、更极致”的视频生成时代
人工智能·gpt·chatgpt·prompt·aigc
DS随心转APP1 小时前
生成word文档的ChatGPT格式乱码终结者:AI导出鸭横向测评与工程化架构解析 摘要
人工智能·ai·chatgpt·word·deepseek·ai导出鸭
MindUp1 小时前
告别排版焦虑:从 PPT 模板到 AI 生成工具的个人使用体验与效率对比
人工智能·powerpoint