forked from 77media/video-flow
283 lines
8.1 KiB
TypeScript
283 lines
8.1 KiB
TypeScript
import { VideoFlowProjectResponse } from '@/api/allMovieType';
|
||
import { RoleEntity } from '../domain/Entities';
|
||
import {
|
||
applyRoleToShots,
|
||
getRoleList,
|
||
getUserRoleLibrary,
|
||
getRoleData,
|
||
regenerateRole,
|
||
getRoleShots,
|
||
replaceRole,
|
||
optimizeRoleDescription,
|
||
detailScriptEpisodeNew
|
||
} 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 getRoleList({ projectId });
|
||
const detail = await detailScriptEpisodeNew({ project_id: projectId });
|
||
const roleList = this.parseRoleList(detail.data);
|
||
if (detail.successful) {
|
||
return roleList;
|
||
} else {
|
||
throw new Error(detail.message || '获取角色列表失败');
|
||
}
|
||
} catch (error) {
|
||
console.error('获取角色列表失败:', error);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
parseRoleList(detail: VideoFlowProjectResponse): RoleEntity[] {
|
||
const characters = detail.data?.character || [];
|
||
|
||
return characters.map((char, index) => {
|
||
const roleEntity: RoleEntity = {
|
||
id: `role_${index + 1}`,
|
||
name: char.name || '',
|
||
generateText: char.description || '',
|
||
tags: [], // 默认为空标签数组
|
||
imageUrl: '', // 默认为空图片URL
|
||
loadingProgress: 100, // 默认加载完成
|
||
disableEdit: false, // 默认允许编辑
|
||
updatedAt: Date.now()
|
||
};
|
||
|
||
return roleEntity;
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 获取角色库的角色列表
|
||
* @returns Promise<RoleEntity[]> 角色库列表
|
||
*/
|
||
async getRoleLibraryList(): Promise<RoleEntity[]> {
|
||
try {
|
||
const response = await getUserRoleLibrary();
|
||
if (response.successful) {
|
||
return response.data;
|
||
} 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;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 重新生成角色
|
||
* @param prompt 角色提示词
|
||
* @returns Promise<RoleEntity> 重新生成的角色
|
||
*/
|
||
async AIgenerateRole(prompt: string): Promise<RoleEntity> {
|
||
try {
|
||
// 直接使用当前角色的ID,不做任何处理
|
||
const response = await regenerateRole({
|
||
prompt,
|
||
tagTypes: [], // 标签现在只是文本的一部分,传递空数组
|
||
roleId: this.selectedRole?.id
|
||
});
|
||
|
||
if (response.successful) {
|
||
return response.data;
|
||
} else {
|
||
throw new Error(response.message || '重新生成角色失败');
|
||
}
|
||
} catch (error) {
|
||
console.error('重新生成角色失败:', 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 userSuggestion 用户优化建议
|
||
* @param roleDescription 角色描述文本
|
||
* @returns Promise<string> 优化后的角色描述
|
||
*/
|
||
async optimizeRoleDescription(userSuggestion: string, roleDescription: string): Promise<string> {
|
||
try {
|
||
if (!this.selectedRole) {
|
||
throw new Error('请先选择角色');
|
||
}
|
||
|
||
// 调用AI优化角色描述API
|
||
const response = await optimizeRoleDescription({
|
||
roleId: this.selectedRole.id,
|
||
userSuggestion,
|
||
roleDescription,
|
||
});
|
||
|
||
if (!response.successful) {
|
||
throw new Error(response.message || 'AI优化角色描述失败');
|
||
}
|
||
|
||
const optimizedDescription = response.data.optimizedDescription;
|
||
|
||
// 更新角色列表中的对应角色描述
|
||
const roleIndex = this.roleList.findIndex(role => role.id === this.selectedRole?.id);
|
||
if (roleIndex !== -1) {
|
||
this.roleList[roleIndex].generateText = optimizedDescription;
|
||
}
|
||
|
||
return optimizedDescription;
|
||
} 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: '通过图片识别生成的角色描述',
|
||
tagIds: [], // 空标签数组
|
||
imageUrl: imageUrl, // 使用传入的图片地址
|
||
loadingProgress: 100, // 加载完成
|
||
disableEdit: false, // 允许编辑
|
||
updatedAt: Date.now()
|
||
};
|
||
|
||
return mockRole;
|
||
} catch (error) {
|
||
console.error('根据图片获取角色失败:', error);
|
||
throw new Error('根据图片获取角色失败');
|
||
}
|
||
}
|
||
|
||
}
|