ADD: 修改数据合并逻辑,新增 event-source-polyfill包,实现长连接通信,展示合并进度

This commit is contained in:
贾同学
2025-09-11 11:03:14 +08:00
parent d18e34d2c9
commit cfd8b072dd
6 changed files with 459 additions and 345 deletions

View File

@@ -14,6 +14,7 @@
}, },
"dependencies": { "dependencies": {
"@element-plus/icons-vue": "^2.3.1", "@element-plus/icons-vue": "^2.3.1",
"@types/event-source-polyfill": "^1.0.5",
"@vue-flow/core": "^1.45.0", "@vue-flow/core": "^1.45.0",
"@vueuse/core": "^10.4.1", "@vueuse/core": "^10.4.1",
"axios": "^1.7.3", "axios": "^1.7.3",
@@ -23,6 +24,7 @@
"echarts": "^5.4.3", "echarts": "^5.4.3",
"echarts-liquidfill": "^3.1.0", "echarts-liquidfill": "^3.1.0",
"element-plus": "^2.7.8", "element-plus": "^2.7.8",
"event-source-polyfill": "^1.0.31",
"html2canvas": "^1.4.1", "html2canvas": "^1.4.1",
"md5": "^2.3.0", "md5": "^2.3.0",
"mitt": "^3.0.1", "mitt": "^3.0.1",

View File

@@ -1,17 +1,23 @@
import { ElMessage, ElTreeSelect } from 'element-plus'; import { ElMessage } from 'element-plus'
import axios, { AxiosInstance, AxiosError, AxiosRequestConfig, InternalAxiosRequestConfig, AxiosResponse } from 'axios' import axios, {
AxiosError,
type AxiosInstance,
type AxiosRequestConfig,
type AxiosResponse,
type InternalAxiosRequestConfig
} from 'axios'
import { showFullScreenLoading, tryHideFullScreenLoading } from '@/components/Loading/fullScreen' import { showFullScreenLoading, tryHideFullScreenLoading } from '@/components/Loading/fullScreen'
import { LOGIN_URL } from '@/config' import { LOGIN_URL } from '@/config'
import { ElMessage } from 'element-plus' import { type ResultData } from '@/api/interface'
import { ResultData } from '@/api/interface'
import { ResultEnum } from '@/enums/httpEnum' import { ResultEnum } from '@/enums/httpEnum'
import { checkStatus } from './helper/checkStatus' import { checkStatus } from './helper/checkStatus'
import { useUserStore } from '@/stores/modules/user' import { useUserStore } from '@/stores/modules/user'
import router from '@/routers' import router from '@/routers'
import {refreshToken} from '@/api/user/login' import { refreshToken } from '@/api/user/login'
import { EventSourcePolyfill } from 'event-source-polyfill'
export interface CustomAxiosRequestConfig extends InternalAxiosRequestConfig { export interface CustomAxiosRequestConfig extends InternalAxiosRequestConfig {
loading?: boolean; loading?: boolean
} }
const config = { const config = {
@@ -22,7 +28,7 @@ const config = {
// 跨域时候允许携带凭证 // 跨域时候允许携带凭证
withCredentials: true, withCredentials: true,
// post请求指定数据类型以及编码 // post请求指定数据类型以及编码
headers: { 'Content-Type': 'application/json;charset=utf-8' }, headers: { 'Content-Type': 'application/json;charset=utf-8' }
} }
class RequestHttp { class RequestHttp {
@@ -46,13 +52,13 @@ class RequestHttp {
config.loading && showFullScreenLoading() config.loading && showFullScreenLoading()
if (config.headers && typeof config.headers.set === 'function') { if (config.headers && typeof config.headers.set === 'function') {
config.headers.set('Authorization', 'Bearer ' + userStore.accessToken) config.headers.set('Authorization', 'Bearer ' + userStore.accessToken)
config.headers.set('Is-Refresh-Token', userStore.isRefreshToken+"") config.headers.set('Is-Refresh-Token', userStore.isRefreshToken + '')
} }
return config return config
}, },
(error: AxiosError) => { (error: AxiosError) => {
return Promise.reject(error) return Promise.reject(error)
}, }
) )
let isFirst = true let isFirst = true
@@ -66,18 +72,19 @@ class RequestHttp {
const userStore = useUserStore() const userStore = useUserStore()
tryHideFullScreenLoading() tryHideFullScreenLoading()
if(data.code === ResultEnum.ACCESSTOKEN_EXPIRED){ if (data.code === ResultEnum.ACCESSTOKEN_EXPIRED) {
// 用长token去换短token // 用长token去换短token
userStore.setAccessToken(userStore.refreshToken) userStore.setAccessToken(userStore.refreshToken)
userStore.setIsRefreshToken(true) userStore.setIsRefreshToken(true)
const result = await refreshToken() const result = await refreshToken()
if (result) { //获取新token成功的话 if (result) {
//获取新token成功的话
// 有新的token后重新请求 // 有新的token后重新请求
userStore.setAccessToken(result.data.accessToken) userStore.setAccessToken(result.data.accessToken)
userStore.setRefreshToken(result.data.refreshToken) userStore.setRefreshToken(result.data.refreshToken)
userStore.setIsRefreshToken(false) userStore.setIsRefreshToken(false)
userStore.setExp(1000 * 60 * 60 * 24 * 30) userStore.setExp(1000 * 60 * 60 * 24 * 30)
response.config.headers.Authorization = `Bearer ${result.data.accessToken}`//重新请求前需要将更新后的新token更换掉之前无效的token,不然会死循环 response.config.headers.Authorization = `Bearer ${result.data.accessToken}` //重新请求前需要将更新后的新token更换掉之前无效的token,不然会死循环
const resp = await this.service.request(response.config) const resp = await this.service.request(response.config)
return resp return resp
} else { } else {
@@ -86,14 +93,15 @@ class RequestHttp {
} }
// 登陆失效 // 登陆失效
if (data.code === ResultEnum.OVERDUE) { if (data.code === ResultEnum.OVERDUE) {
console.log("登陆失效") console.log('登陆失效')
userStore.setAccessToken('') userStore.setAccessToken('')
userStore.setRefreshToken('') userStore.setRefreshToken('')
userStore.setIsRefreshToken(false) userStore.setIsRefreshToken(false)
userStore.setUserInfo({ id:'',name: '' }) userStore.setUserInfo({ id: '', name: '' })
userStore.setExp(0) userStore.setExp(0)
await router.replace(LOGIN_URL) await router.replace(LOGIN_URL)
if(isFirst){//临时处理token失效弹窗多次 if (isFirst) {
//临时处理token失效弹窗多次
ElMessage.error(data.message) ElMessage.error(data.message)
isFirst = false isFirst = false
} }
@@ -101,12 +109,12 @@ class RequestHttp {
} }
// 全局错误信息拦截(防止下载文件的时候返回数据流,没有 code 直接报错) // 全局错误信息拦截(防止下载文件的时候返回数据流,没有 code 直接报错)
if (data.code && data.code !== ResultEnum.SUCCESS) { if (data.code && data.code !== ResultEnum.SUCCESS) {
if(data.message.includes('&')){ if (data.message.includes('&')) {
let formattedMessage = data.message.split('&').join('<br>'); let formattedMessage = data.message.split('&').join('<br>')
if (data.message.includes(':')) { if (data.message.includes(':')) {
formattedMessage = formattedMessage.replace(':', '') formattedMessage = formattedMessage.replace(':', '')
} }
ElMessage.error({ message: formattedMessage, dangerouslyUseHTMLString: true }); ElMessage.error({ message: formattedMessage, dangerouslyUseHTMLString: true })
return Promise.reject(data) return Promise.reject(data)
} }
@@ -119,7 +127,7 @@ class RequestHttp {
userStore.setAccessToken('') userStore.setAccessToken('')
userStore.setRefreshToken('') userStore.setRefreshToken('')
userStore.setIsRefreshToken(false) userStore.setIsRefreshToken(false)
userStore.setUserInfo({ id:'',name: '' }) userStore.setUserInfo({ id: '', name: '' })
userStore.setExp(0) userStore.setExp(0)
ElMessage.error('登录已过期,请重新登录!') ElMessage.error('登录已过期,请重新登录!')
await router.replace(LOGIN_URL) await router.replace(LOGIN_URL)
@@ -139,7 +147,7 @@ class RequestHttp {
// 服务器结果都没有返回(可能服务器错误可能客户端断网),断网处理:可以跳转到断网页面 // 服务器结果都没有返回(可能服务器错误可能客户端断网),断网处理:可以跳转到断网页面
if (!window.navigator.onLine) router.replace('/500') if (!window.navigator.onLine) router.replace('/500')
return Promise.reject(error) return Promise.reject(error)
}, }
) )
} }
@@ -180,11 +188,39 @@ class RequestHttp {
return this.service.post(url, params, { return this.service.post(url, params, {
..._object, ..._object,
headers: { 'Content-Type': 'multipart/form-data' }, headers: { 'Content-Type': 'multipart/form-data' },
responseType: 'blob', responseType: 'blob'
}) })
} }
// 添加SSE连接方法
sse(url: string, params?: any): EventSource {
const userStore = useUserStore()
// 构造带参数的URL
let requestUrl = config.baseURL + url
if (params) {
const searchParams = new URLSearchParams()
for (const key in params) {
if (Object.prototype.hasOwnProperty.call(params, key)) {
searchParams.append(key, String(params[key]))
}
}
requestUrl += '?' + searchParams.toString()
}
// 创建EventSource连接
const eventSource = new EventSourcePolyfill(requestUrl, {
headers: {
Authorization: 'Bearer ' + userStore.accessToken
}
})
// 设置默认的Authorization头部
eventSource.addEventListener('open', function () {
console.log('SSE连接已建立')
})
return eventSource
}
} }
export default new RequestHttp(config) export default new RequestHttp(config)

