Files
leaudit-platform-backend/fastapi_modules/fastapi_leaudit/govdoc_engine/engine/result.py
T

82 lines
2.6 KiB
Python

"""审查结果数据结构。"""
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,
)