add saving

This commit is contained in:
songtianlun 2025-07-30 22:29:46 +08:00
parent 7ccd6e80ca
commit d1207f0541
2 changed files with 110 additions and 2 deletions

View File

@ -10,6 +10,7 @@ import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label' import { Label } from '@/components/ui/label'
import { Textarea } from '@/components/ui/textarea' import { Textarea } from '@/components/ui/textarea'
import { LoadingSpinner } from '@/components/ui/loading-spinner' import { LoadingSpinner } from '@/components/ui/loading-spinner'
import { FullScreenLoading } from '@/components/ui/full-screen-loading'
import { VersionTimeline, VersionTimelineRef } from '@/components/studio/VersionTimeline' import { VersionTimeline, VersionTimelineRef } from '@/components/studio/VersionTimeline'
import { import {
Play, Play,
@ -70,6 +71,10 @@ export default function PromptPage({ params }: PromptPageProps) {
const [originalTitle, setOriginalTitle] = useState('') const [originalTitle, setOriginalTitle] = useState('')
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false) const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false)
const [isDuplicating, setIsDuplicating] = useState(false) const [isDuplicating, setIsDuplicating] = useState(false)
const [fullScreenLoading, setFullScreenLoading] = useState({
isVisible: false,
message: ''
})
const versionTimelineRef = useRef<VersionTimelineRef>(null) const versionTimelineRef = useRef<VersionTimelineRef>(null)
useEffect(() => { useEffect(() => {
@ -163,6 +168,11 @@ export default function PromptPage({ params }: PromptPageProps) {
if (!user || !promptId) return if (!user || !promptId) return
setIsSaving(true) setIsSaving(true)
setFullScreenLoading({
isVisible: true,
message: '正在保存提示词...'
})
try { try {
const response = await fetch(`/api/prompts/${promptId}`, { const response = await fetch(`/api/prompts/${promptId}`, {
method: 'PUT', method: 'PUT',
@ -198,6 +208,10 @@ export default function PromptPage({ params }: PromptPageProps) {
console.error('Failed to save prompt:', error) console.error('Failed to save prompt:', error)
} finally { } finally {
setIsSaving(false) setIsSaving(false)
setFullScreenLoading({
isVisible: false,
message: ''
})
} }
} }
@ -249,6 +263,11 @@ export default function PromptPage({ params }: PromptPageProps) {
if (!user || !prompt) return if (!user || !prompt) return
setIsDuplicating(true) setIsDuplicating(true)
setFullScreenLoading({
isVisible: true,
message: '正在复制提示词...'
})
try { try {
// 创建新的prompt使用当前显示的内容 // 创建新的prompt使用当前显示的内容
const duplicatedPrompt = { const duplicatedPrompt = {
@ -267,13 +286,30 @@ export default function PromptPage({ params }: PromptPageProps) {
if (response.ok) { if (response.ok) {
const newPrompt = await response.json() const newPrompt = await response.json()
// 跳转到新创建的prompt页面
router.push(`/studio/${newPrompt.id}`) // 先隐藏加载遮罩,然后跳转
setFullScreenLoading({
isVisible: false,
message: ''
})
// 延迟跳转以确保遮罩动画完成
setTimeout(() => {
router.push(`/studio/${newPrompt.id}`)
}, 300)
} else { } else {
console.error('Failed to duplicate prompt') console.error('Failed to duplicate prompt')
setFullScreenLoading({
isVisible: false,
message: ''
})
} }
} catch (error) { } catch (error) {
console.error('Error duplicating prompt:', error) console.error('Error duplicating prompt:', error)
setFullScreenLoading({
isVisible: false,
message: ''
})
} finally { } finally {
setIsDuplicating(false) setIsDuplicating(false)
} }
@ -553,6 +589,12 @@ export default function PromptPage({ params }: PromptPageProps) {
</div> </div>
</div> </div>
</div> </div>
{/* Full Screen Loading */}
<FullScreenLoading
isVisible={fullScreenLoading.isVisible}
message={fullScreenLoading.message}
/>
</div> </div>
) )
} }

View File

@ -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 (
<div className={cn(
"fixed inset-0 z-[9999] flex items-center justify-center",
"bg-black/50 backdrop-blur-sm",
"animate-in fade-in duration-200"
)}>
<div className={cn(
"bg-background rounded-lg border border-border shadow-2xl",
"p-8 mx-4 max-w-sm w-full",
"animate-in zoom-in-95 duration-200"
)}>
<div className="flex flex-col items-center space-y-4">
<LoadingSpinner size="lg" />
<div className="text-center">
<p className="text-foreground font-medium">{message}</p>
<p className="text-sm text-muted-foreground mt-1">
...
</p>
</div>
</div>
</div>
</div>
)
}
export default FullScreenLoading