[migrate]:[FL-33][补齐防雷报告分级章节与图表输出]

Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
chengkai3
2026-06-08 01:32:56 +08:00
parent a9e2e587ae
commit f7c577932f
3 changed files with 1082 additions and 140 deletions
File diff suppressed because it is too large Load Diff
+10
View File
@@ -819,6 +819,13 @@ def _prepare_report_payload(
source_job = get_job_by_id(db, str(execution_options.get("source_job_id") or ""))
line = risk_job.line or job.line
mitigation_execution_options = mitigation_job.execution_options_json or {} if mitigation_job is not None else {}
non_construction = bool(
execution_options.get("non_construction")
or mitigation_execution_options.get("non_construction")
or mitigation_execution_options.get("mitigation_mode") == "non_construction"
or any(bool(_safe_dict(item.get("result_json")).get("non_construction")) for item in selected_mitigation_rows)
)
return {
"line": {
@@ -846,6 +853,7 @@ def _prepare_report_payload(
if scenario_job is not None
else None
),
"non_construction": non_construction,
},
"risk_rows": risk_rows,
"selected_risk_rows": selected_risk_rows,
@@ -862,6 +870,8 @@ def _serialize_report_row(item: FlAnalysisTowerResult) -> dict[str, Any]:
"tower_no": snapshot.tower_no if snapshot else None,
"tower_model": snapshot.tower_model if snapshot else None,
"tower_type": snapshot.tower_type if snapshot else None,
"base_tower_json": snapshot.base_tower_json if snapshot else {},
"profile_json": snapshot.profile_json if snapshot else {},
"risk_level": item.risk_level,
"summary_text": item.summary_text,
"result_json": item.result_json or {},
+177 -72
View File
@@ -5,7 +5,156 @@ from datetime import datetime
from app.services.fl_analysis_report import build_report_document, build_report_summary_payload
def _build_risk_row(
*,
tower_id: str,
tower_no: str,
tower_type: str,
terrain: str,
risk_level: str,
risk_grade: int,
score: int,
cause_analysis: str,
mitigation_recommendation: str,
lightning_density: float,
ground_resistance_ohm: float,
slope_deg: float,
protection_angle_deg: float,
insulator_length_mm: float,
shield_wire_height_m: float,
counterstrike_withstand_ka: float,
counterstrike_trip_rate: float,
shielding_withstand_ka: float,
shielding_trip_rate: float,
reason_details: list[dict[str, object]],
) -> dict[str, object]:
return {
"tower_id": tower_id,
"tower_no": tower_no,
"tower_type": tower_type,
"base_tower_json": {
"tower_type": tower_type,
"terrain": terrain,
"line_voltage_kv": 220,
"lightning_density": lightning_density,
"ground_resistance_ohm": ground_resistance_ohm,
"slope_1": slope_deg,
"slope_2": max(slope_deg - 2.0, 0.0),
"longitude": 120.0 + score / 1000.0,
"latitude": 30.0 + score / 1000.0,
},
"profile_json": {
"structure_kind": "单回",
"stroke_mode": "反击",
"insulator_length_m": round(insulator_length_mm / 1000.0, 4),
"shield_wire_height_m": shield_wire_height_m,
},
"risk_level": risk_level,
"result_json": {
"risk_grade": risk_grade,
"score": score,
"cause_analysis": cause_analysis,
"mitigation_recommendation": mitigation_recommendation,
"counterstrike_withstand_ka": counterstrike_withstand_ka,
"counterstrike_trip_rate": counterstrike_trip_rate,
"shielding_withstand_ka": shielding_withstand_ka,
"shielding_trip_rate": shielding_trip_rate,
"reason_details": reason_details,
"inputs": {
"ground_resistance_ohm": ground_resistance_ohm,
"lightning_density": lightning_density,
"insulator_length_mm": insulator_length_mm,
"terrain_slope_deg": slope_deg,
"protection_angle_deg": protection_angle_deg,
},
},
}
def _sample_report_data() -> dict[str, object]:
high_row = _build_risk_row(
tower_id="tower-1",
tower_no="001",
tower_type="直线",
terrain="山地",
risk_level="high",
risk_grade=3,
score=88,
cause_analysis="接地电阻偏高;保护角暴露偏大",
mitigation_recommendation="优先降低接地电阻;优化避雷线与保护角配置",
lightning_density=4.2,
ground_resistance_ohm=18.0,
slope_deg=6.8,
protection_angle_deg=23.0,
insulator_length_mm=2400.0,
shield_wire_height_m=46.0,
counterstrike_withstand_ka=96.2,
counterstrike_trip_rate=0.108,
shielding_withstand_ka=118.6,
shielding_trip_rate=0.021,
reason_details=[
{"code": "ground_resistance", "label": "接地电阻", "grade": 1, "triggered": True},
{"code": "protection_angle", "label": "保护角", "grade": 2, "triggered": True},
{"code": "shield_wire_height", "label": "高度档次", "grade": 1, "triggered": True, "value": 46.0, "standard_value": 33.0},
{"code": "terrain_slope", "label": "地面倾角档次", "grade": 3, "triggered": False, "value": 6.8},
{"code": "insulator_length", "label": "绝缘子串长度档次", "grade": 3, "triggered": False, "value": 2400.0, "standard_value": 2265.0},
],
)
medium_row = _build_risk_row(
tower_id="tower-2",
tower_no="002",
tower_type="耐张",
terrain="丘陵",
risk_level="medium",
risk_grade=2,
score=56,
cause_analysis="地闪密度中等偏高",
mitigation_recommendation="按高雷区口径校核绝缘与屏蔽配置",
lightning_density=2.2,
ground_resistance_ohm=9.0,
slope_deg=3.5,
protection_angle_deg=16.2,
insulator_length_mm=2550.0,
shield_wire_height_m=38.0,
counterstrike_withstand_ka=105.0,
counterstrike_trip_rate=0.052,
shielding_withstand_ka=126.0,
shielding_trip_rate=0.014,
reason_details=[
{"code": "lightning_density", "label": "地闪密度", "grade": 2, "triggered": True},
{"code": "shield_wire_height", "label": "高度档次", "grade": 4, "triggered": False, "value": 38.0, "standard_value": 33.0},
{"code": "terrain_slope", "label": "地面倾角档次", "grade": 4, "triggered": False, "value": 3.5},
{"code": "insulator_length", "label": "绝缘子串长度档次", "grade": 4, "triggered": False, "value": 2550.0, "standard_value": 2265.0},
{"code": "protection_angle", "label": "保护角", "grade": 3, "triggered": False, "value": 16.2},
],
)
low_row = _build_risk_row(
tower_id="tower-3",
tower_no="003",
tower_type="直线",
terrain="平原",
risk_level="low",
risk_grade=1,
score=18,
cause_analysis="主要输入参数处于低风险区间",
mitigation_recommendation="维持现有防雷配置并保持常规巡检",
lightning_density=0.62,
ground_resistance_ohm=4.0,
slope_deg=1.2,
protection_angle_deg=8.0,
insulator_length_mm=3100.0,
shield_wire_height_m=30.0,
counterstrike_withstand_ka=132.8,
counterstrike_trip_rate=0.008,
shielding_withstand_ka=148.4,
shielding_trip_rate=0.003,
reason_details=[
{"code": "shield_wire_height", "label": "高度档次", "grade": 5, "triggered": False, "value": 30.0, "standard_value": 33.0},
{"code": "terrain_slope", "label": "地面倾角档次", "grade": 4, "triggered": False, "value": 1.2},
{"code": "insulator_length", "label": "绝缘子串长度档次", "grade": 5, "triggered": False, "value": 3100.0, "standard_value": 2265.0},
{"code": "protection_angle", "label": "保护角", "grade": 5, "triggered": False, "value": 8.0},
],
)
return {
"line": {
"name": "示例线路",
@@ -25,76 +174,10 @@ def _sample_report_data() -> dict[str, object]:
"scenario_job_id": "scenario-job-1",
"scenario_job_name": "示例线路-加装避雷器复算",
"scenario_base_job_type": "normal",
"non_construction": False,
},
"risk_rows": [
{
"tower_id": "tower-1",
"tower_no": "001",
"risk_level": "high",
"result_json": {
"score": 88,
"cause_analysis": "接地电阻偏高;保护角暴露偏大",
"mitigation_recommendation": "优先降低接地电阻;优化避雷线与保护角配置",
"reason_details": [
{"code": "ground_resistance", "label": "接地电阻", "grade": 1, "triggered": True},
{"code": "protection_angle", "label": "保护角", "grade": 2, "triggered": True},
],
},
},
{
"tower_id": "tower-2",
"tower_no": "002",
"risk_level": "medium",
"result_json": {
"score": 56,
"cause_analysis": "地闪密度中等偏高",
"mitigation_recommendation": "按高雷区口径校核绝缘与屏蔽配置",
"reason_details": [
{"code": "lightning_density", "label": "地闪密度", "grade": 2, "triggered": True},
],
},
},
{
"tower_id": "tower-3",
"tower_no": "003",
"risk_level": "low",
"result_json": {
"score": 18,
"cause_analysis": "主要输入参数处于低风险区间",
"mitigation_recommendation": "维持现有防雷配置并保持常规巡检",
"reason_details": [],
},
},
],
"selected_risk_rows": [
{
"tower_id": "tower-1",
"tower_no": "001",
"risk_level": "high",
"result_json": {
"score": 88,
"cause_analysis": "接地电阻偏高;保护角暴露偏大",
"mitigation_recommendation": "优先降低接地电阻;优化避雷线与保护角配置",
"reason_details": [
{"code": "ground_resistance", "label": "接地电阻", "grade": 1, "triggered": True},
{"code": "protection_angle", "label": "保护角", "grade": 2, "triggered": True},
],
},
},
{
"tower_id": "tower-2",
"tower_no": "002",
"risk_level": "medium",
"result_json": {
"score": 56,
"cause_analysis": "地闪密度中等偏高",
"mitigation_recommendation": "按高雷区口径校核绝缘与屏蔽配置",
"reason_details": [
{"code": "lightning_density", "label": "地闪密度", "grade": 2, "triggered": True},
],
},
},
],
"risk_rows": [high_row, medium_row, low_row],
"selected_risk_rows": [high_row, medium_row],
"selected_mitigation_rows": [
{
"tower_id": "tower-1",
@@ -104,9 +187,27 @@ def _sample_report_data() -> dict[str, object]:
"current_risk_level": "high",
"expected_risk_level": "medium",
"recommendation_result": "需要安装避雷器",
"non_construction": False,
"inputs": {
"ground_resistance_ohm": 18.0,
"insulator_length_mm": 2400.0,
"protection_angle_deg": 23.0,
"lightning_density": 4.2,
},
"mitigation_actions": [
{"code": "grounding_upgrade", "label": "接地治理", "summary": "降低接地电阻"},
{"code": "arrester_install", "label": "安装避雷器", "summary": "关键相增设避雷器"},
{
"code": "grounding_upgrade",
"label": "接地治理",
"summary": "降低接地电阻",
"current_value": 18.0,
"target_value": 5.0,
},
{
"code": "arrester_install",
"label": "安装避雷器",
"summary": "关键相增设避雷器",
"phases": ["A", "B", "C"],
},
],
},
}
@@ -152,8 +253,12 @@ def test_build_report_document_renders_word_compatible_html() -> None:
assert filename.endswith(".doc")
assert "示例线路-报告" in filename
assert "示例线路" in html
assert "2.3线路杆塔高度" in html
assert "图7 线路杆塔地闪密度雷区分布图(表格替代)" in html
assert "图8 线路杆塔避雷线保护角信息统计图" in html
assert "表10 输电线路雷击风险等级划分规则" in html
assert "表13 高风险杆塔差异化防雷措施" in html
assert "雷害风险评估结果" in html
assert "差异化防雷措施与预期效果" in html
assert "安装避雷器" in html
assert "表14 采取措施后的计算结果表" in html
assert "反击耐雷水平(kA)" in html