|
|
@@ -2,68 +2,77 @@
|
|
|
<a-card>
|
|
|
<a-row>
|
|
|
<a-col>
|
|
|
- <a-select
|
|
|
- placeholder="请选择产品"
|
|
|
- v-model:value="state.modelId"
|
|
|
- >
|
|
|
- <a-select-option
|
|
|
- v-for="model in state.modelList"
|
|
|
- :key="model.id"
|
|
|
- :value="model.id"
|
|
|
+ <a-space>
|
|
|
+ <a-select
|
|
|
+ placeholder="请选择产品"
|
|
|
+ v-model:value="state.modelId"
|
|
|
+ style="width: 170px"
|
|
|
>
|
|
|
- {{model.modelLabel}}
|
|
|
- </a-select-option>
|
|
|
- </a-select>
|
|
|
- <a-button @click="exportDomToImage" >导出</a-button>
|
|
|
+ <a-select-option
|
|
|
+ v-for="model in state.modelList"
|
|
|
+ :key="model.id"
|
|
|
+ :value="model.id"
|
|
|
+ >
|
|
|
+ {{model.modelLabel}}
|
|
|
+ </a-select-option>
|
|
|
+ </a-select>
|
|
|
+ <a-button @click="exportDomToImage" >导出</a-button>
|
|
|
+ </a-space>
|
|
|
</a-col>
|
|
|
</a-row>
|
|
|
|
|
|
- <div class="topology-preview" >
|
|
|
- <a-row class="zoom-navbar" >
|
|
|
- <a-col>
|
|
|
- <a-tooltip>
|
|
|
- <template #title>放大</template>
|
|
|
- <zoom-in-outlined :style="{fontSize: '34px'}" />
|
|
|
- </a-tooltip>
|
|
|
- <a-tooltip>
|
|
|
- <template #title>缩小</template>
|
|
|
- <zoom-out-outlined :style="{fontSize: '34px'}" />
|
|
|
- </a-tooltip>
|
|
|
- </a-col>
|
|
|
- </a-row>
|
|
|
- <vue-tree
|
|
|
- style="width: 1000px; height: 600px; border: 1px solid gray;"
|
|
|
- :dataset="treeData.richMediaData"
|
|
|
- :config="treeData.treeConfig"
|
|
|
- id="vueTreeRef"
|
|
|
- ref="vueTreeRef"
|
|
|
- >
|
|
|
- <template v-slot:node="{ node, collapsed }">
|
|
|
- <a-row
|
|
|
- class="rich-media-node"
|
|
|
- >
|
|
|
- <a-col :span="24" >
|
|
|
- <a-space>
|
|
|
- 📦
|
|
|
- <div>
|
|
|
- {{node.value}}
|
|
|
- {{node.modelLabel}}
|
|
|
- {{node.deviceLabel}}
|
|
|
+ <a-spin style="width: 1000px;" :spinning="state.loading" >
|
|
|
+ <div class="topology-preview" >
|
|
|
+ <a-row class="zoom-navbar" justify="center" >
|
|
|
+ <a-col >
|
|
|
+ <a-space>
|
|
|
+ <a-tooltip>
|
|
|
+ <template #title>放大</template>
|
|
|
+ <zoom-in-outlined @click="zoomIn" :style="{fontSize: '20px', cursor: 'pointer'}" />
|
|
|
+ </a-tooltip>
|
|
|
+ <span>{{zoomCount}}%</span>
|
|
|
+ <a-tooltip>
|
|
|
+ <template #title>缩小</template>
|
|
|
+ <zoom-out-outlined @click="zoomOut" :style="{fontSize: '20px', cursor: 'pointer'}" />
|
|
|
+ </a-tooltip>
|
|
|
+ <a-button @click="resetZoom" >重置</a-button>
|
|
|
+ </a-space>
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+ <vue-tree
|
|
|
+ style="width: 1000px; height: 600px; border: 1px solid gray;"
|
|
|
+ :dataset="treeData.richMediaData"
|
|
|
+ :config="treeData.treeConfig"
|
|
|
+ id="vueTreeRef"
|
|
|
+ ref="vueTreeRef"
|
|
|
+ >
|
|
|
+ <template v-slot:node="{ node, collapsed }">
|
|
|
+ <a-row
|
|
|
+ class="rich-media-node"
|
|
|
+ >
|
|
|
+ <a-col :span="24" >
|
|
|
+ <a-space>
|
|
|
+ 📦
|
|
|
+ <div>
|
|
|
+ {{node.value}}
|
|
|
+ {{node.modelLabel}}
|
|
|
+ {{node.deviceLabel}}
|
|
|
+ </div>
|
|
|
+ </a-space>
|
|
|
+ </a-col>
|
|
|
+ <a-col>
|
|
|
+ <div>
|
|
|
+ {{node.transportType}}
|
|
|
+ {{node.payloadType}}
|
|
|
</div>
|
|
|
- </a-space>
|
|
|
- </a-col>
|
|
|
- <a-col>
|
|
|
- <div>
|
|
|
- {{node.transportType}}
|
|
|
- {{node.payloadType}}
|
|
|
- </div>
|
|
|
-
|
|
|
- </a-col>
|
|
|
- <!-- {{node.deviceLabel}} -->
|
|
|
- </a-row>
|
|
|
- </template>
|
|
|
- </vue-tree>
|
|
|
- </div>
|
|
|
+
|
|
|
+ </a-col>
|
|
|
+ <!-- {{node.deviceLabel}} -->
|
|
|
+ </a-row>
|
|
|
+ </template>
|
|
|
+ </vue-tree>
|
|
|
+ </div>
|
|
|
+ </a-spin>
|
|
|
|
|
|
</a-card>
|
|
|
</template>
|
|
|
@@ -83,9 +92,11 @@ const state = reactive<{
|
|
|
gatewayDevice: any[]
|
|
|
model: IOT.API.MODEL.Model[]
|
|
|
subDevice: IOT.API.DEVICE.Device[]
|
|
|
- }
|
|
|
+ },
|
|
|
+ loading: false
|
|
|
}>({
|
|
|
modelId: '',
|
|
|
+ loading: false,
|
|
|
modelList: [],
|
|
|
dataSource: {
|
|
|
gatewayDevice: [],
|
|
|
@@ -96,18 +107,34 @@ const state = reactive<{
|
|
|
|
|
|
const vueTreeRef = ref('')
|
|
|
|
|
|
+const zoomCount = ref(100)
|
|
|
+
|
|
|
const treeData = reactive({
|
|
|
richMediaData: {},
|
|
|
treeConfig: { nodeWidth: 120, nodeHeight: 80, levelHeight: 200 }
|
|
|
}
|
|
|
)
|
|
|
|
|
|
+const zoomIn = () => {
|
|
|
+ zoomCount.value += 10
|
|
|
+ vueTreeRef.value.zoomIn()
|
|
|
+}
|
|
|
+
|
|
|
+const zoomOut = () => {
|
|
|
+ zoomCount.value -= 10
|
|
|
+ vueTreeRef.value.zoomOut()
|
|
|
+}
|
|
|
+
|
|
|
+const resetZoom = () => {
|
|
|
+ zoomCount.value = 100
|
|
|
+}
|
|
|
+
|
|
|
window.addEventListener('wheel', function (event) {
|
|
|
console.log(event.deltaY)
|
|
|
if (event.deltaY > 0) {
|
|
|
- vueTreeRef.value.zoomOut()
|
|
|
+ zoomOut()
|
|
|
} else {
|
|
|
- vueTreeRef.value.zoomIn()
|
|
|
+ zoomIn()
|
|
|
}
|
|
|
})
|
|
|
|
|
|
@@ -127,6 +154,7 @@ function exportDomToImage () {
|
|
|
}
|
|
|
|
|
|
const getDeviceTopology = async () => {
|
|
|
+ state.loading = true
|
|
|
const { data } = await DeviceContriller.getDeviceTopology(state.modelId)
|
|
|
const { gatewayDevice, model, subDevice } = data
|
|
|
|
|
|
@@ -152,6 +180,7 @@ const getDeviceTopology = async () => {
|
|
|
})
|
|
|
|
|
|
treeData.richMediaData = obj
|
|
|
+ state.loading = false
|
|
|
console.log('obj:', obj)
|
|
|
}
|
|
|
|
|
|
@@ -185,12 +214,26 @@ onMounted(() => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+#vueTreeRef {
|
|
|
+ position: relative;
|
|
|
+ z-index: 1;
|
|
|
+}
|
|
|
+
|
|
|
.topology-preview {
|
|
|
position: relative;
|
|
|
+ width: 1000px;
|
|
|
+ margin-top: 20px;
|
|
|
.zoom-navbar {
|
|
|
position: absolute;
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 50px;
|
|
|
+ background-color: #f6f6f6;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ z-index: 2;
|
|
|
}
|
|
|
}
|
|
|
|