TaskDetails.vue 76.9 KB
Newer Older
LiangLiu's avatar
LiangLiu committed
1
<script setup>
LiangLiu's avatar
LiangLiu committed
2
import { ref, watch, onMounted, onUnmounted, computed, nextTick } from 'vue'
LiangLiu's avatar
LiangLiu committed
3
4
5
6
7
import { showTaskDetailModal,
        modalTask,
        closeTaskDetailModal,
        cancelTask,
        reuseTask,
LiangLiu's avatar
LiangLiu committed
8
        handleDownloadFile,
LiangLiu's avatar
LiangLiu committed
9
10
        deleteTask,
        getTaskTypeName,
LiangLiu's avatar
LiangLiu committed
11
        showFailureDetails,
LiangLiu's avatar
LiangLiu committed
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
        formatTime,
        getTaskStatusDisplay,
        getStatusTextClass,
        getProgressTitle,
        getProgressInfo,
        getOverallProgress,
        getSubtaskStatusText,
        getSubtaskProgress,
        formatEstimatedTime,
        generateShareUrl,
        copyShareLink,
        shareToSocial,
        copyPrompt,
        getTaskFileUrlSync,
        getTaskFileFromCache,
        getTaskFileUrl,
LiangLiu's avatar
LiangLiu committed
28
        downloadLoading,
LiangLiu's avatar
LiangLiu committed
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
        showAlert,
        apiRequest,
        startPollingTask,
        resumeTask,
         } from '../utils/other'
import { useI18n } from 'vue-i18n'
import { useRoute, useRouter } from 'vue-router'
const { t, locale } = useI18n()
const route = useRoute()
const router = useRouter()

// 添加响应式变量
const showDetails = ref(false)
const loadingTaskFiles = ref(false)

LiangLiu's avatar
LiangLiu committed
44
45
46
47
48
49
50
51
// 音频播放器相关
const audioElement = ref(null)
const isPlaying = ref(false)
const audioDuration = ref(0)
const currentTime = ref(0)
const isDragging = ref(false)
const currentAudioUrl = ref('')

LiangLiu's avatar
LiangLiu committed
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// 获取图片素材
const getImageMaterials = () => {
    if (!modalTask.value?.inputs?.input_image) return []
    return [['input_image', getTaskFileUrlSync(modalTask.value.task_id, 'input_image')]]
}

// 获取音频素材
const getAudioMaterials = () => {
    if (!modalTask.value?.inputs?.input_audio) return []
    return [['input_audio', getTaskFileUrlSync(modalTask.value.task_id, 'input_audio')]]
}

// 路由关闭功能
const closeWithRoute = () => {
    closeTaskDetailModal()
    modalTask.value = null
LiangLiu's avatar
LiangLiu committed
68
69
70
71
72
73
74
75
76
    // 只有当前路由是 /task/:id 时才进行路由跳转
    // 如果在其他页面(如 /generate)打开的弹窗,关闭时保持在原页面
    if (route.path.startsWith('/task/')) {
        // 从任务详情路由进入的,返回到上一页或首页
        if (window.history.length > 1) {
            router.go(-1)
        } else {
            router.push('/')
        }
LiangLiu's avatar
LiangLiu committed
77
    }
LiangLiu's avatar
LiangLiu committed
78
    // 如果不是任务详情路由,不做任何路由跳转,保持在当前页面
LiangLiu's avatar
LiangLiu committed
79
80
}

LiangLiu's avatar
LiangLiu committed
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// 滚动到生成区域(仅在 generate 页面)
const scrollToCreationArea = () => {
    const mainScrollable = document.querySelector('.main-scrollbar')
    if (mainScrollable) {
        mainScrollable.scrollTo({
            top: 0,
            behavior: 'smooth'
        })
    }
}

// 包装 reuseTask 函数,复用任务后回到生成区域
const handleReuseTask = () => {
    const task = modalTask.value
    if (!task) {
        return
    }
    void reuseTask(task)
    if (route.path === '/generate' || route.name === 'Generate') {
        setTimeout(() => {
            scrollToCreationArea()
        }, 300)
    }
}

LiangLiu's avatar
LiangLiu committed
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// 键盘事件处理
const handleKeydown = (event) => {
    if (event.key === 'Escape' && showTaskDetailModal.value) {
        closeWithRoute()
    }
}

// 获取文件扩展名
const getFileExtension = (fileKey) => {
    if (fileKey.includes('video')) return 'mp4'
    if (fileKey.includes('image')) return 'jpg'
    if (fileKey.includes('audio')) return 'mp3'
    return 'file'
}


const getTaskFailureInfo = (task) => {
                if (!task) return null;

                // 检查子任务的失败信息
                if (!task.fail_msg && task.subtasks && task.subtasks.length > 0) {
                    const failedSubtasks = task.subtasks.filter(subtask =>
                        (subtask.extra_info && subtask.extra_info.fail_msg) || subtask.fail_msg
                    );
                    if (failedSubtasks.length > 0) {
                        const msg = failedSubtasks.map(subtask =>
                            (subtask.extra_info && subtask.extra_info.fail_msg) || subtask.fail_msg
                        ).join('\n');
                        task.fail_msg = msg;
                    }
                }
                console.log('task.fail_msg', task.fail_msg);
                return task.fail_msg;
            };

const viewTaskDetail = async (task) => {
    try {
        const response = await apiRequest(`/api/v1/task/query?task_id=${task.task_id}`);
        console.log('viewTaskDetail: response=', response);
        if (response && response.ok) {
            modalTask.value = await response.json();
            console.log('updated task data:', modalTask.value);
        }
    } catch (error) {
        console.warn(`Failed to fetch updated task data: task_id=${task.task_id}`, error.message);
    }
    // 如果任务还在进行中,开始轮询状态
    if (['CREATED', 'PENDING', 'RUNNING'].includes(task.status)) {

        startPollingTask(task.task_id);
    }
    if (['FAILED'].includes(task.status)) {
        modalTask.value.fail_msg = getTaskFailureInfo(task);
    }
};

// 监听modalTask的第一次变化,确保任务详情正确加载
const hasLoadedTask = ref(false);
watch(modalTask, (newTask) => {
    if (newTask && !hasLoadedTask.value) {
        console.log('modalTask第一次变化,加载任务详情:', newTask);
        viewTaskDetail(newTask);
        hasLoadedTask.value = true;
    }
}, { immediate: true });

// 生命周期钩子
onMounted(async () => {
    document.addEventListener('keydown', handleKeydown)
    console.log('TaskDetails组件已挂载,当前modalTask:', modalTask.value);
})

onUnmounted(() => {
    document.removeEventListener('keydown', handleKeydown)
LiangLiu's avatar
LiangLiu committed
180
181
182
183
184
    // 清理音频资源
    const audio = getCurrentAudioElement()
    if (audio) {
        audio.pause()
    }
LiangLiu's avatar
LiangLiu committed
185
})
LiangLiu's avatar
LiangLiu committed
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273

// 格式化音频时间
const formatAudioTime = (seconds) => {
    if (!seconds || isNaN(seconds)) return '0:00'
    const mins = Math.floor(seconds / 60)
    const secs = Math.floor(seconds % 60)
    return `${mins}:${secs.toString().padStart(2, '0')}`
}

// 获取当前音频元素(处理可能是数组的情况)
const getCurrentAudioElement = () => {
    return Array.isArray(audioElement.value) ? audioElement.value[0] : audioElement.value
}

// 切换播放/暂停
const toggleAudioPlayback = () => {
    const audio = getCurrentAudioElement()
    if (!audio) return

    if (audio.paused) {
        audio.play().catch(error => {
            console.log('播放失败:', error)
        })
    } else {
        audio.pause()
    }
}

// 音频加载完成
const onAudioLoaded = () => {
    const audio = getCurrentAudioElement()
    if (audio) {
        audioDuration.value = audio.duration || 0
    }
}

// 时间更新
const onTimeUpdate = () => {
    const audio = getCurrentAudioElement()
    if (audio && !isDragging.value) {
        currentTime.value = audio.currentTime || 0
    }
}

// 进度条变化处理
const onProgressChange = (event) => {
    const audio = getCurrentAudioElement()
    if (audioDuration.value > 0 && audio && event.target) {
        const newTime = parseFloat(event.target.value)
        currentTime.value = newTime
        audio.currentTime = newTime
    }
}

// 进度条拖拽结束处理
const onProgressEnd = (event) => {
    const audio = getCurrentAudioElement()
    if (audio && audioDuration.value > 0 && event.target) {
        const newTime = parseFloat(event.target.value)
        audio.currentTime = newTime
        currentTime.value = newTime
    }
    isDragging.value = false
}

// 播放结束
const onAudioEnded = () => {
    isPlaying.value = false
    currentTime.value = 0
}

// 监听音频URL变化
watch(() => getAudioMaterials(), (newMaterials) => {
    if (newMaterials && newMaterials.length > 0) {
        currentAudioUrl.value = newMaterials[0][1]
        nextTick(() => {
            const audio = getCurrentAudioElement()
            if (audio) {
                audio.load()
            }
        })
    } else {
        currentAudioUrl.value = ''
        isPlaying.value = false
        currentTime.value = 0
        audioDuration.value = 0
    }
}, { immediate: true })
LiangLiu's avatar
LiangLiu committed
274
275
</script>
<template>
LiangLiu's avatar
LiangLiu committed
276
            <!-- 任务详情弹窗 - Apple 极简风格 -->
