Commit 828a7a79e928cd160e45e441efdb8ffe579e188c

Authored by xp.Huang
2 parents 96fc3929 11aabd82

Merge branch 'ft' into 'main_dev'

feat: 公共接口管理新增自定义脚本,和优化公共接口管理部分代码

See merge request yunteng/thingskit-front!593
Showing 28 changed files with 943 additions and 3762 deletions
  1 +@table-color: #e5e7eb;
  2 +
  3 +.table-border-color {
  4 + border: 1px solid #e5e7eb;
  5 + text-align: center;
  6 +}
  7 +
  8 +.table-content {
  9 + overflow-x: auto;
  10 +
  11 + table {
  12 + border-collapse: collapse;
  13 + width: 35vw;
  14 + &:extend(.table-border-color);
  15 + }
  16 +
  17 + table thead {
  18 + white-space: nowrap;
  19 + }
  20 +
  21 + table td {
  22 + padding: 5px;
  23 + white-space: nowrap;
  24 + &:extend(.table-border-color);
  25 + }
  26 +
  27 + table th {
  28 + padding: 5px;
  29 + &:extend(.table-border-color);
  30 + }
  31 +}
  1 +@table-color: #e5e7eb;
  2 +
  3 +.table-border-color {
  4 + border: 1px solid #e5e7eb;
  5 + text-align: center;
  6 +}
  7 +
  8 +.table-content {
  9 + table {
  10 + width: 31vw;
  11 + &:extend(.table-border-color);
  12 + }
  13 +
  14 + table td {
  15 + padding: 5px;
  16 + white-space: nowrap;
  17 + &:extend(.table-border-color);
  18 + }
  19 +
  20 + table th {
  21 + padding: 5px;
  22 + &:extend(.table-border-color);
  23 + }
  24 +}
