82 lines
2.6 KiB
Python
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,
|
|
)
|