import { useState, useCallback, useMemo } from 'react'; import { SceneEntity, TagEntity, AITextEntity, ShotEntity } from '../domain/Entities'; import { SceneItem, TagItem, TextItem, ShotItem } from '../domain/Item'; import { SceneEditUseCase } from '../usecase/SceneEditUseCase'; import { TagEditUseCase } from '../usecase/TagEditUseCase'; import { TextEditUseCase } from '../usecase/TextEditUseCase'; import { getSceneShots } from '@/api/video_flow'; /** * 分镜选择项接口 */ interface ShotSelectionItem { /** 分镜ID */ id: string; /** 分镜名称 */ name: string; /** 是否已选中 */ selected: boolean; /** 是否已应用场景 */ applied: boolean; /** 分镜数据 */ shot: ShotEntity; } /** * 场景服务Hook返回值接口 */ interface UseSceneService { // 响应式数据 /** 场景列表 */ sceneList: SceneItem[]; /** 当前选中的场景 */ selectedScene: SceneItem | null; /** 当前场景的AI文本 */ currentSceneText: TextItem | null; /** 当前场景的标签列表 */ currentSceneTags: TagItem[]; /** 场景图片URL */ sceneImageUrl: string; /** 分镜选择列表 */ shotSelectionList: ShotSelectionItem[]; /** 是否全选分镜 */ isAllShotsSelected: boolean; /** 已选中的分镜数量 */ selectedShotsCount: number; // 操作方法 /** 选择场景 */ selectScene: (sceneId: string) => void; /** 设置当前场景的AI文本和标签 */ setCurrentSceneData: (text: TextItem, tags: TagItem[]) => void; /** 优化AI文本 */ optimizeSceneText: () => Promise; /** 修改AI文本 */ updateSceneText: (newContent: string) => Promise; /** 修改标签内容 */ updateTagContent: (tagId: string, newContent: string | number) => Promise; /** 重新生成场景 */ regenerateScene: () => Promise; /** 获取场景出现的分镜列表 */ fetchSceneShots: () => Promise; /** 切换全选与全不选 */ toggleSelectAllShots: () => void; /** 选择/取消选择单个分镜 */ toggleShotSelection: (shotId: string) => void; /** 应用场景到选中的分镜 */ applySceneToSelectedShots: () => Promise; } /** * 场景服务Hook * 提供场景相关的所有响应式功能和业务逻辑 */ export const useSceneServiceHook = (): UseSceneService => { // 响应式状态 const [sceneList, setSceneList] = useState([]); const [selectedScene, setSelectedScene] = useState(null); const [currentSceneText, setCurrentSceneText] = useState(null); const [currentSceneTags, setCurrentSceneTags] = useState([]); const [shotSelectionList, setShotSelectionList] = useState([]); // UseCase实例 - 在场景选择时初始化 const [sceneEditUseCase, setSceneEditUseCase] = useState(null); const [textEditUseCase, setTextEditUseCase] = useState(null); const [tagEditUseCases, setTagEditUseCases] = useState>(new Map()); // 计算属性 const sceneImageUrl = useMemo(() => { return selectedScene?.entity.imageUrl || ''; }, [selectedScene]); const isAllShotsSelected = useMemo(() => { return shotSelectionList.length > 0 && shotSelectionList.every(shot => shot.selected); }, [shotSelectionList]); const selectedShotsCount = useMemo(() => { return shotSelectionList.filter(shot => shot.selected).length; }, [shotSelectionList]); // 选择场景 const selectScene = useCallback((sceneId: string) => { const scene = sceneList.find(s => s.entity.id === sceneId); if (scene) { setSelectedScene(scene); setSceneEditUseCase(new SceneEditUseCase(scene)); setTextEditUseCase(null); setTagEditUseCases(new Map()); setCurrentSceneText(null); setCurrentSceneTags([]); } }, [sceneList]); // 设置当前场景数据 const setCurrentSceneData = useCallback((text: TextItem, tags: TagItem[]) => { setCurrentSceneText(text); setCurrentSceneTags(tags); if (text) { setTextEditUseCase(new TextEditUseCase(text)); } const newTagEditUseCases = new Map(); tags.forEach(tag => { newTagEditUseCases.set(tag.entity.id, new TagEditUseCase(tag)); }); setTagEditUseCases(newTagEditUseCases); }, []); // 优化AI文本 const optimizeSceneText = useCallback(async () => { if (!textEditUseCase) { throw new Error('文本编辑UseCase未初始化'); } if (!currentSceneText || !currentSceneText.entity.content) { throw new Error('没有可优化的文本内容'); } const optimizedContent = await textEditUseCase.getOptimizedContent(); const updatedTextItem = await textEditUseCase.updateText(optimizedContent); setCurrentSceneText(updatedTextItem); }, [textEditUseCase, currentSceneText]); // 修改AI文本 const updateSceneText = useCallback(async (newContent: string) => { if (!textEditUseCase) { throw new Error('文本编辑UseCase未初始化'); } if (!currentSceneText) { throw new Error('没有可编辑的文本'); } const updatedTextItem = await textEditUseCase.updateText(newContent); setCurrentSceneText(updatedTextItem); }, [textEditUseCase, currentSceneText]); // 修改标签内容 const updateTagContent = useCallback(async (tagId: string, newContent: string | number) => { const tagEditUseCase = tagEditUseCases.get(tagId); if (!tagEditUseCase) { throw new Error(`标签编辑UseCase未初始化,标签ID: ${tagId}`); } const updatedTagItem = await tagEditUseCase.updateTag(newContent); setCurrentSceneTags(prev => prev.map(tag => tag.entity.id === tagId ? updatedTagItem : tag ) ); }, [tagEditUseCases]); // 重新生成场景 const regenerateScene = useCallback(async () => { if (!sceneEditUseCase) { throw new Error('场景编辑UseCase未初始化'); } if (!selectedScene || !currentSceneText || currentSceneTags.length === 0) { throw new Error('缺少重新生成场景所需的数据'); } const newSceneEntity = await sceneEditUseCase.AIgenerateScene(currentSceneText, currentSceneTags); const newSceneItem = new SceneItem(newSceneEntity); setSelectedScene(newSceneItem); setSceneList(prev => prev.map(scene => scene.entity.id === newSceneEntity.id ? newSceneItem : scene ) ); }, [sceneEditUseCase, selectedScene, currentSceneText, currentSceneTags]); // 获取场景分镜列表 const fetchSceneShots = useCallback(async () => { if (!selectedScene) { throw new Error('请先选择场景'); } try { const response = await getSceneShots({ sceneId: selectedScene.entity.id }); if (response.successful) { const { shots, appliedShotIds } = response.data; const shotSelectionItems: ShotSelectionItem[] = shots.map(shot => ({ id: shot.id, name: shot.name, selected: false, applied: appliedShotIds.includes(shot.id), shot })); setShotSelectionList(shotSelectionItems); } else { throw new Error(`获取场景分镜列表失败: ${response.message}`); } } catch (error) { console.error('获取场景分镜列表失败:', error); throw error; } }, [selectedScene]); // 切换全选与全不选 const toggleSelectAllShots = useCallback(() => { setShotSelectionList(prev => { const isAllSelected = prev.length > 0 && prev.every(shot => shot.selected); return prev.map(shot => ({ ...shot, selected: !isAllSelected })); }); }, []); // 选择/取消选择单个分镜 const toggleShotSelection = useCallback((shotId: string) => { setShotSelectionList(prev => prev.map(shot => shot.id === shotId ? { ...shot, selected: !shot.selected } : shot ) ); }, []); // 应用场景到选中的分镜 const applySceneToSelectedShots = useCallback(async () => { if (!sceneEditUseCase) { throw new Error('场景编辑UseCase未初始化'); } if (!selectedScene) { throw new Error('请先选择场景'); } const selectedShotIds = shotSelectionList .filter(shot => shot.selected) .map(shot => shot.id); if (selectedShotIds.length === 0) { throw new Error('请先选择要应用的分镜'); } await sceneEditUseCase.applyScene(selectedShotIds); setShotSelectionList(prev => prev.map(shot => selectedShotIds.includes(shot.id) ? { ...shot, applied: true, selected: false } : shot ) ); }, [sceneEditUseCase, selectedScene, shotSelectionList]); return { // 响应式数据 sceneList, selectedScene, currentSceneText, currentSceneTags, sceneImageUrl, shotSelectionList, isAllShotsSelected, selectedShotsCount, // 操作方法 selectScene, setCurrentSceneData, optimizeSceneText, updateSceneText, updateTagContent, regenerateScene, fetchSceneShots, toggleSelectAllShots, toggleShotSelection, applySceneToSelectedShots }; };