LiangLiu's avatar
LiangLiu committed
277
278
            <div v-cloak>
                <div v-if="showTaskDetailModal"
LiangLiu's avatar
LiangLiu committed
279
                    class="fixed inset-0 bg-black/50 dark:bg-black/60 backdrop-blur-sm z-[60] flex items-center justify-center p-2 sm:p-1"
LiangLiu's avatar
LiangLiu committed
280
                    @click="closeWithRoute">
LiangLiu's avatar
LiangLiu committed
281
                    <!-- 任务完成时的大弹窗 - Apple 风格 -->
LiangLiu's avatar
LiangLiu committed
282
                    <div v-if="modalTask?.status === 'SUCCEED'"
LiangLiu's avatar
LiangLiu committed
283
284
285
286
287
                        class="w-full h-full max-w-7xl max-h-[100vh] bg-white/95 dark:bg-[#1e1e1e]/95 backdrop-blur-[40px] backdrop-saturate-[180%] border border-black/10 dark:border-white/10 rounded-3xl shadow-[0_20px_60px_rgba(0,0,0,0.2)] dark:shadow-[0_20px_60px_rgba(0,0,0,0.6)] overflow-hidden flex flex-col" @click.stop>
                        <!-- 弹窗头部 - Apple 风格 -->
                        <div class="flex items-center justify-between px-8 py-5 border-b border-black/8 dark:border-white/8 bg-white/50 dark:bg-[#1e1e1e]/50 backdrop-blur-[20px]">
                            <h3 class="text-xl font-semibold text-[#1d1d1f] dark:text-[#f5f5f7] flex items-center gap-3 tracking-tight">
                                <i class="fas fa-check-circle text-[color:var(--brand-primary)] dark:text-[color:var(--brand-primary-light)]"></i>
LiangLiu's avatar
LiangLiu committed
288
                                {{ t('taskDetail') }}
LiangLiu's avatar
LiangLiu committed
289
                            </h3>
LiangLiu's avatar
LiangLiu committed
290
291
292
293
294
                            <div class="flex items-center gap-2">
                                <button @click="closeWithRoute"
                                        class="w-9 h-9 flex items-center justify-center bg-white/80 dark:bg-[#2c2c2e]/80 border border-black/8 dark:border-white/8 text-[#86868b] dark:text-[#98989d] hover:text-red-500 dark:hover:text-red-400 hover:bg-white dark:hover:bg-[#3a3a3c] rounded-full transition-all duration-200 hover:scale-110 active:scale-100"
                                        :title="t('close')">
                                    <i class="fas fa-times text-sm"></i>
LiangLiu's avatar
LiangLiu committed
295
296
297
298
                                </button>
                            </div>
                        </div>

LiangLiu's avatar
LiangLiu committed
299
300
301
                        <!-- 主要内容区域 - Apple 风格 -->
                        <div class="flex-1 overflow-y-auto main-scrollbar">
                            <div class="grid grid-cols-1 lg:grid-cols-2 gap-8 lg:gap-12 p-8 lg:p-12">
LiangLiu's avatar
LiangLiu committed
302
                                <!-- 左侧视频区域 -->
LiangLiu's avatar
LiangLiu committed
303
304
                                <div class="flex items-center justify-center">
                                    <div class="w-full max-w-[400px] aspect-[9/16] bg-black dark:bg-[#000000] rounded-2xl overflow-hidden shadow-[0_8px_24px_rgba(0,0,0,0.15)] dark:shadow-[0_8px_24px_rgba(0,0,0,0.5)]">
LiangLiu's avatar
LiangLiu committed
305
306
307
308
309
                                        <!-- 视频播放器 -->
                                        <video
                                            v-if="modalTask?.outputs?.output_video"
                                            :src="getTaskFileUrlSync(modalTask.task_id, 'output_video')"
                                            :poster="getTaskFileUrlSync(modalTask.task_id, 'input_image')"
LiangLiu's avatar
LiangLiu committed
310
                                            class="w-full h-full object-contain"
LiangLiu's avatar
LiangLiu committed
311
312
313
314
315
316
317
318
                                            controls
                                            loop
                                            preload="metadata"
                                            @loadstart="onVideoLoadStart"
                                            @canplay="onVideoCanPlay"
                                            @error="onVideoError">
                                            {{ t('browserNotSupported') }}
                                        </video>
LiangLiu's avatar
LiangLiu committed
319
320
321
                                        <div v-else class="w-full h-full flex flex-col items-center justify-center bg-[#f5f5f7] dark:bg-[#1c1c1e]">
                                            <div class="w-16 h-16 rounded-full bg-black/5 dark:bg-white/5 flex items-center justify-center mb-4">
                                                <i class="fas fa-video text-3xl text-[#86868b] dark:text-[#98989d]"></i>
LiangLiu's avatar
LiangLiu committed
322
                                            </div>
LiangLiu's avatar
LiangLiu committed
323
                                            <p class="text-sm text-[#86868b] dark:text-[#98989d] tracking-tight">{{ t('videoNotAvailable') }}</p>
LiangLiu's avatar
LiangLiu committed
324
325
326
327
328
                                        </div>
                                    </div>
                                </div>

                                <!-- 右侧信息区域 -->
LiangLiu's avatar
LiangLiu committed
329
330
                                <div class="flex items-center justify-center">
                                    <div class="w-full max-w-[400px] aspect-[9/16] relative flex flex-col">
LiangLiu's avatar
LiangLiu committed
331

LiangLiu's avatar
LiangLiu committed
332
333
334
                                        <!-- 居中的内容区域 -->
                                        <div class="flex-1 flex items-center justify-center px-8 py-6">
                                            <div class="w-full">
LiangLiu's avatar
LiangLiu committed
335
336
337
338
339
340
341
342
343
344
345
346
347
348
                                                <div class="flex flex-col items-center gap-3 mb-6">
                                                    <div class="flex items-center gap-3">
                                                        <button @click="copyShareLink(modalTask.task_id, 'task')"
                                                            class="w-12 h-12 flex items-center justify-center bg-white/95 dark:bg-[#1e1e1e]/95 backdrop-blur-[20px] border border-black/8 dark:border-white/8 text-[color:var(--brand-primary)] dark:text-[color:var(--brand-primary-light)] rounded-full shadow-[0_4px_16px_rgba(0,0,0,0.12)] dark:shadow-[0_4px_16px_rgba(0,0,0,0.4)] hover:scale-110 active:scale-100 transition-all duration-200"
                                                            :title="t('share')">
                                                            <i class="fas fa-share-alt text-base"></i>
                                                        </button>
                                                        <button @click="deleteTask(modalTask.task_id, true)"
                                                            class="w-12 h-12 flex items-center justify-center bg-white/95 dark:bg-[#1e1e1e]/95 backdrop-blur-[20px] border border-black/8 dark:border-white/8 text-red-500 dark:text-red-400 rounded-full shadow-[0_4px_16px_rgba(0,0,0,0.12)] dark:shadow-[0_4px_16px_rgba(0,0,0,0.4)] hover:scale-110 active:scale-100 transition-all duration-200"
                                                            :title="t('delete')">
                                                            <i class="fas fa-trash text-base"></i>
                                                        </button>
                                                    </div>
                                                </div>
LiangLiu's avatar
LiangLiu committed
349
350
351
352
353
354
355
356
357
                                                <!-- 标题 -->
                                                <div class="text-center mb-6">
                                                    <h1 class="text-3xl sm:text-4xl font-semibold text-[#1d1d1f] dark:text-[#f5f5f7] mb-3 tracking-tight">
                                                        {{ t('taskCompleted') }}
                                                    </h1>
                                                    <p class="text-sm sm:text-base text-[#86868b] dark:text-[#98989d] tracking-tight">
                                                        {{ t('taskCompletedSuccessfully') }}
                                                    </p>
                                                </div>
LiangLiu's avatar
LiangLiu committed
358

LiangLiu's avatar
LiangLiu committed
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
                                                <!-- 特性列表 - Apple 风格 -->
                                                <div class="grid grid-cols-3 gap-2 mb-6">
                                                    <div class="flex flex-col items-center gap-1.5 p-3 bg-white/80 dark:bg-[#2c2c2e]/80 backdrop-blur-[20px] border border-black/8 dark:border-white/8 rounded-xl">
                                                        <i class="fas fa-toolbox text-lg text-[color:var(--brand-primary)] dark:text-[color:var(--brand-primary-light)]"></i>
                                                        <span class="text-[11px] text-[#1d1d1f] dark:text-[#f5f5f7] font-medium tracking-tight">{{ getTaskTypeName(modalTask) }}</span>
                                                    </div>
                                                    <div class="flex flex-col items-center gap-1.5 p-3 bg-white/80 dark:bg-[#2c2c2e]/80 backdrop-blur-[20px] border border-black/8 dark:border-white/8 rounded-xl">
                                                        <i class="fas fa-robot text-lg text-[color:var(--brand-primary)] dark:text-[color:var(--brand-primary-light)]"></i>
                                                        <span class="text-[11px] text-[#1d1d1f] dark:text-[#f5f5f7] font-medium tracking-tight truncate max-w-full">{{ modalTask.model_cls }}</span>
                                                    </div>
                                                    <div class="flex flex-col items-center gap-1.5 p-3 bg-white/80 dark:bg-[#2c2c2e]/80 backdrop-blur-[20px] border border-black/8 dark:border-white/8 rounded-xl">
                                                        <i class="fas fa-clock text-lg text-[color:var(--brand-primary)] dark:text-[color:var(--brand-primary-light)]"></i>
                                                        <span class="text-[11px] text-[#1d1d1f] dark:text-[#f5f5f7] font-medium tracking-tight">{{ Math.round(modalTask.extra_info?.active_elapse || 0) }}s</span>
                                                    </div>
                                                </div>
