diff --git a/src/app/studio/[id]/page.tsx b/src/app/studio/[id]/page.tsx index 417778f..69e43b7 100644 --- a/src/app/studio/[id]/page.tsx +++ b/src/app/studio/[id]/page.tsx @@ -10,6 +10,7 @@ import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Textarea } from '@/components/ui/textarea' import { LoadingSpinner } from '@/components/ui/loading-spinner' +import { FullScreenLoading } from '@/components/ui/full-screen-loading' import { VersionTimeline, VersionTimelineRef } from '@/components/studio/VersionTimeline' import { Play, @@ -70,6 +71,10 @@ export default function PromptPage({ params }: PromptPageProps) { const [originalTitle, setOriginalTitle] = useState('') const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false) const [isDuplicating, setIsDuplicating] = useState(false) + const [fullScreenLoading, setFullScreenLoading] = useState({ + isVisible: false, + message: '' + }) const versionTimelineRef = useRef(null) useEffect(() => { @@ -163,6 +168,11 @@ export default function PromptPage({ params }: PromptPageProps) { if (!user || !promptId) return setIsSaving(true) + setFullScreenLoading({ + isVisible: true, + message: '正在保存提示词...' + }) + try { const response = await fetch(`/api/prompts/${promptId}`, { method: 'PUT', @@ -198,6 +208,10 @@ export default function PromptPage({ params }: PromptPageProps) { console.error('Failed to save prompt:', error) } finally { setIsSaving(false) + setFullScreenLoading({ + isVisible: false, + message: '' + }) } } @@ -249,6 +263,11 @@ export default function PromptPage({ params }: PromptPageProps) { if (!user || !prompt) return setIsDuplicating(true) + setFullScreenLoading({ + isVisible: true, + message: '正在复制提示词...' + }) + try { // 创建新的prompt,使用当前显示的内容 const duplicatedPrompt = { @@ -267,13 +286,30 @@ export default function PromptPage({ params }: PromptPageProps) { if (response.ok) { const newPrompt = await response.json() - // 跳转到新创建的prompt页面 - router.push(`/studio/${newPrompt.id}`) + + // 先隐藏加载遮罩,然后跳转 + setFullScreenLoading({ + isVisible: false, + message: '' + }) + + // 延迟跳转以确保遮罩动画完成 + setTimeout(() => { + router.push(`/studio/${newPrompt.id}`) + }, 300) } else { console.error('Failed to duplicate prompt') + setFullScreenLoading({ + isVisible: false, + message: '' + }) } } catch (error) { console.error('Error duplicating prompt:', error) + setFullScreenLoading({ + isVisible: false, + message: '' + }) } finally { setIsDuplicating(false) } @@ -553,6 +589,12 @@ export default function PromptPage({ params }: PromptPageProps) { + + {/* Full Screen Loading */} + ) } \ No newline at end of file diff --git a/src/components/ui/full-screen-loading.tsx b/src/components/ui/full-screen-loading.tsx new file mode 100644 index 0000000..01b3222 --- /dev/null +++ b/src/components/ui/full-screen-loading.tsx @@ -0,0 +1,66 @@ +'use client' + +import { useEffect } from 'react' +import { LoadingSpinner } from './loading-spinner' +import { cn } from '@/lib/utils' + +interface FullScreenLoadingProps { + isVisible: boolean + message?: string + onComplete?: () => void +} + +export function FullScreenLoading({ + isVisible, + message = '正在处理中...', + onComplete +}: FullScreenLoadingProps) { + // 禁止页面滚动 + useEffect(() => { + if (isVisible) { + document.body.style.overflow = 'hidden' + } else { + document.body.style.overflow = 'unset' + } + + return () => { + document.body.style.overflow = 'unset' + } + }, [isVisible]) + + // 自动调用完成回调 + useEffect(() => { + if (!isVisible && onComplete) { + const timer = setTimeout(onComplete, 300) // 等待退出动画完成 + return () => clearTimeout(timer) + } + }, [isVisible, onComplete]) + + if (!isVisible) return null + + return ( +
+
+
+ +
+

{message}

+

+ 请稍候... +

+
+
+
+
+ ) +} + +export default FullScreenLoading \ No newline at end of file