拆镜复刻、爆款开头复刻管理后台完成

This commit is contained in:
2026-06-17 15:42:07 +08:00
parent 5d5e6485ee
commit 0d647a7171
31 changed files with 3042 additions and 2777 deletions
@@ -493,9 +493,16 @@ async def project_to_detail_out(db: AsyncSession, project: ModuleGenerationProje
video_url = video_generate_output.get("result_video_url") or (video_chat.video_url if video_chat else None) or project.final_video_url
cover_url = video_generate_output.get("result_video_cover_url") or (video_chat.video_cover_url if video_chat else None) or project.final_video_cover_url
user_name: str | None = None
if project.user_id:
user_result = await db.execute(select(User.username).where(User.id == project.user_id).limit(1))
user_name = user_result.scalar_one_or_none()
return ShotReplicateTaskDetailOut(
id=project.id,
project_id=project.id,
user_id=project.user_id,
user_name=user_name,
module=project.module,
title=project.title,
status=project.status,
@@ -593,6 +600,26 @@ async def create_shot_replicate_project(db: AsyncSession, current_user: User, re
return project
async def _current_step_map_by_project_ids(
db: AsyncSession,
*,
project_ids: set[str],
step_code: str,
) -> dict[str, ModuleGenerationStep]:
"""一次性查询当前页项目的指定步骤,避免列表逐条查 material_input。"""
if not project_ids:
return {}
result = await db.execute(
select(ModuleGenerationStep).where(
ModuleGenerationStep.project_id.in_(list(project_ids)),
ModuleGenerationStep.step_code == step_code,
ModuleGenerationStep.is_current.is_(True),
ModuleGenerationStep.deleted_at.is_(None),
)
)
return {step.project_id: step for step in result.scalars().all()}
async def list_shot_replicate_projects(
db: AsyncSession,
*,
@@ -601,6 +628,11 @@ async def list_shot_replicate_projects(
page: int,
page_size: int,
) -> ShotReplicateTaskListOut:
"""
拆镜复刻项目列表查询。
这个列表目前不是后台主入口,但仍避免逐条查 material_input,保持和爆款开头列表一致的批量查询策略。
"""
query = select(ModuleGenerationProject).where(
ModuleGenerationProject.module == MODULE,
ModuleGenerationProject.deleted_at.is_(None),
@@ -610,13 +642,23 @@ async def list_shot_replicate_projects(
if status:
query = query.where(ModuleGenerationProject.status == status)
total = (await db.execute(select(func.count()).select_from(query.subquery()))).scalar_one()
result = await db.execute(query.order_by(ModuleGenerationProject.created_at.desc()).offset((page - 1) * page_size).limit(page_size))
projects = list(result.scalars().all())
total = int((await db.execute(select(func.count()).select_from(query.subquery()))).scalar() or 0)
result = await db.execute(
query.order_by(ModuleGenerationProject.created_at.desc())
.offset((page - 1) * page_size)
.limit(page_size)
)
projects = list(result.scalars().unique().all())
project_ids = {project.id for project in projects if project.id}
material_step_map = await _current_step_map_by_project_ids(
db,
project_ids=project_ids,
step_code=ShotReplicateStepCodeEnum.MATERIAL_INPUT.value,
)
items: list[ShotReplicateTaskListItemOut] = []
for project in projects:
material_step = await _get_current_step_by_code(db, project.id, ShotReplicateStepCodeEnum.MATERIAL_INPUT.value)
material_step = material_step_map.get(project.id)
material = _step_payload(material_step.input_json if material_step else None)
items.append(
ShotReplicateTaskListItemOut(