1 -import type { BasicColumn } from '/@/components/Table';  
2 -import type { FormSchema } from '/@/components/Table';  
3 -import { getOrganizationList } from '/@/api/system/system';  
4 -import { copyTransFun } from '/@/utils/fnUtils';  
5 -import { getDeviceDataKeys, getDeviceProfile } from '/@/api/alarm/position';  
6 -import { EChartsOption } from 'echarts';  
7 -  
8 -export enum AggregateDataEnum {  
9 - MIN = 'MIN',  
10 - MAX = 'MAX',  
11 - AVG = 'AVG',  
12 - SUM = 'SUM',  
13 - COUNT = 'COUNT',  
14 - NONE = 'NONE',  
15 -}  
16 -export const formSchema: FormSchema[] = [  
17 - {  
18 - field: 'organizationId',  
19 - label: '',  
20 - component: 'ApiTreeSelect',  
21 - componentProps: {  
22 - placeholder: '请选择组织',  
23 - api: async () => {  
24 - const data = await getOrganizationList();  
25 - copyTransFun(data as any as any[]);  
26 - return data;  
27 - },  
28 - },  
29 - },  
30 - {  
31 - field: 'deviceProfileId',  
32 - label: '',  
33 - component: 'ApiSelect',  
34 - componentProps: {  
35 - api: getDeviceProfile,  
36 - placeholder: '请选择产品',  
37 - labelField: 'name',  
38 - valueField: 'tbProfileId',  
39 - },  
40 - },  
41 - {  
42 - field: 'name',  
43 - label: '',  
44 - component: 'Input',  
45 - componentProps: {  
46 - maxLength: 255,  
47 - placeholder: '请输入设备名称',  
48 - },  
49 - },  
50 - {  
51 - field: 'deviceState',  
52 - label: '',  
53 - component: 'RadioGroup',  
54 - componentProps: {  
55 - size: 'small',  
56 - options: [  
57 - { label: '全部', value: null },  
58 - { label: '待激活', value: 'INACTIVE' },  
59 - { label: '在线', value: 'ONLINE' },  
60 - { label: '离线', value: 'OFFLINE' },  
61 - ],  
62 - },  
63 - },  
64 - {  
65 - field: 'alarmStatus',  
66 - label: '是否告警',  
67 - component: 'RadioGroup',  
68 - labelWidth: '85px',  
69 - componentProps: {  
70 - size: 'small',  
71 - options: [  
72 - { label: '是', value: 1 },  
73 - { label: '否', value: 0 },  
74 - ],  
75 - },  
76 - },  
77 -];  
78 -  
79 -export const columns: BasicColumn[] = [  
80 - {  
81 - title: '名称',  
82 - dataIndex: 'name',  
83 - width: 120,  
84 - format: (_text: string, record: Recordable) => {  
85 - return record?.alias || record?.name;  
86 - },  
87 - },  
88 - {  
89 - title: '设备状态',  
90 - dataIndex: 'deviceState',  
91 - width: 80,  
92 - slots: { customRender: 'deviceState' },  
93 - },  
94 - {  
95 - title: '位置',  
96 - dataIndex: 'deviceInfo.address',  
97 - width: 120,  
98 - },  
99 - {  
100 - title: '告警状态',  
101 - dataIndex: 'alarmStatus',  
102 - width: 80,  
103 - slots: { customRender: 'alarmStatus' },  
104 - },  
105 -];  
106 -  
107 -// 动态生成options  
108 -function generateOptions(value: number) {  
109 - if (value === 3600000) {  
110 - return [  
111 - {  
112 - label: '10秒',  
113 - value: 10000,  
114 - },  
115 - {  
116 - label: '15秒',  
117 - value: 15000,  
118 - },  
119 - {  
120 - label: '30秒',  
121 - value: 30000,  
122 - },  
123 - {  
124 - label: '1分钟',  
125 - value: 60000,  
126 - },  
127 - {  
128 - label: '2分钟',  
129 - value: 120000,  
130 - },  
131 - {  
132 - label: '5分钟',  
133 - value: 300000,  
134 - },  
135 - ];  
136 - } else if (value === 7200000) {  
137 - return [  
138 - {  
139 - label: '15秒',  
140 - value: 15000,  
141 - },  
142 - {  
143 - label: '30秒',  
144 - value: 30000,  
145 - },  
146 - {  
147 - label: '1分钟',  
148 - value: 60000,  
149 - },  
150 - {  
151 - label: '2分钟',  
152 - value: 120000,  
153 - },  
154 - {  
155 - label: '5分钟',  
156 - value: 300000,  
157 - },  
158 - {  
159 - label: '10分钟',  
160 - value: 600000,  
161 - },  
162 - {  
163 - label: '15分钟',  
164 - value: 900000,  
165 - },  
166 - ];  
167 - } else if (value === 18000000) {  
168 - return [  
169 - {  
170 - label: '1分钟',  
171 - value: 60000,  
172 - },  
173 - {  
174 - label: '2分钟',  
175 - value: 120000,  
176 - },  
177 - {  
178 - label: '5分钟',  
179 - value: 300000,  
180 - },  
181 - {  
182 - label: '10分钟',  
183 - value: 600000,  
184 - },  
185 - {  
186 - label: '15分钟',  
187 - value: 900000,  
188 - },  
189 - {  
190 - label: '30分钟',  
191 - value: 1800000,  
192 - },  
193 - ];  
194 - } else if (value === 36000000) {  
195 - return [  
196 - {  
197 - label: '2分钟',  
198 - value: 120000,  
199 - },  
200 - {  
201 - label: '5分钟',  
202 - value: 300000,  
203 - },  
204 - {  
205 - label: '10分钟',  
206 - value: 600000,  
207 - },  
208 - {  
209 - label: '15分钟',  
210 - value: 900000,  
211 - },  
212 - {  
213 - label: '30分钟',  
214 - value: 1800000,  
215 - },  
216 - {  
217 - label: '1小时',  
218 - value: 3600000,  
219 - },  
220 - ];  
221 - } else if (value === 43200000) {  
222 - return [  
223 - {  
224 - label: '2分钟',  
225 - value: 120000,  
226 - },  
227 - {  
228 - label: '5分钟',  
229 - value: 300000,  
230 - },  
231 - {  
232 - label: '10分钟',  
233 - value: 600000,  
234 - },  
235 - {  
236 - label: '15分钟',  
237 - value: 900000,  
238 - },  
239 - {  
240 - label: '30分钟',  
241 - value: 1800000,  
242 - },  
243 - {  
244 - label: '1小时',  
245 - value: 3600000,  
246 - },  
247 - ];  
248 - } else if (value === 86400000) {  
249 - return [  
250 - {  
251 - label: '5分钟',  
252 - value: 300000,  
253 - },  
254 - {  
255 - label: '10分钟',  
256 - value: 600000,  
257 - },  
258 - {  
259 - label: '15分钟',  
260 - value: 900000,  
261 - },  
262 - {  
263 - label: '30分钟',  
264 - value: 1800000,  
265 - },  
266 - {  
267 - label: '1小时',  
268 - value: 3600000,  
269 - },  
270 - {  
271 - label: '2小时',  
272 - value: 7200000,  
273 - },  
274 - ];  
275 - } else if (value === 604800000) {  
276 - return [  
277 - {  
278 - label: '30分钟',  
279 - value: 1800000,  
280 - },  
281 - {  
282 - label: '1小时',  
283 - value: 3600000,  
284 - },  
285 - {  
286 - label: '2小时',  
287 - value: 7200000,  
288 - },  
289 - {  
290 - label: '5小时',  
291 - value: 18000000,  
292 - },  
293 - {  
294 - label: '10小时',  
295 - value: 36000000,  
296 - },  
297 - {  
298 - label: '12小时',  
299 - value: 43200000,  
300 - },  
301 - {  
302 - label: '1天',  
303 - value: 86400000,  
304 - },  
305 - ];  
306 - } else {  
307 - return [  
308 - {  
309 - label: '2小时',  
310 - value: 7200000,  
311 - },  
312 - {  
313 - label: '5小时',  
314 - value: 18000000,  
315 - },  
316 - {  
317 - label: '10小时',  
318 - value: 36000000,  
319 - },  
320 - {  
321 - label: '12小时',  
322 - value: 43200000,  
323 - },  
324 - {  
325 - label: '1天',  
326 - value: 86400000,  
327 - },  
328 - ];  
329 - }  
330 -}  
331 -export const schemas: FormSchema[] = [  
332 - {  
333 - field: 'endTs',  
334 - label: '最后数据',  
335 - component: 'Select',  
336 - required: true,  
337 - componentProps({ formModel, formActionType }) {  
338 - return {  
339 - onChange(value) {  
340 - const { updateSchema } = formActionType;  
341 - console.log(value);  
342 - formModel.interval = '';  
343 - updateSchema({  
344 - field: 'interval',  
345 - componentProps: {  
346 - placeholder: '请选择分组间隔',  
347 - options: generateOptions(value),  
348 - },  
349 - });  
350 - },  
351 - getPopupContainer: () => document.body,  
352 - options: [  
353 - {  
354 - label: '最近1小时',  
355 - value: 3600000,  
356 - },  
357 - {  
358 - label: '最近2小时',  
359 - value: 7200000,  
360 - },  
361 - {  
362 - label: '最近5小时',  
363 - value: 18000000,  
364 - },  
365 - {  
366 - label: '最近10小时',  
367 - value: 36000000,  
368 - },  
369 - {  
370 - label: '最近12小时',  
371 - value: 43200000,  
372 - },  
373 - {  
374 - label: '最近1天',  
375 - value: 86400000,  
376 - },  
377 - {  
378 - label: '最近7天',  
379 - value: 604800000,  
380 - },  
381 - {  
382 - label: '最近30天',  
383 - value: 2592000000,  
384 - },  
385 - ],  
386 - };  
387 - },  
388 - },  
389 - {  
390 - field: 'interval',  
391 - label: '分组间隔',  
392 - component: 'Select',  
393 - componentProps: {  
394 - placeholder: '请选择分组间隔',  
395 - getPopupContainer: () => document.body,  
396 - options: [  
397 - {  
398 - label: '5分钟',  
399 - value: 300000,  
400 - },  
401 - {  
402 - label: '10分钟',  
403 - value: 600000,  
404 - },  
405 - {  
406 - label: '15分钟',  
407 - value: 900000,  
408 - },  
409 - {  
410 - label: '30分钟',  
411 - value: 1800000,  
412 - },  
413 - {  
414 - label: '1小时',  
415 - value: 3600000,  
416 - },  
417 - {  
418 - label: '2小时',  
419 - value: 7200000,  
420 - },  
421 - ],  
422 - },  
423 - },  
424 - {  
425 - field: 'agg',  
426 - label: '数据聚合功能',  
427 - component: 'Select',  
428 - defaultValue: AggregateDataEnum.NONE,  
429 - componentProps: {  
430 - getPopupContainer: () => document.body,  
431 - options: [  
432 - {  
433 - label: '最小值',  
434 - value: AggregateDataEnum.MIN,  
435 - },  
436 - {  
437 - label: '最大值',  
438 - value: AggregateDataEnum.MAX,  
439 - },  
440 - {  
441 - label: '平均值',  
442 - value: AggregateDataEnum.AVG,  
443 - },  
444 - {  
445 - label: '求和',  
446 - value: AggregateDataEnum.SUM,  
447 - },  
448 - {  
449 - label: '计数',  
450 - value: AggregateDataEnum.COUNT,  
451 - },  
452 - {  
453 - label: '空',  
454 - value: AggregateDataEnum.NONE,  
455 - },  
456 - ],  
457 - },  
458 - },  
459 - {  
460 - field: 'attr',  
461 - label: '设备属性',  
462 - component: 'Select',  
463 - componentProps: {  
464 - api: async (id: string) => {  
465 - try {  
466 - const res = await getDeviceDataKeys(id);  
467 - return res.map((item) => ({ label: item, value: item }));  
468 - } catch (error) {}  
469 - },  
470 - },  
471 - },  
472 -];  
473 -  
474 -export const selectDeviceAttrSchema: FormSchema[] = [  
475 - {  
476 - field: 'keys',  
477 - label: '设备属性',  
478 - component: 'Select',  
479 - componentProps: {  
480 - getPopupContainer: () => document.body,  
481 - },  
482 - },  
483 -];  
484 -  
485 -export const eChartOptions = (series: EChartsOption['series'], keys: string[]): EChartsOption => {  
486 - return {  
487 - tooltip: {  
488 - trigger: 'axis',  
489 - },  
490 - legend: {  
491 - data: keys,  
492 - },  
493 - grid: {  
494 - left: '3%',  
495 - right: '4%',  
496 - bottom: '3%',  
497 - containLabel: true,  
498 - },  
499 - dataZoom: [  
500 - {  
501 - type: 'inside',  
502 - start: 0,  
503 - end: 50,  
504 - },  
505 - {  
506 - start: 20,  
507 - end: 40,  
508 - },  
509 - ],  
510 - xAxis: {  
511 - type: 'time',  
512 - boundaryGap: false,  
513 - },  
514 - yAxis: {  
515 - type: 'value',  
516 - boundaryGap: [0, '100%'],  
517 - },  
518 - series,  
519 - };  
520 -};  
521 -  
522 -//百度地图设置个性化地图配置  
523 -export const setMapStyleV2 = {  
524 - styleJson: [  
525 - {  
526 - featureType: 'land',  
527 - elementType: 'geometry',  
528 - stylers: {  
529 - visibility: 'on',  
530 - color: '#091220ff',  
531 - },  
532 - },  
533 - {  
534 - featureType: 'water',  
535 - elementType: 'geometry',  
536 - stylers: {  
537 - visibility: 'on',  
538 - color: '#113549ff',  
539 - },  
540 - },  
541 - {  
542 - featureType: 'green',  
543 - elementType: 'geometry',  
544 - stylers: {  
545 - visibility: 'on',  
546 - color: '#0e1b30ff',  
547 - },  
548 - },  
549 - {  
550 - featureType: 'building',  
551 - elementType: 'geometry',  
552 - stylers: {  
553 - visibility: 'on',  
554 - },  
555 - },  
556 - {  
557 - featureType: 'building',  
558 - elementType: 'geometry.topfill',  
559 - stylers: {  
560 - color: '#113549ff',  
561 - },  
562 - },  
563 - {  
564 - featureType: 'building',  
565 - elementType: 'geometry.sidefill',  
566 - stylers: {  
567 - color: '#143e56ff',  
568 - },  
569 - },  
570 - {  
571 - featureType: 'building',  
572 - elementType: 'geometry.stroke',  
573 - stylers: {  
574 - color: '#dadada00',  
575 - },  
576 - },  
577 - {  
578 - featureType: 'subwaystation',  
579 - elementType: 'geometry',  
580 - stylers: {  
581 - visibility: 'on',  
582 - color: '#113549B2',  
583 - },  
584 - },  
585 - {  
586 - featureType: 'education',  
587 - elementType: 'geometry',  
588 - stylers: {  
589 - visibility: 'on',  
590 - color: '#12223dff',  
591 - },  
592 - },  
593 - {  
594 - featureType: 'medical',  
595 - elementType: 'geometry',  
596 - stylers: {  
597 - visibility: 'on',  
598 - color: '#12223dff',  
599 - },  
600 - },  
601 - {  
602 - featureType: 'scenicspots',  
603 - elementType: 'geometry',  
604 - stylers: {  
605 - visibility: 'on',  
606 - color: '#12223dff',  
607 - },  
608 - },  
609 - {  
610 - featureType: 'highway',  
611 - elementType: 'geometry',  
612 - stylers: {  
613 - visibility: 'on',  
614 - weight: 4,  
615 - },  
616 - },  
617 - {  
618 - featureType: 'highway',  
619 - elementType: 'geometry.fill',  
620 - stylers: {  
621 - color: '#12223dff',  
622 - },  
623 - },  
624 - {  
625 - featureType: 'highway',  
626 - elementType: 'geometry.stroke',  
627 - stylers: {  
628 - color: '#fed66900',  
629 - },  
630 - },  
631 - {  
632 - featureType: 'highway',  
633 - elementType: 'labels',  
634 - stylers: {  
635 - visibility: 'on',  
636 - },  
637 - },  
638 - {  
639 - featureType: 'highway',  
640 - elementType: 'labels.text.fill',  
641 - stylers: {  
642 - color: '#12223dff',  
643 - },  
644 - },  
645 - {  
646 - featureType: 'highway',  
647 - elementType: 'labels.text.stroke',  
648 - stylers: {  
649 - color: '#ffffff00',  
650 - },  
651 - },  
652 - {  
653 - featureType: 'highway',  
654 - elementType: 'labels.icon',  
655 - stylers: {  
656 - visibility: 'on',  
657 - },  
658 - },  
659 - {  
660 - featureType: 'arterial',  
661 - elementType: 'geometry',  
662 - stylers: {  
663 - visibility: 'on',  
664 - weight: 2,  
665 - },  
666 - },  
667 - {  
668 - featureType: 'arterial',  
669 - elementType: 'geometry.fill',  
670 - stylers: {  
671 - color: '#12223dff',  
672 - },  
673 - },  
674 - {  
675 - featureType: 'arterial',  
676 - elementType: 'geometry.stroke',  
677 - stylers: {  
678 - color: '#ffeebb00',  
679 - },  
680 - },  
681 - {  
682 - featureType: 'arterial',  
683 - elementType: 'labels',  
684 - stylers: {  
685 - visibility: 'on',  
686 - },  
687 - },  
688 - {  
689 - featureType: 'arterial',  
690 - elementType: 'labels.text.fill',  
691 - stylers: {  
692 - color: '#2dc4bbff',  
693 - },  
694 - },  
695 - {  
696 - featureType: 'arterial',  
697 - elementType: 'labels.text.stroke',  
698 - stylers: {  
699 - color: '#ffffff00',  
700 - },  
701 - },  
702 - {  
703 - featureType: 'local',  
704 - elementType: 'geometry',  
705 - stylers: {  
706 - visibility: 'on',  
707 - weight: 1,  
708 - },  
709 - },  
710 - {  
711 - featureType: 'local',  
712 - elementType: 'geometry.fill',  
713 - stylers: {  
714 - color: '#12223dff',  
715 - },  
716 - },  
717 - {  
718 - featureType: 'local',  
719 - elementType: 'geometry.stroke',  
720 - stylers: {  
721 - color: '#ffffff00',  
722 - },  
723 - },  
724 - {  
725 - featureType: 'local',  
726 - elementType: 'labels',  
727 - stylers: {  
728 - visibility: 'on',  
729 - },  
730 - },  
731 - {  
732 - featureType: 'local',  
733 - elementType: 'labels.text.fill',  
734 - stylers: {  
735 - color: '#979c9aff',  
736 - },  
737 - },  
738 - {  
739 - featureType: 'local',  
740 - elementType: 'labels.text.stroke',  
741 - stylers: {  
742 - color: '#ffffffff',  
743 - },  
744 - },  
745 - {  
746 - featureType: 'railway',  
747 - elementType: 'geometry',  
748 - stylers: {  
749 - visibility: 'off',  
750 - },  
751 - },  
752 - {  
753 - featureType: 'subway',  
754 - elementType: 'geometry',  
755 - stylers: {  
756 - visibility: 'off',  
757 - weight: 1,  
758 - },  
759 - },  
760 - {  
761 - featureType: 'subway',  
762 - elementType: 'geometry.fill',  
763 - stylers: {  
764 - color: '#d8d8d8ff',  
765 - },  
766 - },  
767 - {  
768 - featureType: 'subway',  
769 - elementType: 'geometry.stroke',  
770 - stylers: {  
771 - color: '#ffffff00',  
772 - },  
773 - },  
774 - {  
775 - featureType: 'subway',  
776 - elementType: 'labels',  
777 - stylers: {  
778 - visibility: 'on',  
779 - },  
780 - },  
781 - {  
782 - featureType: 'subway',  
783 - elementType: 'labels.text.fill',  
784 - stylers: {  
785 - color: '#979c9aff',  
786 - },  
787 - },  
788 - {  
789 - featureType: 'subway',  
790 - elementType: 'labels.text.stroke',  
791 - stylers: {  
792 - color: '#ffffffff',  
793 - },  
794 - },  
795 - {  
796 - featureType: 'continent',  
797 - elementType: 'labels',  
798 - stylers: {  
799 - visibility: 'on',  
800 - },  
801 - },  
802 - {  
803 - featureType: 'continent',  
804 - elementType: 'labels.icon',  
805 - stylers: {  
806 - visibility: 'on',  
807 - },  
808 - },  
809 - {  
810 - featureType: 'continent',  
811 - elementType: 'labels.text.fill',  
812 - stylers: {  
813 - color: '#2dc4bbff',  
814 - },  
815 - },  
816 - {  
817 - featureType: 'continent',  
818 - elementType: 'labels.text.stroke',  
819 - stylers: {  
820 - color: '#ffffff00',  
821 - },  
822 - },  
823 - {  
824 - featureType: 'city',  
825 - elementType: 'labels.icon',  
826 - stylers: {  
827 - visibility: 'off',  
828 - },  
829 - },  
830 - {  
831 - featureType: 'city',  
832 - elementType: 'labels',  
833 - stylers: {  
834 - visibility: 'on',  
835 - },  
836 - },  
837 - {  
838 - featureType: 'city',  
839 - elementType: 'labels.text.fill',  
840 - stylers: {  
841 - color: '#2dc4bbff',  
842 - },  
843 - },  
844 - {  
845 - featureType: 'city',  
846 - elementType: 'labels.text.stroke',  
847 - stylers: {  
848 - color: '#ffffff00',  
849 - },  
850 - },  
851 - {  
852 - featureType: 'town',  
853 - elementType: 'labels.icon',  
854 - stylers: {  
855 - visibility: 'on',  
856 - },  
857 - },  
858 - {  
859 - featureType: 'town',  
860 - elementType: 'labels',  
861 - stylers: {  
862 - visibility: 'off',  
863 - },  
864 - },  
865 - {  
866 - featureType: 'town',  
867 - elementType: 'labels.text.fill',  
868 - stylers: {  
869 - color: '#454d50ff',  
870 - },  
871 - },  
872 - {  
873 - featureType: 'town',  
874 - elementType: 'labels.text.stroke',  
875 - stylers: {  
876 - color: '#ffffffff',  
877 - },  
878 - },  
879 - {  
880 - featureType: 'road',  
881 - elementType: 'geometry.fill',  
882 - stylers: {  
883 - color: '#12223dff',  
884 - },  
885 - },  
886 - {  
887 - featureType: 'poilabel',  
888 - elementType: 'labels',  
889 - stylers: {  
890 - visibility: 'on',  
891 - },  
892 - },  
893 - {  
894 - featureType: 'districtlabel',  
895 - elementType: 'labels',  
896 - stylers: {  
897 - visibility: 'off',  
898 - },  
899 - },  
900 - {  
901 - featureType: 'road',  
902 - elementType: 'geometry',  
903 - stylers: {  
904 - visibility: 'on',  
905 - },  
906 - },  
907 - {  
908 - featureType: 'road',  
909 - elementType: 'labels',  
910 - stylers: {  
911 - visibility: 'off',  
912 - },  
913 - },  
914 - {  
915 - featureType: 'road',  
916 - elementType: 'geometry.stroke',  
917 - stylers: {  
918 - color: '#ffffff00',  
919 - },  
920 - },  
921 - {  
922 - featureType: 'district',  
923 - elementType: 'labels',  
924 - stylers: {  
925 - visibility: 'on',  
926 - },  
927 - },  
928 - {  
929 - featureType: 'poilabel',  
930 - elementType: 'labels.icon',  
931 - stylers: {  
932 - visibility: 'off',  
933 - },  
934 - },  
935 - {  
936 - featureType: 'poilabel',  
937 - elementType: 'labels.text.fill',  
938 - stylers: {  
939 - color: '#2dc4bbff',  
940 - },  
941 - },  
942 - {  
943 - featureType: 'poilabel',  
944 - elementType: 'labels.text.stroke',  
945 - stylers: {  
946 - color: '#ffffff00',  
947 - },  
948 - },  
949 - {  
950 - featureType: 'manmade',  
951 - elementType: 'geometry',  
952 - stylers: {  
953 - color: '#12223dff',  
954 - },  
955 - },  
956 - {  
957 - featureType: 'districtlabel',  
958 - elementType: 'labels.text.stroke',  
959 - stylers: {  
960 - color: '#ffffffff',  
961 - },  
962 - },  
963 - {  
964 - featureType: 'entertainment',  
965 - elementType: 'geometry',  
966 - stylers: {  
967 - color: '#12223dff',  
968 - },  
969 - },  
970 - {  
971 - featureType: 'shopping',  
972 - elementType: 'geometry',  
973 - stylers: {  
974 - color: '#12223dff',  
975 - },  
976 - },  
977 - {  
978 - featureType: 'nationalway',  
979 - stylers: {  
980 - curZoomRegionId: '0',  
981 - curZoomRegion: '6,10',  
982 - level: '6',  
983 - },  
984 - },  
985 - {  
986 - featureType: 'nationalway',  
987 - stylers: {  
988 - curZoomRegionId: '0',  
989 - curZoomRegion: '6,10',  
990 - level: '7',  
991 - },  
992 - },  
993 - {  
994 - featureType: 'nationalway',  
995 - stylers: {  
996 - curZoomRegionId: '0',  
997 - curZoomRegion: '6,10',  
998 - level: '8',  
999 - },  
1000 - },  
1001 - {  
1002 - featureType: 'nationalway',  
1003 - stylers: {  
1004 - curZoomRegionId: '0',  
1005 - curZoomRegion: '6,10',  
1006 - level: '9',  
1007 - },  
1008 - },  
1009 - {  
1010 - featureType: 'nationalway',  
1011 - stylers: {  
1012 - curZoomRegionId: '0',  
1013 - curZoomRegion: '6,10',  
1014 - level: '10',  
1015 - },  
1016 - },  
1017 - {  
1018 - featureType: 'nationalway',  
1019 - elementType: 'geometry',  
1020 - stylers: {  
1021 - visibility: 'off',  
1022 - curZoomRegionId: '0',  
1023 - curZoomRegion: '6,10',  
1024 - level: '6',  
1025 - },  
1026 - },  
1027 - {  
1028 - featureType: 'nationalway',  
1029 - elementType: 'geometry',  
1030 - stylers: {  
1031 - visibility: 'off',  
1032 - curZoomRegionId: '0',  
1033 - curZoomRegion: '6,10',  
1034 - level: '7',  
1035 - },  
1036 - },  
1037 - {  
1038 - featureType: 'nationalway',  
1039 - elementType: 'geometry',  
1040 - stylers: {  
1041 - visibility: 'off',  
1042 - curZoomRegionId: '0',  
1043 - curZoomRegion: '6,10',  
1044 - level: '8',  
1045 - },  
1046 - },  
1047 - {  
1048 - featureType: 'nationalway',  
1049 - elementType: 'geometry',  
1050 - stylers: {  
1051 - visibility: 'off',  
1052 - curZoomRegionId: '0',  
1053 - curZoomRegion: '6,10',  
1054 - level: '9',  
1055 - },  
1056 - },  
1057 - {  
1058 - featureType: 'nationalway',  
1059 - elementType: 'geometry',  
1060 - stylers: {  
1061 - visibility: 'off',  
1062 - curZoomRegionId: '0',  
1063 - curZoomRegion: '6,10',  
1064 - level: '10',  
1065 - },  
1066 - },  
1067 - {  
1068 - featureType: 'nationalway',  
1069 - elementType: 'labels',  
1070 - stylers: {  
1071 - visibility: 'off',  
1072 - curZoomRegionId: '0',  
1073 - curZoomRegion: '6,10',  
1074 - level: '6',  
1075 - },  
1076 - },  
1077 - {  
1078 - featureType: 'nationalway',  
1079 - elementType: 'labels',  
1080 - stylers: {  
1081 - visibility: 'off',  
1082 - curZoomRegionId: '0',  
1083 - curZoomRegion: '6,10',  
1084 - level: '7',  
1085 - },  
1086 - },  
1087 - {  
1088 - featureType: 'nationalway',  
1089 - elementType: 'labels',  
1090 - stylers: {  
1091 - visibility: 'off',  
1092 - curZoomRegionId: '0',  
1093 - curZoomRegion: '6,10',  
1094 - level: '8',  
1095 - },  
1096 - },  
1097 - {  
1098 - featureType: 'nationalway',  
1099 - elementType: 'labels',  
1100 - stylers: {  
1101 - visibility: 'off',  
1102 - curZoomRegionId: '0',  
1103 - curZoomRegion: '6,10',  
1104 - level: '9',  
1105 - },  
1106 - },  
1107 - {  
1108 - featureType: 'nationalway',  
1109 - elementType: 'labels',  
1110 - stylers: {  
1111 - visibility: 'off',  
1112 - curZoomRegionId: '0',  
1113 - curZoomRegion: '6,10',  
1114 - level: '10',  
1115 - },  
1116 - },  
1117 - {  
1118 - featureType: 'cityhighway',  
1119 - stylers: {  
1120 - curZoomRegionId: '0',  
1121 - curZoomRegion: '6,9',  
1122 - level: '6',  
1123 - },  
1124 - },  
1125 - {  
1126 - featureType: 'cityhighway',  
1127 - stylers: {  
1128 - curZoomRegionId: '0',  
1129 - curZoomRegion: '6,9',  
1130 - level: '7',  
1131 - },  
1132 - },  
1133 - {  
1134 - featureType: 'cityhighway',  
1135 - stylers: {  
1136 - curZoomRegionId: '0',  
1137 - curZoomRegion: '6,9',  
1138 - level: '8',  
1139 - },  
1140 - },  
1141 - {  
1142 - featureType: 'cityhighway',  
1143 - stylers: {  
1144 - curZoomRegionId: '0',  
1145 - curZoomRegion: '6,9',  
1146 - level: '9',  
1147 - },  
1148 - },  
1149 - {  
1150 - featureType: 'cityhighway',  
1151 - elementType: 'geometry',  
1152 - stylers: {  
1153 - visibility: 'off',  
1154 - curZoomRegionId: '0',  
1155 - curZoomRegion: '6,9',  
1156 - level: '6',  
1157 - },  
1158 - },  
1159 - {  
1160 - featureType: 'cityhighway',  
1161 - elementType: 'geometry',  
1162 - stylers: {  
1163 - visibility: 'off',  
1164 - curZoomRegionId: '0',  
1165 - curZoomRegion: '6,9',  
1166 - level: '7',  
1167 - },  
1168 - },  
1169 - {  
1170 - featureType: 'cityhighway',  
1171 - elementType: 'geometry',  
1172 - stylers: {  
1173 - visibility: 'off',  
1174 - curZoomRegionId: '0',  
1175 - curZoomRegion: '6,9',  
1176 - level: '8',  
1177 - },  
1178 - },  
1179 - {  
1180 - featureType: 'cityhighway',  
1181 - elementType: 'geometry',  
1182 - stylers: {  
1183 - visibility: 'off',  
1184 - curZoomRegionId: '0',  
1185 - curZoomRegion: '6,9',  
1186 - level: '9',  
1187 - },  
1188 - },  
1189 - {  
1190 - featureType: 'cityhighway',  
1191 - elementType: 'labels',  
1192 - stylers: {  
1193 - visibility: 'off',  
1194 - curZoomRegionId: '0',  
1195 - curZoomRegion: '6,9',  
1196 - level: '6',  
1197 - },  
1198 - },  
1199 - {  
1200 - featureType: 'cityhighway',  
1201 - elementType: 'labels',  
1202 - stylers: {  
1203 - visibility: 'off',  
1204 - curZoomRegionId: '0',  
1205 - curZoomRegion: '6,9',  
1206 - level: '7',  
1207 - },  
1208 - },  
1209 - {  
1210 - featureType: 'cityhighway',  
1211 - elementType: 'labels',  
1212 - stylers: {  
1213 - visibility: 'off',  
1214 - curZoomRegionId: '0',  
1215 - curZoomRegion: '6,9',  
1216 - level: '8',  
1217 - },  
1218 - },  
1219 - {  
1220 - featureType: 'cityhighway',  
1221 - elementType: 'labels',  
1222 - stylers: {  
1223 - visibility: 'off',  
1224 - curZoomRegionId: '0',  
1225 - curZoomRegion: '6,9',  
1226 - level: '9',  
1227 - },  
1228 - },  
1229 - {  
1230 - featureType: 'subwaylabel',  
1231 - elementType: 'labels',  
1232 - stylers: {  
1233 - visibility: 'off',  
1234 - },  
1235 - },  
1236 - {  
1237 - featureType: 'subwaylabel',  
1238 - elementType: 'labels.icon',  
1239 - stylers: {  
1240 - visibility: 'off',  
1241 - },  
1242 - },  
1243 - {  
1244 - featureType: 'tertiarywaysign',  
1245 - elementType: 'labels',  
1246 - stylers: {  
1247 - visibility: 'off',  
1248 - },  
1249 - },  
1250 - {  
1251 - featureType: 'tertiarywaysign',  
1252 - elementType: 'labels.icon',  
1253 - stylers: {  
1254 - visibility: 'off',  
1255 - },  
1256 - },  
1257 - {  
1258 - featureType: 'provincialwaysign',  
1259 - elementType: 'labels',  
1260 - stylers: {  
1261 - visibility: 'off',  
1262 - },  
1263 - },  
1264 - {  
1265 - featureType: 'provincialwaysign',  
1266 - elementType: 'labels.icon',  
1267 - stylers: {  
1268 - visibility: 'off',  
1269 - },  
1270 - },  
1271 - {  
1272 - featureType: 'nationalwaysign',  
1273 - elementType: 'labels',  
1274 - stylers: {  
1275 - visibility: 'off',  
1276 - },  
1277 - },  
1278 - {  
1279 - featureType: 'nationalwaysign',  
1280 - elementType: 'labels.icon',  
1281 - stylers: {  
1282 - visibility: 'off',  
1283 - },  
1284 - },  
1285 - {  
1286 - featureType: 'highwaysign',  
1287 - elementType: 'labels',  
1288 - stylers: {  
1289 - visibility: 'off',  
1290 - },  
1291 - },  
1292 - {  
1293 - featureType: 'highwaysign',  
1294 - elementType: 'labels.icon',  
1295 - stylers: {  
1296 - visibility: 'off',  
1297 - },  
1298 - },  
1299 - {  
1300 - featureType: 'village',  
1301 - elementType: 'labels',  
1302 - stylers: {  
1303 - visibility: 'off',  
1304 - },  
1305 - },  
1306 - {  
1307 - featureType: 'district',  
1308 - elementType: 'labels.text',  
1309 - stylers: {  
1310 - fontsize: 20,  
1311 - },  
1312 - },  
1313 - {  
1314 - featureType: 'district',  
1315 - elementType: 'labels.text.fill',  
1316 - stylers: {  
1317 - color: '#2dc4bbff',  
1318 - },  
1319 - },  
1320 - {  
1321 - featureType: 'district',  
1322 - elementType: 'labels.text.stroke',  
1323 - stylers: {  
1324 - color: '#ffffff00',  
1325 - },  
1326 - },  
1327 - {  
1328 - featureType: 'country',  
1329 - elementType: 'labels.text.fill',  
1330 - stylers: {  
1331 - color: '#2dc4bbff',  
1332 - },  
1333 - },  
1334 - {  
1335 - featureType: 'country',  
1336 - elementType: 'labels.text.stroke',  
1337 - stylers: {  
1338 - color: '#ffffff00',  
1339 - },  
1340 - },  
1341 - {  
1342 - featureType: 'water',  
1343 - elementType: 'labels.text.fill',  
1344 - stylers: {  
1345 - color: '#2dc4bbff',  
1346 - },  
1347 - },  
1348 - {  
1349 - featureType: 'water',  
1350 - elementType: 'labels.text.stroke',  
1351 - stylers: {  
1352 - color: '#ffffff00',  
1353 - },  
1354 - },  
1355 - {  
1356 - featureType: 'cityhighway',  
1357 - elementType: 'geometry.fill',  
1358 - stylers: {  
1359 - color: '#12223dff',  
1360 - },  
1361 - },  
1362 - {  
1363 - featureType: 'cityhighway',  
1364 - elementType: 'geometry.stroke',  
1365 - stylers: {  
1366 - color: '#ffffff00',  
1367 - },  
1368 - },  
1369 - {  
1370 - featureType: 'tertiaryway',  
1371 - elementType: 'geometry.fill',  
1372 - stylers: {  
1373 - color: '#12223dff',  
1374 - },  
1375 - },  
1376 - {  
1377 - featureType: 'tertiaryway',  
1378 - elementType: 'geometry.stroke',  
1379 - stylers: {  
1380 - color: '#ffffff10',  
1381 - },  
1382 - },  
1383 - {  
1384 - featureType: 'provincialway',  
1385 - elementType: 'geometry.fill',  
1386 - stylers: {  
1387 - color: '#12223dff',  
1388 - },  
1389 - },  
1390 - {  
1391 - featureType: 'provincialway',  
1392 - elementType: 'geometry.stroke',  
1393 - stylers: {  
1394 - color: '#ffffff00',  
1395 - },  
1396 - },  
1397 - {  
1398 - featureType: 'nationalway',  
1399 - elementType: 'geometry.fill',  
1400 - stylers: {  
1401 - color: '#12223dff',  
1402 - },  
1403 - },  
1404 - {  
1405 - featureType: 'nationalway',  
1406 - elementType: 'geometry.stroke',  
1407 - stylers: {  
1408 - color: '#ffffff00',  
1409 - },  
1410 - },  
1411 - {  
1412 - featureType: 'highway',  
1413 - elementType: 'labels.text',  
1414 - stylers: {  
1415 - fontsize: 20,  
1416 - },  
1417 - },  
1418 - {  
1419 - featureType: 'nationalway',  
1420 - elementType: 'labels.text.stroke',  
1421 - stylers: {  
1422 - color: '#ffffff00',  
1423 - },  
1424 - },  
1425 - {  
1426 - featureType: 'nationalway',  
1427 - elementType: 'labels.text.fill',  
1428 - stylers: {  
1429 - color: '#12223dff',  
1430 - },  
1431 - },  
1432 - {  
1433 - featureType: 'nationalway',  
1434 - elementType: 'labels.text',  
1435 - stylers: {  
1436 - fontsize: 20,  
1437 - },  
1438 - },  
1439 - {  
1440 - featureType: 'provincialway',  
1441 - elementType: 'labels.text.fill',  
1442 - stylers: {  
1443 - color: '#12223dff',  
1444 - },  
1445 - },  
1446 - {  
1447 - featureType: 'provincialway',  
1448 - elementType: 'labels.text.stroke',  
1449 - stylers: {  
1450 - color: '#ffffff00',  
1451 - },  
1452 - },  
1453 - {  
1454 - featureType: 'provincialway',  
1455 - elementType: 'labels.text',  
1456 - stylers: {  
1457 - fontsize: 20,  
1458 - },  
1459 - },  
1460 - {  
1461 - featureType: 'cityhighway',  
1462 - elementType: 'labels.text.fill',  
1463 - stylers: {  
1464 - color: '#12223dff',  
1465 - },  
1466 - },  
1467 - {  
1468 - featureType: 'cityhighway',  
1469 - elementType: 'labels.text',  
1470 - stylers: {  
1471 - fontsize: 20,  
1472 - },  
1473 - },  
1474 - {  
1475 - featureType: 'cityhighway',  
1476 - elementType: 'labels.text.stroke',  
1477 - stylers: {  
1478 - color: '#ffffff00',  
1479 - },  
1480 - },  
1481 - {  
1482 - featureType: 'estate',  
1483 - elementType: 'geometry',  
1484 - stylers: {  
1485 - color: '#12223dff',  
1486 - },  
1487 - },  
1488 - {  
1489 - featureType: 'tertiaryway',  
1490 - elementType: 'labels.text.fill',  
1491 - stylers: {  
1492 - color: '#2dc4bbff',  
1493 - },  
1494 - },  
1495 - {  
1496 - featureType: 'tertiaryway',  
1497 - elementType: 'labels.text.stroke',  
1498 - stylers: {  
1499 - color: '#ffffff00',  
1500 - },  
1501 - },  
1502 - {  
1503 - featureType: 'fourlevelway',  
1504 - elementType: 'labels.text.fill',  
1505 - stylers: {  
1506 - color: '#2dc4bbff',  
1507 - },  
1508 - },  
1509 - {  
1510 - featureType: 'fourlevelway',  
1511 - elementType: 'labels.text.stroke',  
1512 - stylers: {  
1513 - color: '#ffffff00',  
1514 - },  
1515 - },  
1516 - {  
1517 - featureType: 'scenicspotsway',  
1518 - elementType: 'geometry.fill',  
1519 - stylers: {  
1520 - color: '#12223dff',  
1521 - },  
1522 - },  
1523 - {  
1524 - featureType: 'scenicspotsway',  
1525 - elementType: 'geometry.stroke',  
1526 - stylers: {  
1527 - color: '#ffffff00',  
1528 - },  
1529 - },  
1530 - {  
1531 - featureType: 'universityway',  
1532 - elementType: 'geometry.fill',  
1533 - stylers: {  
1534 - color: '#12223dff',  
1535 - },  
1536 - },  
1537 - {  
1538 - featureType: 'universityway',  
1539 - elementType: 'geometry.stroke',  
1540 - stylers: {  
1541 - color: '#ffffff00',  
1542 - },  
1543 - },  
1544 - {  
1545 - featureType: 'vacationway',  
1546 - elementType: 'geometry.fill',  
1547 - stylers: {  
1548 - color: '#12223dff',  
1549 - },  
1550 - },  
1551 - {  
1552 - featureType: 'vacationway',  
1553 - elementType: 'geometry.stroke',  
1554 - stylers: {  
1555 - color: '#ffffff00',  
1556 - },  
1557 - },  
1558 - {  
1559 - featureType: 'fourlevelway',  
1560 - elementType: 'geometry',  
1561 - stylers: {  
1562 - visibility: 'on',  
1563 - },  
1564 - },  
1565 - {  
1566 - featureType: 'fourlevelway',  
1567 - elementType: 'geometry.fill',  
1568 - stylers: {  
1569 - color: '#12223dff',  
1570 - },  
1571 - },  
1572 - {  
1573 - featureType: 'fourlevelway',  
1574 - elementType: 'geometry.stroke',  
1575 - stylers: {  
1576 - color: '#ffffff00',  
1577 - },  
1578 - },  
1579 - {  
1580 - featureType: 'transportationlabel',  
1581 - elementType: 'labels',  
1582 - stylers: {  
1583 - visibility: 'on',  
1584 - },  
1585 - },  
1586 - {  
1587 - featureType: 'transportationlabel',  
1588 - elementType: 'labels.icon',  
1589 - stylers: {  
1590 - visibility: 'off',  
1591 - },  
1592 - },  
1593 - {  
1594 - featureType: 'transportationlabel',  
1595 - elementType: 'labels.text.fill',  
1596 - stylers: {  
1597 - color: '#2dc4bbff',  
1598 - },  
1599 - },  
1600 - {  
1601 - featureType: 'transportationlabel',  
1602 - elementType: 'labels.text.stroke',  
1603 - stylers: {  
1604 - color: '#ffffff00',  
1605 - },  
1606 - },  
1607 - {  
1608 - featureType: 'educationlabel',  
1609 - elementType: 'labels',  
1610 - stylers: {  
1611 - visibility: 'on',  
1612 - },  
1613 - },  
1614 - {  
1615 - featureType: 'educationlabel',  
1616 - elementType: 'labels.icon',  
1617 - stylers: {  
1618 - visibility: 'off',  
1619 - },  
1620 - },  
1621 - {  
1622 - featureType: 'educationlabel',  
1623 - elementType: 'labels.text.fill',  
1624 - stylers: {  
1625 - color: '#2dc4bbff',  
1626 - },  
1627 - },  
1628 - {  
1629 - featureType: 'educationlabel',  
1630 - elementType: 'labels.text.stroke',  
1631 - stylers: {  
1632 - color: '#ffffff00',  
1633 - },  
1634 - },  
1635 - {  
1636 - featureType: 'transportation',  
1637 - elementType: 'geometry',  
1638 - stylers: {  
1639 - color: '#113549ff',  
1640 - },  
1641 - },  
1642 - {  
1643 - featureType: 'airportlabel',  
1644 - elementType: 'labels.text.fill',  
1645 - stylers: {  
1646 - color: '#2dc4bbff',  
1647 - },  
1648 - },  
1649 - {  
1650 - featureType: 'airportlabel',  
1651 - elementType: 'labels.text.stroke',  
1652 - stylers: {  
1653 - color: '#ffffff00',  
1654 - },  
1655 - },  
1656 - {  
1657 - featureType: 'scenicspotslabel',  
1658 - elementType: 'labels.text.fill',  
1659 - stylers: {  
1660 - color: '#2dc4bbff',  
1661 - },  
1662 - },  
1663 - {  
1664 - featureType: 'scenicspotslabel',  
1665 - elementType: 'labels.text.stroke',  
1666 - stylers: {  
1667 - color: '#ffffff00',  
1668 - },  
1669 - },  
1670 - {  
1671 - featureType: 'medicallabel',  
1672 - elementType: 'labels.text.fill',  
1673 - stylers: {  
1674 - color: '#2dc4bbff',  
1675 - },  
1676 - },  
1677 - {  
1678 - featureType: 'medicallabel',  
1679 - elementType: 'labels.text.stroke',  
1680 - stylers: {  
1681 - color: '#ffffff00',  
1682 - },  
1683 - },  
1684 - {  
1685 - featureType: 'medicallabel',  
1686 - elementType: 'labels.icon',  
1687 - stylers: {  
1688 - visibility: 'off',  
1689 - },  
1690 - },  
1691 - {  
1692 - featureType: 'scenicspotslabel',  
1693 - elementType: 'labels.icon',  
1694 - stylers: {  
1695 - visibility: 'off',  
1696 - },  
1697 - },  
1698 - {  
1699 - featureType: 'airportlabel',  
1700 - elementType: 'labels.icon',  
1701 - stylers: {  
1702 - visibility: 'off',  
1703 - },  
1704 - },  
1705 - {  
1706 - featureType: 'entertainmentlabel',  
1707 - elementType: 'labels.icon',  
1708 - stylers: {  
1709 - visibility: 'off',  
1710 - },  
1711 - },  
1712 - {  
1713 - featureType: 'entertainmentlabel',  
1714 - elementType: 'labels.text.fill',  
1715 - stylers: {  
1716 - color: '#2dc4bbff',  
1717 - },  
1718 - },  
1719 - {  
1720 - featureType: 'entertainmentlabel',  
1721 - elementType: 'labels.text.stroke',  
1722 - stylers: {  
1723 - color: '#ffffff00',  
1724 - },  
1725 - },  
1726 - {  
1727 - featureType: 'estatelabel',  
1728 - elementType: 'labels.icon',  
1729 - stylers: {  
1730 - visibility: 'off',  
1731 - },  
1732 - },  
1733 - {  
1734 - featureType: 'estatelabel',  
1735 - elementType: 'labels.text.fill',  
1736 - stylers: {  
1737 - color: '#2dc4bbff',  
1738 - },  
1739 - },  
1740 - {  
1741 - featureType: 'estatelabel',  
1742 - elementType: 'labels.text.stroke',  
1743 - stylers: {  
1744 - color: '#ffffff00',  
1745 - },  
1746 - },  
1747 - {  
1748 - featureType: 'businesstowerlabel',  
1749 - elementType: 'labels.text.fill',  
1750 - stylers: {  
1751 - color: '#2dc4bbff',  
1752 - },  
1753 - },  
1754 - {  
1755 - featureType: 'businesstowerlabel',  
1756 - elementType: 'labels.text.stroke',  
1757 - stylers: {  
1758 - color: '#ffffff00',  
1759 - },  
1760 - },  
1761 - {  
1762 - featureType: 'businesstowerlabel',  
1763 - elementType: 'labels.icon',  
1764 - stylers: {  
1765 - visibility: 'off',  
1766 - },  
1767 - },  
1768 - {  
1769 - featureType: 'companylabel',  
1770 - elementType: 'labels.text.fill',  
1771 - stylers: {  
1772 - color: '#2dc4bbff',  
1773 - },  
1774 - },  
1775 - {  
1776 - featureType: 'companylabel',  
1777 - elementType: 'labels.text.stroke',  
1778 - stylers: {  
1779 - color: '#ffffff00',  
1780 - },  
1781 - },  
1782 - {  
1783 - featureType: 'companylabel',  
1784 - elementType: 'labels.icon',  
1785 - stylers: {  
1786 - visibility: 'off',  
1787 - },  
1788 - },  
1789 - {  
1790 - featureType: 'governmentlabel',  
1791 - elementType: 'labels.icon',  
1792 - stylers: {  
1793 - visibility: 'off',  
1794 - },  
1795 - },  
1796 - {  
1797 - featureType: 'governmentlabel',  
1798 - elementType: 'labels.text.fill',  
1799 - stylers: {  
1800 - color: '#2dc4bbff',  
1801 - },  
1802 - },  
1803 - {  
1804 - featureType: 'governmentlabel',  
1805 - elementType: 'labels.text.stroke',  
1806 - stylers: {  
1807 - color: '#ffffff00',  
1808 - },  
1809 - },  
1810 - {  
1811 - featureType: 'restaurantlabel',  
1812 - elementType: 'labels.text.fill',  
1813 - stylers: {  
1814 - color: '#2dc4bbff',  
1815 - },  
1816 - },  
1817 - {  
1818 - featureType: 'restaurantlabel',  
1819 - elementType: 'labels.text.stroke',  
1820 - stylers: {  
1821 - color: '#ffffff00',  
1822 - },  
1823 - },  
1824 - {  
1825 - featureType: 'restaurantlabel',  
1826 - elementType: 'labels.icon',  
1827 - stylers: {  
1828 - visibility: 'off',  
1829 - },  
1830 - },  
1831 - {  
1832 - featureType: 'hotellabel',  
1833 - elementType: 'labels.icon',  
1834 - stylers: {  
1835 - visibility: 'off',  
1836 - },  
1837 - },  
1838 - {  
1839 - featureType: 'hotellabel',  
1840 - elementType: 'labels.text.fill',  
1841 - stylers: {  
1842 - color: '#2dc4bbff',  
1843 - },  
1844 - },  
1845 - {  
1846 - featureType: 'hotellabel',  
1847 - elementType: 'labels.text.stroke',  
1848 - stylers: {  
1849 - color: '#ffffff00',  
1850 - },  
1851 - },  
1852 - {  
1853 - featureType: 'shoppinglabel',  
1854 - elementType: 'labels.text.fill',  
1855 - stylers: {  
1856 - color: '#2dc4bbff',  
1857 - },  
1858 - },  
1859 - {  
1860 - featureType: 'shoppinglabel',  
1861 - elementType: 'labels.text.stroke',  
1862 - stylers: {  
1863 - color: '#ffffff00',  
1864 - },  
1865 - },  
1866 - {  
1867 - featureType: 'shoppinglabel',  
1868 - elementType: 'labels.icon',  
1869 - stylers: {  
1870 - visibility: 'off',  
1871 - },  
1872 - },  
1873 - {  
1874 - featureType: 'lifeservicelabel',  
1875 - elementType: 'labels.text.fill',  
1876 - stylers: {  
1877 - color: '#2dc4bbff',  
1878 - },  
1879 - },  
1880 - {  
1881 - featureType: 'lifeservicelabel',  
1882 - elementType: 'labels.text.stroke',  
1883 - stylers: {  
1884 - color: '#ffffff00',  
1885 - },  
1886 - },  
1887 - {  
1888 - featureType: 'lifeservicelabel',  
1889 - elementType: 'labels.icon',  
1890 - stylers: {  
1891 - visibility: 'off',  
1892 - },  
1893 - },  
1894 - {  
1895 - featureType: 'carservicelabel',  
1896 - elementType: 'labels.text.fill',  
1897 - stylers: {  
1898 - color: '#2dc4bbff',  
1899 - },  
1900 - },  
1901 - {  
1902 - featureType: 'carservicelabel',  
1903 - elementType: 'labels.text.stroke',  
1904 - stylers: {  
1905 - color: '#ffffff00',  
1906 - },  
1907 - },  
1908 - {  
1909 - featureType: 'carservicelabel',  
1910 - elementType: 'labels.icon',  
1911 - stylers: {  
1912 - visibility: 'off',  
1913 - },  
1914 - },  
1915 - {  
1916 - featureType: 'financelabel',  
1917 - elementType: 'labels.text.fill',  
1918 - stylers: {  
1919 - color: '#2dc4bbff',  
1920 - },  
1921 - },  
1922 - {  
1923 - featureType: 'financelabel',  
1924 - elementType: 'labels.text.stroke',  
1925 - stylers: {  
1926 - color: '#ffffff00',  
1927 - },  
1928 - },  
1929 - {  
1930 - featureType: 'financelabel',  
1931 - elementType: 'labels.icon',  
1932 - stylers: {  
1933 - visibility: 'off',  
1934 - },  
1935 - },  
1936 - {  
1937 - featureType: 'otherlabel',  
1938 - elementType: 'labels.text.fill',  
1939 - stylers: {  
1940 - color: '#2dc4bbff',  
1941 - },  
1942 - },  
1943 - {  
1944 - featureType: 'otherlabel',  
1945 - elementType: 'labels.text.stroke',  
1946 - stylers: {  
1947 - color: '#ffffff00',  
1948 - },  
1949 - },  
1950 - {  
1951 - featureType: 'otherlabel',  
1952 - elementType: 'labels.icon',  
1953 - stylers: {  
1954 - visibility: 'off',  
1955 - },  
1956 - },  
1957 - {  
1958 - featureType: 'manmade',  
1959 - elementType: 'labels.text.fill',  
1960 - stylers: {  
1961 - color: '#2dc4bbff',  
1962 - },  
1963 - },  
1964 - {  
1965 - featureType: 'manmade',  
1966 - elementType: 'labels.text.stroke',  
1967 - stylers: {  
1968 - color: '#ffffff00',  
1969 - },  
1970 - },  
1971 - {  
1972 - featureType: 'transportation',  
1973 - elementType: 'labels.text.fill',  
1974 - stylers: {  
1975 - color: '#2dc4bbff',  
1976 - },  
1977 - },  
1978 - {  
1979 - featureType: 'transportation',  
1980 - elementType: 'labels.text.stroke',  
1981 - stylers: {  
1982 - color: '#ffffff00',  
1983 - },  
1984 - },  
1985 - {  
1986 - featureType: 'education',  
1987 - elementType: 'labels.text.fill',  
1988 - stylers: {  
1989 - color: '#2dc4bbff',  
1990 - },  
1991 - },  
1992 - {  
1993 - featureType: 'education',  
1994 - elementType: 'labels.text.stroke',  
1995 - stylers: {  
1996 - color: '#ffffff00',  
1997 - },  
1998 - },  
1999 - {  
2000 - featureType: 'medical',  
2001 - elementType: 'labels.text.fill',  
2002 - stylers: {  
2003 - color: '#2dc4bbff',  
2004 - },  
2005 - },  
2006 - {  
2007 - featureType: 'medical',  
2008 - elementType: 'labels.text.stroke',  
2009 - stylers: {  
2010 - color: '#ffffff00',  
2011 - },  
2012 - },  
2013 - {  
2014 - featureType: 'scenicspots',  
2015 - elementType: 'labels.text.fill',  
2016 - stylers: {  
2017 - color: '#2dc4bbff',  
2018 - },  
2019 - },  
2020 - {  
2021 - featureType: 'scenicspots',  
2022 - elementType: 'labels.text.stroke',  
2023 - stylers: {  
2024 - color: '#ffffff00',  
2025 - },  
2026 - },  
2027 - ],  
2028 -};  
1 -import { FormSchema } from '/@/components/Form';  
2 -  
3 -export const scheme: FormSchema[] = [  
4 - // {  
5 - // field: 'effectScope',  
6 - // label: '时间周期',  
7 - // colProps: { span: 24 },  
8 - // component: 'Input',  
9 - // defaultValue: 'effectScope',  
10 - // componentProps: {  
11 - // disabled: true,  
12 - // },  
13 - // },  
14 - {  
15 - field: 'agg',  
16 - label: '聚合方式',  
17 - defaultValue: 'agg',  
18 - colProps: { span: 24 },  
19 - component: 'Input',  
20 - componentProps: {  
21 - disabled: true,  
22 - },  
23 - },  
24 - {  
25 - field: 'interval',  
26 - label: '间隔时间',  
27 - defaultValue: 'interval',  
28 - colProps: { span: 24 },  
29 - component: 'Input',  
30 - componentProps: {  
31 - disabled: true,  
32 - },  
33 - },  
34 -];  
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 -<script setup lang="ts">  
2 - import { BasicForm, useForm } from '/@/components/Form';  
3 - import { scheme } from './config';  
4 -  
5 - defineEmits(['register']);  
6 -  
7 - const [registerForm, { getFieldsValue, setFieldsValue, resetFields }] = useForm({  
8 - schemas: scheme,  
9 - showActionButtonGroup: false,  
10 - });  
11 -  
12 - const getValue = () => {  
13 - return getFieldsValue();  
14 - };  
15 -  
16 - const setValue = (objs) => setFieldsValue(objs);  
17 -  
18 - const resetValue = () => resetFields();  
19 -  
20 - defineExpose({  
21 - getValue,  
22 - setValue,  
23 - resetValue,  
24 - });  
25 -</script>  
26 -  
27 -<template>  
28 - <BasicForm @register="registerForm" />  
29 -</template>  
  1 +<template>
  2 + <div class="flex flex-col justify-between">
  3 + <Tag v-if="scriptType === OnlineEditorTypeEnum.JAVASCRIPT" color="blue" class="tag-text-top">
  4 + <span>function</span>&nbsp;&nbsp;filter(res)&nbsp;&nbsp;{
  5 + </Tag>
  6 + <div class="mt-2 mb-2" ref="aceRef"></div>
  7 + <Tag
  8 + v-if="scriptType === OnlineEditorTypeEnum.JAVASCRIPT"
  9 + color="blue"
  10 + class="mt-2 tag-text-bottom"
  11 + >}</Tag
  12 + >
  13 + <div v-if="scriptType === OnlineEditorTypeEnum.JAVASCRIPT" class="ml-2 -mt-1.5">
  14 + <Button @click="onHandleFormatter" class="mt-8 -ml-2">
  15 + <template #icon>
  16 + <CopyOutlined />
  17 + </template>
  18 + 格式化
  19 + </Button>
  20 + </div>
  21 + </div>
  22 +</template>
  23 +
  24 +<script lang="ts" setup name="aceEditor">
  25 + import { ref, computed, onMounted, nextTick, watch } from 'vue';
  26 + import ace from 'ace-builds';
  27 + import 'ace-builds/src-noconflict/theme-chrome'; // 默认设置的主题
  28 + import 'ace-builds/src-noconflict/theme-terminal'; // 默认设置的主题
  29 + import 'ace-builds/src-noconflict/mode-javascript'; // 默认设置的语言模式javascript
  30 + import 'ace-builds/src-noconflict/snippets/xml'; // 设置xmL
  31 + import { beautify } from 'ace-builds/src-noconflict/ext-beautify.js';
  32 + import { useAppStore } from '/@/store/modules/app';
  33 + import { CopyOutlined } from '@ant-design/icons-vue';
  34 + import { Button, Tag } from 'ant-design-vue';
  35 + import { OnlineEditorTypeEnum } from '../../../config/enum';
  36 +
  37 + const emits = defineEmits(['changeAceContent']);
  38 +
  39 + const props = defineProps({
  40 + restData: {
  41 + type: Object,
  42 + },
  43 + scriptType: {
  44 + type: String,
  45 + default: 'javascript',
  46 + },
  47 + });
  48 +
  49 + const aceEditor = ref();
  50 +
  51 + const aceRef = ref();
  52 +
  53 + const userStore = useAppStore();
  54 +
  55 + const getAceClass = computed((): string => userStore.getDarkMode);
  56 +
  57 + const getRestData: any = ref(null);
  58 +
  59 + watch(
  60 + () => props.restData,
  61 + (newVal) => {
  62 + getRestData.value = newVal;
  63 + onHandleFormatter();
  64 + },
  65 + { deep: true }
  66 + );
  67 +
  68 + // 初始化编辑器
  69 + const initEditor = () => {
  70 + aceEditor.value = ace.edit(aceRef.value, {
  71 + maxLines: 50, // 最大行数,超过会自动出现滚动条
  72 + minLines: props.scriptType === OnlineEditorTypeEnum.JAVASCRIPT ? 36 : 14, // 最小行数,还未到最大行数时,编辑器会自动伸缩大小
  73 + fontSize: 14, // 编辑器内字体大小
  74 + theme: 'ace/theme/chrome', // 默认设置的主题
  75 + mode:
  76 + props.scriptType === OnlineEditorTypeEnum.JAVASCRIPT
  77 + ? 'ace/mode/javascript'
  78 + : 'ace/mode/xml', // 默认设置的语言模式
  79 + tabSize: 2, // 制表符设置为 4 个空格大小
  80 + });
  81 +
  82 + aceEditor.value.setOptions({
  83 + enableBasicAutocompletion: true,
  84 + enableLiveAutocompletion: true,
  85 + enableSnippets: true,
  86 + enableEmmet: true,
  87 + theme: getAceClass.value === 'dark' ? 'ace/theme/terminal' : 'ace/theme/chrome',
  88 + });
  89 + doFilter();
  90 + beautify(aceEditor.value.session);
  91 + };
  92 +
  93 + const doFilter = () => {
  94 + aceEditor.value.getSession().on('change', async () => {
  95 + try {
  96 + await nextTick();
  97 + const jsCode = aceEditor.value.getValue();
  98 + const res = getRestData.value ?? props.restData;
  99 + const fn = new Function('data', 'res', jsCode)(res?.data, res);
  100 + emits('changeAceContent', fn);
  101 + } catch (error) {
  102 + return `过滤函数错误,日志:${error}`;
  103 + }
  104 + });
  105 + };
  106 +
  107 + const onHandleFormatter = () => {
  108 + let oldValue = aceEditor.value?.getValue() || '';
  109 + oldValue = oldValue.replaceAll(/;(\n+)?/g, ';\n');
  110 + aceEditor.value?.setValue(oldValue);
  111 + beautify(aceEditor.value.session);
  112 + };
  113 +
  114 + const getValue = () => {
  115 + return aceEditor?.value?.getValue();
  116 + };
  117 +
  118 + const setValue = (data) => {
  119 + return aceEditor?.value?.setValue(data);
  120 + };
  121 +
  122 + onMounted(() => {
  123 + initEditor();
  124 + });
  125 +
  126 + defineExpose({
  127 + getValue,
  128 + setValue,
  129 + });
  130 +</script>
  131 +
  132 +<style lang="less" scoped>
  133 + .jsoneditor {
  134 + border: none;
  135 + }
  136 +
  137 + .tag-text {
  138 + white-space: normal;
  139 + height: auto;
  140 + }
  141 +
  142 + .tag-text-top {
  143 + width: 8vw;
  144 + &:extend(.tag-text);
  145 + }
  146 +
  147 + .tag-text-bottom {
  148 + width: 1vw;
  149 + &:extend(.tag-text);
  150 + }
  151 +</style>
