You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

180 lines
4.9 KiB

<template>
<div class="relative h-full w-full">
<el-button type="primary" @click="onBack" class="absolute top-0 z-99">
<i class="i-line-md:arrow-left"></i>返回站点数据
</el-button>
<el-empty v-if="!topologyTree && !loading" class="w-full h-full"></el-empty>
<div
id="container"
class="w-full h-full"
v-loading="loading"
element-loading-text="设备加载中请稍等..."
style="width: 100%;height: 100%">
</div>
</div>
<detail-drawer ref="detailDrawerRef"/>
</template>
<script setup lang="ts">
import { DeviceType, NODE_SIZE } from "./utils";
import { useG6 } from "@/hooks/useG6";
import Node from './components/Node.vue'
import { flattenTree } from "@/views/testG6/utils";
import { type PluginOptions } from "@antv/g6"
import type { IDevice, IOfflineDevice, IOnlineDevice } from "@/views/stationData/type";
import { getPointGroup, type IPointGroupParams, type IPointGroupOV } from "@/api/module/transfer";
import DetailDrawer from "./components/detailDrawer.vue";
import { VueNode } from "g6-extension-vue";
const router = useRouter()
const route = useRoute()
const deviceInfo = route.query?.deviceInfo
? JSON.parse(route.query?.deviceInfo as string)
: {} as unknown as IDevice & { isonLine: boolean, siteName: string }
const detailDrawerRef = ref<InstanceType<typeof DetailDrawer>>()
const topologyTree = ref<IPointGroupOV>()
const loading = ref(true)
async function loadDeviceTopology() {
const params: IPointGroupParams = {}
if (deviceInfo.isonLine) {
const onlineDevice = deviceInfo as IOnlineDevice
params.isLocal = false
params.host = onlineDevice.clientIp
} else {
const offlineDevice = deviceInfo as unknown as IOfflineDevice & { siteName: string }
params.sn = offlineDevice.sn
params.site = offlineDevice!.siteName
params.isLocal = true
}
const res = await getPointGroup(params)
if (res.code === 0) {
topologyTree.value = {
id: deviceInfo.sn,
ip: deviceInfo.ip,
name: deviceInfo?.sn,
cnName: deviceInfo?.name ?? deviceInfo?.sn,
port: deviceInfo.port,
slave_addr: 'root',
type: deviceInfo?.type ?? 'emu',
children: []
}
topologyTree.value.children = Array.isArray(res?.data) ? res.data : []
}
}
const getNodeData = (target: VueNode) => {
const targetId = target.config.id
const context = target.config!.context
return context.model.getNodeData(targetId).find((r: any) => r.id === targetId)
}
const canvas = ref<HTMLElement | undefined>(undefined)
const plugins: PluginOptions = [
{
type: 'contextmenu',
enable: (e: any) => e.targetType === 'node',
getItems: (e: any) => {
const { data } = getNodeData(e.target)
const menu = [{ name: '查看详情', value: 'detail' }]
if (data.type === DeviceType.bms) {
menu.unshift({ name: '固件升级', value: 'firmwareUpdate' })
}
return menu;
},
onClick: onContextmenuClick,
},
{
type: 'tooltip',
enable: (e: any) => e.targetType === 'node',
getContent: (e: any, items: any) => {
return `<div>${items[0].data.cnName}</div>`;
},
},
]
function onContextmenuClick(e: string, item: HTMLElement, current: any) {
switch (e) {
case 'detail':
onDetail(item, current)
break;
case 'firmwareUpdate':
onFirmwareUpdate(item, current)
break;
default:
break;
}
}
function init() {
if (!topologyTree.value) return
const filteredTree = filterTree(topologyTree.value)
const device = flattenTree([filteredTree])
const { container, graph } = useG6({
tree: device,
nodeComponent: Node,
nodeSize: NODE_SIZE
}, plugins)
canvas.value = container.value
graph.render();
}
function onDetail(item: HTMLElement, current: any) {
const { data } = getNodeData(current)
const device = deviceInfo as unknown as IDevice & {
isonLine: boolean
siteName: string
}
detailDrawerRef.value?.open(device, data)
}
function onFirmwareUpdate(item: HTMLElement, current: any) {
const { data } = getNodeData(current)
window.open(`http://${data.ip}:${data.port}`, '_blank', 'noopener');
}
onMounted(async () => {
await loadDeviceTopology()
loading.value = false
init()
})
function filterTree(node: IPointGroupOV) {
if (node.type === 'bms_cluster' && Array.isArray(node.children)) {
if (node.children.length > 1) {
const customNode = node.children[0] as any
node.children.forEach(r => {
r.customCnName = r.cnName
})
customNode.cnName = `${node.children[0].cnName} ~ ${node.children[node.children.length - 1].cnName}`
customNode.customNode = true
customNode.brother = node.children
node.children = [customNode]
}
}
if (Array.isArray(node.children)) {
node!.children = node.children.map((child: any) => {
child.parentName = node.name
return filterTree(child)
})
}
return node
}
function onBack() {
router.push('/station')
}
</script>
<style scoped lang="scss">
</style>