diff --git a/components/pages/work-flow/use-edit-data.tsx b/components/pages/work-flow/use-edit-data.tsx index ed0871a..70dcf28 100644 --- a/components/pages/work-flow/use-edit-data.tsx +++ b/components/pages/work-flow/use-edit-data.tsx @@ -43,6 +43,7 @@ export const useEditData = (tabType: string, originalText?: string) => { regenerateRole, uploadImageAndUpdateRole, saveRoleToLibrary, + changeTabCallback, } = useRoleServiceHook(); const { @@ -134,6 +135,7 @@ export const useEditData = (tabType: string, originalText?: string) => { regenerateRole, fetchUserRoleLibrary, uploadImageAndUpdateRole, + changeTabCallback, // role shot shotSelectionList, selectedRoleId, diff --git a/components/ui/character-tab-content.tsx b/components/ui/character-tab-content.tsx index 918886a..c340f33 100644 --- a/components/ui/character-tab-content.tsx +++ b/components/ui/character-tab-content.tsx @@ -1,4 +1,4 @@ -import React, { useState, useRef, useEffect } from 'react'; +import React, { useState, useRef, useEffect, forwardRef } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { ImageUp, Library, Play, Pause, RefreshCw, Wand2, Users, CircleX, ReplaceAll, X, TriangleAlert, Loader2 } from 'lucide-react'; import { cn } from '@/public/lib/utils'; @@ -35,18 +35,17 @@ interface Role { interface CharacterTabContentProps { - taskSketch: any[]; - currentRoleIndex: number; - onSketchSelect: (index: number) => void; - roles: Role[]; + onClose: () => void; + onApply: () => void; + setActiveTab: (tabId: string) => void; } -export function CharacterTabContent({ - taskSketch, - currentRoleIndex, - onSketchSelect, - roles = [] -}: CharacterTabContentProps) { + +export const CharacterTabContent = forwardRef< + { switchBefore: (tabId: string) => boolean, saveBefore: () => void }, +CharacterTabContentProps +>((props, ref) => { + const { onClose, onApply, setActiveTab } = props; const [isReplacePanelOpen, setIsReplacePanelOpen] = useState(false); const [replacePanelKey, setReplacePanelKey] = useState(0); const [ignoreReplace, setIgnoreReplace] = useState(false); @@ -61,6 +60,10 @@ export function CharacterTabContent({ const [isLoadingShots, setIsLoadingShots] = useState(false); const [isLoadingLibrary, setIsLoadingLibrary] = useState(false); const [isUploading, setIsUploading] = useState(false); + const [isUpdate, setIsUpdate] = useState(false); + const [triggerType, setTriggerType] = useState<'tab' | 'apply' | 'user'>('tab'); + const [nextToTabId, setNextToTabId] = useState(''); + const [nextToUserIndex, setNextToUserIndex] = useState(-1); const { loading, @@ -73,6 +76,7 @@ export function CharacterTabContent({ regenerateRole, fetchUserRoleLibrary, uploadImageAndUpdateRole, + changeTabCallback, // role shot shotSelectionList, fetchRoleShots, @@ -82,6 +86,31 @@ export function CharacterTabContent({ const searchParams = useSearchParams(); const episodeId = searchParams.get('episodeId'); + // 暴露方法给父组件 + React.useImperativeHandle(ref, () => ({ + switchBefore: (tabId: string) => { + setNextToTabId(tabId); + // 判断 角色是否修改 + const isChange = selectedRole!.isChangeRole + console.log('switchBefore', isChange); + if (isChange) { + setTriggerType('tab'); + setIsRemindReplacePanelOpen(true); + } + return isChange; + }, + saveBefore: () => { + console.log('saveBefore'); + // 判断 角色是否修改 + changeTabCallback((isChange: Boolean) => { + if (isChange) { + setTriggerType('apply'); + handleStartReplaceCharacter(); + } + }); + } + })); + useEffect(() => { console.log('-==========roleData===========-', roleData); @@ -116,24 +145,32 @@ export function CharacterTabContent({ const handleConfirmGotoReplace = () => { setIsRemindReplacePanelOpen(false); - setIsReplacePanelOpen(true); + handleStartReplaceCharacter(); }; const handleCloseRemindReplacePanel = () => { setIsRemindReplacePanelOpen(false); - setIgnoreReplace(true); + console.log('忽略替换', triggerType, nextToTabId, nextToUserIndex); + if (triggerType === 'apply') { + onClose(); + } else if (triggerType === 'tab') { + setActiveTab(nextToTabId); + } else { + selectRole(roleData[nextToUserIndex]); + } }; // President Alfred King Samuel Ryan - const handleConfirmReplace = (selectedShots: string[], addToLibrary: boolean) => { + const handleConfirmReplace = async (selectedShots: string[], addToLibrary: boolean) => { // 处理替换确认逻辑 console.log('Selected shots:', selectedShots); console.log('Add to library:', addToLibrary); - applyRoleToSelectedShots(selectedRole || {} as RoleEntity); + await applyRoleToSelectedShots(selectedRole || {} as RoleEntity); setIsReplacePanelOpen(false); if(addToLibrary){ saveRoleToLibrary(); } + onApply(); }; // 取消替换 @@ -143,18 +180,22 @@ export function CharacterTabContent({ const handleChangeRole = (index: number) => { const oldRole = roleData.find(role => role.id === selectedRole?.id); - console.log('切换角色前对比', selectedRole?.imageUrl, oldRole?.imageUrl); - if (selectedRole?.imageUrl !== oldRole?.imageUrl && !ignoreReplace) { - // 提示 角色已修改,弹出替换角色面板 - setIsRemindReplacePanelOpen(true); - return; - } - // 重置替换规则 - setEnableAnimation(false); - setIgnoreReplace(false); - setIsRegenerate(false); + console.log('切换角色前对比'); + changeTabCallback((isChange: Boolean) => { + if (isChange) { + setTriggerType('user'); + setIsRemindReplacePanelOpen(true); + setNextToUserIndex(index); + return; + } - selectRole(roleData[index]); + // 重置替换规则 + setEnableAnimation(false); + setIgnoreReplace(false); + setIsRegenerate(false); + + selectRole(roleData[index]); + }); }; // 从角色库中选择角色 @@ -172,7 +213,7 @@ export function CharacterTabContent({ ...role, name: selectedRole?.name || '' }); - handleStartReplaceCharacter(); + // handleStartReplaceCharacter(); } }; @@ -194,7 +235,7 @@ export function CharacterTabContent({ // 然后调用重新生成角色 await regenerateRole(); setIsRegenerate(false); - handleStartReplaceCharacter(); + // handleStartReplaceCharacter(); }; const handleUploadClick = () => { @@ -347,17 +388,7 @@ export function CharacterTabContent({ onUpdateText={(text: string) => updateRoleText(text)} /> {/* 重新生成按钮、替换形象按钮 */} -
- handleStartReplaceCharacter()} - className="flex items-center justify-center gap-2 px-4 py-3 bg-pink-500/10 hover:bg-pink-500/20 - text-pink-500 rounded-lg transition-colors" - whileHover={{ scale: 1.02 }} - whileTap={{ scale: 0.98 }} - > - - Replace - +
handleRegenerate()} className="flex items-center justify-center gap-2 px-4 py-3 bg-blue-500/10 hover:bg-blue-500/20 @@ -410,7 +441,7 @@ export function CharacterTabContent({
-

