review_results.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. """
  2. 审查结果获取接口Mock实现
  3. 模拟风险统计、总结报告和问题条文返回
  4. """
  5. import uuid
  6. import random
  7. from datetime import datetime
  8. from fastapi import APIRouter, HTTPException
  9. from pydantic import BaseModel
  10. from typing import Optional, Dict, Any
  11. from .schemas.error_schemas import ReviewResultsErrors
  12. review_results_router = APIRouter(prefix="/sgsc", tags=["审查结果Mock"])
  13. # 导入文件上传模块的存储
  14. try:
  15. from .file_upload import uploaded_files
  16. except ImportError:
  17. from views.construction_review.file_upload import uploaded_files
  18. class ReviewResultsRequest(BaseModel):
  19. id: str = None
  20. user: str = None
  21. type: str = None # "summary" 或 "issues"
  22. class ReviewResultsResponse(BaseModel):
  23. code: int
  24. data: Dict[str, Any]
  25. def generate_risk_stats():
  26. """生成模拟风险统计"""
  27. return {
  28. "high": random.randint(1, 5),
  29. "medium": random.randint(3, 8),
  30. "low": random.randint(2, 6)
  31. }
  32. def generate_dimension_scores():
  33. """生成模拟四维评分"""
  34. return {
  35. "safety": random.randint(60, 95),
  36. "quality": random.randint(55, 90),
  37. "schedule": random.randint(70, 95),
  38. "cost": random.randint(65, 90)
  39. }
  40. def generate_summary_report(risk_stats):
  41. """生成模拟总结报告"""
  42. total_issues = sum(risk_stats.values())
  43. if risk_stats["high"] > 0:
  44. return f"该施工方案存在{risk_stats['high']}处高风险问题,需重点整改。建议在施工前完善相关技术细节,确保符合规范要求。"
  45. elif total_issues > 5:
  46. return f"该施工方案整体符合规范要求,但存在{total_issues}处中低风险问题,建议优化完善。"
  47. else:
  48. return "该施工方案整体符合规范要求,存在少量细节问题,可正常施工。"
  49. def generate_issues():
  50. """生成模拟问题条文"""
  51. issues = []
  52. # 高风险问题示例
  53. high_risk_issues = [
  54. {
  55. "page": 12,
  56. "chapter": "1.1 路面材料要求",
  57. "original_content": "采用沥青、混凝土作为路面施工材料,未明确标号及来源;施工段落仅标注主线段,未细化具体桩号范围"
  58. },
  59. {
  60. "page": 45,
  61. "chapter": "3.2 模板安装工艺",
  62. "original_content": "模板未按设计要求进行预压,直接浇筑混凝土;预压观测记录采用文字描述,未体现观测点布置及沉降数据"
  63. }
  64. ]
  65. # 中风险问题示例
  66. medium_risk_issues = [
  67. {
  68. "page": 28,
  69. "chapter": "2.3 施工机械配置",
  70. "original_content": "施工机械清单未包含备用设备,未制定设备故障应急预案"
  71. },
  72. {
  73. "page": 67,
  74. "chapter": "4.1 质量保证措施",
  75. "original_content": "质量检测频次未明确具体标准,检验方法描述不够详细"
  76. }
  77. ]
  78. # 生成高风险问题
  79. for i, issue_data in enumerate(high_risk_issues):
  80. issue_id = f"ISSUE-HL-{datetime.now().strftime('%Y%m%d')}-{i+1:03d}"
  81. reviews = [
  82. {
  83. "check_item": "强制性标准符合性检查",
  84. "check_result": "不符合",
  85. "risk_info": {"risk_level": "high"},
  86. "suggestion": {
  87. "suggestion_type": "professional",
  88. "suggestion_content": "按相关规范要求,明确材料规格和施工参数,确保符合技术标准要求",
  89. "verification_standard": "整改后需提供技术规格书,由项目总工签字确认"
  90. }
  91. },
  92. {
  93. "check_item": "条文完整性检查",
  94. "check_result": "不符合",
  95. "risk_info": {"risk_level": "low"},
  96. "suggestion": {
  97. "suggestion_type": "completeness",
  98. "suggestion_content": "补充详细的施工范围描述,与施工平面布置图桩号标注一致",
  99. "verification_standard": "参考施工方案编制导则相关条款"
  100. }
  101. }
  102. ]
  103. issues.append({
  104. "issue_id": issue_id,
  105. "metadata": issue_data,
  106. "risk_summary": {
  107. "max_risk_level": "high",
  108. "risk_count": {"high": 1, "medium": 1, "low": 1},
  109. "key_risk_reminder": "高风险点:技术参数缺失,需24小时内整改"
  110. },
  111. "review_lists": reviews
  112. })
  113. # 生成中风险问题
  114. for i, issue_data in enumerate(medium_risk_issues):
  115. issue_id = f"ISSUE-ML-{datetime.now().strftime('%Y%m%d')}-{i+1:03d}"
  116. reviews = [
  117. {
  118. "check_item": "规范性检查",
  119. "check_result": "不符合",
  120. "risk_info": {"risk_level": "medium"},
  121. "suggestion": {
  122. "suggestion_type": "normative",
  123. "suggestion_content": "完善应急预案制定,明确设备故障处理流程和备用资源配置",
  124. "verification_standard": "参考《施工组织设计规范》相关要求"
  125. }
  126. }
  127. ]
  128. issues.append({
  129. "issue_id": issue_id,
  130. "metadata": issue_data,
  131. "risk_summary": {
  132. "max_risk_level": "medium",
  133. "risk_count": {"high": 0, "medium": 1, "low": 0},
  134. "key_risk_reminder": "中风险点:管理措施不完善,需在施工前完善"
  135. },
  136. "review_lists": reviews
  137. })
  138. return issues
  139. @review_results_router.post("/review_results", response_model=ReviewResultsResponse)
  140. async def review_results(request: ReviewResultsRequest):
  141. """
  142. Mock审查结果获取接口
  143. """
  144. try:
  145. # 验证参数
  146. if not request.type or request.type not in ["summary", "issues"]:
  147. raise ReviewResultsErrors.invalid_type()
  148. if not request.id or not isinstance(request.id, str):
  149. raise ReviewResultsErrors.missing_param_id()
  150. # 验证UUID格式(简单检查)
  151. if len(request.id) != 36 or request.id.count('-') != 4:
  152. raise ReviewResultsErrors.invalid_id_format()
  153. # 验证用户标识(应该是指定用户如user-001)
  154. valid_users = {"user-001", "user-002", "user-003"} # 可以配置化
  155. if not request.user or request.user not in valid_users:
  156. raise ReviewResultsErrors.invalid_user()
  157. # 检查文档是否存在
  158. if request.id not in uploaded_files:
  159. raise ReviewResultsErrors.task_not_found()
  160. # 验证用户权限
  161. file_info = uploaded_files[request.id]
  162. if file_info.get("user") != request.user:
  163. raise ReviewResultsErrors.invalid_user()
  164. # 检查任务状态(模拟:只有完成的任务才能查看结果)
  165. callback_task_id = file_info.get("callback_task_id")
  166. if callback_task_id in uploaded_files:
  167. task_info = uploaded_files[callback_task_id]
  168. if task_info.get("review_task_status") != "completed":
  169. raise ReviewResultsErrors.no_review_results()
  170. # 根据类型返回结果
  171. if request.type == "summary":
  172. risk_stats = generate_risk_stats()
  173. dimension_scores = generate_dimension_scores()
  174. summary_report = generate_summary_report(risk_stats)
  175. return ReviewResultsResponse(
  176. code=200,
  177. data={
  178. "risk_stats": risk_stats,
  179. "dimension_scores": dimension_scores,
  180. "summary_report": summary_report,
  181. "multidimensional_report": summary_report + "建议重点关注安全管理和质量控制措施的落实。"
  182. }
  183. )
  184. else: # issues
  185. issues = generate_issues()
  186. return ReviewResultsResponse(
  187. code=200,
  188. data={
  189. "issues": issues
  190. }
  191. )
  192. except HTTPException:
  193. raise
  194. except Exception as e:
  195. raise ReviewResultsErrors.server_error(e)