@ -19,36 +19,26 @@
@@ -19,36 +19,26 @@
< div class = "device-item" v-for ="item in devices" >
< div class = "device-item-header" >
< div class = "flex items-center" >
< el -checkbox :value ="item.sn" v-if ="isBatchTransfer || isBatchUpgrade" >
< el -checkbox :value ="item.sn" v-if ="( isBatchTransfer || isBatchUpgrade) && item.status !== '离线' " >
< div > 设备ID : { { item . sn } } < / div >
< / e l - c h e c k b o x >
< div v -else>
< div v -else class = "h-32 leading-32px" >
< div > 设备ID : { { item . sn } } < / div >
< / div >
< / div >
< div class = "flex items-center gap-col-2" >
< el -tooltip
content = "数据迁移"
v - if = "isTransfer && item.status === '在线'"
>
< i
class = "i-mdi:database-arrow-right-outline :hover:color-[#8ACE6A] color-[#4B9E5F] cursor-pointer text-20px"
@ click = "onTransfer(item)"
> < / i >
< div class = "flex items-center gap-col-2" v-if ="!(isBatchTransfer || isBatchUpgrade)" >
< el -tooltip content = "数据迁移" v-if ="isTransfer ? item.status === '在线' : true" >
< i class = "i-mdi:database-arrow-right-outline :hover:color-[#8ACE6A] color-[#4B9E5F] cursor-pointer text-20px"
@ click = "onTransfer(item)" > < / i >
< / e l - t o o l t i p >
<!-- v - if = "isTransfer && item.status === '在线'" -- >
< el -tooltip content = "固件升级" >
< i
class = "i-codicon:chip :hover:color-[#8ACE6A] color-[#4B9E5F] cursor-pointer text-20px"
@ click = "onFirmwareUpload([item])"
> < / i >
< el -tooltip content = "固件升级" v-if ="isTransfer && item.status === '在线'" >
< i class = "i-codicon:chip :hover:color-[#8ACE6A] color-[#4B9E5F] cursor-pointer text-20px"
@ click = "onFirmwareUpload([item])" > < / i >
< / e l - t o o l t i p >
< el -tooltip content = "详情" >
< div
class = "i-material-symbols:info-outline :hover:color-[#8ACE6A] color-[#4B9E5F] cursor-pointer text-20px"
@ click = "onDeviceDetails(item)"
> < / div >
@ click = "onDeviceDetails(item)" > < / div >
< / e l - t o o l t i p >
< / div >
< / div >
@ -84,15 +74,10 @@
@@ -84,15 +74,10 @@
< / div >
< / template >
< / template >
< div
class = "absolute l-0 t-0 w-full h-full z-10 bg-#FFF-90"
v - if = "['updating', 'pending', 'rejected'].includes(item.upFirmware)"
>
< div
class = "i-material-symbols-light:close absolute-rt text-base text-gray-950 cursor-pointer"
v - if = "item.upFirmware === 'rejected'"
@ click = "upFirmwareSucceed(item.sn)"
> < / div >
< div class = "absolute l-0 t-0 w-full h-full z-10 bg-#FFF-90"
v - if = "['updating', 'pending', 'rejected', 'timeout'].includes(item.upFirmware)" >
< div class = "i-material-symbols-light:close absolute-rt text-base text-gray-950 cursor-pointer"
v - if = "['timeout', 'rejected'].includes(item.upFirmware)" @ click = "upFirmwareSucceed(item.sn)" > < / div >
< template v-if ="item.upFirmware === 'updating'" >
< div class = "device-item-body" >
< div class = "info-item" >
@ -101,105 +86,118 @@
@@ -101,105 +86,118 @@
< / div >
< div class = "info-item" >
< div > 当前进度 : < / div >
< el -progress
class = "flex-1"
: stroke - width = "12"
: show - text = "true"
: percentage = "item.upFirmwareStatus?.progress || 0"
/ >
< el -progress class = "flex-1" :stroke-width ="12" :show-text ="true"
: percentage = "item.upFirmwareStatus?.progress || 0" / >
< / div >
< / div >
< / template >
< template v -else -if = " item.upFirmware = = = ' pending ' " >
< div class = "w-full h-full flex items-center justify-center" >
< div class = "font-400 text-base" > 等待升级中 ... < / div >
< div class = "font-400 text-base text-[#4B9E5F] " > 等待升级中 ... < / div >
< / div >
< / template >
< template v-if ="item.upFirmware === 'rejected'" >
< div class = "device-item-body" >
< div class = "info-item" >
< div > 当前 步骤: < / div >
< div >
< div > 错误发生 步骤: < / div >
< div class = "text-red" >
{ {
upgradeProgressStatusMap . find (
r => r . status === item . upFirmwareStatus ? . step
r => r . status == item . upFirmwareStatus ? . step
) ? . text ? ? '--'
} }
} } 失败
< / div >
< / div >
< div class = "info-item" >
< div > 升级 错误信息: < / div >
< div > 错误信息 : < / div >
< div > { { item . upFirmwareStatus ? . errMsg ? ? '--' } } < / div >
< / div >
< / div >
< / template >
< template v-if ="item.upFirmware === 'timeout'" >
< div class = "w-full h-full flex items-center justify-center" >
< div class = "font-400 text-base text-[#E6A23C]" > 升级超时 < / div >
< / div >
< / template >
< / div >
< / div >
< / div >
< / e l - c h e c k b o x - g r o u p >
< / div >
< / EdfsWrap >
< EdfsWrap title = "迁移进度" class = "transfer-wrap h-[42%]" v-if ="isShowTransfer" >
< div class = "flex-col gap-col-10 wh-full" >
< div class = "flex items-center gap-col-1" >
< div class = "flex-1 flex items-center" >
< el -progress
: percentage = "100"
class = "flex-1"
: stroke - width = "18"
: text - inside = "true"
: status = "
[ 'progress' , 'success' , undefined ] . includes ( transferStatus )
< TransferMask v-model ="isShowTransferMask" :transferLoading="transferLoading" @close="closeTransferMask" >
< template v-if ="curTransfer === 'export'" >
< div class = "flex-col gap-col-10 h-full w-56% justify-center" >
< div class = "flex items-center gap-col-1" >
< div class = "flex-1 flex items-center" >
< el -progress :percentage ="100" class = "flex-1" :stroke-width ="18" :text-inside ="true"
: striped = "transferStatus === 'progress'" : striped - flow = "transferStatus === 'progress'" : duration = "20"
: status = " [ 'progress' , 'success' , undefined ] . includes ( transferStatus )
? 'success'
: 'exception'
"
>
{ {
transferStatusMap [ transferStatus as keyof typeof transferStatusMap ] ? ? ''
} }
< / e l - p r o g r e s s >
" >
{ {
transferStatusMap [ transferStatus as keyof typeof transferStatusMap ] ? ? ''
} }
< / e l - p r o g r e s s >
< / div >
< el -button v-if ="transferStatus === 'progress'" type="primary" @click="onStopTransfer" > 停止迁移 < / el -button >
< / div >
< div class = "transfer-log-wrap h-490 flex-col" >
< div class = "text-16px font-500" > 迁移日志 < / div >
< el -scrollbar class = "flex-1" >
< div v -for = " i in curTransferLog " : class = "i.status === 'failed' ? 'text-red-500' : ''"
class = "text-gray-600" >
{ { i . msg } }
< / div >
< / e l - s c r o l l b a r >
< / div >
< el -button
v - if = "transferStatus === 'progress'"
type = "primary"
@ click = "onStopTransfer"
> 停止迁移 < / e l - b u t t o n
>
< / div >
< div class = "transfer-log-wrap" >
< div class = "text-16px font-500" > 迁移日志 < / div >
< el -scrollbar class = "h-full" >
< div
v - for = "i in curTransferLog"
: class = "i.status === 'failed' ? 'text-red-500' : ''"
class = "text-gray-600"
>
{ { i . msg } }
< / template >
< template v -else -if = " curTransfer = = = ' import ' " >
< div class = "flex-col gap-col-10 h-full w-56% justify-center" >
< div class = "flex items-center gap-col-1" >
< div class = "flex-1 items-center" >
< el -progress :percentage ="100" : status = " [ ' progress ' , ' success ' , undefined ] .includes ( onOffDeviceTransferStatus )
? 'success'
: 'exception'
" 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 >
< / e l - p r o g r e s s >
< / div >
< / e l - s c r o l l b a r >
< / 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 >
< / e l - s c r o l l b a r >
< / div >
< / div >
< / div >
< / EdfsWrap >
< / template >
< / TransferMask >
< / div >
< TransferDlg
ref = "transferDlgRef"
@ on - save = "onSave"
: is - batch - transfer = "isBatchTransfer"
/ >
< DeviceDrawer
v - model = "isShowDetails"
ref = "deviceDrawerRef"
: siteInfo = "siteInfo"
: is - transfer = "isTransfer"
/ >
< TransferDlg ref = "transferDlgRef" @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" / >
< / template >
< script setup lang = "ts" >
import dayjs from 'dayjs'
import TransferMask from './components/transferMask.vue'
import TransferDlg from './components/transferDlg.vue'
import ZMQWorker from '@/composables/useZMQJsonWorker'
import OffTransferDlg from './components/offTransferDlg.vue'
import {
getPubInitData ,
type PublishMsg ,
@ -217,6 +215,7 @@ import type {
@@ -217,6 +215,7 @@ import type {
import { useMessage } from '@/composables/useMessage'
import { getDeviceList , type ISite } from '@/api/module/transfer'
import DeviceDrawer from './components/deviceDrawer.vue'
import {
getFirmwareUpTopic ,
getTransferTopic ,
@ -235,14 +234,14 @@ const type = ref<'export' | 'details'>(route.query.type as 'export' | 'details')
@@ -235,14 +234,14 @@ const type = ref<'export' | 'details'>(route.query.type as 'export' | 'details')
const isTransfer = computed ( ( ) => type . value === 'export' )
const isShowTransfer = computed ( ( ) => isTransfer . value && ! ! curTransferLog . value . length )
const isShowTransferMask = ref ( false )
const message = useMessage ( )
const worker = ZMQWorker . getInstance ( )
const transferDataStore = useTransferDataStore ( )
const { upFirmwarePending , upFirmwareReset , upFirmwareStatus , upFirmwareSucceed } =
const { upFirmwarePending , upFirmwareReset , upFirmwareStatus , upFirmwareSucceed , upFirmwareStatusReject , upFirmwareTimeout } =
transferDataStore
const { devicesMap } = storeToRefs ( transferDataStore )
@ -265,11 +264,33 @@ const devices = computed(() => {
@@ -265,11 +264,33 @@ const devices = computed(() => {
return isTransfer . value ? Array . from ( devicesMap . value . values ( ) ) : deviceList . value
} ) as Ref < any [ ] >
function onSave ( msg : PublishMsg < 'export' > , device : IOnlineDevice ) {
const transferLoading = ref ( false )
const curTransfer = ref < 'import' | 'export' > ( )
function openTransferMask ( status : 'import' | 'export' ) {
isShowTransferMask . value = true
curTransfer . value = status
transferLoading . value = true
}
function closeTransferMask ( ) {
curTransfer . value = undefined
isShowTransferMask . value = false
transferLoading . value = false
curTransferLog . value = [ ]
transferStatus . value = undefined
siteTransferLogList . value = [ ]
pubIdWithOffDevice . clear ( )
exportPubDeviceMap . clear ( )
}
function onLineDeviceTransfer ( msg : PublishMsg < 'export' > , device : IOnlineDevice ) {
curTransferLog . value = [ ]
openTransferMask ( 'export' )
worker . publish ( postTransferTopic , msg , true , zmqTimeoutCb )
exportPubDeviceMap . set ( msg . id , { device , action : 'export' } )
worker . subscribe ( getTransferTopic , zmqExportCb , msg . id )
if ( isBatchTransfer . value ) {
onBatchCancel ( )
}
@ -281,15 +302,17 @@ const statusMap = {
@@ -281,15 +302,17 @@ const statusMap = {
1003 : 'failed' ,
}
function zmqExportCb ( msg : PubMsgData ) {
if ( ! isTransfer . value ) return
const { feedback , result , id } = msg
transferLoading . value = false
if ( feedback && feedback [ 0 ] ) {
const status = feedback [ 1 ]
? ( statusMap [ feedback [ 1 ] as keyof typeof statusMap ] as
| 'success'
| 'padding'
| 'failed' )
| 'success'
| 'padding'
| 'failed' )
: 'failed'
curTransferLog . value . push ( {
msg : ` 主机【 ${ feedback [ 0 ] } 】: ${ feedback [ 2 ] } ` ,
@ -297,9 +320,9 @@ function zmqExportCb(msg: PubMsgData) {
@@ -297,9 +320,9 @@ function zmqExportCb(msg: PubMsgData) {
status ,
} )
}
/ / 找 到 s t a t u s 为 f a i l e d 的
transferStatus . value = 'progress'
if ( result !== 'progress' ) {
const curMsgInfo = exportPubDeviceMap . get ( id ) !
if ( ! curMsgInfo ) return
const { device , action } = curMsgInfo
@ -314,6 +337,7 @@ function zmqExportCb(msg: PubMsgData) {
@@ -314,6 +337,7 @@ function zmqExportCb(msg: PubMsgData) {
transferStatus . value = 'failed'
}
} else if ( [ 'failed' , 'failure' ] . includes ( result ) ) {
message . error ( ` 迁移失败 ` )
transferStatus . value = 'failed'
}
@ -339,21 +363,17 @@ function onStopTransfer() {
@@ -339,21 +363,17 @@ function onStopTransfer() {
const msg = getPubInitData < 'cancel' > ( 'cancel' , [ ] , 'no' )
worker . publish ( postTransferTopic , msg )
message . success ( '迁移已取消' )
clearTransferData ( )
exportPubDeviceMap . clear ( )
} )
}
function clearTransferData ( ) {
curTransferLog . value = [ ]
transferStatus . value = undefined
exportPubDeviceMap . clear ( )
}
function zmqTimeoutCb ( msg : TimeoutMsg ) {
const { device , action } = exportPubDeviceMap . get ( msg . timeoutId ) !
if ( device && action === 'export' ) {
message . error ( ` 迁移超时,请重新稍后尝试 ` )
exportPubDeviceMap . delete ( msg . timeoutId )
closeTransferMask ( )
}
}
@ -430,7 +450,11 @@ function onBatchCancel() {
@@ -430,7 +450,11 @@ function onBatchCancel() {
onlineDeviceCheckList . value = [ ]
}
function onTransfer ( item : IOnlineDevice ) {
transferDlgRef . value ? . open ( item )
if ( isTransfer . value ) {
transferDlgRef . value ? . open ( item )
} else {
offTransferDlg . value ? . open ( item )
}
}
function onBack ( ) {
@ -458,7 +482,7 @@ onBeforeRouteLeave(async (to, from, next) => {
@@ -458,7 +482,7 @@ onBeforeRouteLeave(async (to, from, next) => {
const deviceList = ref < IOfflineDevice [ ] > ( [ ] )
async function loadDeviceList ( ) {
const res = await getDeviceList ( siteInfo . value . id )
const res = await getDeviceList ( siteInfo . value . name )
if ( res . code === 200 || res . code === 0 ) {
deviceList . value = res . data
}
@ -472,7 +496,7 @@ onMounted(async () => {
@@ -472,7 +496,7 @@ onMounted(async () => {
} else {
const res = await getFirmwarePath ( )
if ( res . code === 200 || res . code === 0 ) {
firmwarePath . value = res . data
firmwarePath . value = res . data . path
}
}
} )
@ -507,7 +531,7 @@ function onFirmwareUpload(devices: IOnlineDevice[]) {
@@ -507,7 +531,7 @@ function onFirmwareUpload(devices: IOnlineDevice[]) {
action : 'upgrade' ,
} )
}
worker . publish ( postFirmwareUpTopic , msg , true , firmwareUpTimeoutCb )
worker . publish ( postFirmwareUpTopic , msg , true , firmwareUpTimeoutCb , true )
worker . subscribe ( getFirmwareUpTopic , zmqUpgradeCb , msg . id )
upgradeSnList . value = deviceSn . split ( ',' )
@ -517,9 +541,18 @@ function onFirmwareUpload(devices: IOnlineDevice[]) {
@@ -517,9 +541,18 @@ function onFirmwareUpload(devices: IOnlineDevice[]) {
function firmwareUpTimeoutCb ( msg : TimeoutMsg ) {
const { device , action } = upgradePubDeviceMap . get ( msg . timeoutId ) !
if ( device && action === 'upgrade' ) {
message . error ( ` 固件升级超时,请重新稍后尝试 ` )
const timeoutUpgradeSnList = upgradeSnList . value
if ( timeoutUpgradeSnList . length === 0 ) {
upFirmwareReset ( upgradeSnList . value )
upgradePubDeviceMap . delete ( msg . timeoutId )
return
}
for ( const deviec of timeoutUpgradeSnList ) {
upFirmwareTimeout ( deviec )
}
upgradePubDeviceMap . delete ( msg . timeoutId )
upFirmwareReset ( upgradeSnList . value )
message . warning ( ` 固件升级超时,请稍后重试 ` )
}
}
@ -529,8 +562,7 @@ function zmqUpgradeCb(msg: PubMsgData) {
@@ -529,8 +562,7 @@ function zmqUpgradeCb(msg: PubMsgData) {
const deviceSn = msg . feedback [ 0 ]
const progressStatus = msg . feedback [ 1 ] as number
const progress = msg . feedback [ 2 ] || undefined
const errMsg = msg . feedback [ 3 ] || undefined
const curentDevice = upgradePubDeviceMap . get ( deviceSn )
const curentDevice = upgradePubDeviceMap . get ( msg . id )
if ( curentDevice && curentDevice . action === 'upgrade' ) {
const { device } = curentDevice
if ( device ) {
@ -542,17 +574,70 @@ function zmqUpgradeCb(msg: PubMsgData) {
@@ -542,17 +574,70 @@ function zmqUpgradeCb(msg: PubMsgData) {
}
}
if ( status === 'success' || status === 'error' ) {
message . success ( ` 固件升级 ${ status === 'success' ? '完成' : '失败' } ` )
upgradePubDeviceMap . delete ( deviceSn )
upFirmwareStatus ( deviceSn , msg . feedback )
if ( status === 'error' ) {
upFirmwareStatusReject ( deviceSn , msg . feedback )
}
upgradeSnList . value = upgradeSnList . value . filter ( item => item !== deviceSn )
/ / u p g r a d e P u b D e v i c e M a p . d e l e t e ( d e v i c e S n )
}
}
}
/ / = = = = = = = = = = = = = = = = 离 线 数 据 导 入 = = = = = = = = =
const offTransferDlg = ref < typeof OffTransferDlg > ( )
const pubIdWithOffDevice = new Map < string , { offDevice : IOfflineDevice ; action : ' import ' } > ( )
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 [ ] > ( [ ] )
const onOffDeviceTransferStatus = ref < 'progress' | 'success' | 'failed' | 'timeout' | undefined > ( )
function zmqImportCb ( msg : PubMsgData ) {
const { id , result , feedback } = msg
const { offDevice , action } = pubIdWithOffDevice . get ( id ) !
if ( action !== 'import' || ! offDevice ) return
transferLoading . value = false
if ( result === 'progress' ) {
onOffDeviceTransferStatus . value = 'progress'
const log : string = Array . isArray ( feedback ) ? feedback [ 0 ] || '' : ''
siteTransferLogList . value . push ( log )
}
if ( result !== 'progress' ) {
if ( result === 'success' ) {
onOffDeviceTransferStatus . value = 'success'
message . success ( ` 导出数据成功 ` )
} else {
onOffDeviceTransferStatus . value = 'failed'
message . error ( ` 导出数据失败 ` )
}
}
}
function zmqImportTimeoutCb ( msg : TimeoutMsg ) {
const { offDevice , action } = pubIdWithOffDevice . get ( msg . timeoutId ) !
if ( offDevice && action === 'import' ) {
message . error ( ` 站点: ${ offDevice . sn } 数据导出超时,请稍后重试 ` )
pubIdWithOffDevice . delete ( msg . timeoutId )
onOffDeviceTransferStatus . value = 'timeout'
closeTransferMask ( )
}
}
/ / = = = = = = = = = = = = = = = = 离 线 数 据 导 入 e n d = = = = = = = = =
< / script >
< style scoped lang = "scss" >
. transfer - log - wrap {
margin - top : 10 px ;
height : calc ( 100 % - 30 px ) ;
@ apply border - radius - 8 px bg - [ # F9FAFB ] p - 10 ;
: deep ( . el - scrollbar ) {