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

382 lines
12 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 } from '@/api/allMovieType';
import { RoleEntity } from '../domain/Entities';
import {
applyRoleToShots,
getRoleList,
getRoleData,
regenerateRole,
getRoleShots,
replaceRole,
getAllCharacterList,
getCharacterListByProjectWithHighlight,
updateAndRegenerateCharacter,
getUserRoleLibrary,
generateCharacterDescription,
} from '@/api/video_flow';
export interface RoleResponse {
/** 角色描述 */
character_description: string;
/** 角色名称 */
character_name: string;
/** 高亮关键词 */
highlights: string[];
/** 角色图片地址 */
image_path: string;
}
/**
* 角色图编辑用例
* 负责角色图内容的初始化、修改和优化
*/
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, // 默认加载完成
disableEdit: false, // 默认允许编辑
updatedAt: Date.now()
};
return roleEntity;
});
}
/**
* 解析项目角色列表接口返回的数据
* @description 将接口返回的项目角色列表数据转换为RoleEntity数组
* @param {RoleResponse[]} projectRoleData - 项目角色列表数据
* @returns {RoleEntity[]} 角色实体数组
* @throws {Error} 如果数据格式不正确则抛出异常
*/
/**
* 解析项目角色列表接口返回的数据
* @description 将接口返回的项目角色列表数据转换为RoleEntity数组
* @param {RoleResponse[]} projectRoleData - 项目角色列表数据
* @returns {RoleEntity[]} 角色实体数组
* @throws {Error} 如果数据格式不正确则抛出异常
*/
parseProjectRoleList(projectRoleData: RoleResponse[]): RoleEntity[] {
if (!Array.isArray(projectRoleData)) {
throw new Error('项目角色数据格式错误');
}
return projectRoleData.map((char, index) => {
/** 角色实体对象 */
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()
};
return roleEntity;
});
}
/**
* 获取角色库的角色列表
* @returns Promise<RoleEntity[]> 角色库列表
*/
async getRoleLibraryList(): Promise<RoleEntity[]> {
try {
// 使用新的角色列表接口获取角色库
const response = await getAllCharacterList();
if (response.successful) {
const roleList = this.parseNewRoleList(response.data);
return roleList;
} else {
throw new Error(response.message || '获取角色库失败');
}
} catch (error) {
console.error('获取角色库失败:', error);
throw error;
}
}
/**
* 选中某个角色作为当前活跃角色
* @param roleId 角色ID
*/
async selectRole(roleId: string): Promise<void> {
try {
// 从已获取的角色列表中查找对应的角色实体
const roleEntity = this.roleList.find(role => role.id === roleId);
if (roleEntity) {
this.selectedRole = roleEntity;
// 获取角色数据
const response = await getRoleData({ roleId });
if (!response.successful) {
throw new Error(response.message || '获取角色数据失败');
}
} else {
throw new Error('未找到对应的角色实体,请先获取角色列表');
}
} catch (error) {
console.error('选择角色失败:', error);
throw error;
}
}
/**
* 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.character;
// 将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_path || '',
loadingProgress: 100,
disableEdit: false,
updatedAt: Date.now()
};
return roleEntity;
} catch (error) {
console.error('AI生成角色失败:', error);
throw error;
}
}
/**
* 应用此角色到指定分镜
* @param shotIds 分镜ID列表
* @param roleId 角色ID
* @returns 应用结果
*/
async applyRole(shotIds: string[], roleId: string) {
try {
const response = await applyRoleToShots({
roleId,
shotIds,
});
if (response.successful) {
return response.data;
} else {
throw new Error(response.message || '应用角色到分镜失败');
}
} catch (error) {
console.error('应用角色到分镜失败:', 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<string[]> 解析出的标签列表
*/
async parseTagsFromAiText(aiText: string): Promise<string[]> {
// TODO: 未来实现从AI文本中解析标签的逻辑
// 例如:解析文本中的关键词、特征描述等作为标签
return [];
}
/**
* @description 根据图片地址获取角色实体数据
* @param imageUrl 图片地址
* @returns Promise<RoleEntity> 角色实体数据
*/
async getRoleByImage(imageUrl: string): Promise<RoleEntity> {
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()
};
return mockRole;
} catch (error) {
console.error('根据图片获取角色失败:', error);
throw new Error('根据图片获取角色失败');
}
}
}