LiangLiu's avatar
LiangLiu committed
374

LiangLiu's avatar
LiangLiu committed
375
376
377
378
                                                <!-- 操作按钮 - Apple 风格 -->
                                                <div class="space-y-2.5">
                                                    <button v-if="modalTask?.outputs?.output_video"
                                                            @click="handleDownloadFile(modalTask.task_id, 'output_video', modalTask.outputs.output_video)"
LiangLiu's avatar
LiangLiu committed
379
380
381
                                                            :disabled="downloadLoading"
                                                            class="w-full rounded-full bg-[color:var(--brand-primary)] dark:bg-[color:var(--brand-primary-light)] border-0 px-6 py-3 text-[15px] font-semibold text-white transition-all duration-200 ease-out tracking-tight flex items-center justify-center gap-2"
                                                            :class="downloadLoading ? 'opacity-60 cursor-not-allowed' : 'hover:scale-[1.02] hover:shadow-[0_8px_24px_rgba(var(--brand-primary-rgb),0.35)] dark:hover:shadow-[0_8px_24px_rgba(var(--brand-primary-light-rgb),0.4)] active:scale-100'">
LiangLiu's avatar
LiangLiu committed
382
383
384
                                                        <i class="fas fa-download text-sm"></i>
                                                        <span>{{ t('downloadVideo') }}</span>
                                                    </button>
LiangLiu's avatar
LiangLiu committed
385
                                                    <button @click="handleReuseTask"
LiangLiu's avatar
LiangLiu committed
386
387
388
389
390
391
392
393
394
395
396
                                                            class="w-full rounded-full bg-white dark:bg-[#3a3a3c] border border-black/8 dark:border-white/8 px-6 py-2.5 text-[15px] font-medium text-[#1d1d1f] dark:text-[#f5f5f7] hover:bg-white/80 dark:hover:bg-[#3a3a3c]/80 hover:border-black/12 dark:hover:border-white/12 hover:shadow-[0_4px_12px_rgba(0,0,0,0.1)] dark:hover:shadow-[0_4px_12px_rgba(0,0,0,0.3)] active:scale-[0.98] transition-all duration-200 tracking-tight flex items-center justify-center gap-2">
                                                        <i class="fas fa-magic text-sm"></i>
                                                        <span>{{ t('reuseTask') }}</span>
                                                    </button>
                                                    <button @click="showDetails = !showDetails"
                                                            class="w-full rounded-full bg-white dark:bg-[#3a3a3c] border border-black/8 dark:border-white/8 px-6 py-2.5 text-[15px] font-medium text-[#1d1d1f] dark:text-[#f5f5f7] hover:bg-white/80 dark:hover:bg-[#3a3a3c]/80 hover:border-black/12 dark:hover:border-white/12 hover:shadow-[0_4px_12px_rgba(0,0,0,0.1)] dark:hover:shadow-[0_4px_12px_rgba(0,0,0,0.3)] active:scale-[0.98] transition-all duration-200 tracking-tight flex items-center justify-center gap-2">
                                                        <i :class="showDetails ? 'fas fa-chevron-up' : 'fas fa-info-circle'" class="text-sm"></i>
                                                        <span>{{ showDetails ? t('hideDetails') : t('showDetails') }}</span>
                                                    </button>
                                                </div>
                                            </div>
LiangLiu's avatar
LiangLiu committed
397
398
399
400
401
                                        </div>
                                    </div>
                                </div>
                            </div>

LiangLiu's avatar
LiangLiu committed
402
403
404
405
406
407
408
                            <!-- 详细信息面板 - Apple 风格 (成功状态)-->
                            <div v-if="showDetails && modalTask" class="bg-[#f5f5f7] dark:bg-[#1c1c1e] border-t border-black/8 dark:border-white/8 py-12">
                                <div class="max-w-6xl mx-auto px-8">
                                    <!-- 输入素材标题 - Apple 风格 -->
                                    <h2 class="text-2xl font-semibold text-[#1d1d1f] dark:text-[#f5f5f7] flex items-center justify-center gap-3 mb-8 tracking-tight">
                                        <i class="fas fa-upload text-[color:var(--brand-primary)] dark:text-[color:var(--brand-primary-light)]"></i>
                                        <span>{{ t('inputMaterials') }}</span>
LiangLiu's avatar
LiangLiu committed
409
410
                                    </h2>

LiangLiu's avatar
LiangLiu committed
411
412
413
414
415
416
417
418
419
420
                                    <!-- 三个并列的分块卡片 - Apple 风格 -->
                                    <div class="grid grid-cols-1 md:grid-cols-3 gap-6">
                                        <!-- 图片卡片 - Apple 风格 -->
                                        <div class="bg-white/80 dark:bg-[#2c2c2e]/80 backdrop-blur-[20px] border border-black/8 dark:border-white/8 rounded-2xl overflow-hidden transition-all duration-200 hover:bg-white dark:hover:bg-[#3a3a3c] hover:border-black/12 dark:hover:border-white/12 hover:shadow-[0_8px_24px_rgba(0,0,0,0.1)] dark:hover:shadow-[0_8px_24px_rgba(0,0,0,0.3)]">
                                            <!-- 卡片头部 -->
                                            <div class="flex items-center justify-between px-5 py-4 bg-[color:var(--brand-primary)]/5 dark:bg-[color:var(--brand-primary-light)]/10 border-b border-black/8 dark:border-white/8">
                                                <div class="flex items-center gap-3">
                                                    <i class="fas fa-image text-lg text-[color:var(--brand-primary)] dark:text-[color:var(--brand-primary-light)]"></i>
                                                    <h3 class="text-base font-semibold text-[#1d1d1f] dark:text-[#f5f5f7] tracking-tight">{{ t('image') }}</h3>
                                                </div>
LiangLiu's avatar
LiangLiu committed
421
422
                                                <button v-if="getImageMaterials().length > 0"
                                                        @click="handleDownloadFile(modalTask.task_id, 'input_image', modalTask.inputs.input_image)"
LiangLiu's avatar
LiangLiu committed
423
424
425
                                                        :disabled="downloadLoading"
                                                        class="w-8 h-8 flex items-center justify-center bg-[color:var(--brand-primary)]/10 dark:bg-[color:var(--brand-primary-light)]/15 border border-[color:var(--brand-primary)]/20 dark:border-[color:var(--brand-primary-light)]/20 text-[color:var(--brand-primary)] dark:text-[color:var(--brand-primary-light)] rounded-lg transition-all duration-200"
                                                        :class="downloadLoading ? 'opacity-60 cursor-not-allowed' : 'hover:scale-110 active:scale-100'"
LiangLiu's avatar
LiangLiu committed
426
                                                        :title="t('download')">
LiangLiu's avatar
LiangLiu committed
427
                                                    <i class="fas fa-download text-xs"></i>
LiangLiu's avatar
LiangLiu committed
428
429
                                                </button>
                                            </div>
LiangLiu's avatar
LiangLiu committed
430
431
432
433
434
                                            <!-- 卡片内容 -->
                                            <div class="p-6 min-h-[200px]">
                                                <div v-if="getImageMaterials().length > 0">
                                                    <div v-for="[inputName, url] in getImageMaterials()" :key="inputName" class="rounded-xl overflow-hidden border border-black/8 dark:border-white/8">
                                                        <img :src="url" :alt="inputName" class="w-full h-auto object-contain">
LiangLiu's avatar
LiangLiu committed
435
436
                                                    </div>
                                                </div>
LiangLiu's avatar
LiangLiu committed
437
438
439
440
                                                <div v-else class="flex flex-col items-center justify-center h-[150px]">
                                                    <i class="fas fa-image text-3xl text-[#86868b]/30 dark:text-[#98989d]/30 mb-3"></i>
                                                    <p class="text-sm text-[#86868b] dark:text-[#98989d] tracking-tight">{{ t('noImage') }}</p>
                                                </div>
LiangLiu's avatar
LiangLiu committed
441
442
443
                                            </div>
                                        </div>

