chore(merge): 将 develop 同步到 release/v1.0.0

This commit is contained in:
Zhou Weidong committed 2026-10-23 13:08:09 +08:00
commit 430ba59613
60 files changed
+6769 -426

No files matched your search

@@ -0,0 +1,137 @@
<!-- Author: fruit.com.cn -->
<!-- 批量上传队列单行:序号、文件名、大小、进度、状态与操作 -->
<script setup lang="ts">
import { computed } from 'vue'
import { useI18n } from '@/hooks/web/useI18n'
import type { UploadQueueItem } from './useUploadQueue'
const props = defineProps<{
item: UploadQueueItem
/** 自然排序后的展示序号(从 1 起) */
index: number
/** 选择阶段才允许移除 */
allowRemove: boolean
}>()
const emit = defineEmits<{
retry: [id: string]
remove: [id: string]
}>()
const { t } = useI18n()
const BYTES_PER_KB = 1024
const BYTES_PER_MB = 1024 * 1024
const sizeLabel = computed(() => {
const size = props.item.fileSize
if (size >= BYTES_PER_MB) {
return `${(size / BYTES_PER_MB).toFixed(1)} MB`
}
return `${Math.max(1, Math.round(size / BYTES_PER_KB))} KB`
})
const statusLabel = computed(() => t(`episodeBatch.status.${props.item.status}`))
const statusType = computed(() => {
switch (props.item.status) {
case 'done':
return 'success'
case 'failed':
return 'danger'
case 'paused':
return 'warning'
case 'merging':
case 'uploading':
return ''
default:
return 'info'
}
})
const canRetry = computed(() => props.item.status === 'failed')
</script>
<template>
<div class="upload-task-row" :class="{ 'is-failed': item.status === 'failed' }">
<div class="upload-task-row__meta">
<span class="upload-task-row__index">{{ index }}</span>
<b class="upload-task-row__name" :title="item.fileName">{{ item.fileName }}</b>
<small>{{ sizeLabel }}</small>
<el-tag :type="statusType" effect="light" size="small">{{ statusLabel }}</el-tag>
</div>
<el-progress
:percentage="item.percent"
:status="
item.status === 'failed' ? 'exception' : item.status === 'done' ? 'success' : undefined
"
:stroke-width="10"
/>
<p v-if="item.error" class="upload-task-row__error">{{ item.error }}</p>
<div class="upload-task-row__actions">
<el-button v-if="canRetry" size="small" type="primary" @click="emit('retry', item.id)">
{{ t('episodeBatch.retry') }}
</el-button>
<el-button
v-if="allowRemove"
size="small"
type="danger"
text
@click="emit('remove', item.id)"
>
{{ t('episodeBatch.remove') }}
</el-button>
</div>
</div>
</template>
<style scoped>
.upload-task-row {
padding: 12px 0;
border-bottom: 1px solid var(--el-border-color-lighter);
}
.upload-task-row__meta {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 8px;
}
.upload-task-row__index {
min-width: 1.5em;
font-size: 13px;
color: var(--el-text-color-secondary);
flex: 0 0 auto;
font-variant-numeric: tabular-nums;
}
.upload-task-row__name {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.upload-task-row__error {
margin: 6px 0 0;
font-size: 12px;
color: var(--el-color-danger);
}
.upload-task-row__actions {
display: flex;
margin-top: 8px;
margin-left: auto;
gap: 8px;
justify-content: flex-end;
}
.upload-task-row.is-failed {
padding-right: 8px;
padding-left: 8px;
background: color-mix(in srgb, var(--el-color-danger) 6%, transparent);
border-radius: 6px;
}
</style>