import { StoryTemplateEntity } from "../domain/Entities"; import { useUploadFile } from "../domain/service"; import { debounce } from "lodash"; import { TemplateStoryUseCase } from "../usecase/templateStoryUseCase"; import { useState, useCallback, useMemo } from "react"; import { generateTextToImage } from "@/api/movie_start"; import { MovieProjectService, MovieProjectMode } from "./MovieProjectService"; import { CreateMovieProjectV3Request } from "@/api/DTO/movie_start_dto"; interface UseTemplateStoryService { /** 模板列表 */ templateStoryList: StoryTemplateEntity[]; /** 当前选中要使用的模板 */ selectedTemplate: StoryTemplateEntity | 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; /** 清空数据 */ clearData: () => void; /** 上传人物头像并分析 */ AvatarAndAnalyzeFeatures: (imageUrl: string, roleName: string) => Promise; /** 更新指定角色的图片 */ updateRoleImage: (roleName: string, imageUrl: string) => void; /** 更新指定道具的图片 */ updateItemImage: (itemName: string, imageUrl: string) => void; /** 带防抖的失焦处理函数 - 角色图片生成 */ handleRoleFieldBlur: (roleName: string, fieldValue: string) => void; /** 带防抖的失焦处理函数 - 道具图片生成 */ handleItemFieldBlur: (itemName: string, fieldValue: string) => void; } export const useTemplateStoryServiceHook = (): UseTemplateStoryService => { const [templateStoryList, setTemplateStoryList] = useState< StoryTemplateEntity[] >([]); const [selectedTemplate, setSelectedTemplate] = useState(null); const [isLoading, setIsLoading] = useState(false); // 使用上传文件Hook const { uploadFile } = useUploadFile(); /** 模板故事用例实例 */ const templateStoryUseCase = useMemo(() => new TemplateStoryUseCase(), []); /** * 获取模板列表函数 */ const getTemplateStoryList = useCallback(async (): Promise => { try { setIsLoading(true); const templates = await templateStoryUseCase.getTemplateStoryList(); setTemplateStoryList(templates); setSelectedTemplate(templates[0]); console.log(selectedTemplate); } catch (err) { console.error("获取模板列表失败:", err); } finally { setIsLoading(false); } }, [templateStoryUseCase]); /** * 更新指定角色的图片 * @param {string} roleName - 角色名称 * @param {string} imageUrl - 新的图片URL */ const updateRoleImage = useCallback( (roleName: string, imageUrl: string): void => { if (!selectedTemplate) { console.warn("updateRoleImage: selectedTemplate 为空"); return; } console.log(`更新角色 ${roleName} 的图片:`, imageUrl); const updatedTemplate = { ...selectedTemplate, storyRole: selectedTemplate.storyRole.map((role) => role.role_name === roleName ? { ...role, photo_url: imageUrl } : role ), }; console.log("更新后的模板:", updatedTemplate); setSelectedTemplate(updatedTemplate); }, [selectedTemplate] ); /** * 更新指定道具的图片 * @param {string} itemName - 道具名称 * @param {string} imageUrl - 新的图片URL */ const updateItemImage = useCallback( (itemName: string, imageUrl: string): void => { if (!selectedTemplate) { console.warn("updateItemImage: selectedTemplate 为空"); return; } console.log(`更新道具 ${itemName} 的图片:`, imageUrl); const updatedTemplate = { ...selectedTemplate, storyItem: selectedTemplate.storyItem.map((item) => item.item_name === itemName ? { ...item, photo_url: imageUrl } : item ), }; console.log("更新后的模板:", updatedTemplate); setSelectedTemplate(updatedTemplate); }, [selectedTemplate] ); /** * 上传人物头像并分析特征,替换旧的角色数据 * @param {string} imageUrl - 图片URL * @param {string} roleName - 角色名称 */ const AvatarAndAnalyzeFeatures = useCallback( async (imageUrl: string, roleName: string): Promise => { try { setIsLoading(true); // 直接更新指定角色的图片 updateRoleImage(roleName, imageUrl); } catch (error) { console.error("人物头像上传和特征分析失败:", error); throw error; } finally { setIsLoading(false); } }, [updateRoleImage] ); /** * 带防抖的失焦处理函数 - 角色图片生成 * @param {string} roleName - 角色名称 * @param {string} fieldValue - 字段值 */ const handleRoleFieldBlur = useCallback( debounce(async (roleName: string, fieldValue: string): Promise => { try { // 设置 loading 状态 setIsLoading(true); // 调用图片生成接口 const result = await generateTextToImage({ description: fieldValue }); if (result.successful && result.data?.image_url) { // 更新对应角色的图片 updateRoleImage(roleName, result.data.image_url); console.log(`角色 ${roleName} 图片生成成功:`, result.data.image_url); } else { console.error(`角色 ${roleName} 图片生成失败:`, result.message); } } catch (error) { console.error(`角色 ${roleName} 处理失败:`, error); } finally { // 清除 loading 状态 setIsLoading(false); } }, 500), [updateRoleImage, setIsLoading] ); /** * 带防抖的失焦处理函数 - 道具图片生成 * @param {string} itemName - 道具名称 * @param {string} fieldValue - 字段值 */ const handleItemFieldBlur = useCallback( debounce(async (itemName: string, fieldValue: string): Promise => { try { // 设置 loading 状态 setIsLoading(true); // 调用图片生成接口 const result = await generateTextToImage({ description: fieldValue }); if (result.successful && result.data?.image_url) { // 更新对应道具的图片 updateItemImage(itemName, result.data.image_url); console.log(`道具 ${itemName} 图片生成成功:`, result.data.image_url); } else { console.error(`道具 ${itemName} 图片生成失败:`, result.message); } } catch (error) { console.error(`道具 ${itemName} 处理失败:`, error); } finally { // 清除 loading 状态 setIsLoading(false); } }, 500), [updateItemImage, setIsLoading] ); const actionStory = useCallback( async ( user_id: string, mode: "auto" | "manual" = "auto", resolution: "720p" | "1080p" | "4k" = "720p", language: string = "English" ) => { console.log('selectedTemplate', selectedTemplate) try { // 设置 loading 状态 setIsLoading(true); const params: CreateMovieProjectV3Request = { script: selectedTemplate?.generateText || "", category: selectedTemplate?.category || "", user_id, mode, resolution, storyRole: selectedTemplate?.storyRole || [], storyItem: selectedTemplate?.storyItem || [], language, template_id: selectedTemplate?.template_id || "", }; console.log("params", params); const result = await MovieProjectService.createProject( MovieProjectMode.TEMPLATE, params ); return result.project_id; } catch (error) { console.error("创建电影项目失败:", error); } finally { // 清除 loading 状态 setIsLoading(false); } }, [selectedTemplate] ); return { templateStoryList, selectedTemplate, isLoading, getTemplateStoryList, actionStory, setSelectedTemplate, AvatarAndAnalyzeFeatures, updateRoleImage, updateItemImage, handleRoleFieldBlur, handleItemFieldBlur, clearData: () => { setTemplateStoryList([]); setSelectedTemplate(null); }, }; };