TellmeStpToGlb/api/routes.py
sladro 90ba65e484 feat: 实现基于XCAF的真正装配结构保留转换
- 新增XCAF转换器,直接从STP到GLB保留完整装配层级
- 修复HTTP API与CLI参数不一致问题
- 修复静默吞没错误的问题,遵循快速失败原则
- 清理旧文件,整理测试文件到tests目录
- 添加URL下载支持,可直接转换远程STP文件
- 更新文档,准确描述XCAF装配保留功能

技术改进:
- 使用STEPCAFControl_Reader读取带装配信息的STEP文件
- 通过RWGltf_CafWriter直接导出GLB,无需STL中间格式
- 支持CPU多线程并行三角化
- HTTP API和CLI使用完全一致的转换参数

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-09 16:50:48 +08:00

155 lines
5.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
API路由定义
"""
import os
from fastapi import APIRouter, HTTPException, BackgroundTasks
from api.schemas import (
ConvertRequestSchema,
ConvertResponseSchema,
TaskStatusSchema,
HealthResponseSchema
)
from services.task_manager import task_manager
from core.models import ConvertOptions, TaskStatus, PrecisionOptions
from utils.network_helper import is_url, validate_url
from utils.helpers import is_stp_file
router = APIRouter()
@router.get("/health", response_model=HealthResponseSchema)
async def health_check():
"""健康检查接口"""
return HealthResponseSchema()
@router.post("/api/v1/convert", response_model=ConvertResponseSchema)
async def convert_file(request: ConvertRequestSchema):
"""转换文件接口"""
# 验证输入文件或URL
if is_url(request.input_path):
# 验证URL
is_valid, error_msg = validate_url(request.input_path)
if not is_valid:
raise HTTPException(status_code=400, detail=f"URL验证失败: {error_msg}")
# 检查URL是否指向STP文件
if not is_stp_file(request.input_path):
raise HTTPException(status_code=400, detail="URL必须指向STP或STEP格式的文件")
else:
# 验证本地文件
if not os.path.isfile(request.input_path):
raise HTTPException(status_code=400, detail=f"输入文件不存在: {request.input_path}")
# 验证本地文件扩展名
if not is_stp_file(request.input_path):
raise HTTPException(status_code=400, detail="输入文件必须是STP或STEP格式")
# 验证输出文件扩展名
if not request.output_path.lower().endswith('.glb'):
raise HTTPException(status_code=400, detail="输出文件必须是GLB格式")
# 确保输出目录存在
output_dir = os.path.dirname(request.output_path)
if output_dir and not os.path.exists(output_dir):
try:
os.makedirs(output_dir, exist_ok=True)
except Exception as e:
raise HTTPException(status_code=400, detail=f"无法创建输出目录: {str(e)}")
# 创建精度选项
precision = PrecisionOptions(
linear_deflection=request.options.precision.linear_deflection,
angular_deflection=request.options.precision.angular_deflection,
mesh_quality=request.options.precision.mesh_quality
)
# 创建转换选项
options = ConvertOptions(
auto_scale=request.options.auto_scale,
auto_center=request.options.auto_center,
precision=precision
)
# 创建任务
task = task_manager.create_task(
input_path=request.input_path,
output_path=request.output_path,
options=options
)
# 启动任务
success = await task_manager.start_task(task.task_id)
if not success:
raise HTTPException(status_code=500, detail="任务启动失败")
return ConvertResponseSchema(
task_id=task.task_id,
status=task.status.value,
message="任务已创建并开始处理"
)
@router.get("/api/v1/status/{task_id}", response_model=TaskStatusSchema)
async def get_task_status(task_id: str):
"""获取任务状态接口"""
task = task_manager.get_task(task_id)
if not task:
raise HTTPException(status_code=404, detail="任务不存在")
return TaskStatusSchema(
task_id=task.task_id,
status=task.status.value,
progress=task.progress,
message=task.message,
created_at=task.created_at,
started_at=task.started_at,
completed_at=task.completed_at,
error_message=task.error_message
)
@router.delete("/api/v1/task/{task_id}")
async def cancel_task(task_id: str):
"""取消任务接口"""
task = task_manager.get_task(task_id)
if not task:
raise HTTPException(status_code=404, detail="任务不存在")
if task.status in [TaskStatus.COMPLETED, TaskStatus.FAILED]:
raise HTTPException(status_code=400, detail="任务已完成,无法取消")
success = task_manager.cancel_task(task_id)
if success:
return {"message": "任务已取消"}
else:
return {"message": "任务未在运行中"}
@router.get("/api/v1/tasks")
async def list_tasks():
"""获取所有任务列表接口"""
tasks = task_manager.get_all_tasks()
task_list = []
for task_id, task in tasks.items():
task_list.append({
"task_id": task.task_id,
"status": task.status.value,
"progress": task.progress,
"input_path": task.input_path,
"output_path": task.output_path,
"created_at": task.created_at,
"message": task.message
})
# 按创建时间倒序排列
task_list.sort(key=lambda x: x["created_at"], reverse=True)
return {"tasks": task_list, "total": len(task_list)}