import { ImageStoryEntity } from "../domain/Entities"; import { useUploadFile } from "../domain/service"; import { ImageStoryUseCase } from "../usecase/imageStoryUseCase"; import { useState, useCallback, useMemo } from "react"; interface UseImageStoryService { /** 当前图片故事数据 */ imageStory: Partial; /** 当前活跃的图片地址 */ activeImageUrl: string; /** 分析故事结果内容 */ analyzedStoryContent: string; /** 当前选中的分类 */ selectedCategory: string; /** 是否正在分析图片 */ isAnalyzing: boolean; /** 是否正在上传 */ isUploading: boolean; /** 故事类型选项 */ storyTypeOptions: Array<{ key: string; label: string }>; /** 上传图片并分析 */ uploadAndAnalyzeImage: (imageUrl: string) => Promise; /** 触发文件选择并自动分析 */ triggerFileSelectionAndAnalyze: () => Promise; /** 触发生成剧本函数 */ generateScript: () => Promise; /** 更新故事类型 */ updateStoryType: (storyType: string) => void; /** 更新故事内容 */ updateStoryContent: (content: string) => void; /** 重置图片故事数据 */ resetImageStory: () => void; } export const useImageStoryServiceHook = ( ): UseImageStoryService => { const [imageStory, setImageStory] = useState>({ imageUrl: "", imageStory: "", storyType: "auto", }); const [isAnalyzing, setIsAnalyzing] = useState(false); const [isUploading, setIsUploading] = useState(false); // 使用上传文件Hook const { uploadFile } = useUploadFile(); /** 图片故事用例实例 */ const imageStoryUseCase = useMemo(() => new ImageStoryUseCase(), []); /** 当前活跃的图片地址 */ const [activeImageUrl, setActiveImageUrl] = useState(""); /** 分析故事结果内容 */ const [analyzedStoryContent, setAnalyzedStoryContent] = useState(""); /** 当前选中的分类 */ const [selectedCategory, setSelectedCategory] = useState("auto"); /** 故事类型选项 */ const storyTypeOptions = useMemo(() => imageStoryUseCase.getStoryTypeOptions(), [imageStoryUseCase]); /** * 上传图片并分析 * @param {string} imageUrl - 已上传的图片URL */ const uploadAndAnalyzeImage = useCallback(async (imageUrl: string): Promise => { try { setIsUploading(true); setIsAnalyzing(true); // 调用用例处理图片上传和分析 await imageStoryUseCase.handleImageUpload(imageUrl); // 获取更新后的数据 const updatedStory = imageStoryUseCase.getImageStory(); setImageStory(updatedStory); // 更新活跃状态 setActiveImageUrl(imageUrl); setAnalyzedStoryContent(updatedStory.imageStory || ""); setSelectedCategory(updatedStory.storyType || "auto"); } catch (error) { console.error('图片上传分析失败:', error); throw error; } finally { setIsUploading(false); setIsAnalyzing(false); } }, [imageStoryUseCase]); /** * 触发生成剧本函数 * @returns {Promise} 生成的剧本ID或内容 */ const generateScript = useCallback(async (): Promise => { if (!activeImageUrl) { throw new Error('请先上传图片'); } if (!analyzedStoryContent) { throw new Error('请先输入或生成故事内容'); } try { setIsAnalyzing(true); // 这里可以调用后端API生成剧本 // 暂时返回一个模拟的剧本ID const scriptId = `script_${Date.now()}`; // TODO: 实现实际的剧本生成逻辑 // const response = await generateScriptFromImage(imageStory); // return response.scriptId; return scriptId; } catch (error) { console.error('生成剧本失败:', error); throw error; } finally { setIsAnalyzing(false); } }, [activeImageUrl, analyzedStoryContent, imageStory]); /** * 更新故事类型 * @param {string} storyType - 新的故事类型 */ const updateStoryType = useCallback((storyType: string): void => { imageStoryUseCase.updateStoryType(storyType); setImageStory(prev => ({ ...prev, storyType })); setSelectedCategory(storyType); }, [imageStoryUseCase]); /** * 更新故事内容 * @param {string} content - 新的故事内容 */ const updateStoryContent = useCallback((content: string): void => { imageStoryUseCase.updateStoryContent(content); setImageStory(prev => ({ ...prev, imageStory: content })); setAnalyzedStoryContent(content); }, [imageStoryUseCase]); /** * 重置图片故事数据 */ const resetImageStory = useCallback((): void => { imageStoryUseCase.resetImageStory(); setImageStory({ imageUrl: "", imageStory: "", storyType: "auto", }); // 重置活跃状态 setActiveImageUrl(""); setAnalyzedStoryContent(""); setSelectedCategory("auto"); setIsAnalyzing(false); setIsUploading(false); }, [imageStoryUseCase]); /** * 触发文件选择并自动分析 */ const triggerFileSelectionAndAnalyze = useCallback(async (): Promise => { return new Promise((resolve, reject) => { // 创建文件输入元素 const fileInput = document.createElement("input"); fileInput.type = "file"; fileInput.accept = "image/*"; fileInput.style.display = "none"; fileInput.onchange = async (e) => { try { const target = e.target as HTMLInputElement; if (target.files && target.files[0]) { // 使用传入的文件上传函数 const uploadedImageUrl = await uploadFile(target.files[0], (progress) => { console.log("上传进度:", progress); }); console.log('uploadedImageUrl', uploadedImageUrl) // await uploadAndAnalyzeImage(uploadedImageUrl); setActiveImageUrl(uploadedImageUrl); } resolve(); } catch (error) { reject(error); } finally { // 清理DOM document.body.removeChild(fileInput); } }; fileInput.oncancel = () => { document.body.removeChild(fileInput); reject(); }; document.body.appendChild(fileInput); fileInput.click(); }); }, [uploadFile]); return { imageStory, activeImageUrl, analyzedStoryContent, selectedCategory, isAnalyzing, isUploading, storyTypeOptions, uploadAndAnalyzeImage, triggerFileSelectionAndAnalyze, generateScript, updateStoryType, updateStoryContent, resetImageStory, }; };