"""Govdoc Bridge — 结果适配器。 将 govdoc_engine 原始结果对象 (AuditResult / Finding / SemanticEntity) 映射为 ORM 模型字段和前端 VO 字典。 """ from __future__ import annotations from typing import Any from fastapi_modules.fastapi_leaudit.govdoc_engine.engine.result import AuditResult class ResultAdapter: """Govdoc 引擎结果 → 平台数据模型适配器。 负责将 govdoc_engine 的原始执行结果转换为: - GovdocRun 状态字段更新 - GovdocRuleResult 列表 - GovdocReportArtifact 清单 - 前端 VO 字典 """ def AdaptRunSummary( self, EngineResult: AuditResult, Structure: list[dict[str, Any]] | None = None, Outline: list[dict[str, Any]] | None = None, Entities: list[dict[str, Any]] | None = None, ) -> dict[str, Any]: """从 AuditResult.summary 提取 run 汇总字段。 同时接受已适配的 structure / outline 列表,一并序列化进 resultSummaryJson,供前端 structure-panel / outline-panel 读取。 """ import json s = EngineResult.summary aux: dict[str, Any] = {} if Structure is not None: aux["structure"] = Structure if Outline is not None: aux["outline"] = Outline if Entities is not None: aux["entities"] = { entity["name"]: entity for entity in Entities if entity.get("name") } return { "totalScore": s.score, "passedCount": s.passed_count, "failedCount": s.failed_count, "skippedCount": s.skipped_count, "resultStatus": "pass" if s.failed_count == 0 else "fail" if s.passed_count == 0 else "partial", "resultSummaryJson": json.dumps(aux, ensure_ascii=False) if aux else None, } def AdaptRuleResults(self, EngineResult: AuditResult) -> list[dict[str, Any]]: """从 AuditResult.findings 提取规则执行明细列表。""" results: list[dict[str, Any]] = [] for f in EngineResult.findings: results.append({ "ruleId": f.rule_id, "ruleName": f.rule_name, "severity": f.severity, "category": f.category, "message": f.message, "suggestion": f.suggestion, "actual": f.actual, "expected": f.expected, "evidence": f.evidence, "paragraphIndex": f.location.paragraph_index if f.location else None, "paragraphText": f.location.context if f.location else None, "locationPath": f.location.role if f.location else None, "result": "fail", "score": None, }) return results def AdaptCheckedRules(self, EngineResult: AuditResult) -> list[dict[str, Any]]: """从 AuditResult.checked_rules 提取规则检查状态列表。""" results: list[dict[str, Any]] = [] for cr in EngineResult.checked_rules: results.append({ "ruleId": cr.rule_id, "ruleName": cr.name, "severity": cr.severity, "category": cr.category, "result": cr.status, # pass/fail/skipped "skipReason": cr.skip_reason, "score": None, }) return results def AdaptEntities(self, EngineResult: AuditResult) -> list[dict[str, Any]]: """从 AuditResult.entities 提取实体识别结果。""" entities: list[dict[str, Any]] = [] for name, entity in EngineResult.entities.items(): if entity is None: continue entities.append({ "name": entity.name, "text": entity.text, "paragraphIndices": entity.paragraph_indices, "primaryRole": entity.primary_role, "source": entity.source, "confidence": entity.confidence, "extra": entity.extra, }) return entities def AdaptStructure(self, EngineResult: AuditResult) -> list[dict[str, Any]]: """从 AuditResult.structure 提取文档结构统计。""" results: list[dict[str, Any]] = [] for s in EngineResult.structure: results.append({ "role": s.role, "label": s.label, "count": s.count, "expected": s.expected, "paragraphIndices": s.paragraph_indices, "samples": s.samples, "charTotal": s.char_total, "dominantFont": s.dominant_font, "dominantSizePt": s.dominant_size_pt, "styleUniform": s.style_uniform, }) return results def AdaptOutline(self, EngineResult: AuditResult) -> list[dict[str, Any]]: """从 AuditResult.outline 提取大纲树(递归)。""" def _node(n) -> dict[str, Any]: return { "paragraphIndex": n.paragraph_index, "level": n.level, "text": n.text, "children": [_node(c) for c in (n.children or [])], } return [_node(n) for n in EngineResult.outline] def AdaptArtifacts(self, _EngineResult: AuditResult, _RunId: int) -> list[dict[str, Any]]: """从引擎结果提取报告产物清单。 报告文件由 reporter 模块生成后上传 OSS。 当前返回空列表,待 report_adapter 实现后补齐。 """ return [] def BuildDetailVO( self, Document: Any, Run: Any, RuleResults: list[dict[str, Any]], Entities: list[dict[str, Any]], Artifacts: list[dict[str, Any]], ) -> dict[str, Any]: """构建前端详情页 VO。""" return { "document": Document, "run": Run, "findings": RuleResults, "entities": Entities, "reports": Artifacts, }