Skip to content

Commit 93cb42f

Browse files
committed
refactor: unify upload and delete task management
- Consolidate separate upload and delete task managers into a unified TaskManager - Create shared task UI components (stats, panel, list, item) under components/object/task/ - Remove unused compatibility layer stores (useDeleteTaskManagerStore, useUploadTaskManagerStore) - Fix status name inconsistencies in task stores - Remove unused processing-status prop from object-task-stats component This refactoring reduces code duplication by ~1000 lines and provides a more maintainable architecture for task management across upload and delete operations.
1 parent 379e36e commit 93cb42f

21 files changed

Lines changed: 1044 additions & 1221 deletions

‎components/object/delete/stats.vue‎

Lines changed: 0 additions & 19 deletions
This file was deleted.

‎components/object/delete/task/item.vue‎

Lines changed: 0 additions & 38 deletions
This file was deleted.

‎components/object/list.vue‎

Lines changed: 48 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@
99
</label>
1010
</div>
1111
<template #actions>
12-
<object-upload-stats />
13-
<object-delete-stats />
12+
<object-task-stats :tasks="taskStore.tasks" :on-clear-tasks="taskStore.clearTasks">
13+
<template #task-list="{ tasks }">
14+
<object-task-list :tasks="tasks" />
15+
</template>
16+
</object-task-stats>
1417
<!-- <Button variant="outline" @click="() => handleNewObject(true)">
1518
<Icon name="ri:add-line" class="size-4" />
1619
<span>{{ t('New Folder') }}</span>
@@ -19,13 +22,7 @@
1922
<Icon name="ri:file-add-line" class="size-4" />
2023
<span>{{ t('Upload File') }}/{{ t('Folder') }}</span>
2124
</Button>
22-
<Button
23-
variant="outline"
24-
class="text-destructive border-destructive"
25-
:disabled="!checkedKeys.length"
26-
v-show="checkedKeys.length"
27-
@click="handleBatchDelete"
28-
>
25+
<Button variant="outline" class="text-destructive border-destructive" :disabled="!checkedKeys.length" v-show="checkedKeys.length" @click="handleBatchDelete">
2926
<Icon name="ri:delete-bin-5-line" class="size-4" />
3027
<span>{{ t('Delete Selected') }}</span>
3128
</Button>
@@ -40,12 +37,7 @@
4037
</template>
4138
</page-header>
4239

43-
<DataTable
44-
:table="table"
45-
:is-loading="loading"
46-
:empty-title="t('No Objects')"
47-
:empty-description="t('Upload files or create folders to populate this bucket.')"
48-
/>
40+
<DataTable :table="table" :is-loading="loading" :empty-title="t('No Objects')" :empty-description="t('Upload files or create folders to populate this bucket.')" />
4941

5042
<div class="flex justify-end gap-2">
5143
<Button variant="outline" :disabled="!continuationToken" @click="goToPreviousPage">
@@ -59,29 +51,18 @@
5951
</div>
6052
</div>
6153

62-
<object-upload-picker
63-
:show="uploadPickerVisible"
64-
:bucketName="bucketName"
65-
:prefix="prefix"
66-
@update:show="
67-
val => {
68-
uploadPickerVisible = val
69-
refresh()
70-
}
71-
"
72-
/>
73-
<object-new-form
74-
:show="newObjectFormVisible"
75-
:bucketName="bucketName"
76-
:prefix="prefix"
77-
:asPrefix="newObjectAsPrefix"
78-
@update:show="
79-
val => {
80-
newObjectFormVisible = val
81-
refresh()
82-
}
83-
"
84-
/>
54+
<object-upload-picker :show="uploadPickerVisible" :bucketName="bucketName" :prefix="prefix" @update:show="
55+
val => {
56+
uploadPickerVisible = val
57+
refresh()
58+
}
59+
" />
60+
<object-new-form :show="newObjectFormVisible" :bucketName="bucketName" :prefix="prefix" :asPrefix="newObjectAsPrefix" @update:show="
61+
val => {
62+
newObjectFormVisible = val
63+
refresh()
64+
}
65+
" />
8566
<object-info ref="infoRef" :bucket-name="bucketName" @refresh-parent="handleObjectDeleted" />
8667
</template>
8768

