Showing
8 changed files
with
705 additions
and
206 deletions
@@ -22,7 +22,7 @@ export const getDeviceHistoryInfo = (params) => { | @@ -22,7 +22,7 @@ export const getDeviceHistoryInfo = (params) => { | ||
22 | 22 | ||
23 | // 获取设备数据的keys | 23 | // 获取设备数据的keys |
24 | export const getDeviceDataKeys = (id: string) => { | 24 | export const getDeviceDataKeys = (id: string) => { |
25 | - return defHttp.get( | 25 | + return defHttp.get<string[]>( |
26 | { | 26 | { |
27 | url: `/plugins/telemetry/DEVICE/${id}/keys/timeseries`, | 27 | url: `/plugins/telemetry/DEVICE/${id}/keys/timeseries`, |
28 | }, | 28 | }, |
@@ -2,7 +2,8 @@ import type { BasicColumn } from '/@/components/Table'; | @@ -2,7 +2,8 @@ import type { BasicColumn } from '/@/components/Table'; | ||
2 | import type { FormSchema } from '/@/components/Table'; | 2 | import type { FormSchema } from '/@/components/Table'; |
3 | import { getOrganizationList } from '/@/api/system/system'; | 3 | import { getOrganizationList } from '/@/api/system/system'; |
4 | import { copyTransFun } from '/@/utils/fnUtils'; | 4 | import { copyTransFun } from '/@/utils/fnUtils'; |
5 | -import { getDeviceProfile } from '/@/api/alarm/position'; | 5 | +import { getDeviceDataKeys, getDeviceProfile } from '/@/api/alarm/position'; |
6 | +import { EChartsOption } from 'echarts'; | ||
6 | 7 | ||
7 | export enum AggregateDataEnum { | 8 | export enum AggregateDataEnum { |
8 | MIN = 'MIN', | 9 | MIN = 'MIN', |
@@ -381,17 +382,11 @@ export const schemas: FormSchema[] = [ | @@ -381,17 +382,11 @@ export const schemas: FormSchema[] = [ | ||
381 | ], | 382 | ], |
382 | }; | 383 | }; |
383 | }, | 384 | }, |
384 | - colProps: { | ||
385 | - span: 6, | ||
386 | - }, | ||
387 | }, | 385 | }, |
388 | { | 386 | { |
389 | field: 'interval', | 387 | field: 'interval', |
390 | label: '分组间隔', | 388 | label: '分组间隔', |
391 | component: 'Select', | 389 | component: 'Select', |
392 | - colProps: { | ||
393 | - span: 6, | ||
394 | - }, | ||
395 | componentProps: { | 390 | componentProps: { |
396 | placeholder: '请选择分组间隔', | 391 | placeholder: '请选择分组间隔', |
397 | getPopupContainer: () => document.body, | 392 | getPopupContainer: () => document.body, |
@@ -427,6 +422,7 @@ export const schemas: FormSchema[] = [ | @@ -427,6 +422,7 @@ export const schemas: FormSchema[] = [ | ||
427 | field: 'agg', | 422 | field: 'agg', |
428 | label: '数据聚合功能', | 423 | label: '数据聚合功能', |
429 | component: 'Select', | 424 | component: 'Select', |
425 | + defaultValue: AggregateDataEnum.NONE, | ||
430 | componentProps: { | 426 | componentProps: { |
431 | getPopupContainer: () => document.body, | 427 | getPopupContainer: () => document.body, |
432 | options: [ | 428 | options: [ |
@@ -446,10 +442,83 @@ export const schemas: FormSchema[] = [ | @@ -446,10 +442,83 @@ export const schemas: FormSchema[] = [ | ||
446 | label: '求和', | 442 | label: '求和', |
447 | value: AggregateDataEnum.SUM, | 443 | value: AggregateDataEnum.SUM, |
448 | }, | 444 | }, |
445 | + { | ||
446 | + label: '计数', | ||
447 | + value: AggregateDataEnum.COUNT, | ||
448 | + }, | ||
449 | + { | ||
450 | + label: '空', | ||
451 | + value: AggregateDataEnum.NONE, | ||
452 | + }, | ||
449 | ], | 453 | ], |
450 | }, | 454 | }, |
451 | - colProps: { | ||
452 | - span: 6, | 455 | + }, |
456 | + { | ||
457 | + field: 'attr', | ||
458 | + label: '设备属性', | ||
459 | + component: 'Select', | ||
460 | + componentProps: { | ||
461 | + api: async (id: string) => { | ||
462 | + try { | ||
463 | + const res = await getDeviceDataKeys(id); | ||
464 | + return res.map((item) => ({ label: item, value: item })); | ||
465 | + } catch (error) {} | ||
466 | + }, | ||
453 | }, | 467 | }, |
454 | }, | 468 | }, |
455 | ]; | 469 | ]; |
470 | + | ||
471 | +export const selectDeviceAttrSchema: FormSchema[] = [ | ||
472 | + { | ||
473 | + field: 'keys', | ||
474 | + label: '设备属性', | ||
475 | + component: 'Select', | ||
476 | + // componentProps: { | ||
477 | + // api: async ({ entityId }: { entityId: string }) => { | ||
478 | + // if (!entityId) return []; | ||
479 | + // try { | ||
480 | + // const res = await getDeviceDataKeys(entityId); | ||
481 | + // return res.map((item) => ({ label: item, value: item })); | ||
482 | + // } catch (error) {} | ||
483 | + // }, | ||
484 | + // immediate: true, | ||
485 | + // }, | ||
486 | + }, | ||
487 | +]; | ||
488 | + | ||
489 | +export const eChartOptions = (series, keys): EChartsOption => { | ||
490 | + return { | ||
491 | + tooltip: { | ||
492 | + trigger: 'axis', | ||
493 | + }, | ||
494 | + legend: { | ||
495 | + data: keys, | ||
496 | + }, | ||
497 | + grid: { | ||
498 | + left: '3%', | ||
499 | + right: '4%', | ||
500 | + bottom: '3%', | ||
501 | + containLabel: true, | ||
502 | + }, | ||
503 | + dataZoom: [ | ||
504 | + { | ||
505 | + type: 'inside', | ||
506 | + start: 0, | ||
507 | + end: 50, | ||
508 | + }, | ||
509 | + { | ||
510 | + start: 20, | ||
511 | + end: 40, | ||
512 | + }, | ||
513 | + ], | ||
514 | + xAxis: { | ||
515 | + type: 'time', | ||
516 | + boundaryGap: false, | ||
517 | + }, | ||
518 | + yAxis: { | ||
519 | + type: 'value', | ||
520 | + boundaryGap: [0, '100%'], | ||
521 | + }, | ||
522 | + series, | ||
523 | + }; | ||
524 | +}; |
1 | +<script setup lang="ts"> | ||
2 | + import { BasicForm, useForm } from '/@/components/Form'; | ||
3 | + import { defaultSchemas, SchemaFiled } from './config'; | ||
4 | + import { onMounted } from 'vue'; | ||
5 | + | ||
6 | + const emit = defineEmits(['register']); | ||
7 | + const [register, method] = useForm({ | ||
8 | + schemas: defaultSchemas, | ||
9 | + labelWidth: 120, | ||
10 | + baseColProps: { | ||
11 | + span: 5, | ||
12 | + }, | ||
13 | + fieldMapToTime: [[SchemaFiled.DATE_RANGE, [SchemaFiled.START_TS, SchemaFiled.END_TS]]], | ||
14 | + }); | ||
15 | + onMounted(() => { | ||
16 | + emit('register', method); | ||
17 | + }); | ||
18 | +</script> | ||
19 | + | ||
20 | +<template> | ||
21 | + <BasicForm @register="register" /> | ||
22 | +</template> |
1 | +import { Moment } from 'moment'; | ||
2 | +import { getPacketIntervalByRange, getPacketIntervalByValue, intervalOption } from './helper'; | ||
3 | +import { FormSchema } from '/@/components/Form'; | ||
4 | +export enum QueryWay { | ||
5 | + LATEST = 'latest', | ||
6 | + TIME_PERIOD = 'timePeriod', | ||
7 | +} | ||
8 | + | ||
9 | +export enum SchemaFiled { | ||
10 | + WAY = 'way', | ||
11 | + TIME_PERIOD = 'timePeriod', | ||
12 | + KEYS = 'keys', | ||
13 | + DATE_RANGE = 'dataRange', | ||
14 | + START_TS = 'startTs', | ||
15 | + END_TS = 'endTs', | ||
16 | + INTERVAL = 'interval', | ||
17 | + LIMIT = 'limit', | ||
18 | + AGG = 'agg', | ||
19 | + ORDER_BY = 'orderBy', | ||
20 | +} | ||
21 | + | ||
22 | +export enum AggregateDataEnum { | ||
23 | + MIN = 'MIN', | ||
24 | + MAX = 'MAX', | ||
25 | + AVG = 'AVG', | ||
26 | + SUM = 'SUM', | ||
27 | + COUNT = 'COUNT', | ||
28 | + NONE = 'NONE', | ||
29 | +} | ||
30 | +export const defaultSchemas: FormSchema[] = [ | ||
31 | + { | ||
32 | + field: SchemaFiled.WAY, | ||
33 | + label: '查询方式', | ||
34 | + component: 'RadioGroup', | ||
35 | + defaultValue: QueryWay.LATEST, | ||
36 | + componentProps({ formActionType }) { | ||
37 | + const { setFieldsValue } = formActionType; | ||
38 | + return { | ||
39 | + options: [ | ||
40 | + { label: '最后', value: QueryWay.LATEST }, | ||
41 | + { label: '时间段', value: QueryWay.TIME_PERIOD }, | ||
42 | + ], | ||
43 | + onChange(value) { | ||
44 | + value === QueryWay.LATEST | ||
45 | + ? setFieldsValue({ | ||
46 | + [SchemaFiled.DATE_RANGE]: [], | ||
47 | + [SchemaFiled.START_TS]: null, | ||
48 | + [SchemaFiled.END_TS]: null, | ||
49 | + }) | ||
50 | + : setFieldsValue({ [SchemaFiled.START_TS]: null }); | ||
51 | + }, | ||
52 | + }; | ||
53 | + }, | ||
54 | + }, | ||
55 | + { | ||
56 | + field: SchemaFiled.START_TS, | ||
57 | + label: '最后数据', | ||
58 | + component: 'Select', | ||
59 | + ifShow({ values }) { | ||
60 | + return values[SchemaFiled.WAY] === QueryWay.LATEST; | ||
61 | + }, | ||
62 | + componentProps({ formActionType }) { | ||
63 | + const { setFieldsValue } = formActionType; | ||
64 | + return { | ||
65 | + options: intervalOption, | ||
66 | + onChange() { | ||
67 | + setFieldsValue({ [SchemaFiled.INTERVAL]: null }); | ||
68 | + }, | ||
69 | + }; | ||
70 | + }, | ||
71 | + rules: [{ required: true, message: '最后数据为必选项', type: 'number' }], | ||
72 | + }, | ||
73 | + { | ||
74 | + field: SchemaFiled.DATE_RANGE, | ||
75 | + label: '时间段', | ||
76 | + component: 'RangePicker', | ||
77 | + ifShow({ values }) { | ||
78 | + return values[SchemaFiled.WAY] === QueryWay.TIME_PERIOD; | ||
79 | + }, | ||
80 | + rules: [{ required: true, message: '时间段为必选项' }], | ||
81 | + componentProps({ formActionType }) { | ||
82 | + const { setFieldsValue } = formActionType; | ||
83 | + let dates: Moment[] = []; | ||
84 | + return { | ||
85 | + showTime: true, | ||
86 | + onCalendarChange(value: Moment[]) { | ||
87 | + console.log('enter '); | ||
88 | + dates = value; | ||
89 | + }, | ||
90 | + disabledDate(current: Moment) { | ||
91 | + if (!dates || dates.length === 0 || !current) { | ||
92 | + return false; | ||
93 | + } | ||
94 | + const diffDate = current.diff(dates[0], 'years', true); | ||
95 | + return Math.abs(diffDate) > 1; | ||
96 | + }, | ||
97 | + onChange() { | ||
98 | + dates = []; | ||
99 | + setFieldsValue({ [SchemaFiled.INTERVAL]: null }); | ||
100 | + }, | ||
101 | + }; | ||
102 | + }, | ||
103 | + colProps: { | ||
104 | + span: 10, | ||
105 | + }, | ||
106 | + }, | ||
107 | + { | ||
108 | + field: SchemaFiled.AGG, | ||
109 | + label: '数据聚合功能', | ||
110 | + component: 'Select', | ||
111 | + defaultValue: AggregateDataEnum.NONE, | ||
112 | + componentProps: { | ||
113 | + getPopupContainer: () => document.body, | ||
114 | + options: [ | ||
115 | + { label: '最小值', value: AggregateDataEnum.MIN }, | ||
116 | + { label: '最大值', value: AggregateDataEnum.MAX }, | ||
117 | + { label: '平均值', value: AggregateDataEnum.AVG }, | ||
118 | + { label: '求和', value: AggregateDataEnum.SUM }, | ||
119 | + { label: '计数', value: AggregateDataEnum.COUNT }, | ||
120 | + { label: '空', value: AggregateDataEnum.NONE }, | ||
121 | + ], | ||
122 | + }, | ||
123 | + }, | ||
124 | + { | ||
125 | + field: SchemaFiled.INTERVAL, | ||
126 | + label: '分组间隔', | ||
127 | + component: 'Select', | ||
128 | + ifShow({ values }) { | ||
129 | + return values[SchemaFiled.AGG] !== AggregateDataEnum.NONE; | ||
130 | + }, | ||
131 | + componentProps({ formModel }) { | ||
132 | + const options = | ||
133 | + formModel[SchemaFiled.WAY] === QueryWay.LATEST | ||
134 | + ? getPacketIntervalByValue(formModel[SchemaFiled.START_TS]) | ||
135 | + : getPacketIntervalByRange(formModel[SchemaFiled.DATE_RANGE]); | ||
136 | + | ||
137 | + return { | ||
138 | + options, | ||
139 | + }; | ||
140 | + }, | ||
141 | + }, | ||
142 | + { | ||
143 | + field: SchemaFiled.LIMIT, | ||
144 | + label: '最大值', | ||
145 | + component: 'InputNumber', | ||
146 | + defaultValue: 7, | ||
147 | + ifShow({ values }) { | ||
148 | + return values[SchemaFiled.AGG] === AggregateDataEnum.NONE; | ||
149 | + }, | ||
150 | + componentProps: { | ||
151 | + max: 50000, | ||
152 | + min: 7, | ||
153 | + }, | ||
154 | + }, | ||
155 | +]; |
1 | +import { Moment } from 'moment'; | ||
2 | + | ||
3 | +enum TimeUnit { | ||
4 | + SECOND = 'second', | ||
5 | + MINUTE = 'MINUTE', | ||
6 | + HOUR = 'HOUR', | ||
7 | + DAY = 'DAY', | ||
8 | +} | ||
9 | + | ||
10 | +const unitMapping = { | ||
11 | + [TimeUnit.SECOND]: '秒', | ||
12 | + [TimeUnit.MINUTE]: '分', | ||
13 | + [TimeUnit.HOUR]: '小时', | ||
14 | + [TimeUnit.DAY]: '天', | ||
15 | +}; | ||
16 | + | ||
17 | +const unitConversion = { | ||
18 | + [TimeUnit.SECOND]: 1 * 1000, | ||
19 | + [TimeUnit.MINUTE]: 1 * 60 * 1000, | ||
20 | + [TimeUnit.HOUR]: 1 * 60 * 60 * 1000, | ||
21 | + [TimeUnit.DAY]: 1 * 60 * 60 * 24 * 1000, | ||
22 | +}; | ||
23 | + | ||
24 | +export const intervalOption = [ | ||
25 | + { | ||
26 | + id: 1, | ||
27 | + unit: TimeUnit.SECOND, | ||
28 | + linkage: [{ id: 1, unit: TimeUnit.SECOND }], | ||
29 | + }, | ||
30 | + { | ||
31 | + id: 5, | ||
32 | + unit: TimeUnit.SECOND, | ||
33 | + linkage: [{ id: 1, unit: TimeUnit.SECOND }], | ||
34 | + }, | ||
35 | + { | ||
36 | + id: 10, | ||
37 | + unit: TimeUnit.SECOND, | ||
38 | + linkage: [{ id: 1, unit: TimeUnit.SECOND }], | ||
39 | + }, | ||
40 | + { | ||
41 | + id: 15, | ||
42 | + unit: TimeUnit.SECOND, | ||
43 | + linkage: [{ id: 1, unit: TimeUnit.SECOND }], | ||
44 | + }, | ||
45 | + { | ||
46 | + id: 30, | ||
47 | + unit: TimeUnit.SECOND, | ||
48 | + linkage: [{ id: 1, unit: TimeUnit.SECOND }], | ||
49 | + }, | ||
50 | + { | ||
51 | + id: 1, | ||
52 | + unit: TimeUnit.MINUTE, | ||
53 | + linkage: [ | ||
54 | + { id: 1, unit: TimeUnit.SECOND }, | ||
55 | + { id: 5, unit: TimeUnit.SECOND }, | ||
56 | + ], | ||
57 | + }, | ||
58 | + { | ||
59 | + id: 2, | ||
60 | + unit: TimeUnit.MINUTE, | ||
61 | + linkage: [ | ||
62 | + { id: 1, unit: TimeUnit.SECOND }, | ||
63 | + { id: 5, unit: TimeUnit.SECOND }, | ||
64 | + { id: 10, unit: TimeUnit.SECOND }, | ||
65 | + { id: 15, unit: TimeUnit.SECOND }, | ||
66 | + ], | ||
67 | + }, | ||
68 | + { | ||
69 | + id: 5, | ||
70 | + unit: TimeUnit.MINUTE, | ||
71 | + linkage: [ | ||
72 | + { id: 1, unit: TimeUnit.SECOND }, | ||
73 | + { id: 5, unit: TimeUnit.SECOND }, | ||
74 | + { id: 10, unit: TimeUnit.SECOND }, | ||
75 | + { id: 15, unit: TimeUnit.SECOND }, | ||
76 | + { id: 30, unit: TimeUnit.SECOND }, | ||
77 | + ], | ||
78 | + }, | ||
79 | + { | ||
80 | + id: 10, | ||
81 | + unit: TimeUnit.MINUTE, | ||
82 | + linkage: [ | ||
83 | + { id: 5, unit: TimeUnit.SECOND }, | ||
84 | + { id: 10, unit: TimeUnit.SECOND }, | ||
85 | + { id: 15, unit: TimeUnit.SECOND }, | ||
86 | + { id: 30, unit: TimeUnit.SECOND }, | ||
87 | + { id: 1, unit: TimeUnit.MINUTE }, | ||
88 | + ], | ||
89 | + }, | ||
90 | + { | ||
91 | + id: 15, | ||
92 | + unit: TimeUnit.MINUTE, | ||
93 | + linkage: [ | ||
94 | + { id: 5, unit: TimeUnit.SECOND }, | ||
95 | + { id: 10, unit: TimeUnit.SECOND }, | ||
96 | + { id: 15, unit: TimeUnit.SECOND }, | ||
97 | + { id: 30, unit: TimeUnit.SECOND }, | ||
98 | + { id: 1, unit: TimeUnit.MINUTE }, | ||
99 | + { id: 2, unit: TimeUnit.MINUTE }, | ||
100 | + ], | ||
101 | + }, | ||
102 | + { | ||
103 | + id: 30, | ||
104 | + unit: TimeUnit.MINUTE, | ||
105 | + linkage: [ | ||
106 | + { id: 5, unit: TimeUnit.SECOND }, | ||
107 | + { id: 10, unit: TimeUnit.SECOND }, | ||
108 | + { id: 15, unit: TimeUnit.SECOND }, | ||
109 | + { id: 30, unit: TimeUnit.SECOND }, | ||
110 | + { id: 1, unit: TimeUnit.MINUTE }, | ||
111 | + { id: 2, unit: TimeUnit.MINUTE }, | ||
112 | + ], | ||
113 | + }, | ||
114 | + { | ||
115 | + id: 1, | ||
116 | + unit: TimeUnit.HOUR, | ||
117 | + linkage: [ | ||
118 | + { id: 10, unit: TimeUnit.SECOND }, | ||
119 | + { id: 15, unit: TimeUnit.SECOND }, | ||
120 | + { id: 30, unit: TimeUnit.SECOND }, | ||
121 | + { id: 1, unit: TimeUnit.MINUTE }, | ||
122 | + { id: 2, unit: TimeUnit.MINUTE }, | ||
123 | + { id: 5, unit: TimeUnit.MINUTE }, | ||
124 | + ], | ||
125 | + }, | ||
126 | + { | ||
127 | + id: 2, | ||
128 | + unit: TimeUnit.HOUR, | ||
129 | + linkage: [ | ||
130 | + { id: 15, unit: TimeUnit.SECOND }, | ||
131 | + { id: 30, unit: TimeUnit.SECOND }, | ||
132 | + { id: 1, unit: TimeUnit.MINUTE }, | ||
133 | + { id: 2, unit: TimeUnit.MINUTE }, | ||
134 | + { id: 5, unit: TimeUnit.MINUTE }, | ||
135 | + { id: 10, unit: TimeUnit.MINUTE }, | ||
136 | + { id: 15, unit: TimeUnit.MINUTE }, | ||
137 | + ], | ||
138 | + }, | ||
139 | + { | ||
140 | + id: 5, | ||
141 | + unit: TimeUnit.HOUR, | ||
142 | + linkage: [ | ||
143 | + { id: 1, unit: TimeUnit.MINUTE }, | ||
144 | + { id: 2, unit: TimeUnit.MINUTE }, | ||
145 | + { id: 5, unit: TimeUnit.MINUTE }, | ||
146 | + { id: 10, unit: TimeUnit.MINUTE }, | ||
147 | + { id: 15, unit: TimeUnit.MINUTE }, | ||
148 | + { id: 30, unit: TimeUnit.MINUTE }, | ||
149 | + ], | ||
150 | + }, | ||
151 | + { | ||
152 | + id: 10, | ||
153 | + unit: TimeUnit.HOUR, | ||
154 | + linkage: [ | ||
155 | + { id: 2, unit: TimeUnit.MINUTE }, | ||
156 | + { id: 5, unit: TimeUnit.MINUTE }, | ||
157 | + { id: 10, unit: TimeUnit.MINUTE }, | ||
158 | + { id: 15, unit: TimeUnit.MINUTE }, | ||
159 | + { id: 30, unit: TimeUnit.MINUTE }, | ||
160 | + { id: 1, unit: TimeUnit.HOUR }, | ||
161 | + ], | ||
162 | + }, | ||
163 | + { | ||
164 | + id: 12, | ||
165 | + unit: TimeUnit.HOUR, | ||
166 | + linkage: [ | ||
167 | + { id: 2, unit: TimeUnit.MINUTE }, | ||
168 | + { id: 5, unit: TimeUnit.MINUTE }, | ||
169 | + { id: 10, unit: TimeUnit.MINUTE }, | ||
170 | + { id: 15, unit: TimeUnit.MINUTE }, | ||
171 | + { id: 30, unit: TimeUnit.MINUTE }, | ||
172 | + { id: 1, unit: TimeUnit.HOUR }, | ||
173 | + ], | ||
174 | + }, | ||
175 | + { | ||
176 | + id: 1, | ||
177 | + unit: TimeUnit.DAY, | ||
178 | + linkage: [ | ||
179 | + { id: 5, unit: TimeUnit.MINUTE }, | ||
180 | + { id: 10, unit: TimeUnit.MINUTE }, | ||
181 | + { id: 15, unit: TimeUnit.MINUTE }, | ||
182 | + { id: 30, unit: TimeUnit.MINUTE }, | ||
183 | + { id: 1, unit: TimeUnit.HOUR }, | ||
184 | + { id: 2, unit: TimeUnit.HOUR }, | ||
185 | + ], | ||
186 | + }, | ||
187 | + { | ||
188 | + id: 7, | ||
189 | + unit: TimeUnit.DAY, | ||
190 | + linkage: [ | ||
191 | + { id: 30, unit: TimeUnit.MINUTE }, | ||
192 | + { id: 1, unit: TimeUnit.HOUR }, | ||
193 | + { id: 2, unit: TimeUnit.HOUR }, | ||
194 | + { id: 5, unit: TimeUnit.HOUR }, | ||
195 | + { id: 10, unit: TimeUnit.HOUR }, | ||
196 | + { id: 12, unit: TimeUnit.HOUR }, | ||
197 | + { id: 1, unit: TimeUnit.DAY }, | ||
198 | + ], | ||
199 | + }, | ||
200 | + { | ||
201 | + id: 30, | ||
202 | + unit: TimeUnit.DAY, | ||
203 | + linkage: [ | ||
204 | + { id: 2, unit: TimeUnit.HOUR }, | ||
205 | + { id: 5, unit: TimeUnit.HOUR }, | ||
206 | + { id: 10, unit: TimeUnit.HOUR }, | ||
207 | + { id: 12, unit: TimeUnit.HOUR }, | ||
208 | + { id: 1, unit: TimeUnit.DAY }, | ||
209 | + ], | ||
210 | + }, | ||
211 | +].map((item) => { | ||
212 | + return { | ||
213 | + value: item.id * unitConversion[item.unit], | ||
214 | + label: item.id + unitMapping[item.unit], | ||
215 | + linkage: item.linkage.map((item) => { | ||
216 | + return { | ||
217 | + value: item.id * unitConversion[item.unit], | ||
218 | + label: item.id + unitMapping[item.unit], | ||
219 | + }; | ||
220 | + }), | ||
221 | + }; | ||
222 | +}); | ||
223 | + | ||
224 | +const rangeIntervalOption = [ | ||
225 | + { | ||
226 | + id: 90, | ||
227 | + unit: TimeUnit.DAY, | ||
228 | + linkage: [ | ||
229 | + { id: 5, unit: TimeUnit.HOUR }, | ||
230 | + { id: 10, unit: TimeUnit.HOUR }, | ||
231 | + { id: 12, unit: TimeUnit.HOUR }, | ||
232 | + { id: 1, unit: TimeUnit.DAY }, | ||
233 | + { id: 7, unit: TimeUnit.DAY }, | ||
234 | + ], | ||
235 | + }, | ||
236 | + { | ||
237 | + id: 180, | ||
238 | + unit: TimeUnit.DAY, | ||
239 | + linkage: [ | ||
240 | + { id: 10, unit: TimeUnit.HOUR }, | ||
241 | + { id: 12, unit: TimeUnit.HOUR }, | ||
242 | + { id: 1, unit: TimeUnit.DAY }, | ||
243 | + { id: 7, unit: TimeUnit.DAY }, | ||
244 | + ], | ||
245 | + }, | ||
246 | + { | ||
247 | + id: 360, | ||
248 | + unit: TimeUnit.DAY, | ||
249 | + linkage: [ | ||
250 | + { id: 1, unit: TimeUnit.DAY }, | ||
251 | + { id: 7, unit: TimeUnit.DAY }, | ||
252 | + { id: 30, unit: TimeUnit.DAY }, | ||
253 | + ], | ||
254 | + }, | ||
255 | +].map((item) => { | ||
256 | + return { | ||
257 | + value: item.id * unitConversion[item.unit], | ||
258 | + label: item.id + unitMapping[item.unit], | ||
259 | + linkage: item.linkage.map((item) => { | ||
260 | + return { | ||
261 | + value: item.id * unitConversion[item.unit], | ||
262 | + label: item.id + unitMapping[item.unit], | ||
263 | + }; | ||
264 | + }), | ||
265 | + }; | ||
266 | +}); | ||
267 | + | ||
268 | +/** | ||
269 | + * @description | ||
270 | + * @param {number} value | ||
271 | + * @returns | ||
272 | + */ | ||
273 | +export function getPacketIntervalByValue(value: number) { | ||
274 | + return intervalOption.find((item) => item.value === value)?.linkage || []; | ||
275 | +} | ||
276 | + | ||
277 | +export function getPacketIntervalByRange( | ||
278 | + [start, end] = [null, null] as [Nullable<Moment>, Nullable<Moment>] | ||
279 | +) { | ||
280 | + if (start && end) { | ||
281 | + const value = end.diff(start, 'ms'); | ||
282 | + let options: { value: number; label: string }[] = []; | ||
283 | + for (const item of [...intervalOption, ...rangeIntervalOption]) { | ||
284 | + if (item.value <= value) continue; | ||
285 | + if (item.value >= value) { | ||
286 | + options = item.linkage; | ||
287 | + break; | ||
288 | + } | ||
289 | + } | ||
290 | + return options; | ||
291 | + } | ||
292 | + return []; | ||
293 | +} |
1 | +import { nextTick, reactive, ref, unref, watch } from 'vue'; | ||
2 | +import { FormActionType, FormProps } from '/@/components/Form'; | ||
3 | +import { getDynamicProps } from '/@/utils'; | ||
4 | + | ||
5 | +export function useTimePeriodForm(props: FormProps): [Fn, FormActionType] { | ||
6 | + const method = reactive<Partial<FormActionType>>({} as any); | ||
7 | + const isInitialize = ref(false); | ||
8 | + async function register(instance: FormActionType) { | ||
9 | + if (unref(isInitialize)) return; | ||
10 | + await nextTick(); | ||
11 | + Object.assign(method, instance); | ||
12 | + isInitialize.value = true; | ||
13 | + watch( | ||
14 | + () => props, | ||
15 | + () => { | ||
16 | + props && instance.setProps(getDynamicProps(props)); | ||
17 | + }, | ||
18 | + { | ||
19 | + immediate: true, | ||
20 | + deep: true, | ||
21 | + } | ||
22 | + ); | ||
23 | + } | ||
24 | + | ||
25 | + return [register, method as FormActionType]; | ||
26 | +} |
@@ -36,11 +36,12 @@ | @@ -36,11 +36,12 @@ | ||
36 | width="70%" | 36 | width="70%" |
37 | :minHeight="400" | 37 | :minHeight="400" |
38 | :footer="null" | 38 | :footer="null" |
39 | - @cancel="cancelHistoryModal" | ||
40 | :canFullscreen="false" | 39 | :canFullscreen="false" |
40 | + @cancel="handleCancelModal" | ||
41 | > | 41 | > |
42 | - <BasicForm @register="registerForm" /> | ||
43 | - <div v-show="isNull" ref="chartRef" :style="{ height: '600px', width }"> | 42 | + <TimePeriodForm @register="timePeriodRegister" /> |
43 | + <!-- <BasicForm @register="registerForm" /> --> | ||
44 | + <div v-show="isNull" ref="chartRef" :style="{ height: '550px', width }"> | ||
44 | <Loading :loading="loading" :absolute="true" /> | 45 | <Loading :loading="loading" :absolute="true" /> |
45 | </div> | 46 | </div> |
46 | <Empty v-show="!isNull" /> | 47 | <Empty v-show="!isNull" /> |
@@ -49,17 +50,15 @@ | @@ -49,17 +50,15 @@ | ||
49 | </div> | 50 | </div> |
50 | </template> | 51 | </template> |
51 | <script lang="ts"> | 52 | <script lang="ts"> |
52 | - import { defineComponent, ref, nextTick, unref, onMounted, Ref } from 'vue'; | 53 | + import { defineComponent, ref, nextTick, unref, onMounted, Ref, onUnmounted } from 'vue'; |
53 | import { useScript } from '/@/hooks/web/useScript'; | 54 | import { useScript } from '/@/hooks/web/useScript'; |
54 | import { formSchema, columns } from './config.data'; | 55 | import { formSchema, columns } from './config.data'; |
55 | import { BasicTable, useTable } from '/@/components/Table'; | 56 | import { BasicTable, useTable } from '/@/components/Table'; |
56 | import { devicePage } from '/@/api/alarm/contact/alarmContact'; | 57 | import { devicePage } from '/@/api/alarm/contact/alarmContact'; |
57 | - import { Tag, Empty } from 'ant-design-vue'; | 58 | + import { Tag, Empty, message } from 'ant-design-vue'; |
58 | import { DeviceState } from '/@/api/device/model/deviceModel'; | 59 | import { DeviceState } from '/@/api/device/model/deviceModel'; |
59 | import { BAI_DU_MAP_URL } from '/@/utils/fnUtils'; | 60 | import { BAI_DU_MAP_URL } from '/@/utils/fnUtils'; |
60 | import { useModal, BasicModal } from '/@/components/Modal'; | 61 | import { useModal, BasicModal } from '/@/components/Modal'; |
61 | - import { BasicForm, useForm } from '/@/components/Form'; | ||
62 | - import { schemas } from './config.data'; | ||
63 | import { useECharts } from '/@/hooks/web/useECharts'; | 62 | import { useECharts } from '/@/hooks/web/useECharts'; |
64 | import { | 63 | import { |
65 | getDeviceHistoryInfo, | 64 | getDeviceHistoryInfo, |
@@ -77,6 +76,11 @@ | @@ -77,6 +76,11 @@ | ||
77 | import online from '/@/assets/images/online1.png'; | 76 | import online from '/@/assets/images/online1.png'; |
78 | import lx1 from '/@/assets/images/lx1.png'; | 77 | import lx1 from '/@/assets/images/lx1.png'; |
79 | import Loading from '/@/components/Loading/src/Loading.vue'; | 78 | import Loading from '/@/components/Loading/src/Loading.vue'; |
79 | + import { TimePeriodForm, useTimePeriodForm } from './cpns/TimePeriodForm'; | ||
80 | + import { selectDeviceAttrSchema, eChartOptions } from './config.data'; | ||
81 | + import { defaultSchemas } from './cpns/TimePeriodForm/config'; | ||
82 | + import { QueryWay, SchemaFiled, AggregateDataEnum } from './cpns/TimePeriodForm/config'; | ||
83 | + import { formatToDateTime } from '/@/utils/dateUtil'; | ||
80 | export default defineComponent({ | 84 | export default defineComponent({ |
81 | name: 'BaiduMap', | 85 | name: 'BaiduMap', |
82 | components: { | 86 | components: { |
@@ -84,9 +88,9 @@ | @@ -84,9 +88,9 @@ | ||
84 | Tag, | 88 | Tag, |
85 | Empty, | 89 | Empty, |
86 | BasicModal, | 90 | BasicModal, |
87 | - BasicForm, | ||
88 | DeviceDetailDrawer, | 91 | DeviceDetailDrawer, |
89 | Loading, | 92 | Loading, |
93 | + TimePeriodForm, | ||
90 | }, | 94 | }, |
91 | props: { | 95 | props: { |
92 | width: { | 96 | width: { |
@@ -100,103 +104,17 @@ | @@ -100,103 +104,17 @@ | ||
100 | }, | 104 | }, |
101 | setup() { | 105 | setup() { |
102 | let entityId = ''; | 106 | let entityId = ''; |
103 | - let keys = []; | ||
104 | let globalRecord: any = {}; | 107 | let globalRecord: any = {}; |
105 | const wrapRef = ref<HTMLDivElement | null>(null); | 108 | const wrapRef = ref<HTMLDivElement | null>(null); |
106 | const chartRef = ref<HTMLDivElement | null>(null); | 109 | const chartRef = ref<HTMLDivElement | null>(null); |
110 | + const deviceAttrs = ref<string[]>([]); | ||
107 | const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); | 111 | const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); |
108 | const isNull = ref(true); | 112 | const isNull = ref(true); |
109 | const { toPromise } = useScript({ src: BAI_DU_MAP_URL }); | 113 | const { toPromise } = useScript({ src: BAI_DU_MAP_URL }); |
110 | const [registerDetailDrawer, { openDrawer }] = useDrawer(); | 114 | const [registerDetailDrawer, { openDrawer }] = useDrawer(); |
111 | const [registerModal, { openModal }] = useModal(); | 115 | const [registerModal, { openModal }] = useModal(); |
112 | const loading = ref(false); | 116 | const loading = ref(false); |
113 | - const [ | ||
114 | - registerForm, | ||
115 | - { resetFields, getFieldsValue, setFieldsValue, validate, updateSchema }, | ||
116 | - ] = useForm({ | ||
117 | - labelWidth: 120, | ||
118 | - schemas, | ||
119 | - async submitFunc() { | ||
120 | - // 表单验证 | ||
121 | - await validate(); | ||
122 | - let { endTs, interval, agg } = getFieldsValue(); | ||
123 | - if (!endTs || !keys.length) return; | ||
124 | - // 数据收集 | ||
125 | - const dataArray: any[] = []; | ||
126 | - const startTs = Date.now() - endTs; | ||
127 | - endTs = Date.now(); | ||
128 | - // 发送请求 | ||
129 | - loading.value = true; | ||
130 | - const res = await getDeviceHistoryInfo({ | ||
131 | - entityId, | ||
132 | - keys: keys.join(), | ||
133 | - startTs, | ||
134 | - endTs, | ||
135 | - interval, | ||
136 | - agg, | ||
137 | - }); | ||
138 | - // 判断数据对象是否为空 | ||
139 | - if (!Object.keys(res).length) { | ||
140 | - isNull.value = false; | ||
141 | - return; | ||
142 | - } else { | ||
143 | - isNull.value = true; | ||
144 | - } | ||
145 | - // 处理数据 | ||
146 | - for (const key in res) { | ||
147 | - for (const item1 of res[key]) { | ||
148 | - let { ts, value } = item1; | ||
149 | - const time = moment(ts).format('YYYY-MM-DD HH:mm:ss'); | ||
150 | - value = Number(value).toFixed(2); | ||
151 | - dataArray.push([time, value, key]); | ||
152 | - } | ||
153 | - } | ||
154 | - const series: any = keys.map((item) => { | ||
155 | - return { | ||
156 | - name: item, | ||
157 | - type: 'line', | ||
158 | - // stack: 'Total', | ||
159 | - data: dataArray.filter((item1) => item1[2] === item), | ||
160 | - }; | ||
161 | - }); | ||
162 | - // 设置数据 | ||
163 | - setOptions({ | ||
164 | - tooltip: { | ||
165 | - trigger: 'axis', | ||
166 | - }, | ||
167 | - legend: { | ||
168 | - data: keys, | ||
169 | - }, | ||
170 | - grid: { | ||
171 | - left: '3%', | ||
172 | - right: '4%', | ||
173 | - bottom: '3%', | ||
174 | - containLabel: true, | ||
175 | - }, | ||
176 | - dataZoom: [ | ||
177 | - { | ||
178 | - type: 'inside', | ||
179 | - start: 0, | ||
180 | - end: 50, | ||
181 | - }, | ||
182 | - { | ||
183 | - start: 20, | ||
184 | - end: 40, | ||
185 | - }, | ||
186 | - ], | ||
187 | - xAxis: { | ||
188 | - type: 'time', | ||
189 | - boundaryGap: false, | ||
190 | - }, | ||
191 | - yAxis: { | ||
192 | - type: 'value', | ||
193 | - boundaryGap: [0, '100%'], | ||
194 | - }, | ||
195 | - series, | ||
196 | - }); | ||
197 | - loading.value = false; | ||
198 | - }, | ||
199 | - }); | 117 | + |
200 | const [registerTable] = useTable({ | 118 | const [registerTable] = useTable({ |
201 | api: devicePage, | 119 | api: devicePage, |
202 | columns, | 120 | columns, |
@@ -231,7 +149,11 @@ | @@ -231,7 +149,11 @@ | ||
231 | const wrapEl = unref(wrapRef); | 149 | const wrapEl = unref(wrapRef); |
232 | const map = new BMap.Map(wrapEl); | 150 | const map = new BMap.Map(wrapEl); |
233 | // if (record.deviceInfo.address) { | 151 | // if (record.deviceInfo.address) { |
234 | - keys = await getDeviceDataKeys(entityId); | 152 | + // keys = await getDeviceDataKeys(entityId); |
153 | + try { | ||
154 | + deviceAttrs.value = (await getDeviceDataKeys(entityId)) || []; | ||
155 | + } catch (error) {} | ||
156 | + | ||
235 | const { name, organizationDTO, deviceState, deviceProfile } = record; | 157 | const { name, organizationDTO, deviceState, deviceProfile } = record; |
236 | const { longitude, latitude, address } = record.deviceInfo; | 158 | const { longitude, latitude, address } = record.deviceInfo; |
237 | //这里如果没有地理位置 最好设置一个默认位置 不然地图会全蓝 | 159 | //这里如果没有地理位置 最好设置一个默认位置 不然地图会全蓝 |
@@ -314,27 +236,81 @@ | @@ -314,27 +236,81 @@ | ||
314 | tbDeviceId, | 236 | tbDeviceId, |
315 | }); | 237 | }); |
316 | }; | 238 | }; |
317 | - const openHistoryModal = async () => { | ||
318 | - openModal(true); | ||
319 | - // 收集参数 | ||
320 | - const dataArray: any[] = []; | ||
321 | - const startTs = Date.now() - 86400000; //最近一天 | ||
322 | - const endTs = Date.now(); | ||
323 | - // 发送请求 | ||
324 | - if (!keys.length) { | ||
325 | - isNull.value = false; | ||
326 | - return; | 239 | + |
240 | + const [timePeriodRegister, method] = useTimePeriodForm({ | ||
241 | + schemas: [...defaultSchemas, ...selectDeviceAttrSchema], | ||
242 | + async submitFunc() { | ||
243 | + // 表单验证 | ||
244 | + await method.validate(); | ||
245 | + const value = method.getFieldsValue(); | ||
246 | + const searchParams = getSearchParams(value); | ||
247 | + | ||
248 | + if (!hasDeviceAttr()) return; | ||
249 | + // 发送请求 | ||
250 | + loading.value = true; | ||
251 | + const res = await getDeviceHistoryInfo(searchParams); | ||
252 | + // 判断数据对象是否为空 | ||
253 | + if (!Object.keys(res).length) { | ||
254 | + isNull.value = false; | ||
255 | + return; | ||
256 | + } else { | ||
257 | + isNull.value = true; | ||
258 | + } | ||
259 | + setChartOptions(res, value.keys); | ||
260 | + loading.value = false; | ||
261 | + }, | ||
262 | + }); | ||
263 | + | ||
264 | + function getSearchParams(value: Recordable) { | ||
265 | + const { startTs, endTs, interval, agg, limit, keys, way } = value; | ||
266 | + if (way === QueryWay.LATEST) { | ||
267 | + return { | ||
268 | + entityId, | ||
269 | + keys: keys ? keys : unref(deviceAttrs).join(), | ||
270 | + startTs: moment().subtract(startTs, 'ms').valueOf(), | ||
271 | + endTs: Date.now(), | ||
272 | + interval, | ||
273 | + agg, | ||
274 | + limit, | ||
275 | + }; | ||
327 | } else { | 276 | } else { |
328 | - isNull.value = true; | 277 | + return { |
278 | + entityId, | ||
279 | + keys: keys ? keys : unref(deviceAttrs).join(), | ||
280 | + startTs: moment(startTs).valueOf(), | ||
281 | + endTs: moment(endTs).valueOf(), | ||
282 | + interval, | ||
283 | + agg, | ||
284 | + limit, | ||
285 | + }; | ||
329 | } | 286 | } |
287 | + } | ||
288 | + | ||
289 | + const openHistoryModal = async () => { | ||
290 | + openModal(true); | ||
291 | + | ||
292 | + await nextTick(); | ||
293 | + method.updateSchema({ | ||
294 | + field: 'keys', | ||
295 | + componentProps: { | ||
296 | + options: unref(deviceAttrs).map((item) => ({ label: item, value: item })), | ||
297 | + }, | ||
298 | + }); | ||
299 | + | ||
300 | + method.setFieldsValue({ | ||
301 | + [SchemaFiled.START_TS]: 1 * 24 * 60 * 60 * 1000, | ||
302 | + }); | ||
303 | + | ||
304 | + if (!hasDeviceAttr()) return; | ||
305 | + | ||
330 | const res = await getDeviceHistoryInfo({ | 306 | const res = await getDeviceHistoryInfo({ |
331 | entityId, | 307 | entityId, |
332 | - keys: keys.join(), | ||
333 | - startTs, | ||
334 | - endTs, | ||
335 | - interval: 7200000, //间隔两小时 | ||
336 | - agg: 'AVG', | 308 | + keys: unref(deviceAttrs).join(), |
309 | + startTs: Date.now() - 1 * 24 * 60 * 60 * 1000, | ||
310 | + endTs: Date.now(), | ||
311 | + agg: AggregateDataEnum.NONE, | ||
337 | }); | 312 | }); |
313 | + | ||
338 | // 判断对象是否为空 | 314 | // 判断对象是否为空 |
339 | if (!Object.keys(res).length) { | 315 | if (!Object.keys(res).length) { |
340 | isNull.value = false; | 316 | isNull.value = false; |
@@ -342,118 +318,74 @@ | @@ -342,118 +318,74 @@ | ||
342 | } else { | 318 | } else { |
343 | isNull.value = true; | 319 | isNull.value = true; |
344 | } | 320 | } |
345 | - // 处理数据 | ||
346 | - for (const key in res) { | ||
347 | - for (const item1 of res[key]) { | 321 | + setChartOptions(res); |
322 | + }; | ||
323 | + function hasDeviceAttr() { | ||
324 | + if (!unref(deviceAttrs).length) { | ||
325 | + isNull.value = false; | ||
326 | + return false; | ||
327 | + } else { | ||
328 | + isNull.value = true; | ||
329 | + return true; | ||
330 | + } | ||
331 | + } | ||
332 | + | ||
333 | + function setChartOptions(data, keys?) { | ||
334 | + const dataArray: any[] = []; | ||
335 | + for (const key in data) { | ||
336 | + for (const item1 of data[key]) { | ||
348 | let { ts, value } = item1; | 337 | let { ts, value } = item1; |
349 | - const time = moment(ts).format('YYYY-MM-DD HH:mm:ss'); | 338 | + const time = formatToDateTime(ts); |
350 | value = Number(value).toFixed(2); | 339 | value = Number(value).toFixed(2); |
351 | dataArray.push([time, value, key]); | 340 | dataArray.push([time, value, key]); |
352 | } | 341 | } |
353 | } | 342 | } |
343 | + keys = keys ? [keys] : unref(deviceAttrs); | ||
354 | const series: any = keys.map((item) => { | 344 | const series: any = keys.map((item) => { |
355 | return { | 345 | return { |
356 | name: item, | 346 | name: item, |
357 | type: 'line', | 347 | type: 'line', |
358 | - // stack: 'Total', | ||
359 | data: dataArray.filter((item1) => item1[2] === item), | 348 | data: dataArray.filter((item1) => item1[2] === item), |
360 | }; | 349 | }; |
361 | }); | 350 | }); |
362 | - console.log(dataArray); | ||
363 | - // 设置数据; | ||
364 | - setOptions({ | ||
365 | - tooltip: { | ||
366 | - trigger: 'axis', | ||
367 | - }, | ||
368 | - legend: { | ||
369 | - data: keys, | ||
370 | - }, | ||
371 | - grid: { | ||
372 | - left: '3%', | ||
373 | - right: '4%', | ||
374 | - bottom: '3%', | ||
375 | - containLabel: true, | ||
376 | - }, | ||
377 | - dataZoom: [ | ||
378 | - { | ||
379 | - type: 'inside', | ||
380 | - start: 0, | ||
381 | - end: 50, | ||
382 | - }, | ||
383 | - { | ||
384 | - start: 0, | ||
385 | - end: 20, | ||
386 | - }, | ||
387 | - ], | ||
388 | - xAxis: { | ||
389 | - type: 'time', | ||
390 | - boundaryGap: false, | ||
391 | - }, | ||
392 | - yAxis: { | ||
393 | - type: 'value', | ||
394 | - boundaryGap: [0, '100%'], | ||
395 | - }, | ||
396 | - series, | ||
397 | - }); | ||
398 | - setFieldsValue({ | ||
399 | - endTs: 86400000, | ||
400 | - interval: 7200000, | ||
401 | - agg: 'AVG', | ||
402 | - }); | ||
403 | - }; | ||
404 | - const cancelHistoryModal = () => { | ||
405 | - resetFields(); | ||
406 | - updateSchema({ | ||
407 | - field: 'interval', | ||
408 | - componentProps: { | ||
409 | - placeholder: '请选择分组间隔', | ||
410 | - options: [ | ||
411 | - { | ||
412 | - label: '5分钟', | ||
413 | - value: 300000, | ||
414 | - }, | ||
415 | - { | ||
416 | - label: '10分钟', | ||
417 | - value: 600000, | ||
418 | - }, | ||
419 | - { | ||
420 | - label: '15分钟', | ||
421 | - value: 900000, | ||
422 | - }, | ||
423 | - { | ||
424 | - label: '30分钟', | ||
425 | - value: 1800000, | ||
426 | - }, | ||
427 | - { | ||
428 | - label: '1小时', | ||
429 | - value: 3600000, | ||
430 | - }, | ||
431 | - { | ||
432 | - label: '2小时', | ||
433 | - value: 7200000, | ||
434 | - }, | ||
435 | - ], | ||
436 | - }, | 351 | + // 设置数据 |
352 | + setOptions(eChartOptions(series, keys)); | ||
353 | + } | ||
354 | + | ||
355 | + const handleCancelModal = () => { | ||
356 | + method.setFieldsValue({ | ||
357 | + [SchemaFiled.WAY]: QueryWay.LATEST, | ||
358 | + [SchemaFiled.KEYS]: null, | ||
359 | + [SchemaFiled.DATE_RANGE]: [], | ||
360 | + [SchemaFiled.INTERVAL]: null, | ||
361 | + [SchemaFiled.LIMIT]: 7, | ||
362 | + [SchemaFiled.AGG]: AggregateDataEnum.NONE, | ||
437 | }); | 363 | }); |
438 | - setOptions({}); | ||
439 | }; | 364 | }; |
365 | + | ||
440 | onMounted(() => { | 366 | onMounted(() => { |
441 | initMap(); | 367 | initMap(); |
442 | (window as any).openDeviceInfoDrawer = openDeviceInfoDrawer; | 368 | (window as any).openDeviceInfoDrawer = openDeviceInfoDrawer; |
443 | (window as any).openHistoryModal = openHistoryModal; | 369 | (window as any).openHistoryModal = openHistoryModal; |
444 | }); | 370 | }); |
371 | + | ||
372 | + onUnmounted(() => { | ||
373 | + (window as any).openDeviceInfoDrawer = null; | ||
374 | + (window as any).openHistoryModal = null; | ||
375 | + }); | ||
376 | + | ||
445 | return { | 377 | return { |
446 | wrapRef, | 378 | wrapRef, |
447 | registerTable, | 379 | registerTable, |
448 | deviceRowClick, | 380 | deviceRowClick, |
449 | DeviceState, | 381 | DeviceState, |
450 | registerModal, | 382 | registerModal, |
451 | - registerForm, | ||
452 | chartRef, | 383 | chartRef, |
453 | isNull, | 384 | isNull, |
454 | - cancelHistoryModal, | ||
455 | registerDetailDrawer, | 385 | registerDetailDrawer, |
456 | loading, | 386 | loading, |
387 | + timePeriodRegister, | ||
388 | + handleCancelModal, | ||
457 | }; | 389 | }; |
458 | }, | 390 | }, |
459 | }); | 391 | }); |