crosssubtitle-ai/src/components/TaskQueue.vue
2026-05-01 17:18:50 +08:00

80 lines
2.6 KiB
Vue

<script setup lang="ts">
import type { SubtitleTask } from '../lib/types'
defineProps<{
tasks: SubtitleTask[]
selectedTaskId: string
}>()
const emit = defineEmits<{
select: [taskId: string]
retry: [taskId: string]
retryTranslate: [taskId: string]
delete: [taskId: string]
}>()
</script>
<template>
<aside class="panel sidebar-panel">
<div class="panel-title">
<div>
<strong>{{ $t('taskQueue.title') }}</strong>
<p class="panel-subtitle">{{ $t('taskQueue.subtitle') }}</p>
</div>
<span class="badge">{{ tasks.length }}</span>
</div>
<div v-if="tasks.length === 0" class="empty-state">
{{ $t('taskQueue.empty') }}
</div>
<div v-else class="list-stack">
<button
v-for="task in tasks"
:key="task.id"
class="task-item"
:class="{
active: task.id === selectedTaskId,
completed: task.status === 'completed',
failed: task.status === 'failed',
}"
@click="emit('select', task.id)"
>
<div class="task-row">
<strong class="truncate">{{ task.fileName }}</strong>
<span
class="subtle"
:class="{ 'status-active': task.status !== 'completed' && task.status !== 'failed' && task.status !== 'queued' }"
>{{ $t(`taskQueue.status.${task.status}`) }}</span>
</div>
<div class="progress">
<div class="progress-bar" :style="{ width: `${task.progress}%` }" />
</div>
<div v-if="task.status === 'failed'" class="failed-footer">
<p class="error-text">{{ task.error }}</p>
<div class="retry-actions">
<button class="retry-button" type="button" @click.stop="emit('retry', task.id)">{{ $t('taskQueue.retry') }}</button>
<button
v-if="task.segments.length > 0"
class="retry-button secondary"
type="button"
@click.stop="emit('retryTranslate', task.id)"
>{{ $t('taskQueue.retryTranslate') }}</button>
</div>
</div>
<button
class="delete-button"
type="button"
:title="$t('taskQueue.delete')"
@click.stop="emit('delete', task.id)"
>
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="3 6 5 6 21 6" />
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
</svg>
</button>
</button>
</div>
</aside>
</template>