better studio debugger loading

This commit is contained in:
songtianlun 2025-08-03 09:59:49 +08:00
parent f0d9797cac
commit 5a7aedf11b

View File

@ -10,7 +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 { LoadingRing } from '@/components/ui/loading-ring'
import { VersionTimeline, VersionTimelineRef } from '@/components/studio/VersionTimeline'
import { PermissionToggle } from '@/components/studio/PermissionToggle'
import {
@ -71,10 +71,6 @@ 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<VersionTimelineRef>(null)
useEffect(() => {
@ -164,10 +160,6 @@ export default function PromptPage({ params }: PromptPageProps) {
if (!user || !promptId) return
setIsSaving(true)
setFullScreenLoading({
isVisible: true,
message: '正在保存提示词...'
})
try {
const response = await fetch(`/api/prompts/${promptId}`, {
@ -204,10 +196,6 @@ export default function PromptPage({ params }: PromptPageProps) {
console.error('Failed to save prompt:', error)
} finally {
setIsSaving(false)
setFullScreenLoading({
isVisible: false,
message: ''
})
}
}
@ -269,10 +257,6 @@ export default function PromptPage({ params }: PromptPageProps) {
if (!user || !prompt) return
setIsDuplicating(true)
setFullScreenLoading({
isVisible: true,
message: '正在复制提示词...'
})
try {
// 创建新的prompt使用当前显示的内容
@ -292,40 +276,22 @@ export default function PromptPage({ params }: PromptPageProps) {
if (response.ok) {
const newPrompt = await response.json()
// 先隐藏加载遮罩,然后跳转
setFullScreenLoading({
isVisible: false,
message: ''
})
// 延迟跳转以确保遮罩动画完成
setTimeout(() => {
router.push(`/studio/${newPrompt.id}`)
}, 300)
router.push(`/studio/${newPrompt.id}`)
} 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)
}
}
if (loading || isLoading) {
return <FullScreenLoading isVisible={true} message={t('loadingStudio')} />
if (loading) {
return null
}
if (!user || !prompt) {
if (!user) {
return null
}
@ -352,8 +318,17 @@ export default function PromptPage({ params }: PromptPageProps) {
<div className="flex items-center space-x-2">
<FileText className="h-5 w-5 text-muted-foreground" />
<div>
<h1 className="font-semibold text-foreground">{prompt?.name || 'Loading...'}</h1>
<p className="text-xs text-muted-foreground">Version {prompt?.currentVersion || 1} {prompt?.usage || 0} uses</p>
{isLoading ? (
<div className="flex items-center space-x-2">
<LoadingRing size="sm" />
<span className="text-muted-foreground">Loading...</span>
</div>
) : (
<>
<h1 className="font-semibold text-foreground">{prompt?.name || 'Loading...'}</h1>
<p className="text-xs text-muted-foreground">Version {prompt?.currentVersion || 1} {prompt?.usage || 0} uses</p>
</>
)}
</div>
</div>
</div>
@ -381,46 +356,61 @@ export default function PromptPage({ params }: PromptPageProps) {
</div>
<div className="max-w-7xl mx-auto p-4">
{/* Mobile Layout (stacked) */}
<div className="lg:hidden space-y-6">
{/* 1. Prompt Editor (Mobile First) */}
<div className="bg-card rounded-lg border border-border">
<div className="p-4 border-b border-border">
<div className="flex items-center justify-between">
<h3 className="font-semibold text-foreground">{t('promptEditor')}</h3>
<div className="flex items-center space-x-1 text-xs text-muted-foreground">
<span>{promptContent.length} characters</span>
</div>
</div>
</div>
<div className="p-4">
<div className="space-y-4">
<div>
<Label htmlFor="promptTitle" className="text-sm font-medium">
{t('promptName')}
</Label>
<Input
id="promptTitle"
value={promptTitle}
onChange={(e) => setPromptTitle(e.target.value)}
className="mt-1"
/>
</div>
<div>
<Label htmlFor="promptContent" className="text-sm font-medium">
{t('promptContent')}
</Label>
<Textarea
id="promptContent"
value={promptContent}
onChange={(e) => setPromptContent(e.target.value)}
className="mt-1 min-h-[300px] font-mono text-sm resize-none"
placeholder="Write your prompt here..."
/>
</div>
</div>
{isLoading ? (
/* Loading State */
<div className="flex items-center justify-center py-16">
<div className="text-center">
<LoadingRing size="lg" className="mb-4" />
<p className="text-muted-foreground">{t('loadingStudio')}</p>
</div>
</div>
) : !prompt ? (
/* No Prompt State */
<div className="text-center py-16">
<p className="text-muted-foreground">Prompt not found</p>
</div>
) : (
<>
{/* Mobile Layout (stacked) */}
<div className="lg:hidden space-y-6">
{/* 1. Prompt Editor (Mobile First) */}
<div className="bg-card rounded-lg border border-border">
<div className="p-4 border-b border-border">
<div className="flex items-center justify-between">
<h3 className="font-semibold text-foreground">{t('promptEditor')}</h3>
<div className="flex items-center space-x-1 text-xs text-muted-foreground">
<span>{promptContent.length} characters</span>
</div>
</div>
</div>
<div className="p-4">
<div className="space-y-4">
<div>
<Label htmlFor="promptTitle" className="text-sm font-medium">
{t('promptName')}
</Label>
<Input
id="promptTitle"
value={promptTitle}
onChange={(e) => setPromptTitle(e.target.value)}
className="mt-1"
/>
</div>
<div>
<Label htmlFor="promptContent" className="text-sm font-medium">
{t('promptContent')}
</Label>
<Textarea
id="promptContent"
value={promptContent}
onChange={(e) => setPromptContent(e.target.value)}
className="mt-1 min-h-[300px] font-mono text-sm resize-none"
placeholder="Write your prompt here..."
/>
</div>
</div>
</div>
</div>
{/* Permissions (Mobile) */}
<PermissionToggle
@ -684,13 +674,9 @@ export default function PromptPage({ params }: PromptPageProps) {
</div>
</div>
</div>
</>
)}
</div>
{/* Full Screen Loading */}
<FullScreenLoading
isVisible={fullScreenLoading.isVisible}
message={fullScreenLoading.message}
/>
</div>
)
}