This commit is contained in:
cjw
2026-02-16 18:33:17 +08:00
parent d111721ed9
commit 1525f6fc0b
5 changed files with 25 additions and 849 deletions
+22 -291
View File
@@ -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