Commit fce71e9f4b5893f32cae23da8e30160bb54c6399

Authored by fengtao
1 parent fc25d5e8

feat(src/packages): 设备分布新增点击弹出抽屉展示设备最新属性数据值

... ... @@ -17,7 +17,8 @@ enum Api {
17 17 GEOJSONURL = '/map/geo_json/',
18 18 DEVICE_URL = '/device',
19 19 GET_ATTRBUTELIST = '/device/attributes/',
20   - GET_DEVICE_LATEST = '/plugins/telemetry/DEVICE/'
  20 + GET_DEVICE_LATEST = '/plugins/telemetry/DEVICE/',
  21 + DEVICE_ATTR = '/device/attributes',
21 22 }
22 23
23 24 export const getDictItemByCode = (value: string) => {
... ... @@ -135,4 +136,13 @@ defHttp.get({
135 136 url: `${Api.GET_DEVICE_LATEST}${tbDeviceId}/values/timeseries`
136 137 }, {
137 138 joinPrefix: false
138   -})
\ No newline at end of file
  139 +})
  140 +
  141 +//获取产品属性
  142 +export const getProfileAttrs = (params: { deviceProfileId: string; dataType?: string }) => {
  143 + const { deviceProfileId, dataType } = params;
  144 + return defHttp.get({
  145 + url: `${Api.DEVICE_ATTR}/${deviceProfileId}`,
  146 + params: { dataType },
  147 + });
  148 +};
\ No newline at end of file
... ...
src/assets/external/marker/1.png renamed from src/packages/components/external/Charts/Maps/OverrideMapAmap/images/marker/1.png

1.24 KB

src/assets/external/marker/2.png renamed from src/packages/components/external/Charts/Maps/OverrideMapAmap/images/marker/2.png

1.4 KB

src/assets/external/marker/3.png renamed from src/packages/components/external/Charts/Maps/OverrideMapAmap/images/marker/3.png

904 Bytes

src/assets/external/marker/4.png renamed from src/packages/components/external/Charts/Maps/OverrideMapAmap/images/marker/4.png

1.02 KB

src/assets/external/marker/5.png renamed from src/packages/components/external/Charts/Maps/OverrideMapAmap/images/marker/5.png

970 Bytes

1 1 <template>
2 2 <n-drawer display-directive="if" v-model:show="modelShow" :width="502" :placement="placement">
3   - <n-drawer-content title="设备最新属性数据" closable>
  3 + <n-drawer-content :title="drawerTitle" closable>
4 4 <n-space vertical>
5   - <n-data-table size="small" :columns="dimensions" :data="source" :pagination="pagination" />
  5 + <n-data-table size="small" :columns="dimensions" :data="source" :pagination="paginationReactive" />
6 6 </n-space>
7 7 </n-drawer-content>
8 8 </n-drawer>
9 9 </template>
10 10
11 11 <script lang="ts" setup>
12   -import { ref } from 'vue'
  12 +import { ref, reactive } from 'vue'
13 13 import { NDataTable,NDrawer, NDrawerContent, NSpace } from 'naive-ui'
14   -import { dimensions, pagination } from '../config'
  14 +import { dimensions } from '../config'
15 15 import type { sourceInterface } from '../config'
16 16 import dayjs from 'dayjs'
  17 +import { Placement } from 'naive-ui/es/drawer/src/DrawerBodyWrapper'
17 18
18   -// defineProps({
19   -// modelShow: Boolean
20   -// })
21   -
22   -const placement = ref('right')
  19 +const placement = ref<Placement>('right')
23 20
24 21 const modelShow =ref(false)
25 22
  23 +const drawerTitle = ref('')
  24 +
26 25 const source =ref<sourceInterface[]>([])
27 26
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   - })
  27 +const paginationReactive = reactive({
  28 + page: 1,
  29 + pageSize: 10,
  30 + showSizePicker: true,
  31 + pageSizes: [10, 20],
  32 + onChange: (page: number) => {
  33 + paginationReactive.page = page
  34 + },
  35 + onUpdatePageSize: (pageSize: number) => {
  36 + paginationReactive.pageSize = pageSize
  37 + paginationReactive.page = 1
  38 + }
  39 + })
  40 +
  41 +const setValue = (value: Recordable, attrs: Recordable[]) => {
  42 + source.value = []
  43 + try {
  44 + if (!value) return
  45 + const deviceLatestList = Object.keys(value).map((item:string) => {
  46 + return {
  47 + key: item,
  48 + value: value[item][0]?.value,
  49 + lastUpdateTime: dayjs( value[item][0]?.ts)?.format('YYYY-MM-DD HH:mm:ss')
  50 + }
  51 + })
  52 + const list = deviceLatestList?.reduce((acc:sourceInterface[],curr: sourceInterface)=>{
  53 + const byKeyFindName = attrs?.find(item => item.identifier === curr.key)?.name
  54 + curr.key = byKeyFindName
  55 + acc.push({...curr})
  56 + return [...acc]
  57 + },[])
  58 + source.value = list.filter(item=>Boolean(item.key))
  59 + }catch(e){
  60 + console.log(e)
  61 + }
37 62 }
38 63
  64 +const setDrawerTitle = (title:string) => drawerTitle.value = title
  65 +
