Browse Source

feat: 前端兼容本地数据批量导出

main
betaqi 2 months ago
parent
commit
3e49830817
  1. 6
      src/utils/zmq.ts
  2. 41
      src/views/stationData/components/offTransferDlg.vue
  3. 3
      src/views/stationData/index.vue
  4. 188
      src/views/stationData/transferData.vue

6
src/utils/zmq.ts

@ -14,6 +14,12 @@ export enum WorkerCMD { @@ -14,6 +14,12 @@ export enum WorkerCMD {
SET_TIMEOUT
}
export enum ZmqMsgResultType {
SUCCESS = 200,
PROGRESS = 1002,
ERROR = 1003,
}
export enum ZmqCMD {
MSG,

41
src/views/stationData/components/offTransferDlg.vue

@ -23,7 +23,7 @@ const message = useMessage() @@ -23,7 +23,7 @@ const message = useMessage()
const emit = defineEmits<{
'on-save': [msg: PublishMsg<'import'>, site: IOfflineDevice]
'on-save': [msg: PublishMsg<'import'>[], site: IOfflineDevice[]]
}>()
const props = defineProps<{
@ -36,41 +36,48 @@ const fromData = { @@ -36,41 +36,48 @@ const fromData = {
clientIp: '',
}
const curOffDeive = ref<IOfflineDevice>()
const curOffDeive = ref<IOfflineDevice[]>([])
const form = ref(cloneDeep(fromData))
const isBatchTransfer = ref(false)
function open(item: IOfflineDevice) {
function open(item: IOfflineDevice[], isBatch: boolean = false) {
curOffDeive.value = item
visible.value = true
isBatchTransfer.value = isBatch
}
function onSave() {
if (verifyData()) return
if (!curOffDeive.value) {
if (!curOffDeive.value.length) {
message.error('请选择设备')
return
}
const params = [
`${form.value.clientIp}`,
'',
'',
'',
'',
'',
`${props.siteInfo!.name}/${curOffDeive.value.sn}`,
]
const msg = getPubInitData<'import'>('import', params)
emit('on-save', msg, curOffDeive.value)
const msgList: PublishMsg<"import">[] = []
for (const device of curOffDeive.value) {
const params = [
`${form.value.clientIp}`,
'',
'',
'',
'',
'',
`${props.siteInfo!.name}/${device.sn}`,
]
const msg = getPubInitData<'import'>('import', params)
msgList.push(msg)
}
emit('on-save', msgList, curOffDeive.value)
close()
}
function close() {
form.value = cloneDeep(fromData)
curOffDeive.value = undefined
curOffDeive.value = []
visible.value = false
isBatchTransfer.value = false
}
const ipPattern =
/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/

3
src/views/stationData/index.vue

@ -110,9 +110,6 @@ function onSiteDetails(site: ISite) { @@ -110,9 +110,6 @@ function onSiteDetails(site: ISite) {
})
}
const isSiteTransfer = ref(false)
const transferLoading = ref(false)
const siteList = ref<ISite[]>([])
async function loadSiteList() {
const res = await getSiteList()

188
src/views/stationData/transferData.vue

@ -12,12 +12,13 @@ @@ -12,12 +12,13 @@
<template v-else>
<el-button type="primary" @click="onBatchTransfer"> <i class="i-mdi:database-arrow-right-outline mr-1" />
批量迁移 </el-button>
<el-button v-if="isTransfer" type="primary" @click="onBatchUpgrade"> <i class="i-codicon:chip mr-1" />批量升级
<el-button v-if="isonLineTransfer" type="primary" @click="onBatchUpgrade"> <i
class="i-codicon:chip mr-1" />批量升级
</el-button>
</template>
</template>
<div class="device-list-wrap">
<el-checkbox-group v-model="onlineDeviceCheckList">
<el-checkbox-group v-model="checkDeviceList">
<div class="device-item" v-for="item in devices">
<div class="device-item-header">
<div class="flex items-center">
@ -29,11 +30,11 @@ @@ -29,11 +30,11 @@
</div>
</div>
<div class="flex items-center gap-col-2" v-if="!(isBatchTransfer || isBatchUpgrade)">
<el-tooltip content="数据迁移" v-if="isTransfer ? item.status === '在线' : true">
<el-tooltip content="数据迁移" v-if="isonLineTransfer ? item.status === '在线' : true">
<i class="i-mdi:database-arrow-right-outline :hover:color-[#8ACE6A] color-[#4B9E5F] cursor-pointer text-20px"
@click="onTransfer(item)"></i>
</el-tooltip>
<el-tooltip content="固件升级" v-if="isTransfer && item.status === '在线'">
<el-tooltip content="固件升级" v-if="isonLineTransfer && item.status === '在线'">
<i class="i-codicon:chip :hover:color-[#8ACE6A] color-[#4B9E5F] cursor-pointer text-20px"
@click="onFirmwareUpload([item])"></i>
</el-tooltip>
@ -46,9 +47,9 @@ @@ -46,9 +47,9 @@
</div>
<div class="device-item-body relative">
<template v-if="isTransfer">
<template v-if="isonLineTransfer">
<template v-for="key in Object.keys(onlineDeviceMap)">
<div class="info-item" v-if="isTransfer && key === 'status'">
<div class="info-item" v-if="isonLineTransfer && key === 'status'">
<div>{{ onlineDeviceMap.status }}:</div>
<el-tag :type="item.status === '在线' ? 'success' : 'danger'">
{{ item.status }}
@ -168,17 +169,21 @@ @@ -168,17 +169,21 @@
" class="flex-1" :stroke-width="18" :text-inside="true"
:striped="onOffDeviceTransferStatus === 'progress'"
:striped-flow="onOffDeviceTransferStatus === 'progress'" :duration="20">
<div class="text-16px font-500">{{ transferStatusMap[onOffDeviceTransferStatus as keyof typeof
transferStatusMap]
??
'' }}</div>
<div class="text-16px font-500"> {{ !!onOffDeviceTransferStatus ? onOffDeviceTransferStatus ===
'progress'
? '数据导入中' : '数据导入完成' : '数据导入中' }}</div>
</el-progress>
</div>
</div>
<div class="h-490 border-radius-8px bg-[#F9FAFB] p-10 flex-col">
<div class="text-16px font-500">迁移日志</div>
<el-scrollbar class="flex-1">
<div v-for="i in siteTransferLogList"> {{ i }} </div>
<div v-for="i in siteTransferLogList" :class="i.status === 'error' ? 'text-red-500' : ''"
class="text-gray-600">
{{ i.device.sn }}{{ i.msg }}
</div>
</el-scrollbar>
</div>
</div>
@ -190,7 +195,7 @@ @@ -190,7 +195,7 @@
<OnLineTransferDlg ref="onLineTransferDlgRef" @on-save="onLineDeviceTransfer" :is-batch-transfer="isBatchTransfer" />
<OffTransferDlg ref="offTransferDlg" :isBatchTransfer="false" :siteInfo="siteInfo" @on-save="onOffDeviceTransfer" />
<DeviceDrawer v-model="isShowDetails" ref="deviceDrawerRef" :siteInfo="siteInfo" :is-transfer="isTransfer" />
<DeviceDrawer v-model="isShowDetails" ref="deviceDrawerRef" :siteInfo="siteInfo" :is-transfer="isonLineTransfer" />
</template>
<script setup lang="ts">
@ -202,6 +207,7 @@ import OffTransferDlg from './components/offTransferDlg.vue' @@ -202,6 +207,7 @@ import OffTransferDlg from './components/offTransferDlg.vue'
import {
getPubInitData,
ZmqMsgResultType,
type PublishMsg,
type PubMsgData,
type TimeoutMsg,
@ -234,7 +240,7 @@ const siteInfo = ref<ISite>( @@ -234,7 +240,7 @@ const siteInfo = ref<ISite>(
)
const type = ref<'export' | 'details'>(route.query.type as 'export' | 'details')
const isTransfer = computed(() => type.value === 'export')
const isonLineTransfer = computed(() => type.value === 'export')
const isShowTransferMask = ref(false)
@ -263,7 +269,7 @@ const curTransferLog = ref< @@ -263,7 +269,7 @@ const curTransferLog = ref<
const transferStatus = ref<'progress' | 'success' | 'failed' | 'timeout' | undefined>()
const devices = computed(() => {
return isTransfer.value ? Array.from(devicesMap.value.values()) : deviceList.value
return isonLineTransfer.value ? Array.from(devicesMap.value.values()) : offLineDeviceList.value
}) as Ref<any[]>
const transferLoading = ref(false)
@ -306,7 +312,7 @@ const statusMap = { @@ -306,7 +312,7 @@ const statusMap = {
function zmqExportCb(msg: PubMsgData) {
if (!isTransfer.value) return
if (!isonLineTransfer.value) return
const { feedback, result, id } = msg
transferLoading.value = false
if (feedback && feedback[0]) {
@ -400,27 +406,32 @@ const offlineDeviceMap: Record< @@ -400,27 +406,32 @@ const offlineDeviceMap: Record<
create_time: '创建时间',
}
const onlineDeviceCheckList = ref<string[]>([])
const checkDeviceList = ref<string[]>([])
const isBatchTransfer = ref(false)
function onBatchTransfer() {
onlineDeviceCheckList.value = []
checkDeviceList.value = []
isBatchTransfer.value = true
}
function onBatchTransferSave(checkList: IOnlineDevice[]) {
const clientIpList = checkList.map(item => item?.clientIp).join(',')
const pathList = checkList
.map(item => `${item?.stationName}/${item?.sn}`)
.filter(Boolean)
.join(',')
function onBatchTransferSave(checkDeviceList: IOnlineDevice[] | IOfflineDevice[]) {
if (isonLineTransfer.value) {
const checkList = checkDeviceList as IOnlineDevice[]
const clientIpList = checkList.map(item => item?.clientIp).join(',')
const pathList = checkList
.map(item => `${item?.stationName}/${item?.sn}`)
.filter(Boolean)
.join(',')
onLineTransferDlgRef.value?.open(checkList[0], clientIpList, pathList)
onLineTransferDlgRef.value?.open(checkList[0], clientIpList, pathList)
} else {
offTransferDlg.value?.open(checkDeviceList, true)
}
}
const isBatchUpgrade = ref(false)
function onBatchUpgrade() {
onlineDeviceCheckList.value = []
checkDeviceList.value = []
isBatchUpgrade.value = true
}
@ -429,33 +440,48 @@ const batchText = computed(() => { @@ -429,33 +440,48 @@ const batchText = computed(() => {
})
function onBatchSave() {
if (!onlineDeviceCheckList.value.length) {
if (!checkDeviceList.value.length) {
message.error(`请选择要${batchText.value}的设备`)
return
}
const checkList = onlineDeviceCheckList.value
.map(sn => {
return devicesMap.value.get(sn) ?? undefined
})
.filter(Boolean) as IOnlineDevice[]
const checkList = isonLineTransfer.value
? getOnlineDeviceList()
: getOfflineDeviceList()
if (isBatchTransfer.value) {
onBatchTransferSave(checkList)
}
if (isBatchUpgrade.value) {
onFirmwareUpload(checkList)
if (isBatchUpgrade.value && isonLineTransfer.value) {
onFirmwareUpload(checkList as IOnlineDevice[])
}
}
function getOnlineDeviceList(): IOnlineDevice[] {
return checkDeviceList.value
.map(sn => {
return devicesMap.value.get(sn) ?? undefined
})
.filter(Boolean) as IOnlineDevice[]
}
function getOfflineDeviceList(): IOfflineDevice[] {
return offLineDeviceList.value.filter(item =>
checkDeviceList.value.includes(item.sn)
)
}
function onBatchCancel() {
isBatchTransfer.value = false
isBatchUpgrade.value = false
onlineDeviceCheckList.value = []
checkDeviceList.value = []
}
function onTransfer(item: IOnlineDevice) {
if (isTransfer.value) {
if (isonLineTransfer.value) {
onLineTransferDlgRef.value?.open(item)
} else {
offTransferDlg.value?.open(item)
offTransferDlg.value?.open([item])
}
}
@ -481,19 +507,19 @@ onBeforeRouteLeave(async (to, from, next) => { @@ -481,19 +507,19 @@ onBeforeRouteLeave(async (to, from, next) => {
}
})
const deviceList = ref<IOfflineDevice[]>([])
const offLineDeviceList = ref<IOfflineDevice[]>([])
async function loadDeviceList() {
const res = await getDeviceList(siteInfo.value.name)
if (res.code === 200 || res.code === 0) {
deviceList.value = res.data
offLineDeviceList.value = res.data
}
}
const firmwarePath = ref('')
onMounted(async () => {
if (!isTransfer.value) {
if (!isonLineTransfer.value) {
loadDeviceList()
} else {
const res = await getFirmwarePath()
@ -510,7 +536,7 @@ function onDeviceDetails(item: IOfflineDevice) { @@ -510,7 +536,7 @@ function onDeviceDetails(item: IOfflineDevice) {
deviceDrawerRef.value?.open(item)
}
const isCanFirmwareUpload = computed(() => !!firmwarePath.value && isTransfer.value)
const isCanFirmwareUpload = computed(() => !!firmwarePath.value && isonLineTransfer.value)
const upgradeSnList = ref<string[]>([])
const upgradePubDeviceMap = new Map<string, UpFirmwarsDevice>()
@ -559,7 +585,7 @@ function firmwareUpTimeoutCb(msg: TimeoutMsg) { @@ -559,7 +585,7 @@ function firmwareUpTimeoutCb(msg: TimeoutMsg) {
}
function zmqUpgradeCb(msg: PubMsgData) {
if (!isTransfer.value) return
if (!isonLineTransfer.value) return
const status = msg.result
const deviceSn = msg.feedback[0]
const progressStatus = msg.feedback[1] as number
@ -590,36 +616,71 @@ function zmqUpgradeCb(msg: PubMsgData) { @@ -590,36 +616,71 @@ function zmqUpgradeCb(msg: PubMsgData) {
const offTransferDlg = ref<typeof OffTransferDlg>()
const pubIdWithOffDevice = new Map<string, { offDevice: IOfflineDevice; action: 'import' }>()
const importQueue = ref<{ msg: PublishMsg<'import'>; offDevice: IOfflineDevice }[]>([]) //
const isImporting = ref(false)
async function processNextImport() {
if (importQueue.value.length === 0 || isImporting.value) {
onOffDeviceTransferStatus.value = 'success'
return
}
isImporting.value = true
const { msg, offDevice } = importQueue.value[0]
function onOffDeviceTransfer(msg: PublishMsg<'import'>, offDevice: IOfflineDevice) {
pubIdWithOffDevice.set(msg.id, { offDevice, action: 'import' })
worker.publish(postTransferTopic, msg, true, zmqImportTimeoutCb)
worker.subscribe(getTransferTopic, zmqImportCb, msg.id)
openTransferMask('import')
}
const siteTransferLogList = ref<string[]>([])
function onOffDeviceTransfer(msg: PublishMsg<'import'>[], offDevice: IOfflineDevice[]) {
//
msg.forEach((m, index) => {
importQueue.value.push({ msg: m, offDevice: offDevice[index] })
})
const onOffDeviceTransferStatus = ref<'progress' | 'success' | 'failed' | 'timeout' | undefined>()
//
processNextImport()
onBatchCancel()
openTransferMask('import')
}
const siteTransferLogList = ref<Array<{
msg: string
device: IOfflineDevice
status: 'success' | 'timeout' | 'error'
}>>([])
const onOffDeviceTransferStatus = ref<'progress' | 'success' | undefined>()
function zmqImportCb(msg: PubMsgData) {
const { id, result, feedback } = msg
const { id, feedback, result, code } = msg
transferLoading.value = false
const { offDevice, action } = pubIdWithOffDevice.get(id)!
if (action !== 'import' || !offDevice) return
transferLoading.value = false
if (result === 'progress') {
if (code === ZmqMsgResultType.PROGRESS) {
onOffDeviceTransferStatus.value = 'progress'
const log: string = Array.isArray(feedback) ? feedback[0] || '' : ''
siteTransferLogList.value.push(log)
siteTransferLogList.value.push({
msg: log,
device: offDevice,
status: 'success'
})
}
if (result !== 'progress') {
if (result === 'success') {
onOffDeviceTransferStatus.value = 'success'
message.success(`导出数据成功`)
} else {
onOffDeviceTransferStatus.value = 'failed'
message.error(`导出数据失败`)
if (code !== ZmqMsgResultType.PROGRESS) {
//
importQueue.value.shift()
isImporting.value = false
if (code === ZmqMsgResultType.ERROR) {
siteTransferLogList.value.push({
msg: `数据导入失败,请稍后重试消息结果:${result}`,
device: offDevice,
status: 'error'
})
}
//
processNextImport()
}
}
@ -627,9 +688,20 @@ function zmqImportTimeoutCb(msg: TimeoutMsg) { @@ -627,9 +688,20 @@ function zmqImportTimeoutCb(msg: TimeoutMsg) {
const { offDevice, action } = pubIdWithOffDevice.get(msg.timeoutId)!
if (offDevice && action === 'import') {
message.error(`站点:${offDevice.sn}数据导出超时,请稍后重试`)
transferLoading.value = false
pubIdWithOffDevice.delete(msg.timeoutId)
onOffDeviceTransferStatus.value = 'timeout'
closeTransferMask()
siteTransferLogList.value.push({
msg: `数据导入超时,请稍后重试`,
device: offDevice,
status: 'error'
})
//
importQueue.value.shift()
isImporting.value = false
//
processNextImport()
}
}

Loading…
Cancel
Save