import { StoryTemplateEntity } from "../domain/Entities"; /** 模板角色接口 */ 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"; interface UseTemplateStoryService { /** 模板列表 */ templateStoryList: StoryTemplateEntity[]; /** 当前选中要使用的模板 */ selectedTemplate: StoryTemplateEntity | null; /** 当前选中的活跃角色索引 */ activeRoleIndex: number; /** 计算属性:当前活跃角色信息 */ activeRole: TemplateRole | null; /** 加载状态 */ isLoading: boolean; /** 获取模板列表函数 */ getTemplateStoryList: () => Promise; /** action 生成电影函数 */ actionStory: () => Promise; /** 设置选中的模板 */ setSelectedTemplate: (template: StoryTemplateEntity | null) => void; /** 设置活跃角色索引 */ setActiveRoleIndex: (index: number) => void; /** 设置当前活跃角色的图片URL */ setActiveRoleImage: (imageUrl: string) => void; /** 设置当前活跃角色的音频URL */ setActiveRoleAudio: (audioUrl: string) => void; } export const useTemplateStoryServiceHook = (): UseTemplateStoryService => { const [templateStoryList, setTemplateStoryList] = useState([]); const [selectedTemplate, setSelectedTemplate] = useState(null); const [activeRoleIndex, setActiveRoleIndex] = useState(0); const [isLoading, setIsLoading] = useState(false); /** 模板故事用例实例 */ 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(); const templates = await new Promise((resolve) => { setTimeout(() => { resolve([ { id: '1', name: '奇幻冒险故事', imageUrl: ['/assets/3dr_howlcastle.png', '/assets/3dr_spirited.jpg'], generateText: '一个关于勇气与友谊的奇幻冒险故事,主角在神秘世界中寻找失落的宝藏,结识了各种奇特的生物和伙伴。', storyRole: [ { role_name: '艾莉娅', photo_url: '/assets/3dr_chihiro.png', voice_url:"" }, { role_name: '魔法师梅林', photo_url: '/assets/3dr_mono.png', voice_url:"" }, { role_name: '守护者龙', photo_url: '/assets/3dr_howlbg.jpg', voice_url:"" } ] }, { id: '2', name: '科幻探索之旅', imageUrl: ['/assets/3dr_monobg.jpg'], generateText: '未来世界的太空探索故事,人类在浩瀚宇宙中寻找新的家园,面对未知的挑战和外星文明的接触。', storyRole: [ { role_name: '船长凯特', photo_url: '/assets/3dr_chihiro.png', voice_url:"" }, { role_name: 'AI助手诺娃', photo_url: '/assets/3dr_mono.png', voice_url:"" } ] }, { id: '3', name: '温馨家庭喜剧', imageUrl: ['/assets/3dr_spirited.jpg'], generateText: '一个充满欢笑和温情的家庭故事,讲述家庭成员之间的日常趣事,以及如何一起面对生活中的小挑战。', storyRole: [ { role_name: '妈妈莉莉', photo_url: '/assets/3dr_chihiro.png', voice_url:"" }, { role_name: '爸爸汤姆', photo_url: '/assets/3dr_mono.png', voice_url:"" }, { role_name: '孩子小杰', photo_url: '/assets/3dr_howlbg.jpg', voice_url:"" } ] } ]); }, 1000); }); setTemplateStoryList(templates); setSelectedTemplate(templates[0]); } catch (err) { console.error('获取模板列表失败:', err); } finally { setIsLoading(false); } }, [templateStoryUseCase]); /** * action 生成电影函数 */ const actionStory = useCallback(async (): Promise => { if (!selectedTemplate) { throw new Error('请先选择一个故事模板'); } try { setIsLoading(true); const projectId = await templateStoryUseCase.actionStory(selectedTemplate); return projectId; } catch (err) { console.error('生成电影失败:', err); throw err; } finally { setIsLoading(false); } }, [selectedTemplate, templateStoryUseCase]); /** * 设置活跃角色索引 */ const handleSetActiveRoleIndex = useCallback((index: number): void => { setActiveRoleIndex(index); }, []); /** * 设置当前活跃角色的图片URL */ const setActiveRoleImage = useCallback((imageUrl: string): void => { if (!selectedTemplate || activeRoleIndex < 0 || activeRoleIndex >= selectedTemplate.storyRole.length) { return; } const updatedTemplate = { ...selectedTemplate, storyRole: selectedTemplate.storyRole.map((role, index) => index === activeRoleIndex ? { ...role, photo_url: imageUrl } : role ), }; setSelectedTemplate(updatedTemplate); }, [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]); return { templateStoryList, selectedTemplate, activeRoleIndex, activeRole, isLoading, getTemplateStoryList, actionStory, setSelectedTemplate, setActiveRoleIndex: handleSetActiveRoleIndex, setActiveRoleImage, setActiveRoleAudio, }; };