Browse Source

style: 文件位置变更

main
betaqi 1 month ago
parent
commit
bff6fef087
  1. 2
      global.types/components.d.ts
  2. 34
      src/router/index.ts
  3. 2
      src/views/stationData/transfer/components/PointGroupTree.vue
  4. 6
      src/views/stationData/transfer/components/deviceDrawer.vue
  5. 5
      src/views/stationData/transfer/components/newDataChart.vue
  6. 13
      src/views/stationData/transfer/components/offTransferDlg.vue
  7. 30
      src/views/stationData/transfer/components/onLineTransferDlg.vue
  8. 0
      src/views/stationData/transfer/components/transferMask.vue
  9. 46
      src/views/stationData/transfer/index.vue
  10. 2
      src/views/testG6/components/Node.vue
  11. 57
      src/views/testG6/index.vue
  12. 37
      src/views/testG6/utils/GenerateGraphData.ts
  13. 85
      src/views/testG6/utils/MyLineEdge.ts
  14. 72
      src/views/testG6/utils/MyNode.ts
  15. 52
      src/views/testG6/utils/data.ts
  16. 5
      src/views/testG6/utils/index.ts

2
global.types/components.d.ts vendored

@ -15,6 +15,8 @@ declare module 'vue' {
EdfsTable: typeof import('./../src/components/Edfs-table/index.vue')['default'] EdfsTable: typeof import('./../src/components/Edfs-table/index.vue')['default']
EdfsWrap: typeof import('./../src/components/Edfs-wrap.vue')['default'] EdfsWrap: typeof import('./../src/components/Edfs-wrap.vue')['default']
ElAside: typeof import('element-plus/es')['ElAside'] ElAside: typeof import('element-plus/es')['ElAside']
ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem']
ElButton: typeof import('element-plus/es')['ElButton'] ElButton: typeof import('element-plus/es')['ElButton']
ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup'] ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']

34
src/router/index.ts

@ -25,13 +25,23 @@ export const defaultRouter = [
{ {
path: '/station/data-transfer', path: '/station/data-transfer',
name: 'data-transfer', name: 'data-transfer',
component: () => import('@/views/stationData/transferData.vue'), component: () => import('@/views/stationData/transfer/index.vue'),
meta: { meta: {
title: '数据迁移', title: '数据迁移',
isShow: false, isShow: false,
icon: 'i-mingcute:transfer-2-line', icon: '',
}, },
}, },
// {
// path: '/station/topology',
// name: 'data-topology',
// component: () => import('@/views/stationData/transfer/index.vue'),
// meta: {
// title: '数据拓扑',
// isShow: false,
// icon: '',
// },
// },
// 固件上传 // 固件上传
{ {
path: '/firmware-upload', path: '/firmware-upload',
@ -53,16 +63,16 @@ export const defaultRouter = [
icon: 'i-mingcute:task-line', icon: 'i-mingcute:task-line',
} }
}, },
// { {
// path: '/testG6', path: '/testG6',
// name: 'testG6', name: 'testG6',
// component: () => import('@/views/testG6/index.vue'), component: () => import('@/views/testG6/index.vue'),
// meta: { meta: {
// title: '测试G6', title: '测试G6',
// isShow: true, isShow: true,
// icon: 'i-mingcute:task-line', icon: 'i-mingcute:task-line',
// } }
// } }
], ],
}, },
] ]

2
src/views/stationData/components/PointGroupTree.vue → src/views/stationData/transfer/components/PointGroupTree.vue