View File

@@ -141,16 +141,6 @@ export const exportPlanCheckData = (params: any) => {
) )
} }
// 导入子检测计划检测结果数据
export const importSubPlanCheckData = (params: Plan.ResPlan) => {
return http.upload(`/adPlan/importSubPlanCheckData`, params)
}
// 合并子检测计划检测结果数据
export const mergeSubPlanCheckData = (params: Plan.ResPlan) => {
return http.upload(`/adPlan/mergePlanCheckData?planId=${params.id}`)
}
//根据误差体系id获取测试项 //根据误差体系id获取测试项
export const getPqErrSysTestItemList = (params: {errorSysId : string}) => { export const getPqErrSysTestItemList = (params: {errorSysId : string}) => {
return http.get(`/pqErrSys/getTestItems?id=${params.errorSysId}`) return http.get(`/pqErrSys/getTestItems?id=${params.errorSysId}`)
@@ -160,3 +150,8 @@ export const getPqErrSysTestItemList = (params: {errorSysId : string}) => {
export const getMemberList = (params: {id : string}) => { export const getMemberList = (params: {id : string}) => {
return http.get(`/adPlan/getMemberList?planId=${params.id}`) return http.get(`/adPlan/getMemberList?planId=${params.id}`)
} }
// 导入并合并子检测计划检测结果数据
export const importAndMergePlanCheckData = (params: Plan.ResPlan) => {
return http.upload(`/adPlan/importAndMergePlanCheckData`, params)
}

View File

@@ -1,24 +1,26 @@
<template> <template>
<el-dialog v-model="dialogVisible" :title="parameter.title" :destroy-on-close="true" width="450px" draggable> <el-dialog
<el-form class="drawer-multiColumn-form" label-width="100px"> v-model="dialogVisible"
<el-form-item label=""> :title="parameter.title"
:destroy-on-close="true"
width="450px"
:close-on-click-modal="!parameter.progressBar"
draggable
>
<el-upload <el-upload
ref="uploadRef" ref="uploadRef"
action="#" action="#"
class="upload" class="upload"
:limit="1"
:http-request="uploadZip" :http-request="uploadZip"
accept=".zip" accept=".zip"
:auto-upload="!parameter.confirmMessage" :auto-upload="!parameter.confirmMessage"
:on-change="handleChange" :on-change="handleChange"
:on-remove="handleRemove" :on-remove="handleRemove"
:disabled="fileDisabled"
> >
<slot name="empty"> <slot name="empty">
<el-icon class="el-icon--upload"> <el-button type="primary" icon="Upload">点击上传</el-button>
<upload-filled />
</el-icon>
<div class="el-upload__text">
<spam>点击上传</spam>
</div>
</slot> </slot>
<template #tip> <template #tip>
<slot name="tip"> <slot name="tip">
@@ -26,8 +28,21 @@
</slot> </slot>
</template> </template>
</el-upload> </el-upload>
</el-form-item> <el-progress
</el-form> 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>
<el-text v-if="parameter.progressBar && progressData.status === 'success'" size="small" type="success">
{{ progressData.message }}
</el-text>
<el-text v-if="parameter.progressBar && progressData.status === ''" size="small" type="info">
{{ progressData.message }}
</el-text>
<template #footer v-if="parameter.confirmMessage"> <template #footer v-if="parameter.confirmMessage">
<el-button :disabled="disable" type="primary" @click="uploadSubmit">开始导入</el-button> <el-button :disabled="disable" type="primary" @click="uploadSubmit">开始导入</el-button>
</template> </template>
@@ -37,16 +52,20 @@
<script setup lang="ts" name="ImportZip"> <script setup lang="ts" name="ImportZip">
import { ref } from 'vue' import { ref } from 'vue'
import type { UploadInstance, UploadProps, UploadRequestOptions } from 'element-plus' import type { UploadInstance, UploadProps, UploadRequestOptions } from 'element-plus'
import http from '@/api'
export interface ZipParameterProps { export interface ZipParameterProps {
title: string // 标题 title: string // 标题
patternId?: string // 模式ID patternId?: string // 模式ID
planId?: string // 计划ID
importApi?: (params: any) => Promise<any> // 批量导入的Api importApi?: (params: any) => Promise<any> // 批量导入的Api
confirmMessage?: string // 提示信息 confirmMessage?: string // 提示信息
progressBar?: boolean // 进度条
} }
// dialog状态 // dialog状态
const dialogVisible = ref(false) const dialogVisible = ref(false)
const disable = ref(true) const disable = ref(true)
const fileDisabled = ref(false)
const uploadRef = ref<UploadInstance>() const uploadRef = ref<UploadInstance>()
// 父组件传过来的参数 // 父组件传过来的参数
@@ -63,16 +82,26 @@ const acceptParams = (params: ZipParameterProps) => {
} }
// 文件上传 // 文件上传
const uploadZip = async (param: UploadRequestOptions) => { const uploadZip = (param: UploadRequestOptions) => {
let zipFormData = new FormData() let zipFormData = new FormData()
zipFormData.append('file', param.file) zipFormData.append('file', param.file)
if (parameter.value.patternId) { if (parameter.value.patternId) {
zipFormData.append('patternId', parameter.value.patternId) zipFormData.append('patternId', parameter.value.patternId)
} }
await parameter.value.importApi!(zipFormData).then(res => handleImportResponse(res)) if (parameter.value.planId) {
zipFormData.append('planId', parameter.value.planId)
}
if (parameter.value.progressBar) {
initSSE()
}
setTimeout(() => {
parameter.value.importApi!(zipFormData).then(res => handleImportResponse(res))
}, 1000)
} }
const handleImportResponse = (res: any) => { const handleImportResponse = (res: any) => {
if (!parameter.value.progressBar) {
if (res.code === 'A0000') { if (res.code === 'A0000') {
ElMessage.success('导入成功') ElMessage.success('导入成功')
} else { } else {
@@ -80,27 +109,114 @@ const handleImportResponse = (res: any) => {
} }
dialogVisible.value = false dialogVisible.value = false
emit('result', res.data) emit('result', res.data)
} else {
//
}
} }
const uploadSubmit = () => { const uploadSubmit = () => {
if (!uploadRef.value) { if (!uploadRef.value) {
return ElMessage.warning('请选择文件!') return ElMessage.warning('请选择文件!')
} }
progressData.value = {
percentage: 0,
status: '',
message: ''
}
ElMessageBox.confirm(parameter.value.confirmMessage, '温馨提示', { ElMessageBox.confirm(parameter.value.confirmMessage, '温馨提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning' type: 'warning'
}) })
.then(() => { .then(() => {
disable.value = true
fileDisabled.value = true
uploadRef.value?.submit() uploadRef.value?.submit()
}) })
.catch(() => {}) .catch(() => {
disable.value = false
fileDisabled.value = false
})
} }
const handleChange: UploadProps['onChange'] = (uploadFile, uploadFiles) => { const handleChange: UploadProps['onChange'] = (uploadFile, uploadFiles) => {
disable.value = uploadFiles.length === 0 disable.value = uploadFiles.length === 0
progressData.value = {
percentage: 0,
status: '',
message: ''
}
} }
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => { const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
disable.value = uploadFiles.length === 0 disable.value = uploadFiles.length === 0
progressData.value = {
percentage: 0,
status: '',
message: ''
}
} }
const progressData = ref({
percentage: 0,
status: '',
message: ''
})
const eventSource = ref<EventSource | null>(null)
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') {
fileDisabled.value = false
disable.value = false
progressData.value.status = 'exception'
ElMessage.error(res.message)
}
if (progressData.value.percentage === 100) {
progressData.value.status = 'success'
eventSource.value!.close()
ElMessage.success('导入成功')
dialogVisible.value = false
emit('result', true)
}
}
eventSource.value.onerror = error => {
console.warn('SSE 连接出错:', error)
eventSource.value!.close()
}
}
// 添加一个手动关闭EventSource的函数
const closeEventSource = () => {
if (eventSource.value) {
eventSource.value.close()
eventSource.value = null
console.log('SSE连接已关闭')
}
}
// 监听 dialogVisible 的变化,确保在对话框关闭时清理资源
watch(dialogVisible, newVal => {
if (!newVal) {
// 延迟执行,确保在组件完全关闭后清理
setTimeout(() => {
closeEventSource()
fileDisabled.value = false
disable.value = false
progressData.value = {
percentage: 0,
status: '',
message: ''
}
}, 100)
}
})
onUnmounted(() => {
closeEventSource()
})
defineExpose({ defineExpose({
acceptParams acceptParams
}) })

