import { message } from "antd"; import { StoryTemplateEntity } from "../domain/Entities"; import { useUploadFile } from "../domain/service"; /** 模板角色接口 */ interface TemplateRole { /** 角色名 */ role_name: string; /** 照片URL */ photo_url: string; /** 声音URL */ voice_url: string; } import { TemplateStoryUseCase } from "../usecase/templateStoryUseCase"; import { getUploadToken, uploadToQiniu } from "@/api/common"; import { useState, useCallback, useMemo } from "react"; import { createMovieProjectV3 } from "@/api/movie_start"; import { CreateMovieProjectV3Request } from "@/api/DTO/movie_start_dto"; interface UseTemplateStoryService { /** 模板列表 */ templateStoryList: StoryTemplateEntity[]; /** 当前选中要使用的模板 */ selectedTemplate: StoryTemplateEntity | null; /** 当前选中的活跃角色索引 */ activeRoleIndex: number; /** 计算属性:当前活跃角色信息 */ activeRole: TemplateRole | null; /** 加载状态 */ isLoading: boolean; /** 获取模板列表函数 */ /** 获取模板列表函数 */ getTemplateStoryList: () => Promise; /** * action 生成电影函数 * @param {string} user_id - 用户ID * @param {"auto" | "manual"} mode - 生成模式 * @param {"720p" | "1080p" | "4k"} resolution - 分辨率 * @param {string} language - 语言 * @returns {Promise} - 生成的电影ID */ actionStory: ( user_id: string, mode: "auto" | "manual", resolution: "720p" | "1080p" | "4k" , language: string ) => Promise; /** 设置选中的模板 */ setSelectedTemplate: (template: StoryTemplateEntity | null) => void; /** 设置活跃角色索引 */ setActiveRoleIndex: (index: number) => void; /** 设置当前活跃角色的音频URL */ setActiveRoleAudio: (audioUrl: string) => void; /**清空数据 */ clearData: () => void; /** 上传人物头像并分析 */ AvatarAndAnalyzeFeatures: (imageUrl: string) => Promise; } export const useTemplateStoryServiceHook = (): UseTemplateStoryService => { const [templateStoryList, setTemplateStoryList] = useState< StoryTemplateEntity[] >([]); const [selectedTemplate, setSelectedTemplate] = useState(null); const [activeRoleIndex, setActiveRoleIndex] = useState(0); const [isLoading, setIsLoading] = useState(false); // 使用上传文件Hook const { uploadFile } = useUploadFile(); /** 模板故事用例实例 */ const templateStoryUseCase = useMemo(() => new TemplateStoryUseCase(), []); /** 计算属性:当前活跃角色信息 */ const activeRole = useMemo(() => { if ( !selectedTemplate || activeRoleIndex < 0 || activeRoleIndex >= selectedTemplate.storyRole.length ) { return null; } return selectedTemplate.storyRole[activeRoleIndex]; }, [selectedTemplate, activeRoleIndex]); /** * 获取模板列表函数 */ const getTemplateStoryList = useCallback(async (): Promise => { try { setIsLoading(true); const templates = await templateStoryUseCase.getTemplateStoryList(); setTemplateStoryList(templates); setSelectedTemplate(templates[0]); setActiveRoleIndex(0); console.log(selectedTemplate, activeRoleIndex) } catch (err) { console.error("获取模板列表失败:", err); } finally { setIsLoading(false); } }, [templateStoryUseCase]); /** * 设置活跃角色索引 */ const handleSetActiveRoleIndex = useCallback((index: number): void => { setActiveRoleIndex(index); }, []); /** * 设置当前活跃角色的图片URL */ const setActiveRoleData = useCallback( (imageUrl: string, desc: string): void => { if ( !selectedTemplate || activeRoleIndex < 0 || activeRoleIndex >= selectedTemplate.storyRole.length ) { console.log(selectedTemplate, activeRoleIndex); return; } try { const character_brief = { name: selectedTemplate.storyRole[activeRoleIndex].role_name, image_url: imageUrl, character_analysis: JSON.parse(desc).character_analysis, }; const updatedTemplate = { ...selectedTemplate, storyRole: selectedTemplate.storyRole.map((role, index) => index === activeRoleIndex ? { ...role, photo_url: imageUrl, role_description: character_brief, } : role ), }; setSelectedTemplate(updatedTemplate); } catch (error) { message.error("Image analysis failed"); console.log("error", error); } }, [selectedTemplate, activeRoleIndex] ); /** * 设置当前活跃角色的音频URL */ const setActiveRoleAudio = useCallback( (audioUrl: string): void => { if ( !selectedTemplate || activeRoleIndex < 0 || activeRoleIndex >= selectedTemplate.storyRole.length ) { return; } const updatedTemplate = { ...selectedTemplate, storyRole: selectedTemplate.storyRole.map((role, index) => index === activeRoleIndex ? { ...role, voice_url: audioUrl } : role ), }; setSelectedTemplate(updatedTemplate); }, [selectedTemplate, activeRoleIndex] ); /** * 上传人物头像并分析特征,替换旧的角色数据 * @param {string} characterName - 角色名称 */ const AvatarAndAnalyzeFeatures = useCallback( async (imageUrl: string): Promise => { try { setIsLoading(true); // 调用用例处理人物头像上传和特征分析 const result = await templateStoryUseCase.AvatarAndAnalyzeFeatures( imageUrl ); setActiveRoleData(result.crop_url, result.whisk_caption); console.log("人物头像和特征描述更新成功:", result); } catch (error) { console.error("人物头像上传和特征分析失败:", error); throw error; } finally { setIsLoading(false); } }, [templateStoryUseCase] ); const actionStory = useCallback( async ( user_id: string, mode: "auto" | "manual" = "auto", resolution: "720p" | "1080p" | "4k" = "720p", language: string = "English" ) => { try { const params: CreateMovieProjectV3Request = { user_id, mode, resolution, storyRole: selectedTemplate?.storyRole || [], language, template_id: selectedTemplate?.template_id || "", }; const result = await createMovieProjectV3(params); return result.data.project_id as string; } catch (error) { console.error("创建电影项目失败:", error); } }, [selectedTemplate] ); return { templateStoryList, selectedTemplate, activeRoleIndex, activeRole, isLoading, getTemplateStoryList, actionStory, setSelectedTemplate, setActiveRoleIndex: handleSetActiveRoleIndex, setActiveRoleAudio, AvatarAndAnalyzeFeatures, clearData: () => { setTemplateStoryList([]); setSelectedTemplate(null); setActiveRoleIndex(0); }, }; };