@ -30,7 +30,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { ElTree } from 'element-plus' import type { ElTree } from 'element-plus'
import type { IPointGroupOV } from '@/api/module/transfer' import type { IPointGroupOV } from '@/api/module/transfer'
import type { IMyPoint } from '../type' import type { IMyPoint } from '../../type'
interface Props { interface Props {
data: IPointGroupOV[] data: IPointGroupOV[]

6
src/views/stationData/components/deviceDrawer.vue → src/views/stationData/transfer/components/deviceDrawer.vue

@ -42,7 +42,7 @@ import NewDataChart from './newDataChart.vue'
import PointGroupTree from './PointGroupTree.vue' import PointGroupTree from './PointGroupTree.vue'
import { type ManualAction, } from '@/utils/zmq' import { type ManualAction, } from '@/utils/zmq'
import ZMQWorker from '@/composables/useZMQJsonWorker' import ZMQWorker from '@/composables/useZMQJsonWorker'
import type { IMyPoint, IOfflineDevice, IOnlineDevice } from '../type' import type { IMyPoint, IOfflineDevice, IOnlineDevice } from '../../type'
import { import {
getDeviceDetails, getDeviceDetails,
getPointGroup, getPointGroup,
@ -215,7 +215,9 @@ async function loadChardData() {
const pageCount = Math.ceil(chartAllTotal.value / Number(limit)) const pageCount = Math.ceil(chartAllTotal.value / Number(limit))
if (pageCount <= 1) { if (pageCount <= 1) {
progress.value = 100 progress.value = 100
setTimeout(()=>{resetChartStatus()}) setTimeout(() => {
resetChartStatus()
})
return return
} }

5
src/views/stationData/components/newDataChart.vue → src/views/stationData/transfer/components/newDataChart.vue

@ -1,7 +1,8 @@
<template> <template>
<div class="device-data-chart"> <div class="device-data-chart">
<v-chart class="chart" :option="chartOption" :autoresize="autoresize" :loading-options="loadingOpt" <v-chart class="chart" :option="chartOption" :autoresize="autoresize"
:loading="loading" ref="chartRef" @legendselectchanged="changeLegend" /> :loading-options="loadingOpt"
:loading="loading" ref="chartRef" @legendselectchanged="changeLegend"/>
</div> </div>
</template> </template>

13
src/views/stationData/components/offTransferDlg.vue → src/views/stationData/transfer/components/offTransferDlg.vue

@ -1,5 +1,6 @@
<template> <template>
<EdfsDialog :title="'数据导出'" :is-show="visible" width="580px" :btnLoading="btnLoading" @on-close="close" <EdfsDialog :title="'数据导出'" :is-show="visible" width="580px" :btnLoading="btnLoading"
@on-close="close"
@on-save="onSave"> @on-save="onSave">
<div class="flex-col gap-10 w-80% m-x-30px"> <div class="flex-col gap-10 w-80% m-x-30px">
<el-row> <el-row>
@ -7,20 +8,20 @@
<span class="require">*</span> <span class="require">*</span>
云端IP: 云端IP:
</div> </div>
<el-input v-model="form.clientIp" class="flex-1" placeholder="请输入云端IP:" /> <el-input v-model="form.clientIp" class="flex-1" placeholder="请输入云端IP:"/>
</el-row> </el-row>
</div> </div>
</EdfsDialog> </EdfsDialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { getPubInitData, type PublishMsg } from '@/utils/zmq'
import { cloneDeep } from 'lodash-es' import { cloneDeep } from 'lodash-es'
import { useMessage } from '@/composables/useMessage' import { useMessage } from '@/composables/useMessage'
import type { IOfflineDevice } from '../type' import type { IOfflineDevice } from '../../type'
import type { ISite } from '@/api/module/transfer' import type { ISite } from '@/api/module/transfer'
import { createTask, type TaskCreateParams } from '@/api/module/taks' import { createTask, type TaskCreateParams } from '@/api/module/taks'
const message = useMessage() const message = useMessage()
@ -47,13 +48,14 @@ function open(parmas: TaskCreateParams) {
} }
const btnLoading = ref(false) const btnLoading = ref(false)
async function onSave() { async function onSave() {
if (verifyData()) return if (verifyData()) return
if (!paramsData.value) { if (!paramsData.value) {
message.error('参数错误') message.error('参数错误')
return return
} }
paramsData.value.devices.forEach((r) => { paramsData.value.devices.forEach((r) => {
r.host = form.value.clientIp r.host = form.value.clientIp
}) })
@ -74,6 +76,7 @@ function close() {
form.value = cloneDeep(fromData) form.value = cloneDeep(fromData)
paramsData.value = undefined paramsData.value = undefined
} }
const ipPattern = 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]?)$/ /^(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]?)$/

30
src/views/stationData/components/onLineTransferDlg.vue → src/views/stationData/transfer/components/onLineTransferDlg.vue

@ -1,16 +1,19 @@
<template> <template>
<EdfsDialog :title="isBatchTransfer ? '批量迁移' : '数据迁移'" :is-show="visible" width="580px" @on-close="close" <EdfsDialog :title="isBatchTransfer ? '批量迁移' : '数据迁移'" :is-show="visible" width="580px"
@on-close="close"
:btnLoading="btnLoading" :btnLoading="btnLoading"
@on-save="onSave"> @on-save="onSave">
<div class="flex-col gap-10 w-80% m-x-30px"> <div class="flex-col gap-10 w-80% m-x-30px">
<el-row> <el-row>
<div class="label"> <div class="label">
<span class="require">*</span> <span class="require">*</span>
数据开始时间: 数据开始时间:
</div> </div>
<el-date-picker v-model="startTime" value-format="YYYY-MM-DD HH:mm" format="YYYY-MM-DD HH:mm" class="flex-1" <el-date-picker v-model="startTime" value-format="YYYY-MM-DD HH:mm"
type="datetime" placeholder="请选择开始时间" :disabled-date="disabledDate" :disabled-time="disabledStartTime" format="YYYY-MM-DD HH:mm" class="flex-1"
@change="handleStartTimeChange" /> type="datetime" placeholder="请选择开始时间" :disabled-date="disabledDate"
:disabled-time="disabledStartTime"
@change="handleStartTimeChange"/>
</el-row> </el-row>
<el-row> <el-row>
@ -18,9 +21,11 @@
<span class="require">*</span> <span class="require">*</span>
数据结束时间: 数据结束时间:
</div> </div>
<el-date-picker v-model="endTime" class="flex-1" value-format="YYYY-MM-DD HH:mm" format="YYYY-MM-DD HH:mm" <el-date-picker v-model="endTime" class="flex-1" value-format="YYYY-MM-DD HH:mm"
type="datetime" placeholder="请选择结束时间" :disabled-date="disabledDate" :disabled-time="disabledEndTime" format="YYYY-MM-DD HH:mm"
@change="handleEndTimeChange" /> type="datetime" placeholder="请选择结束时间" :disabled-date="disabledDate"
:disabled-time="disabledEndTime"
@change="handleEndTimeChange"/>
</el-row> </el-row>
</div> </div>
</EdfsDialog> </EdfsDialog>
@ -28,10 +33,9 @@
<script setup lang="ts"> <script setup lang="ts">
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { getPubInitData, type PublishMsg } from '@/utils/zmq'
import type { IOnlineDevice } from '../type'
import { useMessage } from '@/composables/useMessage' import { useMessage } from '@/composables/useMessage'
import { createTask, type TaskCreateParams } from '@/api/module/taks' import { createTask, type TaskCreateParams } from '@/api/module/taks'
const message = useMessage() const message = useMessage()
const emit = defineEmits<{ const emit = defineEmits<{
@ -98,11 +102,13 @@ function handleEndTimeChange(val: string) {
const paramsData = ref<TaskCreateParams>() const paramsData = ref<TaskCreateParams>()
function open(parmas: TaskCreateParams) { function open(params: TaskCreateParams) {
paramsData.value = parmas paramsData.value = params
visible.value = true visible.value = true
} }
const btnLoading = ref(false) const btnLoading = ref(false)
async function onSave() { async function onSave() {
if (!verifyData()) return if (!verifyData()) return
if (!paramsData.value) { if (!paramsData.value) {

0
src/views/stationData/components/transferMask.vue → src/views/stationData/transfer/components/transferMask.vue

46
src/views/stationData/transferData.vue → src/views/stationData/transfer/index.vue

@ -15,15 +15,15 @@
<el-button type="primary" @click="onBatchSave"> <el-button type="primary" @click="onBatchSave">
确定{{ batchText }} 确定{{ batchText }}
</el-button> </el-button>
<el-button type="info" @click="onBatchCancel"> 取消 </el-button> <el-button type="info" @click="onBatchCancel"> 取消</el-button>
</template> </template>
<template v-else> <template v-else>
<el-button type="primary" @click="onBatchTransfer"> <el-button type="primary" @click="onBatchTransfer">
<i class="i-mdi:database-arrow-right-outline mr-1" /> <i class="i-mdi:database-arrow-right-outline mr-1"/>
{{ isonLineTransfer ? '数据迁移' : '数据导出' }} {{ isonLineTransfer ? '数据迁移' : '数据导出' }}
</el-button> </el-button>
<el-button v-if="isonLineTransfer" type="primary" @click="onBatchUpgrade"> <el-button v-if="isonLineTransfer" type="primary" @click="onBatchUpgrade">
<i class="i-codicon:chip mr-1" />批量升级 <i class="i-codicon:chip mr-1"/>批量升级
</el-button> </el-button>
</template> </template>
</template> </template>
@ -39,13 +39,15 @@
> >
<div>设备ID: {{ item.sn }}</div> <div>设备ID: {{ item.sn }}</div>
</el-checkbox> </el-checkbox>
<div v-else class="h-32 leading-32px"> <div v-else
<div>设备ID: {{ item.sn }}</div> class="h-32 leading-32px">
<div class="overflow-hidden text-ellipsis whitespace-nowrap w-140">设备ID:
{{ item.sn }}
</div>
</div> </div>
</div> </div>
<div <div
class="flex items-center gap-col-2" class="flex items-center gap-col-1"
v-if="!(isBatchTransfer || isBatchUpgrade)" v-if="!(isBatchTransfer || isBatchUpgrade)"
> >
<template v-if="env.VITE_APP_ENV == 'local'"> <template v-if="env.VITE_APP_ENV == 'local'">
@ -56,7 +58,7 @@
<i <i
class="i-mdi:database-arrow-right-outline :hover:color-[#8ACE6A] color-[#4B9E5F] cursor-pointer text-20px" class="i-mdi:database-arrow-right-outline :hover:color-[#8ACE6A] color-[#4B9E5F] cursor-pointer text-20px"
@click="onBatchTransferSave([item])" @click="onBatchTransferSave([item])"
></i> />
</el-tooltip> </el-tooltip>
<el-tooltip <el-tooltip
content="固件升级" content="固件升级"
@ -65,16 +67,23 @@
<i <i
class="i-codicon:chip :hover:color-[#8ACE6A] color-[#4B9E5F] cursor-pointer text-20px" class="i-codicon:chip :hover:color-[#8ACE6A] color-[#4B9E5F] cursor-pointer text-20px"
@click="onFirmwareUpload([item])" @click="onFirmwareUpload([item])"
></i> />
</el-tooltip> </el-tooltip>
</template> </template>
<el-tooltip content="详情"> <el-tooltip content="数据详情">
<div <i
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)" @click="onDeviceDetails(item)"
></div> />
</el-tooltip>
<el-tooltip content="拓扑详情">
<i
class="i-hugeicons:node-edit :hover:color-[#8ACE6A] color-[#4B9E5F] cursor-pointer text-20px"
@click="onTopology(item)"
/>
</el-tooltip> </el-tooltip>
</div> </div>
</div> </div>
@ -141,7 +150,7 @@ import OnLineTransferDlg from './components/onLineTransferDlg.vue'
import OffTransferDlg from './components/offTransferDlg.vue' import OffTransferDlg from './components/offTransferDlg.vue'
import { useTransferDataStore } from '@/stores/transferData' import { useTransferDataStore } from '@/stores/transferData'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import type { IOfflineDevice, IOnlineDevice } from './type' import type { IDevice, IOfflineDevice, IOnlineDevice } from '../type'
import { useMessage } from '@/composables/useMessage' import { useMessage } from '@/composables/useMessage'
import { getDeviceList, type ISite } from '@/api/module/transfer' import { getDeviceList, type ISite } from '@/api/module/transfer'
import DeviceDrawer from './components/deviceDrawer.vue' import DeviceDrawer from './components/deviceDrawer.vue'
@ -149,6 +158,7 @@ import DeviceDrawer from './components/deviceDrawer.vue'
import { getFirmwarePath } from '@/api/module/firmware' import { getFirmwarePath } from '@/api/module/firmware'
import { createTask, type TaskCreateParams } from '@/api/module/taks' import { createTask, type TaskCreateParams } from '@/api/module/taks'
import EdfsWrap from "@/components/Edfs-wrap.vue"; import EdfsWrap from "@/components/Edfs-wrap.vue";
const env = import.meta.env const env = import.meta.env
const onLineTransferDlgRef = ref<typeof OnLineTransferDlg>() const onLineTransferDlgRef = ref<typeof OnLineTransferDlg>()
const router = useRouter() const router = useRouter()
@ -180,6 +190,7 @@ function onLineDeviceTransfer() {
onBatchCancel() onBatchCancel()
} }
} }
const onlineDeviceMap: Record< const onlineDeviceMap: Record<
keyof Omit< keyof Omit<
IOnlineDevice, IOnlineDevice,
@ -204,6 +215,7 @@ const offlineDeviceMap: Record<
const checkDeviceList = ref<string[]>([]) const checkDeviceList = ref<string[]>([])
const isBatchTransfer = ref(false) const isBatchTransfer = ref(false)
function onBatchTransfer() { function onBatchTransfer() {
checkDeviceList.value = [] checkDeviceList.value = []
isBatchTransfer.value = true isBatchTransfer.value = true
@ -247,6 +259,7 @@ function onBatchTransferSave(checkDeviceList: IOnlineDevice[] | IOfflineDevice[]
} }
const isBatchUpgrade = ref(false) const isBatchUpgrade = ref(false)
function onBatchUpgrade() { function onBatchUpgrade() {
checkDeviceList.value = [] checkDeviceList.value = []
isBatchUpgrade.value = true isBatchUpgrade.value = true
@ -339,14 +352,20 @@ onMounted(async () => {
const isShowDetails = ref(false) const isShowDetails = ref(false)
const deviceDrawerRef = ref<typeof DeviceDrawer>() const deviceDrawerRef = ref<typeof DeviceDrawer>()
function onDeviceDetails(item: IOfflineDevice) { function onDeviceDetails(item: IOfflineDevice) {
deviceDrawerRef.value?.openFullScreen() deviceDrawerRef.value?.openFullScreen()
deviceDrawerRef.value?.open(item) deviceDrawerRef.value?.open(item)
} }
function onTopology(item: IDevice) {
console.log(item)
}
const isCanFirmwareUpload = computed(() => !!firmwarePath.value && isonLineTransfer.value) const isCanFirmwareUpload = computed(() => !!firmwarePath.value && isonLineTransfer.value)
const upgradeSnList = ref<string[]>([]) const upgradeSnList = ref<string[]>([])
async function onFirmwareUpload(devices: IOnlineDevice[]) { async function onFirmwareUpload(devices: IOnlineDevice[]) {
upgradeSnList.value = [] upgradeSnList.value = []
if (!isCanFirmwareUpload.value) { if (!isCanFirmwareUpload.value) {
@ -383,6 +402,7 @@ async function onFirmwareUpload(devices: IOnlineDevice[]) {
// ================ 线 ========= // ================ 线 =========
const offTransferDlgRef = ref<typeof OffTransferDlg>() const offTransferDlgRef = ref<typeof OffTransferDlg>()
function onOffDeviceTransfer() { function onOffDeviceTransfer() {
onBatchCancel() onBatchCancel()
} }

2
src/views/testG6/components/Node.vue

@ -3,7 +3,7 @@
width: NODE_SIZE[0] + 'px', width: NODE_SIZE[0] + 'px',
height: NODE_SIZE[1] + 'px', height: NODE_SIZE[1] + 'px',
borderRadius: '6px', borderRadius: '6px',
marginLeft: -(NODE_SIZE[0] / 2 - 10) + 'px', marginTop: '4px',
}" class="box-border rounded-md overflow-hidden flex"> }" class="box-border rounded-md overflow-hidden flex">
<div class="h-100% p-4px" :style="{ background: Device.bgColor}"> <div class="h-100% p-4px" :style="{ background: Device.bgColor}">
<img :src="Device.icon" style="height: 100%;" alt=""> <img :src="Device.icon" style="height: 100%;" alt="">

57
src/views/testG6/index.vue

@ -4,7 +4,7 @@
<script setup lang="ts"> <script setup lang="ts">
import DeviceData from './utils/data'; import DeviceData from './utils/data';
import { EmLineEdge, MyLineEdge } from './utils/MyLineEdge'; import { MyLineEdge } from './utils/MyLineEdge';
import { DeviceType, flattenTree, NODE_SIZE, VIRTUAL_NODE } from "./utils"; import { DeviceType, flattenTree, NODE_SIZE, VIRTUAL_NODE } from "./utils";
import { ExtensionCategory, Graph, register } from '@antv/g6'; import { ExtensionCategory, Graph, register } from '@antv/g6';
import GenerateGraphData from "./utils/GenerateGraphData"; import GenerateGraphData from "./utils/GenerateGraphData";
@ -13,27 +13,35 @@ import Node from './components/Node.vue'
onMounted(() => { onMounted(() => {
register(ExtensionCategory.NODE, 'vue-node', VueNode); register(ExtensionCategory.NODE, 'vue-node', VueNode);
register(ExtensionCategory.EDGE, 'em-line-edge', EmLineEdge)
register(ExtensionCategory.EDGE, 'my-line-edge', MyLineEdge); register(ExtensionCategory.EDGE, 'my-line-edge', MyLineEdge);
const device = flattenTree(DeviceData) const device = flattenTree(DeviceData)
const graphData = new GenerateGraphData(device) const graphData = new GenerateGraphData(device)
const graph = new Graph({ const graph = new Graph({
container: document.getElementById('container')!, container: document.getElementById('container')!,
padding: 50, padding: 50,
autoFit: { autoFit: 'view',
type: 'center',
},
layout: { layout: {
type: 'dagre', type: 'antv-dagre',
nodesep: 50 + NODE_SIZE[0],
ranksep: 50,
}, },
animation: false, animation: false,
node: { node: {
type: 'vue-node', type: 'vue-node',
style: { style: {
component: (data: any) => { component: (data: any) => {
return data.data.type !== VIRTUAL_NODE ? h(Node, { data: data }) : '' return h(Node, { data: data })
},
ports: [{ placement: 'top' }, { placement: 'bottom' }],
size: NODE_SIZE,
dx: -NODE_SIZE[0] / 2,
dy: -NODE_SIZE[1] / 2,
},
},
edge: {
type: 'my-line-edge',
style: {
radius: 10,
router: {
type: 'orth',
}, },
}, },
}, },
@ -57,37 +65,6 @@ onMounted(() => {
}); });
graph.render(); graph.render();
graph.on('afterlayout', async () => {
const nodes = graph.getNodeData();
const root = nodes.find(n => n.data?.type === DeviceType.Ems);
if (!root) return;
const emNodes = nodes.filter(n =>
n.data?.type === DeviceType.Em || n.data?.type === DeviceType['Em-Measure']
);
const [x, y] = graph.getElementPosition(root.id);
graph.updateNodeData(
emNodes.map((n, idx) => {
//
return {
id: n.id,
style: Object.assign(
{},
n.style,
{ // Em
x: x + NODE_SIZE[0] * 2,
y: -y - (emNodes.length * 10) + (idx * 60),
},
)
}
})
);
await graph.draw();
await graph.fitView();
});
}) })
; ;
</script> </script>

37
src/views/testG6/utils/GenerateGraphData.ts

@ -16,8 +16,6 @@ export default class GenerateGraphData {
private generateNodeData() { private generateNodeData() {
for (const device of this.devices) { for (const device of this.devices) {
const deviceChild = this.devices.filter((item: Device) => device.id === item.parentId)
const isNeedPoint = device.type === DeviceType.Ems || device.type === DeviceType['Em-Measure'] || device.type === DeviceType.Em
this.nodes.push({ this.nodes.push({
id: String(device.id), id: String(device.id),
label: device.name, label: device.name,
@ -26,49 +24,18 @@ export default class GenerateGraphData {
}), }),
style: Object.assign( style: Object.assign(
{ {
// labelText: device.name,
opacity: .3, opacity: .3,
icon: (d: any) => EmsIcon, icon: (d: any) => EmsIcon,
}) })
}) })
if (!!deviceChild.length) {
// 在每个有子节点的设备下插入一个虚拟节点
this.nodes.push({
id: `${device.id}-virtual`,
label: '',
type: '',
style: { opacity: 0 },
size: 0,
anchorPoints: [],
data: {
type: VIRTUAL_NODE,
parentId: String(device.id),
depth: device.depth + 1,
},
})
}
} }
} }
private generateEdgeData() { private generateEdgeData() {
for (const node of this.nodes) { for (const node of this.nodes) {
const customData: Device = node.data const customData: Device = node.data
const virtualId = `${customData.parentId}-virtual`;
const findParentNode: Device = this.nodes.some((n: MyNodeData) => n.id === String(customData.parentId)); const findParentNode: Device = this.nodes.some((n: MyNodeData) => n.id === String(customData.parentId));
if (this.isVirtualNode(customData.type)) {
this.edges.push({
source: customData.parentId,
target: String(node.id),
type: 'my-line-edge',
data: customData,
})
continue;
}
//
if (findParentNode) { if (findParentNode) {
if (this.isEms(customData.type)) continue; if (this.isEms(customData.type)) continue;
if (this.isEm(customData.type)) { if (this.isEm(customData.type)) {
@ -76,16 +43,14 @@ export default class GenerateGraphData {
this.edges.push({ this.edges.push({
target: String(customData.parentId), target: String(customData.parentId),
source: String(node.id), source: String(node.id),
type: 'em-line-edge',
data: customData, data: customData,
}) })
continue; continue;
} }
this.edges.push({ this.edges.push({
source: virtualId, source: String(customData.parentId),
target: String(node.id), target: String(node.id),
type: 'my-line-edge',
data: customData, data: customData,
}) })
} }

85
src/views/testG6/utils/MyLineEdge.ts

@ -1,12 +1,11 @@
import { BaseEdge } from '@antv/g6'; import { Polyline } from '@antv/g6';
import type { PathArray } from "@antv/util";
import { Circle } from '@antv/g'; import { Circle } from '@antv/g';
import { subStyleProps } from '@antv/g6'; import { subStyleProps } from '@antv/g6';
import { NODE_SIZE } from "./index"; import { NODE_SIZE } from "./index";
import type { Device } from "../type"; import type { Device } from "../type";
export class MyLineEdge extends BaseEdge { export class MyLineEdge extends Polyline {
getMarkerStyle(attributes: object) { getMarkerStyle(attributes: object) {
return { return {
@ -23,7 +22,7 @@ export class MyLineEdge extends BaseEdge {
.find((edge) => edge.target === this.targetNode.id) as Device; .find((edge) => edge.target === this.targetNode.id) as Device;
const depth = prev!.data!.depth - 1; const depth = prev!.data!.depth;
const delay = depth * 3000; // 每级延迟 3 秒 const delay = depth * 3000; // 每级延迟 3 秒
marker.animate( marker.animate(
[{ offsetDistance: 0 }, { offsetDistance: 1 }], [{ offsetDistance: 0 }, { offsetDistance: 1 }],
@ -65,82 +64,4 @@ export class MyLineEdge extends BaseEdge {
// iterations: Infinity, // iterations: Infinity,
// }); // });
} }
protected getKeyPath(attrs: any): PathArray {
const [sourcePoint, targetPoint] = this.getEndpoints(attrs, false)
const [sx, sy] = [sourcePoint[0], sourcePoint[1]];
const [tx, ty] = [targetPoint[0], targetPoint[1]];
// 固定的主干 X
const busX = attrs.busX ?? tx;
return [
['M', sx, sy],
['L', busX, sy],
['L', busX, ty],
['L', tx, ty],
];
}
}
export class EmLineEdge extends BaseEdge {
getMarkerStyle(attributes: object) {
return {
r: 4,
fill: '#58C448',
offsetPath: this.shapeMap.key, ...subStyleProps(attributes, 'marker')
};
}
onCreate() {
const marker = this.upsert('marker', Circle, this.getMarkerStyle(this.attributes), this)!;
const delay = 0;
marker.animate(
[{ offsetDistance: 0 }, { offsetDistance: 1 }],
{
duration: 3000,
iterations: Infinity,
delay,
}
);
// 涟漪效果:在 marker 外套一个圆
const ripple = this.upsert(
'ripple',
Circle,
{
r: 4, // 初始半径和 marker 一样
stroke: '#58C448',
lineWidth: 2,
fill: 'none',
offsetPath: this.shapeMap.key,
},
this
)!;
// 涟漪动画:半径变大 + 透明度变小
ripple.animate(
[
{ offsetDistance: 0, r: 4, opacity: 0.7 },
{ offsetDistance: 1, r: 6, opacity: 0 },
],
{
duration: 3000,
iterations: Infinity,
}
);
}
getKeyPath(attributes: any): PathArray {
const [sourcePoint, targetPoint] = this.getEndpoints(attributes, false);
return [
['M', sourcePoint[0], sourcePoint[1]],
['L', targetPoint[0] / 2 + (1 / 2) * sourcePoint[0], sourcePoint[1]],
['L', targetPoint[0] / 2 + (1 / 2) * sourcePoint[0], targetPoint[1]],
['L', targetPoint[0], targetPoint[1]],
];
}
} }

72
src/views/testG6/utils/MyNode.ts

@ -1,72 +0,0 @@
import { Graph, register, Rect, ExtensionCategory } from '@antv/g6';
import { DeviceType, NODE_SIZE } from "./index";
// const typeToIconMap = Object.entries(DeviceType).filter(([key, value]) => typeof value === 'number')
// console.log(typeToIconMap)
export default class UserCardNode extends Rect {
get nodeData() {
return this.context.graph.getNodeData(this.id);
}
get data() {
return this.nodeData.data || {};
}
// 用户名样式
drawNameShape(attributes: any, container: any) {
if (!this.data.name) return;
const getUsernameStyle = (attributes: any) => {
return {
x: -14,
text: this.data.name || '',
// fontSize: 12,
width: 20,
fill: '#262626',
fontWeight: 'bold',
textAlign: 'left',
textBaseline: 'middle',
maxWidth: 80, // 限制最大宽度
ellipsis: true, // 超出显示 ...
};
}
const usernameStyle = getUsernameStyle(attributes);
this.upsert('username', 'text', usernameStyle, container);
}
// 头像样式
getAvatarStyle(attributes: any) {
const [width, height] = this.getSize(attributes);
const type = this!.data!.type
return {
x: -width / 2 + 4,
y: -height / 2 + 6,
width: 24,
height: 24,
src: typeToIconMap[type as keyof typeof type] || '',
};
}
drawAvatarShape(attributes: any, container: any) {
if (!this.data.typeString) return;
const avatarStyle = this.getAvatarStyle(attributes);
this.upsert('avatar', 'image', avatarStyle, container);
}
render(attributes: any, container: any) {
// 渲染基础矩形
super.render(attributes, container);
this.drawAvatarShape(attributes, container);
this.drawNameShape(attributes, container);
}
}

52
src/views/testG6/utils/data.ts

@ -183,57 +183,5 @@ export default [{
} }
] ]
}, },
{
"id": 412,
"sn": "B48100B210TF36003E-em",
"name": "电量信息-1",
"sort": 1,
"parentId": 398,
"deviceId": "t00510412",
"dictName": "device_two_entity_type",
"level": 1,
"type": 4,
"description": "",
"children": null
},
{
"id": 413,
"sn": "B48100B210TF36003K-em",
"name": "电量信息-2",
"sort": 1,
"parentId": 398,
"deviceId": "t00510413",
"dictName": "device_two_entity_type",
"level": 1,
"type": 4,
"description": "",
"children": null
},
{
"id": 414,
"sn": "B48100B210TF36002V-em",
"name": "电量信息-3",
"sort": 1,
"parentId": 398,
"deviceId": "t00510414",
"dictName": "device_two_entity_type",
"level": 1,
"type": 4,
"description": "",
"children": null
},
{
"id": 415,
"sn": "B48100B210TF360029-em",
"name": "电量信息-4",
"sort": 1,
"parentId": 398,
"deviceId": "t00510415",
"dictName": "device_two_entity_type",
"level": 1,
"type": 4,
"description": "",
"children": null
}
] ]
}] }]

5
src/views/testG6/utils/index.ts

@ -22,11 +22,10 @@ export enum DeviceType {
export const VIRTUAL_NODE = 'virtual-node' export const VIRTUAL_NODE = 'virtual-node'
export function flattenTree(tree: Device[], depth = 1): Device[] { export function flattenTree(tree: Device[], depth = 0): Device[] {
return flatMap(tree, (node: Device,) => { return flatMap(tree, (node: Device,) => {
const { children, ...rest } = node const { children, ...rest } = node
const current = { ...rest, depth } const current = { ...rest, depth }
// 有用虚拟节点的存在 depth + 2 return [current, ...(children ? flattenTree(children, depth + 1) : [])]
return [current, ...(children ? flattenTree(children, depth + 2) : [])]
}) })
} }
Loading…
Cancel
Save