UPDATE: 异步导出检测数据逻辑。

This commit is contained in:
贾同学
2025-09-19 16:18:10 +08:00
parent 3e7509cd44
commit a9156f0954
4 changed files with 150 additions and 15 deletions

View File

@@ -211,13 +211,19 @@ class RequestHttp {
const eventSource = new EventSourcePolyfill(requestUrl, {
headers: {
Authorization: 'Bearer ' + userStore.accessToken
}
},
// 增加超时时间到120秒
heartbeatTimeout: 120000
})
// 设置默认的Authorization头部
eventSource.addEventListener('open', function () {
console.log('SSE连接已建立')
})
// 添加错误处理
eventSource.addEventListener('error', function (err) {
console.error('SSE连接错误:', err)
})
return eventSource
}

View File

@@ -136,7 +136,7 @@ export const importSubPlan = (params: Plan.ResPlan) => {
// 导出计划检测结果数据
export const exportPlanCheckData = (params: any) => {
return http.download(
return http.post(
`/adPlan/exportPlanCheckData?planId=${params.id}&devIds=${params.devIds}&report=${params.report}`
)
}

View File

@@ -5,6 +5,7 @@
:destroy-on-close="true"
width="450px"
:close-on-click-modal="!parameter.progressBar"
:show-close="!disable"
draggable
>
<el-upload
@@ -20,7 +21,7 @@
:disabled="fileDisabled"
>
<slot name="empty">
<el-button type="primary" icon="Upload">点击上传</el-button>
<el-button type="primary" :disabled="fileDisabled" icon="Upload">点击上传</el-button>
</slot>
<template #tip>
<slot name="tip">
@@ -28,11 +29,7 @@
</slot>
</template>
</el-upload>
<el-progress
v-if="parameter.progressBar"
:status="progressData.status"
:percentage="progressData.percentage"
></el-progress>
<el-text v-if="parameter.progressBar && progressData.status === 'exception'" size="small" type="danger">
{{ progressData.message }}
</el-text>
@@ -42,6 +39,15 @@
<el-text v-if="parameter.progressBar && progressData.status === ''" size="small" type="info">
{{ progressData.message }}
</el-text>
<el-progress
style="margin-top: 10px; margin-bottom: 10px"
v-if="parameter.progressBar"
:status="progressData.status"
:percentage="progressData.percentage"
:stroke-width="10"
striped
striped-flow
></el-progress>
<template #footer v-if="parameter.confirmMessage">
<el-button :disabled="disable" type="primary" @click="uploadSubmit">开始导入</el-button>
@@ -96,7 +102,12 @@ const uploadZip = (param: UploadRequestOptions) => {
}
setTimeout(() => {
parameter.value.importApi!(zipFormData).then(res => handleImportResponse(res))
parameter.value.importApi!(zipFormData)
.then(res => handleImportResponse(res))
.catch(err => {
fileDisabled.value = false
disable.value = false
})
}, 1000)
}
@@ -104,13 +115,17 @@ const handleImportResponse = (res: any) => {
if (!parameter.value.progressBar) {
if (res.code === 'A0000') {
ElMessage.success('导入成功')
} else {
ElMessage.error(res.message)
}
dialogVisible.value = false
emit('result', res.data)
} else {
//
ElMessage.error(res.message)
fileDisabled.value = false
disable.value = false
}
} else {
if (res.code !== 'A0000') {
ElMessage.error(res.message)
}
}
}

View File

