Showing
6 changed files
with
278 additions
and
53 deletions
... | ... | @@ -75,7 +75,11 @@ interface TrendParamsType { |
75 | 75 | startTs: number; |
76 | 76 | endTs: number; |
77 | 77 | interval: number; |
78 | - trend: 'CUSTOMER_TREND' | 'TENANT_TREND'; | |
78 | + trend: | |
79 | + | 'CUSTOMER_TREND' | |
80 | + | 'TENANT_TREND' | |
81 | + | 'CUSTOMER_MESSAGE_STATISTICAL' | |
82 | + | 'CUSTOMER_MESSAGE_STATISTICAL'; | |
79 | 83 | } |
80 | 84 | // 获取租户趋势或者客户趋势数据 |
81 | 85 | export const getTrendData = (params: TrendParamsType) => { | ... | ... |
... | ... | @@ -8,6 +8,7 @@ import { useMessage } from '/@/hooks/web/useMessage'; |
8 | 8 | * hasBatchDelete: 是否可以删除 |
9 | 9 | * selectionOptions 表格复选框配置项 |
10 | 10 | * handleDeleteOrBatchDelete 删除方法,适用单一删除和批量删除。参数为null为批量删除 |
11 | + * resetSelectedRowKeys 重置选中的数据 | |
11 | 12 | * } |
12 | 13 | * |
13 | 14 | */ |
... | ... | @@ -49,6 +50,10 @@ export const useBatchDelete = ( |
49 | 50 | } |
50 | 51 | }; |
51 | 52 | |
53 | + const resetSelectedRowKeys = () => { | |
54 | + selectedRowIds.value = []; | |
55 | + }; | |
56 | + | |
52 | 57 | const selectionOptions: selectionOptions = { |
53 | 58 | rowKey: 'id', |
54 | 59 | clickToRowSelect: false, |
... | ... | @@ -57,5 +62,5 @@ export const useBatchDelete = ( |
57 | 62 | type: 'checkbox', |
58 | 63 | }, |
59 | 64 | }; |
60 | - return { hasBatchDelete, selectionOptions, handleDeleteOrBatchDelete }; | |
65 | + return { hasBatchDelete, selectionOptions, handleDeleteOrBatchDelete, resetSelectedRowKeys }; | |
61 | 66 | }; | ... | ... |
1 | +<!-- 客户消息量或告警统计 --> | |
2 | +<template> | |
3 | + <div ref="chartRef" :style="{ height, width }"></div> | |
4 | +</template> | |
5 | +<script lang="ts" setup> | |
6 | + import { ref, Ref, withDefaults, onMounted, watch } from 'vue'; | |
7 | + import { useECharts } from '/@/hooks/web/useECharts'; | |
8 | + import { getTrendData } from '/@/api/dashboard'; | |
9 | + | |
10 | + interface Props { | |
11 | + width?: string; | |
12 | + height?: string; | |
13 | + customerList?: Array<[number, string]>; | |
14 | + type: 'CUSTOMER_ALARM_STATISTICAL' | 'CUSTOMER_MESSAGE_STATISTICAL'; | |
15 | + } | |
16 | + const props = withDefaults(defineProps<Props>(), { | |
17 | + width: '100%', | |
18 | + height: '320px', | |
19 | + customerList: () => [], | |
20 | + type: '', | |
21 | + }); | |
22 | + watch( | |
23 | + () => props.customerList, | |
24 | + (newValue) => { | |
25 | + const transferResult = newValue.map((item) => [item.ts, item.value]); | |
26 | + | |
27 | + setOptions({ | |
28 | + tooltip: { | |
29 | + trigger: 'axis', | |
30 | + axisPointer: { | |
31 | + lineStyle: { | |
32 | + width: 1, | |
33 | + color: '#019680', | |
34 | + }, | |
35 | + }, | |
36 | + }, | |
37 | + xAxis: { | |
38 | + type: 'time', | |
39 | + splitLine: { | |
40 | + show: true, | |
41 | + lineStyle: { | |
42 | + width: 1, | |
43 | + type: 'solid', | |
44 | + color: 'rgba(226,226,226,0.5)', | |
45 | + }, | |
46 | + }, | |
47 | + axisTick: { | |
48 | + show: false, | |
49 | + }, | |
50 | + }, | |
51 | + yAxis: { | |
52 | + splitArea: { | |
53 | + show: true, | |
54 | + areaStyle: { | |
55 | + color: ['rgba(255,255,255,0.2)', 'rgba(226,226,226,0.2)'], | |
56 | + }, | |
57 | + }, | |
58 | + }, | |
59 | + grid: { | |
60 | + left: '1%', | |
61 | + right: '2%', | |
62 | + bottom: 0, | |
63 | + containLabel: true, | |
64 | + }, | |
65 | + series: [ | |
66 | + { | |
67 | + smooth: true, | |
68 | + name: '当前趋势', | |
69 | + type: 'line', | |
70 | + data: transferResult, | |
71 | + areaStyle: {}, | |
72 | + itemStyle: { | |
73 | + color: '#5ab1ef', | |
74 | + }, | |
75 | + }, | |
76 | + ], | |
77 | + animationDuration: 1500, | |
78 | + }); | |
79 | + } | |
80 | + ); | |
81 | + | |
82 | + const chartRef = ref<HTMLDivElement | null>(null); | |
83 | + const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); | |
84 | + onMounted(async () => { | |
85 | + const endTs = Date.now(); | |
86 | + const res = await getTrendData({ | |
87 | + startTs: endTs - 2592000000, | |
88 | + endTs, | |
89 | + interval: 86400000, | |
90 | + trend: props.type, | |
91 | + }); | |
92 | + | |
93 | + const transferResult = res.map((item) => [item.ts, item.value]); | |
94 | + setOptions({ | |
95 | + tooltip: { | |
96 | + trigger: 'axis', | |
97 | + axisPointer: { | |
98 | + lineStyle: { | |
99 | + width: 1, | |
100 | + color: '#019680', | |
101 | + }, | |
102 | + }, | |
103 | + }, | |
104 | + xAxis: { | |
105 | + type: 'time', | |
106 | + splitLine: { | |
107 | + show: true, | |
108 | + lineStyle: { | |
109 | + width: 1, | |
110 | + type: 'solid', | |
111 | + color: 'rgba(226,226,226,0.5)', | |
112 | + }, | |
113 | + }, | |
114 | + axisTick: { | |
115 | + show: false, | |
116 | + }, | |
117 | + }, | |
118 | + | |
119 | + yAxis: { | |
120 | + splitArea: { | |
121 | + show: true, | |
122 | + areaStyle: { | |
123 | + color: ['rgba(255,255,255,0.2)', 'rgba(226,226,226,0.2)'], | |
124 | + }, | |
125 | + }, | |
126 | + }, | |
127 | + grid: { | |
128 | + left: '1%', | |
129 | + right: '2%', | |
130 | + bottom: 0, | |
131 | + containLabel: true, | |
132 | + }, | |
133 | + series: [ | |
134 | + { | |
135 | + smooth: true, | |
136 | + name: '当前趋势', | |
137 | + type: 'line', | |
138 | + data: transferResult, | |
139 | + areaStyle: {}, | |
140 | + itemStyle: { | |
141 | + color: '#5ab1ef', | |
142 | + }, | |
143 | + }, | |
144 | + ], | |
145 | + animationDuration: 1500, | |
146 | + }); | |
147 | + }); | |
148 | +</script> | ... | ... |
... | ... | @@ -10,21 +10,40 @@ |
10 | 10 | <div class="extra-date"> |
11 | 11 | <template v-for="(item, index) in dateList" :key="item.value"> |
12 | 12 | <span |
13 | - @click="quickQueryDate(index, item.value)" | |
13 | + @click="quickQueryDate(index, item.value, role === 'CUSTOMER_USER' && 'customer')" | |
14 | 14 | :class="{ active: index === activeIndex }" |
15 | 15 | >{{ item.label }}</span |
16 | 16 | > |
17 | 17 | </template> |
18 | - <DatePicker @change="onDateChange" v-model:value="dateValue" /> | |
18 | + <DatePicker | |
19 | + @change=" | |
20 | + (_, DateString) => onDateChange(_, DateString, role === 'CUSTOMER_USER' && 'customer') | |
21 | + " | |
22 | + v-model:value="dateValue" | |
23 | + /> | |
19 | 24 | </div> |
20 | 25 | </template> |
21 | 26 | <div v-if="activeKey === '1'"> |
22 | 27 | <!-- 折线图 --> |
23 | - <VisitAnalysis :alarmList="state.alarmList" /> | |
28 | + <CustomerAlarmMessage | |
29 | + v-if="role === 'CUSTOMER_USER'" | |
30 | + type="CUSTOMER_ALARM_STATISTICAL" | |
31 | + :customerList="customerAlarmList" | |
32 | + /> | |
33 | + <VisitAnalysis v-else :alarmList="state.alarmList" /> | |
24 | 34 | </div> |
25 | 35 | <div v-if="activeKey === '2'"> |
26 | 36 | <!-- 柱形图 --> |
27 | - <VisitAnalysisBar :dataPointList="state.dataPointList" :messageList="state.messageList" /> | |
37 | + <CustomerAlarmMessage | |
38 | + v-if="role === 'CUSTOMER_USER'" | |
39 | + type="CUSTOMER_MESSAGE_STATISTICAL" | |
40 | + :customerList="customerMessageList" | |
41 | + /> | |
42 | + <VisitAnalysisBar | |
43 | + v-else | |
44 | + :dataPointList="state.dataPointList" | |
45 | + :messageList="state.messageList" | |
46 | + /> | |
28 | 47 | </div> |
29 | 48 | </Card> |
30 | 49 | <div v-if="isAdmin(role)"> |
... | ... | @@ -62,7 +81,7 @@ |
62 | 81 | <div class="extra-date"> |
63 | 82 | <template v-for="(item, index) in TenantOrCustomerDateList" :key="item.value"> |
64 | 83 | <span |
65 | - @click="quickQueryTenantOrCustomerTime(index, item.value, 'customer')" | |
84 | + @click="quickQueryTenantOrCustomerTime(index, item.value)" | |
66 | 85 | :class="{ active: index === activeCustomerIndex }" |
67 | 86 | >{{ item.label }}</span |
68 | 87 | > |
... | ... | @@ -79,7 +98,7 @@ |
79 | 98 | </div> |
80 | 99 | </template> |
81 | 100 | <script lang="ts" setup> |
82 | - import { ref, reactive } from 'vue'; | |
101 | + import { ref, reactive, onMounted } from 'vue'; | |
83 | 102 | import { Card, DatePicker } from 'ant-design-vue'; |
84 | 103 | import VisitAnalysis from './VisitAnalysis.vue'; |
85 | 104 | import VisitAnalysisBar from './VisitAnalysisBar.vue'; |
... | ... | @@ -91,7 +110,10 @@ |
91 | 110 | import { getEntitiesId } from '/@/api/dashboard/index'; |
92 | 111 | import CustomerTrend from './CustomerTrend.vue'; |
93 | 112 | import TenantTrend from './TenantTrend.vue'; |
113 | + import CustomerAlarmMessage from './CustomerAlarmMessage.vue'; | |
94 | 114 | import { useDate } from '../hooks/useDate'; |
115 | + import { getTrendData } from '/@/api/dashboard'; | |
116 | + | |
95 | 117 | defineExpose({ |
96 | 118 | isAdmin, |
97 | 119 | }); |
... | ... | @@ -330,32 +352,56 @@ |
330 | 352 | send(sendValue); |
331 | 353 | } |
332 | 354 | // 选择日期 |
333 | - function onDateChange(_, dateString) { | |
355 | + async function onDateChange(_, dateString, roleType = '') { | |
356 | + console.log(_, dateString, roleType); | |
334 | 357 | activeIndex.value = -1; |
335 | 358 | const dateTime = Number(formatToDateTime(dateString, 'x')); |
336 | - // 动态发送ws数据 | |
337 | - const sendValue = JSON.stringify({ | |
338 | - entityDataCmds: [ | |
339 | - { | |
340 | - cmdId: activeKey.value, | |
341 | - historyCmd: { | |
342 | - keys: | |
343 | - activeKey.value === '1' | |
344 | - ? ['createdAlarmsCountHourly'] | |
345 | - : ['transportMsgCountHourly', 'transportDataPointsCountHourly'], | |
346 | - startTs: dateTime, | |
347 | - endTs: dateTime + 86400000, | |
348 | - interval: 7200000, | |
349 | - limit: 12, | |
350 | - agg: 'SUM', | |
359 | + if (!dateString) return; | |
360 | + if (roleType === 'customer') { | |
361 | + if (activeKey.value === '1') { | |
362 | + const data = await getTrendData({ | |
363 | + startTs: dateTime, | |
364 | + endTs: dateTime + 86400000, | |
365 | + interval: 7200000, | |
366 | + trend: 'CUSTOMER_ALARM_STATISTICAL', | |
367 | + }); | |
368 | + customerAlarmList.value = data; | |
369 | + } else if (activeKey.value === '2') { | |
370 | + const data = await getTrendData({ | |
371 | + startTs: dateTime, | |
372 | + endTs: dateTime + 86400000, | |
373 | + interval: 7200000, | |
374 | + trend: 'CUSTOMER_MESSAGE_STATISTICAL', | |
375 | + }); | |
376 | + customerMessageList.value = data; | |
377 | + } | |
378 | + } else { | |
379 | + // 动态发送ws数据 | |
380 | + const sendValue = JSON.stringify({ | |
381 | + entityDataCmds: [ | |
382 | + { | |
383 | + cmdId: activeKey.value, | |
384 | + historyCmd: { | |
385 | + keys: | |
386 | + activeKey.value === '1' | |
387 | + ? ['createdAlarmsCountHourly'] | |
388 | + : ['transportMsgCountHourly', 'transportDataPointsCountHourly'], | |
389 | + startTs: dateTime, | |
390 | + endTs: dateTime + 86400000, | |
391 | + interval: 7200000, | |
392 | + limit: 12, | |
393 | + agg: 'SUM', | |
394 | + }, | |
351 | 395 | }, |
352 | - }, | |
353 | - ], | |
354 | - }); | |
355 | - send(sendValue); | |
396 | + ], | |
397 | + }); | |
398 | + send(sendValue); | |
399 | + } | |
356 | 400 | } |
401 | + const customerAlarmList = ref([]); | |
402 | + const customerMessageList = ref([]); | |
357 | 403 | // 快速选择时间 |
358 | - function quickQueryDate(index: number, value: number) { | |
404 | + async function quickQueryDate(index: number, value: number, roleType = '') { | |
359 | 405 | if (activeIndex.value === index) return; |
360 | 406 | activeIndex.value = index; |
361 | 407 | dateValue.value = ''; |
... | ... | @@ -365,26 +411,49 @@ |
365 | 411 | } else if (value === 604800000 || value === 2592000000) { |
366 | 412 | interval = 86400000; |
367 | 413 | } |
368 | - // 动态发送ws数据 | |
369 | - const sendValue = JSON.stringify({ | |
370 | - entityDataCmds: [ | |
371 | - { | |
372 | - cmdId: activeKey.value, | |
373 | - historyCmd: { | |
374 | - keys: | |
375 | - activeKey.value === '1' | |
376 | - ? ['createdAlarmsCountHourly'] | |
377 | - : ['transportMsgCountHourly', 'transportDataPointsCountHourly'], | |
378 | - startTs: Date.now() - value, | |
379 | - endTs: Date.now(), | |
380 | - interval, | |
381 | - agg: 'SUM', | |
414 | + if (roleType === 'customer') { | |
415 | + if (activeKey.value === '1') { | |
416 | + const data = await getTrendData({ | |
417 | + startTs: Date.now() - value, | |
418 | + endTs: Date.now(), | |
419 | + interval, | |
420 | + trend: 'CUSTOMER_ALARM_STATISTICAL', | |
421 | + }); | |
422 | + customerAlarmList.value = data; | |
423 | + } else if (activeKey.value === '2') { | |
424 | + const data = await getTrendData({ | |
425 | + startTs: Date.now() - value, | |
426 | + endTs: Date.now(), | |
427 | + interval, | |
428 | + trend: 'CUSTOMER_MESSAGE_STATISTICAL', | |
429 | + }); | |
430 | + customerMessageList.value = data; | |
431 | + } | |
432 | + } else { | |
433 | + // 动态发送ws数据 | |
434 | + const sendValue = JSON.stringify({ | |
435 | + entityDataCmds: [ | |
436 | + { | |
437 | + cmdId: activeKey.value, | |
438 | + historyCmd: { | |
439 | + keys: | |
440 | + activeKey.value === '1' | |
441 | + ? ['createdAlarmsCountHourly'] | |
442 | + : ['transportMsgCountHourly', 'transportDataPointsCountHourly'], | |
443 | + startTs: Date.now() - value, | |
444 | + endTs: Date.now(), | |
445 | + interval, | |
446 | + agg: 'SUM', | |
447 | + }, | |
382 | 448 | }, |
383 | - }, | |
384 | - ], | |
385 | - }); | |
386 | - send(sendValue); | |
449 | + ], | |
450 | + }); | |
451 | + send(sendValue); | |
452 | + } | |
387 | 453 | } |
454 | + onMounted(() => { | |
455 | + console.log(props.role); | |
456 | + }); | |
388 | 457 | |
389 | 458 | const { |
390 | 459 | tenantDateValue, | ... | ... |
... | ... | @@ -70,10 +70,8 @@ |
70 | 70 | name: 'LinkEdge', |
71 | 71 | components: { BasicTable, SceneLinkAgeDrawer, TableAction, Switch }, |
72 | 72 | setup() { |
73 | - const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete( | |
74 | - screenLinkPageDeleteApi, | |
75 | - handleSuccess | |
76 | - ); | |
73 | + const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions, resetSelectedRowKeys } = | |
74 | + useBatchDelete(screenLinkPageDeleteApi, handleSuccess); | |
77 | 75 | selectionOptions.rowSelection.getCheckboxProps = (record: Recordable) => { |
78 | 76 | // Demo:status为1的选择框禁用 |
79 | 77 | if (record.status === 1) { |
... | ... | @@ -87,7 +85,7 @@ |
87 | 85 | const userId = userInfo.userId; |
88 | 86 | const role: string = userInfo.roles[0]; |
89 | 87 | const [registerDrawer, { openDrawer }] = useDrawer(); |
90 | - const [registerTable, { reload, setProps }] = useTable({ | |
88 | + const [registerTable, { reload, setProps, setSelectedRowKeys }] = useTable({ | |
91 | 89 | title: '场景联动列表', |
92 | 90 | api: screenLinkPageGetApi, |
93 | 91 | columns, |
... | ... | @@ -136,6 +134,8 @@ |
136 | 134 | setProps({ |
137 | 135 | loading: true, |
138 | 136 | }); |
137 | + setSelectedRowKeys([]); | |
138 | + resetSelectedRowKeys(); | |
139 | 139 | const newStatus = checked ? 1 : 0; |
140 | 140 | const { createMessage } = useMessage(); |
141 | 141 | try { | ... | ... |
... | ... | @@ -87,7 +87,6 @@ |
87 | 87 | const { setLoginState, getLoginState } = useLoginState(); |
88 | 88 | const { getFormRules } = useFormRules(); |
89 | 89 | const storage = createLocalStorage(); |
90 | - const visible = ref(false); | |
91 | 90 | const formRef = ref(); |
92 | 91 | const loading = ref(false); |
93 | 92 | const rememberMe = ref(false); | ... | ... |