Files
autoclip/backend/services/clip_service.py
T
Kris Ka 8ee2d50044 修复WebSocket进度更新和前端状态自动更新问题
- 修复WebSocketNotificationService.send_processing_progress方法参数不匹配问题
- 修复前端RealTimeStatus组件WebSocket消息处理逻辑
- 修复Celery Worker队列配置,确保任务正确路由到processing队列
- 修复Celery应用导入冲突,统一使用正确的celery_app配置
- 添加实时项目状态更新功能,前端无需手动刷新即可看到处理进度
- 完善系统启动脚本,修复PYTHONPATH未绑定变量错误
- 优化流水线处理逻辑,确保所有6个步骤正常执行
- 添加完整的项目文档和启动指南

测试结果:
- WebSocket进度更新正常工作(16%, 33%, 100%)
- 流水线处理完全正常(6个步骤全部成功)
- 前端状态自动更新正常
- 项目状态正确同步到数据库
2025-09-08 17:21:31 +08:00

91 lines
3.8 KiB
Python

"""
切片服务
提供切片相关的业务逻辑操作
"""
from typing import Optional, List, Dict, Any
from sqlalchemy.orm import Session
from ..services.base import BaseService
from ..repositories.clip_repository import ClipRepository
from ..models.clip import Clip
from ..schemas.clip import ClipCreate, ClipUpdate, ClipResponse, ClipListResponse, ClipFilter
from ..schemas.base import PaginationParams, PaginationResponse
class ClipService(BaseService[Clip, ClipCreate, ClipUpdate, ClipResponse]):
"""Clip service with business logic."""
def __init__(self, db: Session):
repository = ClipRepository(db)
super().__init__(repository)
self.db = db
def create_clip(self, clip_data: ClipCreate) -> Clip:
"""Create a new clip with business logic."""
data = clip_data.model_dump()
orm_data = {
"project_id": data["project_id"],
"title": data["title"],
"description": data["description"],
"start_time": int(data["start_time"]) if data["start_time"] is not None else 0,
"end_time": int(data["end_time"]) if data["end_time"] is not None else 0,
"duration": int(data["duration"]) if data["duration"] is not None else 0,
"score": data.get("score"),
"clip_metadata": data.get("clip_metadata", {}),
"tags": data.get("tags", [])
}
return self.create(**orm_data)
def update_clip(self, clip_id: str, clip_data: ClipUpdate) -> Optional[Clip]:
"""Update a clip with business logic."""
update_data = {k: v for k, v in clip_data.model_dump().items() if v is not None}
if not update_data:
return self.get(clip_id)
return self.update(clip_id, **update_data)
def get_clips_by_project(self, project_id: str, skip: int = 0, limit: int = 100) -> List[Clip]:
"""Get clips by project ID."""
return self.repository.find_by(project_id=project_id)
def get_clips_paginated(
self,
pagination: PaginationParams,
filters: Optional[ClipFilter] = None
) -> ClipListResponse:
"""Get paginated clips with filtering."""
filter_dict = {}
if filters:
filter_data = filters.model_dump()
filter_dict = {k: v for k, v in filter_data.items() if v is not None}
items, pagination_response = self.get_paginated(pagination, filter_dict)
# Convert to response schemas (simplified)
clip_responses = []
for clip in items:
status_obj = getattr(clip, 'status', None)
status_value = status_obj.value if hasattr(status_obj, 'value') else 'pending'
clip_responses.append(ClipResponse(
id=str(clip.id),
project_id=str(clip.project_id),
title=str(clip.title),
description=str(clip.description) if clip.description else None,
start_time=getattr(clip, 'start_time', 0),
end_time=getattr(clip, 'end_time', 0),
duration=int(getattr(clip, 'duration', 0)),
score=getattr(clip, 'score', None),
status=status_value,
tags=getattr(clip, 'tags', []) or [],
clip_metadata=getattr(clip, 'clip_metadata', {}) or {},
created_at=getattr(clip, 'created_at', None) if isinstance(getattr(clip, 'created_at', None), (type(None), __import__('datetime').datetime)) else None,
updated_at=getattr(clip, 'updated_at', None) if isinstance(getattr(clip, 'updated_at', None), (type(None), __import__('datetime').datetime)) else None,
collection_ids=[]
))
return ClipListResponse(
items=clip_responses,
pagination=pagination_response
)