| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- from __future__ import annotations
- from datetime import datetime, timezone
- from sqlalchemy.orm import Session
- from app.db.base import new_id
- from app.db.models.evaluation import EvaluationRun
- from app.db.repositories import diagnosis as diagnosis_repo
- from app.db.repositories import evaluation as evaluation_repo
- from app.db.repositories import monitoring as monitoring_repo
- from app.db.repositories import work_order as work_order_repo
- from app.schemas.evaluation import EvaluationRunRequest
- from app.services.mine_service import require_mine
- def _run_no() -> str:
- stamp = datetime.now(timezone.utc).strftime("%Y%m%d%H%M%S")
- return f"EV-{stamp}-{new_id()[:6].upper()}"
- def _grade(score: float) -> str:
- if score >= 90:
- return "A"
- if score >= 80:
- return "B"
- if score >= 70:
- return "C"
- return "D"
- def run_evaluation(
- db: Session,
- payload: EvaluationRunRequest,
- ) -> EvaluationRun:
- mine = require_mine(db, payload.mine_id)
- monitoring = monitoring_repo.monitoring_overview(db, mine.id)
- defects = diagnosis_repo.result_summary(db, mine.id)
- work_orders = work_order_repo.status_summary(db, mine.id)
- sensor_total = max(monitoring["sensor_count"], 1)
- online_ratio = monitoring["online_sensor_count"] / sensor_total
- high_defects = defects.get("high", 0)
- medium_defects = defects.get("medium", 0)
- open_orders = work_orders.get("pending", 0) + work_orders.get("processing", 0)
- total_orders = max(sum(work_orders.values()), 1)
- dimension_scores = {
- "安全性": max(50, 100 - high_defects * 8 - medium_defects * 3),
- "可靠性": round(70 + online_ratio * 30, 2),
- "经济性": 85.0,
- "管理合规": max(60, 100 - open_orders / total_orders * 30),
- "数据质量": round(80 + online_ratio * 15, 2),
- }
- default_weights = {
- "安全性": 0.3,
- "可靠性": 0.2,
- "经济性": 0.15,
- "管理合规": 0.2,
- "数据质量": 0.15,
- }
- total_score = round(
- sum(dimension_scores[key] * default_weights[key] for key in dimension_scores),
- 2,
- )
- grade = _grade(total_score)
- recommendations = []
- if high_defects:
- recommendations.append("优先处置高风险缺陷并完成复核闭环。")
- if online_ratio < 0.95:
- recommendations.append("核查离线传感器通讯与供电状态,提高数据连续性。")
- if open_orders:
- recommendations.append("压降未闭环工单数量,重点关注逾期和超时任务。")
- if not recommendations:
- recommendations.append("维持当前通防业务管控状态,继续按周期复评。")
- run = evaluation_repo.create_run(
- db,
- {
- "mine_id": mine.id,
- "run_no": _run_no(),
- "period_start": payload.period_start,
- "period_end": payload.period_end,
- "status": "completed",
- "total_score": total_score,
- "grade": grade,
- "summary": (
- f"{mine.name}通防业务综合得分 {total_score},等级 {grade}。"
- f"当前高风险缺陷 {high_defects} 项,传感器在线率 {online_ratio:.1%}。"
- ),
- "recommendations": recommendations,
- "weight_snapshot": default_weights,
- "input_snapshot": payload.context,
- "model_output": {
- "dimension_scores": dimension_scores,
- "monitoring": monitoring,
- "defects": defects,
- "work_orders": work_orders,
- },
- "started_at": datetime.now(timezone.utc),
- "finished_at": datetime.now(timezone.utc),
- "created_by": payload.requested_by,
- },
- )
- indicators = evaluation_repo.list_indicators(db, mine_id=mine.id)
- if indicators:
- for indicator in indicators:
- score = dimension_scores.get(indicator.dimension, 80)
- weight = indicator.weight if indicator.weight else default_weights.get(indicator.dimension, 0)
- evaluation_repo.create_score(
- db,
- {
- "run_id": run.id,
- "indicator_id": indicator.id,
- "raw_value": score,
- "score": score,
- "weighted_score": round(score * weight, 2),
- "weight": weight,
- "level": _grade(score),
- "evidence": "根据监测在线率、缺陷数量、工单闭环和业务基础数据综合计算。",
- "metadata_json": {},
- },
- )
- return run
|