Browse Source

feat: 兼容云端的一些修改

main
betaqi 2 months ago
parent
commit
cde2242e52
  1. 2
      global.types/components.d.ts
  2. 37
      src/App.vue
  3. 4
      src/api/module/transfer/index.ts
  4. 4
      src/composables/useZMQJsonWorker.ts
  5. 2
      src/stores/transferData.ts
  6. 2
      src/utils/zmqJsonWorker.ts
  7. 66
      src/views/layout/index.vue
  8. 4
      src/views/stationData/components/PointGroupTree.vue
  9. 85
      src/views/stationData/components/deviceDrawer.vue
  10. 3
      src/views/stationData/components/newDataChart.vue
  11. 2
      src/views/stationData/components/onLineTransferDlg.vue
  12. 58
      src/views/stationData/transferData.vue
  13. 3
      src/views/stationData/type.ts

2
global.types/components.d.ts vendored

@ -24,8 +24,6 @@ declare module 'vue' {
ElDialog: typeof import('element-plus/es')['ElDialog'] ElDialog: typeof import('element-plus/es')['ElDialog']
ElDivider: typeof import('element-plus/es')['ElDivider'] ElDivider: typeof import('element-plus/es')['ElDivider']
ElDrawer: typeof import('element-plus/es')['ElDrawer'] ElDrawer: typeof import('element-plus/es')['ElDrawer']
ElEmpt: typeof import('element-plus/es')['ElEmpt']
ElEmpty: typeof import('element-plus/es')['ElEmpty']
ElHeader: typeof import('element-plus/es')['ElHeader'] ElHeader: typeof import('element-plus/es')['ElHeader']
ElInput: typeof import('element-plus/es')['ElInput'] ElInput: typeof import('element-plus/es')['ElInput']
ElMenu: typeof import('element-plus/es')['ElMenu'] ElMenu: typeof import('element-plus/es')['ElMenu']

37
src/App.vue

@ -5,7 +5,7 @@ import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import { ElNotification, type NotificationHandle } from 'element-plus' import { ElNotification, type NotificationHandle } from 'element-plus'
const worker = ZMQWorker.getInstance() const worker = ZMQWorker.getInstance()
const zmqStatus = ref<ZmqStatus>('connected') const zmqStatus = ref<ZmqStatus>('connected')
const env = import.meta.env
worker.setStatusCallback((status: string) => { worker.setStatusCallback((status: string) => {
zmqStatus.value = status as ZmqStatus zmqStatus.value = status as ZmqStatus
}) })
@ -21,23 +21,26 @@ onBeforeUnmount(() => {
const notification = ref<NotificationHandle>() const notification = ref<NotificationHandle>()
watch(zmqStatus, status => { watch(zmqStatus, status => {
if (status === 'disconnected') { if (env.VITE_APP_ENV === 'local') {
notification.value?.close() if (status === 'disconnected') {
notification.value = ElNotification({ notification.value?.close()
title: '通讯异常', notification.value = ElNotification({
message: '请检查通讯连接', title: '通讯异常',
type: 'error', message: '请检查连接状态',
duration: 0, type: 'error',
}) duration: 0,
} else { })
notification.value?.close() } else {
notification.value = ElNotification({ notification.value?.close()
title: '通讯正常', notification.value = ElNotification({
message: '通讯正常', title: '通讯正常',
type: 'success', message: '通讯正常',
duration: 3000, type: 'success',
}) duration: 3000,
})
}
} }
}) })
</script> </script>

4
src/api/module/transfer/index.ts

@ -1,12 +1,14 @@
import { globalServer } from '../index' import { globalServer } from '../index'
interface IGetDeviceDataParams { export interface IGetDeviceDataParams {
columns: string[] columns: string[]
isLocal: boolean isLocal: boolean
limit?: number limit?: number
offset?: number offset?: number
host?: string host?: string
name: string name: string
site_id?: string, // 云端必传
device_id?: string,// 云端必传
} }

4
src/composables/useZMQJsonWorker.ts

@ -1,7 +1,7 @@
import { WorkerCMD, ZmqCMD, } from '@/utils/zmq' import { WorkerCMD, ZmqCMD, } from '@/utils/zmq'
import type { ManualAction, PublishMsg, PubMsgData, SubMsgData, TimeoutMsg, ZmqMessage } from '@/utils/zmq' import type { ManualAction, PublishMsg, PubMsgData, SubMsgData, TimeoutMsg, ZmqMessage } from '@/utils/zmq'
import webWorker from '@/utils/zmqJsonWorker?worker' import webWorker from '@/utils/zmqJsonWorker?worker'
const env = import.meta.env
const defaultHost = import.meta.env.PROD ? window.location.hostname : '192.168.1.199' const defaultHost = import.meta.env.PROD ? window.location.hostname : '192.168.1.199'
class ZMQJsonWorker { class ZMQJsonWorker {
@ -131,7 +131,7 @@ class ZMQJsonWorker {
} else if (cmd === ZmqCMD.TIMEOUT) { } else if (cmd === ZmqCMD.TIMEOUT) {
this.handleTimeoutMessage(topic, msg); this.handleTimeoutMessage(topic, msg);
this.GC_pubReleaseTimeout(msg) this.GC_pubReleaseTimeout(msg)
console.log('pubTimeoutHandlers=>', this.pubTimeoutHandlers) // console.log('pubTimeoutHandlers=>', this.pubTimeoutHandlers)
} }
} }

2
src/stores/transferData.ts

@ -44,7 +44,7 @@ export const useTransferDataStore = defineStore('transfer', () => {
const device: IOnlineDevice = { const device: IOnlineDevice = {
clientIp: feedback[0], clientIp: feedback[0],
sn: sn, sn: sn,
stationName: feedback[2], site_id: feedback[2],
footprint: feedback[3] ?? '--', footprint: feedback[3] ?? '--',
lastUpdated: Date.now(), lastUpdated: Date.now(),
status: '在线', // 初始状态为在线 status: '在线', // 初始状态为在线

2
src/utils/zmqJsonWorker.ts

@ -5,7 +5,7 @@ import { WorkerCMD, ZmqCMD, type PublishMsg, type PubMsgData, } from './zmq'
const HEARTBEAT_TOPIC = 'HEARTBEAT' const HEARTBEAT_TOPIC = 'HEARTBEAT'
const HEARTBEAT_INTERVAL = 3000 const HEARTBEAT_INTERVAL = 3000
const STATUS_CHECK_INTERVAL = 1000 const STATUS_CHECK_INTERVAL = 1000
let messageTimeout = 5000 let messageTimeout = 10000
let heartClient: ZmqClient | null, subClient: ZmqClient | null, pubClient: ZmqClient | null let heartClient: ZmqClient | null, subClient: ZmqClient | null, pubClient: ZmqClient | null
let subHost = '', pubHost = '' let subHost = '', pubHost = ''

66
src/views/layout/index.vue

@ -2,55 +2,31 @@
<div class="common-layout"> <div class="common-layout">
<el-container> <el-container>
<el-aside class="aside-wrap"> <el-aside class="aside-wrap">
<RouterLink <RouterLink to="/" class="layout-logo" :class="{ 'layout-logo-collapse': isCollapse }">
to="/" <svg class="inline-block text-32px" width="1em" height="1em" viewBox="0 0 160 160"
class="layout-logo" xmlns="http://www.w3.org/2000/svg">
:class="{ 'layout-logo-collapse': isCollapse }"
>
<svg
class="inline-block text-32px"
width="1em"
height="1em"
viewBox="0 0 160 160"
xmlns="http://www.w3.org/2000/svg"
>
<path <path
d="M81.28 55.9c-.1-11.67-2.93-22.55-9.37-32.38-1-1.5-2.14-2.86-2.5-4.71a8.1 8.1 0 014-8.61 7.89 7.89 0 019.3 1.23 35.999 35.999 0 015.9 8.83 75.18 75.18 0 018.44 28.58 83.211 83.211 0 01-5.23 36.74 102.983 102.983 0 01-3 7.28 1.2 1.2 0 000 1.41c9.58 13.3 21.76 23 37.85 27.24a54.37 54.37 0 0019.68 1.57 7.72 7.72 0 018.36 6.9 7.903 7.903 0 01-6.7 9 64.744 64.744 0 01-23-1.33 77.68 77.68 0 01-36.93-19.88 93.628 93.628 0 01-11.91-13.71 2.18 2.18 0 00-2.3-1.06 72.744 72.744 0 00-27.38 7.55c-11.6 6-20.67 14.58-26.4 26.45a10.134 10.134 0 01-3.7 4.7 8 8 0 01-9.19-.7 7.86 7.86 0 01-2.36-9.28 60.324 60.324 0 018.72-14.52c12.2-15.43 28.21-24.59 47.32-28.57A85.085 85.085 0 0173.07 87c.524.015 1-.307 1.18-.8a76.06 76.06 0 006.53-22.3c.351-2.652.518-5.325.5-8z" d="M81.28 55.9c-.1-11.67-2.93-22.55-9.37-32.38-1-1.5-2.14-2.86-2.5-4.71a8.1 8.1 0 014-8.61 7.89 7.89 0 019.3 1.23 35.999 35.999 0 015.9 8.83 75.18 75.18 0 018.44 28.58 83.211 83.211 0 01-5.23 36.74 102.983 102.983 0 01-3 7.28 1.2 1.2 0 000 1.41c9.58 13.3 21.76 23 37.85 27.24a54.37 54.37 0 0019.68 1.57 7.72 7.72 0 018.36 6.9 7.903 7.903 0 01-6.7 9 64.744 64.744 0 01-23-1.33 77.68 77.68 0 01-36.93-19.88 93.628 93.628 0 01-11.91-13.71 2.18 2.18 0 00-2.3-1.06 72.744 72.744 0 00-27.38 7.55c-11.6 6-20.67 14.58-26.4 26.45a10.134 10.134 0 01-3.7 4.7 8 8 0 01-9.19-.7 7.86 7.86 0 01-2.36-9.28 60.324 60.324 0 018.72-14.52c12.2-15.43 28.21-24.59 47.32-28.57A85.085 85.085 0 0173.07 87c.524.015 1-.307 1.18-.8a76.06 76.06 0 006.53-22.3c.351-2.652.518-5.325.5-8z"
fill="currentColor" fill="currentColor"></path>
></path>
<path <path
d="M136.26 108.34a44.742 44.742 0 01-11.13-2.87 46.108 46.108 0 01-19.66-13.76 8 8 0 015.72-13.22 7.93 7.93 0 016.54 2.93 33.27 33.27 0 0018.87 10.75c1.546.155 3.058.553 4.48 1.18a8.08 8.08 0 013.84 9.21c-.92 3.52-4.13 5.81-8.66 5.78zm-80.6-75.02a7.61 7.61 0 016.64 5 49.139 49.139 0 013.64 17 46.33 46.33 0 01-2.46 17.28c-2 5.77-8.24 7.79-12.89 4.15a8.1 8.1 0 01-2.39-9 31.679 31.679 0 001.68-12.36 35.77 35.77 0 00-2.43-11c-2.1-5.45 1.75-11.07 8.21-11.07zm22.26 93.25a8 8 0 01-6.68 7.86 32.88 32.88 0 00-19.7 12.19 8.13 8.13 0 01-11.21 1.62 8 8 0 01-1.41-11.58A51.043 51.043 0 0154 123.81a45.842 45.842 0 0114-5.1c5.35-1.04 9.91 2.56 9.92 7.86z" d="M136.26 108.34a44.742 44.742 0 01-11.13-2.87 46.108 46.108 0 01-19.66-13.76 8 8 0 015.72-13.22 7.93 7.93 0 016.54 2.93 33.27 33.27 0 0018.87 10.75c1.546.155 3.058.553 4.48 1.18a8.08 8.08 0 013.84 9.21c-.92 3.52-4.13 5.81-8.66 5.78zm-80.6-75.02a7.61 7.61 0 016.64 5 49.139 49.139 0 013.64 17 46.33 46.33 0 01-2.46 17.28c-2 5.77-8.24 7.79-12.89 4.15a8.1 8.1 0 01-2.39-9 31.679 31.679 0 001.68-12.36 35.77 35.77 0 00-2.43-11c-2.1-5.45 1.75-11.07 8.21-11.07zm22.26 93.25a8 8 0 01-6.68 7.86 32.88 32.88 0 00-19.7 12.19 8.13 8.13 0 01-11.21 1.62 8 8 0 01-1.41-11.58A51.043 51.043 0 0154 123.81a45.842 45.842 0 0114-5.1c5.35-1.04 9.91 2.56 9.92 7.86z"
fill="currentColor" fill="currentColor"></path>
></path>
</svg> </svg>
<h2 class="pl-8px text-16px font-bold" v-show="!isCollapse"> <h2 class="pl-8px text-16px font-bold" v-show="!isCollapse">
数据迁移管理平台 数据迁移管理平台
</h2> </h2>
</RouterLink> </RouterLink>
<el-menu <el-menu class="layout-menu" :default-active="activeMenu" @select="menuSelect" router :collapse="isCollapse">
class="layout-menu"
:default-active="activeMenu"
@select="menuSelect"
router
:collapse="isCollapse"
>
<template v-for="router in menuList"> <template v-for="router in menuList">
<template v-if="router.meta?.isShow"> <template v-if="router.meta?.isShow">
<el-sub-menu <el-sub-menu v-if="router?.children?.filter((item: any) => item.meta?.isShow).length" :index="router.path"
v-if="router?.children?.filter((item: any) => item.meta?.isShow).length" :key="router.path">
:index="router.path"
:key="router.path"
>
<template #title> <template #title>
<div :class="router.meta.icon" class="menu-icon"></div> <div :class="router.meta.icon" class="menu-icon"></div>
<span>{{ router.meta.title }}</span> <span>{{ router.meta.title }}</span>
</template> </template>
<template v-for="child in router?.children"> <template v-for="child in router?.children">
<el-menu-item <el-menu-item v-if="child?.meta?.isShow" :key="child.path" :index="`${router.path}/${child.path}`">
v-if="child?.meta?.isShow"
:key="child.path"
:index="`${router.path}/${child.path}`"
>
<div :class="child.meta.icon" class="menu-icon"></div> <div :class="child.meta.icon" class="menu-icon"></div>
<span>{{ child.meta.title }}</span> <span>{{ child.meta.title }}</span>
</el-menu-item> </el-menu-item>
@ -91,13 +67,20 @@
import { useTheme } from '@/composables/useTheme' import { useTheme } from '@/composables/useTheme'
import { defaultRouter } from '@/router' import { defaultRouter } from '@/router'
import dayjs from 'dayjs' import dayjs from 'dayjs'
const env = import.meta.env
const unfold = 'i-icon-park-outline:menu-unfold' const unfold = 'i-icon-park-outline:menu-unfold'
const fold = 'i-icon-park-outline:menu-fold' const fold = 'i-icon-park-outline:menu-fold'
const { theme } = useTheme() const { theme } = useTheme()
const menuList = computed<any[]>(() => defaultRouter[0].children) const menuList = computed<any[]>(() => {
let data = defaultRouter[0].children
if (env.VITE_APP_ENV !== 'local') {
data = data.filter(item => item.name === 'firmware-upload')
}
return data
}
)
const circleUrl = ref( const circleUrl = ref(
'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png' 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png'
@ -137,15 +120,19 @@ onMounted(() => {
:deep(.el-container) { :deep(.el-container) {
@apply w-full h-full; @apply w-full h-full;
} }
:deep(.el-header) { :deep(.el-header) {
@apply h-56 w-full p0 flex items-center justify-between bg-white; @apply h-56 w-full p0 flex items-center justify-between bg-white;
} }
:deep(.el-main) { :deep(.el-main) {
@apply p0; @apply p0;
} }
:deep(.el-aside) { :deep(.el-aside) {
@apply w-auto; @apply w-auto;
} }
:deep(.el-menu) { :deep(.el-menu) {
@apply h-full; @apply h-full;
} }
@ -155,6 +142,7 @@ onMounted(() => {
border-radius: 4px; border-radius: 4px;
height: calc(100vh - 16px); height: calc(100vh - 16px);
} }
.layout-logo { .layout-logo {
@apply w-full flex-center nowrap-hidden h-56 bg-white; @apply w-full flex-center nowrap-hidden h-56 bg-white;
} }
@ -163,30 +151,38 @@ onMounted(() => {
height: calc(100vh - 56px); height: calc(100vh - 56px);
@apply border-r-none; @apply border-r-none;
} }
.layout-menu:not(.el-menu--collapse) { .layout-menu:not(.el-menu--collapse) {
width: 220px; width: 220px;
height: calc(100vh - 56px); height: calc(100vh - 56px);
} }
.layout-logo { .layout-logo {
transition: width 0.3s ease-in-out; transition: width 0.3s ease-in-out;
width: 220px; width: 220px;
} }
.layout-logo-collapse { .layout-logo-collapse {
width: 64px; width: 64px;
} }
:deep(.el-header) { :deep(.el-header) {
@apply p-x-12; @apply p-x-12;
} }
.collapes-btn { .collapes-btn {
@apply border-none; @apply border-none;
&:hover { &:hover {
background-color: rgba(46, 51, 56, 0.09); background-color: rgba(46, 51, 56, 0.09);
color: rgb(51, 54, 57); color: rgb(51, 54, 57);
} }
} }
.avatar { .avatar {
@apply w-24 h-24; @apply w-24 h-24;
} }
.menu-icon { .menu-icon {
@apply m-r-8; @apply m-r-8;
} }

4
src/views/stationData/components/PointGroupTree.vue

@ -1,6 +1,6 @@
<template> <template>
<div class=" h-full flex"> <div class=" h-full flex">
<div class="w-530"> <div class="w-280">
<el-scrollbar class="fault-device-tree"> <el-scrollbar class="fault-device-tree">
<el-tree :data="data" node-key="name" ref="treeRef" :expand-on-click-node="false" :props="defaultProps" <el-tree :data="data" node-key="name" ref="treeRef" :expand-on-click-node="false" :props="defaultProps"
highlight-current @node-click="handleNodeClick" :default-expanded-keys="checkDefault"> highlight-current @node-click="handleNodeClick" :default-expanded-keys="checkDefault">
@ -13,7 +13,7 @@
</el-scrollbar> </el-scrollbar>
</div> </div>
<el-divider direction="vertical" class="h-full" /> <el-divider direction="vertical" class="h-full" />
<div class="w-440"> <div class="w-340">
<el-scrollbar class="scroll"> <el-scrollbar class="scroll">
<el-checkbox-group v-model="checkPointList" class="point-checks" @change="changePoints"> <el-checkbox-group v-model="checkPointList" class="point-checks" @change="changePoints">
<template v-for="(item, index) in devicePoints" :key="index"> <template v-for="(item, index) in devicePoints" :key="index">

85
src/views/stationData/components/deviceDrawer.vue

@ -8,8 +8,12 @@
:groupChangeLoading="groupChangeLoading" @onchangePoints="onchangePoints" :device-points="pointList" :groupChangeLoading="groupChangeLoading" @onchangePoints="onchangePoints" :device-points="pointList"
:isTransfer="props.isTransfer" :siteInfo="props.siteInfo" ref="pointGroupTreeRef" /> :isTransfer="props.isTransfer" :siteInfo="props.siteInfo" ref="pointGroupTreeRef" />
</EdfsWrap> </EdfsWrap>
<NewDataChart v-if="isShowChart" :chart-datas="chartDatas" :legends="checkPointList" <div class="flex-1 p-4 h-full overflow-hidden">
<el-button class="mb-4" type="primary"
@click="loadChardData">查询数据</el-button>
<NewDataChart v-if="isShowChart" :chart-datas="chartDatas" :legends="legends"
:axis-data="Array.from(axisData)" ref="chartRef" /> :axis-data="Array.from(axisData)" ref="chartRef" />
</div>
</main> </main>
</el-drawer> </el-drawer>
</div> </div>
@ -30,6 +34,7 @@ import {
getDeviceDetails, getDeviceDetails,
getPointGroup, getPointGroup,
getPoints, getPoints,
type IGetDeviceDataParams,
type IPointGroupOV, type IPointGroupOV,
type IPointGroupParams, type IPointGroupParams,
type IPointsParams, type IPointsParams,
@ -38,6 +43,8 @@ import {
import { useMessage } from '@/composables/useMessage' import { useMessage } from '@/composables/useMessage'
import { getTransferTopic, postTransferTopic } from '../utils' import { getTransferTopic, postTransferTopic } from '../utils'
import dayjs from 'dayjs' import dayjs from 'dayjs'
const env = import.meta.env
const worker = ZMQWorker.getInstance() const worker = ZMQWorker.getInstance()
const isShowDrawer = defineModel<boolean>() const isShowDrawer = defineModel<boolean>()
@ -71,7 +78,7 @@ async function open(device: IOfflineDevice | IOnlineDevice) {
}) })
} }
const columsParams = computed(() => ['ts', ...pointList.value.map(i => i.addr)]) const columsParams = computed(() => ['ts', ...checkPointList.value.map(i => i.addr)])
async function loadPoints() { async function loadPoints() {
if (!curGroup.value) { if (!curGroup.value) {
message.error('请先选择点位组') message.error('请先选择点位组')
@ -93,7 +100,8 @@ async function loadPoints() {
const res = await getPoints(params) const res = await getPoints(params)
if (res.code === 0) { if (res.code === 0) {
pointList.value = res.data.map((i: any) => ({ const data = Array.isArray(res?.data) ? res.data : []
pointList.value = data.map((i: any) => ({
label: i.cnName, label: i.cnName,
addr: i.addr, addr: i.addr,
})) }))
@ -121,23 +129,61 @@ async function loadDeviceDetails() {
fullscreenLoading.value?.close() fullscreenLoading.value?.close()
return return
} }
isShowDrawer.value = true
groupChangeLoading.value = false
fullscreenLoading.value?.close()
}
const chartDatas = reactive(new Map<string, any[]>())
const axisData = new Set<string>()
const legends = ref<{ addr: string; label: string }[]>([])
async function loadChardData(){
if(!columsParams.value.filter(i => i !== 'ts').length){
message.error('请选择点位')
return
}
const res = await getDeviceDetails({ const params: IGetDeviceDataParams = {
columns: columsParams.value, columns: columsParams.value,
isLocal: props.isTransfer ? false : true, isLocal: props.isTransfer ? false : true,
host: props.isTransfer ? (curDevice.value as IOnlineDevice).clientIp : '', host: props.isTransfer ? (curDevice.value as IOnlineDevice).clientIp : '',
name: curGroupName.value as string name: curGroupName.value as string
}) }
if (env.VITE_APP_ENV !== 'local') {
params.site_id = props.siteInfo!.name || ''
params.device_id = curDevice.value?.sn || ''
}
const res = await getDeviceDetails(params)
if (res.code === 0) { if (res.code === 0) {
pointData.value = Array.isArray(res.data.results) ? res.data.results : [] pointData.value = Array.isArray(res.data.results) ? res.data.results : []
chartDatas.clear()
axisData.clear()
pointData.value.forEach((data: any[]) => {
const [ts, val, addr] = data
legends.value.push({
addr: addr,
label: checkPointList.value.find(i => i.addr === addr)!.label,
})
if (checkPointList.value.some(i => i.addr === addr)) {
const time = dayjs(Number(ts)).format('YYYY-MM-DD HH:mm:ss')
if (addr) {
const colData = chartDatas.get(addr)
if (colData) {
colData.push([time, val])
} else {
chartDatas.set(addr, [[time, val]])
}
}
isShowDrawer.value = true if (ts) {
axisData.add(time)
}
}
})
} else { } else {
message.error('获取设备数据失败') message.error('获取设备数据失败')
} }
groupChangeLoading.value = false
fullscreenLoading.value?.close()
} }
function zmqImport(device: IOfflineDevice) { function zmqImport(device: IOfflineDevice) {
@ -243,34 +289,13 @@ function onGroupChange(item: IPointGroupOV) {
loadDeviceDetails() loadDeviceDetails()
} }
const chartDatas = reactive(new Map<string, any[]>())
const axisData = new Set<string>()
const checkPointList = ref<IMyPoint[]>([]) const checkPointList = ref<IMyPoint[]>([])
function onchangePoints(checkPoints: IMyPoint[]) { function onchangePoints(checkPoints: IMyPoint[]) {
checkPointList.value = [] checkPointList.value = []
checkPointList.value = checkPoints checkPointList.value = checkPoints
chartDatas.clear()
axisData.clear()
pointData.value.forEach((data: any[]) => {
const [ts, val, addr] = data
if (checkPoints.some(i => i.addr === addr)) {
const time = dayjs(Number(ts)).format('YYYY-MM-DD HH:mm:ss')
if (addr) {
const colData = chartDatas.get(addr)
if (colData) {
colData.push([time, val])
} else {
chartDatas.set(addr, [[time, val]])
}
}
if (ts) {
axisData.add(time)
}
}
})
} }
defineExpose({ defineExpose({

3
src/views/stationData/components/newDataChart.vue

@ -1,7 +1,6 @@
<template> <template>
<div class="device-data-chart"> <div class="device-data-chart">
<el-empty v-if="legends.length > 0 && chartDatas.size == 0" description="description" /> <v-chart class="chart" :option="chartOption" :autoresize="autoresize" :loading-options="loadingOpt"
<v-chart v-else class="chart" :option="chartOption" :autoresize="autoresize" :loading-options="loadingOpt"
:loading="loading" ref="chartRef" @legendselectchanged="changeLegend" /> :loading="loading" ref="chartRef" @legendselectchanged="changeLegend" />
</div> </div>
</template> </template>

2
src/views/stationData/components/onLineTransferDlg.vue

@ -81,7 +81,7 @@ function onSave() {
`${ `${
props.isBatchTransfer props.isBatchTransfer
? batchPath.value ? batchPath.value
: `${curDevice.value.stationName}/${curDevice.value.sn}` : `${curDevice.value.site_id}/${curDevice.value.sn}`
}`, }`,
`${dayjs(form.value.timeArr[0]).valueOf()},${dayjs(form.value.timeArr[1]).valueOf()}`, `${dayjs(form.value.timeArr[0]).valueOf()},${dayjs(form.value.timeArr[1]).valueOf()}`,
] ]

58
src/views/stationData/transferData.vue

@ -5,17 +5,20 @@
</el-button> </el-button>
<EdfsWrap title="设备列表" class="flex-1" useScrollBar> <EdfsWrap title="设备列表" class="flex-1" useScrollBar>
<template #title-right> <template #title-right>
<template v-if="isBatchTransfer || isBatchUpgrade"> <template v-if="env.VITE_APP_ENV == 'local'">
<el-button type="primary" @click="onBatchSave"> 确定{{ batchText }} </el-button> <template v-if="isBatchTransfer || isBatchUpgrade">
<el-button type="info" @click="onBatchCancel"> 取消 </el-button> <el-button type="primary" @click="onBatchSave"> 确定{{ batchText }} </el-button>
</template> <el-button type="info" @click="onBatchCancel"> 取消 </el-button>
<template v-else> </template>
<el-button type="primary" @click="onBatchTransfer"> <i class="i-mdi:database-arrow-right-outline mr-1" /> <template v-else>
批量迁移 </el-button> <el-button type="primary" @click="onBatchTransfer"> <i class="i-mdi:database-arrow-right-outline mr-1" />
<el-button v-if="isonLineTransfer" type="primary" @click="onBatchUpgrade"> <i 批量迁移 </el-button>
class="i-codicon:chip mr-1" />批量升级 <el-button v-if="isonLineTransfer" type="primary" @click="onBatchUpgrade"> <i
</el-button> class="i-codicon:chip mr-1" />批量升级
</el-button>
</template>
</template> </template>
</template> </template>
<div class="device-list-wrap"> <div class="device-list-wrap">
<el-checkbox-group v-model="checkDeviceList"> <el-checkbox-group v-model="checkDeviceList">
@ -29,21 +32,26 @@
<div>设备ID: {{ item.sn }}</div> <div>设备ID: {{ item.sn }}</div>
</div> </div>
</div> </div>
<div class="flex items-center gap-col-2" v-if="!(isBatchTransfer || isBatchUpgrade)"> <div class="flex items-center gap-col-2" v-if="!(isBatchTransfer || isBatchUpgrade)">
<el-tooltip content="数据迁移" v-if="isonLineTransfer ? item.status === '在线' : true"> <template v-if="env.VITE_APP_ENV == 'local'">
<i class="i-mdi:database-arrow-right-outline :hover:color-[#8ACE6A] color-[#4B9E5F] cursor-pointer text-20px" <el-tooltip content="数据迁移" v-if="isonLineTransfer ? item.status === '在线' : true">
@click="onTransfer(item)"></i> <i class="i-mdi:database-arrow-right-outline :hover:color-[#8ACE6A] color-[#4B9E5F] cursor-pointer text-20px"
</el-tooltip> @click="onTransfer(item)"></i>
<el-tooltip content="固件升级" v-if="isonLineTransfer && item.status === '在线'"> </el-tooltip>
<i class="i-codicon:chip :hover:color-[#8ACE6A] color-[#4B9E5F] cursor-pointer text-20px" <el-tooltip content="固件升级" v-if="isonLineTransfer && item.status === '在线'">
@click="onFirmwareUpload([item])"></i> <i class="i-codicon:chip :hover:color-[#8ACE6A] color-[#4B9E5F] cursor-pointer text-20px"
</el-tooltip> @click="onFirmwareUpload([item])"></i>
</el-tooltip>
</template>
<el-tooltip content="详情"> <el-tooltip content="详情">
<div <div
class="i-material-symbols:info-outline :hover:color-[#8ACE6A] color-[#4B9E5F] cursor-pointer text-20px" class="i-material-symbols:info-outline :hover:color-[#8ACE6A] color-[#4B9E5F] cursor-pointer text-20px"
@click="onDeviceDetails(item)"></div> @click="onDeviceDetails(item)"></div>
</el-tooltip> </el-tooltip>
</div> </div>
</div> </div>
<div class="device-item-body relative"> <div class="device-item-body relative">
@ -167,8 +175,8 @@
? 'success' ? 'success'
: 'exception' : 'exception'
" class="flex-1" :stroke-width="18" :text-inside="true" " class="flex-1" :stroke-width="18" :text-inside="true"
:striped="onOffDeviceTransferStatus === 'progress'" :striped="onOffDeviceTransferStatus === 'progress' || !onOffDeviceTransferStatus"
:striped-flow="onOffDeviceTransferStatus === 'progress'" :duration="20"> :striped-flow="onOffDeviceTransferStatus === 'progress' || !onOffDeviceTransferStatus" :duration="20">
<div class="text-16px font-500"> {{ !!onOffDeviceTransferStatus ? onOffDeviceTransferStatus === <div class="text-16px font-500"> {{ !!onOffDeviceTransferStatus ? onOffDeviceTransferStatus ===
'progress' 'progress'
@ -188,7 +196,6 @@
</div> </div>
</div> </div>
</template> </template>
</TransferMask> </TransferMask>
</div> </div>
@ -232,6 +239,7 @@ import {
upgradeProgressStatusMap, upgradeProgressStatusMap,
} from './utils' } from './utils'
import { getFirmwarePath } from '@/api/module/firmware' import { getFirmwarePath } from '@/api/module/firmware'
const env = import.meta.env
const onLineTransferDlgRef = ref<typeof OnLineTransferDlg>() const onLineTransferDlgRef = ref<typeof OnLineTransferDlg>()
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
@ -393,15 +401,15 @@ const onlineDeviceMap: Record<
string string
> = { > = {
status: '状态', status: '状态',
stationName: '站点名称', site_id: '站点名称',
clientIp: '客户端IP', clientIp: '客户端IP',
footprint: '数据占用空间', footprint: '数据占用空间',
} }
const offlineDeviceMap: Record< const offlineDeviceMap: Record<
keyof Pick<IOfflineDevice, 'stationName' | 'db' | 'create_time'>, keyof Pick<IOfflineDevice, 'site_id' | 'db' | 'create_time'>,
string string
> = { > = {
stationName: '站点名称', site_id: '站点名称',
db: '数据库', db: '数据库',
create_time: '创建时间', create_time: '创建时间',
} }
@ -419,7 +427,7 @@ function onBatchTransferSave(checkDeviceList: IOnlineDevice[] | IOfflineDevice[]
const checkList = checkDeviceList as IOnlineDevice[] const checkList = checkDeviceList as IOnlineDevice[]
const clientIpList = checkList.map(item => item?.clientIp).join(',') const clientIpList = checkList.map(item => item?.clientIp).join(',')
const pathList = checkList const pathList = checkList
.map(item => `${item?.stationName}/${item?.sn}`) .map(item => `${item?.site_id}/${item?.sn}`)
.filter(Boolean) .filter(Boolean)
.join(',') .join(',')

3
src/views/stationData/type.ts

@ -1,7 +1,7 @@
export interface IOnlineDevice { export interface IOnlineDevice {
clientIp: string clientIp: string
sn: string sn: string
stationName: string site_id: string
footprint: string footprint: string
lastUpdated: number // 新增字段,记录最后更新时间 lastUpdated: number // 新增字段,记录最后更新时间
status?: string status?: string
@ -13,7 +13,6 @@ export interface IOnlineDevice {
export interface IOfflineDevice { export interface IOfflineDevice {
id: string id: string
sn: string sn: string
stationName: string
databaseList: string databaseList: string
last_modify_time?: string last_modify_time?: string
create_time: string create_time: string

Loading…
Cancel
Save