mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-06 08:06:43 +08:00
重构 TransferQueueDialog 组件,添加整体和当前文件进度管理
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
@@ -2064,6 +2064,10 @@ export default {
|
|||||||
startAll: '全部开始',
|
startAll: '全部开始',
|
||||||
refresh: '刷新',
|
refresh: '刷新',
|
||||||
close: '关闭',
|
close: '关闭',
|
||||||
|
processingFile: '正在整理',
|
||||||
|
overallProgress: '整体进度',
|
||||||
|
currentFileProgress: '当前文件进度',
|
||||||
|
processingStatus: '整理中',
|
||||||
},
|
},
|
||||||
reorganize: {
|
reorganize: {
|
||||||
title: '整理',
|
title: '整理',
|
||||||
|
|||||||
@@ -2063,6 +2063,10 @@ export default {
|
|||||||
startAll: '全部開始',
|
startAll: '全部開始',
|
||||||
refresh: '刷新',
|
refresh: '刷新',
|
||||||
close: '關閉',
|
close: '關閉',
|
||||||
|
processingFile: '正在整理',
|
||||||
|
overallProgress: '整體進度',
|
||||||
|
currentFileProgress: '當前文件進度',
|
||||||
|
processingStatus: '整理中',
|
||||||
},
|
},
|
||||||
reorganize: {
|
reorganize: {
|
||||||
title: '整理',
|
title: '整理',
|
||||||
|
|||||||
Reference in New Issue
Block a user