"""审查结果数据结构。""" from __future__ import annotations from collections import Counter from typing import Literal from pydantic import BaseModel, Field from fastapi_modules.fastapi_leaudit.govdoc_engine.models import Finding from fastapi_modules.fastapi_leaudit.govdoc_engine.parser.entities import SemanticEntity class CheckedRule(BaseModel): rule_id: str name: str severity: str category: str status: Literal["pass", "fail", "skipped"] skip_reason: str = "" class StructureItem(BaseModel): """文档结构里一种 role 的统计。""" role: str label: str count: int expected: bool paragraph_indices: list[int] = Field(default_factory=list) samples: list[str] = Field(default_factory=list) char_total: int = 0 dominant_font: str | None = None dominant_size_pt: float | None = None style_uniform: bool = True class OutlineNode(BaseModel): """大纲节点(heading_1~4 的层级树)。""" paragraph_index: int level: int text: str children: list["OutlineNode"] = Field(default_factory=list) class AuditSummary(BaseModel): score: int = 100 total_findings: int = 0 by_severity: dict[str, int] = Field(default_factory=dict) by_category: dict[str, int] = Field(default_factory=dict) passed_count: int = 0 failed_count: int = 0 skipped_count: int = 0 class AuditResult(BaseModel): audit_id: str document: dict = Field(default_factory=dict) summary: AuditSummary = Field(default_factory=AuditSummary) findings: list[Finding] = Field(default_factory=list) checked_rules: list[CheckedRule] = Field(default_factory=list) structure: list[StructureItem] = Field(default_factory=list) outline: list[OutlineNode] = Field(default_factory=list) entities: dict[str, SemanticEntity | None] = Field(default_factory=dict) def compute_summary(self) -> None: sev_count = Counter(f.severity for f in self.findings) cat_count = Counter(f.category for f in self.findings) score = 100 score -= 10 * sev_count.get("error", 0) score -= 3 * sev_count.get("warning", 0) passed = sum(1 for r in self.checked_rules if r.status == "pass") failed = sum(1 for r in self.checked_rules if r.status == "fail") skipped = sum(1 for r in self.checked_rules if r.status == "skipped") self.summary = AuditSummary( score=max(0, score), total_findings=len(self.findings), by_severity=dict(sev_count), by_category=dict(cat_count), passed_count=passed, failed_count=failed, skipped_count=skipped, )