feat: 批量下载任务
This commit is contained in:
@ -16,7 +16,7 @@ export function configAutoImport() {
|
|||||||
'@vueuse/core',
|
'@vueuse/core',
|
||||||
{
|
{
|
||||||
dayjs: [['default', 'dayjs']],
|
dayjs: [['default', 'dayjs']],
|
||||||
'lodash-es': ['cloneDeep', 'omit', 'pick', 'union', 'uniq', 'isNumber', 'uniqBy', 'isEmpty', 'merge'],
|
'lodash-es': ['cloneDeep', 'omit', 'pick', 'union', 'uniq', 'isNumber', 'uniqBy', 'isEmpty', 'merge', 'debounce'],
|
||||||
'@/hooks': ['useModal'],
|
'@/hooks': ['useModal'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@ -47,4 +47,14 @@ export const patchTaskRead = (params = {}) => {
|
|||||||
// 任务中心-重做任务
|
// 任务中心-重做任务
|
||||||
export const postRedoTask = (id: string) => {
|
export const postRedoTask = (id: string) => {
|
||||||
return Http.post(`/v1/tasks/${id}/redo`);
|
return Http.post(`/v1/tasks/${id}/redo`);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 任务中心-批量下载
|
||||||
|
export const postBatchDownload = (params = {}) => {
|
||||||
|
return Http.post(`/v1/tasks/batch-download`, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 任务中心-批量查询任务状态
|
||||||
|
export const batchQueryTaskStatus = (params = {}) => {
|
||||||
|
return Http.get(`/v1/tasks/batch-query-status`, params);
|
||||||
};
|
};
|
||||||
@ -3,10 +3,10 @@ import { ref, computed } from 'vue';
|
|||||||
import { Input, Table, TableColumn, Checkbox, Pagination, Button, Tooltip, Notification } from '@arco-design/web-vue';
|
import { Input, Table, TableColumn, Checkbox, Pagination, Button, Tooltip, Notification } from '@arco-design/web-vue';
|
||||||
import { IconSearch, IconClose, IconQuestionCircle } from '@arco-design/web-vue/es/icon';
|
import { IconSearch, IconClose, IconQuestionCircle } from '@arco-design/web-vue/es/icon';
|
||||||
import NoData from '@/components/no-data';
|
import NoData from '@/components/no-data';
|
||||||
import { getTask, postRedoTask } from '@/api/all/common';
|
import { getTask, postRedoTask, postBatchDownload, batchQueryTaskStatus } from '@/api/all/common';
|
||||||
import { INITIAL_FORM, TABLE_COLUMNS } from './constants';
|
import { INITIAL_FORM, TABLE_COLUMNS } from './constants';
|
||||||
import { EXPORT_TASK_STATUS, enumTaskStatus } from '../../constants';
|
import { EXPORT_TASK_STATUS, enumTaskStatus } from '../../constants';
|
||||||
import { formatTableField, exactFormatTime } from '@/utils/tools';
|
import { formatTableField, exactFormatTime, genRandomId } from '@/utils/tools';
|
||||||
import { useTableSelectionWithPagination } from '@/hooks/useTableSelectionWithPagination';
|
import { useTableSelectionWithPagination } from '@/hooks/useTableSelectionWithPagination';
|
||||||
import { downloadByUrl } from '@/utils/tools';
|
import { downloadByUrl } from '@/utils/tools';
|
||||||
import DeleteTaskModal from './delete-task-modal.vue';
|
import DeleteTaskModal from './delete-task-modal.vue';
|
||||||
@ -34,9 +34,11 @@ export default {
|
|||||||
getData();
|
getData();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
let queryTaskTimer = null;
|
||||||
|
|
||||||
const query = ref({ ...INITIAL_FORM });
|
const query = ref(cloneDeep(INITIAL_FORM));
|
||||||
const deleteTaskModalRef = ref(null);
|
const deleteTaskModalRef = ref(null);
|
||||||
|
const downloadTaskIds = ref([]);
|
||||||
|
|
||||||
const checkedAll = computed(() => selectedRows.value.length === dataSource.value.length);
|
const checkedAll = computed(() => selectedRows.value.length === dataSource.value.length);
|
||||||
const indeterminate = computed(
|
const indeterminate = computed(
|
||||||
@ -44,11 +46,12 @@ export default {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
query.value = { ...INITIAL_FORM };
|
query.value = cloneDeep(INITIAL_FORM);
|
||||||
pageInfo.value = { ...DEFAULT_PAGE_INFO };
|
pageInfo.value = cloneDeep(DEFAULT_PAGE_INFO);
|
||||||
selectedRowKeys.value = [];
|
selectedRowKeys.value = [];
|
||||||
selectedRows.value = [];
|
selectedRows.value = [];
|
||||||
dataSource.value = [];
|
dataSource.value = [];
|
||||||
|
downloadTaskIds.value = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
const init = () => {
|
const init = () => {
|
||||||
@ -82,7 +85,7 @@ export default {
|
|||||||
reload();
|
reload();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCloseTip = () => {
|
const clearSelectedRows = () => {
|
||||||
selectedRows.value = [];
|
selectedRows.value = [];
|
||||||
selectedRowKeys.value = [];
|
selectedRowKeys.value = [];
|
||||||
};
|
};
|
||||||
@ -98,8 +101,66 @@ export default {
|
|||||||
record.file && downloadByUrl(record.file);
|
record.file && downloadByUrl(record.file);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleBatchDownload = () => {
|
|
||||||
// 批量下载逻辑
|
const clearQueryTaskTimer = () => {
|
||||||
|
if (queryTaskTimer) {
|
||||||
|
clearInterval(queryTaskTimer);
|
||||||
|
queryTaskTimer = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const startBatchDownload = (id) => {
|
||||||
|
const randomId = genRandomId();
|
||||||
|
showExportNotification(
|
||||||
|
`正在批量下载“${selectedRows.value[0]?.name}”等${selectedRows.value.length}个文件,请稍后...`,
|
||||||
|
{
|
||||||
|
duration: 0,
|
||||||
|
id: randomId,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
downloadTaskIds.value.push({
|
||||||
|
id,
|
||||||
|
randomId,
|
||||||
|
});
|
||||||
|
|
||||||
|
// getSyncTaskStatus(randomId);
|
||||||
|
if (!queryTaskTimer) {
|
||||||
|
queryTaskTimer = setInterval(() => getSyncTaskStatus(), 3000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleBatchDownload = debounce(async () => {
|
||||||
|
const { code, data } = await postBatchDownload({ ids: selectedRowKeys.value });
|
||||||
|
if (code === 200) {
|
||||||
|
startBatchDownload(data.id);
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
const getSyncTaskStatus = async () => {
|
||||||
|
const { code, data } = await batchQueryTaskStatus({ ids: downloadTaskIds.value.map((v) => v.id) });
|
||||||
|
if (code === 200) {
|
||||||
|
let completeTaskNum = 0;
|
||||||
|
data.forEach((item) => {
|
||||||
|
const { status, file, id } = item;
|
||||||
|
if (status !== 0) {
|
||||||
|
completeTaskNum++;
|
||||||
|
|
||||||
|
const notificationId = downloadTaskIds.value.find((v) => v.id === id)?.randomId;
|
||||||
|
notificationId && Notification.remove(notificationId);
|
||||||
|
|
||||||
|
if (status === 1) {
|
||||||
|
AMessage.success('批量下载已完成,正在下载文件...');
|
||||||
|
downloadByUrl(file);
|
||||||
|
} else if (status === 2) {
|
||||||
|
AMessage.error('批量下载失败,请重新尝试下载');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 全部完成了
|
||||||
|
if (completeTaskNum === data.length) {
|
||||||
|
clearQueryTaskTimer();
|
||||||
|
clearSelectedRows();
|
||||||
|
downloadTaskIds.value = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDelete = (record) => {
|
const handleDelete = (record) => {
|
||||||
@ -121,8 +182,14 @@ export default {
|
|||||||
selectedRowKeys.value = [];
|
selectedRowKeys.value = [];
|
||||||
getData();
|
getData();
|
||||||
};
|
};
|
||||||
|
const unloadComp = () => {
|
||||||
|
clearQueryTaskTimer();
|
||||||
|
};
|
||||||
|
onUnmounted(() => {
|
||||||
|
clearQueryTaskTimer;
|
||||||
|
});
|
||||||
|
|
||||||
expose({ init, reset });
|
expose({ init, reset, unloadComp });
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<div class="export-task-wrap">
|
<div class="export-task-wrap">
|
||||||
@ -187,7 +254,7 @@ export default {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<IconClose size={16} class="cursor-pointer color-#737478" onClick={handleCloseTip} />
|
<IconClose size={16} class="cursor-pointer color-#737478" onClick={clearSelectedRows} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@ -252,7 +319,7 @@ export default {
|
|||||||
))}
|
))}
|
||||||
<TableColumn
|
<TableColumn
|
||||||
data-index="operation"
|
data-index="operation"
|
||||||
width={100}
|
width={110}
|
||||||
fixed="right"
|
fixed="right"
|
||||||
title="操作"
|
title="操作"
|
||||||
v-slots={{
|
v-slots={{
|
||||||
|
|||||||
@ -52,6 +52,7 @@ const onClose = () => {
|
|||||||
activeTab.value = '0';
|
activeTab.value = '0';
|
||||||
|
|
||||||
clearTimer();
|
clearTimer();
|
||||||
|
componentRef.value?.unloadComp?.()
|
||||||
visible.value = false;
|
visible.value = false;
|
||||||
};
|
};
|
||||||
const clearTimer = () => {
|
const clearTimer = () => {
|
||||||
|
|||||||
@ -13,7 +13,7 @@ interface RenderNotificationData {
|
|||||||
file?: string;
|
file?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function showExportNotification(label: string, id: '') {
|
export function showExportNotification(label: string, { id = '', duration = 3000}) {
|
||||||
Notification.warning({
|
Notification.warning({
|
||||||
id,
|
id,
|
||||||
showIcon: false,
|
showIcon: false,
|
||||||
@ -24,7 +24,7 @@ export function showExportNotification(label: string, id: '') {
|
|||||||
<p class="text-14px lh-22px font-400 color-#211F24">{label}</p>
|
<p class="text-14px lh-22px font-400 color-#211F24">{label}</p>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
duration: 3000,
|
duration,
|
||||||
class: 'px-16px py-9px w-400px rounded-2px bg-#F0EDFF',
|
class: 'px-16px py-9px w-400px rounded-2px bg-#F0EDFF',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -107,3 +107,6 @@ export function downloadByUrl(url: string, filename?: string) {
|
|||||||
document.body.removeChild(a);
|
document.body.removeChild(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function genRandomId() {
|
||||||
|
return `id_${Date.now()}_${Math.floor(Math.random() * 10000)}`;
|
||||||
|
}
|
||||||
@ -28,6 +28,7 @@ import SyncDataModal from '../sync-data-modal';
|
|||||||
|
|
||||||
// import { downloadByUrl } from '@/utils/tools';
|
// import { downloadByUrl } from '@/utils/tools';
|
||||||
import { showExportNotification } from '@/utils/arcoD';
|
import { showExportNotification } from '@/utils/arcoD';
|
||||||
|
import { genRandomId } from '@/utils/tools';
|
||||||
import {
|
import {
|
||||||
fetchAccountTags,
|
fetchAccountTags,
|
||||||
fetchAccountGroups,
|
fetchAccountGroups,
|
||||||
@ -188,9 +189,9 @@ export default {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (code === 200) {
|
if (code === 200) {
|
||||||
const ID = 'IMPORT-ACCOUNT';
|
const id = genRandomId();
|
||||||
showExportNotification(`正在导入“${file.value.name}”,请稍后...`, ID);
|
showExportNotification(`正在导入“${file.value.name}”,请稍后...`, { id });
|
||||||
emit('startQueryTaskStatus', data.id, ID);
|
emit('startQueryTaskStatus', data.id, id);
|
||||||
onClose();
|
onClose();
|
||||||
} else {
|
} else {
|
||||||
uploadStatus.value = UploadStatus.ERROR;
|
uploadStatus.value = UploadStatus.ERROR;
|
||||||
|
|||||||
@ -151,6 +151,7 @@ import StatusBox from '../status-box';
|
|||||||
import { PLATFORM_LIST, ENUM_PLATFORM } from '@/views/property-marketing/put-account/common_constants';
|
import { PLATFORM_LIST, ENUM_PLATFORM } from '@/views/property-marketing/put-account/common_constants';
|
||||||
|
|
||||||
import { showExportNotification } from '@/utils/arcoD';
|
import { showExportNotification } from '@/utils/arcoD';
|
||||||
|
import { genRandomId } from '@/utils/tools';
|
||||||
import {
|
import {
|
||||||
postPlacementAccounts,
|
postPlacementAccounts,
|
||||||
getPlacementAccountsDetail,
|
getPlacementAccountsDetail,
|
||||||
@ -289,9 +290,9 @@ const handleBatchImport = async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (code === 200) {
|
if (code === 200) {
|
||||||
const ID = 'IMPORT-PUT-ACCOUNT';
|
const id = genRandomId();
|
||||||
showExportNotification(`正在导入“${file.value.name}”,请稍后...`, ID);
|
showExportNotification(`正在导入“${file.value.name}”,请稍后...`, { id });
|
||||||
emits('startQueryTaskStatus', data.id, ID);
|
emit('startQueryTaskStatus', data.id, id);
|
||||||
onClose();
|
onClose();
|
||||||
} else {
|
} else {
|
||||||
uploadStatus.value = UploadStatus.ERROR;
|
uploadStatus.value = UploadStatus.ERROR;
|
||||||
|
|||||||
Reference in New Issue
Block a user