@@ -8,30 +8,28 @@ @@ -8,30 +8,28 @@
8 </a-radio-group> 8 </a-radio-group>
9 <div class="mt-3"> 9 <div class="mt-3">
10 <a-textarea 10 <a-textarea
11 - v-show="getRequestBody.content.requestParamsBodyType === 'none'" 11 + v-show="getRequestBody.content.requestParamsBodyType === RequestBodyTypeEnum.NONE"
12 disabled 12 disabled
13 placeholder="该接口没有 Body 体" 13 placeholder="该接口没有 Body 体"
14 - :rows="2"  
15 /> 14 />
16 <BodyTable 15 <BodyTable
17 ref="bodyCellFormDataTableRef" 16 ref="bodyCellFormDataTableRef"
18 - v-show="getRequestBody.content.requestParamsBodyType === 'form-data'" 17 + v-show="getRequestBody.content.requestParamsBodyType === RequestBodyTypeEnum.FORMDATA"
19 /> 18 />
20 <BodyTable 19 <BodyTable
21 ref="bodyCellXwwwTableRef" 20 ref="bodyCellXwwwTableRef"
22 - v-show="getRequestBody.content.requestParamsBodyType === 'x-www-form-urlencoded'" 21 + v-show="getRequestBody.content.requestParamsBodyType === RequestBodyTypeEnum.XWWW"
23 /> 22 />
24 <JsonEditor 23 <JsonEditor
25 :showBtn="false" 24 :showBtn="false"
26 - style="width: 35vw; height: 30vh"  
27 - v-show="getRequestBody.content.requestParamsBodyType === 'json'" 25 + style="width: 35vw; height: 25vh"
  26 + v-show="getRequestBody.content.requestParamsBodyType === RequestBodyTypeEnum.JSON"
28 ref="jsonEditorRef" 27 ref="jsonEditorRef"
29 /> 28 />
30 - <a-textarea  
31 - v-model:value="getRequestBody.content.xml"  
32 - v-show="getRequestBody.content.requestParamsBodyType === 'xml'"  
33 - placeholder="请输入xml"  
34 - :rows="6" 29 + <AceTypeXmlEditor
  30 + ref="aceEditorRef"
  31 + v-show="getRequestBody.content.requestParamsBodyType === RequestBodyTypeEnum.XML"
  32 + :scriptType="OnlineEditorTypeEnum.XML"
35 /> 33 />
36 </div> 34 </div>
37 </div> 35 </div>
@@ -39,10 +37,12 @@ @@ -39,10 +37,12 @@
39 <script lang="ts" setup name="body"> 37 <script lang="ts" setup name="body">
40 import { reactive, ref, nextTick } from 'vue'; 38 import { reactive, ref, nextTick } from 'vue';
41 import { RequestBodyTypeEnum } from '../../../config/enum'; 39 import { RequestBodyTypeEnum } from '../../../config/enum';
42 - import BodyTable from './bodyTable.vue'; 40 + import BodyTable from './paramsTable.vue';
43 import { isEmpty } from '/@/utils/is'; 41 import { isEmpty } from '/@/utils/is';
44 import { useUtils } from '../../../hooks/useUtils'; 42 import { useUtils } from '../../../hooks/useUtils';
45 import JsonEditor from './jsonEditor.vue'; 43 import JsonEditor from './jsonEditor.vue';
  44 + import AceTypeXmlEditor from './aceEditor.vue';
  45 + import { OnlineEditorTypeEnum } from '../../../config/enum';