LiangLiu's avatar
LiangLiu committed
444
445
446
447
448
449
450
451
                                        <!-- 音频卡片 - Apple 风格 -->
                                        <div class="bg-white/80 dark:bg-[#2c2c2e]/80 backdrop-blur-[20px] border border-black/8 dark:border-white/8 rounded-2xl overflow-hidden transition-all duration-200 hover:bg-white dark:hover:bg-[#3a3a3c] hover:border-black/12 dark:hover:border-white/12 hover:shadow-[0_8px_24px_rgba(0,0,0,0.1)] dark:hover:shadow-[0_8px_24px_rgba(0,0,0,0.3)]">
                                            <!-- 卡片头部 -->
                                            <div class="flex items-center justify-between px-5 py-4 bg-[color:var(--brand-primary)]/5 dark:bg-[color:var(--brand-primary-light)]/10 border-b border-black/8 dark:border-white/8">
                                                <div class="flex items-center gap-3">
                                                    <i class="fas fa-music text-lg text-[color:var(--brand-primary)] dark:text-[color:var(--brand-primary-light)]"></i>
                                                    <h3 class="text-base font-semibold text-[#1d1d1f] dark:text-[#f5f5f7] tracking-tight">{{ t('audio') }}</h3>
                                                </div>
LiangLiu's avatar
LiangLiu committed
452
453
                                                <button v-if="getAudioMaterials().length > 0"
                                                        @click="handleDownloadFile(modalTask.task_id, 'input_audio', modalTask.inputs.input_audio)"
LiangLiu's avatar
LiangLiu committed
454
455
456
                                                        :disabled="downloadLoading"
                                                        class="w-8 h-8 flex items-center justify-center bg-[color:var(--brand-primary)]/10 dark:bg-[color:var(--brand-primary-light)]/15 border border-[color:var(--brand-primary)]/20 dark:border-[color:var(--brand-primary-light)]/20 text-[color:var(--brand-primary)] dark:text-[color:var(--brand-primary-light)] rounded-lg transition-all duration-200"
                                                        :class="downloadLoading ? 'opacity-60 cursor-not-allowed' : 'hover:scale-110 active:scale-100'"
LiangLiu's avatar
LiangLiu committed
457
                                                        :title="t('download')">
LiangLiu's avatar
LiangLiu committed
458
                                                    <i class="fas fa-download text-xs"></i>
LiangLiu's avatar
LiangLiu committed
459
460
                                                </button>
                                            </div>
LiangLiu's avatar
LiangLiu committed
461
462
463
464
                                            <!-- 卡片内容 -->
                                            <div class="p-6 min-h-[200px]">
                                                <div v-if="getAudioMaterials().length > 0" class="space-y-4">
                                                    <div v-for="[inputName, url] in getAudioMaterials()" :key="inputName">
LiangLiu's avatar
LiangLiu committed
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
                                                        <!-- 音频播放器卡片 - Apple 风格 -->
                                                        <div class="bg-white/80 dark:bg-[#2c2c2e]/80 backdrop-blur-[20px] border border-black/8 dark:border-white/8 rounded-xl transition-all duration-200 hover:bg-white dark:hover:bg-[#3a3a3c] hover:border-black/12 dark:hover:border-white/12 hover:shadow-[0_4px_12px_rgba(0,0,0,0.08)] dark:hover:shadow-[0_4px_12px_rgba(0,0,0,0.2)] w-full p-4">
                                                            <div class="relative flex items-center mb-3">
                                                                <!-- 头像容器 -->
                                                                <div class="relative mr-3 flex-shrink-0">
                                                                    <!-- 透明白色头像 -->
                                                                    <div class="w-12 h-12 rounded-full bg-white/40 dark:bg-white/20 border border-white/30 dark:border-white/20 transition-all duration-200"></div>
                                                                    <!-- 播放/暂停按钮 -->
                                                                    <button
                                                                        @click="toggleAudioPlayback"
                                                                        class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-8 h-8 bg-[color:var(--brand-primary)]/90 dark:bg-[color:var(--brand-primary-light)]/90 rounded-full flex items-center justify-center text-white cursor-pointer hover:scale-110 transition-all duration-200 z-20 shadow-[0_2px_8px_rgba(var(--brand-primary-rgb),0.3)] dark:shadow-[0_2px_8px_rgba(var(--brand-primary-light-rgb),0.4)]"
                                                                    >
                                                                        <i :class="isPlaying ? 'fas fa-pause' : 'fas fa-play'" class="text-xs ml-0.5"></i>
                                                                    </button>
                                                                </div>

                                                                <!-- 音频信息 -->
                                                                <div class="flex-1 min-w-0">
                                                                    <div class="text-sm font-medium text-[#1d1d1f] dark:text-[#f5f5f7] tracking-tight truncate">
                                                                        {{ t('audio') }}
                                                                    </div>
                                                                </div>

                                                                <!-- 音频时长 -->
                                                                <div class="text-xs font-medium text-[#86868b] dark:text-[#98989d] tracking-tight flex-shrink-0">
                                                                    {{ formatAudioTime(currentTime) }} / {{ formatAudioTime(audioDuration) }}
                                                                </div>
                                                            </div>

                                                            <!-- 进度条 -->
                                                            <div class="flex items-center gap-2" v-if="audioDuration > 0">
                                                                <input
                                                                    type="range"
                                                                    :min="0"
                                                                    :max="audioDuration"
                                                                    :value="currentTime"
                                                                    @input="onProgressChange"
                                                                    @change="onProgressChange"
                                                                    @mousedown="isDragging = true"
                                                                    @mouseup="onProgressEnd"
                                                                    @touchstart="isDragging = true"
                                                                    @touchend="onProgressEnd"
                                                                    class="flex-1 h-1 bg-black/6 dark:bg-white/15 rounded-full appearance-none cursor-pointer [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:w-3 [&::-webkit-slider-thumb]:h-3 [&::-webkit-slider-thumb]:bg-[color:var(--brand-primary)] dark:[&::-webkit-slider-thumb]:bg-[color:var(--brand-primary-light)] [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:cursor-pointer"
                                                                />
                                                            </div>
                                                        </div>

                                                        <!-- 隐藏的音频元素 -->
                                                        <audio
                                                            ref="audioElement"
                                                            :src="url"
                                                            @loadedmetadata="onAudioLoaded"
                                                            @timeupdate="onTimeUpdate"
                                                            @ended="onAudioEnded"
                                                            @play="isPlaying = true"
                                                            @pause="isPlaying = false"
                                                            class="hidden"
                                                        ></audio>
LiangLiu's avatar
LiangLiu committed
523
524
525
526
527
                                                    </div>
                                                </div>
                                                <div v-else class="flex flex-col items-center justify-center h-[150px]">
                                                    <i class="fas fa-music text-3xl text-[#86868b]/30 dark:text-[#98989d]/30 mb-3"></i>
                                                    <p class="text-sm text-[#86868b] dark:text-[#98989d] tracking-tight">{{ t('noAudio') }}</p>
LiangLiu's avatar
LiangLiu committed
528
529
530
531
                                                </div>
                                            </div>
                                        </div>

LiangLiu's avatar
LiangLiu committed
532
533
534
535
536
537
538
539
                                        <!-- 提示词卡片 - Apple 风格 -->
                                        <div class="bg-white/80 dark:bg-[#2c2c2e]/80 backdrop-blur-[20px] border border-black/8 dark:border-white/8 rounded-2xl overflow-hidden transition-all duration-200 hover:bg-white dark:hover:bg-[#3a3a3c] hover:border-black/12 dark:hover:border-white/12 hover:shadow-[0_8px_24px_rgba(0,0,0,0.1)] dark:hover:shadow-[0_8px_24px_rgba(0,0,0,0.3)]">
                                            <!-- 卡片头部 -->
                                            <div class="flex items-center justify-between px-5 py-4 bg-[color:var(--brand-primary)]/5 dark:bg-[color:var(--brand-primary-light)]/10 border-b border-black/8 dark:border-white/8">
                                                <div class="flex items-center gap-3">
                                                    <i class="fas fa-file-alt text-lg text-[color:var(--brand-primary)] dark:text-[color:var(--brand-primary-light)]"></i>
                                                    <h3 class="text-base font-semibold text-[#1d1d1f] dark:text-[#f5f5f7] tracking-tight">{{ t('prompt') }}</h3>
                                                </div>
LiangLiu's avatar
LiangLiu committed
540
541
                                                <button v-if="modalTask?.params?.prompt"
                                                        @click="copyPrompt(modalTask?.params?.prompt)"
LiangLiu's avatar
LiangLiu committed
542
                                                        class="w-8 h-8 flex items-center justify-center bg-[color:var(--brand-primary)]/10 dark:bg-[color:var(--brand-primary-light)]/15 border border-[color:var(--brand-primary)]/20 dark:border-[color:var(--brand-primary-light)]/20 text-[color:var(--brand-primary)] dark:text-[color:var(--brand-primary-light)] rounded-lg transition-all duration-200 hover:scale-110 active:scale-100"
LiangLiu's avatar
LiangLiu committed
543
                                                        :title="t('copy')">
LiangLiu's avatar
LiangLiu committed
544
                                                    <i class="fas fa-copy text-xs"></i>
LiangLiu's avatar
LiangLiu committed
545
546
                                                </button>
                                            </div>
