From 1525f6fc0b73468467942fdc76514ac252639ef4 Mon Sep 17 00:00:00 2001 From: cjw <792430652@qq.com> Date: Mon, 16 Feb 2026 18:33:17 +0800 Subject: [PATCH] deving --- src/api/routes.py | 313 +------------- src/models/database.py | 31 -- src/services/storage_integration_rustfs.py | 77 +--- templates/result.html | 2 +- templates/snapshot.html | 451 --------------------- 5 files changed, 25 insertions(+), 849 deletions(-) delete mode 100644 templates/snapshot.html diff --git a/src/api/routes.py b/src/api/routes.py index 0662c8c..946c3cc 100644 --- a/src/api/routes.py +++ b/src/api/routes.py @@ -15,7 +15,6 @@ 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 datetime import datetime logger = get_logger(__name__) @@ -117,56 +116,14 @@ async def upload_stp( @router.get("/status/{task_id}") @router.post("/status/{task_id}") -async def get_status(task_id: str, db_session: AsyncSession = Depends(get_db_session)): +async def get_status(task_id: str): """获取任务状态""" - # 先从内存查找 - if task_id in tasks: - task = tasks[task_id] - logger.info(f"返回任务状态(内存): {task_id} - {task['status']}") - return task - - # 内存中没有,从数据库查找 - from sqlalchemy import select - from models.database import ProcessingTask, STPFile - - result = await db_session.execute( - select(ProcessingTask, STPFile) - .join(STPFile, ProcessingTask.stp_file_id == STPFile.id) - .where(ProcessingTask.task_id == task_id) - ) - - task_record = result.first() - if not task_record: + if task_id not in tasks: raise HTTPException(404, "任务不存在") - task, stp_file = task_record - task_data = { - "task_id": task.task_id, - "filename": stp_file.original_filename if stp_file else "", - "file_size": stp_file.file_size if stp_file else 0, - "status": task.status, - "progress": task.progress, - "current_step": task.current_step, - "upload_time": task.created_time.astimezone().strftime('%Y-%m-%d %H:%M:%S') if task.created_time else "", - "completed_at": task.completed_time.astimezone().strftime('%Y-%m-%d %H:%M:%S') if task.completed_time else "", - "error": task.error_message if task.error_message else "" - } - - # 尝试获取快照中的 key_info - from models.database import AnalysisResultSnapshot - snapshot_result = await db_session.execute( - select(AnalysisResultSnapshot) - .where(AnalysisResultSnapshot.stp_file_id == stp_file.id) - .order_by(AnalysisResultSnapshot.created_time.desc()) - .limit(1) - ) - snapshot = snapshot_result.scalar_one_or_none() - - if snapshot and snapshot.key_info: - task_data["key_info"] = snapshot.key_info - - logger.info(f"返回任务状态(数据库): {task_id} - {task['status']}") - return task_data + task = tasks[task_id] + logger.info(f"返回任务状态: {task_id} - {task['status']}") + return task @router.get("/debug/tasks") @@ -205,7 +162,7 @@ async def get_file_history(db_session: AsyncSession = Depends(get_db_session)): file_groups[filename].append({ "task_id": task.task_id, "filename": filename, - "upload_time": task.created_time.astimezone().strftime('%Y-%m-%d %H:%M:%S') if task.created_time else "", + "upload_time": task.created_time.isoformat() if task.created_time else "", "status": task.status, "file_size": stp_file.file_size }) @@ -260,9 +217,9 @@ async def get_file_records(filename: str, db_session: AsyncSession = Depends(get "task_id": task.task_id, "filename": stp_file.original_filename, "file_size": stp_file.file_size, - "upload_time": task.created_time.astimezone().strftime('%Y-%m-%d %H:%M:%S') if task.created_time else "", + "upload_time": task.created_time.isoformat() if task.created_time else "", "status": task.status, - "completed_at": task.completed_time.astimezone().strftime('%Y-%m-%d %H:%M:%S') if task.completed_time else "" + "completed_at": task.completed_time.isoformat() if task.completed_time else "" }) # 按上传时间排序(最新的在前) @@ -287,92 +244,28 @@ async def history_page(request: Request): }) -@router.get("/api/snapshots/{stp_file_id}") -@router.post("/api/snapshots/{stp_file_id}") -async def get_analysis_snapshots(stp_file_id: int, db_session: AsyncSession = Depends(get_db_session)): - """获取指定STP文件的分析结果快照列表""" - storage_service = StorageIntegrationService() - - try: - snapshots = await storage_service.get_analysis_result_snapshots(db_session, stp_file_id) - - # 构建返回数据 - snapshot_list = [] - for snapshot in snapshots: - snapshot_list.append({ - "id": snapshot.id, - "snapshot_name": snapshot.snapshot_name, - "created_time": snapshot.created_time.isoformat() if snapshot.created_time else "", - "analysis_time": snapshot.analysis_time.isoformat() if snapshot.analysis_time else "", - "task_data": snapshot.task_data - }) - - return { - "stp_file_id": stp_file_id, - "total_snapshots": len(snapshot_list), - "snapshots": snapshot_list - } - - except Exception as e: - logger.error(f"获取分析结果快照失败: {e}") - raise HTTPException(500, f"获取快照失败: {str(e)}") - - -@router.get("/api/snapshot/{snapshot_id}") -@router.post("/api/snapshot/{snapshot_id}") -async def get_analysis_snapshot(snapshot_id: int, db_session: AsyncSession = Depends(get_db_session)): - """获取指定分析结果快照的完整数据""" - from sqlalchemy import select - from models.database import AnalysisResultSnapshot - - try: - result = await db_session.execute( - select(AnalysisResultSnapshot).where(AnalysisResultSnapshot.id == snapshot_id) - ) - snapshot = result.scalar_one_or_none() - - if not snapshot: - raise HTTPException(404, "快照不存在") - - return { - "id": snapshot.id, - "snapshot_name": snapshot.snapshot_name, - "stp_file_id": snapshot.stp_file_id, - "created_time": snapshot.created_time.isoformat() if snapshot.created_time else "", - "analysis_time": snapshot.analysis_time.isoformat() if snapshot.analysis_time else "", - "task_data": snapshot.task_data, - "geometry_data": snapshot.geometry_data, - "mold_cavity_data": snapshot.mold_cavity_data, - "key_info": snapshot.key_info, - "html_info": snapshot.html_info - } - - except Exception as e: - logger.error(f"获取分析结果快照详情失败: {e}") - raise HTTPException(500, f"获取快照详情失败: {str(e)}") - - @router.get("/result/{task_id}") @router.post("/result/{task_id}") async def result_page(request: Request, task_id: str, db_session: AsyncSession = Depends(get_db_session)): """结果详情页面""" from sqlalchemy import select - from models.database import ProcessingTask, STPFile, GeometryData, MoldCavityData, HTMLFile, AnalysisResultSnapshot - - # 先查询任务记录 - task_result = await db_session.execute( + from models.database import ProcessingTask, STPFile, GeometryData, MoldCavityData, HTMLFile + + # 从数据库查询任务详情 + result = await db_session.execute( select(ProcessingTask, STPFile) .join(STPFile, ProcessingTask.stp_file_id == STPFile.id) .where(ProcessingTask.task_id == task_id) ) - task_record = task_result.first() - + + task_record = result.first() + if not task_record: raise HTTPException(404, "任务不存在") - + task, stp_file = task_record - - # 构建任务详情数据 + + # 构建任务详情数据(先只包含基本数据) task_data = { "task_id": task.task_id, "filename": stp_file.original_filename if stp_file else "", @@ -380,90 +273,11 @@ async def result_page(request: Request, task_id: str, db_session: AsyncSession = "status": task.status, "progress": task.progress, "current_step": task.current_step, - "upload_time": task.created_time.astimezone().strftime('%Y-%m-%d %H:%M:%S') if task.created_time else "", - "completed_at": task.completed_time.astimezone().strftime('%Y-%m-%d %H:%M:%S') if task.completed_time else "", + "created_at": task.created_time.isoformat() if task.created_time else "", + "completed_at": task.completed_time.isoformat() if task.completed_time else "", "error": task.error_message if task.error_message else "" } - - # 尝试从分析结果快照获取数据 - snapshot_result = await db_session.execute( - select(AnalysisResultSnapshot) - .where(AnalysisResultSnapshot.stp_file_id == stp_file.id) - .order_by(AnalysisResultSnapshot.created_time.desc()) - .limit(1) - ) - snapshot = snapshot_result.scalar_one_or_none() - - if snapshot: - # 从快照获取完整的数据 - task_data["geometry_data"] = snapshot.geometry_data if snapshot.geometry_data else None - task_data["key_info"] = snapshot.key_info if snapshot.key_info else None - task_data["mold_cavity_data"] = snapshot.mold_cavity_data if snapshot.mold_cavity_data else None - logger.info(f"从快照加载任务数据: {task_id}") - else: - # 如果没有快照,从各个表分别获取 - result = await db_session.execute( - select(GeometryData, MoldCavityData, HTMLFile) - .outerjoin(MoldCavityData, GeometryData.stp_file_id == MoldCavityData.stp_file_id) - .outerjoin(HTMLFile, GeometryData.stp_file_id == HTMLFile.stp_file_id) - .where(GeometryData.stp_file_id == stp_file.id) - ) - - other_data = result.first() - - if other_data: - geometry_data, mold_cavity_data, html_file = other_data - - # 如果有几何数据,添加到返回结果 - if geometry_data: - task_data["geometry_data"] = { - "volume": geometry_data.volume, - "surface_area": geometry_data.surface_area, - "bounding_box": { - "min": geometry_data.bounding_box_min, - "max": geometry_data.bounding_box_max, - "dimensions": [ - geometry_data.bounding_box_max[0] - geometry_data.bounding_box_min[0] if geometry_data.bounding_box_max and geometry_data.bounding_box_min else 0, - geometry_data.bounding_box_max[1] - geometry_data.bounding_box_min[1] if geometry_data.bounding_box_max and geometry_data.bounding_box_min else 0, - geometry_data.bounding_box_max[2] - geometry_data.bounding_box_min[2] if geometry_data.bounding_box_max and geometry_data.bounding_box_min else 0 - ] - }, - "topology": { - "faces": geometry_data.topology_faces, - "edges": geometry_data.topology_edges, - "vertices": geometry_data.topology_vertices - }, - "center_of_mass": geometry_data.center_of_mass - } - - # 如果有模具型腔数据,添加到返回结果 - if mold_cavity_data: - task_data["key_info"] = { - "metadata": { - "shrinkage_rate": mold_cavity_data.shrinkage_rate, - "draft_angle": mold_cavity_data.draft_angle - }, - "manufacturing_info": { - "mold_material": mold_cavity_data.mold_material, - "estimated_clamping_force": mold_cavity_data.estimated_clamping_force, - "parting_line_length": mold_cavity_data.parting_line_length, - "estimated_cycle_time": mold_cavity_data.estimated_cycle_time, - "manufacturing_tolerance": mold_cavity_data.manufacturing_tolerance - }, - "mold_cavities": { - "cavity_key_info": { - "geometric_characteristics": { - "product_weight": mold_cavity_data.product_weight, - "product_volume": mold_cavity_data.product_volume, - "wall_thickness_range": mold_cavity_data.wall_thickness_range, - "complexity_score": mold_cavity_data.complexity_score - } - } - } - } - - logger.info(f"从各个表加载任务数据: {task_id}") - + from fastapi.templating import Jinja2Templates import os # 简化路径配置,直接使用当前工作目录下的templates文件夹 @@ -638,8 +452,7 @@ async def process_file_core( "mold_hardness": "HB 150-170", "surface_finish": "Ra 0.8 μm", "parting_line_length": f"{parting_line_length:.2f} mm", - "estimated_cycle_time": f"{int(cycle_time)} 秒", - "manufacturing_tolerance": "±0.1 mm" + "estimated_cycle_time": f"{int(cycle_time)} 秒" }, "mold_cavities": { "cavity_count": 1, @@ -656,55 +469,6 @@ async def process_file_core( "warpage_risk": "low" } } - }, - # 添加特征检测数据 - "detected_features": [ - { - "feature_type": "壁厚检测", - "confidence": 0.85, - "location": "整体结构", - "description": f"平均壁厚: {avg_thickness_mm:.2f} mm" - }, - { - "feature_type": "拔模角检测", - "confidence": 0.92, - "location": "主要表面", - "description": "拔模角符合要求" - }, - { - "feature_type": "几何复杂性", - "confidence": 0.78, - "location": "整体结构", - "description": f"复杂度评分: {complexity_score:.2f}" - } - ], - # 添加设计建议数据 - "design_recommendations": [ - { - "rec_type": "壁厚优化", - "priority": "medium", - "description": f"建议优化壁厚均匀性,当前范围: {wall_thickness_min:.2f} - {wall_thickness_max:.2f} mm", - "reason": "提高注塑成型质量" - }, - { - "rec_type": "拔模角", - "priority": "low", - "description": "拔模角符合标准要求", - "reason": "便于脱模" - }, - { - "rec_type": "结构简化", - "priority": "medium", - "description": f"建议简化复杂结构,当前复杂度: {complexity_score:.2f}", - "reason": "降低制造成本" - } - ], - # 添加质量指标数据 - "quality_metrics": { - "volume_utilization": round(complexity_score * 100, 2), - "wall_thickness_uniformity": round((1 - (wall_thickness_max - wall_thickness_min) / avg_thickness_mm) * 100, 2), - "geometric_complexity": round(complexity_score * 10, 2), - "moldability_score": round((complexity_score + 1) * 50, 2) } } @@ -758,39 +522,6 @@ async def process_file_core( db_session, task_id, "completed", 100, "模具型腔生成完成" ) - # 构建完整的分析结果数据 - task_info = tasks[task_id] - - # 构建任务基本信息 - task_data = { - "task_id": task_info["task_id"], - "filename": task_info["filename"], - "file_size": task_info["file_size"], - "status": task_info["status"], - "upload_time": task_info["upload_time"], - "completed_at": str(datetime.now()) - } - - # 保存分析结果快照到数据库 - try: - await storage_service.save_analysis_result_snapshot( - db_session, - stp_file_id, - task_data=task_data, - geometry_data=geometry_data, - mold_cavity_data=detailed_cavity_json, - key_info=detailed_cavity_json, - html_info={ - "filename": Path(html_file_path).name, - "file_path": html_file_path, - "generated_time": str(datetime.now()) - } - ) - logger.info(f"分析结果快照保存成功: {task_id}") - except Exception as e: - logger.error(f"保存分析结果快照失败: {e}") - # 不影响主流程,继续执行 - # 更新内存任务状态 tasks[task_id]["geometry_data"] = geometry_data tasks[task_id]["analysis_result"] = analysis_result diff --git a/src/models/database.py b/src/models/database.py index a327cb0..5eaceac 100644 --- a/src/models/database.py +++ b/src/models/database.py @@ -199,8 +199,6 @@ class MoldCavityData(Base): product_volume = Column(Float, nullable=True) wall_thickness_range = Column(String(50), nullable=True) complexity_score = Column(Float, nullable=True) - estimated_cycle_time = Column(String(50), nullable=True) - manufacturing_tolerance = Column(String(50), nullable=True) # 质量评估 weld_line_risk = Column(String(50), nullable=True) # 熔接痕风险 @@ -328,32 +326,3 @@ class SystemLog(Base): def __repr__(self): return f"" - -class AnalysisResultSnapshot(Base): - """分析结果快照表 - 存储每次分析结果的完整副本""" - __tablename__ = "analysis_result_snapshots" - - id = Column(Integer, primary_key=True, index=True) - stp_file_id = Column(Integer, ForeignKey("stp_files.id"), nullable=False, index=True) - - # 快照标识信息 - snapshot_name = Column(String(255), nullable=False, index=True) # 文件名+日期时间格式 - snapshot_type = Column(String(50), default="complete") # complete, geometry_only, key_info_only - - # 完整分析结果数据 - task_data = Column(JSON, nullable=False) # 任务基本信息 - geometry_data = Column(JSON, nullable=True) # 几何数据 - mold_cavity_data = Column(JSON, nullable=True) # 模具型腔数据 - key_info = Column(JSON, nullable=True) # 关键信息 - html_info = Column(JSON, nullable=True) # HTML文件信息 - - # 时间戳 - created_time = Column(DateTime, default=func.now()) - analysis_time = Column(DateTime, nullable=False) # 原始分析时间 - - # 关联关系 - stp_file = relationship("STPFile") - - def __repr__(self): - return f"" - diff --git a/src/services/storage_integration_rustfs.py b/src/services/storage_integration_rustfs.py index eaa74f5..e327735 100644 --- a/src/services/storage_integration_rustfs.py +++ b/src/services/storage_integration_rustfs.py @@ -3,7 +3,7 @@ from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, update from pathlib import Path -from typing import Optional, Dict, Any, List +from typing import Optional, Dict, Any import json from datetime import datetime @@ -11,7 +11,7 @@ from models.database import ( STPFile, GeometryData, MoldCavityData, HTMLFile, ProcessingTask, User, FeatureDetection, DesignRecommendation, - UserActivity, SystemLog, AnalysisResultSnapshot + UserActivity, SystemLog ) from storage.rustfs_storage import rustfs_manager from utils.logger import get_logger @@ -493,79 +493,6 @@ class StorageIntegrationService: logger.info(f"STP文件及其关联数据已删除: {stp_file_id}") - async def save_analysis_result_snapshot( - self, - session: AsyncSession, - stp_file_id: int, - task_data: Dict[str, Any], - geometry_data: Optional[Dict[str, Any]] = None, - mold_cavity_data: Optional[Dict[str, Any]] = None, - key_info: Optional[Dict[str, Any]] = None, - html_info: Optional[Dict[str, Any]] = None - ) -> AnalysisResultSnapshot: - """保存分析结果快照 - 文件名+日期时间命名方式""" - - # 获取STP文件信息 - stp_file = await session.get(STPFile, stp_file_id) - if not stp_file: - raise ValueError(f"STP文件不存在: {stp_file_id}") - - # 生成快照名称:文件名_YYYYMMDD_HHMMSS - filename = stp_file.original_filename - # 移除文件扩展名 - base_name = Path(filename).stem - # 生成时间戳 - timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") - snapshot_name = f"{base_name}_{timestamp}" - - # 获取分析时间(从任务数据中获取或使用当前时间) - analysis_time_str = task_data.get('created_at') or task_data.get('upload_time') - if analysis_time_str: - analysis_time = datetime.fromisoformat(analysis_time_str.replace('Z', '+00:00')) - else: - analysis_time = datetime.now() - - # 创建快照记录 - snapshot = AnalysisResultSnapshot( - stp_file_id=stp_file_id, - snapshot_name=snapshot_name, - task_data=task_data, - geometry_data=geometry_data, - mold_cavity_data=mold_cavity_data, - key_info=key_info, - html_info=html_info, - analysis_time=analysis_time - ) - - session.add(snapshot) - await session.commit() - await session.refresh(snapshot) - - logger.info(f"分析结果快照保存成功: {snapshot_name} (ID: {snapshot.id})") - return snapshot - - async def get_analysis_result_snapshots( - self, - session: AsyncSession, - stp_file_id: int, - limit: int = 10 - ) -> List[AnalysisResultSnapshot]: - """获取指定STP文件的分析结果快照列表""" - - from sqlalchemy import select - from sqlalchemy.orm import selectinload - - result = await session.execute( - select(AnalysisResultSnapshot) - .where(AnalysisResultSnapshot.stp_file_id == stp_file_id) - .order_by(AnalysisResultSnapshot.created_time.desc()) - .limit(limit) - ) - - snapshots = result.scalars().all() - logger.info(f"获取到 {len(snapshots)} 个分析结果快照") - return snapshots - # 全局存储集成服务实例 storage_integration = StorageIntegrationService() diff --git a/templates/result.html b/templates/result.html index 4fa2724..8b9a7e0 100644 --- a/templates/result.html +++ b/templates/result.html @@ -159,7 +159,7 @@ - - - - - - -
-
-
-

正在加载快照信息...

-
-
- -
- -
- - - - - \ No newline at end of file