diff --git a/frontend/src/hooks/useWebsocket.ts b/frontend/src/hooks/useWebsocket.ts new file mode 100644 index 0000000000..e936733599 --- /dev/null +++ b/frontend/src/hooks/useWebsocket.ts @@ -0,0 +1,30 @@ +import { getSocket } from '@/api/modules/project-management/commonScript'; + +export interface WebsocketParams { + reportId: string | number; + socketUrl?: string; + host?: string; + onMessage?: (event: MessageEvent) => void; +} + +export default function useWebsocket(options: WebsocketParams) { + const websocket = ref(); + function createSocket() { + return new Promise((resolve) => { + websocket.value = getSocket(options.reportId, options.socketUrl, options.host); + websocket.value.addEventListener('message', (event) => { + if (options.onMessage) { + options.onMessage(event); + } + }); + websocket.value.addEventListener('open', () => { + resolve(true); + }); + }); + } + + return { + websocket, + createSocket, + }; +} diff --git a/frontend/src/views/api-test/components/requestComposition/index.vue b/frontend/src/views/api-test/components/requestComposition/index.vue index c90c380311..2cd1c9f9e5 100644 --- a/frontend/src/views/api-test/components/requestComposition/index.vue +++ b/frontend/src/views/api-test/components/requestComposition/index.vue @@ -510,10 +510,10 @@ import { getPluginScript, getProtocolList } from '@/api/modules/api-test/common'; import { addCase } from '@/api/modules/api-test/management'; - import { getSocket } from '@/api/modules/project-management/commonScript'; import { getProjectOptions } from '@/api/modules/project-management/projectMember'; import { useI18n } from '@/hooks/useI18n'; import useShortcutSave from '@/hooks/useShortcutSave'; + import useWebsocket from '@/hooks/useWebsocket'; import useRequestCompositionStore from '@/store/modules/api/requestComposition'; import useAppStore from '@/store/modules/app'; import useUserStore from '@/store/modules/user'; @@ -1026,40 +1026,42 @@ /** * 开启websocket监听,接收执行结果 */ - function debugSocket(executeType?: 'localExec' | 'serverExec') { - websocket.value = getSocket( - reportId.value, - executeType === 'localExec' ? '/ws/debug' : '', - executeType === 'localExec' ? localExecuteUrl.value : '' - ); - websocket.value.addEventListener('message', (event) => { - const data = JSON.parse(event.data); - if (data.msgType === 'EXEC_RESULT') { - if (requestVModel.value.reportId === data.reportId) { - // 判断当前查看的tab是否是当前返回的报告的tab,是的话直接赋值 - requestVModel.value.response = data.taskResult; - requestVModel.value.executeLoading = false; - requestVModel.value.isExecute = false; - } else { - // 不是则需要把报告缓存起来,等切换到对应的tab再赋值 - temporaryResponseMap[data.reportId] = data.taskResult; + async function debugSocket(executeType?: 'localExec' | 'serverExec') { + const { createSocket, websocket: _websocket } = useWebsocket({ + reportId: reportId.value, + socketUrl: executeType === 'localExec' ? '/ws/debug' : '', + host: executeType === 'localExec' ? localExecuteUrl.value : '', + onMessage: (event) => { + const data = JSON.parse(event.data); + if (data.msgType === 'EXEC_RESULT') { + if (requestVModel.value.reportId === data.reportId) { + // 判断当前查看的tab是否是当前返回的报告的tab,是的话直接赋值 + requestVModel.value.response = data.taskResult; + requestVModel.value.executeLoading = false; + requestVModel.value.isExecute = false; + } else { + // 不是则需要把报告缓存起来,等切换到对应的tab再赋值 + temporaryResponseMap[data.reportId] = data.taskResult; + } + } else if (data.msgType === 'EXEC_END') { + // 执行结束,关闭websocket + websocket.value?.close(); + if (requestVModel.value.reportId === data.reportId) { + requestVModel.value.executeLoading = false; + requestVModel.value.isExecute = false; + } } - } else if (data.msgType === 'EXEC_END') { - // 执行结束,关闭websocket - websocket.value?.close(); - if (requestVModel.value.reportId === data.reportId) { - requestVModel.value.executeLoading = false; - requestVModel.value.isExecute = false; - } - } + }, }); + await createSocket(); + websocket.value = _websocket.value; } /** * 生成请求参数 * @param executeType 执行类型,执行时传入 */ - function makeRequestParams(executeType?: 'localExec' | 'serverExec') { + async function makeRequestParams(executeType?: 'localExec' | 'serverExec') { const isExecute = executeType === 'localExec' || executeType === 'serverExec'; const { formDataBody, wwwFormBody, jsonBody } = requestVModel.value.body; const polymorphicName = protocolOptions.value.find( @@ -1120,7 +1122,7 @@ reportId.value = getGenerateId(); requestVModel.value.reportId = reportId.value; // 存储报告ID if (isExecute && !props.isCase) { - debugSocket(executeType); // 开启websocket + await debugSocket(executeType); // 开启websocket } let requestName = ''; let requestModuleId = ''; @@ -1199,7 +1201,7 @@ await nextTick(); requestVModel.value.executeLoading = true; requestVModel.value.response = cloneDeep(defaultResponse); - const res = await props.executeApi(makeRequestParams(executeType) as ExecuteRequestParams); + const res = await props.executeApi((await makeRequestParams(executeType)) as ExecuteRequestParams); if (executeType === 'localExec' && props.localExecuteApi && localExecuteUrl.value) { await props.localExecuteApi(localExecuteUrl.value, res); } @@ -1217,7 +1219,7 @@ if (!props.executeApi) return; requestVModel.value.executeLoading = true; requestVModel.value.response = cloneDeep(defaultResponse); - const res = await props.executeApi(makeRequestParams(executeType) as ExecuteRequestParams); + const res = await props.executeApi((await makeRequestParams(executeType)) as ExecuteRequestParams); if (executeType === 'localExec' && props.localExecuteApi && localExecuteUrl.value) { await props.localExecuteApi(localExecuteUrl.value, res); } @@ -1347,7 +1349,7 @@ saveLoading.value = true; } let params; - const requestParams = makeRequestParams(); + const requestParams = await makeRequestParams(); if (props.isDefinition) { params = { ...(fullParams || requestParams), @@ -1551,7 +1553,7 @@ if (!errors) { try { saveCaseLoading.value = true; - const definitionParams = makeRequestParams(); + const definitionParams = await makeRequestParams(); if (requestVModel.value.isNew) { // 未保存过的接口保存为用例,先保存接口定义,再保存为用例 await realSave(definitionParams, true); @@ -1614,7 +1616,7 @@ const tempApiDetail = ref(); const saveNewApiModalVisible = ref(false); - function handleSelect(value: string | number | Record | undefined) { + async function handleSelect(value: string | number | Record | undefined) { if (requestVModel.value.url === '' && requestVModel.value.protocol === 'HTTP') { isUrlError.value = true; return; @@ -1626,7 +1628,7 @@ isUrlError.value = false; isNameError.value = false; if (value === 'saveAsApi') { - const params = makeRequestParams(); + const params = await makeRequestParams(); tempApiDetail.value = { ...params, ...params.request, diff --git a/frontend/src/views/api-test/management/components/management/api/apiTable.vue b/frontend/src/views/api-test/management/components/management/api/apiTable.vue index 2d1ba93f16..47fd813abc 100644 --- a/frontend/src/views/api-test/management/components/management/api/apiTable.vue +++ b/frontend/src/views/api-test/management/components/management/api/apiTable.vue @@ -322,10 +322,10 @@ stopApiExport, updateDefinition, } from '@/api/modules/api-test/management'; - import { getSocket } from '@/api/modules/project-management/commonScript'; import { useI18n } from '@/hooks/useI18n'; import useModal from '@/hooks/useModal'; import useTableStore from '@/hooks/useTableStore'; + import useWebsocket from '@/hooks/useWebsocket'; import useAppStore from '@/store/modules/app'; import useCacheStore from '@/store/modules/cache/cache'; import { characterLimit, downloadByteFile, getGenerateId, operationWidth } from '@/utils'; @@ -1136,26 +1136,31 @@ const exportingMessage = ref(); // 开启websocket监听,接收结果 - function startWebsocketGetExportResult() { - websocket.value = getSocket(reportId.value, '/ws/export'); - websocket.value.addEventListener('message', (event) => { - const data = JSON.parse(event.data); - if (data.msgType === 'EXEC_RESULT') { - exportingMessage.value.close(); - reportId.value = data.fileId; - // taskId.value = data.taskId; - if (data.isSuccessful) { - showExportSuccessfulMessage(reportId.value, data.count); - } else { - Message.error({ - content: t('common.exportFailed'), - duration: 999999999, // 一直展示,除非手动关闭 - closable: true, - }); + async function startWebsocketGetExportResult() { + const { createSocket, websocket: _websocket } = useWebsocket({ + reportId: reportId.value, + socketUrl: '/ws/export', + onMessage: (event) => { + const data = JSON.parse(event.data); + if (data.msgType === 'EXEC_RESULT') { + exportingMessage.value.close(); + reportId.value = data.fileId; + // taskId.value = data.taskId; + if (data.isSuccessful) { + showExportSuccessfulMessage(reportId.value, data.count); + } else { + Message.error({ + content: t('common.exportFailed'), + duration: 999999999, // 一直展示,除非手动关闭 + closable: true, + }); + } + websocket.value?.close(); } - websocket.value?.close(); - } + }, }); + await createSocket(); + websocket.value = _websocket.value; } // 取消导出 @@ -1203,7 +1208,7 @@ try { exportLoading.value = true; reportId.value = getGenerateId(); - startWebsocketGetExportResult(); + await startWebsocketGetExportResult(); const batchConditionParams = await getBatchConditionParams(); const res = await exportApiDefinition( { diff --git a/frontend/src/views/api-test/management/components/management/case/caseDetail.vue b/frontend/src/views/api-test/management/components/management/case/caseDetail.vue index 381c8c324c..a32c47bb96 100644 --- a/frontend/src/views/api-test/management/components/management/case/caseDetail.vue +++ b/frontend/src/views/api-test/management/components/management/case/caseDetail.vue @@ -140,8 +140,8 @@ import { localExecuteApiDebug, stopExecute, stopLocalExecute } from '@/api/modules/api-test/common'; import { debugCase, deleteCase, runCase, toggleFollowCase } from '@/api/modules/api-test/management'; - import { getSocket } from '@/api/modules/project-management/commonScript'; import useModal from '@/hooks/useModal'; + import useWebsocket from '@/hooks/useWebsocket'; import useAppStore from '@/store/modules/app'; import { getGenerateId } from '@/utils'; @@ -276,31 +276,33 @@ const websocket = ref(); const temporaryResponseMap: Record = {}; // 缓存websocket返回的报告内容,避免执行接口后切换tab导致报告丢失 // 开启websocket监听,接收执行结果 - function debugSocket(executeType?: 'localExec' | 'serverExec') { - websocket.value = getSocket( - reportId.value, - executeType === 'localExec' ? '/ws/debug' : '', - executeType === 'localExec' ? executeRef.value?.localExecuteUrl : '' - ); - websocket.value.addEventListener('message', (event) => { - const data = JSON.parse(event.data); - if (data.msgType === 'EXEC_RESULT') { - if (caseDetail.value.reportId === data.reportId) { - // 判断当前查看的tab是否是当前返回的报告的tab,是的话直接赋值 - caseDetail.value.response = data.taskResult; // 渲染出用例详情和创建用例抽屉的响应数据 + async function debugSocket(executeType?: 'localExec' | 'serverExec') { + const { createSocket, websocket: _websocket } = useWebsocket({ + reportId: reportId.value, + socketUrl: executeType === 'localExec' ? '/ws/debug' : '', + host: executeType === 'localExec' ? executeRef.value?.localExecuteUrl : '', + onMessage: (event) => { + const data = JSON.parse(event.data); + if (data.msgType === 'EXEC_RESULT') { + if (caseDetail.value.reportId === data.reportId) { + // 判断当前查看的tab是否是当前返回的报告的tab,是的话直接赋值 + caseDetail.value.response = data.taskResult; // 渲染出用例详情和创建用例抽屉的响应数据 + caseDetail.value.executeLoading = false; + executeCase.value = false; + } else { + // 不是则需要把报告缓存起来,等切换到对应的tab再赋值 + temporaryResponseMap[data.reportId] = data.taskResult; + } + } else if (data.msgType === 'EXEC_END') { + // 执行结束,关闭websocket + websocket.value?.close(); caseDetail.value.executeLoading = false; executeCase.value = false; - } else { - // 不是则需要把报告缓存起来,等切换到对应的tab再赋值 - temporaryResponseMap[data.reportId] = data.taskResult; } - } else if (data.msgType === 'EXEC_END') { - // 执行结束,关闭websocket - websocket.value?.close(); - caseDetail.value.executeLoading = false; - executeCase.value = false; - } + }, }); + await createSocket(); + websocket.value = _websocket.value; } async function handleExecute(executeType?: 'localExec' | 'serverExec') { try { @@ -320,7 +322,7 @@ linkFileIds: caseDetail.value.linkFileIds, uploadFileIds: caseDetail.value.uploadFileIds, }; - debugSocket(executeType); // 开启websocket + await debugSocket(executeType); // 开启websocket if (executeType === 'serverExec') { // 已创建的服务端 res = await runCase(params); diff --git a/frontend/src/views/api-test/management/components/management/case/createAndEditCaseDrawer.vue b/frontend/src/views/api-test/management/components/management/case/createAndEditCaseDrawer.vue index 539476a745..ccfffe57e0 100644 --- a/frontend/src/views/api-test/management/components/management/case/createAndEditCaseDrawer.vue +++ b/frontend/src/views/api-test/management/components/management/case/createAndEditCaseDrawer.vue @@ -124,9 +124,9 @@ updateCase, uploadTempFileCase, } from '@/api/modules/api-test/management'; - import { getSocket } from '@/api/modules/project-management/commonScript'; import { useI18n } from '@/hooks/useI18n'; import useShortcutSave from '@/hooks/useShortcutSave'; + import useWebsocket from '@/hooks/useWebsocket'; import useAppStore from '@/store/modules/app'; import { getGenerateId } from '@/utils'; @@ -277,9 +277,9 @@ } drawerLoading.value = true; // 给后端传的参数 - if (!requestCompositionRef.value?.makeRequestParams()) return; - const { linkFileIds, uploadFileIds, request, unLinkFileIds, deleteFileIds } = - requestCompositionRef.value.makeRequestParams(); + const requestParams = await requestCompositionRef.value?.makeRequestParams(); + if (!requestParams) return; + const { linkFileIds, uploadFileIds, request, unLinkFileIds, deleteFileIds } = requestParams; const { name, priority, status, tags, id } = detailForm.value; const params: AddApiCaseParams = { projectId: appStore.currentProjectId, @@ -339,35 +339,37 @@ const websocket = ref(); const temporaryResponseMap: Record = {}; // 缓存websocket返回的报告内容,避免执行接口后切换tab导致报告丢失 // 开启websocket监听,接收执行结果 - function debugSocket(executeType?: 'localExec' | 'serverExec') { - websocket.value = getSocket( - reportId.value, - executeType === 'localExec' ? '/ws/debug' : '', - executeType === 'localExec' ? executeRef.value?.localExecuteUrl : '' - ); - websocket.value.addEventListener('message', (event) => { - const data = JSON.parse(event.data); - if (data.msgType === 'EXEC_RESULT') { - if (detailForm.value.reportId === data.reportId) { - // 判断当前查看的tab是否是当前返回的报告的tab,是的话直接赋值 - detailForm.value.response = data.taskResult; // 渲染出用例详情和创建用例抽屉的响应数据 + async function debugSocket(executeType?: 'localExec' | 'serverExec') { + const { createSocket, websocket: _websocket } = useWebsocket({ + reportId: reportId.value, + socketUrl: executeType === 'localExec' ? '/ws/debug' : '', + host: executeType === 'localExec' ? executeRef.value?.localExecuteUrl : '', + onMessage: (event) => { + const data = JSON.parse(event.data); + if (data.msgType === 'EXEC_RESULT') { + if (detailForm.value.reportId === data.reportId) { + // 判断当前查看的tab是否是当前返回的报告的tab,是的话直接赋值 + detailForm.value.response = data.taskResult; // 渲染出用例详情和创建用例抽屉的响应数据 + detailForm.value.executeLoading = false; + } else { + // 不是则需要把报告缓存起来,等切换到对应的tab再赋值 + temporaryResponseMap[data.reportId] = data.taskResult; + } + } else if (data.msgType === 'EXEC_END') { + // 执行结束,关闭websocket + websocket.value?.close(); detailForm.value.executeLoading = false; - } else { - // 不是则需要把报告缓存起来,等切换到对应的tab再赋值 - temporaryResponseMap[data.reportId] = data.taskResult; } - } else if (data.msgType === 'EXEC_END') { - // 执行结束,关闭websocket - websocket.value?.close(); - detailForm.value.executeLoading = false; - } + }, }); + await createSocket(); + websocket.value = _websocket.value; } async function handleExecute(executeType?: 'localExec' | 'serverExec') { try { detailForm.value.executeLoading = true; detailForm.value.response = cloneDeep(defaultResponse); - const makeRequestParams = requestCompositionRef.value?.makeRequestParams(executeType); // 写在reportId之前,防止覆盖reportId + const makeRequestParams = await requestCompositionRef.value?.makeRequestParams(executeType); // 写在reportId之前,防止覆盖reportId reportId.value = getGenerateId(); detailForm.value.reportId = reportId.value; // 存储报告ID let res; @@ -381,7 +383,7 @@ linkFileIds: makeRequestParams?.linkFileIds, uploadFileIds: makeRequestParams?.uploadFileIds, }; - debugSocket(executeType); // 开启websocket + await debugSocket(executeType); // 开启websocket if (!(detailForm.value.id as string).startsWith('c') && executeType === 'serverExec') { // 已创建的服务端 res = await runCase({ diff --git a/frontend/src/views/api-test/scenario/components/step/useStepExecute.ts b/frontend/src/views/api-test/scenario/components/step/useStepExecute.ts index b1a5419aa3..0a83e1f83f 100644 --- a/frontend/src/views/api-test/scenario/components/step/useStepExecute.ts +++ b/frontend/src/views/api-test/scenario/components/step/useStepExecute.ts @@ -44,34 +44,39 @@ export default function useStepExecute({ * 开启websocket监听,接收执行结果 */ function debugSocket(step: ScenarioStepItem, _scenario: Scenario, reportId: string | number) { - websocketMap[reportId] = getSocket( - reportId || '', - scenario.value.executeType === 'localExec' ? '/ws/debug' : '', - scenario.value.executeType === 'localExec' ? localExecuteUrl?.value : '' - ); - websocketMap[reportId].addEventListener('message', (event) => { - const data = JSON.parse(event.data); - if (data.msgType === 'EXEC_RESULT') { - if (step.reportId === data.reportId) { - // 判断当前查看的tab是否是当前返回的报告的tab,是的话直接赋值 - data.taskResult.requestResults.forEach((result: RequestResult) => { - if (_scenario.stepResponses[result.stepId] === undefined) { - _scenario.stepResponses[result.stepId] = []; - } - _scenario.stepResponses[result.stepId].push({ - ...result, - console: data.taskResult.console, + return new Promise((resolve) => { + websocketMap[reportId] = getSocket( + reportId || '', + scenario.value.executeType === 'localExec' ? '/ws/debug' : '', + scenario.value.executeType === 'localExec' ? localExecuteUrl?.value : '' + ); + websocketMap[reportId].addEventListener('message', (event) => { + const data = JSON.parse(event.data); + if (data.msgType === 'EXEC_RESULT') { + if (step.reportId === data.reportId) { + // 判断当前查看的tab是否是当前返回的报告的tab,是的话直接赋值 + data.taskResult.requestResults.forEach((result: RequestResult) => { + if (_scenario.stepResponses[result.stepId] === undefined) { + _scenario.stepResponses[result.stepId] = []; + } + _scenario.stepResponses[result.stepId].push({ + ...result, + console: data.taskResult.console, + }); }); - }); + } + } else if (data.msgType === 'EXEC_END') { + // 执行结束,关闭websocket + websocketMap[reportId]?.close(); + if (step.reportId === data.reportId) { + step.isExecuting = false; + updateStepStatus([step], _scenario.stepResponses, step.uniqueId); + } } - } else if (data.msgType === 'EXEC_END') { - // 执行结束,关闭websocket - websocketMap[reportId]?.close(); - if (step.reportId === data.reportId) { - step.isExecuting = false; - updateStepStatus([step], _scenario.stepResponses, step.uniqueId); - } - } + }); + websocketMap[reportId].addEventListener('open', () => { + resolve(true); + }); }); } @@ -82,7 +87,7 @@ export default function useStepExecute({ try { currentStep.isExecuting = true; currentStep.executeStatus = ScenarioExecuteStatus.EXECUTING; - debugSocket(currentStep, scenario.value, executeParams.reportId); // 开启websocket + await debugSocket(currentStep, scenario.value, executeParams.reportId); // 开启websocket const res = await debugScenario({ id: scenario.value.id || '', grouped: false, diff --git a/frontend/src/views/api-test/scenario/index.vue b/frontend/src/views/api-test/scenario/index.vue index f3e36a7ab4..8db1f300d7 100644 --- a/frontend/src/views/api-test/scenario/index.vue +++ b/frontend/src/views/api-test/scenario/index.vue @@ -211,45 +211,50 @@ * 开启websocket监听,接收执行结果 */ function debugSocket(scenario: Scenario, executeType?: 'localExec' | 'serverExec') { - websocketMap[scenario.reportId] = getSocket( - scenario.reportId || '', - executeType === 'localExec' ? '/ws/debug' : '', - executeType === 'localExec' ? localExecuteUrl.value : '' - ); - websocketMap[scenario.reportId].addEventListener('message', (event) => { - const data = JSON.parse(event.data); - if (data.msgType === 'EXEC_RESULT') { - if (scenario.reportId === data.reportId) { - // 判断当前查看的tab是否是当前返回的报告的tab,是的话直接赋值 - data.taskResult.requestResults.forEach((result: RequestResult) => { - if (result.stepId) { - // 过滤掉前后置配置的执行结果,没有步骤 id - if (scenario.stepResponses[result.stepId] === undefined) { - scenario.stepResponses[result.stepId] = []; + return new Promise((resolve) => { + websocketMap[scenario.reportId] = getSocket( + scenario.reportId || '', + executeType === 'localExec' ? '/ws/debug' : '', + executeType === 'localExec' ? localExecuteUrl.value : '' + ); + websocketMap[scenario.reportId].addEventListener('message', (event) => { + const data = JSON.parse(event.data); + if (data.msgType === 'EXEC_RESULT') { + if (scenario.reportId === data.reportId) { + // 判断当前查看的tab是否是当前返回的报告的tab,是的话直接赋值 + data.taskResult.requestResults.forEach((result: RequestResult) => { + if (result.stepId) { + // 过滤掉前后置配置的执行结果,没有步骤 id + if (scenario.stepResponses[result.stepId] === undefined) { + scenario.stepResponses[result.stepId] = []; + } + scenario.stepResponses[result.stepId].push({ + ...result, + console: data.taskResult.console, + }); + if (result.status === ScenarioExecuteStatus.FAKE_ERROR) { + scenario.executeFakeErrorCount += 1; + } else if (result.isSuccessful) { + scenario.executeSuccessCount += 1; + } else { + scenario.executeFailCount += 1; + } } - scenario.stepResponses[result.stepId].push({ - ...result, - console: data.taskResult.console, - }); - if (result.status === ScenarioExecuteStatus.FAKE_ERROR) { - scenario.executeFakeErrorCount += 1; - } else if (result.isSuccessful) { - scenario.executeSuccessCount += 1; - } else { - scenario.executeFailCount += 1; - } - } - }); + }); + } + } else if (data.msgType === 'EXEC_END') { + // 执行结束,关闭websocket + websocketMap[scenario.reportId]?.close(); + if (scenario.reportId === data.reportId) { + scenario.executeLoading = false; + scenario.isExecute = false; + setStepExecuteStatus(scenario); + } } - } else if (data.msgType === 'EXEC_END') { - // 执行结束,关闭websocket - websocketMap[scenario.reportId]?.close(); - if (scenario.reportId === data.reportId) { - scenario.executeLoading = false; - scenario.isExecute = false; - setStepExecuteStatus(scenario); - } - } + }); + websocketMap[scenario.reportId].addEventListener('open', () => { + resolve(true); + }); }); } @@ -275,8 +280,8 @@ activeScenarioTab.value.stepResponses = {}; activeScenarioTab.value.reportId = executeParams.reportId; // 存储报告ID activeScenarioTab.value.executeType = executeType; // 存储报告ID - debugSocket(activeScenarioTab.value, executeType); // 开启websocket activeScenarioTab.value.isDebug = !isExecute; + await debugSocket(activeScenarioTab.value, executeType); // 开启websocket let res; if (isExecute && executeType !== 'localExec' && !activeScenarioTab.value.isNew) { // 执行场景且非本地执行且非未保存场景 diff --git a/frontend/src/views/case-management/caseManagementFeature/components/caseTable.vue b/frontend/src/views/case-management/caseManagementFeature/components/caseTable.vue index 73fe050775..7ba18b9834 100644 --- a/frontend/src/views/case-management/caseManagementFeature/components/caseTable.vue +++ b/frontend/src/views/case-management/caseManagementFeature/components/caseTable.vue @@ -426,10 +426,10 @@ stopCaseExport, updateCaseRequest, } from '@/api/modules/case-management/featureCase'; - import { getSocket } from '@/api/modules/project-management/commonScript'; import { getCaseRelatedInfo } from '@/api/modules/project-management/menuManagement'; import { useI18n } from '@/hooks/useI18n'; import useModal from '@/hooks/useModal'; + import useWebsocket from '@/hooks/useWebsocket'; import { useAppStore, useTableStore } from '@/store'; import useCacheStore from '@/store/modules/cache/cache'; import useFeatureCaseStore from '@/store/modules/case/featureCase'; @@ -1252,26 +1252,31 @@ }); } // 开启websocket监听,接收结果 - function startWebsocketGetExportResult() { - websocket.value = getSocket(reportId.value, '/ws/export'); - websocket.value.addEventListener('message', (event) => { - const data = JSON.parse(event.data); - if (data.msgType === 'EXEC_RESULT') { - exportingMessage.value.close(); - reportId.value = data.fileId; - taskId.value = data.taskId; - if (data.isSuccessful) { - showExportSuccessfulMessage(reportId.value, data.count); - } else { - Message.error({ - content: t('common.exportFailed'), - duration: 999999999, // 一直展示,除非手动关闭 - closable: true, - }); + async function startWebsocketGetExportResult() { + const { createSocket, websocket: _websocket } = useWebsocket({ + reportId: reportId.value, + socketUrl: '/ws/export', + onMessage: (event) => { + const data = JSON.parse(event.data); + if (data.msgType === 'EXEC_RESULT') { + exportingMessage.value.close(); + reportId.value = data.fileId; + taskId.value = data.taskId; + if (data.isSuccessful) { + showExportSuccessfulMessage(reportId.value, data.count); + } else { + Message.error({ + content: t('common.exportFailed'), + duration: 999999999, // 一直展示,除非手动关闭 + closable: true, + }); + } + websocket.value?.close(); } - websocket.value?.close(); - } + }, }); + await createSocket(); + websocket.value = _websocket.value; } function getConfirmFields(option: MsExportDrawerOption[], columnType: string) { @@ -1284,7 +1289,7 @@ exportLoading.value = true; const { selectedIds, selectAll, excludeIds } = batchParams.value; reportId.value = getGenerateId(); - startWebsocketGetExportResult(); + await startWebsocketGetExportResult(); const params = { projectId: currentProjectId.value, selectIds: selectAll ? [] : selectedIds, @@ -1329,7 +1334,7 @@ taskId.value = res.taskId; Message.error(t('caseManagement.featureCase.alreadyExportTasks')); if (!websocket.value) { - startWebsocketGetExportResult(); + await startWebsocketGetExportResult(); } showExportingMessage(); }