39 66 const openDrawer = () => modelShow.value = true
40 67
41 68 defineExpose({
42 69 setValue,
43   - openDrawer
  70 + openDrawer,
  71 + setDrawerTitle
44 72 })
45 73 </script>
46 74
... ...
... ... @@ -4,7 +4,7 @@ import { OverrideMapAmapConfig } from './index'
4 4 import { chartInitConfig } from '@/settings/designSetting'
5 5 import cloneDeep from 'lodash/cloneDeep'
6 6 import dataJson from './data.json'
7   -import defaultImg from './images/marker/1.png'
  7 +import defaultImg from '../../../../../../assets/external/marker/1.png'
8 8
9 9 export type dataExtraInfoType = typeof dataJson.markers[number]['extraInfo'] //data.json下的extraInfo类型
10 10
... ... @@ -26,6 +26,7 @@ export const filterDevice = (items: any) => {
26 26 organizationDTO: curr.organizationDTO,
27 27 deviceState: curr.deviceState,
28 28 deviceProfile: curr.deviceProfile,
  29 + deviceProfileId: curr.deviceProfileId,
29 30 deviceInfo: curr.deviceInfo
30 31 }
31 32 })
... ... @@ -36,6 +37,13 @@ export const filterDevice = (items: any) => {
36 37 }
37 38 }
38 39
  40 +export interface devicePartInfoInterface{
  41 + tbDeviceId:string
  42 + name:string
  43 + alias:string
  44 + deviceProfileId:string
  45 +}
  46 +