View File

@@ -1,33 +1,23 @@
<template> <template>
<div class='table-box'> <div class="table-box">
<ProTable <ProTable ref="proTable" :columns="columns" :request-api="getTableList">
ref='proTable'
:columns='columns'
:request-api='getTableList'
>
<!-- 表格 header 按钮 --> <!-- 表格 header 按钮 -->
<template #tableHeader> <template #tableHeader>
<el-button type='primary' :icon='DataAnalysis'>分析</el-button> <el-button type="primary" :icon="DataAnalysis">分析</el-button>
<el-button type='primary' :icon='Upload' @click='handleExport'>导出csv</el-button> <el-button type="primary" :icon="Upload" @click="handleExport">导出csv</el-button>
</template> </template>
</ProTable> </ProTable>
</div> </div>
</template> </template>
<script setup lang='tsx' name='useProTable'> <script setup lang="tsx" name="useProTable">
// 根据实际路径调整 // 根据实际路径调整
import TimeControl from '@/components/TimeControl/index.vue' import TimeControl from '@/components/TimeControl/index.vue'
import {type AuditLog} from '@/api/system/log/interface/log.ts'
import ProTable from '@/components/ProTable/index.vue' import ProTable from '@/components/ProTable/index.vue'
import {DataAnalysis, Upload} from '@element-plus/icons-vue' import { DataAnalysis, Upload } from '@element-plus/icons-vue'
import type {ColumnProps, ProTableInstance} from '@/components/ProTable/interface' import type { ColumnProps, ProTableInstance } from '@/components/ProTable/interface'
import {reactive, ref} from 'vue' import { reactive, ref } from 'vue'
import {getAuditLog, exportCsv} from '@/api/system/log/index.ts' import { exportCsv, getAuditLog } from '@/api/system/log'
import {useDownload} from "@/hooks/useDownload"; import { useDownload } from '@/hooks/useDownload'
import {exportPqDev} from "@/api/device/device";
// defineOptions({ // defineOptions({
// name: 'log' // name: 'log'
@@ -45,21 +35,20 @@ const getTableList = async (params: any) => {
return getAuditLog(newParams) return getAuditLog(newParams)
} }
// 表格配置项 // 表格配置项
const columns = reactive<ColumnProps<AuditLog.ReqAuditLogParams>[]>([ const columns = reactive<ColumnProps[]>([
{type: 'selection', fixed: 'left', width: 70}, { type: 'selection', fixed: 'left', width: 70 },
{type: 'index', fixed: 'left', width: 70, label: '序号'}, { type: 'index', fixed: 'left', width: 70, label: '序号' },
{ {
prop: 'userName', prop: 'userName',
label: '操作用户', label: '操作用户',
search: {el: 'input'}, search: { el: 'input' },
minWidth: 100, minWidth: 100
}, },
{ {
prop: 'ip', prop: 'ip',
label: 'IP', label: 'IP',
minWidth: 120, minWidth: 120
}, },
{ {
prop: 'logTime', prop: 'logTime',
@@ -68,7 +57,7 @@ const columns = reactive<ColumnProps<AuditLog.ReqAuditLogParams>[]>([
search: { search: {
render: () => { render: () => {
return ( return (
<div class='flx-flex-start'> <div class="flx-flex-start">
<TimeControl <TimeControl
include={['日', '周', '月', '自定义']} include={['日', '周', '月', '自定义']}
default={'月'} default={'月'}
@@ -76,20 +65,20 @@ const columns = reactive<ColumnProps<AuditLog.ReqAuditLogParams>[]>([
/> />
</div> </div>
) )
}, }
}, }
}, },
{ {
label: '事件描述', label: '事件描述',
minWidth: 450, minWidth: 450,
render: (scope) => { render(scope) {
return (scope.row.userName + '在' + scope.row.logTime + '执行了' + scope.row.reCheckType + scope.row.operate + '操作,结果为' + scope.row.result + '。') return `${scope.row.userName}${scope.row.logTime}执行了【${scope.row.operateType}${scope.row.operate}操作,结果为${scope.row.result}`
} }
}, },
{ {
prop: 'result', prop: 'result',
label: '事件结果', label: '事件结果',
minWidth: 120, minWidth: 120
}, },
{ {
prop: 'warn', prop: 'warn',
@@ -97,15 +86,17 @@ const columns = reactive<ColumnProps<AuditLog.ReqAuditLogParams>[]>([
minWidth: 100, minWidth: 100,
render: scope => { render: scope => {
return ( return (
<el-tag type={scope.row.warn == 1 ? 'danger' : 'success'}>{scope.row.warn == 1 ? '已告警' : '未告警'}</el-tag> <el-tag type={scope.row.warn == 1 ? 'danger' : 'success'}>
{scope.row.warn == 1 ? '已告警' : '未告警'}
</el-tag>
) )
}, }
}, },
{ {
prop: 'operateType', prop: 'operateType',
label: '日志类型', label: '日志类型',
width: 100, width: 100
}, }
]) ])
// 处理日期变化的回调函数 // 处理日期变化的回调函数
@@ -124,9 +115,6 @@ const handleExport = () => {
useDownload(exportCsv, '日志列表', searchParam, false, '.csv') useDownload(exportCsv, '日志列表', searchParam, false, '.csv')
} }
</script> </script>
<style scoped> <style scoped></style>
</style>

View File

@@ -62,21 +62,12 @@
> >
数据下载 数据下载
</el-button> </el-button>
<el-button
v-if="planFormContent && planFormContent?.children.length > 0"
v-auth.plan="'add_subplan'"
icon="Upload"
type="primary"
@click="importSubCheckDataClick"
>
导入检测结果
</el-button>
<el-button <el-button
v-if="!isTabPlanFather && planFormContent && planFormContent?.children.length > 0" v-if="!isTabPlanFather && planFormContent && planFormContent?.children.length > 0"
v-auth.plan="'add_subplan'" v-auth.plan="'add_subplan'"
icon="Box" icon="Box"
type="primary" type="primary"
@click="mergeSubCheckDataClick" @click="importAndMergePlanCheckDataClick"
> >
数据合并 数据合并
</el-button> </el-button>
@@ -181,17 +172,16 @@ import { reactive, ref } from 'vue'
import PlanPopup from '@/views/plan/planList/components/planPopup.vue' // 导入子组件 import PlanPopup from '@/views/plan/planList/components/planPopup.vue' // 导入子组件
import { Plan } from '@/api/plan/interface' import { Plan } from '@/api/plan/interface'
import { useModeStore } from '@/stores/modules/mode' // 引入模式 store import { useModeStore } from '@/stores/modules/mode' // 引入模式 store
import { ColumnProps, ProTableInstance, SearchRenderScope } from '@/components/ProTable/interface' import type { ColumnProps, ProTableInstance, SearchRenderScope } from '@/components/ProTable/interface'
import { import {
deletePlan, deletePlan,
exportPlanCheckData, exportPlanCheckData,
exportSubPlan, exportSubPlan,
getDevListByPlanId, getDevListByPlanId,
importSubPlanCheckData, importAndMergePlanCheckData,
mergeSubPlanCheckData,
subPlanBindDev subPlanBindDev
} from '@/api/plan/plan' } from '@/api/plan/plan'
import { Device } from '@/api/device/interface/device' import { type Device } from '@/api/device/interface/device'
import { useDictStore } from '@/stores/modules/dict' import { useDictStore } from '@/stores/modules/dict'
import DevTransfer from '@/views/plan/planList/components/devTransfer.vue' import DevTransfer from '@/views/plan/planList/components/devTransfer.vue'
import { useHandleData } from '@/hooks/useHandleData' import { useHandleData } from '@/hooks/useHandleData'
@@ -667,11 +657,14 @@ const exportPlanCheckResultData = async (selectedListIds: string[]) => {
}) })
} }
const importSubCheckDataClick = () => { const importAndMergePlanCheckDataClick = () => {
const params = { const params = {
title: '导入计划检测结果', title: '合并检测计划检测结果',
confirmMessage: `确定合并【${planFormContent.value?.name}】的检测数据吗`,
patternId: dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? '', patternId: dictStore.getDictData('Pattern').find(item => item.name === modeStore.currentMode)?.id ?? '',
importApi: importSubPlanCheckData importApi: importAndMergePlanCheckData,
progressBar: true,
planId: planId.value
} }
planCheckDataImportZip.value?.acceptParams(params) planCheckDataImportZip.value?.acceptParams(params)
} }
@@ -682,22 +675,6 @@ const importResult = async (success: boolean | undefined) => {
} }
} }
const mergeSubCheckDataClick = () => {
ElMessageBox.confirm(`确定合并【${planFormContent.value?.name}】的检测数据吗`, '温馨提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
const params = {
id: planFormContent.value?.id
}
mergeSubPlanCheckData(params).then(res => {
ElMessage.success('合并成功')
})
})
.catch(() => {})
}
defineExpose({ open, handleTableDataUpdate }) defineExpose({ open, handleTableDataUpdate })
interface ChildrenPlanProps { interface ChildrenPlanProps {