LiangLiu's avatar
LiangLiu committed
547
548
549
550
551
552
553
554
555
                                            <!-- 卡片内容 -->
                                            <div class="p-6 min-h-[200px]">
                                                <div v-if="modalTask?.params?.prompt" class="bg-white/50 dark:bg-[#1e1e1e]/50 backdrop-blur-[10px] border border-black/6 dark:border-white/6 rounded-xl p-4">
                                                    <p class="text-sm text-[#1d1d1f] dark:text-[#f5f5f7] leading-relaxed tracking-tight break-words">{{ modalTask.params.prompt }}</p>
                                                </div>
                                                <div v-else class="flex flex-col items-center justify-center h-[150px]">
                                                    <i class="fas fa-file-alt text-3xl text-[#86868b]/30 dark:text-[#98989d]/30 mb-3"></i>
                                                    <p class="text-sm text-[#86868b] dark:text-[#98989d] tracking-tight">{{ t('noPrompt') }}</p>
                                                </div>
LiangLiu's avatar
LiangLiu committed
556
557
558
559
560
561
562
563
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>

LiangLiu's avatar
LiangLiu committed
564
565
566
567
568
569
570
571
                    <!-- 其他状态的弹窗 - Apple 风格 -->
                    <div v-else class="w-full max-w-7xl max-h-[95vh] bg-white/95 dark:bg-[#1e1e1e]/95 backdrop-blur-[40px] backdrop-saturate-[180%] border border-black/10 dark:border-white/10 rounded-3xl shadow-[0_20px_60px_rgba(0,0,0,0.2)] dark:shadow-[0_20px_60px_rgba(0,0,0,0.6)] overflow-hidden flex flex-col" @click.stop>
                        <!-- 弹窗头部 - Apple 风格 -->
                        <div class="flex items-center justify-between px-8 py-5 border-b border-black/8 dark:border-white/8 bg-white/50 dark:bg-[#1e1e1e]/50 backdrop-blur-[20px]">
                            <h3 class="text-xl font-semibold text-[#1d1d1f] dark:text-[#f5f5f7] flex items-center gap-3 tracking-tight">
                                <i v-if="modalTask?.status === 'FAILED'" class="fas fa-exclamation-triangle text-red-500 dark:text-red-400"></i>
                                <i v-else-if="modalTask?.status === 'CANCEL'" class="fas fa-ban text-[#86868b] dark:text-[#98989d]"></i>
                                <i v-else class="fas fa-spinner fa-spin text-[color:var(--brand-primary)] dark:text-[color:var(--brand-primary-light)]"></i>
LiangLiu's avatar
LiangLiu committed
572
                                <span>{{ t('taskDetail') }}</span>
LiangLiu's avatar
LiangLiu committed
573
                            </h3>
LiangLiu's avatar
LiangLiu committed
574
575
576
577
578
                            <div class="flex items-center gap-2">
                                <button @click="closeWithRoute"
                                        class="w-9 h-9 flex items-center justify-center bg-white/80 dark:bg-[#2c2c2e]/80 border border-black/8 dark:border-white/8 text-[#86868b] dark:text-[#98989d] hover:text-red-500 dark:hover:text-red-400 hover:bg-white dark:hover:bg-[#3a3a3c] rounded-full transition-all duration-200 hover:scale-110 active:scale-100"
                                        :title="t('close')">
                                    <i class="fas fa-times text-sm"></i>
LiangLiu's avatar
LiangLiu committed
579
580
581
582
                                </button>
                            </div>
                        </div>

LiangLiu's avatar
LiangLiu committed
583
584
585
586
587
588
                        <!-- 主要内容区域 - Apple 风格 -->
                        <div class="flex-1 overflow-y-auto main-scrollbar">
                            <div class="grid grid-cols-1 lg:grid-cols-2 gap-8 lg:gap-12 p-8 lg:p-12">
                                <!-- 左侧占位图区域 - Apple 风格 -->
                                <div class="flex items-center justify-center">
                                    <div class="w-full max-w-[400px] aspect-[9/16] bg-black dark:bg-[#000000] rounded-2xl overflow-hidden shadow-[0_8px_24px_rgba(0,0,0,0.15)] dark:shadow-[0_8px_24px_rgba(0,0,0,0.5)] relative">
LiangLiu's avatar
LiangLiu committed
589
                                        <!-- 根据状态显示不同的占位图 -->
LiangLiu's avatar
LiangLiu committed
590
591
592
593
594
                                        <!-- 进行中状态 -->
                                        <div v-if="['CREATED', 'PENDING', 'RUNNING'].includes(modalTask?.status)" class="w-full h-full flex flex-col items-center justify-center relative bg-[#f5f5f7] dark:bg-[#1c1c1e]">
                                            <!-- 如果有图像输入,显示为背景 -->
                                            <div v-if="getImageMaterials().length > 0" class="absolute top-0 left-0 w-full h-full z-[1]">
                                                <img :src="getImageMaterials()[0][1]" :alt="getImageMaterials()[0][0]" class="w-full h-full object-cover opacity-20 blur-sm">
LiangLiu's avatar
LiangLiu committed
595
                                            </div>
LiangLiu's avatar
LiangLiu committed
596
597
598
599
600
601
                                            <div class="absolute top-0 left-0 w-full h-full flex flex-col justify-center items-center z-[2]">
                                                <div class="relative w-12 h-12 mb-6">
                                                    <div class="absolute inset-0 rounded-full border-2 border-black/8 dark:border-white/8"></div>
                                                    <div class="absolute inset-0 rounded-full border-2 border-transparent border-t-[color:var(--brand-primary)] dark:border-t-[color:var(--brand-primary-light)] animate-spin"></div>
                                                </div>
                                                <p class="text-sm font-medium text-[#86868b] dark:text-[#98989d] tracking-tight">{{ t('videoGenerating') }}...</p>
LiangLiu's avatar
LiangLiu committed
602
603
                                            </div>
                                        </div>
LiangLiu's avatar
LiangLiu committed
604
605
606
607
608
609
610
611
612
613
                                        <!-- 失败状态 -->
                                        <div v-else-if="modalTask?.status === 'FAILED'" class="w-full h-full flex flex-col items-center justify-center relative bg-[#fef2f2] dark:bg-[#2c1b1b]">
                                            <div v-if="getImageMaterials().length > 0" class="absolute top-0 left-0 w-full h-full z-[1]">
                                                <img :src="getImageMaterials()[0][1]" :alt="getImageMaterials()[0][0]" class="w-full h-full object-cover opacity-10 blur-sm">
                                            </div>
                                            <div class="absolute top-0 left-0 w-full h-full flex flex-col justify-center items-center z-[2]">
                                                <div class="w-16 h-16 rounded-full bg-red-500/10 dark:bg-red-400/10 flex items-center justify-center mb-4">
                                                    <i class="fas fa-exclamation-triangle text-3xl text-red-500 dark:text-red-400"></i>
                                                </div>
                                                <p class="text-sm font-medium text-[#1d1d1f] dark:text-[#f5f5f7] tracking-tight">{{ t('videoGeneratingFailed') }}</p>
LiangLiu's avatar
LiangLiu committed
614
615
                                            </div>
                                        </div>
LiangLiu's avatar
LiangLiu committed
616
617
618
619
620
621
622
623
624
625
                                        <!-- 取消状态 -->
                                        <div v-else-if="modalTask?.status === 'CANCEL'" class="w-full h-full flex flex-col items-center justify-center relative bg-[#f5f5f7] dark:bg-[#1c1c1e]">
                                            <div v-if="getImageMaterials().length > 0" class="absolute top-0 left-0 w-full h-full z-[1]">
                                                <img :src="getImageMaterials()[0][1]" :alt="getImageMaterials()[0][0]" class="w-full h-full object-cover opacity-10 blur-sm">
                                            </div>
                                            <div class="absolute top-0 left-0 w-full h-full flex flex-col justify-center items-center z-[2]">
                                                <div class="w-16 h-16 rounded-full bg-black/5 dark:bg-white/5 flex items-center justify-center mb-4">
                                                    <i class="fas fa-ban text-3xl text-[#86868b] dark:text-[#98989d]"></i>
                                                </div>
                                                <p class="text-sm font-medium text-[#1d1d1f] dark:text-[#f5f5f7] tracking-tight">{{ t('taskCancelled') }}</p>
LiangLiu's avatar
LiangLiu committed
626
627
628
629
630
                                            </div>
                                        </div>
                                    </div>
                                </div>

LiangLiu's avatar
LiangLiu committed
631
632
633
634
635
636
637
638
639
640
641
                                <!-- 右侧信息区域 - Apple 风格 -->
                                <div class="flex items-center justify-center">
                                    <div class="w-full max-w-[400px] aspect-[9/16] relative flex flex-col">
                                        <!-- 右上角删除按钮 - Apple 极简风格 -->
                                        <div class="absolute top-0 right-0 z-10">
                                            <button v-if="['FAILED', 'CANCEL'].includes(modalTask?.status)"
                                                    @click="deleteTask(modalTask.task_id, true)"
                                                    class="w-8 h-8 flex items-center justify-center bg-white/95 dark:bg-[#1e1e1e]/95 backdrop-blur-[20px] border border-black/10 dark:border-white/10 rounded-full shadow-[0_2px_8px_rgba(0,0,0,0.12)] dark:shadow-[0_2px_8px_rgba(0,0,0,0.4)] text-red-500 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/30 hover:scale-110 hover:shadow-[0_4px_12px_rgba(239,68,68,0.2)] dark:hover:shadow-[0_4px_12px_rgba(248,113,113,0.3)] active:scale-100 transition-all duration-200"
                                                    :title="t('delete')">
                                                <i class="fas fa-trash text-xs"></i>
                                            </button>
