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

460 lines
14 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 { NewCharacterItem, CharacterListByProjectItem, CharacterListByProjectWithHighlightResponse, CharacterUpdateAndRegenerateRequest, CharacterUpdateAndRegenerateResponse, RoleResponse } from "@/api/DTO/movieEdit";
import { RoleEntity } from '../domain/Entities';
import {
applyRoleToShots,
getRoleList,
getRoleData,
regenerateRole,
getRoleShots,
replaceRole,
getCharacterListByProjectWithHighlight,
updateAndRegenerateCharacter,
getUserRoleLibrary,
generateCharacterDescription,
saveRegeneratedCharacter,
getSimilarCharacters,
checkShotVideoStatus,
analyzeImageDescription,
} from '@/api/video_flow';
/**
* 角色图编辑用例
* 负责角色图内容的初始化、修改和优化
*/
export class RoleEditUseCase {
/** 角色列表 */
roleList: RoleEntity[] = [];
/** 当前选中的角色 */
selectedRole: RoleEntity | null = null;
/** 角色库列表 */
roleLibraryList: RoleEntity[] = [];
constructor() {
}
/**
* 获取当前项目角色列表
* @param projectId 项目ID
* @returns Promise<RoleEntity[]> 角色列表
*/
async getRoleList(projectId: string): Promise<RoleEntity[]> {
try {
// 使用新的项目角色列表接口
const response = await getCharacterListByProjectWithHighlight({
project_id: projectId,
max_keywords: 6 // 默认提取6个关键词
});
if (response.successful) {
const roleList = this.parseProjectRoleList(response.data);
return roleList;
} else {
throw new Error(response.message || '获取项目角色列表失败');
}
} catch (error) {
console.error('获取项目角色列表失败:', error);
throw error;
}
}
/**
* 解析新角色列表接口返回的数据
* @param newCharacterData 新角色列表数据
* @returns RoleEntity[] 角色实体数组
*/
parseNewRoleList(newCharacterData: { data: NewCharacterItem[] }): RoleEntity[] {
const characters = newCharacterData.data || [];
return characters.map((char, index) => {
const roleEntity: RoleEntity = {
id: `role_${index + 1}`,
name: char.character_name || '',
generateText: char.character_description || '',
tags: [], // 默认为空标签数组
imageUrl: char.image_path || '', // 使用API返回的图片路径
loadingProgress: 100, // 默认加载完成
updatedAt: Date.now(),
fromDraft: false,
isChangeRole: false
};
return roleEntity;
});
}
/**
* 解析项目角色列表接口返回的数据
* @description 将接口返回的项目角色列表数据转换为RoleEntity数组
* @param {RoleResponse[]} projectRoleData - 项目角色列表数据
* @returns {RoleEntity[]} 角色实体数组
* @throws {Error} 如果数据格式不正确则抛出异常
*/
parseProjectRoleList(projectRoleData: RoleResponse): RoleEntity[] {
// if (!Array.isArray(projectRoleData)) {
// throw new Error('项目角色数据格式错误');
// }
let draftRoleList:Record<string,RoleEntity> = {};
// 如果草稿箱有数据,则返回草稿箱数据
if(projectRoleData.character_draft){
const roleList = JSON.parse(projectRoleData.character_draft);
for(const role of roleList){
draftRoleList[role.name] = role;
}
}
return projectRoleData.data.map((char, index) => {
if(draftRoleList[char.character_name]){
return {
...draftRoleList[char.character_name],
fromDraft: true,
id: `role_${index + 1}`,
updatedAt: Date.now(),
};
}
/** 角色实体对象 */
const roleEntity: RoleEntity = {
id: `role_${index + 1}`,
name: char.character_name || '',
generateText: char.character_description || '',
tags: Array.isArray(char.highlights)
? char.highlights.map((highlight: string) => ({
id: `tag_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
updatedAt: Date.now(),
/** 名称 */
name: highlight,
/** 内容 */
content: highlight,
loadingProgress: 100,
}))
: [],
imageUrl: char.image_path || '',
loadingProgress: 100,
updatedAt: Date.now(),
fromDraft: false,
isChangeRole: false
};
return roleEntity;
});
}
/**
* 解析相似角色列表接口返回的数据
* @description 将接口返回的相似角色列表数据转换为RoleEntity数组
* @param {any} similarCharacterData - 相似角色列表数据
* @returns {RoleEntity[]} 角色实体数组
* @throws {Error} 如果数据格式不正确则抛出异常
*/
parseSimilarCharacterList(similarCharacterData: any): RoleEntity[] {
// if (!similarCharacterData || !Array.isArray(similarCharacterData.characters)) {
// throw new Error('相似角色数据格式错误');
// }
const characters = [...similarCharacterData.similar_characters, ...similarCharacterData.user_characters];
return characters.map((char: any, index: number) => {
/** 角色实体对象 */
const roleEntity: RoleEntity = {
id: char.id || `role_${Date.now()}_${index}`,
name: char.name || '',
generateText: char.brief || '',
tags: [], // 相似角色接口可能不返回标签,暂时为空
imageUrl: char.avatar || '',
loadingProgress: 100,
updatedAt: Date.now(),
fromDraft: false,
isChangeRole: false
};
return roleEntity;
});
}
/**
* 获取角色库的角色列表
* @param userId 用户ID
* @param userDescription 用户描述(角色描述)
* @returns Promise<RoleEntity[]> 角色库列表
*/
async getRoleLibraryList(userId: string, userDescription: string): Promise<RoleEntity[]> {
try {
// 使用新的相似角色接口获取角色库
const response = await getSimilarCharacters({
userId,
user_description: userDescription,
similar_limit: 15 // 固定为15
});
if (response.successful) {
const roleList = this.parseSimilarCharacterList(response.data);
return roleList;
} else {
throw new Error(response.message || '获取角色库失败');
}
} catch (error) {
console.error('获取角色库失败:', error);
throw error;
}
}
/**
* 选中某个角色作为当前活跃角色
* @param role
*/
/**
* 选中某个角色作为当前活跃角色并用新角色替换掉roleList中name相同的项
* @param role 选中的角色
*/
async selectRole(role: RoleEntity): Promise<void> {
this.selectedRole = role;
console.log(' this.selectedRole', this.selectedRole)
if (Array.isArray(this.roleList)) {
this.roleList = this.roleList.map(r => r.name === role.name ? role : r);
}
}
/**
* AI生成角色
* @param projectId 项目ID
* @param characterName 角色名称
* @param characterDescription 角色描述
* @returns Promise<RoleEntity> 生成的角色实体
*/
async AIgenerateRole(
projectId: string,
characterName: string,
characterDescription: string
): Promise<RoleEntity> {
try {
// 使用新的角色更新和重新生成接口
const response = await updateAndRegenerateCharacter({
project_id: projectId,
character_name: characterName,
character_description: characterDescription,
max_keywords: 6 // 默认提取6个关键词
});
if (!response.successful) {
throw new Error(response.message || 'AI生成角色失败');
}
const characterData = response.data;
// 将API响应转换为RoleEntity
const roleEntity: RoleEntity = {
id: `role_${Date.now()}`, // 生成唯一ID
name: characterData.character_name,
generateText: characterData.character_description,
tags: (characterData.highlights || []).map(highlight => ({
id: `tag_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
updatedAt: Date.now(),
name: highlight,
content: highlight,
loadingProgress: 100,
})), // 将高亮关键词转换为TagValueObject格式
imageUrl: characterData.image_url || '',
loadingProgress: 100,
updatedAt: Date.now(),
fromDraft: false,
isChangeRole: true
};
return roleEntity;
} catch (error) {
console.error('AI生成角色失败:', error);
throw error;
}
}
/**
* 获取角色应用到的分镜列表
* @param roleId 角色ID
* @returns 分镜列表和应用状态
*/
async getRoleShotsList(roleId: string) {
try {
const response = await getRoleShots({ roleId });
if (response.successful) {
return response.data;
} else {
throw new Error(response.message || '获取角色分镜列表失败');
}
} catch (error) {
console.error('获取角色分镜列表失败:', error);
throw error;
}
}
/**
* 替换角色
* @param currentRoleId 当前角色ID
* @param replaceRoleId 替换的角色ID
* @returns 替换结果
*/
async replaceRoleById(currentRoleId: string, replaceRoleId: string) {
try {
const response = await replaceRole({
currentRoleId,
replaceRoleId,
});
if (response.successful) {
return response.data;
} else {
throw new Error(response.message || '替换角色失败');
}
} catch (error) {
console.error('替换角色失败:', error);
throw error;
}
}
/**
* @description: AI优化当前角色描述
* @param selectedRole 角色描述文本
* @returns Promise<{optimizedDescription: string, keywords: string[]}> 优化后的角色描述和关键词
*/
async optimizeRoleDescription( selectedRole: RoleEntity): Promise<{optimizedDescription: string, keywords: string[]}> {
try {
// 调用新的AI优化角色描述API
const response = await generateCharacterDescription({
original_text: selectedRole.generateText,
});
if (!response.successful) {
throw new Error(response.message || 'AI优化角色描述失败');
}
const { optimized_description, keywords } = response.data;
// 更新角色列表中的对应角色描述
const roleIndex = this.roleList.findIndex(role => role.id === this.selectedRole?.id);
if (roleIndex !== -1) {
this.roleList[roleIndex].generateText = optimized_description;
}
return {
optimizedDescription: optimized_description,
keywords: keywords
};
} catch (error) {
console.error('AI优化角色描述失败:', error);
throw error;
}
}
/**
* @description 保存重新生成的角色到角色库
* @param roleData 角色实体数据
* @param projectId 项目ID
* @param userId 用户ID
* @param originalCharacterName 原始角色名称
* @param videoUrls 视频URL列表
* @returns Promise<{character_id: string, message: string}> 保存结果
*/
async saveRegeneratedCharacterToLibrary(
roleData: RoleEntity,
projectId: string,
userId: string,
): Promise<{character_id: string, message: string}> {
try {
// 调用保存重新生成角色的API
const response = await saveRegeneratedCharacter({
user_id: userId,
project_id: projectId,
original_character_name: roleData.name,
character_description: roleData.generateText,
character_image: roleData.imageUrl,
video_urls: []
});
if (response.successful) {
console.log('角色保存到角色库成功:', response.data);
return {
character_id: response.data.character_id,
message: response.data.message
};
} else {
throw new Error(response.message || '保存角色到角色库失败');
}
} catch (error) {
console.error('保存角色到角色库失败:', error);
throw error;
}
}
/**
* @description 检查镜头视频状态
* @param projectId 项目ID
* @returns Promise<any> 镜头视频状态信息
*/
async checkShotVideoStatus(projectId: string): Promise<any> {
try {
// 这里需要调用后端API来检查镜头视频状态
// 由于这是一个新的功能需要根据实际的后端API接口来实现
// 目前返回一个模拟的状态信息
// TODO: 替换为真实的API调用
const response = await checkShotVideoStatus({ project_id: projectId });
return response.data;
} catch (error) {
console.error('检查镜头视频状态失败:', error);
throw new Error('检查镜头视频状态失败');
}
}
/**
* @description 分析图片并更新角色信息
* @param imageUrl 图片URL地址
* @param selectedRole 当前选中的角色
* @returns Promise<RoleEntity> 更新后的角色实体
*/
async analyzeImageAndUpdateRole(imageUrl: string, selectedRole: RoleEntity): Promise<RoleEntity> {
try {
// 调用图片分析接口获取描述
const result = await analyzeImageDescription({
image_url: imageUrl,
});
if (!result.successful) {
throw new Error(`图片分析失败: ${result.message}`);
}
const { description, highlights } = result.data;
// 更新当前选中角色的图片、描述和标签
const updatedRole: RoleEntity = {
...selectedRole,
imageUrl: imageUrl,
generateText: description,
tags: highlights.map((highlight: string, index: number) => ({
id: `tag_${Date.now()}_${index}`,
/** 名称 */
name: highlight,
/** 内容 */
content: highlight,
loadingProgress: 100,
updatedAt: Date.now(),
})),
};
// 更新角色列表中的对应角色
if (Array.isArray(this.roleList)) {
this.roleList = this.roleList.map(role =>
role.id === selectedRole.id ? updatedRole : role
);
}
// 更新当前选中的角色
this.selectedRole = updatedRole;
return updatedRole;
} catch (error) {
console.error('分析图片并更新角色失败:', error);
throw error;
}
}
}