重构 TransferQueueDialog 组件,添加整体和当前文件进度管理

This commit is contained in:
jxxghp
2025-08-24 13:02:40 +08:00
parent 3ec3212ca5
commit 9c405e90ac
4 changed files with 149 additions and 50 deletions
+137 -50
View File
@@ -1,4 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
import { formatFileSize } from '@/@core/utils/formatters' import { formatFileSize } from '@/@core/utils/formatters'
import api from '@/api' import api from '@/api'
import { FileItem, TransferQueue } from '@/api/types' import { FileItem, TransferQueue } from '@/api/types'
@@ -18,11 +19,22 @@ const emit = defineEmits(['close'])
// 数据列表 // 数据列表
const dataList = ref<TransferQueue[]>([]) const dataList = ref<TransferQueue[]>([])
// 整进度文本 // 整进度相关
const progressText = ref(t('dialog.transferQueue.processing')) const overallProgress = ref({
enable: false,
value: 0,
text: t('dialog.transferQueue.processing'),
data: {
current: '',
finished: [] as string[],
},
})
// 整理进度 // 当前文件进度相关
const progressValue = ref(0) const currentFileProgress = ref({
enable: false,
value: 0,
})
// 数据可刷新标志 // 数据可刷新标志
const refreshFlag = ref(false) const refreshFlag = ref(false)
@@ -93,54 +105,113 @@ async function remove_queue_task(fileitem: FileItem) {
} }
} }
// 进度SSE消息处理函数 // 整体进度SSE消息处理函数
function handleProgressMessage(event: MessageEvent) { function handleOverallProgressMessage(event: MessageEvent) {
const progress = JSON.parse(event.data) try {
if (progress) { const progress = JSON.parse(event.data)
if (!progress.enable) { if (progress) {
progressText.value = t('dialog.transferQueue.processing') overallProgress.value = {
progressValue.value = 0 enable: progress.enable || false,
if (refreshFlag.value) { value: progress.value || 0,
refreshFlag.value = false text: progress.text || t('dialog.transferQueue.processing'),
get_transfer_queue() data: {
current: progress.data?.current || '',
finished: progress.data?.finished || [],
},
} }
return
} // 如果进度完成或禁用,刷新队列数据
progressText.value = progress.text if (!progress.enable || progress.value >= 100) {
progressValue.value = progress.value if (refreshFlag.value) {
if (progress.value >= 100 && refreshFlag.value) { refreshFlag.value = false
refreshFlag.value = false get_transfer_queue()
get_transfer_queue() }
} else {
if (progress.value > 0 && refreshFlag.value && progress.text?.includes('整理完成')) {
refreshFlag.value = false
get_transfer_queue()
} else { } else {
refreshFlag.value = true refreshFlag.value = true
} }
} }
} catch (error) {
console.error('解析整体进度消息失败:', error)
} }
} }
// 使用优化的进度SSE连接 // 当前文件进度SSE消息处理函数
const progressSSE = useProgressSSE( function handleCurrentFileProgressMessage(event: MessageEvent) {
try {
const progress = JSON.parse(event.data)
if (progress) {
currentFileProgress.value = {
enable: progress.enable || false,
value: progress.value || 0,
}
}
} catch (error) {
console.error('解析当前文件进度消息失败:', error)
}
}
// 使用优化的进度SSE连接 - 整体进度
const overallProgressSSE = useProgressSSE(
`${import.meta.env.VITE_API_BASE_URL}system/progress/filetransfer`, `${import.meta.env.VITE_API_BASE_URL}system/progress/filetransfer`,
handleProgressMessage, handleOverallProgressMessage,
'transfer-queue-progress', 'transfer-queue-overall-progress',
progressActive, progressActive,
) )
// 当前文件进度SSE连接
let currentFileProgressSSE: any = null
// 启动当前文件进度监听
function startCurrentFileProgress(filePath: string) {
if (currentFileProgressSSE) {
currentFileProgressSSE.stop()
}
if (filePath) {
const encodedPath = encodeURIComponent(filePath)
currentFileProgressSSE = useProgressSSE(
`${import.meta.env.VITE_API_BASE_URL}system/progress/${encodedPath}`,
handleCurrentFileProgressMessage,
'transfer-queue-current-file-progress',
progressActive,
)
currentFileProgressSSE.start()
}
}
// 停止当前文件进度监听
function stopCurrentFileProgress() {
if (currentFileProgressSSE) {
currentFileProgressSSE.stop()
currentFileProgressSSE = null
}
}
// 监听当前文件变化,自动切换进度监听
watch(
() => overallProgress.value.data.current,
newCurrentFile => {
if (newCurrentFile) {
startCurrentFileProgress(newCurrentFile)
} else {
stopCurrentFileProgress()
currentFileProgress.value = { enable: false, value: 0 }
}
},
)
// 使用SSE监听加载进度 // 使用SSE监听加载进度
function startLoadingProgress() { function startLoadingProgress() {
progressText.value = t('dialog.transferQueue.processing') overallProgress.value.text = t('dialog.transferQueue.processing')
progressActive.value = true progressActive.value = true
progressSSE.start() overallProgressSSE.start()
} }
// 停止监听加载进度 // 停止监听加载进度
function stopLoadingProgress() { function stopLoadingProgress() {
progressActive.value = false progressActive.value = false
progressSSE.stop() overallProgressSSE.stop()
stopCurrentFileProgress()
} }
onMounted(() => { onMounted(() => {
@@ -154,25 +225,25 @@ onUnmounted(() => {
</script> </script>
<template> <template>
<VDialog scrollable max-width="50rem" :fullscreen="!display.mdAndUp.value"> <VDialog scrollable max-width="60rem" :fullscreen="!display.mdAndUp.value">
<VCard class="mx-auto" width="100%"> <VCard class="mx-auto" width="100%">
<VCardItem> <VCardItem>
<VCardTitle>{{ t('dialog.transferQueue.title') }}</VCardTitle> <VCardTitle>{{ t('dialog.transferQueue.title') }}</VCardTitle>
</VCardItem> </VCardItem>
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
<VDivider />
<VProgressLinear <!-- 整体进度显示 -->
v-if="dataList.length > 0 && progressValue > 0" <VProgressLinear v-if="dataList.length > 0" :value="overallProgress.value" color="primary" :height="2" />
:value="progressValue" <VDivider v-else />
color="primary" <div v-if="overallProgress.enable && overallProgress.value > 0" class="pt-2 text-center">
indeterminate <div class="text-sm font-medium">{{ overallProgress.value.toFixed(1) }}%{{ overallProgress.text }}</div>
:height="2" </div>
/>
<VCardItem v-if="dataList.length > 0 && progressValue > 0" class="text-center pt-2"> <VCardText v-if="dataList.length === 0" class="text-center">
<span class="text-sm">{{ progressText }}</span> {{ t('dialog.transferQueue.noTasks') }}
</VCardItem> </VCardText>
<VCardText v-if="dataList.length === 0" class="text-center"> {{ t('dialog.transferQueue.noTasks') }} </VCardText>
<VCardText> <VCardText v-if="dataList.length > 0">
<VTabs v-model="activeTab" show-arrows class="v-tabs-pill" stacked> <VTabs v-model="activeTab" show-arrows class="v-tabs-pill" stacked>
<VTab <VTab
v-for="media in mediaList" v-for="media in mediaList"
@@ -186,16 +257,32 @@ onUnmounted(() => {
<VWindow v-model="activeTab" class="mt-5 disable-tab-transition" :touch="false"> <VWindow v-model="activeTab" class="mt-5 disable-tab-transition" :touch="false">
<VWindowItem v-for="media in mediaList" :value="media.title_year"> <VWindowItem v-for="media in mediaList" :value="media.title_year">
<VList> <VList>
<VListItem v-for="task in activeTasks"> <VListItem v-for="task in activeTasks" :key="task.fileitem.path">
<VListItemTitle>{{ task.fileitem.name }}</VListItemTitle> <VListItemTitle>{{ task.fileitem.name }}</VListItemTitle>
<VListItemSubtitle> <VListItemSubtitle class="py-1">
{{ t('dialog.transferQueue.sizeTitle') }}{{ formatFileSize(task.fileitem.size || 0) }} {{ t('dialog.transferQueue.sizeTitle') }}{{ formatFileSize(task.fileitem.size || 0) }}
<VChip size="small" :color="getStateColor(task.state)" class="ms-2"> <VChip size="small" :color="getStateColor(task.state)" class="mx-2">
{{ stateDict[task.state] }} {{ stateDict[task.state] }}
</VChip> </VChip>
</VListItemSubtitle> </VListItemSubtitle>
<!-- 当前文件进度显示 -->
<div
v-if="overallProgress.data.current === task.fileitem.path && currentFileProgress.enable"
class="mt-2"
>
<VProgressLinear :value="currentFileProgress.value" color="success" :height="1" class="mb-1" />
<div class="text-xs text-medium-emphasis text-center">
{{ currentFileProgress.value.toFixed(1) }}%
</div>
</div>
<template #append> <template #append>
<IconBtn size="small" icon="mdi-cancel" @click="remove_queue_task(task.fileitem)" /> <IconBtn
size="small"
icon="mdi-cancel"
@click="remove_queue_task(task.fileitem)"
:disabled="overallProgress.data.current === task.fileitem.path"
/>
</template> </template>
</VListItem> </VListItem>
</VList> </VList>
+4
View File
@@ -2090,6 +2090,10 @@ export default {
startAll: 'Start All', startAll: 'Start All',
refresh: 'Refresh', refresh: 'Refresh',
close: 'Close', close: 'Close',
processingFile: 'Processing',
overallProgress: 'Overall Progress',
currentFileProgress: 'Current File Progress',
processingStatus: 'Processing',
}, },
reorganize: { reorganize: {
title: 'Organize', title: 'Organize',
+4
View File
@@ -2064,6 +2064,10 @@ export default {
startAll: '全部开始', startAll: '全部开始',
refresh: '刷新', refresh: '刷新',
close: '关闭', close: '关闭',
processingFile: '正在整理',
overallProgress: '整体进度',
currentFileProgress: '当前文件进度',
processingStatus: '整理中',
}, },
reorganize: { reorganize: {
title: '整理', title: '整理',
+4
View File
@@ -2063,6 +2063,10 @@ export default {
startAll: '全部開始', startAll: '全部開始',
refresh: '刷新', refresh: '刷新',
close: '關閉', close: '關閉',
processingFile: '正在整理',
overallProgress: '整體進度',
currentFileProgress: '當前文件進度',
processingStatus: '整理中',
}, },
reorganize: { reorganize: {
title: '整理', title: '整理',