LiangLiu's avatar
LiangLiu committed
642
643
                                        </div>

LiangLiu's avatar
LiangLiu committed
644
645
646
647
648
649
650
651
652
653
654
                                        <!-- 居中的内容区域 -->
                                        <div class="flex-1 flex items-center justify-center px-8 py-6">
                                            <div class="w-full">
                                                <!-- 标题和状态 - Apple 风格 -->
                                                <div class="text-center mb-6">
                                                    <h1 class="text-3xl sm:text-4xl font-semibold text-[#1d1d1f] dark:text-[#f5f5f7] mb-3 tracking-tight">
                                                        <span v-if="modalTask?.status === 'SUCCEED'">{{ t('taskCompleted') }}</span>
                                                        <span v-else-if="modalTask?.status === 'FAILED'">{{ t('taskFailed') }}</span>
                                                        <span v-else-if="modalTask?.status === 'CANCEL'">{{ t('taskCancelled') }}</span>
                                                        <span v-else-if="modalTask?.status === 'RUNNING'">{{ t('taskRunning') }}</span>
                                                        <span v-else-if="modalTask?.status === 'PENDING'">{{ t('taskPending') }}</span>
LiangLiu's avatar
LiangLiu committed
655
                                                        <span v-else>{{ t('taskDetail') }}</span>
LiangLiu's avatar
LiangLiu committed
656
657
658
659
660
661
662
663
664
665
666
667
                                                    </h1>
                                                </div>

                                                <!-- 进度条 - Apple 风格 -->
                                                <div v-if="['CREATED', 'PENDING', 'RUNNING'].includes(modalTask?.status)" class="mb-6">
                                            <div v-for="(subtask, index) in (modalTask.subtasks || [])" :key="index">
                                                <!-- PENDING状态:Apple 风格排队显示 -->
                                                <div v-if="subtask.status === 'PENDING'" class="text-center">
                                                    <div v-if="subtask.estimated_pending_order !== null && subtask.estimated_pending_order !== undefined && subtask.estimated_pending_order >= 0" class="flex flex-col items-center gap-3">
                                                        <!-- 排队图标 -->
                                                        <div class="flex flex-wrap justify-center gap-1.5 mb-2">
                                                            <i v-for="n in Math.min(Math.max(subtask.estimated_pending_order, 0), 10)"
LiangLiu's avatar
LiangLiu committed
668
                                                               :key="n"
LiangLiu's avatar
LiangLiu committed
669
670
                                                               class="fas fa-circle text-[8px] text-[#86868b] dark:text-[#98989d] opacity-60"></i>
                                                            <span v-if="subtask.estimated_pending_order > 10" class="text-xs text-[#86868b] dark:text-[#98989d] font-medium ml-0.5">
LiangLiu's avatar
LiangLiu committed
671
672
673
                                                                +{{ subtask.estimated_pending_order - 10 }}
                                                            </span>
                                                        </div>
LiangLiu's avatar
LiangLiu committed
674
675
                                                        <!-- 排队文字 -->
                                                        <span class="text-sm text-[#1d1d1f] dark:text-[#f5f5f7] font-medium tracking-tight">
LiangLiu's avatar
LiangLiu committed
676
677
678
679
680
                                                            {{ t('queuePosition') }}: {{ subtask.estimated_pending_order }}
                                                        </span>
                                                    </div>
                                                </div>

LiangLiu's avatar
LiangLiu committed
681
682
683
684
685
686
                                                <!-- RUNNING状态:Apple 风格进度条 -->
                                                <div v-else-if="subtask.status === 'RUNNING'" class="w-full">
                                                    <!-- 进度条 -->
                                                    <div class="mb-4">
                                                        <div class="relative w-full h-1 bg-black/8 dark:bg-white/8 rounded-full overflow-hidden">
                                                            <div class="absolute top-0 left-0 h-full bg-[color:var(--brand-primary)] dark:bg-[color:var(--brand-primary-light)] rounded-full transition-all duration-500 ease-out" :style="{ width: getSubtaskProgress(subtask) + '%' }"></div>
LiangLiu's avatar
LiangLiu committed
687
688
                                                        </div>
                                                    </div>
LiangLiu's avatar
LiangLiu committed
689
690
691
                                                    <!-- 百分比显示 -->
                                                    <div class="flex justify-center items-center">
                                                        <span class="text-2xl font-semibold text-[#1d1d1f] dark:text-[#f5f5f7] tracking-tight">
LiangLiu's avatar
LiangLiu committed
692
693
694
695
696
697
                                                            {{ getSubtaskProgress(subtask) }}%
                                                        </span>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
LiangLiu's avatar
LiangLiu committed
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718

                                                <!-- 描述 - Apple 风格 -->
                                                <div class="text-sm sm:text-base text-[#86868b] dark:text-[#98989d] text-center mb-6 tracking-tight">
                                                    <p v-if="['RUNNING'].includes(modalTask?.status)" class="mb-0">
                                                        {{ t('aiIsGeneratingYourVideo') }}
                                                    </p>
                                                    <p v-else-if="['CREATED'].includes(modalTask?.status)" class="mb-0">
                                                        {{ t('taskSubmittedSuccessfully') }}
                                                    </p>
                                                    <p v-else-if="['PENDING'].includes(modalTask?.status)" class="mb-0">
                                                        {{ t('taskQueuePleaseWait') }}
                                                    </p>
                                                    <div v-else-if="modalTask?.status === 'FAILED'">
                                                        <p class="mb-4">{{ t('sorryYourVideoGenerationTaskFailed') }}</p>
                                                        <button v-if="modalTask?.fail_msg"
                                                                @click="showFailureDetails = !showFailureDetails"
                                                                class="text-sm text-[#86868b] dark:text-[#98989d] hover:text-red-500 dark:hover:text-red-400 transition-colors underline underline-offset-2">
                                                            {{ showFailureDetails ? t('hideDetails') : t('viewErrorDetails') }}
                                                        </button>
                                                        <div v-if="showFailureDetails && modalTask?.fail_msg" class="mt-4 p-4 bg-black/2 dark:bg-white/2 border border-black/6 dark:border-white/6 rounded-xl text-left">
                                                            <p class="text-xs text-[#86868b] dark:text-[#98989d] whitespace-pre-wrap leading-relaxed">{{ modalTask?.fail_msg }}</p>
LiangLiu's avatar
LiangLiu committed
719
720
                                                        </div>
                                                    </div>
LiangLiu's avatar
LiangLiu committed
721
722
723
                                                    <p v-else-if="modalTask?.status === 'CANCEL'" class="mb-0">
                                                        {{ t('thisTaskHasBeenCancelledYouCanRegenerateOrViewTheMaterialsYouUploadedBefore') }}
                                                    </p>
LiangLiu's avatar
LiangLiu committed
724
725
                                                </div>

LiangLiu's avatar
LiangLiu committed
726
727
728
729
730
731
732
733
734
735
736
                                                <!-- 特性列表 - Apple 风格 -->
                                                <div class="grid grid-cols-2 gap-2 mb-6">
                                                    <div class="flex flex-col items-center gap-1.5 p-3 bg-white/80 dark:bg-[#2c2c2e]/80 backdrop-blur-[20px] border border-black/8 dark:border-white/8 rounded-xl">
                                                        <i class="fas fa-toolbox text-lg text-[color:var(--brand-primary)] dark:text-[color:var(--brand-primary-light)]"></i>
                                                        <span class="text-[11px] text-[#1d1d1f] dark:text-[#f5f5f7] font-medium tracking-tight">{{ getTaskTypeName(modalTask) }}</span>
                                                    </div>
                                                    <div class="flex flex-col items-center gap-1.5 p-3 bg-white/80 dark:bg-[#2c2c2e]/80 backdrop-blur-[20px] border border-black/8 dark:border-white/8 rounded-xl">
                                                        <i class="fas fa-robot text-lg text-[color:var(--brand-primary)] dark:text-[color:var(--brand-primary-light)]"></i>
                                                        <span class="text-[11px] text-[#1d1d1f] dark:text-[#f5f5f7] font-medium tracking-tight truncate max-w-full">{{ modalTask.model_cls }}</span>
                                                    </div>
                                                </div>
LiangLiu's avatar
LiangLiu committed
737