@@ -102,9 +83,8 @@ import { saveAs } from 'file-saver'
10283
import JSZip from 'jszip'
10384
import { joinRelativeURL } from 'ufo'
10485
import type { VNode } from 'vue'
105-
import { computed, h, ref, watch } from 'vue'
106-
import { useDeleteTaskManagerStore } from '~/store/delete-tasks'
107-
import { useUploadTaskManagerStore } from '~/store/upload-tasks'
86+
import { computed, h, onMounted, onUnmounted, ref, watch } from 'vue'
87+
import { useTaskManagerStore } from '~/store/tasks'
10888
10989
const { $s3Client } = useNuxtApp()
11090
const { t } = useI18n()
@@ -139,8 +119,7 @@ watch(searchTerm, () => {
139119
handleSearch()
140120
})
141121
142-
const uploadTaskStore = useUploadTaskManagerStore()
143-
const deleteTaskStore = useDeleteTaskManagerStore()
122+
const taskStore = useTaskManagerStore()
144123
145124
type ObjectRow = {
146125
Key: string
@@ -230,9 +209,8 @@ const fetchObjects = async (): Promise<ObjectRow[]> => {
230209
}
231210
232211
const asyncDataCacheKey = computed(() => {
233-
return `objects-${bucketName.value}-${prefix.value}-${continuationToken.value || 'start'}-${searchTerm.value || 'all'}-${
234-
showDeleted.value ? 'withDeleted' : 'withoutDeleted'
235-
}`
212+
return `objects-${bucketName.value}-${prefix.value}-${continuationToken.value || 'start'}-${searchTerm.value || 'all'}-${showDeleted.value ? 'withDeleted' : 'withoutDeleted'
213+
}`
236214
})
237215
238216
const displayKey = (key: string) => {
@@ -318,14 +296,14 @@ const columns = computed<ColumnDef<ObjectRow, any>[]>(() => {
318296
h('div', { class: 'flex items-center gap-2' }, [
319297
row.original.type === 'object'
320298
? h(
321-
Button,
322-
{
323-
variant: 'outline',
324-
size: 'sm',
325-
onClick: () => downloadFile(row.original.Key),
326-
},
327-
() => [h(Icon, { name: 'ri:download-cloud-2-line', class: 'size-4' }), h('span', t('Download'))]
328-
)
299+
Button,
300+
{
301+
variant: 'outline',
302+
size: 'sm',
303+
onClick: () => downloadFile(row.original.Key),
304+
},
305+
() => [h(Icon, { name: 'ri:download-cloud-2-line', class: 'size-4' }), h('span', t('Download'))]
306+
)
329307
: null,
330308
h(
331309
Button,
@@ -352,17 +330,22 @@ const { table, selectedRowIds } = useDataTable<ObjectRow>({
352330
// Use selectedRowIds from data-table instead of manually maintaining checkedKeys
353331
const checkedKeys = computed(() => selectedRowIds.value)
354332
355-
watch(
356-
() => uploadTaskStore.tasks,
357-
() => setTimeout(() => refresh(), 500),
358-
{ deep: true }
359-
)
333+
// 监听任务完成事件,只在所有任务完成时刷新列表
334+
// 这样可以避免在上传/删除大量文件时频繁刷新
335+
// 保存事件处理函数引用,以便在卸载时正确清理
336+
const handleAllTasksCompleted = () => {
337+
refresh()
338+
}
360339
361-
watch(
362-
() => deleteTaskStore.tasks,
363-
() => setTimeout(() => refresh(), 500),
364-
{ deep: true }
365-
)
340+
onMounted(() => {
341+
// 监听所有任务全部完成事件(上传/删除)
342+
taskStore.on('drained', handleAllTasksCompleted)
343+
})
344+
345+
onUnmounted(() => {
346+
// 清理事件监听器
347+
taskStore.off('drained', handleAllTasksCompleted)
348+
})
366349
367350
const goToNextPage = () => {
368351
if (!nextToken.value) return
@@ -518,7 +501,7 @@ const handleDelete = async (keys: string[]) => {
518501
if (!targets.length) {
519502
message.success(t('Delete Success'))
520503
} else {
521-
deleteTaskStore.addKeys(targets, bucketName.value)
504+
taskStore.addDeleteKeys(targets, bucketName.value)
522505
message.success(t('Delete task created'))
523506
}
524507
table.resetRowSelection()

‎components/object/task-stats.vue‎

Lines changed: 0 additions & 149 deletions
This file was deleted.

0 commit comments

Comments
 (0)