@@ -172,6 +172,45 @@
<PlanPopup ref="planPopup" :refresh-table="proTable?.getTableList" @update:tab="addNewChildTab" />
<DevTransfer ref="devTransfer" @update:table="addNewChildTab" />
<ImportZip ref="planCheckDataImportZip" @result="importResult" />
<el-dialog
v-model="showProgress"
title="数据下载进度"
width="500"
draggable
:show-close="false"
:close-on-click-modal="false"
>
<el-row style="margin-top: 10px">
<el-text v-if="progressData.status === ''" type="info">
{{ progressData.message }}
</el-text>
<el-text v-if="progressData.status === 'exception'" type="danger">
{{ progressData.message }}
</el-text>
<el-text v-if="progressData.status === 'success'">文件所在目录:</el-text>
<el-link
v-if="progressData.status === 'success'"
type="primary"
title="点击打开目录"
:href="progressData.message"
@click="openDownloadLocation"
>
{{ progressData.message }}
</el-link>
</el-row>
<el-progress
style="margin-top: 10px; margin-bottom: 10px"
:status="progressData.status"
:percentage="progressData.percentage"
:stroke-width="10"
striped
striped-flow
></el-progress>
<template #footer>
<el-button :disabled="progressData.status === ''" @click="showProgress = false">关闭</el-button>
</template>
</el-dialog>
</template>
<script lang="tsx" setup>
import { ElFormItem, ElMessage, ElMessageBox, ElSwitch, type TabPaneName } from 'element-plus'
@@ -195,6 +234,7 @@ import { useHandleData } from '@/hooks/useHandleData'
import router from '@/routers'
import { useDownload } from '@/hooks/useDownload'
import ImportZip from '@/components/ImportZip/index.vue'
import http from '@/api'
const dictStore = useDictStore()
const planFormContent = ref<Plan.ReqPlan>()
@@ -642,28 +682,103 @@ const exportPlan = async () => {
useDownload(exportSubPlan, `${subPlanFormContent.name}_子计划元信息`, params, false, '.zip')
)
}
const exportPlanCheckResultData = async (selectedListIds: string[]) => {
const params = {
id: planFormContent.value.id,
report: downloadReport.value,
devIds: selectedListIds.join(',')
}
progressData.value = {
percentage: 0,
status: '',
message: ''
}
initSSE()
ElMessageBox.confirm(vnode, '温馨提示', {
type: '',
distinguishCancelAndClose: true,
closeOnClickModal: false,
confirmButtonText: '确定',
cancelButtonText: '取消'
})
.then(() => {
params.report = downloadReport.value
useDownload(exportPlanCheckData, `${planFormContent.value.name}_检测计划检测数据包`, params, false, '.zip')
exportPlanCheckData(params).then(res => {
if (res.code !== 'A0000') {
ElMessage.error(res.message)
} else {
showProgress.value = true
}
})
})
.catch(action => {
// 用户取消或关闭对话框
console.log('用户取消操作: ', action)
closeEventSource()
})
}
const eventSource = ref<EventSource | null>(null)
const showProgress = ref(false)
const filePath = ref('')
const progressData = ref({
percentage: 0,
status: '',
message: ''
})
const initSSE = () => {
eventSource.value = http.sse('/sse/createSse')
eventSource.value.onmessage = event => {
console.log('收到消息内容是:', event.data)
const res = JSON.parse(event.data)
progressData.value.percentage = res.data
progressData.value.message = res.message
if (res.code === 'A0002') {
progressData.value.status = 'exception'
ElMessage.error(res.message)
}
if (progressData.value.percentage === 100) {
progressData.value.status = 'success'
eventSource.value!.close()
filePath.value = res.message
}
}
eventSource.value.onerror = error => {
console.warn('SSE 连接出错:', error)
eventSource.value!.close()
}
}
const closeEventSource = () => {
if (eventSource.value) {
eventSource.value.close()
eventSource.value = null
console.log('SSE连接已关闭')
}
}
// 打开下载文件所在位置
const openDownloadLocation = () => {
try {
const Renderer = window.require && window.require('electron')
if (Renderer && Renderer.shell) {
if (filePath.value) {
// 打开指定文件所在的目录,并选中该文件
Renderer.shell.showItemInFolder(filePath.value)
} else {
// 使用默认下载路径
const downloadPath = Renderer.app.getPath('downloads')
Renderer.shell.openPath(downloadPath)
}
} else {
ElMessage.warning('当前运行环境不支持,请复制路径自行打开')
}
} catch (error) {
console.error('打开文件所在位置时出错:', error)
ElMessage.error('打开文件所在位置失败')
}
}
const importAndMergePlanCheckDataClick = () => {
const params = {
title: '合并检测计划检测结果',
@@ -675,7 +790,6 @@ const importAndMergePlanCheckDataClick = () => {
}
planCheckDataImportZip.value?.acceptParams(params)
}
const importResult = async (success: boolean | undefined) => {
if (success) {
await props.refreshTable!()