39 47 export const dimensions= [
40 48 {
41 49 "title": "键",
... ... @@ -57,11 +65,6 @@ export interface sourceInterface {
57 65 lastUpdateTime: string
58 66 }
59 67
60   -export const pagination = {
61   - page: 1,
62   - pageSize: 10
63   -}
64   -
65 68 export enum ThemeEnum {
66 69 NORMAL = 'normal',
67 70 DARK = 'dark',
... ...
... ... @@ -254,7 +254,7 @@ const isHref = (url: string) => {
254 254
255 255 // import.meta.glob 这个不能封装,必须是字符串,不能通过传值传进去
256 256 const iconMarkerOptions = computed(() => {
257   - const pathList = import.meta.glob('./images/marker/*')
  257 + const pathList = import.meta.glob('../../../../../../assets/external/marker/*')
258 258 return Object.keys(pathList).map(item => {
259 259 const imgName = item.split('/').at(-1)
260 260 return {
... ... @@ -266,7 +266,7 @@ const iconMarkerOptions = computed(() => {
266 266 //
267 267
268 268 const getMarkerImagePath = (name: string) => {
269   - return isHref(name) ? name : new URL(`./images/marker/${name}`, import.meta.url).href
  269 + return isHref(name) ? name : new URL(`../../../../../../assets/external/marker/${name}`, import.meta.url).href
270 270 }
271 271
272 272 const renderOption = (option: SelectOption) => {
... ... @@ -334,6 +334,7 @@ const selectMapBorderHandle = (value: string) => {
334 334 onMounted(() => {
335 335 iconMarkerValue.value = props.optionData.mapOptions.iconMarker?.split('/')?.at(-1) as string
336 336 props.optionData.mapOptions.iconMarker = getMarkerImagePath(iconMarkerValue.value)
  337 + console.log(getMarkerImagePath(iconMarkerValue.value));
337 338 mapSelectBorderValue.value = `${props.optionData.mapOptions.mpBorderConfig.value?.toLocaleLowerCase()}.png`
338 339 })
339 340 </script>
... ...
... ... @@ -15,6 +15,7 @@
15 15 "deviceProfile": {
16 16 "transportType": "MQTT"
17 17 },
  18 + "deviceProfileId":"",
18 19 "deviceInfo": {
19 20 "address": "四川省",
20 21 "longitude": 103.856504,
... ... @@ -37,6 +38,7 @@
37 38 "deviceProfile": {
38 39 "transportType": "TCP"
39 40 },
  41 + "deviceProfileId":"",
40 42 "deviceInfo": {
41 43 "address": "四川省",
42 44 "longitude": 104.095368,
... ...
1 1 <template>
2 2 <div class="chart-amap" ref="vChartRef">
3   - <device-latest-table ref="deviceLatestTableRef" :tbDeviceId="tbDeviceIdStr"></device-latest-table>
  3 + <device-latest-table ref="deviceLatestTableRef"></device-latest-table>
4 4 </div>
5 5 </template>
6 6
7 7 <script setup lang="ts">
8   -import { ref, PropType, toRefs, watch, render, h, onMounted, onUnmounted} from 'vue'
  8 +import { ref, PropType, toRefs, watch, render, h, onMounted, onUnmounted, reactive} from 'vue'
9 9 import AMapLoader from '@amap/amap-jsapi-loader'
10 10 import { CreateComponentType } from '@/packages/index.d'
11 11 import { useChartDataFetch } from '@/hooks'
12 12 import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
13   -import { MarkerEnum, ThemeEnum, dataExtraInfoType, dataJsonType, dataJsonMarkersType } from './config'
  13 +import { MarkerEnum, ThemeEnum, dataExtraInfoType, dataJsonType, dataJsonMarkersType, devicePartInfoInterface } from './config'
14 14 import { isArray } from '@/utils'
15 15 import djh from './images/djh.png'
16 16 import online from './images/online.png'
17 17 import lx1 from './images/lx1.png'
18   -import onLineImg from './images/marker/3.png'
  18 +import onLineImg from '../../../../../../assets/external/marker/3.png'
19 19 import listImg from './images/list.png'
20 20 import { getDeviceActiveTime } from '@/api/external/common/index'
21 21 import dayjs from 'dayjs'
22 22 import DeviceLatestTable from './components/DeviceLatestTable.vue'
23   -import { getDeviceLatest } from '@/api/external/common'
  23 +import { getDeviceLatest, getProfileAttrs } from '@/api/external/common'
24 24
25 25 const props = defineProps({
26 26 chartConfig: {
... ... @@ -97,13 +97,22 @@ const initMap = (newData: any) => {
97 97 }
98 98
99 99
100   -const tbDeviceIdStr = ref('')
  100 +//携带设备的tbDeviceId和别名或者名称
  101 +const devicePartInfo = reactive<devicePartInfoInterface>({
  102 + tbDeviceId:'',
  103 + name:'',
  104 + alias:'',
  105 + deviceProfileId:'',
  106 +})
101 107
102 108 //创建信息弹窗
103 109 const createInfoWindow = async (extraInfo: dataExtraInfoType) => {
104 110 try {
105   - const { name, alias, organizationDTO, deviceState, deviceProfile, deviceInfo, tbDeviceId } = extraInfo
106   - tbDeviceIdStr.value = tbDeviceId
  111 + const { name, alias, organizationDTO, deviceState, deviceProfile, deviceInfo, tbDeviceId, deviceProfileId } = extraInfo
  112 + devicePartInfo.tbDeviceId = tbDeviceId
  113 + devicePartInfo.alias = alias
  114 + devicePartInfo.name = name
  115 + devicePartInfo.deviceProfileId = deviceProfileId
107 116 if (tbDeviceId.startsWith('@')) return //假的模拟数据则终止
108 117 const res = await getDeviceActiveTime(tbDeviceId) //查询设备最后离线时间
109 118 let { lastUpdateTs } = res[0]
... ... @@ -164,9 +173,11 @@ const createInfoWindow = async (extraInfo: dataExtraInfoType) => {
164 173
165 174 const handleOpenDrawer = async () => {
166 175 deviceLatestTableRef.value?.openDrawer()
167   - if (!tbDeviceIdStr.value) return
168   - const resp = await getDeviceLatest(tbDeviceIdStr.value)
169   - deviceLatestTableRef.value?.setValue(resp)
  176 + deviceLatestTableRef.value?.setDrawerTitle(devicePartInfo.alias || devicePartInfo.name)
  177 + if (!devicePartInfo.tbDeviceId) return
  178 + const resp = await getDeviceLatest(devicePartInfo.tbDeviceId)
  179 + const respGetAttrs = await getProfileAttrs({deviceProfileId: devicePartInfo.deviceProfileId})
  180 + deviceLatestTableRef.value?.setValue(resp,respGetAttrs)
170 181 }
171 182
172 183 onMounted(() => {
... ...