角色已修改,是否需要替换?

+

角色已修改,不替换就会丢失修改,是否需要替换?

@@ -436,4 +467,4 @@ export function CharacterTabContent({
); -} +}); diff --git a/components/ui/edit-modal.tsx b/components/ui/edit-modal.tsx index f13048f..5399d94 100644 --- a/components/ui/edit-modal.tsx +++ b/components/ui/edit-modal.tsx @@ -66,6 +66,7 @@ export function EditModal({ const [resetKey, setResetKey] = useState(0); const [remindFallbackText, setRemindFallbackText] = useState('The task will be regenerated and edited. Do you want to continue?'); const scriptTabContentRef = useRef(null); + const characterTabContentRef = useRef(null); // 添加一个状态来标记是否是从切换tab触发的提醒 const [pendingSwitchTabId, setPendingSwitchTabId] = useState(null); @@ -97,11 +98,16 @@ const [pendingSwitchTabId, setPendingSwitchTabId] = useState(null } const checkUpdate = (tabId: string) => { - if (tabId === '0') { + if (activeTab === '0') { const scriptTabContent = scriptTabContentRef.current; if (scriptTabContent) { return scriptTabContent.checkUpdate(); } + } else if (activeTab === '1') { + const characterTabContent = characterTabContentRef.current; + if (characterTabContent) { + return characterTabContent.switchBefore(tabId); + } } return false; } @@ -109,11 +115,11 @@ const [pendingSwitchTabId, setPendingSwitchTabId] = useState(null const handleChangeTab = (tabId: string, disabled: boolean) => { if (disabled) return; // 切换前 检查是否更新 - const isUpdate = checkUpdate(activeTab); + const isUpdate = checkUpdate(tabId); if (isUpdate) { - setPendingSwitchTabId(tabId); // 记录要切换到的目标tab - setRemindFallbackText('You must click Apply button to save the current changes.'); - setIsRemindFallbackOpen(true); + // setPendingSwitchTabId(tabId); // 记录要切换到的目标tab + // setRemindFallbackText('You must click Apply button to save the current changes.'); + // setIsRemindFallbackOpen(true); return; } setActiveTab(tabId); @@ -122,7 +128,15 @@ const [pendingSwitchTabId, setPendingSwitchTabId] = useState(null const handleSave = () => { console.log('handleSave'); - setIsRemindFallbackOpen(true); + // setIsRemindFallbackOpen(true); + if (activeTab === '1') { + characterTabContentRef.current.saveBefore(); + } + } + + const handleApply = () => { + console.log('handleApply'); + handleConfirmGotoFallback(); } const handleConfirmGotoFallback = () => { @@ -174,10 +188,10 @@ const [pendingSwitchTabId, setPendingSwitchTabId] = useState(null case '1': return ( ); case '2':