- 移除有问题的OCC.Core导入,避免模块依赖问题 - 重新实现基于trimesh的层级保留功能,使用连通组件分离 - 添加智能回退机制,如果分离失败自动使用标准转换 - 扩展CLI和API接口支持层级保留参数 - 更新文档说明新的实现方式 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
135 lines
4.2 KiB
Python
135 lines
4.2 KiB
Python
#!/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
|
|
|
|
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):
|
|
"""转换文件接口"""
|
|
|
|
# 验证输入文件是否存在
|
|
if not os.path.isfile(request.input_path):
|
|
raise HTTPException(status_code=400, detail=f"输入文件不存在: {request.input_path}")
|
|
|
|
# 验证输入文件扩展名
|
|
if not request.input_path.lower().endswith(('.stp', '.step')):
|
|
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)}")
|
|
|
|
# 创建转换选项
|
|
options = ConvertOptions(
|
|
auto_scale=request.options.auto_scale,
|
|
auto_center=request.options.auto_center,
|
|
preserve_hierarchy=request.options.preserve_hierarchy
|
|
)
|
|
|
|
# 创建任务
|
|
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)} |