|
@@ -26,6 +26,10 @@
|
|
|
results = reviewer.review_standards(standards_list)
|
|
results = reviewer.review_standards(standards_list)
|
|
|
"""
|
|
"""
|
|
|
import asyncio
|
|
import asyncio
|
|
|
|
|
+import json
|
|
|
|
|
+import os
|
|
|
|
|
+import threading
|
|
|
|
|
+from datetime import datetime
|
|
|
from typing import List, Dict, Any, Optional
|
|
from typing import List, Dict, Any, Optional
|
|
|
from dataclasses import dataclass, asdict
|
|
from dataclasses import dataclass, asdict
|
|
|
|
|
|
|
@@ -67,13 +71,14 @@ class StandardTimelinessReviewer:
|
|
|
对标准列表进行时效性审查。
|
|
对标准列表进行时效性审查。
|
|
|
"""
|
|
"""
|
|
|
|
|
|
|
|
- def __init__(self, db_pool=None, standard_service: Optional[StandardMatchingService] = None):
|
|
|
|
|
|
|
+ def __init__(self, db_pool=None, standard_service: Optional[StandardMatchingService] = None, callback_task_id: Optional[str] = None):
|
|
|
"""
|
|
"""
|
|
|
初始化审查器
|
|
初始化审查器
|
|
|
|
|
|
|
|
Args:
|
|
Args:
|
|
|
db_pool: 数据库连接池,用于初始化 StandardMatchingService(如未提供standard_service则必填)
|
|
db_pool: 数据库连接池,用于初始化 StandardMatchingService(如未提供standard_service则必填)
|
|
|
standard_service: 已初始化的 StandardMatchingService 实例(优先级高于 db_pool)
|
|
standard_service: 已初始化的 StandardMatchingService 实例(优先级高于 db_pool)
|
|
|
|
|
+ callback_task_id: 回调任务ID,用于持久化判定结果
|
|
|
|
|
|
|
|
Raises:
|
|
Raises:
|
|
|
RuntimeError: 当db_pool和standard_service都为None时抛出异常
|
|
RuntimeError: 当db_pool和standard_service都为None时抛出异常
|
|
@@ -86,6 +91,8 @@ class StandardTimelinessReviewer:
|
|
|
self.db_pool = db_pool
|
|
self.db_pool = db_pool
|
|
|
self._service = standard_service
|
|
self._service = standard_service
|
|
|
self._own_service = False # 标记是否由本实例创建 service
|
|
self._own_service = False # 标记是否由本实例创建 service
|
|
|
|
|
+ self.callback_task_id = callback_task_id
|
|
|
|
|
+ self._log_lock = threading.Lock()
|
|
|
|
|
|
|
|
async def __aenter__(self):
|
|
async def __aenter__(self):
|
|
|
"""异步上下文管理器入口"""
|
|
"""异步上下文管理器入口"""
|
|
@@ -102,6 +109,38 @@ class StandardTimelinessReviewer:
|
|
|
await self._service.close()
|
|
await self._service.close()
|
|
|
return False
|
|
return False
|
|
|
|
|
|
|
|
|
|
+ def _log_determination_results(self, review_results: List["TimelinessReviewResult"]) -> None:
|
|
|
|
|
+ """将时效性判定结果持久化到JSON文件,不影响主逻辑"""
|
|
|
|
|
+ if not self.callback_task_id:
|
|
|
|
|
+ return
|
|
|
|
|
+ try:
|
|
|
|
|
+ with self._log_lock:
|
|
|
|
|
+ log_dir = os.path.join("temp", "construction_review", "timeliness_result")
|
|
|
|
|
+ os.makedirs(log_dir, exist_ok=True)
|
|
|
|
|
+ log_path = os.path.join(log_dir, f"{self.callback_task_id}.json")
|
|
|
|
|
+
|
|
|
|
|
+ records = []
|
|
|
|
|
+ if os.path.exists(log_path):
|
|
|
|
|
+ try:
|
|
|
|
|
+ with open(log_path, "r", encoding="utf-8") as f:
|
|
|
|
|
+ records = json.load(f)
|
|
|
|
|
+ if not isinstance(records, list):
|
|
|
|
|
+ records = []
|
|
|
|
|
+ except Exception:
|
|
|
|
|
+ records = []
|
|
|
|
|
+
|
|
|
|
|
+ for result in review_results:
|
|
|
|
|
+ records.append({
|
|
|
|
|
+ "timestamp": datetime.now().isoformat(),
|
|
|
|
|
+ "callback_task_id": self.callback_task_id,
|
|
|
|
|
+ **result.to_dict()
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ with open(log_path, "w", encoding="utf-8") as f:
|
|
|
|
|
+ json.dump(records, f, ensure_ascii=False, indent=2)
|
|
|
|
|
+ except Exception as e:
|
|
|
|
|
+ logger.warning(f"记录时效性判定结果失败: {e}")
|
|
|
|
|
+
|
|
|
def review_standards(self, standards: List[Dict[str, str]]) -> List[TimelinessReviewResult]:
|
|
def review_standards(self, standards: List[Dict[str, str]]) -> List[TimelinessReviewResult]:
|
|
|
"""
|
|
"""
|
|
|
审查标准列表的时效性
|
|
审查标准列表的时效性
|
|
@@ -128,6 +167,7 @@ class StandardTimelinessReviewer:
|
|
|
review_result = self._convert_match_to_review_result(match_result)
|
|
review_result = self._convert_match_to_review_result(match_result)
|
|
|
review_results.append(review_result)
|
|
review_results.append(review_result)
|
|
|
|
|
|
|
|
|
|
+ self._log_determination_results(review_results)
|
|
|
return review_results
|
|
return review_results
|
|
|
|
|
|
|
|
def review_single(self, standard_name: str, standard_number: str, seq_no: int = 1) -> Optional[TimelinessReviewResult]:
|
|
def review_single(self, standard_name: str, standard_number: str, seq_no: int = 1) -> Optional[TimelinessReviewResult]:
|
|
@@ -150,7 +190,9 @@ class StandardTimelinessReviewer:
|
|
|
# 如果 match 返回 None(文件名为空),则返回 None
|
|
# 如果 match 返回 None(文件名为空),则返回 None
|
|
|
if match_result is None:
|
|
if match_result is None:
|
|
|
return None
|
|
return None
|
|
|
- return self._convert_match_to_review_result(match_result)
|
|
|
|
|
|
|
+ review_result = self._convert_match_to_review_result(match_result)
|
|
|
|
|
+ self._log_determination_results([review_result])
|
|
|
|
|
+ return review_result
|
|
|
|
|
|
|
|
def _convert_match_to_review_result(self, match_result: StandardMatchResult) -> TimelinessReviewResult:
|
|
def _convert_match_to_review_result(self, match_result: StandardMatchResult) -> TimelinessReviewResult:
|
|
|
"""
|
|
"""
|