video-flow-b/app/service/Interaction/ImageStoryService.ts
2025-08-16 21:38:05 +08:00

161 lines
4.6 KiB
TypeScript

import { ImageStoryEntity } from "../domain/Entities";
import { ImageStoryUseCase } from "../usecase/imageStoryUseCase";
import { useState, useCallback, useMemo } from "react";
interface UseImageStoryService {
/** 当前图片故事数据 */
imageStory: Partial<ImageStoryEntity>;
/** 当前活跃的图片地址 */
activeImageUrl: string;
/** 当前活跃的文本信息 */
activeTextContent: string;
/** 当前选中的分类 */
selectedCategory: string;
/** 是否正在分析图片 */
isAnalyzing: boolean;
/** 是否正在上传 */
isUploading: boolean;
/** 故事类型选项 */
storyTypeOptions: Array<{ key: string; label: string }>;
/** 上传图片并分析 */
uploadAndAnalyzeImage: (imageUrl: string) => Promise<void>;
/** 触发生成剧本函数 */
generateScript: () => Promise<string>;
/** 更新故事类型 */
updateStoryType: (storyType: string) => void;
/** 更新故事内容 */
updateStoryContent: (content: string) => void;
/** 重置图片故事数据 */
resetImageStory: () => void;
}
export const useImageStoryServiceHook = (): UseImageStoryService => {
const [imageStory, setImageStory] = useState<Partial<ImageStoryEntity>>({
imageUrl: "",
imageStory: "",
storyType: "auto",
});
const [isAnalyzing, setIsAnalyzing] = useState(false);
const [isUploading, setIsUploading] = useState(false);
/** 图片故事用例实例 */
const imageStoryUseCase = useMemo(() => new ImageStoryUseCase(), []);
/** 当前活跃的图片地址 */
const activeImageUrl = imageStory.imageUrl || "";
/** 当前活跃的文本信息 */
const activeTextContent = imageStory.imageStory || "";
/** 当前选中的分类 */
const selectedCategory = imageStory.storyType || "auto";
/** 故事类型选项 */
const storyTypeOptions = useMemo(() => imageStoryUseCase.getStoryTypeOptions(), [imageStoryUseCase]);
/**
* 上传图片并分析
* @param {string} imageUrl - 已上传的图片URL
*/
const uploadAndAnalyzeImage = useCallback(async (imageUrl: string): Promise<void> => {
try {
setIsUploading(true);
setIsAnalyzing(true);
// 调用用例处理图片上传和分析
await imageStoryUseCase.handleImageUpload(imageUrl);
// 获取更新后的数据
const updatedStory = imageStoryUseCase.getImageStory();
setImageStory(updatedStory);
} catch (error) {
console.error('图片上传分析失败:', error);
throw error;
} finally {
setIsUploading(false);
setIsAnalyzing(false);
}
}, [imageStoryUseCase]);
/**
* 触发生成剧本函数
* @returns {Promise<string>} 生成的剧本ID或内容
*/
const generateScript = useCallback(async (): Promise<string> => {
if (!activeImageUrl) {
throw new Error('请先上传图片');
}
if (!activeTextContent) {
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, activeTextContent, imageStory]);
/**
* 更新故事类型
* @param {string} storyType - 新的故事类型
*/
const updateStoryType = useCallback((storyType: string): void => {
imageStoryUseCase.updateStoryType(storyType);
setImageStory(prev => ({ ...prev, storyType }));
}, [imageStoryUseCase]);
/**
* 更新故事内容
* @param {string} content - 新的故事内容
*/
const updateStoryContent = useCallback((content: string): void => {
imageStoryUseCase.updateStoryContent(content);
setImageStory(prev => ({ ...prev, imageStory: content }));
}, [imageStoryUseCase]);
/**
* 重置图片故事数据
*/
const resetImageStory = useCallback((): void => {
imageStoryUseCase.resetImageStory();
setImageStory({
imageUrl: "",
imageStory: "",
storyType: "auto",
});
setIsAnalyzing(false);
setIsUploading(false);
}, [imageStoryUseCase]);
return {
imageStory,
activeImageUrl,
activeTextContent,
selectedCategory,
isAnalyzing,
isUploading,
storyTypeOptions,
uploadAndAnalyzeImage,
generateScript,
updateStoryType,
updateStoryContent,
resetImageStory,
};
};