video-flow-b/app/service/usecase/ShotEditUsecase.ts

204 lines
6.4 KiB
TypeScript
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.

import { ShotEntity, RoleEntity, SceneEntity, AITextEntity, TagEntity } from '../domain/Entities';
import { ShotItem, RoleItem, SceneItem, TextItem, TagItem } from '../domain/Item';
import {
getShotRoles,
getShotScenes,
getShotData,
regenerateShot,
updateShotContent
} from '@/api/video_flow';
/**
* 分镜编辑用例
* 负责分镜内容的初始化、修改和优化
*/
export class ShotEditUseCase {
constructor(private shotItem: ShotItem) {
}
/**
* 获取分镜关联的角色信息列表
* @description 获取当前分镜可以使用的角色列表
* @returns Promise<RoleEntity[]> 角色信息列表
* @throws {Error} 当API调用失败时抛出错误
*/
async getShotRoles(): Promise<RoleEntity[]> {
const shotId = this.shotItem.entity.id;
if (!shotId) {
throw new Error('分镜ID不存在无法获取角色信息');
}
const response = await getShotRoles({
shotId: shotId
});
if (response.successful) {
return response.data;
} else {
throw new Error(`获取分镜角色信息失败: ${response.message}`);
}
}
/**
* 获取分镜关联的场景信息列表
* @description 获取当前分镜可以使用的场景列表
* @returns Promise<SceneEntity[]> 场景信息列表
* @throws {Error} 当API调用失败时抛出错误
*/
async getShotScenes(): Promise<SceneEntity[]> {
const shotId = this.shotItem.entity.id;
if (!shotId) {
throw new Error('分镜ID不存在无法获取场景信息');
}
const response = await getShotScenes({
shotId: shotId
});
if (response.successful) {
return response.data;
} else {
throw new Error(`获取分镜场景信息失败: ${response.message}`);
}
}
/**
* 重新获取当前分镜信息
* @description 从服务器重新获取当前分镜的详细数据,并更新当前实体
* @returns Promise<{ text: AITextEntity; tags: TagEntity[] }> 分镜相关的AI文本和标签数据
* @throws {Error} 当API调用失败时抛出错误
*/
async refreshShotData(): Promise<{ text: AITextEntity; tags: TagEntity[] }> {
const shotId = this.shotItem.entity.id;
if (!shotId) {
throw new Error('分镜ID不存在无法获取分镜数据');
}
const response = await getShotData({
shotId: shotId
});
if (response.successful) {
// 更新当前分镜的实体数据
const { text, tags } = response.data;
// 更新分镜实体中的相关字段
const updatedShotEntity = {
...this.shotItem.entity,
generateTextId: text.id, // 更新AI文本ID
tagIds: tags.map((tag: TagEntity) => tag.id), // 更新标签ID列表
updatedAt: Date.now(), // 更新时间戳
};
// 更新当前UseCase中的实体
this.shotItem.setEntity(updatedShotEntity);
// 检查状态是否需要更新为视频状态
this.checkAndUpdateVideoStatus(updatedShotEntity);
return response.data;
} else {
throw new Error(`获取分镜数据失败: ${response.message}`);
}
}
/**
* 重新生成当前分镜
* @description 使用镜头、对话内容、角色ID替换参数、场景ID替换参数重新生成分镜
* @param shotPrompt 镜头描述
* @param dialogueContent 对话内容
* @param roleReplaceParams 角色ID替换参数格式为{oldId:string,newId:string}[]
* @param sceneReplaceParams 场景ID替换参数格式为{oldId:string,newId:string}[]
* @returns Promise<ShotEntity> 重新生成的分镜实体
* @throws {Error} 当API调用失败时抛出错误
*/
async regenerateShot(
shotPrompt: string,
dialogueContent: string,
roleReplaceParams: { oldId: string; newId: string }[],
sceneReplaceParams: { oldId: string; newId: string }[]
): Promise<ShotEntity> {
const shotId = this.shotItem.entity.id;
if (!shotId) {
throw new Error('分镜ID不存在无法重新生成分镜');
}
// 调用重新生成分镜接口
const response = await regenerateShot({
shotId: shotId,
shotPrompt: shotPrompt,
dialogueContent: dialogueContent,
roleReplaceParams: roleReplaceParams,
sceneReplaceParams: sceneReplaceParams,
});
if (response.successful) {
const shotEntity = response.data;
this.shotItem.setEntity(shotEntity);
// 检查状态是否需要更新为视频状态
this.checkAndUpdateVideoStatus(shotEntity);
return shotEntity;
} else {
throw new Error(`重新生成分镜失败: ${response.message}`);
}
}
/**
* 修改分镜对话内容
* @description 更新分镜的对话内容ContentItem数量和ID顺序不能变只能修改content字段
* @param newContent 新的对话内容数组
* @returns Promise<ShotEntity> 修改后的分镜实体
* @throws {Error} 当API调用失败时抛出错误
*/
async updateShotContent(newContent: Array<{ roleId: string; content: string }>): Promise<ShotEntity> {
const shotId = this.shotItem.entity.id;
if (!shotId) {
throw new Error('分镜ID不存在无法修改对话内容');
}
// 验证ContentItem数量和ID顺序
const currentContent = this.shotItem.entity.content;
if (newContent.length !== currentContent.length) {
throw new Error('ContentItem数量不能改变');
}
// 验证角色ID顺序
for (let i = 0; i < newContent.length; i++) {
if (newContent[i].roleId !== currentContent[i].roleId) {
throw new Error('ContentItem的roleId顺序不能改变');
}
}
const response = await updateShotContent({
shotId: shotId,
content: newContent,
});
if (response.successful) {
const shotEntity = response.data;
this.shotItem.setEntity(shotEntity);
// 检查状态是否需要更新为视频状态
this.checkAndUpdateVideoStatus(shotEntity);
return shotEntity;
} else {
throw new Error(`修改分镜对话内容失败: ${response.message}`);
}
}
/**
* 检查并更新视频状态
* @description 当分镜状态变为视频加载中或完成时调用updateToVideoStatus
* @param shotEntity 分镜实体
*/
private checkAndUpdateVideoStatus(shotEntity: ShotEntity): void {
// 当状态为视频加载中或完成时,更新为视频状态
if (shotEntity.status === 1 || shotEntity.status === 2) { // videoLoading 或 finished
this.shotItem.updateToVideoStatus();
}
}
}