|
|
|
@ -1,6 +1,6 @@ |
|
|
|
<script setup> |
|
|
|
// 修复部署加载问题 - 强制刷新文件Hash |
|
|
|
import { onMounted, ref, watch } from 'vue' |
|
|
|
import { onBeforeUnmount, onMounted, ref, watch } from 'vue' |
|
|
|
import { ElMessage } from 'element-plus' |
|
|
|
import moment from 'moment' |
|
|
|
import API from '@/util/http.js' |
|
|
|
@ -531,10 +531,12 @@ const exportExcel = async function () { |
|
|
|
} |
|
|
|
|
|
|
|
const exportListVisible = ref(false) |
|
|
|
// 轮询频率控制在 3 秒,兼顾实时性和接口压力。 |
|
|
|
const EXPORT_LIST_POLL_INTERVAL = 3000 |
|
|
|
let exportListPollingTimer = null |
|
|
|
|
|
|
|
// 打开导出列表弹窗 |
|
|
|
const openExportList = () => { |
|
|
|
getExportList() |
|
|
|
exportListVisible.value = true |
|
|
|
} |
|
|
|
|
|
|
|
@ -542,9 +544,47 @@ const openExportList = () => { |
|
|
|
const exportList = ref([]) |
|
|
|
// 导出列表加载状态 |
|
|
|
const exportListLoading = ref(false) |
|
|
|
// 防止上一次列表请求还没结束时,又被轮询或手动操作重复触发。 |
|
|
|
const exportListRequesting = ref(false) |
|
|
|
|
|
|
|
// 只有待执行/执行中的任务,才需要继续轮询刷新列表。 |
|
|
|
const hasPendingExportTask = (list = []) => { |
|
|
|
return list.some(item => item.state === 0 || item.state === 1) |
|
|
|
} |
|
|
|
|
|
|
|
// 统一停止轮询,避免弹窗关闭后定时器还在继续请求接口。 |
|
|
|
const stopExportListPolling = () => { |
|
|
|
if (exportListPollingTimer) { |
|
|
|
clearInterval(exportListPollingTimer) |
|
|
|
exportListPollingTimer = null |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 只在存在未完成任务时启动轮询;如果已经启动过,则不重复创建定时器。 |
|
|
|
const startExportListPolling = () => { |
|
|
|
if (exportListPollingTimer) { |
|
|
|
return |
|
|
|
} |
|
|
|
exportListPollingTimer = setInterval(() => { |
|
|
|
// 弹窗关闭后立即停止轮询,避免无意义请求。 |
|
|
|
if (!exportListVisible.value) { |
|
|
|
stopExportListPolling() |
|
|
|
return |
|
|
|
} |
|
|
|
getExportList({ showLoading: false, silentError: true }) |
|
|
|
}, EXPORT_LIST_POLL_INTERVAL) |
|
|
|
} |
|
|
|
|
|
|
|
// 获取导出列表 |
|
|
|
const getExportList = async () => { |
|
|
|
exportListLoading.value = true |
|
|
|
const getExportList = async ({ showLoading = true, silentError = false } = {}) => { |
|
|
|
// 轮询期间如果上一次请求未结束,直接跳过,避免并发请求堆积。 |
|
|
|
if (exportListRequesting.value) { |
|
|
|
return |
|
|
|
} |
|
|
|
if (showLoading) { |
|
|
|
exportListLoading.value = true |
|
|
|
} |
|
|
|
exportListRequesting.value = true |
|
|
|
try { |
|
|
|
const result = await API({ url: '/export/export' }) |
|
|
|
if (result.code === 200) { |
|
|
|
@ -552,14 +592,29 @@ const getExportList = async () => { |
|
|
|
return item.type === 2; //2表示金币充值列表 |
|
|
|
}); |
|
|
|
exportList.value = filteredData |
|
|
|
// 打开弹窗且仍有未完成任务时继续轮询;全部完成/失败后自动停掉。 |
|
|
|
if (exportListVisible.value && hasPendingExportTask(filteredData)) { |
|
|
|
startExportListPolling() |
|
|
|
} else { |
|
|
|
stopExportListPolling() |
|
|
|
} |
|
|
|
} else { |
|
|
|
ElMessage.error(result.msg || t('elmessage.getExportListError')) |
|
|
|
stopExportListPolling() |
|
|
|
if (!silentError) { |
|
|
|
ElMessage.error(result.msg || t('elmessage.getExportListError')) |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (error) { |
|
|
|
console.error('获取导出列表出错:', error) |
|
|
|
ElMessage.error(t('elmessage.getExportListError')) |
|
|
|
stopExportListPolling() |
|
|
|
if (!silentError) { |
|
|
|
ElMessage.error(t('elmessage.getExportListError')) |
|
|
|
} |
|
|
|
} finally { |
|
|
|
exportListLoading.value = false |
|
|
|
exportListRequesting.value = false |
|
|
|
if (showLoading) { |
|
|
|
exportListLoading.value = false |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
// 下载导出文件 |
|
|
|
@ -604,6 +659,20 @@ const getTagText = (state) => { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 弹窗打开时先拉一次最新列表;弹窗关闭时停止轮询。 |
|
|
|
watch(exportListVisible, (visible) => { |
|
|
|
if (visible) { |
|
|
|
getExportList() |
|
|
|
} else { |
|
|
|
stopExportListPolling() |
|
|
|
} |
|
|
|
}) |
|
|
|
|
|
|
|
// 页面销毁时兜底清理定时器,避免离开页面后还在轮询。 |
|
|
|
onBeforeUnmount(() => { |
|
|
|
stopExportListPolling() |
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
</script> |
|
|
|
|
|
|
|
|