From 26613676f88b1cd4a40efc0eafa1473397d0f6f6 Mon Sep 17 00:00:00 2001 From: chenjw28 <792430652@qq.com> Date: Mon, 25 May 2026 18:35:33 +0800 Subject: [PATCH] x --- src/api/routes.py | 634 +++------------------------------------------- 1 file changed, 31 insertions(+), 603 deletions(-) diff --git a/src/api/routes.py b/src/api/routes.py index 62372ae..613ca44 100644 --- a/src/api/routes.py +++ b/src/api/routes.py @@ -7,22 +7,14 @@ import os from pathlib import Path from models.schemas import ProcessingStatus, create_task_info -from core.stp_parser import STPParser -from core.geometry_analyzer import GeometryAnalyzer from utils.file_handler import FileHandler -from utils.html_generator import HTMLGenerator from services.storage_integration_rustfs import StorageIntegrationService from services.redis_task_manager import redis_task_manager from services.processing_service import processing_service -from services.llm_service import llm_service from services.task_query_service import TaskQueryService from database.database import get_db_session from utils.logger import get_logger from sqlalchemy.ext.asyncio import AsyncSession -from core.mold_generator import MoldCavityGenerator -from core.aluminum_foam_mold import AluminumFoamMoldGenerator -from core.mold_quality_inspector import AluminumFoamMoldQualityInspector -from core.mesh_generator import MeshGenerator from core.cavity_layout_optimizer import CavityLayoutOptimizer from core.mold_system_designer import MoldSystemDesigner from core.side_action_designer import SideActionDesigner @@ -36,16 +28,7 @@ logger = get_logger(__name__) router = APIRouter() -stp_parser = STPParser() -geometry_analyzer = GeometryAnalyzer() file_handler = FileHandler() -html_generator = HTMLGenerator() -mold_generator = MoldCavityGenerator(shrinkage_rate=0.005) -# 铝泡沫模具生成器 -aluminum_foam_generator = AluminumFoamMoldGenerator(shrinkage_rate=0.015, draft_angle=3.0) -# 铝泡沫模具质量检测器 -mold_quality_inspector = AluminumFoamMoldQualityInspector() -mesh_generator = MeshGenerator(quality="medium") cavity_layout_optimizer = CavityLayoutOptimizer() mold_system_designer = MoldSystemDesigner() side_action_designer = SideActionDesigner() @@ -56,8 +39,6 @@ edm_designer = EDMElectrodeDesigner() machining_simulator = MachiningSimulator() cad_exporter = CADExporter() -tasks = {} - @router.get("/health") @router.post("/health") @@ -120,15 +101,15 @@ async def upload_stp( upload_time=str(datetime.now()) ) await redis_task_manager.set_task(task_id, task_info) - tasks[task_id] = task_info # 后台处理走统一编排服务,避免请求会话在后台失效 + process_params = {"material": material} background_tasks.add_task( processing_service.process_file_with_storage, task_id, file_path, stp_file.id, - material, + process_params, ) logger.info(f"[UPLOAD] 后台处理已调度: task_id={task_id}") @@ -158,8 +139,6 @@ async def get_status(task_id: str, db_session: AsyncSession = Depends(get_db_ses try: task_view = await TaskQueryService.get_task_view(db_session, task_id) if task_view is None: - if task_id in tasks: - return tasks[task_id] raise HTTPException(404, "任务不存在") return task_view except HTTPException: @@ -178,7 +157,6 @@ async def debug_tasks(): "total_tasks": len(all_tasks), "tasks": all_tasks, "redis_connected": redis_task_manager.is_connected, - "memory_fallback_tasks": len(tasks), } @@ -259,48 +237,6 @@ async def result_page(request: Request, task_id: str, db_session: AsyncSession = }) -async def process_file_with_storage( - task_id: str, - file_path: str, - stp_file_id: int, - db_session: AsyncSession, - material: str = "ABS" -): - """处理文件的后台任务""" - - storage_service = StorageIntegrationService() - - try: - logger.info(f"开始处理文件并生成模具型腔: {file_path}") - - # 设置处理超时(5分钟) - import asyncio - timeout_seconds = 300 # 5分钟 - - async def process_with_timeout(): - # 处理逻辑将在下面添加 - pass - - # 使用超时保护 - try: - await asyncio.wait_for(process_file_core(storage_service, task_id, file_path, stp_file_id, db_session, material), timeout_seconds) - except asyncio.TimeoutError: - logger.error(f"处理超时: {task_id}") - raise Exception(f"处理超时,超过{timeout_seconds}秒未完成") - - except Exception as e: - logger.error(f"模具型腔生成失败: {e}") - - await storage_service.update_stp_file_status(db_session, stp_file_id, "failed") - await storage_service.update_task_status( - db_session, task_id, "failed", error_message=str(e) - ) - - tasks[task_id]["status"] = ProcessingStatus.FAILED - tasks[task_id]["error"] = str(e) - tasks[task_id]["completed_at"] = str(datetime.now()) - - # ==================== P3 新增 API ==================== @router.post("/optimize-layout") @@ -417,10 +353,13 @@ async def ai_parting_surface_detect( body = await request.json() task_id = body.get("task_id") - if not task_id or task_id not in tasks: + if not task_id: + raise HTTPException(404, "缺少 task_id") + + task_data = await redis_task_manager.get_task(task_id) + if not task_data: raise HTTPException(404, "任务不存在") - task_data = tasks[task_id] geometry_data = task_data.get("geometry_data") if not geometry_data: raise HTTPException(400, "该任务尚未完成几何分析") @@ -444,10 +383,13 @@ async def detect_undercuts( parting_direction = body.get("parting_direction", [0, 0, 1]) mold_size = body.get("mold_size", {"length": 300, "width": 300, "height": 200}) - if not task_id or task_id not in tasks: + if not task_id: + raise HTTPException(404, "缺少 task_id") + + task_data = await redis_task_manager.get_task(task_id) + if not task_data: raise HTTPException(404, "任务不存在") - task_data = tasks[task_id] geometry_data = task_data.get("geometry_data") if not geometry_data: raise HTTPException(400, "该任务尚未完成几何分析") @@ -570,16 +512,29 @@ async def export_mold_results( task_id = body.get("task_id") formats = body.get("formats", ["step", "stl"]) components = body.get("components", ["cavity", "core"]) + scheme_id = body.get("scheme_id") - if not task_id or task_id not in tasks: - raise HTTPException(404, "任务不存在") + if not task_id: + raise HTTPException(404, "缺少 task_id") - task_data = tasks[task_id] - cavity_shapes = task_data.get("cavity_shapes") + cavity_shapes = processing_service.get_export_shapes(task_id, scheme_id=scheme_id) if not cavity_shapes: - raise HTTPException(400, "该任务尚未完成模具生成或形状数据不可用") + task_data = await redis_task_manager.get_task(task_id) + if not task_data: + raise HTTPException(404, "任务不存在") + filename = task_data.get("filename", f"mold_{task_id}") + raise HTTPException( + 400, + f"该任务的 OCC 形状数据已过期(仅保留 STEP 导出文件)," + f"请通过历史页面的下载链接获取已导出的 STEP 文件", + ) - base_filename = Path(task_data.get("filename", f"mold_{task_id}")).stem + task_data = await redis_task_manager.get_task(task_id) + base_filename = ( + Path(task_data.get("filename", f"mold_{task_id}")).stem + if task_data + else f"mold_{task_id}" + ) result = cad_exporter.export_mold_results( cavity_data=cavity_shapes, @@ -636,531 +591,4 @@ async def get_export_recommendations( return {"status": "success", "data": result} -async def _save_analysis_metrics(session, stp_file_id, analysis_result): - """保存分析指标到数据库""" - from models.database import AnalysisMetrics - - quality_metrics = analysis_result.get("quality_metrics", {}) - analysis_summary = analysis_result.get("analysis_summary", "") - - # 创建分析指标记录 - metrics = AnalysisMetrics( - stp_file_id=stp_file_id, - volume_utilization=quality_metrics.get("volume_utilization", 0), - topology_complexity=quality_metrics.get("topology_complexity", 0), - wall_uniformity=quality_metrics.get("wall_uniformity", 0), - analysis_summary=analysis_summary - ) - - session.add(metrics) - await session.commit() - logger.info(f"分析指标保存成功: {metrics.id}") - -async def _save_verification_metrics(session, stp_file_id, verification_result): - """保存验证指标到数据库""" - from models.database import AnalysisMetrics - from sqlalchemy import select - - # 查找现有的分析指标记录 - result = await session.execute( - select(AnalysisMetrics).where(AnalysisMetrics.stp_file_id == stp_file_id) - ) - metrics = result.scalar_one_or_none() - - if metrics: - # 更新现有记录 - metrics.verification_status = verification_result.get("status", "unknown") - comparison = verification_result.get("comparison", {}) - volume_comparison = comparison.get("volume", {}) - area_comparison = comparison.get("surface_area", {}) - - metrics.verification_volume_diff = volume_comparison.get("difference_percent", 0) - metrics.verification_area_diff = area_comparison.get("difference_percent", 0) - metrics.verification_details = verification_result - else: - # 创建新记录 - comparison = verification_result.get("comparison", {}) - volume_comparison = comparison.get("volume", {}) - area_comparison = comparison.get("surface_area", {}) - - metrics = AnalysisMetrics( - stp_file_id=stp_file_id, - verification_status=verification_result.get("status", "unknown"), - verification_volume_diff=volume_comparison.get("difference_percent", 0), - verification_area_diff=area_comparison.get("difference_percent", 0), - verification_details=verification_result - ) - session.add(metrics) - - await session.commit() - logger.info(f"验证指标保存成功: stp_file_id={stp_file_id}") - - -async def process_file_core( - storage_service: StorageIntegrationService, - task_id: str, - file_path: str, - stp_file_id: int, - db_session: AsyncSession, - material: str = "ABS" -): - """核心处理逻辑""" - - try: - logger.info(f"开始处理文件并生成模具型腔: {file_path}") - - # 更新任务状态 - await storage_service.update_task_status( - db_session, task_id, "processing", 20, "解析STP文件" - ) - - # 1. 解析STP文件 - await storage_service.update_task_status( - db_session, task_id, "processing", 20, "解析STP文件" - ) - - # 使用STPParser类进行真实解析 - shape = stp_parser.load_step_file(Path(file_path)) - geometry_data = stp_parser.analyze_geometry(shape) - - # 2. 生成网格数据并持久化(详细 JSON 存 RustFS,摘要写 PostgreSQL) - await storage_service.update_task_status( - db_session, task_id, "processing", 30, "生成网格数据" - ) - - mesh_result = None - mesh_json = None - try: - mesh_result = mesh_generator.generate_mesh_from_shape(shape) - - # mesh_generator 返回: vertices, faces, points, normals, point_count, vertex_count, face_count - vertices = mesh_result.get("vertices", []) - faces = mesh_result.get("faces", []) - points = mesh_result.get("points", []) - normals = mesh_result.get("normals", []) - point_count = mesh_result.get("point_count", 0) - vertex_count = mesh_result.get("vertex_count", 0) - face_count = mesh_result.get("face_count", 0) - - if vertices and faces: - # 使用已计算的几何边界框,避免重复计算 - bbox = geometry_data.get("bounding_box", {}) - - mesh_json = { - "metadata": { - "file_name": Path(file_path).name, - "generated_at": datetime.now().isoformat(), - "quality": "medium", - "vertex_count": vertex_count, - "face_count": face_count, - "point_count": point_count, - }, - "mesh": { - "vertices": vertices, - "faces": faces, - }, - "pointcloud": { - "points": points, - "normals": normals, - "count": point_count - }, - "bounding_box": bbox, - } - - await storage_service.save_mesh_data( - db_session, - stp_file_id=stp_file_id, - mesh_json=mesh_json, - quality="medium", - ) - # 将简要网格摘要写入内存任务,便于前端展示汇总信息 - tasks[task_id]["mesh_summary"] = { - "vertex_count": vertex_count, - "face_count": face_count, - "point_count": point_count, - "quality": "medium", - } - except Exception as mesh_err: - # 网格失败不影响整体流程,只记录日志 - logger.warning(f"网格生成或保存失败,不影响主流程: {mesh_err}") - - # 3. 生成模具型腔(使用真实的 MoldCavityGenerator) - await storage_service.update_task_status( - db_session, task_id, "processing", 40, "生成模具型腔" - ) - - # 材料属性(需在型腔生成前定义) - material_properties = { - "ABS": {"density": 1.05, "shrinkage": 0.005, "name": "ABS"}, - "PP": {"density": 0.90, "shrinkage": 0.016, "name": "PP"}, - "PE": {"density": 0.95, "shrinkage": 0.020, "name": "PE"}, - "PC": {"density": 1.20, "shrinkage": 0.007, "name": "PC"}, - "PA": {"density": 1.14, "shrinkage": 0.010, "name": "PA"}, - "POM": {"density": 1.41, "shrinkage": 0.020, "name": "POM"}, - "PMMA": {"density": 1.18, "shrinkage": 0.005, "name": "PMMA"}, - "PBT": {"density": 1.31, "shrinkage": 0.015, "name": "PBT"}, - "AlSi10Mg": {"density": 0.45, "shrinkage": 0.015, "name": "AlSi10Mg", "is_foam": True}, - "AlSi12": {"density": 0.50, "shrinkage": 0.012, "name": "AlSi12", "is_foam": True}, - "Pure Al Foam": {"density": 0.35, "shrinkage": 0.020, "name": "Pure Al Foam", "is_foam": True}, - "AlSi7Mg": {"density": 0.40, "shrinkage": 0.018, "name": "AlSi7Mg", "is_foam": True}, - } - - requested_material = material if material in material_properties else "ABS" - selected_material = material_properties.get(requested_material, material_properties["ABS"]) - is_foam_material = selected_material.get("is_foam", False) - - # 使用 MoldCavityGenerator 生成型腔数据 - cavity_mesh_data = None - try: - if shape: - if is_foam_material: - aluminum_foam_generator.set_material(selected_material["name"]) - cavity_result = aluminum_foam_generator.generate_mold_cavities(shape) - cavity_mesh_data = aluminum_foam_generator.generate_detailed_cavity_json(cavity_result) - logger.info(f"使用铝泡沫模具生成器: {selected_material['name']}") - else: - cavity_result = mold_generator.generate_mold_cavities(shape) - cavity_mesh_data = mold_generator.generate_detailed_cavity_json(cavity_result) - logger.info(f"使用普通塑料模具生成器: {selected_material['name']}") - - if cavity_mesh_data: - logger.info(f"型腔网格数据生成完成: {cavity_mesh_data.get('mold_cavities', {}).get('cavity', {}).get('vertex_count', 0)} 顶点") - except Exception as cavity_err: - logger.warning(f"型腔生成失败,使用简化数据: {cavity_err}") - import traceback - traceback.print_exc() - cavity_mesh_data = None - - # 4. 生成详细JSON数据(使用计算值) - await storage_service.update_task_status( - db_session, task_id, "processing", 60, "生成型腔详细数据" - ) - - # 使用模具生成器计算各项参数 - volume_mm3 = geometry_data.get("volume", 0) - surface_area_mm2 = geometry_data.get("surface_area", 0) - bbox = geometry_data.get("bounding_box", {}) - bbox_dims = bbox.get("dimensions", [0, 0, 0]) - - material_density = selected_material["density"] - shrinkage_rate = selected_material["shrinkage"] - - # 计算产品重量 - volume_cm3 = volume_mm3 / 1000 - product_weight_g = volume_cm3 * material_density - - # 计算投影面积(取X、Y方向) - if len(bbox_dims) >= 2: - projected_area_cm2 = (bbox_dims[0] * bbox_dims[1]) / 100 - else: - projected_area_cm2 = 0 - - # 计算最优型腔数量 - # 基于产品重量和投影面积计算 - # 小产品(< 100g)可以多型腔,大产品(> 1000g)通常单型腔 - if product_weight_g < 50: - cavity_count = 8 # 小产品,多型腔 - elif product_weight_g < 100: - cavity_count = 4 # 中小产品 - elif product_weight_g < 300: - cavity_count = 2 # 中等产品 - elif product_weight_g < 1000: - cavity_count = 1 # 较大产品 - else: - cavity_count = 1 # 大产品,单型腔 - - # 根据投影面积调整型腔数量 - # 如果单型腔投影面积超过 400 cm²,减少型腔数量 - single_cavity_area = projected_area_cm2 - if single_cavity_area > 400: - cavity_count = 1 - elif single_cavity_area > 200 and cavity_count > 2: - cavity_count = 2 - - # 计算总投影面积(包括流道系统) - # 流道系统约占型腔投影面积的 15-25% - runner_ratio = 0.20 - total_projected_area = single_cavity_area * cavity_count * (1 + runner_ratio) - - # 计算夹紧力(总投影面积 × 注塑压力 / 1000 吨) - # 注塑压力根据材料选择:ABS 约 600-800 kg/cm² - injection_pressure = 700 # kg/cm² - clamping_force_ton = int(total_projected_area * injection_pressure / 1000) - - # 确保夹紧力在合理范围内 - clamping_force_ton = max(50, min(clamping_force_ton, 3000)) - - # 计算壁厚范围 - if surface_area_mm2 > 0 and volume_mm3 > 0: - avg_thickness_mm = (volume_mm3 / surface_area_mm2) * 0.6 - wall_thickness_min = avg_thickness_mm * 0.7 - wall_thickness_max = avg_thickness_mm * 1.3 - else: - avg_thickness_mm = 2.5 - wall_thickness_min = 2.0 - wall_thickness_max = 3.0 - - # 计算复杂度评分 - if surface_area_mm2 > 0 and volume_mm3 > 0: - complexity_score = min((avg_thickness_mm / 5.0), 1.0) - else: - complexity_score = 0.5 - - # 计算模具尺寸(基于型腔布局) - # 单型腔:产品尺寸 + 边距 - # 多型腔:需要考虑型腔排列 - cavity_spacing = 30 # 型腔间距 mm - edge_margin = 50 # 边缘余量 mm - - if cavity_count == 1: - mold_length = max(bbox_dims[0] if len(bbox_dims) > 0 else 120, 120) + 2 * edge_margin - mold_width = max(bbox_dims[1] if len(bbox_dims) > 1 else 100, 100) + 2 * edge_margin - elif cavity_count == 2: - # 2型腔:并排排列 - mold_length = 2 * max(bbox_dims[0] if len(bbox_dims) > 0 else 120, 120) + cavity_spacing + 2 * edge_margin - mold_width = max(bbox_dims[1] if len(bbox_dims) > 1 else 100, 100) + 2 * edge_margin - elif cavity_count == 4: - # 4型腔:2x2 排列 - mold_length = 2 * max(bbox_dims[0] if len(bbox_dims) > 0 else 120, 120) + cavity_spacing + 2 * edge_margin - mold_width = 2 * max(bbox_dims[1] if len(bbox_dims) > 1 else 100, 100) + cavity_spacing + 2 * edge_margin - else: - # 8型腔:2x4 排列 - mold_length = 4 * max(bbox_dims[0] if len(bbox_dims) > 0 else 120, 120) + 3 * cavity_spacing + 2 * edge_margin - mold_width = 2 * max(bbox_dims[1] if len(bbox_dims) > 1 else 100, 100) + cavity_spacing + 2 * edge_margin - - mold_height = max(bbox_dims[2] if len(bbox_dims) > 2 else 60, 60) + 80 # 包含冷却系统 - - # 计算分型线长度(基于型腔布局) - if len(bbox_dims) >= 2: - single_parting_line = 2 * (bbox_dims[0] + bbox_dims[1]) - parting_line_length = single_parting_line * cavity_count - else: - parting_line_length = 0 - - # 估算成型周期(基于体积和壁厚) - # 周期 = 冷却时间 + 注塑时间 + 开合模时间 - cooling_time = (wall_thickness_max ** 2) * 4 # 冷却时间与壁厚平方成正比 - injection_time = max(3, volume_cm3 / 100) # 注塑时间 - ejection_time = 3 # 顶出时间 - cycle_time = cooling_time + injection_time + ejection_time + 5 # 开合模约5秒 - - # 根据型腔数量调整周期(多型腔需要更长冷却时间) - if cavity_count > 1: - cycle_time = cycle_time * (1 + 0.1 * (cavity_count - 1)) - - detailed_cavity_json = { - "metadata": { - "file_name": Path(file_path).name, - "analysis_date": datetime.now().isoformat(), - "shrinkage_rate": shrinkage_rate, - "draft_angle": 2.0, - "selected_material": selected_material["name"] - }, - "product_analysis": { - "volume": volume_mm3, - "surface_area": surface_area_mm2, - "bounding_box": bbox - }, - "manufacturing_info": { - "recommended_material": selected_material["name"], - "material_density": f"{material_density} g/cm³", - "estimated_clamping_force": f"{clamping_force_ton} 吨", - "estimated_mold_size": { - "length": int(mold_length), - "width": int(mold_width), - "height": int(mold_height) - }, - "mold_material": "铝合金7075" if clamping_force_ton < 200 else "P20钢材", - "mold_hardness": "HB 150-170" if clamping_force_ton < 200 else "HRC 28-32", - "surface_finish": "Ra 0.8 μm", - "parting_line_length": f"{parting_line_length:.2f} mm", - "estimated_cycle_time": f"{int(cycle_time)} 秒", - "injection_pressure": f"{injection_pressure} kg/cm²" - }, - "mold_cavities": { - "cavity_count": cavity_count, - } - } - - # 合并型腔网格数据(如果有) - if cavity_mesh_data and "mold_cavities" in cavity_mesh_data: - mold_cavities = cavity_mesh_data["mold_cavities"] - if "cavity" in mold_cavities: - detailed_cavity_json["mold_cavities"]["cavity"] = mold_cavities["cavity"] - if "core" in mold_cavities: - detailed_cavity_json["mold_cavities"]["core"] = mold_cavities["core"] - if "parting_surface" in mold_cavities: - detailed_cavity_json["mold_cavities"]["parting_surface"] = mold_cavities["parting_surface"] - logger.info(f"型腔网格数据已合并: cavity {mold_cavities.get('cavity', {}).get('vertex_count', 0)} 顶点") - - # 添加型腔关键信息 - detailed_cavity_json["mold_cavities"]["cavity_key_info"] = { - "geometric_characteristics": { - "product_weight": f"{product_weight_g:.2f} g", - "wall_thickness_range": f"{wall_thickness_min:.2f} - {wall_thickness_max:.2f} mm", - "complexity_score": round(complexity_score, 2), - "product_volume": f"{volume_cm3:.2f} cm³", - "projected_area": f"{projected_area_cm2:.2f} cm²" - }, - "quality_considerations": { - "potential_weld_lines": "center" if cavity_count > 1 else "minimal", - "sink_mark_areas": "thick_sections" if wall_thickness_max > 4 else "minimal", - "warpage_risk": "medium" if wall_thickness_max > 5 else "low" - } - } - - # 5. 生成关键信息(模拟) - cavity_key_info = detailed_cavity_json["mold_cavities"]["cavity_key_info"] - - # 6. 保存几何数据到数据库 - await storage_service.update_task_status( - db_session, task_id, "processing", 70, "保存几何数据" - ) - - geometry_record = await storage_service.save_geometry_data( - db_session, - stp_file_id, - geometry_data, - geometry_data.get("analysis_method", "mold_cavity") - ) - - # 7. 保存模具型腔数据 - await storage_service.save_mold_cavity_data( - db_session, - stp_file_id, - detailed_cavity_json - ) - - # 8. 生成HTML可视化(包含型腔信息和点云数据) - await storage_service.update_task_status( - db_session, task_id, "processing", 85, "生成可视化报告" - ) - - # 获取点云数据 - mesh_result 直接返回 points 和 normals - pointcloud_data = None - if mesh_result: - pointcloud_data = { - "points": mesh_result.get("points", []), - "normals": mesh_result.get("normals", []), - "point_count": mesh_result.get("point_count", 0) - } - - html_file_path = html_generator.generate_and_save_visualization( - geometry_data, - Path(file_path).name, - cavity_data=detailed_cavity_json, - pointcloud_data=pointcloud_data - ) - - # 保存HTML文件信息 - html_record = await storage_service.save_html_file( - db_session, - stp_file_id, - Path(html_file_path).name, - html_file_path - ) - - # 9. 分析模具设计 - analysis_result = geometry_analyzer.analyze_mold_design(geometry_data, shape=shape) - - # 9.5 保存完整的分析结果到数据库 - if analysis_result: - await storage_service.save_features_and_recommendations( - db_session, - stp_file_id, - analysis_result.get("detected_features", []), - analysis_result.get("design_recommendations", []) - ) - - # 保存质量指标和分析摘要到数据库 - await _save_analysis_metrics(db_session, stp_file_id, analysis_result) - - # 9.6 更新STP文件的分析摘要字段(用于快速查询) - await storage_service.update_stp_file_analysis_summary( - db_session, - stp_file_id, - volume=volume_mm3, - surface_area=surface_area_mm2, - product_weight=product_weight_g - ) - - # 9.7 FreeCAD 几何验证(可通过配置禁用) - verification_result = None - from config.settings import settings - - if settings.ENABLE_FREECAD_VERIFICATION: - await storage_service.update_task_status( - db_session, task_id, "processing", 90, "FreeCAD几何验证" - ) - - try: - from services.verification_service import GeometryVerificationService - # 使用配置的超时时间 - verification_svc = GeometryVerificationService(timeout=settings.FREECAD_VERIFICATION_TIMEOUT) - verification_result = await verification_svc.verify_stp_file(file_path) - - # 保存验证结果到数据库 - if verification_result and analysis_result: - await _save_verification_metrics( - db_session, - stp_file_id, - verification_result - ) - - logger.info(f"FreeCAD验证完成: {verification_result.get('status', 'unknown') if verification_result else 'failed'}") - except Exception as ve: - logger.warning(f"FreeCAD验证失败(不影响主流程): {ve}") - verification_result = {"status": "error", "error": str(ve)} - else: - logger.info("FreeCAD验证已禁用(设置 ENABLE_FREECAD_VERIFICATION=true 启用)") - verification_result = {"status": "disabled", "reason": "FreeCAD验证已禁用"} - - # 9.8 LLM 增强分析 - llm_report = None - if analysis_result: - side_action_ai = await llm_service.generate_side_action_analysis( - analysis_result, detailed_cavity_json - ) - design_report = await llm_service.generate_design_report( - analysis_result, detailed_cavity_json - ) - llm_report = llm_service.compose_llm_report( - design_report, side_action_ai - ) - - # 10. 完成处理 - await storage_service.update_stp_file_status(db_session, stp_file_id, "completed") - await storage_service.update_task_status( - db_session, task_id, "completed", 100, "模具型腔生成完成" - ) - - # 更新内存任务状态 - tasks[task_id]["geometry_data"] = geometry_data - tasks[task_id]["analysis_result"] = analysis_result - tasks[task_id]["cavity_data"] = detailed_cavity_json - tasks[task_id]["cavity_shapes"] = cavity_result - tasks[task_id]["key_info"] = detailed_cavity_json # 传递完整数据给前端 - tasks[task_id]["html_file"] = f"/html/{Path(html_file_path).name}" # 只使用文件名 - tasks[task_id]["verification"] = verification_result # 添加验证结果 - tasks[task_id]["llm_report"] = llm_report - tasks[task_id]["status"] = ProcessingStatus.COMPLETED - tasks[task_id]["completed_at"] = str(datetime.now()) - - # 调试日志 - logger.info(f"模具型腔生成完成: {task_id}") - logger.info(f"key_info metadata: {detailed_cavity_json.get('metadata', {})}") - logger.info(f"key_info manufacturing_info: {detailed_cavity_json.get('manufacturing_info', {})}") - logger.info(f"key_info geometric_characteristics: {detailed_cavity_json.get('mold_cavities', {}).get('cavity_key_info', {}).get('geometric_characteristics', {})}") - - except Exception as e: - logger.error(f"模具型腔生成失败: {e}") - - await storage_service.update_stp_file_status(db_session, stp_file_id, "failed") - await storage_service.update_task_status( - db_session, task_id, "failed", error_message=str(e) - ) - - tasks[task_id]["status"] = ProcessingStatus.FAILED - tasks[task_id]["error"] = str(e) - tasks[task_id]["completed_at"] = str(datetime.now())