Commit fc25d5e8ba05b1e66ab36b6646d288732701239d
1 parent
1e80cb7f
fix(src/api/external): 修改设备分布新增设备最新属性表格
Showing
5 changed files
with
116 additions
and
37 deletions
@@ -16,7 +16,8 @@ enum Api { | @@ -16,7 +16,8 @@ enum Api { | ||
16 | VIDEOURL = '/video/url/', | 16 | VIDEOURL = '/video/url/', |
17 | GEOJSONURL = '/map/geo_json/', | 17 | GEOJSONURL = '/map/geo_json/', |
18 | DEVICE_URL = '/device', | 18 | DEVICE_URL = '/device', |
19 | - GET_ATTRBUTELIST = '/device/attributes/' | 19 | + GET_ATTRBUTELIST = '/device/attributes/', |
20 | + GET_DEVICE_LATEST = '/plugins/telemetry/DEVICE/' | ||
20 | } | 21 | } |
21 | 22 | ||
22 | export const getDictItemByCode = (value: string) => { | 23 | export const getDictItemByCode = (value: string) => { |
@@ -127,3 +128,11 @@ export const getAttribute = (deviceProfileId: string) => | @@ -127,3 +128,11 @@ export const getAttribute = (deviceProfileId: string) => | ||
127 | defHttp.get({ | 128 | defHttp.get({ |
128 | url: `${Api.GET_ATTRBUTELIST}${deviceProfileId}` | 129 | url: `${Api.GET_ATTRBUTELIST}${deviceProfileId}` |
129 | }) | 130 | }) |
131 | + | ||
132 | +// 获取设备最新数据 | ||
133 | +export const getDeviceLatest = (tbDeviceId: string) => | ||
134 | +defHttp.get({ | ||
135 | + url: `${Api.GET_DEVICE_LATEST}${tbDeviceId}/values/timeseries` | ||
136 | +}, { | ||
137 | + joinPrefix: false | ||
138 | +}) |
src/packages/components/external/Charts/Maps/OverrideMapAmap/components/DeviceLatestTable.vue
0 → 100644
1 | +<template> | ||
2 | + <n-drawer display-directive="if" v-model:show="modelShow" :width="502" :placement="placement"> | ||
3 | + <n-drawer-content title="设备最新属性数据" closable> | ||
4 | + <n-space vertical> | ||
5 | + <n-data-table size="small" :columns="dimensions" :data="source" :pagination="pagination" /> | ||
6 | + </n-space> | ||
7 | + </n-drawer-content> | ||
8 | + </n-drawer> | ||
9 | +</template> | ||
10 | + | ||
11 | +<script lang="ts" setup> | ||
12 | +import { ref } from 'vue' | ||
13 | +import { NDataTable,NDrawer, NDrawerContent, NSpace } from 'naive-ui' | ||
14 | +import { dimensions, pagination } from '../config' | ||
15 | +import type { sourceInterface } from '../config' | ||
16 | +import dayjs from 'dayjs' | ||
17 | + | ||
18 | +// defineProps({ | ||
19 | +// modelShow: Boolean | ||
20 | +// }) | ||
21 | + | ||
22 | +const placement = ref('right') | ||
23 | + | ||
24 | +const modelShow =ref(false) | ||
25 | + | ||
26 | +const source =ref<sourceInterface[]>([]) | ||
27 | + | ||
28 | +const setValue = (value: Recordable) => { | ||
29 | + if (!value) return | ||
30 | + source.value = Object.keys(value).map((item:string) => { | ||
31 | + return { | ||
32 | + key: item, | ||
33 | + value: value[item][0].value, | ||
34 | + lastUpdateTime: dayjs( value[item][0].ts).format('YYYY-MM-DD HH:mm:ss') | ||
35 | + } | ||
36 | + }) | ||
37 | +} | ||
38 | + | ||
39 | +const openDrawer = () => modelShow.value = true | ||
40 | + | ||
41 | +defineExpose({ | ||
42 | + setValue, | ||
43 | + openDrawer | ||
44 | +}) | ||
45 | +</script> | ||
46 | + | ||
47 | +<style lang="scss" scoped></style> |
@@ -36,6 +36,32 @@ export const filterDevice = (items: any) => { | @@ -36,6 +36,32 @@ export const filterDevice = (items: any) => { | ||
36 | } | 36 | } |
37 | } | 37 | } |
38 | 38 | ||
39 | +export const dimensions= [ | ||
40 | + { | ||
41 | + "title": "键", | ||
42 | + "key": "key" | ||
43 | + }, | ||
44 | + { | ||
45 | + "title": "值", | ||
46 | + "key": "value" | ||
47 | + }, | ||
48 | + { | ||
49 | + "title": "最后更新时间", | ||
50 | + "key": "lastUpdateTime" | ||
51 | + } | ||
52 | +] | ||
53 | + | ||
54 | +export interface sourceInterface { | ||
55 | + key: string | ||
56 | + value: string | ||
57 | + lastUpdateTime: string | ||
58 | +} | ||
59 | + | ||
60 | +export const pagination = { | ||
61 | + page: 1, | ||
62 | + pageSize: 10 | ||
63 | +} | ||
64 | + | ||
39 | export enum ThemeEnum { | 65 | export enum ThemeEnum { |
40 | NORMAL = 'normal', | 66 | NORMAL = 'normal', |
41 | DARK = 'dark', | 67 | DARK = 'dark', |
404 Bytes
1 | <template> | 1 | <template> |
2 | - <div @mouseenter="handleMouseenter" @mouseleave="handleMouseleave" class="chart-amap" ref="vChartRef"> | ||
3 | - <!-- <div v-show="showSearchBox" @click.stop="handleOpenSearchBox" class="search-box"></div> | ||
4 | - <search-box :modelShow="modelShow" @searchParams="handleSearchParams" @closeDrawer="handleCloseDrawer"></search-box> --> | 2 | + <div class="chart-amap" ref="vChartRef"> |
3 | + <device-latest-table ref="deviceLatestTableRef" :tbDeviceId="tbDeviceIdStr"></device-latest-table> | ||
5 | </div> | 4 | </div> |
6 | </template> | 5 | </template> |
7 | 6 | ||
8 | <script setup lang="ts"> | 7 | <script setup lang="ts"> |
9 | -import { ref, PropType, toRefs, watch, render, h } from 'vue' | 8 | +import { ref, PropType, toRefs, watch, render, h, onMounted, onUnmounted} from 'vue' |
10 | import AMapLoader from '@amap/amap-jsapi-loader' | 9 | import AMapLoader from '@amap/amap-jsapi-loader' |
11 | import { CreateComponentType } from '@/packages/index.d' | 10 | import { CreateComponentType } from '@/packages/index.d' |
12 | import { useChartDataFetch } from '@/hooks' | 11 | import { useChartDataFetch } from '@/hooks' |
@@ -17,9 +16,11 @@ import djh from './images/djh.png' | @@ -17,9 +16,11 @@ import djh from './images/djh.png' | ||
17 | import online from './images/online.png' | 16 | import online from './images/online.png' |
18 | import lx1 from './images/lx1.png' | 17 | import lx1 from './images/lx1.png' |
19 | import onLineImg from './images/marker/3.png' | 18 | import onLineImg from './images/marker/3.png' |
19 | +import listImg from './images/list.png' | ||
20 | import { getDeviceActiveTime } from '@/api/external/common/index' | 20 | import { getDeviceActiveTime } from '@/api/external/common/index' |
21 | import dayjs from 'dayjs' | 21 | import dayjs from 'dayjs' |
22 | -// import SearchBox from './components/SearchBox.vue' | 22 | +import DeviceLatestTable from './components/DeviceLatestTable.vue' |
23 | +import { getDeviceLatest } from '@/api/external/common' | ||
23 | 24 | ||
24 | const props = defineProps({ | 25 | const props = defineProps({ |
25 | chartConfig: { | 26 | chartConfig: { |
@@ -28,9 +29,7 @@ const props = defineProps({ | @@ -28,9 +29,7 @@ const props = defineProps({ | ||
28 | } | 29 | } |
29 | }) | 30 | }) |
30 | 31 | ||
31 | -// const modelShow = ref(false) | ||
32 | - | ||
33 | -const showSearchBox = ref(false) | 32 | +const deviceLatestTableRef = ref<Nullable<InstanceType<typeof DeviceLatestTable>>>(null); |
34 | 33 | ||
35 | const { | 34 | const { |
36 | amapKey, | 35 | amapKey, |
@@ -88,7 +87,7 @@ const initMap = (newData: any) => { | @@ -88,7 +87,7 @@ const initMap = (newData: any) => { | ||
88 | `amap://styles/${amapStyleKeyCustom.value !== '' ? amapStyleKeyCustom.value : amapStyleKey.value}` | 87 | `amap://styles/${amapStyleKeyCustom.value !== '' ? amapStyleKeyCustom.value : amapStyleKey.value}` |
89 | ) | 88 | ) |
90 | } | 89 | } |
91 | - mapIns.on('mouseout', () => { | 90 | + mapIns.on('click', () => { |
92 | mapIns.clearInfoWindow() | 91 | mapIns.clearInfoWindow() |
93 | }) | 92 | }) |
94 | }) | 93 | }) |
@@ -97,10 +96,14 @@ const initMap = (newData: any) => { | @@ -97,10 +96,14 @@ const initMap = (newData: any) => { | ||
97 | }) | 96 | }) |
98 | } | 97 | } |
99 | 98 | ||
99 | + | ||
100 | +const tbDeviceIdStr = ref('') | ||
101 | + | ||
100 | //创建信息弹窗 | 102 | //创建信息弹窗 |
101 | const createInfoWindow = async (extraInfo: dataExtraInfoType) => { | 103 | const createInfoWindow = async (extraInfo: dataExtraInfoType) => { |
102 | try { | 104 | try { |
103 | const { name, alias, organizationDTO, deviceState, deviceProfile, deviceInfo, tbDeviceId } = extraInfo | 105 | const { name, alias, organizationDTO, deviceState, deviceProfile, deviceInfo, tbDeviceId } = extraInfo |
106 | + tbDeviceIdStr.value = tbDeviceId | ||
104 | if (tbDeviceId.startsWith('@')) return //假的模拟数据则终止 | 107 | if (tbDeviceId.startsWith('@')) return //假的模拟数据则终止 |
105 | const res = await getDeviceActiveTime(tbDeviceId) //查询设备最后离线时间 | 108 | const res = await getDeviceActiveTime(tbDeviceId) //查询设备最后离线时间 |
106 | let { lastUpdateTs } = res[0] | 109 | let { lastUpdateTs } = res[0] |
@@ -142,7 +145,10 @@ const createInfoWindow = async (extraInfo: dataExtraInfoType) => { | @@ -142,7 +145,10 @@ const createInfoWindow = async (extraInfo: dataExtraInfoType) => { | ||
142 | </div>` | 145 | </div>` |
143 | } | 146 | } |
144 | </div> | 147 | </div> |
145 | - <div style="display:flex;flex-direction:column;justify-content:space-between;color:white;margin-top:2rem;gap:0.8rem;"> | 148 | + <div style="display:flex;justify-content:flex-end;cursor:pointer;" onclick="handleOpenDrawer()"> |
149 | + <img style="${deviceStateImg};position:relative;top:0.7rem" src="${listImg}"/> | ||
150 | + </div> | ||
151 | + <div style="display:flex;flex-direction:column;justify-content:space-between;color:white;margin-top:1rem;gap:0.8rem;"> | ||
146 | <div style="${textOverflow}">所属组织:${organizationDTO.name}</div> | 152 | <div style="${textOverflow}">所属组织:${organizationDTO.name}</div> |
147 | <div style="${textOverflow}">接入协议:${deviceProfile.transportType}</div> | 153 | <div style="${textOverflow}">接入协议:${deviceProfile.transportType}</div> |
148 | <div style="${textOverflow}">设备位置:${!deviceInfo.address ? '该设备暂无地理位置' : deviceInfo.address}</div> | 154 | <div style="${textOverflow}">设备位置:${!deviceInfo.address ? '该设备暂无地理位置' : deviceInfo.address}</div> |
@@ -156,37 +162,28 @@ const createInfoWindow = async (extraInfo: dataExtraInfoType) => { | @@ -156,37 +162,28 @@ const createInfoWindow = async (extraInfo: dataExtraInfoType) => { | ||
156 | } | 162 | } |
157 | } | 163 | } |
158 | 164 | ||
159 | -const handleMouseenter = () => (showSearchBox.value = true) | ||
160 | - | ||
161 | -const handleMouseleave = () => (showSearchBox.value = false) | ||
162 | - | ||
163 | -// const handleOpenSearchBox = () => (modelShow.value = true) | 165 | +const handleOpenDrawer = async () => { |
166 | + deviceLatestTableRef.value?.openDrawer() | ||
167 | + if (!tbDeviceIdStr.value) return | ||
168 | + const resp = await getDeviceLatest(tbDeviceIdStr.value) | ||
169 | + deviceLatestTableRef.value?.setValue(resp) | ||
170 | +} | ||
164 | 171 | ||
165 | -// const handleCloseDrawer = () => (modelShow.value = false) | 172 | +onMounted(() => { |
173 | + (window as any).handleOpenDrawer = handleOpenDrawer; | ||
174 | +}); | ||
166 | 175 | ||
167 | -// const handleSearchParams = async (searchPage: any, params: any) => { | ||
168 | -// try { | ||
169 | -// Object.keys(params).forEach(item => { | ||
170 | -// if (!params[item]) Reflect.deleteProperty(params, item) | ||
171 | -// }) | ||
172 | -// const { items } = await getDeviceList(searchPage, params) | ||
173 | -// const values = filterDevice(items) | ||
174 | -// if (!values) return | ||
175 | -// setTimeout(() => { | ||
176 | -// dataHandle(values) | ||
177 | -// }, 1000) | ||
178 | -// } finally { | ||
179 | -// handleCloseDrawer() | ||
180 | -// } | ||
181 | -// } | 176 | +onUnmounted(() => { |
177 | + (window as any).handleOpenDrawer = null; | ||
178 | +}); | ||
182 | 179 | ||
183 | //地图鼠标hover | 180 | //地图鼠标hover |
184 | const mapClick = (markerInstance: any, markerItem: dataJsonMarkersType) => { | 181 | const mapClick = (markerInstance: any, markerItem: dataJsonMarkersType) => { |
185 | markerInstance.setExtData({ | 182 | markerInstance.setExtData({ |
186 | extraInfo: markerItem.extraInfo | 183 | extraInfo: markerItem.extraInfo |
187 | }) | 184 | }) |
188 | - // click | ||
189 | - markerInstance.on('mouseover', async (e: any) => { | 185 | + // mouseover |
186 | + markerInstance.on('click', async (e: any) => { | ||
190 | const { extraInfo } = e.target.getExtData() | 187 | const { extraInfo } = e.target.getExtData() |
191 | if (extraInfo.tbDeviceId.startsWith('@')) return //假的模拟数据则终止弹窗 | 188 | if (extraInfo.tbDeviceId.startsWith('@')) return //假的模拟数据则终止弹窗 |
192 | let infoWindow = new AMapIns.InfoWindow({ | 189 | let infoWindow = new AMapIns.InfoWindow({ |
@@ -195,9 +192,9 @@ const mapClick = (markerInstance: any, markerItem: dataJsonMarkersType) => { | @@ -195,9 +192,9 @@ const mapClick = (markerInstance: any, markerItem: dataJsonMarkersType) => { | ||
195 | }) | 192 | }) |
196 | infoWindow.open(mapIns, e.target.getPosition()) | 193 | infoWindow.open(mapIns, e.target.getPosition()) |
197 | }) | 194 | }) |
198 | - markerInstance.on('mouseout', () => { | ||
199 | - mapIns.clearInfoWindow() | ||
200 | - }) | 195 | + // markerInstance.on('click', () => { |
196 | + // mapIns.clearInfoWindow() | ||
197 | + // }) | ||
201 | } | 198 | } |
202 | 199 | ||
203 | const dataHandle = (newData: dataJsonType) => { | 200 | const dataHandle = (newData: dataJsonType) => { |