Commit edef147b3f2154a933ee65078f680ab988d455a1
Merge branch 'sqy_dev' into 'main'
feat:地理位置完成,首页条件判断完成,接口待调试,设备修改字段。 See merge request huang/yun-teng-iot-front!64
Showing
17 changed files
with
389 additions
and
216 deletions
@@ -30,3 +30,14 @@ export const getDeviceDataKeys = (id: string) => { | @@ -30,3 +30,14 @@ export const getDeviceDataKeys = (id: string) => { | ||
30 | } | 30 | } |
31 | ); | 31 | ); |
32 | }; | 32 | }; |
33 | +// 获取设备状态,在线 or 离线时间 | ||
34 | +export const getDeviceActiveTime = (entityId: string) => { | ||
35 | + return defHttp.get( | ||
36 | + { | ||
37 | + url: `/plugins/telemetry/DEVICE/${entityId}/values/attributes?keys=active`, | ||
38 | + }, | ||
39 | + { | ||
40 | + joinPrefix: false, | ||
41 | + } | ||
42 | + ); | ||
43 | +}; |
src/api/dashboard/index.ts
0 → 100644
src/assets/images/kf.png
0 → 100644
1.1 KB
src/assets/images/zh.png
0 → 100644
1.45 KB
1 | export enum RoleEnum { | 1 | export enum RoleEnum { |
2 | ROLE_SYS_ADMIN = 'SYS_ADMIN', | 2 | ROLE_SYS_ADMIN = 'SYS_ADMIN', |
3 | ROLE_TENANT_ADMIN = 'TENANT_ADMIN', | 3 | ROLE_TENANT_ADMIN = 'TENANT_ADMIN', |
4 | - ROLE_NORMAL_USER = 'CUSTOMER_USER', | ||
5 | ROLE_PLATFORM_ADMIN = 'PLATFORM_ADMIN', | 4 | ROLE_PLATFORM_ADMIN = 'PLATFORM_ADMIN', |
5 | + ROLE_NORMAL_USER = 'CUSTOMER_USER', | ||
6 | } | 6 | } |
@@ -51,7 +51,6 @@ | @@ -51,7 +51,6 @@ | ||
51 | severity: alarmLevel(data.severity), | 51 | severity: alarmLevel(data.severity), |
52 | status: statusType(data.status), | 52 | status: statusType(data.status), |
53 | }); | 53 | }); |
54 | - console.log(data.status); | ||
55 | alarmStatus.value = data.status; | 54 | alarmStatus.value = data.status; |
56 | alarmId.value = data.id; | 55 | alarmId.value = data.id; |
57 | }); | 56 | }); |
@@ -34,8 +34,16 @@ | @@ -34,8 +34,16 @@ | ||
34 | :canFullscreen="false" | 34 | :canFullscreen="false" |
35 | > | 35 | > |
36 | <BasicForm @register="registerForm" /> | 36 | <BasicForm @register="registerForm" /> |
37 | - <div ref="chartRef" :style="{ height: '600px', width }"></div> | 37 | + <Alert |
38 | + v-if="!isNull" | ||
39 | + message="当前时间节点暂无历史数据" | ||
40 | + description="请尝试选择其他时间段查询历史数据" | ||
41 | + type="warning" | ||
42 | + show-icon | ||
43 | + /> | ||
44 | + <div v-show="isNull" ref="chartRef" :style="{ height: '600px', width }"></div> | ||
38 | </BasicModal> | 45 | </BasicModal> |
46 | + <DeviceDetailDrawer @register="registerDetailDrawer" /> | ||
39 | </div> | 47 | </div> |
40 | </template> | 48 | </template> |
41 | <script lang="ts"> | 49 | <script lang="ts"> |
@@ -44,22 +52,30 @@ | @@ -44,22 +52,30 @@ | ||
44 | import { formSchema, columns } from './config.data'; | 52 | import { formSchema, columns } from './config.data'; |
45 | import { BasicTable, useTable } from '/@/components/Table'; | 53 | import { BasicTable, useTable } from '/@/components/Table'; |
46 | import { devicePage } from '/@/api/alarm/contact/alarmContact'; | 54 | import { devicePage } from '/@/api/alarm/contact/alarmContact'; |
47 | - import { Tag } from 'ant-design-vue'; | 55 | + import { Tag, Alert } from 'ant-design-vue'; |
48 | import { DeviceState } from '/@/api/device/model/deviceModel'; | 56 | import { DeviceState } from '/@/api/device/model/deviceModel'; |
49 | import { BAI_DU_MAP_URL } from '/@/utils/fnUtils'; | 57 | import { BAI_DU_MAP_URL } from '/@/utils/fnUtils'; |
50 | import { useModal, BasicModal } from '/@/components/Modal'; | 58 | import { useModal, BasicModal } from '/@/components/Modal'; |
51 | import { BasicForm, useForm } from '/@/components/Form'; | 59 | import { BasicForm, useForm } from '/@/components/Form'; |
52 | import { schemas } from './config.data'; | 60 | import { schemas } from './config.data'; |
53 | import { useECharts } from '/@/hooks/web/useECharts'; | 61 | import { useECharts } from '/@/hooks/web/useECharts'; |
54 | - import { getDeviceHistoryInfo, getDeviceDataKeys } from '/@/api/alarm/position'; | 62 | + import { |
63 | + getDeviceHistoryInfo, | ||
64 | + getDeviceDataKeys, | ||
65 | + getDeviceActiveTime, | ||
66 | + } from '/@/api/alarm/position'; | ||
67 | + import { useDrawer } from '/@/components/Drawer'; | ||
68 | + import DeviceDetailDrawer from '/@/views/device/manage/cpns/modal/DeviceDetailDrawer.vue'; | ||
55 | import moment from 'moment'; | 69 | import moment from 'moment'; |
56 | export default defineComponent({ | 70 | export default defineComponent({ |
57 | name: 'BaiduMap', | 71 | name: 'BaiduMap', |
58 | components: { | 72 | components: { |
59 | BasicTable, | 73 | BasicTable, |
60 | Tag, | 74 | Tag, |
75 | + Alert, | ||
61 | BasicModal, | 76 | BasicModal, |
62 | BasicForm, | 77 | BasicForm, |
78 | + DeviceDetailDrawer, | ||
63 | }, | 79 | }, |
64 | props: { | 80 | props: { |
65 | width: { | 81 | width: { |
@@ -74,7 +90,10 @@ | @@ -74,7 +90,10 @@ | ||
74 | setup() { | 90 | setup() { |
75 | const wrapRef = ref<HTMLDivElement | null>(null); | 91 | const wrapRef = ref<HTMLDivElement | null>(null); |
76 | const { toPromise } = useScript({ src: BAI_DU_MAP_URL }); | 92 | const { toPromise } = useScript({ src: BAI_DU_MAP_URL }); |
77 | - const entityId = ref(''); | 93 | + const [registerDetailDrawer, { openDrawer }] = useDrawer(); |
94 | + | ||
95 | + let entityId = ''; | ||
96 | + let globalRecord: any = {}; | ||
78 | async function initMap() { | 97 | async function initMap() { |
79 | await toPromise(); | 98 | await toPromise(); |
80 | await nextTick(); | 99 | await nextTick(); |
@@ -101,13 +120,14 @@ | @@ -101,13 +120,14 @@ | ||
101 | }, | 120 | }, |
102 | }); | 121 | }); |
103 | // 点击表格某一行触发 | 122 | // 点击表格某一行触发 |
104 | - const deviceRowClick = (record) => { | ||
105 | - entityId.value = record.tbDeviceId; | 123 | + const deviceRowClick = async (record) => { |
124 | + entityId = record.tbDeviceId; | ||
125 | + globalRecord = record; | ||
106 | const BMap = (window as any).BMap; | 126 | const BMap = (window as any).BMap; |
107 | const wrapEl = unref(wrapRef); | 127 | const wrapEl = unref(wrapRef); |
108 | const map = new BMap.Map(wrapEl); | 128 | const map = new BMap.Map(wrapEl); |
109 | if (record.deviceInfo.address) { | 129 | if (record.deviceInfo.address) { |
110 | - const { name, organizationDTO, updateTime, deviceState, deviceProfile } = record; | 130 | + const { name, organizationDTO, deviceState, deviceProfile } = record; |
111 | const { longitude, latitude, address } = record.deviceInfo; | 131 | const { longitude, latitude, address } = record.deviceInfo; |
112 | const point = new BMap.Point(longitude, latitude); | 132 | const point = new BMap.Point(longitude, latitude); |
113 | let options = { | 133 | let options = { |
@@ -117,6 +137,10 @@ | @@ -117,6 +137,10 @@ | ||
117 | map.centerAndZoom(point, 15); | 137 | map.centerAndZoom(point, 15); |
118 | map.enableScrollWheelZoom(true); | 138 | map.enableScrollWheelZoom(true); |
119 | // 创建信息窗口对象 | 139 | // 创建信息窗口对象 |
140 | + const res = await getDeviceActiveTime(entityId); | ||
141 | + | ||
142 | + let { value: activeStatus, lastUpdateTs } = res[0]; | ||
143 | + lastUpdateTs = moment(lastUpdateTs).format('YYYY-MM-DD HH:mm:ss'); | ||
120 | let infoWindow = new BMap.InfoWindow( | 144 | let infoWindow = new BMap.InfoWindow( |
121 | ` | 145 | ` |
122 | <div style="display:flex;justify-content:space-between; margin:20px 0px;"> | 146 | <div style="display:flex;justify-content:space-between; margin:20px 0px;"> |
@@ -132,10 +156,9 @@ | @@ -132,10 +156,9 @@ | ||
132 | <div>所属组织:${organizationDTO.name}</div> | 156 | <div>所属组织:${organizationDTO.name}</div> |
133 | <div style="margin-top:6px;">接入协议:${deviceProfile.transportType}</div> | 157 | <div style="margin-top:6px;">接入协议:${deviceProfile.transportType}</div> |
134 | <div style="margin-top:6px;">设备位置:${address}</div> | 158 | <div style="margin-top:6px;">设备位置:${address}</div> |
135 | - <div style="margin-top:6px;">下线时间:${updateTime}</div> | ||
136 | - <div style="display:flex;justify-content:space-between; margin-top:10px"> | ||
137 | - <button style="color:#fff;background-color:#409eff;padding:4px; border-radius:4px;">设备信息</button> | ||
138 | - <button style="color:#fff;background-color:#409eff;padding:4px; border-radius:4px;">报警记录</button> | 159 | + <div style="margin-top:6px;">${activeStatus ? '在' : '离'}线时间:${lastUpdateTs}</div> |
160 | + <div style="display:flex;justify-content:end; margin-top:10px"> | ||
161 | + <button onclick="openDeviceInfoDrawer()" style="margin-right:10px;color:#fff;background-color:#409eff;padding:4px; border-radius:4px;">设备信息</button> | ||
139 | <button onclick="openHistoryModal()" style="color:#fff;background-color:#409eff;padding:4px; border-radius:4px;">历史数据</button> | 162 | <button onclick="openHistoryModal()" style="color:#fff;background-color:#409eff;padding:4px; border-radius:4px;">历史数据</button> |
140 | </div> | 163 | </div> |
141 | `, | 164 | `, |
@@ -185,13 +208,20 @@ | @@ -185,13 +208,20 @@ | ||
185 | endTs = Date.now(); | 208 | endTs = Date.now(); |
186 | // 发送请求 | 209 | // 发送请求 |
187 | const res = await getDeviceHistoryInfo({ | 210 | const res = await getDeviceHistoryInfo({ |
188 | - entityId: entityId.value, | 211 | + entityId, |
189 | keys: keys.join(), | 212 | keys: keys.join(), |
190 | startTs, | 213 | startTs, |
191 | endTs, | 214 | endTs, |
192 | interval, | 215 | interval, |
193 | agg, | 216 | agg, |
194 | }); | 217 | }); |
218 | + // 判断对象是否为空 | ||
219 | + if (Object.keys(res).length === 0) { | ||
220 | + isNull.value = false; | ||
221 | + return; | ||
222 | + } else { | ||
223 | + isNull.value = true; | ||
224 | + } | ||
195 | // 处理数据 | 225 | // 处理数据 |
196 | for (const key in res) { | 226 | for (const key in res) { |
197 | for (const item1 of res[key]) { | 227 | for (const item1 of res[key]) { |
@@ -250,24 +280,38 @@ | @@ -250,24 +280,38 @@ | ||
250 | 280 | ||
251 | const chartRef = ref<HTMLDivElement | null>(null); | 281 | const chartRef = ref<HTMLDivElement | null>(null); |
252 | const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); | 282 | const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); |
253 | - | 283 | + const isNull = ref(true); |
284 | + // 设备信息 | ||
285 | + const openDeviceInfoDrawer = async () => { | ||
286 | + const { id, tbDeviceId } = globalRecord; | ||
287 | + openDrawer(true, { | ||
288 | + id, | ||
289 | + tbDeviceId, | ||
290 | + }); | ||
291 | + }; | ||
254 | const openHistoryModal = async () => { | 292 | const openHistoryModal = async () => { |
255 | openModal(true); | 293 | openModal(true); |
256 | - | ||
257 | // 收集参数 | 294 | // 收集参数 |
258 | const dataArray: any[] = []; | 295 | const dataArray: any[] = []; |
259 | const startTs = Date.now() - 86400000; //最近一天 | 296 | const startTs = Date.now() - 86400000; //最近一天 |
260 | const endTs = Date.now(); | 297 | const endTs = Date.now(); |
261 | // 发送请求 | 298 | // 发送请求 |
262 | - keys = await getDeviceDataKeys(entityId.value); | 299 | + keys = await getDeviceDataKeys(entityId); |
263 | const res = await getDeviceHistoryInfo({ | 300 | const res = await getDeviceHistoryInfo({ |
264 | - entityId: entityId.value, | 301 | + entityId, |
265 | keys: keys.join(), | 302 | keys: keys.join(), |
266 | startTs, | 303 | startTs, |
267 | endTs, | 304 | endTs, |
268 | interval: 7200000, //间隔两小时 | 305 | interval: 7200000, //间隔两小时 |
269 | agg: 'AVG', | 306 | agg: 'AVG', |
270 | }); | 307 | }); |
308 | + // 判断对象是否为空 | ||
309 | + if (Object.keys(res).length === 0) { | ||
310 | + isNull.value = false; | ||
311 | + return; | ||
312 | + } else { | ||
313 | + isNull.value = true; | ||
314 | + } | ||
271 | // 处理数据 | 315 | // 处理数据 |
272 | for (const key in res) { | 316 | for (const key in res) { |
273 | for (const item1 of res[key]) { | 317 | for (const item1 of res[key]) { |
@@ -327,12 +371,14 @@ | @@ -327,12 +371,14 @@ | ||
327 | agg: 'AVG', | 371 | agg: 'AVG', |
328 | }); | 372 | }); |
329 | }; | 373 | }; |
374 | + | ||
330 | const cancelHistoryModal = () => { | 375 | const cancelHistoryModal = () => { |
331 | resetFields(); | 376 | resetFields(); |
332 | setOptions({}); | 377 | setOptions({}); |
333 | }; | 378 | }; |
334 | onMounted(() => { | 379 | onMounted(() => { |
335 | initMap(); | 380 | initMap(); |
381 | + (window as any).openDeviceInfoDrawer = openDeviceInfoDrawer; | ||
336 | (window as any).openHistoryModal = openHistoryModal; | 382 | (window as any).openHistoryModal = openHistoryModal; |
337 | }); | 383 | }); |
338 | return { | 384 | return { |
@@ -343,7 +389,9 @@ | @@ -343,7 +389,9 @@ | ||
343 | registerModal, | 389 | registerModal, |
344 | registerForm, | 390 | registerForm, |
345 | chartRef, | 391 | chartRef, |
392 | + isNull, | ||
346 | cancelHistoryModal, | 393 | cancelHistoryModal, |
394 | + registerDetailDrawer, | ||
347 | }; | 395 | }; |
348 | }, | 396 | }, |
349 | }); | 397 | }); |
1 | <template> | 1 | <template> |
2 | - <div class="md:flex justify-between"> | ||
3 | - <template v-for="(item, index) in growCardList" :key="item.title"> | ||
4 | - <div | ||
5 | - class="growCardItem md:w-1/3 w-full !md:mt-0 !mt-4 bg-white" | ||
6 | - :class="index === 0 ? '!md:ml-0' : '!md:ml-4'" | ||
7 | - > | ||
8 | - <div | ||
9 | - class=" | ||
10 | - growCardItem-top | ||
11 | - border border-solid border-t-0 border-r-0 border-l-0 border-b-1 | ||
12 | - dark:border-#ccc | ||
13 | - light:border-#F2F2F5 | ||
14 | - " | ||
15 | - > | ||
16 | - <img :src="item.imgUrl" style="width: 5rem; height: 5rem" /> | ||
17 | - <div class="growCardItem-right"> | ||
18 | - <div class="flex justify-between ml-3"> | ||
19 | - <div style="font-size: 1.625rem; color: #333">{{ item.value }}</div> | ||
20 | - <img src="../../../../assets/images/tip.png" style="width: 1.4rem; height: 1.4rem" /> | 2 | + <div class="md:flex"> |
3 | + <Card size="small" class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:mr-4"> | ||
4 | + <div class="flex" style="height: 100px"> | ||
5 | + <div class="mr-4" | ||
6 | + ><img src="/src/assets/images/device-count.png" style="width: 5rem; height: 5rem" | ||
7 | + /></div> | ||
8 | + <div class="flex-auto"> | ||
9 | + <div class="flex justify-between" style="align-items: center"> | ||
10 | + <div style="font-size: 1.625rem; color: #333">{{ | ||
11 | + growCardList?.deviceInfo?.sumCount | ||
12 | + }}</div> | ||
13 | + <img src="/src/assets/images/tip.png" style="width: 1.4rem; height: 1.4rem" /> | ||
14 | + </div> | ||
15 | + <div> 设备数(个) </div> | ||
16 | + <div class="flex mt-2"> | ||
17 | + <div class="flex mr-1" style="align-items: center; font-size: 0.75rem" | ||
18 | + ><img src="/src/assets/images/online.png" class="mr-1" /> | ||
19 | + <span>在线{{ growCardList?.deviceInfo?.onLine }}</span> | ||
21 | </div> | 20 | </div> |
22 | - <div class="ml-3">{{ item.title }}</div> | ||
23 | - <div class="ml-1.5 mt-3 flex flex-nowrap" style="width: 15rem" v-if="item.offLine"> | ||
24 | - <div class="count"> | ||
25 | - <img | ||
26 | - src="../../../../assets/images/online.png" | ||
27 | - style="width: 0.6rem; height: 0.6rem" | ||
28 | - class="mr-1" | ||
29 | - /> | ||
30 | - 在线 {{ item.onLine }} | ||
31 | - </div> | ||
32 | - <div class="count"> | ||
33 | - <img | ||
34 | - src="../../../../assets/images/offline.png" | ||
35 | - style="width: 0.6rem; height: 0.6rem" | ||
36 | - class="mr-1" | ||
37 | - /> | ||
38 | - 离线 {{ item.offLine }} | ||
39 | - </div> | ||
40 | - <div class="count"> | ||
41 | - <img | ||
42 | - src="../../../../assets/images/inactive.png" | ||
43 | - style="width: 0.6rem; height: 0.6rem" | ||
44 | - class="mr-1" | ||
45 | - /> | ||
46 | - 未激活 {{ item.inactive }} | ||
47 | - </div> | 21 | + <div class="flex mr-1" style="align-items: center; font-size: 0.75rem"> |
22 | + <img src="/src/assets/images/offline.png" class="mr-1" /> | ||
23 | + <span> 离线{{ growCardList?.deviceInfo?.offLine }} </span> | ||
48 | </div> | 24 | </div> |
25 | + <div class="flex mr-1" style="align-items: center; font-size: 0.75rem"> | ||
26 | + <img src="/src/assets/images/inactive.png" class="mr-1" /> | ||
27 | + <span> 未激活{{ growCardList?.deviceInfo?.inActive }} </span> | ||
28 | + </div> | ||
29 | + </div> | ||
30 | + </div> | ||
31 | + </div> | ||
32 | + <div class="ml-2 pt-4" style="border-top: 2px solid #f0f2f5"> | ||
33 | + 今日新增 {{ growCardList?.deviceInfo?.todayAdd }}</div | ||
34 | + > | ||
35 | + </Card> | ||
36 | + <Card size="small" class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:mr-4"> | ||
37 | + <div class="flex" style="height: 100px"> | ||
38 | + <div class="mr-4" | ||
39 | + ><img | ||
40 | + :src=" | ||
41 | + role === 'TENANT_ADMIN' | ||
42 | + ? '/src/assets/images/alarm-count.png' | ||
43 | + : '/src/assets/images/zh.png' | ||
44 | + " | ||
45 | + style="width: 5rem; height: 5rem" | ||
46 | + /></div> | ||
47 | + <div class="flex-auto"> | ||
48 | + <div class="flex justify-between" style="align-items: center"> | ||
49 | + <div style="font-size: 1.625rem; color: #333">{{ | ||
50 | + growCardList?.tenantInfo?.sumCount | ||
51 | + }}</div> | ||
52 | + <img src="/src/assets/images/tip.png" style="width: 1.4rem; height: 1.4rem" /> | ||
49 | </div> | 53 | </div> |
54 | + <div> {{ role === 'TENANT_ADMIN' ? '11月告警数(条)' : '租户总量(个)' }}</div> | ||
50 | </div> | 55 | </div> |
51 | - <div class="growCardItem-bottom"> 今日新增 {{ item.newDay }}</div> | ||
52 | </div> | 56 | </div> |
53 | - </template> | 57 | + <div class="ml-2 pt-4" style="border-top: 2px solid #f0f2f5"> |
58 | + 今日新增 {{ growCardList?.tenantInfo?.todayAdd }}</div | ||
59 | + > | ||
60 | + </Card> | ||
61 | + <Card size="small" class="md:w-1/3 w-full !md:mt-0 !mt-4"> | ||
62 | + <div class="flex" style="height: 100px"> | ||
63 | + <div class="mr-4" | ||
64 | + ><img | ||
65 | + :src=" | ||
66 | + role === 'TENANT_ADMIN' | ||
67 | + ? '/src/assets/images/msg-count.png' | ||
68 | + : '/src/assets/images/kf.png' | ||
69 | + " | ||
70 | + style="width: 5rem; height: 5rem" | ||
71 | + /></div> | ||
72 | + <div class="flex-auto"> | ||
73 | + <div class="flex justify-between" style="align-items: center"> | ||
74 | + <div style="font-size: 1.625rem; color: #333">{{ | ||
75 | + growCardList?.customerInfo?.sumCount | ||
76 | + }}</div> | ||
77 | + <img src="/src/assets/images/tip.png" style="width: 1.4rem; height: 1.4rem" /> | ||
78 | + </div> | ||
79 | + <div> {{ role === 'TENANT_ADMIN' ? '11月消息量(条)' : '客户总量(个)' }} </div> | ||
80 | + </div> | ||
81 | + </div> | ||
82 | + <div class="ml-2 pt-4" style="border-top: 2px solid #f0f2f5"> | ||
83 | + 今日新增 {{ growCardList?.customerInfo?.todayAdd }}</div | ||
84 | + > | ||
85 | + </Card> | ||
54 | </div> | 86 | </div> |
55 | </template> | 87 | </template> |
56 | <script lang="ts" setup> | 88 | <script lang="ts" setup> |
57 | - import { growCardList } from '../data'; | ||
58 | -</script> | ||
59 | - | ||
60 | -<style scoped lang="less"> | ||
61 | - .growCardItem { | ||
62 | - height: 11.187rem; | ||
63 | - color: #666; | ||
64 | - .growCardItem-top { | ||
65 | - display: flex; | ||
66 | - margin: 1.25rem; | ||
67 | - padding-bottom: 0.625rem; | ||
68 | - .growCardItem-right { | ||
69 | - width: 18.75rem; | ||
70 | - .count { | ||
71 | - display: flex; | ||
72 | - font-size: 0.75rem; | ||
73 | - align-items: center; | ||
74 | - margin-left: 0.5rem; | ||
75 | - } | ||
76 | - } | ||
77 | - } | ||
78 | - .growCardItem-bottom { | ||
79 | - margin-left: 1.25rem; | ||
80 | - } | 89 | + import { defineProps, ref, onMounted } from 'vue'; |
90 | + import { Card } from 'ant-design-vue'; | ||
91 | + import { getHomeData } from '/@/api/dashboard'; | ||
92 | + interface CardList { | ||
93 | + deviceInfo: { | ||
94 | + sumCount: number; | ||
95 | + onLine: number; | ||
96 | + offLine: number; | ||
97 | + inActive: number; | ||
98 | + todayAdd: number; | ||
99 | + }; | ||
100 | + tenantInfo: { sumCount: number; todayAdd: number }; | ||
101 | + customerInfo: { sumCount: number; todayAdd: number }; | ||
81 | } | 102 | } |
82 | -</style> | 103 | + const growCardList = ref<CardList>(); |
104 | + onMounted(async () => { | ||
105 | + const res = await getHomeData(); | ||
106 | + growCardList.value = res; | ||
107 | + console.log(growCardList.value); | ||
108 | + }); | ||
109 | + defineProps<{ | ||
110 | + role: string; | ||
111 | + }>(); | ||
112 | +</script> |
1 | <template> | 1 | <template> |
2 | - <Card title="帮助文档"> | ||
3 | - <div> | ||
4 | - <template v-for="item in helpDoc" :key="item.title"> | ||
5 | - <AnchorLink v-bind="item" /> | ||
6 | - </template> | ||
7 | - </div> | ||
8 | - <Card | ||
9 | - :tab-list="tabListTitle" | ||
10 | - v-bind="$attrs" | ||
11 | - :active-tab-key="activeKey" | ||
12 | - :bordered="false" | ||
13 | - @tabChange="onTabChange" | ||
14 | - :bodyStyle="{ padding: 0 }" | ||
15 | - > | ||
16 | - <div v-if="activeKey === 'tab1'"> | ||
17 | - <List item-layout="horizontal" :dataSource="dataSource"> | ||
18 | - <template #renderItem="{ item }"> | ||
19 | - <ListItem> | ||
20 | - <ListItemMeta> | ||
21 | - <template #avatar> | ||
22 | - <Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" /> | ||
23 | - </template> | ||
24 | - <template #description> | ||
25 | - <span | ||
26 | - @click="go('/stationnotification/mynotification')" | ||
27 | - class="cursor-pointer noticeTitle" | ||
28 | - >{{ item.sysNotice.title }} | ||
29 | - </span> | ||
30 | - </template> | ||
31 | - <template #title> | ||
32 | - <span>{{ item.user.realName }}</span> | 2 | + <div> |
3 | + <Card title="帮助文档" v-if="role === 'TENANT_ADMIN'"> | ||
4 | + <div> | ||
5 | + <template v-for="item in helpDoc" :key="item.title"> | ||
6 | + <AnchorLink v-bind="item" /> | ||
7 | + </template> | ||
8 | + </div> | ||
9 | + <Card | ||
10 | + v-if="role === 'TENANT_ADMIN'" | ||
11 | + :tab-list="tabListTitle" | ||
12 | + v-bind="$attrs" | ||
13 | + :active-tab-key="activeKey" | ||
14 | + :bordered="false" | ||
15 | + @tabChange="onTabChange" | ||
16 | + :bodyStyle="{ padding: 0 }" | ||
17 | + > | ||
18 | + <div v-if="activeKey === 'tab1'"> | ||
19 | + <List item-layout="horizontal" :dataSource="dataSource"> | ||
20 | + <template #renderItem="{ item }"> | ||
21 | + <ListItem> | ||
22 | + <ListItemMeta> | ||
23 | + <template #avatar> | ||
24 | + <Avatar | ||
25 | + src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" | ||
26 | + /> | ||
27 | + </template> | ||
28 | + <template #description> | ||
29 | + <span | ||
30 | + class="cursor-pointer noticeTitle" | ||
31 | + @click="go('/stationnotification/mynotification')" | ||
32 | + >{{ item.sysNotice.title }} | ||
33 | + </span> | ||
34 | + </template> | ||
35 | + <template #title> | ||
36 | + <span>{{ item.user.realName }}</span> | ||
37 | + </template> | ||
38 | + </ListItemMeta> | ||
39 | + <template #extra> | ||
40 | + <Time :value="item.sysNotice.senderDate" /> | ||
33 | </template> | 41 | </template> |
34 | - </ListItemMeta> | ||
35 | - <template #extra> | ||
36 | - <Time :value="item.sysNotice.senderDate" /> | ||
37 | - </template> | ||
38 | - </ListItem> | ||
39 | - </template> | ||
40 | - </List> | ||
41 | - <Card hoverable title="联系我们" :bordered="false"> | ||
42 | - <template #cover> | ||
43 | - <img :src="getQrCode" alt="" style="width: 150px; height: 150px; margin: 50px auto" /> | ||
44 | - </template> | ||
45 | - <CardMeta> | ||
46 | - <template #description> | ||
47 | - <p>联系人: {{ getContacts }}</p> | ||
48 | - <p>联系电话: {{ getTel }}</p> | ||
49 | - <p>联系地址: {{ getAddress }} </p> | 42 | + </ListItem> |
50 | </template> | 43 | </template> |
51 | - </CardMeta> | ||
52 | - </Card> | ||
53 | - </div> | 44 | + </List> |
45 | + <Card hoverable title="联系我们" :bordered="false"> | ||
46 | + <template #cover> | ||
47 | + <img :src="getQrCode" alt="" style="width: 150px; height: 150px; margin: 50px auto" /> | ||
48 | + </template> | ||
49 | + <CardMeta> | ||
50 | + <template #description> | ||
51 | + <p>联系人: {{ getContacts }}</p> | ||
52 | + <p>联系电话: {{ getTel }}</p> | ||
53 | + <p>联系地址: {{ getAddress }} </p> | ||
54 | + </template> | ||
55 | + </CardMeta> | ||
56 | + </Card> | ||
57 | + </div> | ||
58 | + </Card> | ||
54 | </Card> | 59 | </Card> |
55 | - </Card> | 60 | + |
61 | + <Card v-if="role !== 'TENANT_ADMIN'"> | ||
62 | + <Descriptions title="租户消息量TOP10" :column="1"> | ||
63 | + <template v-for="(item, index) in 10" :key="index"> | ||
64 | + <DescriptionsItem> | ||
65 | + <span | ||
66 | + class="mr-2" | ||
67 | + style=" | ||
68 | + width: 1.25rem; | ||
69 | + height: 1.25rem; | ||
70 | + border: 1px solid; | ||
71 | + color: #0b55f1; | ||
72 | + border-radius: 50%; | ||
73 | + display: flex; | ||
74 | + align-items: center; | ||
75 | + justify-content: center; | ||
76 | + " | ||
77 | + :style="{ | ||
78 | + color: | ||
79 | + index === 0 | ||
80 | + ? '#f0a16e' | ||
81 | + : index === 1 | ||
82 | + ? '#868585' | ||
83 | + : index === 2 | ||
84 | + ? '#e78739' | ||
85 | + : '#4e84f5', | ||
86 | + backgroundColor: | ||
87 | + index === 0 ? '#fed36a' : index === 1 ? '#CBCAC9' : index === 2 ? '#F1B889' : '', | ||
88 | + borderColor: | ||
89 | + index === 0 | ||
90 | + ? '#fdee7d' | ||
91 | + : index === 1 | ||
92 | + ? '#e6e6e5' | ||
93 | + : index === 2 | ||
94 | + ? '#f8c296' | ||
95 | + : '#0b55f1;', | ||
96 | + }" | ||
97 | + >{{ index + 1 }}</span | ||
98 | + >兰州天兆猪业</DescriptionsItem | ||
99 | + > | ||
100 | + </template> | ||
101 | + </Descriptions> | ||
102 | + </Card> | ||
103 | + <BasicTable @register="registerTable" v-if="role !== 'TENANT_ADMIN'" /> | ||
104 | + </div> | ||
56 | </template> | 105 | </template> |
57 | 106 | ||
58 | <script lang="ts"> | 107 | <script lang="ts"> |
59 | import { defineComponent, ref, computed, onMounted } from 'vue'; | 108 | import { defineComponent, ref, computed, onMounted } from 'vue'; |
60 | - import { Card, AnchorLink, List, ListItem, ListItemMeta, Avatar, CardMeta } from 'ant-design-vue'; | 109 | + import { |
110 | + Card, | ||
111 | + AnchorLink, | ||
112 | + List, | ||
113 | + ListItem, | ||
114 | + ListItemMeta, | ||
115 | + Avatar, | ||
116 | + CardMeta, | ||
117 | + Descriptions, | ||
118 | + DescriptionsItem, | ||
119 | + } from 'ant-design-vue'; | ||
61 | import { useUserStore } from '/@/store/modules/user'; | 120 | import { useUserStore } from '/@/store/modules/user'; |
62 | import { getEnterPriseDetail } from '/@/api/oem'; | 121 | import { getEnterPriseDetail } from '/@/api/oem'; |
63 | import { notifyMyGetrPageApi } from '/@/api/stationnotification/stationnotifyApi'; | 122 | import { notifyMyGetrPageApi } from '/@/api/stationnotification/stationnotifyApi'; |
64 | import { Time } from '/@/components/Time'; | 123 | import { Time } from '/@/components/Time'; |
65 | import { useGo } from '/@/hooks/web/usePage'; | 124 | import { useGo } from '/@/hooks/web/usePage'; |
125 | + import { BasicTable, useTable } from '/@/components/Table'; | ||
126 | + import { columns } from './props'; | ||
66 | export default defineComponent({ | 127 | export default defineComponent({ |
67 | components: { | 128 | components: { |
68 | Card, | 129 | Card, |
@@ -73,12 +134,18 @@ | @@ -73,12 +134,18 @@ | ||
73 | Avatar, | 134 | Avatar, |
74 | Time, | 135 | Time, |
75 | CardMeta, | 136 | CardMeta, |
137 | + BasicTable, | ||
138 | + Descriptions, | ||
139 | + DescriptionsItem, | ||
76 | }, | 140 | }, |
77 | - setup() { | ||
78 | - onMounted(async () => { | ||
79 | - const res = await getEnterPriseDetail(); | ||
80 | - userStore.setEnterPriseInfo(res); | ||
81 | - }); | 141 | + props: { |
142 | + role: String, | ||
143 | + }, | ||
144 | + setup(props) { | ||
145 | + // 通知数据 | ||
146 | + const dataSource = ref([]); | ||
147 | + const go = useGo(); | ||
148 | + | ||
82 | const helpDoc = ref([ | 149 | const helpDoc = ref([ |
83 | { | 150 | { |
84 | title: '如何接入设备?', | 151 | title: '如何接入设备?', |
@@ -108,6 +175,12 @@ | @@ -108,6 +175,12 @@ | ||
108 | const onTabChange = (key) => { | 175 | const onTabChange = (key) => { |
109 | activeKey.value = key; | 176 | activeKey.value = key; |
110 | }; | 177 | }; |
178 | + const [registerTable] = useTable({ | ||
179 | + title: '本月即将过期租户', | ||
180 | + showIndexColumn: false, | ||
181 | + useSearchForm: false, | ||
182 | + columns, | ||
183 | + }); | ||
111 | 184 | ||
112 | const userStore = useUserStore(); | 185 | const userStore = useUserStore(); |
113 | const getContacts = computed(() => { | 186 | const getContacts = computed(() => { |
@@ -122,13 +195,12 @@ | @@ -122,13 +195,12 @@ | ||
122 | const getQrCode = computed(() => { | 195 | const getQrCode = computed(() => { |
123 | return userStore.enterPriseInfo?.qrCode; | 196 | return userStore.enterPriseInfo?.qrCode; |
124 | }); | 197 | }); |
125 | - | ||
126 | - // 通知数据 | ||
127 | - const dataSource = ref([]); | ||
128 | - const go = useGo(); | ||
129 | onMounted(async () => { | 198 | onMounted(async () => { |
130 | - const res = await notifyMyGetrPageApi({ page: 1, pageSize: 5 }); | ||
131 | - dataSource.value = res.items; | 199 | + if (props.role !== 'TENANT_ADMIN') return; |
200 | + const res = await getEnterPriseDetail(); | ||
201 | + const notice = await notifyMyGetrPageApi({ page: 1, pageSize: 5 }); | ||
202 | + userStore.setEnterPriseInfo(res); | ||
203 | + dataSource.value = notice.items; | ||
132 | }); | 204 | }); |
133 | 205 | ||
134 | return { | 206 | return { |
@@ -142,6 +214,7 @@ | @@ -142,6 +214,7 @@ | ||
142 | getTel, | 214 | getTel, |
143 | dataSource, | 215 | dataSource, |
144 | go, | 216 | go, |
217 | + registerTable, | ||
145 | }; | 218 | }; |
146 | }, | 219 | }, |
147 | }); | 220 | }); |
@@ -5,7 +5,7 @@ | @@ -5,7 +5,7 @@ | ||
5 | :active-tab-key="activeKey" | 5 | :active-tab-key="activeKey" |
6 | @tabChange="onTabChange" | 6 | @tabChange="onTabChange" |
7 | > | 7 | > |
8 | - <template #tabBarExtraContent> | 8 | + <template #tabBarExtraContent v-if="role === 'TENANT_ADMIN'"> |
9 | <div class="extra-date"> | 9 | <div class="extra-date"> |
10 | <template v-for="(item, index) in dateList" :key="item"> | 10 | <template v-for="(item, index) in dateList" :key="item"> |
11 | <span @click="changeDate(index)" :class="{ active: index === activeIndex }">{{ | 11 | <span @click="changeDate(index)" :class="{ active: index === activeIndex }">{{ |
@@ -16,8 +16,9 @@ | @@ -16,8 +16,9 @@ | ||
16 | </div> | 16 | </div> |
17 | </template> | 17 | </template> |
18 | <div v-if="activeKey === 'tab1'"> | 18 | <div v-if="activeKey === 'tab1'"> |
19 | - <p class="center">告警数</p> | ||
20 | - <VisitAnalysis /> | 19 | + <p class="center">{{ role === 'TENANT_ADMIN' ? '告警数' : '租户趋势' }}</p> |
20 | + <VisitAnalysis v-if="role === 'TENANT_ADMIN'" /> | ||
21 | + <VisitAnalysisBar v-else /> | ||
21 | </div> | 22 | </div> |
22 | <div v-else> | 23 | <div v-else> |
23 | <p class="center">消息数</p> | 24 | <p class="center">消息数</p> |
@@ -30,19 +31,33 @@ | @@ -30,19 +31,33 @@ | ||
30 | import { Card, DatePicker } from 'ant-design-vue'; | 31 | import { Card, DatePicker } from 'ant-design-vue'; |
31 | import VisitAnalysis from './VisitAnalysis.vue'; | 32 | import VisitAnalysis from './VisitAnalysis.vue'; |
32 | import VisitAnalysisBar from './VisitAnalysisBar.vue'; | 33 | import VisitAnalysisBar from './VisitAnalysisBar.vue'; |
34 | + import { defineProps } from 'vue'; | ||
33 | 35 | ||
36 | + const props = defineProps<{ | ||
37 | + role: string; | ||
38 | + }>(); | ||
34 | const activeKey = ref('tab1'); | 39 | const activeKey = ref('tab1'); |
35 | 40 | ||
36 | - const tabListTitle = [ | ||
37 | - { | ||
38 | - key: 'tab1', | ||
39 | - tab: '告警数统计', | ||
40 | - }, | ||
41 | - { | ||
42 | - key: 'tab2', | ||
43 | - tab: '消息量统计', | ||
44 | - }, | ||
45 | - ]; | 41 | + // 动态根据登录角色来判断 |
42 | + const tabListTitle = | ||
43 | + props.role === 'TENANT_ADMIN' | ||
44 | + ? [ | ||
45 | + { | ||
46 | + key: 'tab1', | ||
47 | + tab: '告警数统计', | ||
48 | + }, | ||
49 | + { | ||
50 | + key: 'tab2', | ||
51 | + tab: '消息量统计', | ||
52 | + }, | ||
53 | + ] | ||
54 | + : [ | ||
55 | + { | ||
56 | + key: 'tab1', | ||
57 | + tab: '租户', | ||
58 | + }, | ||
59 | + ]; | ||
60 | + | ||
46 | const dateList = ref(['1小时', '1天', '7天', '30天']); | 61 | const dateList = ref(['1小时', '1天', '7天', '30天']); |
47 | const activeIndex = ref(0); | 62 | const activeIndex = ref(0); |
48 | function onTabChange(key) { | 63 | function onTabChange(key) { |
1 | import { PropType } from 'vue'; | 1 | import { PropType } from 'vue'; |
2 | - | 2 | +import type { BasicColumn } from '/@/components/Table'; |
3 | export interface BasicProps { | 3 | export interface BasicProps { |
4 | width: string; | 4 | width: string; |
5 | height: string; | 5 | height: string; |
@@ -14,3 +14,16 @@ export const basicProps = { | @@ -14,3 +14,16 @@ export const basicProps = { | ||
14 | default: '280px', | 14 | default: '280px', |
15 | }, | 15 | }, |
16 | }; | 16 | }; |
17 | + | ||
18 | +export const columns: BasicColumn[] = [ | ||
19 | + { | ||
20 | + title: '租户名称', | ||
21 | + dataIndex: 'tenantName', | ||
22 | + width: 120, | ||
23 | + }, | ||
24 | + { | ||
25 | + title: '过期时间', | ||
26 | + dataIndex: 'createdTime', | ||
27 | + width: 120, | ||
28 | + }, | ||
29 | +]; |
src/views/dashboard/workbench/data.ts
deleted
100644 → 0
1 | -export interface GrowCardItem { | ||
2 | - imgUrl: string; | ||
3 | - title: string; | ||
4 | - value: string; | ||
5 | - onLine?: number; | ||
6 | - offLine?: number; | ||
7 | - inactive?: number; | ||
8 | - newDay: string; | ||
9 | -} | ||
10 | - | ||
11 | -export const growCardList: GrowCardItem[] = [ | ||
12 | - { | ||
13 | - imgUrl: '/src/assets/images/device-count.png', | ||
14 | - title: '设备数(个)', | ||
15 | - value: '10,000', | ||
16 | - onLine: 2000, | ||
17 | - offLine: 3000, | ||
18 | - inactive: 4000, | ||
19 | - newDay: '123,45', | ||
20 | - }, | ||
21 | - { | ||
22 | - imgUrl: '/src/assets/images/alarm-count.png', | ||
23 | - title: '11月告警数(条)', | ||
24 | - value: '11,000', | ||
25 | - newDay: '167,45', | ||
26 | - }, | ||
27 | - { | ||
28 | - imgUrl: '/src/assets/images/msg-count.png', | ||
29 | - title: '11月消息量(条)', | ||
30 | - value: '12,000', | ||
31 | - newDay: '198,45', | ||
32 | - }, | ||
33 | -]; |
1 | <template> | 1 | <template> |
2 | <div class="p-4 md:flex"> | 2 | <div class="p-4 md:flex"> |
3 | <div class="md:w-7/10 w-full !mr-4 enter-y"> | 3 | <div class="md:w-7/10 w-full !mr-4 enter-y"> |
4 | - <GrowCard :loading="loading" class="enter-y" /> | ||
5 | - <SiteAnalysis class="!my-4 enter-y" :loading="loading" /> | ||
6 | - <div class="md:flex enter-y"> | 4 | + <GrowCard :loading="loading" class="enter-y" :role="role" /> |
5 | + <SiteAnalysis class="!my-4 enter-y" :loading="loading" :role="role" /> | ||
6 | + <div class="md:flex enter-y" v-if="role === 'TENANT_ADMIN'"> | ||
7 | <Card title="核心流程指南" style="width: 100%"> | 7 | <Card title="核心流程指南" style="width: 100%"> |
8 | <img alt="核心流程指南" src="../../../assets/images/flow.png" /> | 8 | <img alt="核心流程指南" src="../../../assets/images/flow.png" /> |
9 | </Card> | 9 | </Card> |
10 | </div> | 10 | </div> |
11 | </div> | 11 | </div> |
12 | <div class="md:w-3/10 w-full enter-y"> | 12 | <div class="md:w-3/10 w-full enter-y"> |
13 | - <HelpDoc /> | 13 | + <HelpDoc :role="role" /> |
14 | </div> | 14 | </div> |
15 | </div> | 15 | </div> |
16 | </template> | 16 | </template> |
@@ -20,7 +20,11 @@ | @@ -20,7 +20,11 @@ | ||
20 | import SiteAnalysis from './components/SiteAnalysis.vue'; | 20 | import SiteAnalysis from './components/SiteAnalysis.vue'; |
21 | import { Card } from 'ant-design-vue'; | 21 | import { Card } from 'ant-design-vue'; |
22 | import HelpDoc from './components/HelpDoc.vue'; | 22 | import HelpDoc from './components/HelpDoc.vue'; |
23 | - | 23 | + import { USER_INFO_KEY } from '/@/enums/cacheEnum'; |
24 | + import { getAuthCache } from '/@/utils/auth'; | ||
25 | + const userInfo: any = getAuthCache(USER_INFO_KEY); | ||
26 | + const role = userInfo.roles[0]; | ||
27 | + console.log(role); | ||
24 | const loading = ref(true); | 28 | const loading = ref(true); |
25 | setTimeout(() => { | 29 | setTimeout(() => { |
26 | loading.value = false; | 30 | loading.value = false; |
1 | import { formatToDateTime } from '/@/utils/dateUtil'; | 1 | import { formatToDateTime } from '/@/utils/dateUtil'; |
2 | import { FormSchema } from '/@/components/Form'; | 2 | import { FormSchema } from '/@/components/Form'; |
3 | import { BasicColumn } from '/@/components/Table'; | 3 | import { BasicColumn } from '/@/components/Table'; |
4 | + | ||
4 | import { DeviceTypeEnum } from '/@/api/device/model/deviceModel'; | 5 | import { DeviceTypeEnum } from '/@/api/device/model/deviceModel'; |
5 | 6 | ||
6 | export const columns: BasicColumn[] = [ | 7 | export const columns: BasicColumn[] = [ |
@@ -8,25 +9,20 @@ export const columns: BasicColumn[] = [ | @@ -8,25 +9,20 @@ export const columns: BasicColumn[] = [ | ||
8 | title: '设备名称', | 9 | title: '设备名称', |
9 | dataIndex: 'name', | 10 | dataIndex: 'name', |
10 | width: 120, | 11 | width: 120, |
11 | - key: 'name', | ||
12 | }, | 12 | }, |
13 | { | 13 | { |
14 | title: '设备标签', | 14 | title: '设备标签', |
15 | dataIndex: 'label', | 15 | dataIndex: 'label', |
16 | width: 100, | 16 | width: 100, |
17 | - key: 'label', | ||
18 | }, | 17 | }, |
19 | { | 18 | { |
20 | title: '设备配置', | 19 | title: '设备配置', |
21 | dataIndex: 'deviceProfile.name', | 20 | dataIndex: 'deviceProfile.name', |
22 | width: 160, | 21 | width: 160, |
23 | - key: 'deviceProfile.name', | ||
24 | }, | 22 | }, |
25 | - | ||
26 | { | 23 | { |
27 | title: '设备类型', | 24 | title: '设备类型', |
28 | dataIndex: 'deviceType', | 25 | dataIndex: 'deviceType', |
29 | - key: 'deviceType', | ||
30 | customRender({ text }) { | 26 | customRender({ text }) { |
31 | return text === DeviceTypeEnum.GATEWAY | 27 | return text === DeviceTypeEnum.GATEWAY |
32 | ? '网关设备' | 28 | ? '网关设备' |
@@ -39,7 +35,6 @@ export const columns: BasicColumn[] = [ | @@ -39,7 +35,6 @@ export const columns: BasicColumn[] = [ | ||
39 | title: '描述', | 35 | title: '描述', |
40 | dataIndex: 'description', | 36 | dataIndex: 'description', |
41 | width: 180, | 37 | width: 180, |
42 | - key: 'description', | ||
43 | }, | 38 | }, |
44 | ]; | 39 | ]; |
45 | // 实时数据表格 | 40 | // 实时数据表格 |
1 | +import { formatToDate } from '/@/utils/dateUtil'; | ||
1 | import { BasicColumn } from '/@/components/Table'; | 2 | import { BasicColumn } from '/@/components/Table'; |
2 | import { FormSchema } from '/@/components/Table'; | 3 | import { FormSchema } from '/@/components/Table'; |
3 | import { DeviceTypeEnum, DeviceState } from '/@/api/device/model/deviceModel'; | 4 | import { DeviceTypeEnum, DeviceState } from '/@/api/device/model/deviceModel'; |
@@ -19,6 +20,7 @@ export const columns: BasicColumn[] = [ | @@ -19,6 +20,7 @@ export const columns: BasicColumn[] = [ | ||
19 | dataIndex: 'deviceProfile.name', | 20 | dataIndex: 'deviceProfile.name', |
20 | width: 160, | 21 | width: 160, |
21 | slots: { customRender: 'deviceProfile' }, | 22 | slots: { customRender: 'deviceProfile' }, |
23 | + ellipsis: true, | ||
22 | }, | 24 | }, |
23 | 25 | ||
24 | { | 26 | { |
@@ -36,10 +38,16 @@ export const columns: BasicColumn[] = [ | @@ -36,10 +38,16 @@ export const columns: BasicColumn[] = [ | ||
36 | width: 120, | 38 | width: 120, |
37 | slots: { customRender: 'deviceState' }, | 39 | slots: { customRender: 'deviceState' }, |
38 | }, | 40 | }, |
39 | - | ||
40 | { | 41 | { |
41 | title: '最后连接时间', | 42 | title: '最后连接时间', |
42 | - dataIndex: 'lastConnectTime', | 43 | + dataIndex: 'lastOnlineTime', |
44 | + format: (text) => formatToDate(text, 'YYYY-MM-DD HH:mm:ss'), | ||
45 | + width: 180, | ||
46 | + }, | ||
47 | + { | ||
48 | + title: '最后断开时间', | ||
49 | + dataIndex: 'lastOfflineTime', | ||
50 | + format: (text) => formatToDate(text, 'YYYY-MM-DD HH:mm:ss'), | ||
43 | width: 180, | 51 | width: 180, |
44 | }, | 52 | }, |
45 | ]; | 53 | ]; |
@@ -6,7 +6,7 @@ | @@ -6,7 +6,7 @@ | ||
6 | :destroyOnClose="true" | 6 | :destroyOnClose="true" |
7 | @close="closeDrawer" | 7 | @close="closeDrawer" |
8 | :title="deviceDetail.name" | 8 | :title="deviceDetail.name" |
9 | - width="78%" | 9 | + width="70%" |
10 | > | 10 | > |
11 | <Tabs v-model:activeKey="activeKey" :size="size" type="card"> | 11 | <Tabs v-model:activeKey="activeKey" :size="size" type="card"> |
12 | <TabPane key="1" tab="详情" | 12 | <TabPane key="1" tab="详情" |
@@ -10,8 +10,8 @@ | @@ -10,8 +10,8 @@ | ||
10 | bordered | 10 | bordered |
11 | :columns="columns" | 11 | :columns="columns" |
12 | :data-source="[deviceDetail]" | 12 | :data-source="[deviceDetail]" |
13 | + :rowKey="(_, index) => index" | ||
13 | :pagination="false" | 14 | :pagination="false" |
14 | - rowKey="tbDeviceId" | ||
15 | style="width: 800px" | 15 | style="width: 800px" |
16 | /> | 16 | /> |
17 | </div> | 17 | </div> |
@@ -23,7 +23,7 @@ | @@ -23,7 +23,7 @@ | ||
23 | </div> | 23 | </div> |
24 | <div v-if="deviceDetail?.deviceInfo?.address" class="mt-4"> | 24 | <div v-if="deviceDetail?.deviceInfo?.address" class="mt-4"> |
25 | <p>设备位置</p> | 25 | <p>设备位置</p> |
26 | - <div ref="wrapRef" style="height: 400px; width: 90%"></div> | 26 | + <div ref="wrapRef" style="height: 400px; width: 100%"></div> |
27 | </div> | 27 | </div> |
28 | </div> | 28 | </div> |
29 | </template> | 29 | </template> |