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, } from '@/api/video_flow'; /** * 角色图编辑用例 * 负责角色图内容的初始化、修改和优化 */ export class RoleEditUseCase { /** 角色列表 */ roleList: RoleEntity[] = []; /** 当前选中的角色 */ selectedRole: RoleEntity | null = null; /** 角色库列表 */ roleLibraryList: RoleEntity[] = []; constructor() { } /** * 获取当前项目角色列表 * @param projectId 项目ID * @returns Promise 角色列表 */ async getRoleList(projectId: string): Promise { 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, // 默认加载完成 disableEdit: false, // 默认允许编辑 updatedAt: Date.now(), fromDraft: 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 = {}; // 如果草稿箱有数据,则返回草稿箱数据 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, disableEdit: false })) : [], imageUrl: char.image_path || '', loadingProgress: 100, disableEdit: false, updatedAt: Date.now(), fromDraft: 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, disableEdit: false, updatedAt: Date.now(), fromDraft: false }; return roleEntity; }); } /** * 获取角色库的角色列表 * @param userId 用户ID * @param userDescription 用户描述(角色描述) * @returns Promise 角色库列表 */ async getRoleLibraryList(userId: string, userDescription: string): Promise { 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 { 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 生成的角色实体 */ async AIgenerateRole( projectId: string, characterName: string, characterDescription: string ): Promise { 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, disableEdit: false })), // 将高亮关键词转换为TagValueObject格式 imageUrl: characterData.image_url || '', loadingProgress: 100, disableEdit: false, updatedAt: Date.now(), fromDraft: false }; 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 { // if (!this.selectedRole) { // throw new Error('请先选择角色'); // } // 调用新的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: 从AI文本描述中解析标签信息(预留函数,未来实现) * @param aiText AI文本描述 * @returns Promise 解析出的标签列表 */ async parseTagsFromAiText(aiText: string): Promise { // TODO: 未来实现从AI文本中解析标签的逻辑 // 例如:解析文本中的关键词、特征描述等作为标签 return []; } /** * @description 根据图片地址获取角色实体数据 * @param imageUrl 图片地址 * @returns Promise 角色实体数据 */ async getRoleByImage(imageUrl: string): Promise { try { // TODO: 调用后端API,根据图片地址获取角色数据 // 这里需要根据实际的后端API接口来实现 // const response = await getRoleByImage({ imageUrl }); // 临时实现:返回一个模拟的角色实体 // 实际使用时需要替换为真实的API调用 const mockRole: RoleEntity = { id: `role_${Date.now()}`, name: '从图片识别的角色', generateText: '通过图片识别生成的角色描述', tags: [], // 空标签数组 imageUrl: imageUrl, // 使用传入的图片地址 loadingProgress: 100, // 加载完成 disableEdit: false, // 允许编辑 updatedAt: Date.now(), fromDraft: false }; return mockRole; } catch (error) { console.error('根据图片获取角色失败:', error); throw new 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 镜头视频状态信息 */ async checkShotVideoStatus(projectId: string): Promise { try { // 这里需要调用后端API来检查镜头视频状态 // 由于这是一个新的功能,需要根据实际的后端API接口来实现 // 目前返回一个模拟的状态信息 // TODO: 替换为真实的API调用 const response = await checkShotVideoStatus({ project_id: projectId }); return response.data; } catch (error) { console.error('检查镜头视频状态失败:', error); throw new Error('检查镜头视频状态失败'); } } }