LiangLiu's avatar
LiangLiu committed
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
                                                <!-- 操作按钮 - Apple 风格 -->
                                                <div class="space-y-2.5">
                                                    <!-- 进行中状态:取消按钮 -->
                                                    <button v-if="['CREATED', 'PENDING', 'RUNNING'].includes(modalTask?.status)"
                                                            @click="cancelTask(modalTask.task_id, true)"
                                                            class="w-full rounded-full bg-white dark:bg-[#3a3a3c] border border-black/8 dark:border-white/8 px-6 py-3 text-[15px] font-semibold text-red-500 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/20 hover:border-red-500/30 dark:hover:border-red-400/30 hover:shadow-[0_8px_24px_rgba(239,68,68,0.2)] dark:hover:shadow-[0_8px_24px_rgba(248,113,113,0.3)] active:scale-[0.98] transition-all duration-200 tracking-tight flex items-center justify-center gap-2">
                                                        <i class="fas fa-times text-sm"></i>
                                                        <span>{{ t('cancelTask') }}</span>
                                                    </button>

                                                    <!-- 失败或取消状态:重试按钮 -->
                                                    <button v-if="modalTask?.status === 'FAILED' || modalTask?.status === 'CANCEL'"
                                                            @click="resumeTask(modalTask.task_id, true)"
                                                            class="w-full rounded-full bg-[color:var(--brand-primary)] dark:bg-[color:var(--brand-primary-light)] border-0 px-6 py-3 text-[15px] font-semibold text-white hover:scale-[1.02] hover:shadow-[0_8px_24px_rgba(var(--brand-primary-rgb),0.35)] dark:hover:shadow-[0_8px_24px_rgba(var(--brand-primary-light-rgb),0.4)] active:scale-100 transition-all duration-200 ease-out tracking-tight flex items-center justify-center gap-2">
                                                        <i class="fas fa-redo text-sm"></i>
                                                        <span>{{ modalTask?.status === 'CANCEL' ? t('regenerateTask') : t('retryTask') }}</span>
                                                    </button>

                                                    <!-- 通用按钮 -->
                                                    <button v-if="['SUCCEED', 'FAILED', 'CANCEL','CREATED', 'PENDING', 'RUNNING'].includes(modalTask?.status)"
LiangLiu's avatar
LiangLiu committed
758
                                                            @click="handleReuseTask"
LiangLiu's avatar
LiangLiu committed
759
760
761
762
763
764
765
766
767
768
769
770
                                                            class="w-full rounded-full bg-white dark:bg-[#3a3a3c] border border-black/8 dark:border-white/8 px-6 py-2.5 text-[15px] font-medium text-[#1d1d1f] dark:text-[#f5f5f7] hover:bg-white/80 dark:hover:bg-[#3a3a3c]/80 hover:border-black/12 dark:hover:border-white/12 hover:shadow-[0_4px_12px_rgba(0,0,0,0.1)] dark:hover:shadow-[0_4px_12px_rgba(0,0,0,0.3)] active:scale-[0.98] transition-all duration-200 tracking-tight flex items-center justify-center gap-2">
                                                        <i class="fas fa-copy text-sm"></i>
                                                        <span>{{ t('reuseTask') }}</span>
                                                    </button>

                                                    <button @click="showDetails = !showDetails"
                                                            class="w-full rounded-full bg-white dark:bg-[#3a3a3c] border border-black/8 dark:border-white/8 px-6 py-2.5 text-[15px] font-medium text-[#1d1d1f] dark:text-[#f5f5f7] hover:bg-white/80 dark:hover:bg-[#3a3a3c]/80 hover:border-black/12 dark:hover:border-white/12 hover:shadow-[0_4px_12px_rgba(0,0,0,0.1)] dark:hover:shadow-[0_4px_12px_rgba(0,0,0,0.3)] active:scale-[0.98] transition-all duration-200 tracking-tight flex items-center justify-center gap-2">
                                                        <i :class="showDetails ? 'fas fa-chevron-up' : 'fas fa-info-circle'" class="text-sm"></i>
                                                        <span>{{ showDetails ? t('hideDetails') : t('showDetails') }}</span>
                                                    </button>
                                                </div>
                                            </div>
LiangLiu's avatar
LiangLiu committed
771
772
773
774
775
                                        </div>
                                    </div>
                                </div>
                            </div>

LiangLiu's avatar
LiangLiu committed
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
                            <!-- 详细信息面板 - Apple 风格(其他状态)-->
                        <div v-if="showDetails && modalTask" class="bg-[#f5f5f7] dark:bg-[#1c1c1e] border-t border-black/8 dark:border-white/8 py-12">
                            <div class="max-w-6xl mx-auto px-8">
                                <!-- 输入素材标题 - Apple 风格 -->
                                <h2 class="text-2xl font-semibold text-[#1d1d1f] dark:text-[#f5f5f7] flex items-center justify-center gap-3 mb-8 tracking-tight">
                                    <i class="fas fa-upload text-[color:var(--brand-primary)] dark:text-[color:var(--brand-primary-light)]"></i>
                                    <span>{{ t('inputMaterials') }}</span>
                                </h2>

                                <!-- 三个并列的分块卡片 - Apple 风格 -->
                                <div class="grid grid-cols-1 md:grid-cols-3 gap-6">
                                    <!-- 图片卡片 - Apple 风格 -->
                                    <div class="bg-white/80 dark:bg-[#2c2c2e]/80 backdrop-blur-[20px] border border-black/8 dark:border-white/8 rounded-2xl overflow-hidden transition-all duration-200 hover:bg-white dark:hover:bg-[#3a3a3c] hover:border-black/12 dark:hover:border-white/12 hover:shadow-[0_8px_24px_rgba(0,0,0,0.1)] dark:hover:shadow-[0_8px_24px_rgba(0,0,0,0.3)]">
                                        <!-- 卡片头部 -->
                                        <div class="flex items-center justify-between px-5 py-4 bg-[color:var(--brand-primary)]/5 dark:bg-[color:var(--brand-primary-light)]/10 border-b border-black/8 dark:border-white/8">
                                            <div class="flex items-center gap-3">
                                                <i class="fas fa-image text-lg text-[color:var(--brand-primary)] dark:text-[color:var(--brand-primary-light)]"></i>
                                                <h3 class="text-base font-semibold text-[#1d1d1f] dark:text-[#f5f5f7] tracking-tight">{{ t('image') }}</h3>
LiangLiu's avatar
LiangLiu committed
794
                                            </div>
LiangLiu's avatar
LiangLiu committed
795
796
                                            <button v-if="getImageMaterials().length > 0"
                                                    @click="handleDownloadFile(modalTask.task_id, 'input_image', modalTask.inputs.input_image)"
LiangLiu's avatar
LiangLiu committed
797
798
799
                                                    :disabled="downloadLoading"
                                                    class="w-8 h-8 flex items-center justify-center bg-[color:var(--brand-primary)]/10 dark:bg-[color:var(--brand-primary-light)]/15 border border-[color:var(--brand-primary)]/20 dark:border-[color:var(--brand-primary-light)]/20 text-[color:var(--brand-primary)] dark:text-[color:var(--brand-primary-light)] rounded-lg transition-all duration-200"
                                                    :class="downloadLoading ? 'opacity-60 cursor-not-allowed' : 'hover:scale-110 active:scale-100'"
LiangLiu's avatar
LiangLiu committed
800
801
802
                                                    :title="t('download')">
                                                <i class="fas fa-download text-xs"></i>
                                            </button>
LiangLiu's avatar
LiangLiu committed
803
                                        </div>
LiangLiu's avatar
LiangLiu committed
804
805
806
807
808
                                        <!-- 卡片内容 -->
                                        <div class="p-6 min-h-[200px]">
                                            <div v-if="getImageMaterials().length > 0">
                                                <div v-for="[inputName, url] in getImageMaterials()" :key="inputName" class="rounded-xl overflow-hidden border border-black/8 dark:border-white/8">
                                                    <img :src="url" :alt="inputName" class="w-full h-auto object-contain">
LiangLiu's avatar
LiangLiu committed
809
810
                                                </div>
                                            </div>
LiangLiu's avatar
LiangLiu committed
811
812
813
                                            <div v-else class="flex flex-col items-center justify-center h-[150px]">
                                                <i class="fas fa-image text-3xl text-[#86868b]/30 dark:text-[#98989d]/30 mb-3"></i>
                                                <p class="text-sm text-[#86868b] dark:text-[#98989d] tracking-tight">{{ t('noImage') }}</p>
LiangLiu's avatar
LiangLiu committed
814
815
816
817
                                            </div>
                                        </div>
                                    </div>

LiangLiu's avatar
LiangLiu committed
818
819
820
821
822
823
824
                                    <!-- 音频卡片 - Apple 风格 -->
                                    <div class="bg-white/80 dark:bg-[#2c2c2e]/80 backdrop-blur-[20px] border border-black/8 dark:border-white/8 rounded-2xl overflow-hidden transition-all duration-200 hover:bg-white dark:hover:bg-[#3a3a3c] hover:border-black/12 dark:hover:border-white/12 hover:shadow-[0_8px_24px_rgba(0,0,0,0.1)] dark:hover:shadow-[0_8px_24px_rgba(0,0,0,0.3)]">
                                        <!-- 卡片头部 -->
                                        <div class="flex items-center justify-between px-5 py-4 bg-[color:var(--brand-primary)]/5 dark:bg-[color:var(--brand-primary-light)]/10 border-b border-black/8 dark:border-white/8">
                                            <div class="flex items-center gap-3">
                                                <i class="fas fa-music text-lg text-[color:var(--brand-primary)] dark:text-[color:var(--brand-primary-light)]"></i>
                                                <h3 class="text-base font-semibold text-[#1d1d1f] dark:text-[#f5f5f7] tracking-tight">{{ t('audio') }}</h3>
LiangLiu's avatar
LiangLiu committed
825
                                            </div>
LiangLiu's avatar
LiangLiu committed
826
827
                                            <button v-if="getAudioMaterials().length > 0"
                                                    @click="handleDownloadFile(modalTask.task_id, 'input_audio', modalTask.inputs.input_audio)"