46 46
47 const getRequestBody = reactive({ 47 const getRequestBody = reactive({
48 content: { 48 content: {
@@ -62,6 +62,8 @@ @@ -62,6 +62,8 @@
62 62
63 const jsonEditorRef = ref<InstanceType<typeof JsonEditor>>(); 63 const jsonEditorRef = ref<InstanceType<typeof JsonEditor>>();
64 64
  65 + const aceEditorRef = ref<InstanceType<typeof AceTypeXmlEditor>>();
  66 +
65 const bodyCellXwwwTableRef = ref<InstanceType<typeof BodyTable>>(); 67 const bodyCellXwwwTableRef = ref<InstanceType<typeof BodyTable>>();
66 68
67 const handleChange = ({ target }) => { 69 const handleChange = ({ target }) => {
@@ -76,9 +78,11 @@ @@ -76,9 +78,11 @@
76 const valuesFormData = bodyCellFormDataTableRef.value?.getValue(); 78 const valuesFormData = bodyCellFormDataTableRef.value?.getValue();
77 const valuesXWww = bodyCellXwwwTableRef.value?.getValue(); 79 const valuesXWww = bodyCellXwwwTableRef.value?.getValue();
78 const jsonEditorValue = jsonEditorRef.value?.getJsonValue(); 80 const jsonEditorValue = jsonEditorRef.value?.getJsonValue();
79 - getRequestBody.content['form-data'] = valuesFormData as any;  
80 - getRequestBody.content['x-www-form-urlencoded'] = valuesXWww as any;  
81 - getRequestBody.content['json'] = jsonEditorValue as any; 81 + const xmlEditorValue = aceEditorRef.value?.getValue();
  82 + getRequestBody.content[RequestBodyTypeEnum.FORMDATA] = valuesFormData as any;
  83 + getRequestBody.content[RequestBodyTypeEnum.XWWW] = valuesXWww as any;
  84 + getRequestBody.content[RequestBodyTypeEnum.JSON] = jsonEditorValue as any;
  85 + getRequestBody.content[RequestBodyTypeEnum.XML] = xmlEditorValue as any;
82 if (type === 'none') getRequestBody.content = {} as any; 86 if (type === 'none') getRequestBody.content = {} as any;
83 return getRequestBody.content; 87 return getRequestBody.content;
84 }; 88 };
@@ -90,18 +94,22 @@ @@ -90,18 +94,22 @@
90 getRequestBody.content.requestParamsBodyType = type; 94 getRequestBody.content.requestParamsBodyType = type;
91 await nextTick(); 95 await nextTick();
92 await nextTick(); 96 await nextTick();
93 - bodyCellFormDataTableRef.value?.setValue(isEmpty(data) ? [pushObj] : data['form-data']);  
94 - bodyCellXwwwTableRef.value?.setValue(isEmpty(data) ? [pushObj] : data['x-www-form-urlencoded']); 97 + bodyCellFormDataTableRef.value?.setValue(
  98 + isEmpty(data) ? [pushObj] : data[RequestBodyTypeEnum.FORMDATA]
  99 + );
  100 + bodyCellXwwwTableRef.value?.setValue(
  101 + isEmpty(data) ? [pushObj] : data[RequestBodyTypeEnum.XWWW]
  102 + );
95 jsonEditorRef.value?.setJsonValue(data['json'] || '{}'); 103 jsonEditorRef.value?.setJsonValue(data['json'] || '{}');
96 - getRequestBody.content.xml = data['xml']; 104 + aceEditorRef.value?.setValue(data['xml'] || '');
97 }; 105 };
98 106
99 //重置数据 107 //重置数据
100 const resetValue = () => { 108 const resetValue = () => {
101 for (let i in getRequestBody.content) Reflect.set(getRequestBody.content, i, ''); 109 for (let i in getRequestBody.content) Reflect.set(getRequestBody.content, i, '');
102 - getRequestBody.content['form-data'] = {};  
103 - getRequestBody.content['x-www-form-urlencoded'] = {};  
104 - getRequestBody.content.requestParamsBodyType = 'none'; 110 + getRequestBody.content[RequestBodyTypeEnum.FORMDATA] = {};
  111 + getRequestBody.content[RequestBodyTypeEnum.XWWW] = {};
  112 + getRequestBody.content.requestParamsBodyType = RequestBodyTypeEnum.NONE;
105 nextTick(() => { 113 nextTick(() => {
106 bodyCellFormDataTableRef?.value?.resetValue(); 114 bodyCellFormDataTableRef?.value?.resetValue();
107 bodyCellXwwwTableRef?.value?.resetValue(); 115 bodyCellXwwwTableRef?.value?.resetValue();
1 -<template>  
2 - <div class="table-content">  
3 - <!-- 采用的原生表格 -->  
4 - <table align="center">  
5 - <thead>  
6 - <tr>  
7 - <th v-for="item in editCellTableTHeadConfig" :key="item">{{ item }}</th>  
8 - </tr>  
9 - </thead>  
10 - <tbody>  
11 - <tr v-for="(item, index) in tableArray.content" :key="index">  
12 - <td>  
13 - {{ index + 1 }}  
14 - </td>  
15 - <td style="width: 12vw">  
16 - <Select  
17 - v-model:value="item.key"  
18 - placeholder="请选择"  
19 - :options="selectOptions"  
20 - @change="handleChange"  
21 - @dropdownVisibleChange="hanldeDropdownVisibleChange"  
22 - allowClear  
23 - />  
24 - </td>  
25 - <td style="width: 12vw">  
26 - <div v-if="item.key === 'date_range'">  
27 - <a-input style="width: 6vw" placeholder="请输入" v-model:value="item.date1" />  
28 - <span>~</span>  
29 - <a-input style="width: 6vw" placeholder="请输入" v-model:value="item.date2" />  
30 - </div>  
31 - <div v-else>  
32 - <a-input  
33 - :disabled="item.editDisabled"  
34 - placeholder="请输入"  
35 - v-model:value="item.value"  
36 - />  
37 - </div>  
38 - </td>  
39 - <td style="width: 4vw">  
40 - <a-switch v-model:checked="item.required" />  
41 - </td>  
42 - <td style="width: 4vw">  
43 - <div>  
44 - <Button type="dashed" @click="add(item, index)">  
45 - <template #icon><PlusOutlined /></template  
46 - ></Button>  
47 - <Button type="dashed" style="margin-left: 5px" @click="remove(item, index)">  
48 - <template #icon> <MinusOutlined /></template>  
49 - </Button>  
50 - </div>  
51 - </td>  
52 - </tr>  
53 - </tbody>  
54 - </table>  
55 - </div>  
56 -</template>  
57 -<script lang="ts" setup name="editCellTable">  
58 - import { reactive, ref, onMounted, nextTick } from 'vue';  
59 - import { Select, Button } from 'ant-design-vue';  
60 - import { findDictItemByCode } from '/@/api/system/dict';  
61 - import { PlusOutlined, MinusOutlined } from '@ant-design/icons-vue';  
62 - import { editCellTableTHeadConfig } from '../../../config/config';  
63 - import { selectType, tableItems } from '../../../config/types';  
64 -  
65 - defineProps({  
66 - method: {  
67 - type: String,  
68 - },  
69 - });  
70 -  
71 - const selectOptions = ref<selectType[]>([]);  
72 -  
73 - onMounted(() => {  
74 - getSelectOptions();  
75 - });  
76 -  
77 - const getSelectOptions = async () => {  
78 - const res = await findDictItemByCode({ dictCode: 'dataview_builtin_params' });  
79 - selectOptions.value = res.map((m) => ({ label: m.itemText, value: m.itemValue }));  
80 - selectOptions.value.push({  
81 - label: '自定义',  
82 - value: 'scope',  
83 - });  
84 - };  
85 -  
86 - const tableArray = reactive<{  
87 - content: tableItems[];  
88 - }>({  
89 - content: [  
90 - {  
91 - key: undefined,  
92 - value: '',  
93 - editDisabled: false,  
94 - required: false,  
95 - date1: '',  
96 - date2: '',  
97 - },  
98 - ],  
99 - });  
100 -  
101 - // 新增  
102 - const add = (_, index: number) => {  
103 - tableArray.content.splice(index + 1, 0, {  
104 - key: undefined,  
105 - value: '',  
106 - editDisabled: false,  
107 - required: false,  
108 - date1: '',  
109 - date2: '',  
110 - });  
111 - };  
112 -  
113 - // 减少  
114 - const remove = (item, index: number) => {  
115 - if (tableArray.content.length > 1) {  
116 - selectOptions.value.forEach((ele) => {  
117 - if (ele.value == item.key) {  
118 - ele.disabled = false;  
119 - }  
120 - });  
121 - tableArray.content.splice(index, 1);  
122 - } else {  
123 - resetValue();  
124 - }  
125 - };  
126 -  
127 - const hanldeDropdownVisibleChange = () => handleChange();  
128 -  
129 - //Select互斥  
130 - const handleChange = () => {  
131 - selectOptions.value.forEach((ele) => {  
132 - ele.disabled = false;  
133 - tableArray.content.forEach((element) => {  
134 - if (element.key === 'scope' || element.key === 'fixed_date') {  
135 - element.editDisabled = false;  
136 - } else {  
137 - element.value = '';  
138 - element.editDisabled = true;  
139 - }  
140 - if (element.key === ele.value && element.key !== 'scope' && element.key !== 'fixed_date') {  
141 - ele.disabled = true;  
142 - }  
143 - });  
144 - });  
145 - };  
146 -  
147 - //获取数据  
148 - const getValue = () => {  
149 - const assemblyData = tableArray.content.map((it) => {  
150 - return {  
151 - key: it.key,  
152 - value: it.key === 'date_range' ? `${it.date1},${it.date2}` : it.value,  
153 - editDisabled: it.editDisabled,  
154 - required: it.required,  
155 - };  
156 - });  
157 - return assemblyData;  
158 - };  
159 -  
160 - //设置数据  
161 - const setValue = async (data) => {  
162 - await nextTick();  
163 - const assemblyData = data.map((it) => {  
164 - return {  
165 - key: it.key,  
166 - value: it.value,  
167 - editDisabled: it.editDisabled,  
168 - required: it.required,  
169 - date1: it.key === 'date_range' ? it.value?.split(',')?.at(-2) : '',  
170 - date2: it.key === 'date_range' ? it.value?.split(',')?.at(-1) : '',  
171 - };  
172 - });  
173 - tableArray.content = assemblyData;  
174 - tableArray.content.forEach(() => {  
175 - handleChange();  
176 - });  
177 - };  
178 -  
179 - //重置数据  
180 - const resetValue = () => {  
181 - tableArray.content = [];  
182 - tableArray.content.push({  
183 - key: undefined,  
184 - value: '',  
185 - editDisabled: false,  
186 - required: false,  
187 - date1: '',  
188 - date2: '',  
189 - });  
190 - nextTick(() => {  
191 - tableArray.content.forEach(() => {  
192 - handleChange();  
193 - });  
194 - });  
195 - };  
196 - defineExpose({  
197 - getValue,  
198 - setValue,  
199 - resetValue,  
200 - });  
201 -</script>  
202 -  
203 -<style scoped lang="less">  
204 - @table-color: #e5e7eb;  
205 -  
206 - .table-border-color {  
207 - border: 1px solid #e5e7eb;  
208 - text-align: center;  
209 - }  
210 -  
211 - .table-content {  
212 - overflow-x: auto;  
213 -  
214 - table {  
215 - border-collapse: collapse;  
216 - width: 35vw;  
217 - &:extend(.table-border-color);  
218 - }  
219 -  
220 - table thead {  
221 - white-space: nowrap;  
222 - }  
223 -  
224 - table td {  
225 - padding: 5px;  
226 - white-space: nowrap;  
227 - &:extend(.table-border-color);  
228 - }  
229 -  
230 - table th {  
231 - padding: 5px;  
232 - &:extend(.table-border-color);  
233 - }  
234 - }  
235 -</style>  
@@ -42,43 +42,42 @@ @@ -42,43 +42,42 @@
42 import { PlusOutlined, MinusOutlined } from '@ant-design/icons-vue'; 42 import { PlusOutlined, MinusOutlined } from '@ant-design/icons-vue';
43 import { editTestCellTableTHeaderConfig } from '../../../config/config'; 43 import { editTestCellTableTHeaderConfig } from '../../../config/config';
44 import { tableItems } from '../../../config/types'; 44 import { tableItems } from '../../../config/types';
45 - defineProps({  
46 - method: {  
47 - type: String,  
48 - },  
49 - }); 45 + import { useUtils } from '../../../hooks/useUtils';
  46 +
  47 + const { CommonFuncValue } = useUtils();
50 48
51 const tableArray = reactive<{ 49 const tableArray = reactive<{
52 content: tableItems[]; 50 content: tableItems[];
53 }>({ 51 }>({
54 content: [ 52 content: [
55 { 53 {
56 - key: 'ContentType',  
57 - value: 'none', 54 + key: '',
  55 + value: '',
58 required: false, 56 required: false,
59 }, 57 },
60 ], 58 ],
61 }); 59 });
62 60
63 - // 新增  
64 const add = (_, index: number) => { 61 const add = (_, index: number) => {
65 tableArray.content.splice(index + 1, 0, { 62 tableArray.content.splice(index + 1, 0, {
66 - key: 'ContentType',  
67 - value: 'none', 63 + key: '',
  64 + value: '',
68 required: false, 65 required: false,
69 }); 66 });
70 }; 67 };
71 68
72 - // 减少  
73 const remove = (index: number) => { 69 const remove = (index: number) => {
74 - if (tableArray.content.length !== 1) { 70 + if (tableArray.content.length > 1) {
75 tableArray.content.splice(index, 1); 71 tableArray.content.splice(index, 1);
  72 + } else {
  73 + resetValue();
76 } 74 }
77 }; 75 };
78 76
79 //获取数据 77 //获取数据
80 const getValue = () => { 78 const getValue = () => {
81 - return tableArray.content; 79 + const newFuncValue = new CommonFuncValue(tableArray.content as tableItems[]);
  80 + return newFuncValue.get();
82 }; 81 };
83 82
84 //设置数据 83 //设置数据
@@ -104,35 +103,5 @@ @@ -104,35 +103,5 @@
104 </script> 103 </script>
105 104
106 <style scoped lang="less"> 105 <style scoped lang="less">
107 - @table-color: #e5e7eb;  
108 -  
109 - .table-border-color {  
110 - border: 1px solid #e5e7eb;  
111 - text-align: center;  
112 - }  
113 -  
114 - .table-content {  
115 - overflow-x: auto;  
116 -  
117 - table {  
118 - border-collapse: collapse;  
119 - width: 35vw;  
120 - &:extend(.table-border-color);  
121 - }  
122 -  
123 - table thead {  
124 - white-space: nowrap;  
125 - }  
126 -  
127 - table td {  
128 - padding: 5px;  
129 - white-space: nowrap;  
130 - &:extend(.table-border-color);  
131 - }  
132 -  
133 - table th {  
134 - padding: 5px;  
135 - &:extend(.table-border-color);  
136 - }  
137 - } 106 + @import '../common/commonTable.less';
138 </style> 107 </style>
1 <template> 1 <template>
2 <div class="flex flex-col justify-between"> 2 <div class="flex flex-col justify-between">
3 - <div ref="jsoneditorRef" style="height: 100%; width: 100%"></div> 3 + <div ref="jsoneditorRef" style="height: 100%"></div>
4 <div class="ml-2 -mt-1.5"> 4 <div class="ml-2 -mt-1.5">
5 <Button v-if="showBtn" @click="onHandleCopy" class="mt-8 -ml-2"> 5 <Button v-if="showBtn" @click="onHandleCopy" class="mt-8 -ml-2">
6 <template #icon> 6 <template #icon>
@@ -14,7 +14,6 @@ @@ -14,7 +14,6 @@
14 </td> 14 </td>
15 <td style="width: 12vw"> 15 <td style="width: 12vw">
16 <Select 16 <Select
17 - :disabled="item.key === 'agg,interval' ? true : false"  
18 v-model:value="item.key" 17 v-model:value="item.key"
19 placeholder="请选择" 18 placeholder="请选择"
20 :options="selectOptions" 19 :options="selectOptions"
@@ -23,12 +22,12 @@ @@ -23,12 +22,12 @@
23 allowClear 22 allowClear
24 /> 23 />
25 </td> 24 </td>
26 - <td style="width: 12vw"> 25 + <td>
27 <div v-if="item.key === 'date_range'"> 26 <div v-if="item.key === 'date_range'">
28 - <div>  
29 - <a-input style="width: 6vw" placeholder="请输入" v-model:value="item.date1" /> 27 + <div class="flex">
  28 + <a-input placeholder="请输入" v-model:value="item.date1" />
30 <span>~</span> 29 <span>~</span>
31 - <a-input style="width: 6vw" placeholder="请输入" v-model:value="item.date2" /> 30 + <a-input placeholder="请输入" v-model:value="item.date2" />
32 </div> 31 </div>
33 <div class="flex mt-2"> 32 <div class="flex mt-2">
34 <a-checkbox @change="onHandleCheck" v-model:checked="mores">更多选项</a-checkbox> 33 <a-checkbox @change="onHandleCheck" v-model:checked="mores">更多选项</a-checkbox>
@@ -43,15 +42,15 @@ @@ -43,15 +42,15 @@
43 /> 42 />
44 </div> 43 </div>
45 </td> 44 </td>
46 - <td style="width: 4vw"> 45 + <td>
47 <a-switch v-model:checked="item.required" /> 46 <a-switch v-model:checked="item.required" />
48 </td> 47 </td>
49 - <td style="width: 4vw"> 48 + <td>
50 <div> 49 <div>
51 <Button type="dashed" @click="add(item, index)"> 50 <Button type="dashed" @click="add(item, index)">
52 <template #icon><PlusOutlined /></template 51 <template #icon><PlusOutlined /></template
53 ></Button> 52 ></Button>
54 - <Button type="dashed" style="margin-left: 5px" @click="remove(item, index)"> 53 + <Button type="dashed" class="ml-1" @click="remove(item, index)">
55 <template #icon> <MinusOutlined /></template> 54 <template #icon> <MinusOutlined /></template>
56 </Button> 55 </Button>
57 </div> 56 </div>
@@ -60,18 +59,6 @@ @@ -60,18 +59,6 @@
60 </tbody> 59 </tbody>
61 </table> 60 </table>
62 </div> 61 </div>
63 - <BasicModal  
64 - @register="registerModal"  
65 - title=""  
66 - width="40%"  
67 - :minHeight="90"  
68 - wrap-class-name="history-trend-model"  
69 - :canFullscreen="false"  
70 - @cancel="handleCancelModal"  
71 - @ok="onHandleModal"  
72 - >  
73 - <DateRangeSelect ref="dateRangeSelectRef" />  
74 - </BasicModal>  
75 </template> 62 </template>
76 <script lang="ts" setup name="editCellTable"> 63 <script lang="ts" setup name="editCellTable">
77 import { reactive, ref, onMounted, nextTick } from 'vue'; 64 import { reactive, ref, onMounted, nextTick } from 'vue';
@@ -80,42 +67,16 @@ @@ -80,42 +67,16 @@
80 import { PlusOutlined, MinusOutlined } from '@ant-design/icons-vue'; 67 import { PlusOutlined, MinusOutlined } from '@ant-design/icons-vue';
81 import { editCellTableTHeadConfig } from '../../../config/config'; 68 import { editCellTableTHeadConfig } from '../../../config/config';
82 import { selectType, tableItems } from '../../../config/types'; 69 import { selectType, tableItems } from '../../../config/types';
83 - import { useModal, BasicModal } from '/@/components/Modal';  
84 - import DateRangeSelect from './DateRangeSelect/index.vue'; 70 + import { useUtils } from '../../../hooks/useUtils';
85 71
86 - defineProps({  
87 - method: {  
88 - type: String,  
89 - },  
90 - }); 72 + const { ParamsFuncValue } = useUtils();
91 73
92 const selectOptions = ref<selectType[]>([]); 74 const selectOptions = ref<selectType[]>([]);
93 75
94 - const dateRangeSelectRef = ref<InstanceType<typeof DateRangeSelect>>();  
95 -  
96 - const [registerModal, { closeModal }] = useModal();  
97 -  
98 const mores = ref(false); 76 const mores = ref(false);
99 77
100 const onHandleCheck = ({ target }) => { 78 const onHandleCheck = ({ target }) => {
101 mores.value = target?.checked; 79 mores.value = target?.checked;
102 - if (mores.value) {  
103 - // openModal(true);  
104 - }  
105 - };  
106 -  
107 - const handleCancelModal = () => {  
108 - closeModal();  
109 - dateRangeSelectRef.value?.resetValue();  
110 - mores.value = false;  
111 - };  
112 -  
113 - const getDateRangeValue = ref<any>({});  
114 -  
115 - const onHandleModal = () => {  
116 - const values = dateRangeSelectRef.value?.getValue();  
117 - getDateRangeValue.value = values;  
118 - closeModal();  
119 }; 80 };
120 81
121 onMounted(() => { 82 onMounted(() => {
@@ -146,7 +107,6 @@ @@ -146,7 +107,6 @@
146 ], 107 ],
147 }); 108 });
148 109
149 - // 新增  
150 const add = (_, index: number) => { 110 const add = (_, index: number) => {
151 tableArray.content.splice(index + 1, 0, { 111 tableArray.content.splice(index + 1, 0, {
152 key: undefined, 112 key: undefined,
@@ -158,7 +118,6 @@ @@ -158,7 +118,6 @@
158 }); 118 });
159 }; 119 };
160 120
161 - // 减少  
162 const remove = (item, index: number) => { 121 const remove = (item, index: number) => {
163 if (tableArray.content.length > 1) { 122 if (tableArray.content.length > 1) {
164 selectOptions.value.forEach((ele) => { 123 selectOptions.value.forEach((ele) => {
@@ -177,44 +136,34 @@ @@ -177,44 +136,34 @@
177 selectOptions.value.forEach((ele) => { 136 selectOptions.value.forEach((ele) => {
178 ele.disabled = false; 137 ele.disabled = false;
179 tableArray.content.forEach((element) => { 138 tableArray.content.forEach((element) => {
180 - if (element.key === 'scope' || element.key === 'fixed_date') { 139 + if (element.key === 'scope') {
181 element.editDisabled = false; 140 element.editDisabled = false;
182 } else { 141 } else {
183 element.value = ''; 142 element.value = '';
184 element.editDisabled = true; 143 element.editDisabled = true;
185 } 144 }
186 - if (element.key === ele.value && element.key !== 'scope' && element.key !== 'fixed_date') { 145 + if (element.key === ele.value && element.key !== 'scope') {
187 ele.disabled = true; 146 ele.disabled = true;
188 } 147 }
189 }); 148 });
190 }); 149 });
191 }; 150 };
192 151
  152 + //fix 解决编辑回显下拉框已选择应禁用问题
193 const hanldeDropdownVisibleChange = () => handleChange(); 153 const hanldeDropdownVisibleChange = () => handleChange();
194 154
  155 + const commonHandleChange = (tableArray) => {
  156 + nextTick(() => {
  157 + tableArray.forEach(() => {
  158 + handleChange();
  159 + });
  160 + });
  161 + };
  162 +
195 //获取数据 163 //获取数据
196 const getValue = () => { 164 const getValue = () => {
197 - let assemblyData: any = tableArray.content.map((it) => {  
198 - return {  
199 - key: it.key,  
200 - value: it.key === 'date_range' ? `${it.date1},${it.date2}` : it.value,  
201 - mores: it.key === 'date_range' ? mores.value : null,  
202 - editDisabled: it.editDisabled,  
203 - required: it.required,  
204 - };  
205 - });  
206 - // assemblyData = assemblyData.filter((item) => item.key !== 'agg,interval');  
207 - // if (getDateRangeValue.value) {  
208 - // const joinStr = Object.keys(getDateRangeValue.value)?.join(',');  
209 - // if (mores.value) {  
210 - // assemblyData.push({  
211 - // key: joinStr,  
212 - // value: '',  
213 - // mores: mores.value,  
214 - // });  
215 - // }  
216 - // }  
217 - return assemblyData; 165 + const paramsFuncValue = new ParamsFuncValue(tableArray.content as any, mores.value);
  166 + return paramsFuncValue.get();
218 }; 167 };
219 168
220 //设置数据 169 //设置数据
@@ -233,17 +182,11 @@ @@ -233,17 +182,11 @@
233 const findIsDateRange = data.find((it) => it?.mores === true); 182 const findIsDateRange = data.find((it) => it?.mores === true);
234 if (findIsDateRange?.mores) { 183 if (findIsDateRange?.mores) {
235 mores.value = findIsDateRange?.mores; 184 mores.value = findIsDateRange?.mores;
236 - getDateRangeValue.value = {  
237 - agg: 'agg',  
238 - interval: 'interval',  
239 - };  
240 } else { 185 } else {
241 assemblyData = assemblyData.filter((item) => item?.mores == false || !item?.mores); 186 assemblyData = assemblyData.filter((item) => item?.mores == false || !item?.mores);
242 } 187 }
243 tableArray.content = assemblyData; 188 tableArray.content = assemblyData;
244 - tableArray.content.forEach(() => {  
245 - handleChange();  
246 - }); 189 + commonHandleChange(tableArray.content);
247 }; 190 };
248 191
249 //重置数据 192 //重置数据
@@ -258,11 +201,7 @@ @@ -258,11 +201,7 @@
258 date1: '', 201 date1: '',
259 date2: '', 202 date2: '',
260 }); 203 });
261 - nextTick(() => {  
262 - tableArray.content.forEach(() => {  
263 - handleChange();  
264 - });  
265 - }); 204 + commonHandleChange(tableArray.content);
266 }; 205 };
267 defineExpose({ 206 defineExpose({
268 getValue, 207 getValue,
@@ -272,35 +211,5 @@ @@ -272,35 +211,5 @@
272 </script> 211 </script>
273 212
274 <style scoped lang="less"> 213 <style scoped lang="less">
275 - @table-color: #e5e7eb;  
276 -  
277 - .table-border-color {  
278 - border: 1px solid #e5e7eb;  
279 - text-align: center;  
280 - }  
281 -  
282 - .table-content {  
283 - overflow-x: auto;  
284 -  
285 - table {  
286 - border-collapse: collapse;  
287 - width: 35vw;  
288 - &:extend(.table-border-color);  
289 - }  
290 -  
291 - table thead {  
292 - white-space: nowrap;  
293 - }  
294 -  
295 - table td {  
296 - padding: 5px;  
297 - white-space: nowrap;  
298 - &:extend(.table-border-color);  
299 - }  
300 -  
301 - table th {  
302 - padding: 5px;  
303 - &:extend(.table-border-color);  
304 - }  
305 - } 214 + @import '../common/commonTable.less';
306 </style> 215 </style>
1 <template> 1 <template>
2 <div> 2 <div>
3 - <!--TODO: 待优化三者共存下的测试和是否能复用表格 -->  
4 - <Tabs @change="handleChange" v-model:activeKey="activeKey">  
5 - <TabPane class="tab-pane" forceRender key="Params" tab="Params">  
6 - <ParamsTable ref="paramsCellTableRef" :method="method" />  
7 - <ParamsTest  
8 - @testParamsInterface="handleTestParamsInterface"  
9 - @closeTest="onCloseTest"  
10 - ref="testParamsRequestRef"  
11 - :data="dataMap.mapParamsObj"  
12 - :interfaceType="interfaceType"  
13 - />  
14 - </TabPane>  
15 - <TabPane  
16 - v-if="method !== '2' && requestTypeAndUrl?.requestHttpType !== 'GET'"  
17 - class="tab-pane"  
18 - forceRender  
19 - key="Body"  
20 - tab="Body"  
21 - >  
22 - <Body ref="bodyRef" @resetValue="handleResetValue" />  
23 - <BodyTest  
24 - v-if="bodyType !== 'none'"  
25 - @testBodyInterface="handleTestBodyInterface"  
26 - @closeTest="onCloseTest"  
27 - ref="testBodyRequestRef"  
28 - :interfaceType="interfaceType"  
29 - :data="dataMap.mapBodyObj"  
30 - />  
31 - </TabPane>  
32 - <TabPane v-if="method !== '2'" class="tab-pane" forceRender key="Header" tab="Header">  
33 - <HeaderTable ref="editHeaderCellTableRef" :method="method" />  
34 - <HeaderTest  
35 - @testHeaderInterface="handleTestHeaderInterface"  
36 - @closeTest="onCloseTest"  
37 - ref="testHeaderRequestRef"  
38 - :interfaceType="interfaceType"  
39 - :data="dataMap.mapHeaderObj"  
40 - />  
41 - </TabPane>  
42 - </Tabs>  
43 - <ExcuteTest ref="excuteTestRef" @emitExcute="handleEmitExcute" :data="excuteData" /> 3 + <div>
  4 + <Tabs @change="handleChange" v-model:activeKey="activeKey">
  5 + <TabPane class="tab-pane" forceRender key="Params" tab="Params">
  6 + <ParamsTable ref="paramsCellTableRef" />
  7 + <ParamsTest
  8 + @testParamsInterface="handleTestParamsInterface"
  9 + @closeTest="onCloseTest"
  10 + ref="testParamsRequestRef"
  11 + :data="dataMap.mapParamsObj"
  12 + :interfaceType="interfaceType"
  13 + />
  14 + </TabPane>
  15 + <TabPane
  16 + v-if="
  17 + method !== RequestMethodTypeEnum.WEBSOCKET &&
  18 + requestTypeAndUrl?.requestHttpType !== RequestHttpTypeEnum.GET
  19 + "
  20 + class="tab-pane"
  21 + forceRender
  22 + key="Body"
  23 + tab="Body"
  24 + >
  25 + <Body ref="bodyRef" @resetValue="handleResetValue" />
  26 + <BodyTest
  27 + v-if="bodyType !== RequestBodyTypeEnum.NONE"
  28 + @testBodyInterface="handleTestBodyInterface"
  29 + @closeTest="onCloseTest"
  30 + ref="testBodyRequestRef"
  31 + :interfaceType="interfaceType"
  32 + :data="dataMap.mapBodyObj"
  33 + />
  34 + </TabPane>
  35 + <TabPane
  36 + v-if="method !== RequestMethodTypeEnum.WEBSOCKET"
  37 + class="tab-pane"
  38 + forceRender
  39 + key="Header"
  40 + tab="Header"
  41 + >
  42 + <HeaderTable ref="editHeaderCellTableRef" />
  43 + <HeaderTest
  44 + @testHeaderInterface="handleTestHeaderInterface"
  45 + @closeTest="onCloseTest"
  46 + ref="testHeaderRequestRef"
  47 + :interfaceType="interfaceType"
  48 + :data="dataMap.mapHeaderObj"
  49 + />
  50 + </TabPane>
  51 + </Tabs>
  52 + </div>
  53 + <div>
  54 + <ExcuteTest
  55 + ref="excuteTestRef"
  56 + @emitExcute="handleEmitExcute"
  57 + :data="excuteData"
  58 + :method="method"
  59 + :httpType="requestTypeAndUrl?.requestHttpType"
  60 + />
  61 + </div>
44 </div> 62 </div>
45 </template> 63 </template>
46 <script lang="ts" setup name="simpleRequest"> 64 <script lang="ts" setup name="simpleRequest">
@@ -53,6 +71,12 @@ @@ -53,6 +71,12 @@
53 import { isEmpty } from '/@/utils/is'; 71 import { isEmpty } from '/@/utils/is';
54 import { useUtils } from '../../hooks/useUtils'; 72 import { useUtils } from '../../hooks/useUtils';
55 import ExcuteTest from '../TestInterface/components/excuteTest.vue'; 73 import ExcuteTest from '../TestInterface/components/excuteTest.vue';
  74 + import {
  75 + RequestMethodTypeEnum,
  76 + RequestHttpTypeEnum,
  77 + RequestBodyTypeEnum,
  78 + RequestOriginTypeEnum,
  79 + } from '../../config/enum';
56 80
57 const props = defineProps({ 81 const props = defineProps({
58 method: { 82 method: {
@@ -127,18 +151,18 @@ @@ -127,18 +151,18 @@
127 151
128 const handleEmitExcute = () => { 152 const handleEmitExcute = () => {
129 let apiGetUrl = ''; 153 let apiGetUrl = '';
130 - if (props?.method === '2') {  
131 - if (props?.originUrlType === 'server_url') { 154 + if (props?.method === RequestMethodTypeEnum.WEBSOCKET) {
  155 + if (props?.originUrlType === RequestOriginTypeEnum.SERVER_URL) {
132 const pathUrl = window.location.host; 156 const pathUrl = window.location.host;
133 const protocol = window.location.protocol; 157 const protocol = window.location.protocol;
134 apiGetUrl = `${ 158 apiGetUrl = `${
135 - protocol === 'http' ? 'ws:' : protocol === 'https' ? 'wss:' : 'ws:' 159 + protocol === 'http:' ? 'ws:' : protocol === 'https:' ? 'wss:' : 'ws:'
136 }//${pathUrl}${props?.requestTypeAndUrl?.requestUrl}`; 160 }//${pathUrl}${props?.requestTypeAndUrl?.requestUrl}`;
137 } else { 161 } else {
138 apiGetUrl = `${props?.requestOriginUrl}${props?.requestTypeAndUrl?.requestUrl}`; 162 apiGetUrl = `${props?.requestOriginUrl}${props?.requestTypeAndUrl?.requestUrl}`;
139 } 163 }
140 } else { 164 } else {
141 - if (props?.originUrlType === 'server_url') { 165 + if (props?.originUrlType === RequestOriginTypeEnum.SERVER_URL) {
142 const pathUrl = window.location.host; 166 const pathUrl = window.location.host;
143 const protocol = window.location.protocol; 167 const protocol = window.location.protocol;
144 apiGetUrl = `${protocol}//${pathUrl}${props?.requestTypeAndUrl?.requestUrl}`; 168 apiGetUrl = `${protocol}//${pathUrl}${props?.requestTypeAndUrl?.requestUrl}`;
@@ -215,6 +239,11 @@ @@ -215,6 +239,11 @@
215 }; 239 };
216 }; 240 };
217 241
  242 + //获取编写过滤器里的数
  243 + const getFilterValue = () => {
  244 + return excuteTestRef?.value?.getFilterValue();
  245 + };
  246 +
218 //设置数据 247 //设置数据
219 const setValue = (data, flag, defaultValue) => { 248 const setValue = (data, flag, defaultValue) => {
220 if (!flag) { 249 if (!flag) {
@@ -247,6 +276,7 @@ @@ -247,6 +276,7 @@
247 getValue, 276 getValue,
248 setValue, 277 setValue,
249 resetValue, 278 resetValue,
  279 + getFilterValue,
250 }); 280 });
251 </script> 281 </script>
252 282
@@ -2,28 +2,10 @@ @@ -2,28 +2,10 @@
2 <div> 2 <div>
3 <div class="mt-8"> 3 <div class="mt-8">
4 <div class="flex"> 4 <div class="flex">
5 - <div class="flex" v-if="interfaceType === 'SYSTEM' && isAdmin(role)">  
6 - <Select  
7 - v-model:value="selectTenant"  
8 - allowClear  
9 - @change="onSelect"  
10 - style="width: 150px"  
11 - placeholder="请选择租户"  
12 - :options="selectOptions"  
13 - />  
14 - <Select  
15 - v-model:value="selectSysTenant"  
16 - allowClear  
17 - @change="onSelctTenant"  
18 - style="width: 150px; margin-left: 10px"  
19 - v-if="selectTenantOptions.length > 0"  
20 - placeholder="请选择租户"  
21 - :options="selectTenantOptions"  
22 - />  
23 - </div> 5 + <SelectTenant :interfaceType="interfaceType" @emitToken="onHandleEmitToken" />
  6 + <div v-if="role === 'SYS_ADMIN'" class="ml-2"></div>
24 <Button 7 <Button
25 :disabled="interfaceType === 'SYSTEM' && isAdmin(role) ? testDisabled : false" 8 :disabled="interfaceType === 'SYSTEM' && isAdmin(role) ? testDisabled : false"
26 - class="ml-2"  
27 @click="handleTest(isSingleClickText)" 9 @click="handleTest(isSingleClickText)"
28 type="primary" 10 type="primary"
29 >{{ `${isSingleClickText === 'open' ? '打开' : '关闭'}测试接口` }} 11 >{{ `${isSingleClickText === 'open' ? '打开' : '关闭'}测试接口` }}
@@ -33,37 +15,44 @@ @@ -33,37 +15,44 @@
33 <a-row type="flex" justify="center"> 15 <a-row type="flex" justify="center">
34 <a-col :span="3"> 参数设置 </a-col> 16 <a-col :span="3"> 参数设置 </a-col>
35 <a-col :span="21"> 17 <a-col :span="21">
36 - <div v-if="data?.type === 'x-www-form-urlencoded' || data?.type === 'form-data'"> 18 + <div
  19 + v-if="
  20 + data?.type === RequestBodyTypeEnum.XWWW ||
  21 + data?.type === RequestBodyTypeEnum.FORMDATA
  22 + "
  23 + >
37 <TestBodyCellTable :token="getToken" ref="testEditCellTableRef" /> 24 <TestBodyCellTable :token="getToken" ref="testEditCellTableRef" />
38 </div> 25 </div>
39 - <div style="width: 30vw" v-else-if="data?.type === 'json'"> 26 + <div style="width: 30vw" v-else-if="data?.type === RequestBodyTypeEnum.JSON">
40 <JsonEditor :showBtn="false" style="width: 35vw; height: 30vh" ref="jsonEditorRef" /> 27 <JsonEditor :showBtn="false" style="width: 35vw; height: 30vh" ref="jsonEditorRef" />
41 </div> 28 </div>
42 - <div style="width: 30vw" v-else-if="data?.type === 'xml'">  
43 - <a-textarea v-model:value="xmlContent" placeholder="请输入xml" :rows="6" /> 29 + <div style="width: 30vw" v-else-if="data?.type === RequestBodyTypeEnum.XML">
  30 + <AceTypeXmlEditor ref="aceEditorRef" :scriptType="OnlineEditorTypeEnum.XML" />
44 </div> 31 </div>
45 </a-col> 32 </a-col>
46 </a-row> 33 </a-row>
47 </div> 34 </div>
48 </div> 35 </div>
49 - <div class="mt-8"> </div>  
50 </div> 36 </div>
51 </template> 37 </template>
52 <script lang="ts" setup name="testRequest"> 38 <script lang="ts" setup name="testRequest">
53 - import { ref, nextTick, onMounted } from 'vue'; 39 + import { ref, nextTick } from 'vue';
54 import { Button } from 'ant-design-vue'; 40 import { Button } from 'ant-design-vue';
55 - import TestBodyCellTable from './testEditBodyCellTable.vue'; 41 + import TestBodyCellTable from '../paramsTest/testEditParamsCellTable.vue';
56 import moment from 'moment'; 42 import moment from 'moment';
57 import { useUtils } from '../../../hooks/useUtils'; 43 import { useUtils } from '../../../hooks/useUtils';
58 import JsonEditor from '../../SimpleRequest/components/jsonEditor.vue'; 44 import JsonEditor from '../../SimpleRequest/components/jsonEditor.vue';
59 import { useMessage } from '/@/hooks/web/useMessage'; 45 import { useMessage } from '/@/hooks/web/useMessage';
60 - import { getTenantAllPageLists, getTenantPageList } from '/@/api/tenant/tenantApi';  
61 - import { selectType } from '../../../config/types';  
62 - import { Select } from 'ant-design-vue';  
63 - import { getUserToken } from '/@/api/sys/user';  
64 import { USER_INFO_KEY } from '/@/enums/cacheEnum'; 46 import { USER_INFO_KEY } from '/@/enums/cacheEnum';
65 import { getAuthCache } from '/@/utils/auth'; 47 import { getAuthCache } from '/@/utils/auth';
66 import { isAdmin } from '/@/enums/roleEnum'; 48 import { isAdmin } from '/@/enums/roleEnum';
  49 + import AceTypeXmlEditor from '../../SimpleRequest/components/aceEditor.vue';
  50 + import {
  51 + OnlineEditorTypeEnum,
  52 + RequestBodyTypeEnum,
  53 + TableDefaultTypeEnum,
  54 + } from '../../../config/enum';
  55 + import SelectTenant from '../components/selectTenant.vue';
67 56
68 const userInfo: any = getAuthCache(USER_INFO_KEY); 57 const userInfo: any = getAuthCache(USER_INFO_KEY);
69 58
@@ -80,21 +69,6 @@ @@ -80,21 +69,6 @@
80 }, 69 },
81 }); 70 });
82 71
83 - onMounted(async () => {  
84 - if (isAdmin(role)) {  
85 - const res = await getTenantPageList();  
86 - selectOptions.value = res.map((m) => ({ label: m.name, value: m.tenantId }));  
87 - } else {  
88 - //租户  
89 - const { token } = await getUserToken(userInfo?.userId);  
90 - getToken.value = token;  
91 - }  
92 - });  
93 -  
94 - const selectOptions = ref<selectType[]>([]);  
95 -  
96 - const selectTenantOptions = ref<selectType[]>([]);  
97 -  
98 const { createMessage } = useMessage(); 72 const { createMessage } = useMessage();
99 73
100 const showTestEditCell = ref(false); 74 const showTestEditCell = ref(false);
@@ -103,52 +77,26 @@ @@ -103,52 +77,26 @@
103 77
104 const excuteData = ref({}); 78 const excuteData = ref({});
105 79
106 - const selectTenant = ref(undefined);  
107 -  
108 - const selectSysTenant = ref(undefined);  
109 -  
110 - const xmlContent = ref('');  
111 -  
112 const testEditCellTableRef = ref<InstanceType<typeof TestBodyCellTable>>(); 80 const testEditCellTableRef = ref<InstanceType<typeof TestBodyCellTable>>();
113 81
114 const jsonEditorRef = ref<InstanceType<typeof JsonEditor>>(); 82 const jsonEditorRef = ref<InstanceType<typeof JsonEditor>>();
115 83
  84 + const aceEditorRef = ref<InstanceType<typeof AceTypeXmlEditor>>();
  85 +
116 const testResult = ref(''); 86 const testResult = ref('');
117 87
118 const { getMultipleKeys } = useUtils(); 88 const { getMultipleKeys } = useUtils();
119 89
120 const getToken = ref(''); 90 const getToken = ref('');
121 91
122 - const onSelect = async (e) => {  
123 - if (e) {  
124 - testDisabled.value = false;  
125 - } else {  
126 - testDisabled.value = true;  
127 - }  
128 - selectSysTenant.value = undefined;  
129 - const rest = (await getTenantAllPageLists(e)) as any;  
130 - selectTenantOptions.value = rest?.map((m) => ({ label: m.realName, value: m.id }));  
131 - }; 92 + const isSingleClickText = ref('open');
132 93
133 - const onSelctTenant = async (e) => {  
134 - if (e) {  
135 - testDisabled.value = false;  
136 - } else {  
137 - testDisabled.value = true;  
138 - }  
139 - const { token } = await getUserToken(e); 94 + const onHandleEmitToken = (token, flag) => {
140 getToken.value = token; 95 getToken.value = token;
  96 + testDisabled.value = flag;
141 }; 97 };
142 98
143 - const isSingleClickText = ref('open');  
144 -  
145 const handleTest = (o) => { 99 const handleTest = (o) => {
146 - if (isAdmin(role)) {  
147 - if (!selectTenant.value || !selectSysTenant.value) {  
148 - createMessage.error('请选择租户或者租户管理员');  
149 - throw Error('请选择租户或者租户管理员');  
150 - }  
151 - }  
152 if (o === 'open') { 100 if (o === 'open') {
153 showTestEditCell.value = true; 101 showTestEditCell.value = true;
154 emits('testBodyInterface'); 102 emits('testBodyInterface');
@@ -163,8 +111,10 @@ @@ -163,8 +111,10 @@
163 const getValue = async () => { 111 const getValue = async () => {
164 await nextTick(); 112 await nextTick();
165 await nextTick(() => { 113 await nextTick(() => {
166 - console.log(props.data?.list);  
167 - if (props.data?.type === 'x-www-form-urlencoded' || props.data?.type === 'form-data') { 114 + if (
  115 + props.data?.type === RequestBodyTypeEnum.XWWW ||
  116 + props.data?.type === RequestBodyTypeEnum.FORMDATA
  117 + ) {
168 const getSingleKey = props.data?.list; 118 const getSingleKey = props.data?.list;
169 const getMuteKey = props.data?.list?.filter((it: any) => it.key.split(',').length > 1); 119 const getMuteKey = props.data?.list?.filter((it: any) => it.key.split(',').length > 1);
170 const getMuteKeys = getMultipleKeys(getMuteKey); 120 const getMuteKeys = getMultipleKeys(getMuteKey);
@@ -172,10 +122,10 @@ @@ -172,10 +122,10 @@
172 (it: any) => it.key.split(',').length === 1 122 (it: any) => it.key.split(',').length === 1
173 ); 123 );
174 testEditCellTableRef.value?.setTableArray(mergeKeys); 124 testEditCellTableRef.value?.setTableArray(mergeKeys);
175 - } else if (props.data?.type === 'json') { 125 + } else if (props.data?.type === RequestBodyTypeEnum.JSON) {
176 jsonEditorRef.value?.setJsonValue(props.data?.list); 126 jsonEditorRef.value?.setJsonValue(props.data?.list);
177 - } else if (props.data?.type === 'xml') {  
178 - xmlContent.value = props.data?.list; 127 + } else if (props.data?.type === RequestBodyTypeEnum.XML) {
  128 + aceEditorRef?.value?.setValue(props.data?.list);
179 } 129 }
180 }); 130 });
181 }; 131 };
@@ -186,8 +136,9 @@ @@ -186,8 +136,9 @@
186 //把日期拆分成多个 136 //把日期拆分成多个
187 const keyValueList: any = []; 137 const keyValueList: any = [];
188 testEditCellTableRef.value?.getValue()?.forEach((item: any) => { 138 testEditCellTableRef.value?.getValue()?.forEach((item: any) => {
189 - const splitDateKey = item?.key === 'date_range' ? item?.value?.split(',') : [];  
190 - const splitDateValue = item?.key === 'date_range' ? item?.dateValue : []; 139 + const splitDateKey =
  140 + item?.key === TableDefaultTypeEnum.DATERANGE ? item?.value?.split(',') : [];
  141 + const splitDateValue = item?.key === TableDefaultTypeEnum.DATERANGE ? item?.dateValue : [];
191 for (let i in splitDateKey) { 142 for (let i in splitDateKey) {
192 const obj = { 143 const obj = {
193 key: splitDateKey[i], 144 key: splitDateKey[i],
@@ -199,15 +150,10 @@ @@ -199,15 +150,10 @@
199 return testEditCellTableRef.value 150 return testEditCellTableRef.value
200 ?.getValue() 151 ?.getValue()
201 .concat(keyValueList) 152 .concat(keyValueList)
202 - .filter((it) => it.key !== 'date_range') 153 + .filter((it) => it.key !== TableDefaultTypeEnum.DATERANGE)
203 .map((it: any) => { 154 .map((it: any) => {
204 - const value =  
205 - it?.key === 'scope'  
206 - ? it?.keyValue  
207 - : it?.key === 'fixed_date'  
208 - ? moment(it?.fixed_date_value).valueOf()  
209 - : it?.value;  
210 - const key = it?.key === 'scope' || it?.key === 'fixed_date' ? it?.value : it?.key; 155 + const value = it?.key === TableDefaultTypeEnum.SCOPE ? it?.keyValue : it?.value;
  156 + const key = it?.key === TableDefaultTypeEnum.SCOPE ? it?.value : it?.key;
211 return { 157 return {
212 key, 158 key,
213 value, 159 value,
@@ -219,7 +165,10 @@ @@ -219,7 +165,10 @@
219 //获取数据 165 //获取数据
220 const getTestValue = () => { 166 const getTestValue = () => {
221 let params: any = {}; 167 let params: any = {};
222 - if (props.data?.type === 'x-www-form-urlencoded' || props.data?.type === 'form-data') { 168 + if (
  169 + props.data?.type === RequestBodyTypeEnum.XWWW ||
  170 + props.data?.type === RequestBodyTypeEnum.FORMDATA
  171 + ) {
223 const getTable = getTestTableKeyValue(); 172 const getTable = getTestTableKeyValue();
224 const hasRequired = getTable?.some((it) => it.required === true && !it.value); 173 const hasRequired = getTable?.some((it) => it.required === true && !it.value);
225 if (hasRequired) { 174 if (hasRequired) {
@@ -227,10 +176,10 @@ @@ -227,10 +176,10 @@
227 throw new Error('参数不能为空'); 176 throw new Error('参数不能为空');
228 } 177 }
229 getTable?.map((it) => (params[it.key!] = it.value!)); 178 getTable?.map((it) => (params[it.key!] = it.value!));
230 - } else if (props.data?.type === 'json') { 179 + } else if (props.data?.type === RequestBodyTypeEnum.JSON) {
231 params = jsonEditorRef.value?.getJsonValue(); 180 params = jsonEditorRef.value?.getJsonValue();
232 - } else if (props.data?.type === 'xml') {  
233 - params = xmlContent.value; 181 + } else if (props.data?.type === RequestBodyTypeEnum.XML) {
  182 + params = aceEditorRef?.value?.getValue();
234 } 183 }
235 if (params['keys']) { 184 if (params['keys']) {
236 Reflect.set(params, 'keys', params['keys'].join(',')); 185 Reflect.set(params, 'keys', params['keys'].join(','));
@@ -245,11 +194,9 @@ @@ -245,11 +194,9 @@
245 194
246 //设置数据 195 //设置数据
247 const setValue = () => { 196 const setValue = () => {
  197 + isSingleClickText.value = 'open';
248 showTestEditCell.value = false; 198 showTestEditCell.value = false;
249 testResult.value = ''; 199 testResult.value = '';
250 - selectTenant.value = undefined;  
251 - selectSysTenant.value = undefined;  
252 - selectTenantOptions.value = [];  
253 }; 200 };
254 201
255 const onCloseTest = () => { 202 const onCloseTest = () => {
1 -<!-- eslint-disable vue/valid-v-model -->  
2 -<template>  
3 - <div class="table-content">  
4 - <!-- TODO: 待优化测试表格 -->  
5 - <table align="center">  
6 - <thead>  
7 - <tr>  
8 - <th v-for="item in editTestCellTableTHeadConfig" :key="item">  
9 - <a-tooltip v-if="item === '参数值'">  
10 - <template #title>当自定义为entityType,应输入DEVICE</template>  
11 - <QuestionCircleOutlined :style="{ fontSize: '14px', marginLeft: '5px' }" />  
12 - </a-tooltip>  
13 - {{ item }}  
14 - </th>  
15 - </tr>  
16 - </thead>  
17 - <tbody>  
18 - <tr v-for="(item, index) in tableTestArray.content" :key="index">  
19 - <td style="width: 7.5vw">  
20 - <Select  
21 - :getPopupContainer="  
22 - (triggerNode) => {  
23 - return triggerNode.parentNode;  
24 - }  
25 - "  
26 - :disabled="true"  
27 - v-model:value="item.key"  
28 - placeholder="请选择"  
29 - :options="selectOptions"  
30 - />  
31 - </td>  
32 - <td style="width: 6.5vw">  
33 - <a-input v-if="item.key === 'scope'" placeholder="请输入" v-model:value="item.value" />  
34 - <a-tree-select  
35 - :getPopupContainer="  
36 - (triggerNode) => {  
37 - return triggerNode.parentNode;  
38 - }  
39 - "  
40 - v-else-if="item.key === 'organizationId'"  
41 - v-model:value="item.value"  
42 - show-search  
43 - :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"  
44 - placeholder="请选择组织"  
45 - allow-clear  
46 - tree-default-expand-all  
47 - :tree-data="treeData"  
48 - @change="handleOrgnationChange(item)"  
49 - />  
50 - <Select  
51 - :getPopupContainer="  
52 - (triggerNode) => {  
53 - return triggerNode.parentNode;  
54 - }  
55 - "  
56 - v-else-if="item.key === 'entityId'"  
57 - v-model:value="item.value"  
58 - placeholder="请选择"  
59 - notFoundContent="请选择"  
60 - :options="entityOptions"  
61 - allowClear  
62 - />  
63 - <Select  
64 - :getPopupContainer="  
65 - (triggerNode) => {  
66 - return triggerNode.parentNode;  
67 - }  
68 - "  
69 - v-else-if="item.key === 'keys'"  
70 - v-model:value="item.value"  
71 - placeholder="请选择"  
72 - notFoundContent="请选择"  
73 - :options="attributeOptions"  
74 - mode="multiple"  
75 - allowClear  
76 - />  
77 - <div v-else-if="item.key === 'date_range'">  
78 - <a-button disabled type="primary">{{ item.value?.split(',').at(-2) }}</a-button>  
79 - <span>~</span>  
80 - <a-button disabled type="primary">{{ item.value?.split(',').at(-1) }}</a-button>  
81 - </div>  
82 - <div v-else-if="item.key === 'fixed_date'">  
83 - <a-button disabled type="primary">{{ item.value }}</a-button>  
84 - </div>  
85 - <Select  
86 - :getPopupContainer="  
87 - (triggerNode) => {  
88 - return triggerNode.parentNode;  
89 - }  
90 - "  
91 - v-else  
92 - v-model:value="item.value"  
93 - placeholder="请选择"  
94 - notFoundContent="请选择"  
95 - :options="valueOptions"  
96 - allowClear  
97 - @change="handleValueChange(item)"  
98 - />  
99 - </td>  
100 - <td style="width: 6.5vw">  
101 - <a-input  
102 - v-if="item.key === 'scope'"  
103 - placeholder="请输入"  
104 - v-model:value="item.keyValue"  
105 - />  
106 - <a-date-picker  
107 - v-else-if="item.key === 'fixed_date'"  
108 - style="width: 6.5vw"  
109 - v-model:value="item.keyValue"  
110 - :show-time="{ format: 'HH:mm' }"  
111 - format="YYYY-MM-DD HH:mm:ss"  
112 - placeholder="日期时间"  
113 - />  
114 - <a-range-picker  
115 - v-else-if="item.key == 'date_range'"  
116 - style="width: 6.5vw"  
117 - v-model:value="item.dateValue"  
118 - :show-time="{ format: 'HH:mm' }"  
119 - format="YYYY-MM-DD HH:mm"  
120 - :placeholder="['开始', '结束']"  
121 - />  
122 - <a-input v-else disabled placeholder="请输入" v-model:value="item.keyValue" />  
123 - </td>  
124 - </tr>  
125 - </tbody>  
126 - </table>  
127 - </div>  
128 -</template>  
129 -<script lang="ts" setup name="editCellTable">  
130 - import { reactive, ref, onMounted } from 'vue';  
131 - import { Select } from 'ant-design-vue';  
132 - import { findDictItemByCode } from '/@/api/system/dict';  
133 - import { useApi } from '../../../hooks/useApi';  
134 - import { useUtils } from '../../../hooks/useUtils';  
135 - import { cloneDeep } from 'lodash-es';  
136 - import { tableItems, selectType } from '../../../config/types';  
137 - import { editTestCellTableTHeadConfig } from '../../../config/config';  
138 - import { QuestionCircleOutlined } from '@ant-design/icons-vue';  
139 -  
140 - const props = defineProps({  
141 - method: {  
142 - type: String,  
143 - },  
144 - token: {  
145 - type: String,  
146 - },  
147 - });  
148 -  
149 - onMounted(async () => {  
150 - const res = await findDictItemByCode({ dictCode: 'dataview_builtin_params' });  
151 - selectOptions.value = res.map((m) => ({ label: m.itemText, value: m.itemValue }));  
152 - selectOptions.value.push({  
153 - label: '自定义',  
154 - value: 'scope',  
155 - });  
156 - if (props.method === '2')  
157 - selectOptions.value = selectOptions.value.filter((f) => f.value !== 'scope');  
158 - });  
159 -  
160 - const { isOtherHttp } = useUtils();  
161 -  
162 - const selectOptions = ref<selectType[]>([]);  
163 -  
164 - const valueOptions = ref<selectType[]>([]);  
165 -  
166 - const entityOptions = ref<selectType[]>([]);  
167 -  
168 - const attributeOptions = ref<selectType[]>([]);  
169 -  
170 - const treeData = ref([]);  
171 -  
172 - const tableTestArray = reactive<{  
173 - content: tableItems[];  
174 - }>({  
175 - content: [  
176 - {  
177 - key: undefined,  
178 - value: undefined,  
179 - keyValue: null,  
180 - editDisabled: false,  
181 - dateValue: null,  
182 - },  
183 - ],  
184 - });  
185 -  
186 - //设置数据  
187 - const setTableArray = (data) => {  
188 - const list = cloneDeep(data);  
189 - list?.forEach((it) => {  
190 - if (it.key === 'keys') it.value = [];  
191 - });  
192 - if (Array.isArray(list)) (tableTestArray.content = list) && getApi(list);  
193 - if (list.hasOwnProperty('form-data') && Array.isArray(list['form-data']))  
194 - (tableTestArray.content = list['form-data']) && getApi(list['form-data']);  
195 - if (  
196 - list.hasOwnProperty('x-www-form-urlencoded') &&  
197 - Array.isArray(list['x-www-form-urlencoded'])  
198 - )  
199 - (tableTestArray.content = list['x-www-form-urlencoded']) &&  
200 - getApi(list['x-www-form-urlencoded']);  
201 - };  
202 -  
203 - const getApi = (list) => {  
204 - list?.forEach(async (it) => {  
205 - if (it.key === 'deviceProfileId') {  
206 - const { options } = await useApi(it.key, props.token);  
207 - valueOptions.value = options;  
208 - } else if (it.key === 'organizationId') {  
209 - const { options } = await useApi(it.key, props.token);  
210 - treeData.value = options as any;  
211 - }  
212 - });  
213 - };  
214 -  
215 - const handleOrgnationChange = async (e) => {  
216 - let deviceProfileId = '';  
217 - tableTestArray.content.forEach((f: any) => {  
218 - if (f.key === 'entityId') {  
219 - f.value = null;  
220 - }  
221 - if (f.key === 'deviceProfileId') deviceProfileId = f.value;  
222 - });  
223 - getEntityOptions(e.value, deviceProfileId);  
224 - };  
225 -  
226 - const getEntityOptions = async (organizationId: string, deviceProfileId?: string) => {  
227 - const res = await isOtherHttp('api/yt/device/list', props.token, {  
228 - organizationId,  
229 - deviceProfileId,  
230 - });  
231 - entityOptions.value = res.map((item) => ({  
232 - label: item.alias || item.name,  
233 - value: item.tbDeviceId,  
234 - }));  
235 - };  
236 -  
237 - const getAttributeOptions = async (params) => {  
238 - const { deviceProfileId, dataType } = params;  
239 - const res = await isOtherHttp(`api/yt/device/attributes/${deviceProfileId}`, props.token, {  
240 - dataType,  
241 - });  
242 - if (Object.keys(res).length === 0) return (attributeOptions.value.length = 0);  
243 - attributeOptions.value = res?.map((item) => ({ label: item.name, value: item.identifier }));  
244 - };  
245 -  
246 - const handleValueChange = (e) => {  
247 - let organizationId = '';  
248 - if (e.key === 'deviceProfileId') {  
249 - tableTestArray.content.forEach((f: any) => {  
250 - if (f.key === 'keys') {  
251 - f.value = [];  
252 - }  
253 - if (f.key === 'organizationId') organizationId = f.value;  
254 - if (f.key === 'entityId') f.value = null;  
255 - });  
256 - if (e.value) {  
257 - getAttributeOptions({ deviceProfileId: e.value });  
258 - }  
259 - if (organizationId !== '') {  
260 - getEntityOptions(organizationId, e.value);  
261 - }  
262 - }  
263 - };  
264 -  
265 - //获取数据  
266 - const getValue = () => {  
267 - return tableTestArray.content;  
268 - };  
269 - defineExpose({  
270 - getValue,  
271 - setTableArray,  
272 - });  
273 -</script>  
274 -  
275 -<style scoped lang="less">  
276 - @table-color: #e5e7eb;  
277 -  
278 - .table-border-color {  
279 - border: 1px solid #e5e7eb;  
280 - text-align: center;  
281 - }  
282 -  
283 - .table-content {  
284 - table {  
285 - width: 31vw;  
286 - &:extend(.table-border-color);  
287 - }  
288 -  
289 - table td {  
290 - padding: 5px;  
291 - white-space: nowrap;  
292 - &:extend(.table-border-color);  
293 - }  
294 -  
295 - table th {  
296 - padding: 5px;  
297 - &:extend(.table-border-color);  
298 - }  
299 - }  
300 -</style>  
@@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
4 <a-row> 4 <a-row>
5 <Button @click="handleExcute" type="primary"> 执行测试请求 </Button> 5 <Button @click="handleExcute" type="primary"> 执行测试请求 </Button>
6 </a-row> 6 </a-row>
7 - <div v-if="isShowTestResult" style="display: flex; justify-content: space-between"> 7 + <div v-if="isShowTestResult" class="flex justify-between">
8 <a-row class="mt-8" type="flex" justify="center" align="middle"> 8 <a-row class="mt-8" type="flex" justify="center" align="middle">
9 <a-col :span="3"> 测试地址 </a-col> 9 <a-col :span="3"> 测试地址 </a-col>
10 <a-col :span="21"> 10 <a-col :span="21">
@@ -16,22 +16,52 @@ @@ -16,22 +16,52 @@
16 </div> 16 </div>
17 </div> 17 </div>
18 <div class="mt-8"> 18 <div class="mt-8">
19 - <a-row type="flex" justify="space-between" align="middle">  
20 - <a-col :span="24">  
21 - <div>  
22 - <JsonEditor  
23 - :showBtn="true"  
24 - v-if="isWebSocketType === '2'"  
25 - style="width: 40vw; height: 40vh"  
26 - ref="jsonWebsocketEditorRef"  
27 - />  
28 - <JsonEditor  
29 - :showBtn="true"  
30 - v-else  
31 - style="width: 40vw; height: 40vh"  
32 - ref="jsonEditorRef"  
33 - />  
34 - </div> 19 + <a-row type="flex" align="top">
  20 + <a-col
  21 + :span="
  22 + method === RequestMethodTypeEnum.WEBSOCKET
  23 + ? 11
  24 + : httpType === RequestHttpTypeEnum.POST
  25 + ? 4
  26 + : 6
  27 + "
  28 + >
  29 + <p>过滤器函数编写:</p>
  30 + <AceTypeIsJsEditor
  31 + :restData="getRestData"
  32 + @changeAceContent="onHandleAceContent"
  33 + ref="aceTypeIsJsEditorRef"
  34 + />
  35 + </a-col>
  36 + <a-col :span="1">
  37 + <a-divider type="vertical" class="divider-color" />
  38 + </a-col>
  39 + <a-col
  40 + :span="
  41 + method === RequestMethodTypeEnum.WEBSOCKET
  42 + ? 12
  43 + : httpType === RequestHttpTypeEnum.POST
  44 + ? 19
  45 + : 17
  46 + "
  47 + style="position: relative"
  48 + :style="{
  49 + left:
  50 + (method === RequestMethodTypeEnum.WEBSOCKET
  51 + ? 1.5
  52 + : httpType === RequestHttpTypeEnum.POST
  53 + ? -1.5
  54 + : 0) + 'vw',
  55 + }"
  56 + >
  57 + <a-col>
  58 + <p>接口返回数据(res):</p>
  59 + <JsonEditor style="height: 35vh" :showBtn="true" ref="jsonEditorRef" />
  60 + </a-col>
  61 + <a-col class="mt-3">
  62 + <p>过滤器结果:</p>
  63 + <JsonFilterEditor style="height: 35vh" :showBtn="true" ref="jsonEditorFilterRef" />
  64 + </a-col>
35 </a-col> 65 </a-col>
36 </a-row> 66 </a-row>
37 </div> 67 </div>
@@ -44,8 +74,11 @@ @@ -44,8 +74,11 @@
44 import { useWebSocket } from '@vueuse/core'; 74 import { useWebSocket } from '@vueuse/core';
45 import { useUtils } from '../../../hooks/useUtils'; 75 import { useUtils } from '../../../hooks/useUtils';
46 import JsonEditor from '../../SimpleRequest/components/jsonEditor.vue'; 76 import JsonEditor from '../../SimpleRequest/components/jsonEditor.vue';
  77 + import JsonFilterEditor from '../../SimpleRequest/components/jsonEditor.vue';
  78 + import AceTypeIsJsEditor from '../../SimpleRequest/components/aceEditor.vue';
47 import { Tag } from 'ant-design-vue'; 79 import { Tag } from 'ant-design-vue';
48 import { useThrottleFn } from '@vueuse/shared'; 80 import { useThrottleFn } from '@vueuse/shared';
  81 + import { RequestMethodTypeEnum, RequestHttpTypeEnum } from '../../../config/enum';
49 82
50 const emits = defineEmits(['emitExcute']); 83 const emits = defineEmits(['emitExcute']);
51 84
@@ -53,13 +86,25 @@ @@ -53,13 +86,25 @@
53 data: { 86 data: {
54 type: Object, 87 type: Object,
55 }, 88 },
  89 + method: {
  90 + type: String,
  91 + },
  92 + httpType: {
  93 + type: String,
  94 + },
56 }); 95 });
57 96
58 const showTestFlag = ref(false); 97 const showTestFlag = ref(false);
59 98
  99 + const openFilterFlag = ref(false);
  100 +
60 const jsonEditorRef = ref<InstanceType<typeof JsonEditor>>(); 101 const jsonEditorRef = ref<InstanceType<typeof JsonEditor>>();
61 102
62 - const jsonWebsocketEditorRef = ref<InstanceType<typeof JsonEditor>>(); 103 + const jsonEditorFilterRef = ref<InstanceType<typeof JsonFilterEditor>>();
  104 +
  105 + const aceTypeIsJsEditorRef = ref<InstanceType<typeof AceTypeIsJsEditor>>();
  106 +
  107 + const getRestData: any = ref(null);
63 108
64 const socketUrls = ref(''); 109 const socketUrls = ref('');
65 110
@@ -70,6 +115,12 @@ @@ -70,6 +115,12 @@
70 }, 115 },
71 }); 116 });
72 117
  118 + const { staticWebSocketParams, commonRest } = useUtils();
  119 +
  120 + const onHandleAceContent = (resp) => {
  121 + commonRest(resp, jsonEditorFilterRef.value?.setJsonValue);
  122 + };
  123 +
73 //格式化替换像"http:xxxx/api/xx/{xx}/{xx}/{xx}这种格式" 124 //格式化替换像"http:xxxx/api/xx/{xx}/{xx}/{xx}这种格式"
74 String.prototype.restfulFormat = function (replacements) { 125 String.prototype.restfulFormat = function (replacements) {
75 var formatString = function (str, replacements) { 126 var formatString = function (str, replacements) {
@@ -109,7 +160,7 @@ @@ -109,7 +160,7 @@
109 isShowTestResult.value = true; 160 isShowTestResult.value = true;
110 nextTick(() => { 161 nextTick(() => {
111 jsonEditorRef.value?.setJsonValue('测试结果为'); 162 jsonEditorRef.value?.setJsonValue('测试结果为');
112 - jsonWebsocketEditorRef.value?.setJsonValue('测试结果为'); 163 + jsonEditorFilterRef.value?.setJsonValue('过滤结果为');
113 }); 164 });
114 }; 165 };
115 166
@@ -121,17 +172,17 @@ @@ -121,17 +172,17 @@
121 await nextTick(); 172 await nextTick();
122 //获取Params和Header和Body 173 //获取Params和Header和Body
123 const Objects = props.data; 174 const Objects = props.data;
124 - isWebSocketType.value = Objects?.method;  
125 const apiType = Objects?.apiType; 175 const apiType = Objects?.apiType;
126 const url = Objects?.apiGetUrl; 176 const url = Objects?.apiGetUrl;
127 const headers = Objects?.Header?.params; 177 const headers = Objects?.Header?.params;
128 const params = Objects?.Params?.params; 178 const params = Objects?.Params?.params;
129 - isToken.value = Objects?.Params?.token;  
130 const body = Objects?.Body?.params; 179 const body = Objects?.Body?.params;
  180 + isWebSocketType.value = Objects?.method;
  181 + isToken.value = Objects?.Params?.token;
131 isPostToken.value = Objects?.Body?.token; 182 isPostToken.value = Objects?.Body?.token;
132 postBodyType.value = Objects?.Body?.type; 183 postBodyType.value = Objects?.Body?.type;
133 apiUrl.value = url?.restfulFormat(params); 184 apiUrl.value = url?.restfulFormat(params);
134 - if (isWebSocketType.value === '2') { 185 + if (isWebSocketType.value === RequestMethodTypeEnum.WEBSOCKET) {
135 socketUrls.value = url; 186 socketUrls.value = url;
136 socketMessage.server = `${socketUrls.value}?token=${isToken.value}`; 187 socketMessage.server = `${socketUrls.value}?token=${isToken.value}`;
137 const list = Object.values(params); 188 const list = Object.values(params);
@@ -154,19 +205,10 @@ @@ -154,19 +205,10 @@
154 postBodyType.value 205 postBodyType.value
155 ); 206 );
156 if (!resp) return; 207 if (!resp) return;
157 - if (Object.prototype.toString.call(resp) === '[object Object]') {  
158 - jsonEditorRef.value?.setJsonValue(resp);  
159 - } else if (typeof resp === 'string') {  
160 - jsonEditorRef.value?.setJsonValue(resp);  
161 - } else if (Array.isArray(resp)) {  
162 - const temp = {  
163 - data: resp,  
164 - };  
165 - jsonEditorRef.value?.setJsonValue(temp);  
166 - } else {  
167 - jsonEditorRef.value?.setJsonValue(JSON.stringify(resp));  
168 - } 208 + getRestData.value = resp;
  209 + commonRest(resp, jsonEditorRef.value?.setJsonValue);
169 } catch (e) { 210 } catch (e) {
  211 + console.log(e);
170 if (Object.prototype.toString.call(e) === '[object Object]') { 212 if (Object.prototype.toString.call(e) === '[object Object]') {
171 jsonEditorRef.value?.setJsonValue(e); 213 jsonEditorRef.value?.setJsonValue(e);
172 } else { 214 } else {
@@ -176,50 +218,45 @@ @@ -176,50 +218,45 @@
176 } 218 }
177 }; 219 };
178 220
179 - //websocket请求 221 + //ws请求
180 const websocketRequest = (params, destroy = false) => { 222 const websocketRequest = (params, destroy = false) => {
181 - //websocket请求  
182 - if (Object.prototype.toString.call(params) === '[object Object]') {  
183 - Reflect.deleteProperty(params, 'deviceProfileId');  
184 - Reflect.deleteProperty(params, 'organizationId');  
185 - Reflect.set(params, 'cmdId', 1);  
186 - Reflect.set(params, 'scope', 'LATEST_TELEMETRY');  
187 - Reflect.set(params, 'entityType', 'DEVICE'); 223 + try {
  224 + let webSocketParams: any = null;
  225 + if (Object.prototype.toString.call(params) === '[object Object]') {
  226 + const { entityId, keys } = params;
  227 + webSocketParams = {
  228 + entityId,
  229 + keys,
  230 + ...staticWebSocketParams,
  231 + };
  232 + }
  233 + socketMessage.sendValue.tsSubCmds = [webSocketParams];
  234 + const { send, close } = useWebSocket(socketMessage.server, {
  235 + onConnected() {
  236 + send(JSON.stringify(socketMessage.sendValue));
  237 + },
  238 + onMessage(_, e) {
  239 + const { data } = JSON.parse(e.data);
  240 + getRestData.value = data;
  241 + commonRest(data, jsonEditorRef.value?.setJsonValue);
  242 + },
  243 + onDisconnected() {
  244 + close();
  245 + },
  246 + onError() {},
  247 + });
  248 + if (destroy) close();
  249 + } finally {
188 } 250 }
189 - socketMessage.sendValue.tsSubCmds = [params];  
190 - const { send, close } = useWebSocket(socketMessage.server, {  
191 - onConnected() {  
192 - send(JSON.stringify(socketMessage.sendValue));  
193 - console.log('建立连接了');  
194 - },  
195 - onMessage(_, e) {  
196 - const { data } = JSON.parse(e.data);  
197 - if (Object.prototype.toString.call(data) === '[object Object]') {  
198 - jsonWebsocketEditorRef.value?.setJsonValue(data);  
199 - } else if (typeof data === 'string') {  
200 - jsonWebsocketEditorRef.value?.setJsonValue(data);  
201 - } else if (Array.isArray(data)) {  
202 - jsonWebsocketEditorRef.value?.setJsonValue(JSON.stringify(data));  
203 - } else {  
204 - jsonEditorRef.value?.setJsonValue(JSON.stringify(data));  
205 - }  
206 - },  
207 - onDisconnected() {  
208 - console.log('断开连接了');  
209 - close();  
210 - },  
211 - onError() {},  
212 - });  
213 - if (destroy) close();  
214 }; 251 };
215 252
216 onUnmounted(() => { 253 onUnmounted(() => {
217 - if (isWebSocketType.value === '2') { 254 + if (isWebSocketType.value === RequestMethodTypeEnum.WEBSOCKET) {
218 websocketRequest(null, true); 255 websocketRequest(null, true);
219 } 256 }
220 }); 257 });
221 258
222 - //TODO: 待优化 项目自带第三方请求 259 + //http请求
223 const otherHttpRequest = async ( 260 const otherHttpRequest = async (
224 apiType, 261 apiType,
225 apiUrl, 262 apiUrl,
@@ -228,69 +265,27 @@ @@ -228,69 +265,27 @@
228 body, 265 body,
229 token, 266 token,
230 postToken, 267 postToken,
231 - postBodyType,  
232 - joinPrefix = false 268 + postBodyType
233 ) => { 269 ) => {
234 - const { convertObj } = useUtils(); 270 + const { convertObj, commonHttpParams, commonParams } = useUtils();
235 switch (apiType) { 271 switch (apiType) {
236 case 'GET': 272 case 'GET':
237 - const objGet = Object.assign(  
238 - {},  
239 - {  
240 - 'X-Authorization': `Bearer ${!token ? postToken : token}`,  
241 - },  
242 - headers  
243 - );  
244 return await otherHttp.get( 273 return await otherHttp.get(
245 - { url: apiUrl, params, headers: objGet },  
246 { 274 {
247 - apiUrl: '',  
248 - joinPrefix,  
249 - withToken: false,  
250 - errorMessageMode: 'none',  
251 - }  
252 - );  
253 - case 'POST':  
254 - const objPost = Object.assign(  
255 - {},  
256 - {  
257 - 'X-Authorization': `Bearer ${!postToken ? token : postToken}`, 275 + url: apiUrl,
  276 + params,
  277 + headers: commonHttpParams(postToken, token, postBodyType, headers),
258 }, 278 },
259 - {  
260 - 'Content-Type':  
261 - postBodyType === 'xml'  
262 - ? 'text/xml'  
263 - : postBodyType === 'form-data'  
264 - ? 'multipart/form-data'  
265 - : postBodyType === 'x-www-form-urlencoded'  
266 - ? 'application/x-www-form-urlencoded'  
267 - : postBodyType === 'json'  
268 - ? 'application/json'  
269 - : 'application/json',  
270 - },  
271 - headers 279 + commonParams
272 ); 280 );
  281 + case 'POST':
273 return await otherHttp.post( 282 return await otherHttp.post(
274 - { url: `${apiUrl}?${convertObj(params)}`, data: body, headers: objPost },  
275 { 283 {
276 - apiUrl: '',  
277 - joinPrefix,  
278 - withToken: false,  
279 - errorMessageMode: 'none',  
280 - }  
281 - );  
282 - case 'PUT':  
283 - const objPut = Object.assign({}, headers, {  
284 - 'X-Authorization': `Bearer ${!postToken ? token : postToken}`,  
285 - });  
286 - return await otherHttp.put(  
287 - { url: `${apiUrl}?${convertObj(params)}`, data: body, headers: objPut, params },  
288 - {  
289 - apiUrl: '',  
290 - joinPrefix,  
291 - withToken: false,  
292 - errorMessageMode: 'none',  
293 - } 284 + url: `${apiUrl}${`?${convertObj(params)}`}`,
  285 + data: body,
  286 + headers: commonHttpParams(postToken, token, postBodyType, headers),
  287 + },
  288 + commonParams
294 ); 289 );
295 } 290 }
296 }; 291 };
@@ -298,19 +293,25 @@ @@ -298,19 +293,25 @@
298 const resetValue = (flag) => { 293 const resetValue = (flag) => {
299 if (flag) { 294 if (flag) {
300 showTestFlag.value = false; 295 showTestFlag.value = false;
  296 + openFilterFlag.value = false;
301 } 297 }
302 nextTick(() => { 298 nextTick(() => {
303 jsonEditorRef.value?.setJsonValue('测试结果为'); 299 jsonEditorRef.value?.setJsonValue('测试结果为');
304 - jsonWebsocketEditorRef.value?.setJsonValue('测试结果为'); 300 + jsonEditorFilterRef.value?.setJsonValue('过滤结果为');
305 }); 301 });
306 - isWebSocketType.value = '0'; 302 + isWebSocketType.value = RequestMethodTypeEnum.COMMOM;
307 }; 303 };
308 304
309 const showTest = () => (showTestFlag.value = true); 305 const showTest = () => (showTestFlag.value = true);
310 306
  307 + const getFilterValue = () => {
  308 + return aceTypeIsJsEditorRef?.value?.getValue();
  309 + };
  310 +
311 defineExpose({ 311 defineExpose({
312 resetValue, 312 resetValue,
313 showTest, 313 showTest,
  314 + getFilterValue,
314 }); 315 });
315 </script> 316 </script>
316 317
@@ -318,4 +319,11 @@ @@ -318,4 +319,11 @@
318 :deep(.ant-input-textarea-show-count) { 319 :deep(.ant-input-textarea-show-count) {
319 width: 30vw; 320 width: 30vw;
320 } 321 }
  322 +
  323 + .divider-color {
  324 + height: 78.5vh;
  325 + background-color: #e5e7eb;
  326 + position: relative;
  327 + left: 1.16vw;
  328 + }
321 </style> 329 </style>
  1 +<template>
  2 + <div class="flex" v-if="interfaceType === 'SYSTEM' && isAdmin(role)">
  3 + <Select
  4 + v-model:value="selectTenant"
  5 + @change="onSelect"
  6 + style="width: 150px"
  7 + placeholder="请选择租户"
  8 + :options="selectOptions"
  9 + show-search
  10 + :filter-option="filterOption"
  11 + />
  12 + <Select
  13 + v-model:value="selectSysTenant"
  14 + @change="onSelctTenant"
  15 + style="width: 150px; margin-left: 10px"
  16 + v-if="selectTenantOptions.length > 0"
  17 + placeholder="请选择租户"
  18 + :options="selectTenantOptions"
  19 + show-search
  20 + :filter-option="filterTenantOption"
  21 + />
  22 + </div>
  23 +</template>
  24 +<script lang="ts" setup name="selectTenant">
  25 + import { onMounted, ref, onUnmounted } from 'vue';
  26 + import { selectType } from '../../../config/types';
  27 + import { Select } from 'ant-design-vue';
  28 + import { getUserToken } from '/@/api/sys/user';
  29 + import { USER_INFO_KEY } from '/@/enums/cacheEnum';
  30 + import { getAuthCache } from '/@/utils/auth';
  31 + import { isAdmin } from '/@/enums/roleEnum';
  32 + import { getTenantAllPageLists, getTenantPageList } from '/@/api/tenant/tenantApi';
  33 +
  34 + defineProps({
  35 + interfaceType: {
  36 + type: String,
  37 + },
  38 + });
  39 +
  40 + const emits = defineEmits(['emitToken']);
  41 +
  42 + const userInfo: any = getAuthCache(USER_INFO_KEY);
  43 +
  44 + const role: string = userInfo?.roles[0];
  45 +
  46 + onMounted(async () => {
  47 + if (isAdmin(role)) {
  48 + const res = await getTenantPageList();
  49 + selectOptions.value = res.map((m) => ({ label: m.name, value: m.tenantId }));
  50 + } else {
  51 + //租户
  52 + const { token } = await getUserToken(userInfo?.userId);
  53 + getToken.value = token;
  54 + emits('emitToken', getToken.value, testDisabled.value);
  55 + }
  56 + });
  57 +
  58 + const selectOptions = ref<selectType[]>([]);
  59 +
  60 + const testDisabled = ref(true);
  61 +
  62 + const selectTenantOptions = ref<selectType[]>([]);
  63 +
  64 + const selectTenant = ref(undefined);
  65 +
  66 + const selectSysTenant = ref(undefined);
  67 +
  68 + const getToken = ref('');
  69 +
  70 + const filterOption = (input: string, option: any) => {
  71 + return option.label.includes(input);
  72 + };
  73 +
  74 + const filterTenantOption = (input: string, option: any) => {
  75 + return option.label.includes(input);
  76 + };
  77 +
  78 + const onSelect = async (e) => {
  79 + if (e) {
  80 + testDisabled.value = false;
  81 + } else {
  82 + testDisabled.value = true;
  83 + }
  84 + selectSysTenant.value = undefined;
  85 + const rest = (await getTenantAllPageLists(e)) as any;
  86 + selectTenantOptions.value = rest?.map((m) => ({ label: m.realName, value: m.id }));
  87 + };
  88 +
  89 + const onSelctTenant = async (e) => {
  90 + if (e) {
  91 + testDisabled.value = false;
  92 + } else {
  93 + testDisabled.value = true;
  94 + }
  95 + const { token } = await getUserToken(e);
  96 + getToken.value = token;
  97 + emits('emitToken', getToken.value, testDisabled.value);
  98 + };
  99 +
  100 + onUnmounted(() => {
  101 + selectTenant.value = undefined;
  102 + selectSysTenant.value = undefined;
  103 + selectTenantOptions.value = [];
  104 + getToken.value = '';
  105 + });
  106 +</script>
  107 +
  108 +<style scoped lang="less"></style>
@@ -2,28 +2,10 @@ @@ -2,28 +2,10 @@
2 <div> 2 <div>
3 <div class="mt-8"> 3 <div class="mt-8">
4 <div class="flex"> 4 <div class="flex">
5 - <div class="flex" v-if="interfaceType === 'SYSTEM' && isAdmin(role)">  
6 - <Select  
7 - allowClear  
8 - v-model:value="selectTenant"  
9 - @change="onSelect"  
10 - style="width: 150px"  
11 - placeholder="请选择租户"  
12 - :options="selectOptions"  
13 - />  
14 - <Select  
15 - v-model:value="selectSysTenant"  
16 - allowClear  
17 - @change="onSelctTenant"  
18 - style="width: 150px; margin-left: 10px"  
19 - v-if="selectTenantOptions.length > 0"  
20 - placeholder="请选择租户"  
21 - :options="selectTenantOptions"  
22 - />  
23 - </div> 5 + <SelectTenant :interfaceType="interfaceType" @emitToken="onHandleEmitToken" />
  6 + <div v-if="role === 'SYS_ADMIN'" class="ml-2"></div>
24 <Button 7 <Button
25 :disabled="interfaceType === 'SYSTEM' && isAdmin(role) ? testDisabled : false" 8 :disabled="interfaceType === 'SYSTEM' && isAdmin(role) ? testDisabled : false"
26 - class="ml-2"  
27 @click="handleTest(isSingleClickText)" 9 @click="handleTest(isSingleClickText)"
28 type="primary" 10 type="primary"
29 >{{ `${isSingleClickText === 'open' ? '打开' : '关闭'}测试接口` }} 11 >{{ `${isSingleClickText === 'open' ? '打开' : '关闭'}测试接口` }}
@@ -38,21 +20,17 @@ @@ -38,21 +20,17 @@
38 </a-row> 20 </a-row>
39 </div> 21 </div>
40 </div> 22 </div>
41 - <div class="mt-8"> </div>  
42 </div> 23 </div>
43 </template> 24 </template>
44 <script lang="ts" setup name="testRequest"> 25 <script lang="ts" setup name="testRequest">
45 - import { ref, nextTick, onMounted } from 'vue'; 26 + import { ref, nextTick } from 'vue';
46 import { Button } from 'ant-design-vue'; 27 import { Button } from 'ant-design-vue';
47 import TestHeaderEditCellTable from './testEditHeaderCellTable.vue'; 28 import TestHeaderEditCellTable from './testEditHeaderCellTable.vue';
48 import { useMessage } from '/@/hooks/web/useMessage'; 29 import { useMessage } from '/@/hooks/web/useMessage';
49 - import { selectType } from '../../../config/types';  
50 - import { Select } from 'ant-design-vue';  
51 - import { getUserToken } from '/@/api/sys/user';  
52 import { USER_INFO_KEY } from '/@/enums/cacheEnum'; 30 import { USER_INFO_KEY } from '/@/enums/cacheEnum';
53 - import { getTenantAllPageLists, getTenantPageList } from '/@/api/tenant/tenantApi';  
54 import { getAuthCache } from '/@/utils/auth'; 31 import { getAuthCache } from '/@/utils/auth';
55 import { isAdmin } from '/@/enums/roleEnum'; 32 import { isAdmin } from '/@/enums/roleEnum';
  33 + import SelectTenant from '../components/selectTenant.vue';
56 34
57 const emits = defineEmits(['testHeaderInterface', 'closeTest']); 35 const emits = defineEmits(['testHeaderInterface', 'closeTest']);
58 36
@@ -69,21 +47,6 @@ @@ -69,21 +47,6 @@
69 }, 47 },
70 }); 48 });
71 49
72 - onMounted(async () => {  
73 - if (isAdmin(role)) {  
74 - const res = await getTenantPageList();  
75 - selectOptions.value = res.map((m) => ({ label: m.name, value: m.tenantId }));  
76 - } else {  
77 - //租户  
78 - const { token } = await getUserToken(userInfo?.userId);  
79 - getToken.value = token;  
80 - }  
81 - });  
82 -  
83 - const selectOptions = ref<selectType[]>([]);  
84 -  
85 - const selectTenantOptions = ref<selectType[]>([]);  
86 -  
87 const testDisabled = ref(true); 50 const testDisabled = ref(true);
88 51
89 const { createMessage } = useMessage(); 52 const { createMessage } = useMessage();
@@ -92,46 +55,20 @@ @@ -92,46 +55,20 @@
92 55
93 const excuteData = ref({}); 56 const excuteData = ref({});
94 57
95 - const selectTenant = ref(undefined);  
96 -  
97 - const selectSysTenant = ref(undefined);  
98 -  
99 const testEditCellTableRef = ref<InstanceType<typeof TestHeaderEditCellTable>>(); 58 const testEditCellTableRef = ref<InstanceType<typeof TestHeaderEditCellTable>>();
100 59
101 const testResult = ref(''); 60 const testResult = ref('');
102 61
103 const getToken = ref(''); 62 const getToken = ref('');
104 63
105 - const onSelect = async (e) => {  
106 - if (e) {  
107 - testDisabled.value = false;  
108 - } else {  
109 - testDisabled.value = true;  
110 - }  
111 - selectSysTenant.value = undefined;  
112 - const rest = (await getTenantAllPageLists(e)) as any;  
113 - selectTenantOptions.value = rest?.map((m) => ({ label: m.realName, value: m.id }));  
114 - }; 64 + const isSingleClickText = ref('open');
115 65
116 - const onSelctTenant = async (e) => {  
117 - if (e) {  
118 - testDisabled.value = false;  
119 - } else {  
120 - testDisabled.value = true;  
121 - }  
122 - const { token } = await getUserToken(e); 66 + const onHandleEmitToken = (token, flag) => {
123 getToken.value = token; 67 getToken.value = token;
  68 + testDisabled.value = flag;
124 }; 69 };
125 70
126 - const isSingleClickText = ref('open');  
127 -  
128 const handleTest = (o) => { 71 const handleTest = (o) => {
129 - if (isAdmin(role)) {  
130 - if (!selectTenant.value || !selectSysTenant.value) {  
131 - createMessage.error('请选择租户或者租户管理员');  
132 - throw Error('请选择租户或者租户管理员');  
133 - }  
134 - }  
135 if (o === 'open') { 72 if (o === 'open') {
136 showTestEditCell.value = true; 73 showTestEditCell.value = true;
137 emits('testHeaderInterface'); 74 emits('testHeaderInterface');
@@ -177,9 +114,6 @@ @@ -177,9 +114,6 @@
177 const setValue = () => { 114 const setValue = () => {
178 showTestEditCell.value = false; 115 showTestEditCell.value = false;
179 testResult.value = ''; 116 testResult.value = '';
180 - selectTenant.value = undefined;  
181 - selectSysTenant.value = undefined;  
182 - selectTenantOptions.value = [];  
183 }; 117 };
184 118
185 const onCloseTest = () => { 119 const onCloseTest = () => {
1 -<!-- eslint-disable vue/valid-v-model -->  
2 <template> 1 <template>
3 <div class="table-content"> 2 <div class="table-content">
4 - <!-- TODO: 待优化测试表格 -->  
5 <table align="center"> 3 <table align="center">
6 <thead> 4 <thead>
7 <tr> 5 <tr>
@@ -10,10 +8,10 @@ @@ -10,10 +8,10 @@
10 </thead> 8 </thead>
11 <tbody> 9 <tbody>
12 <tr v-for="(item, index) in tableTestArray.content" :key="index"> 10 <tr v-for="(item, index) in tableTestArray.content" :key="index">
13 - <td style="width: 7.5vw">  
14 - <a-input disabled placeholder="请输入" v-model:value="item.key" /> 11 + <td>
  12 + <a-input disabled v-model:value="item.key" />
15 </td> 13 </td>
16 - <td style="width: 6.5vw"> 14 + <td>
17 <a-input placeholder="请输入" v-model:value="item.value" /> 15 <a-input placeholder="请输入" v-model:value="item.value" />
18 </td> 16 </td>
19 </tr> 17 </tr>
@@ -27,12 +25,6 @@ @@ -27,12 +25,6 @@
27 import { tableItems } from '../../../config/types'; 25 import { tableItems } from '../../../config/types';
28 import { editTestCellTableTHeadConfig } from '../../../config/config'; 26 import { editTestCellTableTHeadConfig } from '../../../config/config';
29 27
30 - defineProps({  
31 - method: {  
32 - type: String,  
33 - },  
34 - });  
35 -  
36 const tableTestArray = reactive<{ 28 const tableTestArray = reactive<{
37 content: tableItems[]; 29 content: tableItems[];
38 }>({ 30 }>({
@@ -57,6 +49,7 @@ @@ -57,6 +49,7 @@
57 const getValue = () => { 49 const getValue = () => {
58 return tableTestArray.content; 50 return tableTestArray.content;
59 }; 51 };
  52 +
60 defineExpose({ 53 defineExpose({
61 getValue, 54 getValue,
62 setTableArray, 55 setTableArray,
@@ -64,28 +57,5 @@ @@ -64,28 +57,5 @@
64 </script> 57 </script>
65 58
66 <style scoped lang="less"> 59 <style scoped lang="less">
67 - @table-color: #e5e7eb;  
68 -  
69 - .table-border-color {  
70 - border: 1px solid #e5e7eb;  
71 - text-align: center;  
72 - }  
73 -  
74 - .table-content {  
75 - table {  
76 - width: 31vw;  
77 - &:extend(.table-border-color);  
78 - }  
79 -  
80 - table td {  
81 - padding: 5px;  
82 - white-space: nowrap;  
83 - &:extend(.table-border-color);  
84 - }  
85 -  
86 - table th {  
87 - padding: 5px;  
88 - &:extend(.table-border-color);  
89 - }  
90 - } 60 + @import '../../SimpleRequest/common/commonTestTable.less';
91 </style> 61 </style>
@@ -2,28 +2,10 @@ @@ -2,28 +2,10 @@
2 <div> 2 <div>
3 <div class="mt-8"> 3 <div class="mt-8">
4 <div class="flex"> 4 <div class="flex">
5 - <div class="flex" v-if="interfaceType === 'SYSTEM' && isAdmin(role)">  
6 - <Select  
7 - allowClear  
8 - v-model:value="selectTenant"  
9 - @change="onSelect"  
10 - style="width: 150px"  
11 - placeholder="请选择租户"  
12 - :options="selectOptions"  
13 - />  
14 - <Select  
15 - v-model:value="selectSysTenant"  
16 - allowClear  
17 - @change="onSelctTenant"  
18 - style="width: 150px; margin-left: 10px"  
19 - v-if="selectTenantOptions.length > 0"  
20 - placeholder="请选择租户"  
21 - :options="selectTenantOptions"  
22 - />  
23 - </div> 5 + <SelectTenant :interfaceType="interfaceType" @emitToken="onHandleEmitToken" />
  6 + <div v-if="role === 'SYS_ADMIN'" class="ml-2"></div>
24 <Button 7 <Button
25 :disabled="interfaceType === 'SYSTEM' && isAdmin(role) ? testDisabled : false" 8 :disabled="interfaceType === 'SYSTEM' && isAdmin(role) ? testDisabled : false"
26 - class="ml-2"  
27 @click="handleTest(isSingleClickText)" 9 @click="handleTest(isSingleClickText)"
28 type="primary" 10 type="primary"
29 >{{ `${isSingleClickText === 'open' ? '打开' : '关闭'}测试接口` }} 11 >{{ `${isSingleClickText === 'open' ? '打开' : '关闭'}测试接口` }}
@@ -38,23 +20,21 @@ @@ -38,23 +20,21 @@
38 </a-row> 20 </a-row>
39 </div> 21 </div>
40 </div> 22 </div>
41 - <div class="mt-8"> </div>  
42 </div> 23 </div>
43 </template> 24 </template>
44 <script lang="ts" setup name="testRequest"> 25 <script lang="ts" setup name="testRequest">
45 - import { ref, nextTick, onMounted } from 'vue'; 26 + import { ref, nextTick } from 'vue';
46 import { Button } from 'ant-design-vue'; 27 import { Button } from 'ant-design-vue';
47 import TestParamsCellTable from './testEditParamsCellTable.vue'; 28 import TestParamsCellTable from './testEditParamsCellTable.vue';
48 import moment from 'moment'; 29 import moment from 'moment';
49 import { useUtils } from '../../../hooks/useUtils'; 30 import { useUtils } from '../../../hooks/useUtils';
50 import { useMessage } from '/@/hooks/web/useMessage'; 31 import { useMessage } from '/@/hooks/web/useMessage';
51 - import { getTenantAllPageLists, getTenantPageList } from '/@/api/tenant/tenantApi';  
52 - import { selectType } from '../../../config/types';  
53 - import { Select } from 'ant-design-vue';  
54 - import { getUserToken } from '/@/api/sys/user';  
55 import { USER_INFO_KEY } from '/@/enums/cacheEnum'; 32 import { USER_INFO_KEY } from '/@/enums/cacheEnum';
56 import { getAuthCache } from '/@/utils/auth'; 33 import { getAuthCache } from '/@/utils/auth';
57 import { isAdmin } from '/@/enums/roleEnum'; 34 import { isAdmin } from '/@/enums/roleEnum';
  35 + import { TableDefaultTypeEnum } from '../../../config/enum';
  36 + import { AggregateDataEnum } from '/@/views/report/config/timeConfig';
  37 + import SelectTenant from '../components/selectTenant.vue';
58 38
59 const userInfo: any = getAuthCache(USER_INFO_KEY); 39 const userInfo: any = getAuthCache(USER_INFO_KEY);
60 40
@@ -71,33 +51,14 @@ @@ -71,33 +51,14 @@
71 }, 51 },
72 }); 52 });
73 53
74 - onMounted(async () => {  
75 - if (isAdmin(role)) {  
76 - const res = await getTenantPageList();  
77 - selectOptions.value = res.map((m) => ({ label: m.name, value: m.tenantId }));  
78 - } else {  
79 - //租户  
80 - const { token } = await getUserToken(userInfo?.userId);  
81 - getToken.value = token;  
82 - }  
83 - });  
84 -  
85 - const selectOptions = ref<selectType[]>([]);  
86 -  
87 const testDisabled = ref(true); 54 const testDisabled = ref(true);
88 55
89 - const selectTenantOptions = ref<selectType[]>([]);  
90 -  
91 const { createMessage } = useMessage(); 56 const { createMessage } = useMessage();
92 57
93 const showTestEditCell = ref(false); 58 const showTestEditCell = ref(false);
94 59
95 const excuteData = ref({}); 60 const excuteData = ref({});
96 61
97 - const selectTenant = ref(undefined);  
98 -  
99 - const selectSysTenant = ref(undefined);  
100 -  
101 const testEditCellTableRef = ref<InstanceType<typeof TestParamsCellTable>>(); 62 const testEditCellTableRef = ref<InstanceType<typeof TestParamsCellTable>>();
102 63
103 const testResult = ref(''); 64 const testResult = ref('');
@@ -106,26 +67,11 @@ @@ -106,26 +67,11 @@
106 67
107 const getToken = ref(''); 68 const getToken = ref('');
108 69
109 - const onSelect = async (e) => {  
110 - if (e) {  
111 - testDisabled.value = false;  
112 - } else {  
113 - testDisabled.value = true;  
114 - }  
115 - selectSysTenant.value = undefined;  
116 - const rest = (await getTenantAllPageLists(e)) as any;  
117 - selectTenantOptions.value = rest?.map((m) => ({ label: m.realName, value: m.id }));  
118 - };  
119 -  
120 - const onSelctTenant = async (e) => {  
121 - if (e) {  
122 - testDisabled.value = false;  
123 - } else {  
124 - testDisabled.value = true;  
125 - }  
126 - const { token } = await getUserToken(e); 70 + const onHandleEmitToken = (token, flag) => {
127 getToken.value = token; 71 getToken.value = token;
  72 + testDisabled.value = flag;
128 }; 73 };
  74 +
129 const isSingleClickText = ref('open'); 75 const isSingleClickText = ref('open');
130 76
131 const handleTest = (o) => { 77 const handleTest = (o) => {
@@ -147,7 +93,7 @@ @@ -147,7 +93,7 @@
147 const getSingleKey = props.data?.list; 93 const getSingleKey = props.data?.list;
148 let getMuteDateRangeKeys: any = null; 94 let getMuteDateRangeKeys: any = null;
149 const findDateRange = getSingleKey.find( 95 const findDateRange = getSingleKey.find(
150 - (item) => item?.key == 'date_range' && item?.mores === true 96 + (item) => item?.key == TableDefaultTypeEnum.DATERANGE && item?.mores === true
151 ); 97 );
152 if (findDateRange) { 98 if (findDateRange) {
153 getMuteDateRangeKeys = getMultipleKeys([{ key: 'agg', value: '' }]); 99 getMuteDateRangeKeys = getMultipleKeys([{ key: 'agg', value: '' }]);
@@ -164,14 +110,13 @@ @@ -164,14 +110,13 @@
164 }; 110 };
165 111
166 //测试表格里的数据转化为 key value 数组对象形式 112 //测试表格里的数据转化为 key value 数组对象形式
167 - //TODO:待优化这里的TS类型  
168 const getTestTableKeyValue = () => { 113 const getTestTableKeyValue = () => {
169 //把日期拆分成多个 114 //把日期拆分成多个
170 const keyValueList: any = []; 115 const keyValueList: any = [];
171 - console.log(testEditCellTableRef.value?.getValue());  
172 testEditCellTableRef.value?.getValue()?.forEach((item: any) => { 116 testEditCellTableRef.value?.getValue()?.forEach((item: any) => {
173 - const splitDateKey = item?.key === 'date_range' ? item?.value?.split(',') : [];  
174 - const splitDateValue = item?.key === 'date_range' ? item?.dateValue : []; 117 + const splitDateKey =
  118 + item?.key === TableDefaultTypeEnum.DATERANGE ? item?.value?.split(',') : [];
  119 + const splitDateValue = item?.key === TableDefaultTypeEnum.DATERANGE ? item?.dateValue : [];
175 for (let i in splitDateKey) { 120 for (let i in splitDateKey) {
176 const obj = { 121 const obj = {
177 key: splitDateKey[i], 122 key: splitDateKey[i],
@@ -183,17 +128,11 @@ @@ -183,17 +128,11 @@
183 return testEditCellTableRef.value 128 return testEditCellTableRef.value
184 ?.getValue() 129 ?.getValue()
185 .concat(keyValueList) 130 .concat(keyValueList)
186 - .filter((it) => it.key !== 'date_range') 131 + .filter((it) => it.key !== TableDefaultTypeEnum.DATERANGE)
187 .map((it: any) => { 132 .map((it: any) => {
188 - const value =  
189 - it?.key === 'scope'  
190 - ? it?.keyValue  
191 - : it?.key === 'fixed_date'  
192 - ? moment(it?.fixed_date_value).valueOf()  
193 - : it?.value;  
194 - const key = it?.key === 'scope' || it?.key === 'fixed_date' ? it?.value : it?.key; 133 + const value = it?.key === TableDefaultTypeEnum.SCOPE ? it?.keyValue : it?.value;
  134 + const key = it?.key === TableDefaultTypeEnum.SCOPE ? it?.value : it?.key;
195 const limit = it?.limit; 135 const limit = it?.limit;
196 - console.log(limit);  
197 return { 136 return {
198 key, 137 key,
199 value, 138 value,
@@ -213,16 +152,15 @@ @@ -213,16 +152,15 @@
213 } 152 }
214 const params: any = {}; 153 const params: any = {};
215 getTable?.map((it) => { 154 getTable?.map((it) => {
216 - console.log(it);  
217 params[it.key!] = it.value!; 155 params[it.key!] = it.value!;
218 - if (it.key === 'agg') { 156 + if (it.key === TableDefaultTypeEnum.AGG) {
219 params.limit = it.limit; 157 params.limit = it.limit;
220 } 158 }
221 }); 159 });
222 if (params['keys']) { 160 if (params['keys']) {
223 Reflect.set(params, 'keys', params['keys'].join(',')); 161 Reflect.set(params, 'keys', params['keys'].join(','));
224 } 162 }
225 - if (params['agg'] !== 'NONE') { 163 + if (params['agg'] !== AggregateDataEnum.NONE) {
226 Reflect.set(params, 'limit', null); 164 Reflect.set(params, 'limit', null);
227 } 165 }
228 excuteData.value = { 166 excuteData.value = {
@@ -234,11 +172,9 @@ @@ -234,11 +172,9 @@
234 172
235 //设置数据 173 //设置数据
236 const setValue = () => { 174 const setValue = () => {
  175 + isSingleClickText.value = 'open';
237 showTestEditCell.value = false; 176 showTestEditCell.value = false;
238 testResult.value = ''; 177 testResult.value = '';
239 - selectTenant.value = undefined;  
240 - selectSysTenant.value = undefined;  
241 - selectTenantOptions.value = [];  
242 }; 178 };
243 179
244 const onCloseTest = () => { 180 const onCloseTest = () => {
1 -<!-- eslint-disable vue/valid-v-model -->  
2 <template> 1 <template>
3 - <!-- {{ tableTestArray.content }} -->  
4 <div class="table-content"> 2 <div class="table-content">
5 - <!-- TODO: 待优化测试表格 -->  
6 <table align="center"> 3 <table align="center">
7 <thead> 4 <thead>
8 <tr> 5 <tr>
@@ -17,30 +14,18 @@ @@ -17,30 +14,18 @@
17 </thead> 14 </thead>
18 <tbody> 15 <tbody>
19 <tr v-for="(item, index) in tableTestArray.content" :key="index"> 16 <tr v-for="(item, index) in tableTestArray.content" :key="index">
20 - <td style="width: 7.5vw">  
21 - <Select  
22 - :getPopupContainer="  
23 - (triggerNode) => {  
24 - return triggerNode.parentNode;  
25 - }  
26 - "  
27 - :disabled="true"  
28 - v-model:value="item.key"  
29 - placeholder="请选择"  
30 - :options="selectOptions"  
31 - /> 17 + <td>
  18 + <Select :disabled="true" v-model:value="item.key" :options="selectOptions" />
32 </td> 19 </td>
33 - <td style="width: 6.5vw">  
34 - <a-input v-if="item.key === 'scope'" placeholder="请输入" v-model:value="item.value" /> 20 + <td style="width: 10.5vw">
  21 + <a-input
  22 + v-if="item.key === TableDefaultTypeEnum.SCOPE"
  23 + placeholder="请输入"
  24 + v-model:value="item.value"
  25 + />
35 <a-tree-select 26 <a-tree-select
36 - :getPopupContainer="  
37 - (triggerNode) => {  
38 - return triggerNode.parentNode;  
39 - }  
40 - "  
41 - v-else-if="item.key === 'organizationId'" 27 + v-else-if="item.key === TableDefaultTypeEnum.ORGANIZATIONID"
42 v-model:value="item.value" 28 v-model:value="item.value"
43 - show-search  
44 :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }" 29 :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
45 placeholder="请选择组织" 30 placeholder="请选择组织"
46 allow-clear 31 allow-clear
@@ -54,10 +39,9 @@ @@ -54,10 +39,9 @@
54 return triggerNode.parentNode; 39 return triggerNode.parentNode;
55 } 40 }
56 " 41 "
57 - v-else-if="item.key === 'entityId'" 42 + v-else-if="item.key === TableDefaultTypeEnum.ENTITYID"
58 v-model:value="item.value" 43 v-model:value="item.value"
59 placeholder="请选择" 44 placeholder="请选择"
60 - notFoundContent="请选择"  
61 :options="entityOptions" 45 :options="entityOptions"
62 allowClear 46 allowClear
63 /> 47 />
@@ -67,24 +51,21 @@ @@ -67,24 +51,21 @@
67 return triggerNode.parentNode; 51 return triggerNode.parentNode;
68 } 52 }
69 " 53 "
70 - v-else-if="item.key === 'keys'" 54 + v-else-if="item.key === TableDefaultTypeEnum.KEYS"
71 v-model:value="item.value" 55 v-model:value="item.value"
72 placeholder="请选择" 56 placeholder="请选择"
73 - notFoundContent="请选择"  
74 :options="attributeOptions" 57 :options="attributeOptions"
75 mode="multiple" 58 mode="multiple"
76 allowClear 59 allowClear
77 /> 60 />
78 - <!-- <div v-else-if="item.value === 'NONE'">  
79 - <a-input-number id="inputNumber" v-model:value="item.value" :min="7" :max="5000000" />  
80 - </div> -->  
81 - <div v-else-if="item.key === 'date_range'">  
82 - <a-button disabled type="primary">{{ item.value?.split(',').at(-2) }}</a-button> 61 + <div v-else-if="item.key === TableDefaultTypeEnum.DATERANGE">
  62 + <a-button disabled type="primary">{{
  63 + (item.value as any)?.split(',').at(-2)
  64 + }}</a-button>
83 <span>~</span> 65 <span>~</span>
84 - <a-button disabled type="primary">{{ item.value?.split(',').at(-1) }}</a-button>  
85 - </div>  
86 - <div v-else-if="item.key === 'fixed_date'">  
87 - <a-button disabled type="primary">{{ item.value }}</a-button> 66 + <a-button disabled type="primary">{{
  67 + (item.value as any)?.split(',').at(-1)
  68 + }}</a-button>
88 </div> 69 </div>
89 <Select 70 <Select
90 :getPopupContainer=" 71 :getPopupContainer="
@@ -92,11 +73,10 @@ @@ -92,11 +73,10 @@
92 return triggerNode.parentNode; 73 return triggerNode.parentNode;
93 } 74 }
94 " 75 "
95 - v-else-if="item.key === 'agg'" 76 + v-else-if="item.key === TableDefaultTypeEnum.AGG"
96 v-model:value="item.value" 77 v-model:value="item.value"
97 @change="onHandleAgg" 78 @change="onHandleAgg"
98 placeholder="请选择" 79 placeholder="请选择"
99 - notFoundContent="请选择"  
100 :options="aggOptions" 80 :options="aggOptions"
101 allowClear 81 allowClear
102 /> 82 />
@@ -106,10 +86,11 @@ @@ -106,10 +86,11 @@
106 return triggerNode.parentNode; 86 return triggerNode.parentNode;
107 } 87 }
108 " 88 "
109 - v-else-if="item.key === 'interval' && item.value !== 'NONE'" 89 + v-else-if="
  90 + item.key === TableDefaultTypeEnum.INTERVAL && item.value !== AggregateDataEnum.NONE
  91 + "
110 v-model:value="item.value" 92 v-model:value="item.value"
111 placeholder="请选择" 93 placeholder="请选择"
112 - notFoundContent="请选择"  
113 :options="intervalOptions" 94 :options="intervalOptions"
114 allowClear 95 allowClear
115 /> 96 />
@@ -122,39 +103,34 @@ @@ -122,39 +103,34 @@
122 v-else 103 v-else
123 v-model:value="item.value" 104 v-model:value="item.value"
124 placeholder="请选择" 105 placeholder="请选择"
125 - notFoundContent="请选择"  
126 :options="valueOptions" 106 :options="valueOptions"
127 allowClear 107 allowClear
128 @change="handleValueChange(item)" 108 @change="handleValueChange(item)"
129 /> 109 />
130 </td> 110 </td>
131 - <td style="width: 6.5vw"> 111 + <td>
132 <a-input 112 <a-input
133 - v-if="item.key === 'scope'" 113 + v-if="item.key === TableDefaultTypeEnum.SCOPE"
134 placeholder="请输入" 114 placeholder="请输入"
135 v-model:value="item.keyValue" 115 v-model:value="item.keyValue"
136 /> 116 />
137 - <a-date-picker  
138 - v-else-if="item.key === 'fixed_date'"  
139 - style="width: 6.5vw"  
140 - v-model:value="item.fixed_date_value"  
141 - :show-time="{ format: 'HH:mm' }"  
142 - format="YYYY-MM-DD HH:mm:ss"  
143 - placeholder="日期时间"  
144 - />  
145 <a-range-picker 117 <a-range-picker
146 - v-else-if="item.key == 'date_range'" 118 + v-else-if="item.key == TableDefaultTypeEnum.DATERANGE"
147 style="width: 10vw" 119 style="width: 10vw"
148 v-model:value="item.dateValue" 120 v-model:value="item.dateValue"
149 :disabled-date="disabledDate" 121 :disabled-date="disabledDate"
150 - :show-time="{ format: 'HH:mm:ss' }" 122 + :show-time="{
  123 + format: 'HH:mm:ss',
  124 + defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')],
  125 + }"
151 @calendarChange="calendarPriceRangeChange" 126 @calendarChange="calendarPriceRangeChange"
152 @change="changePriceRangeDate" 127 @change="changePriceRangeDate"
153 format="YYYY-MM-DD HH:mm:ss" 128 format="YYYY-MM-DD HH:mm:ss"
154 - :placeholder="['开始', '结束']" 129 + :placeholder="['开始日期', '结束日期']"
  130 + clearable
155 /> 131 />
156 <a-input-number 132 <a-input-number
157 - v-else-if="item.value == 'NONE'" 133 + v-else-if="item.value == AggregateDataEnum.NONE"
158 v-model:value="item.limit" 134 v-model:value="item.limit"
159 :min="7" 135 :min="7"
160 :max="50000" 136 :max="50000"
@@ -164,7 +140,6 @@ @@ -164,7 +140,6 @@
164 </tr> 140 </tr>
165 </tbody> 141 </tbody>
166 </table> 142 </table>
167 - <!-- {{ tableTestArray.content }} -->  
168 </div> 143 </div>
169 </template> 144 </template>
170 <script lang="ts" setup name="editCellTable"> 145 <script lang="ts" setup name="editCellTable">
@@ -181,6 +156,7 @@ @@ -181,6 +156,7 @@
181 import { AggregateDataEnum } from '/@/views/report/config/timeConfig'; 156 import { AggregateDataEnum } from '/@/views/report/config/timeConfig';
182 import { getPacketIntervalByRange } from '/@/views/device/localtion/cpns/TimePeriodForm/helper'; 157 import { getPacketIntervalByRange } from '/@/views/device/localtion/cpns/TimePeriodForm/helper';
183 import { uniqBy } from 'lodash'; 158 import { uniqBy } from 'lodash';
  159 + import { TableDefaultTypeEnum } from '../../../config/enum';
184 160
185 const props = defineProps({ 161 const props = defineProps({
186 method: { 162 method: {
@@ -207,7 +183,9 @@ @@ -207,7 +183,9 @@
207 value: 'scope', 183 value: 'scope',
208 }); 184 });
209 if (props.method === '2') 185 if (props.method === '2')
210 - selectOptions.value = selectOptions.value.filter((f) => f.value !== 'scope'); 186 + selectOptions.value = selectOptions.value.filter(
  187 + (f) => f.value !== TableDefaultTypeEnum.SCOPE
  188 + );
211 }); 189 });
212 190
213 const { isOtherHttp } = useUtils(); 191 const { isOtherHttp } = useUtils();
@@ -242,8 +220,15 @@ @@ -242,8 +220,15 @@
242 }); 220 });
243 221
244 const onHandleAgg = (e) => { 222 const onHandleAgg = (e) => {
245 - if (e === 'NONE') {  
246 - tableTestArray.content = tableTestArray.content.filter((item) => item.key !== 'interval'); 223 + if (e === AggregateDataEnum.NONE) {
  224 + tableTestArray.content = tableTestArray.content.filter(
  225 + (item) => item.key !== TableDefaultTypeEnum.INTERVAL
  226 + );
  227 + tableTestArray.content.forEach((it) => {
  228 + if (it.key === TableDefaultTypeEnum.AGG && it.value === AggregateDataEnum.NONE) {
  229 + it.limit = 7;
  230 + }
  231 + });
247 } else { 232 } else {
248 tableTestArray.content.push({ 233 tableTestArray.content.push({
249 key: 'interval', 234 key: 'interval',
@@ -255,8 +240,6 @@ @@ -255,8 +240,6 @@
255 240
256 const selectPriceDate = ref(''); 241 const selectPriceDate = ref('');
257 242
258 - const offsetDays = 86400000 * 365;  
259 -  
260 const calendarPriceRangeChange = (date) => { 243 const calendarPriceRangeChange = (date) => {
261 selectPriceDate.value = date[0]; 244 selectPriceDate.value = date[0];
262 intervalOptions.value = getPacketIntervalByRange(date) as any; 245 intervalOptions.value = getPacketIntervalByRange(date) as any;
@@ -266,6 +249,8 @@ @@ -266,6 +249,8 @@
266 selectPriceDate.value = ''; 249 selectPriceDate.value = '';
267 }; 250 };
268 251
  252 + //时间跨度小于一年
  253 + const offsetDays = 86400000 * 365;
269 const disabledDate = (current) => { 254 const disabledDate = (current) => {
270 if (selectPriceDate.value) { 255 if (selectPriceDate.value) {
271 let selectV = moment(selectPriceDate.value, 'YYYY-MM-DD').valueOf(); 256 let selectV = moment(selectPriceDate.value, 'YYYY-MM-DD').valueOf();
@@ -282,34 +267,38 @@ @@ -282,34 +267,38 @@
282 const setTableArray = (data) => { 267 const setTableArray = (data) => {
283 const list = cloneDeep(data); 268 const list = cloneDeep(data);
284 list?.forEach((it) => { 269 list?.forEach((it) => {
285 - if (it.key === 'keys') it.value = []; 270 + if (it?.value === TableDefaultTypeEnum.ENTITYTYPE) it.keyValue = TableDefaultTypeEnum.DEVICE;
  271 + if (it.key === TableDefaultTypeEnum.KEYS) it.value = [];
286 }); 272 });
287 if (Array.isArray(list)) (tableTestArray.content = list) && getApi(list); 273 if (Array.isArray(list)) (tableTestArray.content = list) && getApi(list);
288 }; 274 };
289 275
  276 + //获取组织和产品
290 const getApi = (list) => { 277 const getApi = (list) => {
291 list?.forEach(async (it) => { 278 list?.forEach(async (it) => {
292 - if (it.key === 'deviceProfileId') { 279 + if (it.key === TableDefaultTypeEnum.DEVICEPROFILEID) {
293 const { options } = await useApi(it.key, props.token); 280 const { options } = await useApi(it.key, props.token);
294 valueOptions.value = options; 281 valueOptions.value = options;
295 - } else if (it.key === 'organizationId') { 282 + } else if (it.key === TableDefaultTypeEnum.ORGANIZATIONID) {
296 const { options } = await useApi(it.key, props.token); 283 const { options } = await useApi(it.key, props.token);
297 treeData.value = options as any; 284 treeData.value = options as any;
298 } 285 }
299 }); 286 });
300 }; 287 };
301 288
  289 + //组织Select改变
302 const handleOrgnationChange = async (e) => { 290 const handleOrgnationChange = async (e) => {
303 let deviceProfileId = ''; 291 let deviceProfileId = '';
304 tableTestArray.content.forEach((f: any) => { 292 tableTestArray.content.forEach((f: any) => {
305 - if (f.key === 'entityId') { 293 + if (f.key === TableDefaultTypeEnum.ENTITYID) {
306 f.value = null; 294 f.value = null;
307 } 295 }
308 - if (f.key === 'deviceProfileId') deviceProfileId = f.value; 296 + if (f.key === TableDefaultTypeEnum.DEVICEPROFILEID) deviceProfileId = f.value;
309 }); 297 });
310 getEntityOptions(e.value, deviceProfileId); 298 getEntityOptions(e.value, deviceProfileId);
311 }; 299 };
312 300
  301 + //设备Select改变
313 const getEntityOptions = async (organizationId: string, deviceProfileId?: string) => { 302 const getEntityOptions = async (organizationId: string, deviceProfileId?: string) => {
314 const res = await isOtherHttp('api/yt/device/list', props.token, { 303 const res = await isOtherHttp('api/yt/device/list', props.token, {
315 organizationId, 304 organizationId,
@@ -321,6 +310,7 @@ @@ -321,6 +310,7 @@
321 })); 310 }));
322 }; 311 };
323 312
  313 + //属性Select改变
324 const getAttributeOptions = async (params) => { 314 const getAttributeOptions = async (params) => {
325 const { deviceProfileId, dataType } = params; 315 const { deviceProfileId, dataType } = params;
326 const res = await isOtherHttp(`api/yt/device/attributes/${deviceProfileId}`, props.token, { 316 const res = await isOtherHttp(`api/yt/device/attributes/${deviceProfileId}`, props.token, {
@@ -330,15 +320,16 @@ @@ -330,15 +320,16 @@
330 attributeOptions.value = res?.map((item) => ({ label: item.name, value: item.identifier })); 320 attributeOptions.value = res?.map((item) => ({ label: item.name, value: item.identifier }));
331 }; 321 };
332 322
  323 + //产品Select改变
333 const handleValueChange = (e) => { 324 const handleValueChange = (e) => {
334 let organizationId = ''; 325 let organizationId = '';
335 - if (e.key === 'deviceProfileId') { 326 + if (e.key === TableDefaultTypeEnum.DEVICEPROFILEID) {
336 tableTestArray.content.forEach((f: any) => { 327 tableTestArray.content.forEach((f: any) => {
337 - if (f.key === 'keys') { 328 + if (f.key === TableDefaultTypeEnum.KEYS) {
338 f.value = []; 329 f.value = [];
339 } 330 }
340 - if (f.key === 'organizationId') organizationId = f.value;  
341 - if (f.key === 'entityId') f.value = null; 331 + if (f.key === TableDefaultTypeEnum.ORGANIZATIONID) organizationId = f.value;
  332 + if (f.key === TableDefaultTypeEnum.ENTITYID) f.value = null;
342 }); 333 });
343 if (e.value) { 334 if (e.value) {
344 getAttributeOptions({ deviceProfileId: e.value }); 335 getAttributeOptions({ deviceProfileId: e.value });
@@ -353,6 +344,7 @@ @@ -353,6 +344,7 @@
353 const getValue = () => { 344 const getValue = () => {
354 return tableTestArray.content; 345 return tableTestArray.content;
355 }; 346 };
  347 +
356 defineExpose({ 348 defineExpose({
357 getValue, 349 getValue,
358 setTableArray, 350 setTableArray,
@@ -360,28 +352,5 @@ @@ -360,28 +352,5 @@
360 </script> 352 </script>
361 353
362 <style scoped lang="less"> 354 <style scoped lang="less">
363 - @table-color: #e5e7eb;  
364 -  
365 - .table-border-color {  
366 - border: 1px solid #e5e7eb;  
367 - text-align: center;  
368 - }  
369 -  
370 - .table-content {  
371 - table {  
372 - width: 31vw;  
373 - &:extend(.table-border-color);  
374 - }  
375 -  
376 - table td {  
377 - padding: 5px;  
378 - white-space: nowrap;  
379 - &:extend(.table-border-color);  
380 - }  
381 -  
382 - table th {  
383 - padding: 5px;  
384 - &:extend(.table-border-color);  
385 - }  
386 - } 355 + @import '../../SimpleRequest/common/commonTestTable.less';
387 </style> 356 </style>
1 -import TestSql from './index.vue';  
2 -  
3 -export { TestSql };  
1 -<template>  
2 - <div class="mt-8">  
3 - <div>  
4 - <Button @click="handleExcute" type="primary"> 测试SQL </Button>  
5 - </div>  
6 - </div>  
7 - <div v-if="testResultStatus" class="mt-8">  
8 - <div class="mt-8">  
9 - <a-row type="flex" justify="center">  
10 - <a-col :span="3"> 测试结果 </a-col>  
11 - <a-col :span="21">  
12 - <a-textarea  
13 - allow-clear  
14 - show-count  
15 - v-model:value="testResult"  
16 - placeholder="测试结果为:"  
17 - :rows="8"  
18 - />  
19 - </a-col>  
20 - </a-row>  
21 - </div>  
22 - </div>  
23 -</template>  
24 -<script lang="ts" setup name="testRequest">  
25 - import { ref } from 'vue';  
26 - import { Button } from 'ant-design-vue';  
27 -  
28 - defineProps({  
29 - method: {  
30 - type: String,  
31 - },  
32 - });  
33 -  
34 - const testResult = ref('');  
35 -  
36 - const testResultStatus = ref(false);  
37 -  
38 - const handleExcute = async () => {  
39 - testResultStatus.value = true;  
40 - testResult.value = '测试结果为:1234';  
41 - };  
42 -  
43 - const resetValue = () => (testResult.value = '');  
44 -  
45 - defineExpose({  
46 - resetValue,  
47 - });  
48 -</script>  
49 -  
50 -<style scoped lang="less"></style>  
@@ -288,14 +288,6 @@ export const schemas: FormSchema[] = [ @@ -288,14 +288,6 @@ export const schemas: FormSchema[] = [
288 colProps: { span: 24 }, 288 colProps: { span: 24 },
289 ifShow: ({ values }) => values['requestContentType'] !== '1', 289 ifShow: ({ values }) => values['requestContentType'] !== '1',
290 }, 290 },
291 - {  
292 - field: 'testSlot',  
293 - label: '',  
294 - component: 'Input',  
295 - slot: 'testSql',  
296 - colProps: { span: 24 },  
297 - ifShow: ({ values }) => values['requestContentType'] === '1',  
298 - },  
299 ]; 291 ];
300 292
301 //表格表头配置 293 //表格表头配置
1 ///公共接口管理所需枚举值 1 ///公共接口管理所需枚举值
2 2
3 /** 3 /**
4 - * @description: 请求体类型 4 + * @description: 请求体类型枚举
5 */ 5 */
6 export enum RequestBodyTypeEnum { 6 export enum RequestBodyTypeEnum {
7 NONE = 'none', 7 NONE = 'none',
@@ -12,7 +12,7 @@ export enum RequestBodyTypeEnum { @@ -12,7 +12,7 @@ export enum RequestBodyTypeEnum {
12 } 12 }
13 13
14 /** 14 /**
15 - * @description: 请求方式 15 + * @description: 请求方式枚举
16 */ 16 */
17 export enum RequestMethodTypeEnum { 17 export enum RequestMethodTypeEnum {
18 COMMOM = '0', 18 COMMOM = '0',
@@ -21,9 +21,41 @@ export enum RequestMethodTypeEnum { @@ -21,9 +21,41 @@ export enum RequestMethodTypeEnum {
21 } 21 }
22 22
23 /** 23 /**
24 - * @description: 源地址类型 24 + * @description: 源地址类型枚举
25 */ 25 */
26 export enum RequestOriginTypeEnum { 26 export enum RequestOriginTypeEnum {
27 CUSTOM_URL = 'custom_url', 27 CUSTOM_URL = 'custom_url',
28 SERVER_URL = 'server_url', 28 SERVER_URL = 'server_url',
29 } 29 }
  30 +
  31 +/**
  32 + * @description: 请求类型枚举
  33 + */
  34 +export enum RequestHttpTypeEnum {
  35 + GET = 'GET',
  36 + POST = 'POST',
  37 +}
  38 +
  39 +/**
  40 + * @description: 在线编辑器枚举
  41 + */
  42 +export enum OnlineEditorTypeEnum {
  43 + JAVASCRIPT = 'javascript',
  44 + XML = 'xml',
  45 +}
  46 +
  47 +/**
  48 + * @description:表格内置默认属性枚举
  49 + */
  50 +export enum TableDefaultTypeEnum {
  51 + ORGANIZATIONID = 'organizationId',
  52 + SCOPE = 'scope',
  53 + ENTITYID = 'entityId',
  54 + KEYS = 'keys',
  55 + DATERANGE = 'date_range',
  56 + AGG = 'agg',
  57 + INTERVAL = 'interval',
  58 + DEVICEPROFILEID = 'deviceProfileId',
  59 + ENTITYTYPE = 'entityType',
  60 + DEVICE = 'DEVICE',
  61 +}
@@ -14,8 +14,12 @@ @@ -14,8 +14,12 @@
14 watchRequestHttpTypeAndUrl(model['requestHttpTypeAndUrl']) 14 watchRequestHttpTypeAndUrl(model['requestHttpTypeAndUrl'])
15 }}</p> 15 }}</p>
16 <SimpleRequest 16 <SimpleRequest
  17 + v-if="
  18 + [RequestMethodTypeEnum.COMMOM, RequestMethodTypeEnum.WEBSOCKET].includes(
  19 + model['requestContentType']
  20 + )
  21 + "
17 ref="simpleRequestRef" 22 ref="simpleRequestRef"
18 - v-if="model['requestContentType'] === '0' || model['requestContentType'] === '2'"  
19 :requestTypeAndUrl="model['requestHttpTypeAndUrl']" 23 :requestTypeAndUrl="model['requestHttpTypeAndUrl']"
20 :method="model['requestContentType']" 24 :method="model['requestContentType']"
21 :requestOriginUrl="model['requestOriginUrl']" 25 :requestOriginUrl="model['requestOriginUrl']"
@@ -23,23 +27,10 @@ @@ -23,23 +27,10 @@
23 :interfaceType="model['interfaceType']" 27 :interfaceType="model['interfaceType']"
24 /> 28 />
25 </template> 29 </template>
26 - <template #testSql="{ model }">  
27 - <div style="margin: auto 7.5rem">  
28 - <TestSql  
29 - ref="testSqlRef"  
30 - v-if="model['requestContentType'] === '1'"  
31 - :method="model['requestContentType']"  
32 - />  
33 - </div>  
34 - </template>  
35 <template #slotFillAddress="{ model }"> 30 <template #slotFillAddress="{ model }">
36 <div> 31 <div>
37 - <template v-if="model['originUrlType'] === 'custom_url'">  
38 - <Tag  
39 - v-if="model['requestOriginUrl']"  
40 - color="blue"  
41 - style="width: 35vw; white-space: normal; height: auto"  
42 - > 32 + <template v-if="[RequestOriginTypeEnum.CUSTOM_URL].includes(model['originUrlType'])">
  33 + <Tag v-if="model['requestOriginUrl']" color="blue" class="tag-text">
43 {{ ` ${model['requestOriginUrl'] + model['requestHttpTypeAndUrl']?.requestUrl}` }} 34 {{ ` ${model['requestOriginUrl'] + model['requestHttpTypeAndUrl']?.requestUrl}` }}
44 </Tag> 35 </Tag>
45 </template> 36 </template>
@@ -48,9 +39,9 @@ @@ -48,9 +39,9 @@
48 <template #slotServerAddress="{ model }"> 39 <template #slotServerAddress="{ model }">
49 <div> 40 <div>
50 <Tag 41 <Tag
51 - v-if="model['originUrlType'] === 'server_url'" 42 + v-if="[RequestOriginTypeEnum.SERVER_URL].includes(model['originUrlType'])"
52 color="blue" 43 color="blue"
53 - style="width: 35vw; white-space: normal; height: auto" 44 + class="tag-text"
54 > 45 >
55 {{ 46 {{
56 ` ${`${templateFillAddress(model['requestContentType'], model['originUrlType'])}${ 47 ` ${`${templateFillAddress(model['requestContentType'], model['originUrlType'])}${
@@ -71,17 +62,16 @@ @@ -71,17 +62,16 @@
71 import { BasicForm, useForm } from '/@/components/Form'; 62 import { BasicForm, useForm } from '/@/components/Form';
72 import { schemas } from './config/config'; 63 import { schemas } from './config/config';
73 import SimpleRequest from './components/SimpleRequest/index.vue'; 64 import SimpleRequest from './components/SimpleRequest/index.vue';
74 - import { TestSql } from './components/TestSql/index';  
75 import { 65 import {
76 saveDataViewInterface, 66 saveDataViewInterface,
77 updateDataViewInterface, 67 updateDataViewInterface,
78 } from '/@/api/bigscreen/center/bigscreenCenter'; 68 } from '/@/api/bigscreen/center/bigscreenCenter';
79 -  
80 import { useMessage } from '/@/hooks/web/useMessage'; 69 import { useMessage } from '/@/hooks/web/useMessage';
81 import { useUtils } from './hooks/useUtils'; 70 import { useUtils } from './hooks/useUtils';
82 import { Tag } from 'ant-design-vue'; 71 import { Tag } from 'ant-design-vue';
  72 + import { RequestMethodTypeEnum, RequestOriginTypeEnum } from './config/enum';
83 73
84 - const { resetReqHttpType, isServerUrl } = useUtils(); 74 + const { resetReqHttpType, isServerUrl, resetUpdateSchema } = useUtils();
85 75
86 const emits = defineEmits(['success', 'register']); 76 const emits = defineEmits(['success', 'register']);
87 77
@@ -93,8 +83,6 @@ @@ -93,8 +83,6 @@
93 83
94 const simpleRequestRef = ref<InstanceType<typeof SimpleRequest>>(); 84 const simpleRequestRef = ref<InstanceType<typeof SimpleRequest>>();
95 85
96 - const testSqlRef = ref<InstanceType<typeof TestSql>>();  
97 -  
98 const templateFillAddress = (method, type) => { 86 const templateFillAddress = (method, type) => {
99 return isServerUrl(method, type); 87 return isServerUrl(method, type);
100 }; 88 };
@@ -136,15 +124,10 @@ @@ -136,15 +124,10 @@
136 setFieldsValue(resetReqHttpType); 124 setFieldsValue(resetReqHttpType);
137 const title = `${!data.isUpdate ? '新增' : '修改'}公共接口`; 125 const title = `${!data.isUpdate ? '新增' : '修改'}公共接口`;
138 setDrawerProps({ title }); 126 setDrawerProps({ title });
139 - updateSchema({  
140 - field: 'requestHttpTypeAndUrl',  
141 - componentProps: {  
142 - type: '0',  
143 - },  
144 - }); 127 + updateSchema(resetUpdateSchema);
145 isUpdate.value = data.isUpdate; 128 isUpdate.value = data.isUpdate;
146 !isUpdate.value ? (putId.value = '') : (putId.value = data.record.id); 129 !isUpdate.value ? (putId.value = '') : (putId.value = data.record.id);
147 - simpleRequestRef.value?.resetValue() && testSqlRef.value?.resetValue(); 130 + simpleRequestRef.value?.resetValue();
148 if (isUpdate.value) { 131 if (isUpdate.value) {
149 await setFieldsValue({ 132 await setFieldsValue({
150 ...data.record, 133 ...data.record,
@@ -174,7 +157,7 @@ @@ -174,7 +157,7 @@
174 const values = await validate(); 157 const values = await validate();
175 if (!values) return; 158 if (!values) return;
176 const isRequestHttpTypeAndUrlEmpty = values?.requestHttpTypeAndUrl; 159 const isRequestHttpTypeAndUrlEmpty = values?.requestHttpTypeAndUrl;
177 - if (values.requestContentType === '0') { 160 + if (values.requestContentType === RequestMethodTypeEnum.COMMOM) {
178 if ( 161 if (
179 !Reflect.get(isRequestHttpTypeAndUrlEmpty, 'requestHttpType') || 162 !Reflect.get(isRequestHttpTypeAndUrlEmpty, 'requestHttpType') ||
180 !Reflect.get(isRequestHttpTypeAndUrlEmpty, 'requestUrl') 163 !Reflect.get(isRequestHttpTypeAndUrlEmpty, 'requestUrl')
@@ -182,15 +165,18 @@ @@ -182,15 +165,18 @@
182 createMessage.error('请填写请求类型&地址'); 165 createMessage.error('请填写请求类型&地址');
183 throw Error('请填写请求类型&地址'); 166 throw Error('请填写请求类型&地址');
184 } 167 }
185 - } else if (values.requestContentType === '2') { 168 + } else if (values.requestContentType === RequestMethodTypeEnum.WEBSOCKET) {
186 if (!Reflect.get(isRequestHttpTypeAndUrlEmpty, 'requestUrl')) { 169 if (!Reflect.get(isRequestHttpTypeAndUrlEmpty, 'requestUrl')) {
187 createMessage.error('请填写请求类型&地址'); 170 createMessage.error('请填写请求类型&地址');
188 throw Error('请填写请求类型&地址'); 171 throw Error('请填写请求类型&地址');
189 } 172 }
190 } 173 }
191 const Objects = simpleRequestRef.value?.getValue(true); 174 const Objects = simpleRequestRef.value?.getValue(true);
  175 + const filter = simpleRequestRef.value?.getFilterValue();
192 const requestOriginUrl = 176 const requestOriginUrl =
193 - values['originUrlType'] === 'server_url' ? 'localhost' : values['requestOriginUrl']; 177 + values['originUrlType'] === RequestOriginTypeEnum.SERVER_URL
  178 + ? 'localhost'
  179 + : values['requestOriginUrl'];
194 const data = { 180 const data = {
195 ...values, 181 ...values,
196 id: !putId.value ? null : putId.value, 182 id: !putId.value ? null : putId.value,
@@ -200,12 +186,14 @@ @@ -200,12 +186,14 @@
200 }, 186 },
201 ...Objects, 187 ...Objects,
202 }), 188 }),
  189 + filter: !filter ? null : filter,
203 requestOriginUrl, 190 requestOriginUrl,
204 requestHttpType: values['requestHttpTypeAndUrl']?.requestHttpType, 191 requestHttpType: values['requestHttpTypeAndUrl']?.requestHttpType,
205 requestUrl: values['requestHttpTypeAndUrl']?.requestUrl, 192 requestUrl: values['requestHttpTypeAndUrl']?.requestUrl,
206 }; 193 };
207 Reflect.deleteProperty(data, 'requestHttpTypeAndUrl'); 194 Reflect.deleteProperty(data, 'requestHttpTypeAndUrl');
208 - if (values['requestContentType'] === '2') Reflect.deleteProperty(data, 'requestHttpType'); 195 + if (values['requestContentType'] === RequestMethodTypeEnum.WEBSOCKET)
  196 + Reflect.deleteProperty(data, 'requestHttpType');
209 !putId.value ? await saveDataViewInterface(data) : await updateDataViewInterface(data); 197 !putId.value ? await saveDataViewInterface(data) : await updateDataViewInterface(data);
210 emits('success'); 198 emits('success');
211 closeDrawer(); 199 closeDrawer();
@@ -215,3 +203,11 @@ @@ -215,3 +203,11 @@
215 } 203 }
216 }; 204 };
217 </script> 205 </script>
  206 +
  207 +<style lang="less" scoped>
  208 + .tag-text {
  209 + width: 35vw;
  210 + white-space: normal;
  211 + height: auto;
  212 + }
  213 +</style>
1 import { commonHttpPlaceHolder, websocketPlaceHolder } from '../config/constants'; 1 import { commonHttpPlaceHolder, websocketPlaceHolder } from '../config/constants';
2 import { RequestMethodTypeEnum } from '../config/enum'; 2 import { RequestMethodTypeEnum } from '../config/enum';
3 import { otherHttp } from '/@/utils/http/axios'; 3 import { otherHttp } from '/@/utils/http/axios';
  4 +import { tableItems } from '../config/types';
4 5
5 export const useUtils = () => { 6 export const useUtils = () => {
6 //获取多个key 7 //获取多个key
@@ -46,15 +47,19 @@ export const useUtils = () => { @@ -46,15 +47,19 @@ export const useUtils = () => {
46 //对象转get params参数 47 //对象转get params参数
47 const convertObj = (data: object) => { 48 const convertObj = (data: object) => {
48 const _result: any = []; 49 const _result: any = [];
49 - for (const key in data) {  
50 - const value = data[key];  
51 - if (value.constructor == Array) {  
52 - value.forEach(function (_value) {  
53 - _result.push(key + '=' + _value);  
54 - });  
55 - } else {  
56 - _result.push(key + '=' + value); 50 + try {
  51 + for (const key in data) {
  52 + const value = data[key];
  53 + if (value.constructor == Array) {
  54 + value.forEach(function (_value) {
  55 + _result.push(key + '=' + _value);
  56 + });
  57 + } else {
  58 + _result.push(key + '=' + value);
  59 + }
57 } 60 }
  61 + } catch (e) {
  62 + console.log(`Post没有传递params${e}`);
58 } 63 }
59 return _result.join('&'); 64 return _result.join('&');
60 }; 65 };
@@ -104,6 +109,128 @@ export const useUtils = () => { @@ -104,6 +109,128 @@ export const useUtils = () => {
104 : '' 109 : ''
105 }`; 110 }`;
106 111
  112 + //动态获取post请求ContentType类型
  113 + const contentTypeStatic = [
  114 + {
  115 + key: 'xml',
  116 + value: 'text/xml',
  117 + },
  118 + {
  119 + key: 'form-data',
  120 + value: 'multipart/form-data',
  121 + },
  122 + {
  123 + key: 'x-www-form-urlencoded',
  124 + value: 'application/x-www-form-urlencoded',
  125 + },
  126 + {
  127 + key: 'json',
  128 + value: 'application/json',
  129 + },
  130 + ];
  131 +
  132 + const getContentType = (contentType) => {
  133 + const findValue = contentTypeStatic.find((it) => it.key === contentType)?.value;
  134 + if (findValue) return findValue;
  135 + return contentTypeStatic.at(-1)?.value;
  136 + };
  137 +
  138 + const commonHttpParams = (postToken, token, postBodyType, headers) => {
  139 + const mergeHeaders = Object.assign(
  140 + {},
  141 + {
  142 + 'X-Authorization': `Bearer ${!postToken ? token : postToken}`,
  143 + },
  144 + !postBodyType
  145 + ? null
  146 + : {
  147 + 'Content-Type': getContentType(postBodyType),
  148 + },
  149 + headers
  150 + );
  151 + return mergeHeaders;
  152 + };
  153 +
  154 + //websocket请求静态参数
  155 + const staticWebSocketParams = {
  156 + cmdId: 1,
  157 + scope: 'LATEST_TELEMETRY',
  158 + entityType: 'DEVICE',
  159 + };
  160 +
  161 + const commonRest = (data, fn) => {
  162 + if (Object.prototype.toString.call(data) === '[object Object]') {
  163 + fn(data);
  164 + } else if (typeof data === 'string') {
  165 + fn(data);
  166 + } else if (Array.isArray(data)) {
  167 + const temp = {
  168 + data,
  169 + };
  170 + fn(temp);
  171 + } else {
  172 + fn(JSON.stringify(data));
  173 + }
  174 + };
  175 +
  176 + const commonParams = {
  177 + apiUrl: '',
  178 + joinPrefix: false,
  179 + withToken: false,
  180 + errorMessageMode: 'none',
  181 + } as any;
  182 +
  183 + //表格基类
  184 + class CommonFuncValue {
  185 + constructor(public data: tableItems[]) {
  186 + this.data = data;
  187 + }
  188 + get(): tableItems[] {
  189 + return this.data;
  190 + }
  191 + set(outderData: tableItems[]) {
  192 + this.data = outderData;
  193 + }
  194 + reset(): void {
  195 + this.data = [];
  196 + this.data.push({
  197 + key: '',
  198 + value: '',
  199 + required: false,
  200 + });
  201 + }
  202 + }
  203 +
  204 + //paramsTable覆盖父类
  205 + class ParamsFuncValue extends CommonFuncValue {
  206 + constructor(public data: tableItems[], public mores: boolean) {
  207 + super(data);
  208 + this.mores = mores;
  209 + }
  210 + get(): tableItems[] {
  211 + return this.data.map((it) => {
  212 + return {
  213 + key: it.key,
  214 + value: it.key === 'date_range' ? `${it.date1},${it.date2}` : it.value,
  215 + mores: it.key === 'date_range' ? this.mores : null,
  216 + editDisabled: it.editDisabled,
  217 + required: it.required,
  218 + };
  219 + });
  220 + }
  221 + reset(): void {
  222 + this.data = [];
  223 + this.data.push({
  224 + key: undefined,
  225 + value: '',
  226 + editDisabled: false,
  227 + required: false,
  228 + date1: '',
  229 + date2: '',
  230 + });
  231 + }
  232 + }
  233 +
107 return { 234 return {
108 getMultipleKeys, 235 getMultipleKeys,
109 pushObj, 236 pushObj,
@@ -113,5 +240,11 @@ export const useUtils = () => { @@ -113,5 +240,11 @@ export const useUtils = () => {
113 convertObj, 240 convertObj,
114 isOtherHttp, 241 isOtherHttp,
115 usePlaceholder, 242 usePlaceholder,
  243 + commonHttpParams,
  244 + staticWebSocketParams,
  245 + commonRest,
  246 + commonParams,
  247 + CommonFuncValue,
  248 + ParamsFuncValue,
116 }; 249 };
117 }; 250 };
@@ -58,3 +58,9 @@ @@ -58,3 +58,9 @@
58 }, 58 },
59 }); 59 });
60 </script> 60 </script>
  61 +
  62 +<style scoped>
  63 + .vben-collapse-container {
  64 + background-color: white !important;
  65 + }
  66 +</style>