LiangLiu's avatar
LiangLiu committed
828
829
830
                                                    :disabled="downloadLoading"
                                                    class="w-8 h-8 flex items-center justify-center bg-[color:var(--brand-primary)]/10 dark:bg-[color:var(--brand-primary-light)]/15 border border-[color:var(--brand-primary)]/20 dark:border-[color:var(--brand-primary-light)]/20 text-[color:var(--brand-primary)] dark:text-[color:var(--brand-primary-light)] rounded-lg transition-all duration-200"
                                                    :class="downloadLoading ? 'opacity-60 cursor-not-allowed' : 'hover:scale-110 active:scale-100'"
LiangLiu's avatar
LiangLiu committed
831
832
833
                                                    :title="t('download')">
                                                <i class="fas fa-download text-xs"></i>
                                            </button>
LiangLiu's avatar
LiangLiu committed
834
                                        </div>
LiangLiu's avatar
LiangLiu committed
835
836
837
838
                                        <!-- 卡片内容 -->
                                        <div class="p-6 min-h-[200px]">
                                            <div v-if="getAudioMaterials().length > 0" class="space-y-4">
                                                <div v-for="[inputName, url] in getAudioMaterials()" :key="inputName">
LiangLiu's avatar
LiangLiu committed
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
                                                    <!-- 音频播放器卡片 - Apple 风格 -->
                                                    <div class="bg-white/80 dark:bg-[#2c2c2e]/80 backdrop-blur-[20px] border border-black/8 dark:border-white/8 rounded-xl transition-all duration-200 hover:bg-white dark:hover:bg-[#3a3a3c] hover:border-black/12 dark:hover:border-white/12 hover:shadow-[0_4px_12px_rgba(0,0,0,0.08)] dark:hover:shadow-[0_4px_12px_rgba(0,0,0,0.2)] w-full p-4">
                                                        <div class="relative flex items-center mb-3">
                                                            <!-- 头像容器 -->
                                                            <div class="relative mr-3 flex-shrink-0">
                                                                <!-- 透明白色头像 -->
                                                                <div class="w-12 h-12 rounded-full bg-white/40 dark:bg-white/20 border border-white/30 dark:border-white/20 transition-all duration-200"></div>
                                                                <!-- 播放/暂停按钮 -->
                                                                <button
                                                                    @click="toggleAudioPlayback"
                                                                    class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-8 h-8 bg-[color:var(--brand-primary)]/90 dark:bg-[color:var(--brand-primary-light)]/90 rounded-full flex items-center justify-center text-white cursor-pointer hover:scale-110 transition-all duration-200 z-20 shadow-[0_2px_8px_rgba(var(--brand-primary-rgb),0.3)] dark:shadow-[0_2px_8px_rgba(var(--brand-primary-light-rgb),0.4)]"
                                                                >
                                                                    <i :class="isPlaying ? 'fas fa-pause' : 'fas fa-play'" class="text-xs ml-0.5"></i>
                                                                </button>
                                                            </div>

                                                            <!-- 音频信息 -->
                                                            <div class="flex-1 min-w-0">
                                                                <div class="text-sm font-medium text-[#1d1d1f] dark:text-[#f5f5f7] tracking-tight truncate">
                                                                    {{ t('audio') }}
                                                                </div>
                                                            </div>

                                                            <!-- 音频时长 -->
                                                            <div class="text-xs font-medium text-[#86868b] dark:text-[#98989d] tracking-tight flex-shrink-0">
                                                                {{ formatAudioTime(currentTime) }} / {{ formatAudioTime(audioDuration) }}
                                                            </div>
                                                        </div>

                                                        <!-- 进度条 -->
                                                        <div class="flex items-center gap-2" v-if="audioDuration > 0">
                                                            <input
                                                                type="range"
                                                                :min="0"
                                                                :max="audioDuration"
                                                                :value="currentTime"
                                                                @input="onProgressChange"
                                                                @change="onProgressChange"
                                                                @mousedown="isDragging = true"
                                                                @mouseup="onProgressEnd"
                                                                @touchstart="isDragging = true"
                                                                @touchend="onProgressEnd"
                                                                class="flex-1 h-1 bg-black/6 dark:bg-white/15 rounded-full appearance-none cursor-pointer [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:w-3 [&::-webkit-slider-thumb]:h-3 [&::-webkit-slider-thumb]:bg-[color:var(--brand-primary)] dark:[&::-webkit-slider-thumb]:bg-[color:var(--brand-primary-light)] [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:cursor-pointer"
                                                            />
                                                        </div>
                                                    </div>

                                                    <!-- 隐藏的音频元素 -->
                                                    <audio
                                                        ref="audioElement"
                                                        :src="url"
                                                        @loadedmetadata="onAudioLoaded"
                                                        @timeupdate="onTimeUpdate"
                                                        @ended="onAudioEnded"
                                                        @play="isPlaying = true"
                                                        @pause="isPlaying = false"
                                                        class="hidden"
                                                    ></audio>
LiangLiu's avatar
LiangLiu committed
897
898
                                                </div>
                                            </div>
LiangLiu's avatar
LiangLiu committed
899
900
901
                                            <div v-else class="flex flex-col items-center justify-center h-[150px]">
                                                <i class="fas fa-music text-3xl text-[#86868b]/30 dark:text-[#98989d]/30 mb-3"></i>
                                                <p class="text-sm text-[#86868b] dark:text-[#98989d] tracking-tight">{{ t('noAudio') }}</p>
LiangLiu's avatar
LiangLiu committed
902
903
904
905
                                            </div>
                                        </div>
                                    </div>

LiangLiu's avatar
LiangLiu committed
906
907
908
909
910
911
912
                                    <!-- 提示词卡片 - Apple 风格 -->
                                    <div class="bg-white/80 dark:bg-[#2c2c2e]/80 backdrop-blur-[20px] border border-black/8 dark:border-white/8 rounded-2xl overflow-hidden transition-all duration-200 hover:bg-white dark:hover:bg-[#3a3a3c] hover:border-black/12 dark:hover:border-white/12 hover:shadow-[0_8px_24px_rgba(0,0,0,0.1)] dark:hover:shadow-[0_8px_24px_rgba(0,0,0,0.3)]">
                                        <!-- 卡片头部 -->
                                        <div class="flex items-center justify-between px-5 py-4 bg-[color:var(--brand-primary)]/5 dark:bg-[color:var(--brand-primary-light)]/10 border-b border-black/8 dark:border-white/8">
                                            <div class="flex items-center gap-3">
                                                <i class="fas fa-file-alt text-lg text-[color:var(--brand-primary)] dark:text-[color:var(--brand-primary-light)]"></i>
                                                <h3 class="text-base font-semibold text-[#1d1d1f] dark:text-[#f5f5f7] tracking-tight">{{ t('prompt') }}</h3>
LiangLiu's avatar
LiangLiu committed
913
                                            </div>
LiangLiu's avatar
LiangLiu committed
914
915
916
917
918
919
                                            <button v-if="modalTask?.params?.prompt"
                                                    @click="copyPrompt(modalTask?.params?.prompt)"
                                                    class="w-8 h-8 flex items-center justify-center bg-[color:var(--brand-primary)]/10 dark:bg-[color:var(--brand-primary-light)]/15 border border-[color:var(--brand-primary)]/20 dark:border-[color:var(--brand-primary-light)]/20 text-[color:var(--brand-primary)] dark:text-[color:var(--brand-primary-light)] rounded-lg transition-all duration-200 hover:scale-110 active:scale-100"
                                                    :title="t('copy')">
                                                <i class="fas fa-copy text-xs"></i>
                                            </button>
LiangLiu's avatar
LiangLiu committed
920
                                        </div>
LiangLiu's avatar
LiangLiu committed
921
922
923
924
                                        <!-- 卡片内容 -->
                                        <div class="p-6 min-h-[200px]">
                                            <div v-if="modalTask?.params?.prompt" class="bg-white/50 dark:bg-[#1e1e1e]/50 backdrop-blur-[10px] border border-black/6 dark:border-white/6 rounded-xl p-4">
                                                <p class="text-sm text-[#1d1d1f] dark:text-[#f5f5f7] leading-relaxed tracking-tight break-words">{{ modalTask.params.prompt }}</p>
LiangLiu's avatar
LiangLiu committed
925
                                            </div>
LiangLiu's avatar
LiangLiu committed
926
927
928
                                            <div v-else class="flex flex-col items-center justify-center h-[150px]">
                                                <i class="fas fa-file-alt text-3xl text-[#86868b]/30 dark:text-[#98989d]/30 mb-3"></i>
                                                <p class="text-sm text-[#86868b] dark:text-[#98989d] tracking-tight">{{ t('noPrompt') }}</p>
LiangLiu's avatar
LiangLiu committed
929
930
931
932
933
934
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
LiangLiu's avatar
LiangLiu committed
935
                        </div>
LiangLiu's avatar
LiangLiu committed
936
                    </div>
LiangLiu's avatar
LiangLiu committed
937
938
                </div>
            </div>
LiangLiu's avatar
LiangLiu committed
939
940
941
</template>

<style scoped>
LiangLiu's avatar
LiangLiu committed
942
/* Apple 风格极简样式 - 所有样式已通过 Tailwind CSS 的 dark: 前缀在 template 中定义 */
LiangLiu's avatar
LiangLiu committed
943
</style>