matrix_components 2.0.385 → 2.0.387

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,631 @@
1
+ <template>
2
+ <div class="demo-container">
3
+ <div class="control-panel">
4
+ <h3>动态表单组件演示</h3>
5
+ <!-- 配置文件选择 -->
6
+ <el-form :model="state" ref="formRef" label-position="left">
7
+ <el-button type="primary" @click="getFormData">获取表单数据</el-button>
8
+ <el-button type="default" @click="resetFormData">重置表单</el-button>
9
+ <br />
10
+ <span style="color: red"> 结果:{{ state.formData }} </span>
11
+ <br />
12
+ <br />
13
+ <NsFormTitle title="模型参数">
14
+ <NsForm
15
+ ref="row1Ref"
16
+ :readOnly="state.readOnly"
17
+ backgroundColor="#fff"
18
+ :model="state.model"
19
+ :rows="state.rows"
20
+ formPropKey="rows"
21
+ labelColor="#606266"
22
+ labelWidth="150"
23
+ gapH="20px"
24
+ gapV="10px"
25
+ ></NsForm>
26
+ </NsFormTitle>
27
+ <NsFormTitle title="视频配置">
28
+ <NsForm
29
+ ref="row2Ref"
30
+ :readOnly="state.readOnly"
31
+ backgroundColor="#fff"
32
+ :model="state.model"
33
+ :rows="state.rows2"
34
+ formPropKey="rows2"
35
+ labelColor="#606266"
36
+ labelWidth="150"
37
+ gapH="20px"
38
+ gapV="10px"
39
+ ></NsForm>
40
+ </NsFormTitle>
41
+ <NsFormTitle title="结果保存">
42
+ <NsForm
43
+ ref="row3Ref"
44
+ :readOnly="state.readOnly"
45
+ backgroundColor="#fff"
46
+ :model="state.model"
47
+ :rows="state.rows3"
48
+ formPropKey="rows3"
49
+ labelColor="#606266"
50
+ labelWidth="150"
51
+ gapH="20px"
52
+ gapV="10px"
53
+ ></NsForm>
54
+ </NsFormTitle>
55
+ <NsFormTitle title="级联选择器测试">
56
+ <NsForm
57
+ ref="row4Ref"
58
+ :readOnly="state.readOnly"
59
+ backgroundColor="#fff"
60
+ :model="state.model"
61
+ :rows="state.rows4"
62
+ formPropKey="rows4"
63
+ labelColor="#606266"
64
+ labelWidth="150"
65
+ gapH="20px"
66
+ gapV="10px"
67
+ ></NsForm>
68
+ </NsFormTitle>
69
+ </el-form>
70
+ </div>
71
+ </div>
72
+ </template>
73
+
74
+ <script setup lang="ts">
75
+ import { ElInput, ElMessage, ElRadioGroup, ElCascader } from 'element-plus'
76
+ import { h, onMounted, reactive, ref } from 'vue'
77
+ import { cloneDeep } from 'lodash-es'
78
+ import { nextTick } from 'vue'
79
+
80
+ const props = defineProps({
81
+ readOnly: {
82
+ type: Boolean,
83
+ default: false,
84
+ },
85
+ row: {
86
+ type: Object,
87
+ default: () => ({}),
88
+ },
89
+ })
90
+
91
+ const formRef = ref()
92
+ const row1Ref = ref()
93
+ const row2Ref = ref()
94
+ const row3Ref = ref()
95
+ const row4Ref = ref()
96
+
97
+ const state = reactive({
98
+ formData: {},
99
+ readOnly: props.readOnly,
100
+ model: props.readOnly ? '' : 'vertical',
101
+ rows: [
102
+ [
103
+ {
104
+ key: 'confidence',
105
+ label: '置信度',
106
+ value: 'aaa',
107
+ component: ElInput,
108
+ params: {
109
+ rules: [
110
+ {
111
+ required: true,
112
+ message: '请输入',
113
+ },
114
+ ],
115
+ },
116
+ },
117
+ {
118
+ key: 'iou',
119
+ label: '交并比',
120
+ value: '',
121
+ component: ElInput,
122
+ params: {
123
+ 'v-length.range': {
124
+ min: 0,
125
+ max: 1,
126
+ maxLength: 3,
127
+ },
128
+ rules: [
129
+ {
130
+ required: true,
131
+ message: '请输入',
132
+ },
133
+ ],
134
+ },
135
+ },
136
+ ],
137
+ ],
138
+ rows2: [
139
+ [
140
+ {
141
+ key: 'timeInterval',
142
+ label: '时间间隔(秒)',
143
+ value: '',
144
+ component: ElInput,
145
+ params: {
146
+ 'v-length.range': {
147
+ min: 0,
148
+ max: 6000,
149
+ int: true,
150
+ },
151
+ rules: [
152
+ {
153
+ required: true,
154
+ message: '请输入',
155
+ },
156
+ ],
157
+ },
158
+ },
159
+ {
160
+ key: 'stuck_threshold',
161
+ label: '视频帧卡顿(秒)',
162
+ value: '',
163
+ component: ElInput,
164
+ params: {
165
+ 'v-length.range': {
166
+ min: 0,
167
+ max: 1000,
168
+ int: true,
169
+ },
170
+ rules: [
171
+ {
172
+ required: true,
173
+ message: '请输入',
174
+ },
175
+ ],
176
+ },
177
+ },
178
+ ],
179
+ [
180
+ {
181
+ key: 'max_retries',
182
+ label: '最大重连次数',
183
+ value: '',
184
+ component: ElInput,
185
+ params: {
186
+ 'v-length.range': {
187
+ min: 0,
188
+ max: 100,
189
+ int: true,
190
+ },
191
+ rules: [
192
+ {
193
+ required: true,
194
+ message: '请输入',
195
+ },
196
+ ],
197
+ },
198
+ },
199
+ {
200
+ value: ' ',
201
+ },
202
+ ],
203
+ ],
204
+ rows3: [
205
+ [
206
+ {
207
+ key: 'save_video',
208
+ label: '是否保存视频',
209
+ value: true,
210
+ component: ElRadioGroup,
211
+ params: {
212
+ rules: [
213
+ {
214
+ required: true,
215
+ message: '请选择',
216
+ trigger: 'change',
217
+ },
218
+ ],
219
+ options: [
220
+ {
221
+ value: true,
222
+ label: '是',
223
+ },
224
+ {
225
+ value: false,
226
+ label: '否',
227
+ },
228
+ ],
229
+ },
230
+ },
231
+ {
232
+ key: 'pre_buffer_second',
233
+ label: '帧前缓存(秒)',
234
+ value: '',
235
+ component: ElInput,
236
+ params: {
237
+ 'v-length.range': {
238
+ min: 0,
239
+ max: 1000,
240
+ int: true,
241
+ },
242
+ rules: [
243
+ {
244
+ required: true,
245
+ message: '请输入',
246
+ },
247
+ ],
248
+ },
249
+ },
250
+ ],
251
+ [
252
+ {
253
+ key: 'det_area_mode',
254
+ label: '检测区域工作模式',
255
+ value: 'normal',
256
+ component: ElRadioGroup,
257
+ events: {
258
+ change: detAreaModeChange,
259
+ },
260
+ params: {
261
+ rules: [
262
+ {
263
+ required: true,
264
+ message: '请选择',
265
+ trigger: 'change',
266
+ },
267
+ ],
268
+ options: [
269
+ {
270
+ value: 'normal',
271
+ label: '常规检测(normal)',
272
+ },
273
+ {
274
+ value: 'abnormal',
275
+ label: '非常规检测(abnormal)',
276
+ },
277
+ ],
278
+ },
279
+ },
280
+ ],
281
+ ],
282
+ rows4: [
283
+ [
284
+ {
285
+ key: 'region',
286
+ label: '地区选择',
287
+ value: ['beijing', 'chaoyang'],
288
+ component: ElCascader,
289
+ params: {
290
+ rules: [
291
+ {
292
+ required: true,
293
+ message: '请选择地区',
294
+ trigger: 'change',
295
+ },
296
+ ],
297
+ props: {
298
+ showPrefix: false,
299
+ checkStrictly: true,
300
+ checkOnClickNode: true,
301
+ },
302
+ options: [
303
+ {
304
+ value: 'beijing',
305
+ label: '北京市',
306
+ children: [
307
+ {
308
+ value: 'chaoyang',
309
+ label: '朝阳区',
310
+ children: [
311
+ {
312
+ value: 'chaoyangmen',
313
+ label: '朝阳门街道',
314
+ },
315
+ ],
316
+ },
317
+ {
318
+ value: 'haidian',
319
+ label: '海淀区',
320
+ },
321
+ ],
322
+ },
323
+ {
324
+ value: 'shanghai',
325
+ label: '上海市',
326
+ children: [
327
+ {
328
+ value: 'pudong',
329
+ label: '浦东新区',
330
+ },
331
+ ],
332
+ },
333
+ ],
334
+ },
335
+ },
336
+ {
337
+ key: 'department',
338
+ label: '部门选择',
339
+ value: 'tech',
340
+ component: ElCascader,
341
+ params: {
342
+ props: {
343
+ value: 'code',
344
+ label: 'name',
345
+ children: 'subDepartments',
346
+ },
347
+ options: [
348
+ {
349
+ code: 'company',
350
+ name: '公司总部',
351
+ subDepartments: [
352
+ {
353
+ code: 'tech',
354
+ name: '技术部',
355
+ subDepartments: [
356
+ {
357
+ code: 'frontend',
358
+ name: '前端组',
359
+ },
360
+ {
361
+ code: 'backend',
362
+ name: '后端组',
363
+ },
364
+ ],
365
+ },
366
+ {
367
+ code: 'sales',
368
+ name: '销售部',
369
+ },
370
+ ],
371
+ },
372
+ ],
373
+ },
374
+ },
375
+ ],
376
+ [
377
+ {
378
+ key: 'single_level_cascader',
379
+ label: '单层级联',
380
+ value: 'beijing',
381
+ component: ElCascader,
382
+ params: {
383
+ options: [
384
+ {
385
+ value: 'beijing',
386
+ label: '北京市',
387
+ },
388
+ {
389
+ value: 'shanghai',
390
+ label: '上海市',
391
+ },
392
+ {
393
+ value: 'guangzhou',
394
+ label: '广州市',
395
+ },
396
+ ],
397
+ },
398
+ },
399
+ {
400
+ value: ' ',
401
+ },
402
+ ],
403
+ ],
404
+ })
405
+
406
+ function detAreaModeChange(value: any) {
407
+ if (value === 'abnormal') {
408
+ if (state.rows3?.length && state.rows3[state.rows3.length - 1]?.[0]?.key === 'det_area_json') {
409
+ state.rows3.pop()
410
+ }
411
+ state.rows3.push([
412
+ {
413
+ key: 'det_area_json',
414
+ label: '感兴趣区域',
415
+ value: '',
416
+ readOnlyUseComponent: true,
417
+ component: CustomUIs,
418
+ span: 6,
419
+ events: {
420
+ change: (value) => getAreasHandler(value),
421
+ },
422
+ params: {
423
+ rules: [
424
+ {
425
+ required: true,
426
+ message: '请输入',
427
+ trigger: 'change',
428
+ },
429
+ ],
430
+ },
431
+ },
432
+ { value: ' ' },
433
+ ])
434
+ } else {
435
+ state.rows3.pop()
436
+ }
437
+ }
438
+
439
+ function CustomUIs() {
440
+ return h('div', {style:'color: red', class:"xx"}, 'xxx')
441
+ }
442
+
443
+ function getAreasHandler(value: any) {
444
+ state.rows3[state.rows3.length - 1][0].value = value
445
+ }
446
+
447
+ /**
448
+ * 保存
449
+ */
450
+ async function getFormData() {
451
+ try {
452
+ await formRef.value.validate()
453
+ } catch (error: any) {
454
+ console.log(error)
455
+ ElMessage.error('表单校验失败')
456
+ state.formData = {}
457
+ return false
458
+ }
459
+ const data1 = row1Ref.value?.getFormKvData?.()
460
+ const data2 = row2Ref.value?.getFormKvData?.()
461
+ const data3 = row3Ref.value?.getFormKvData?.()
462
+ const data4 = row4Ref.value?.getFormKvData?.()
463
+ const data = { ...data1, ...data2, ...data3, ...data4 }
464
+ state.formData = data
465
+ ElMessage.success('表单校验成功')
466
+ return data
467
+ }
468
+
469
+ /**
470
+ * 重置表单
471
+ */
472
+ async function resetFormData() {
473
+ // 使用组件内置的 resetForm 方法
474
+ row1Ref.value?.resetForm?.()
475
+ row2Ref.value?.resetForm?.()
476
+ row3Ref.value?.resetForm?.()
477
+ row4Ref.value?.resetForm?.()
478
+ setTimeout(()=>{
479
+ // 重置表单验证状态
480
+ formRef.value?.clearValidate?.()
481
+ // 清空结果显示
482
+ state.formData = {}
483
+ ElMessage.success('表单重置成功')
484
+ }, 0)
485
+ }
486
+
487
+ async function getDetail() {
488
+ // 模拟获取详情数据
489
+ setTimeout(()=>{
490
+ const res = {
491
+ "confidence": "aaa1",
492
+ "iou": "1",
493
+ "timeInterval": "2",
494
+ "stuck_threshold": "3",
495
+ "max_retries": "4",
496
+ "save_video": true,
497
+ "pre_buffer_second": "5",
498
+ "det_area_mode": "abnormal",
499
+ "det_area_json": "6",
500
+ "region": ["beijing", "haidian"],
501
+ "department": "tech",
502
+ "single_level_cascader": "shanghai"
503
+ }
504
+ for (const [k, v] of Object.entries(res)) {
505
+ let rows1 = getAllFormNodeByKey(state.rows,k);
506
+ if(rows1) {
507
+ rows1.value = v;
508
+ }
509
+ let rows2 = getAllFormNodeByKey(state.rows2,k);
510
+ if(rows2) {
511
+ rows2.value = v;
512
+ }
513
+ let rows3 = getAllFormNodeByKey(state.rows3,k);
514
+ if(rows3) {
515
+ rows3.value = v;
516
+ if(k === 'det_area_mode'){
517
+ detAreaModeChange(v)
518
+ }
519
+ }
520
+ let rows4 = getAllFormNodeByKey(state.rows4,k);
521
+ if(rows4) {
522
+ rows4.value = v;
523
+ }
524
+ }
525
+ }, 2000)
526
+ }
527
+
528
+ onMounted(() => {
529
+ getDetail()
530
+ })
531
+
532
+ </script>
533
+
534
+ <style lang="scss" scoped>
535
+ .demo-container {
536
+ padding: 20px;
537
+ max-width: 1400px;
538
+ margin: 0 auto;
539
+ }
540
+
541
+ .control-panel {
542
+ background: #f5f5f5;
543
+ padding: 20px;
544
+ border-radius: 8px;
545
+ margin-bottom: 20px;
546
+
547
+ h3 {
548
+ margin: 0 0 20px 0;
549
+ color: #333;
550
+ }
551
+
552
+ h4 {
553
+ margin: 15px 0 10px 0;
554
+ color: #666;
555
+ font-size: 14px;
556
+ }
557
+ }
558
+
559
+ .config-section,
560
+ .upload-section,
561
+ .action-section {
562
+ margin-bottom: 20px;
563
+ padding: 15px;
564
+ background: white;
565
+ border-radius: 6px;
566
+ border: 1px solid #e0e0e0;
567
+
568
+ .config-select {
569
+ width: 300px;
570
+ margin-right: 10px;
571
+ }
572
+
573
+ input[type='file'] {
574
+ margin-right: 10px;
575
+ }
576
+
577
+ .el-button {
578
+ margin-right: 10px;
579
+ margin-bottom: 5px;
580
+ }
581
+ }
582
+
583
+ .form-container {
584
+ background: white;
585
+ padding: 20px;
586
+ border-radius: 8px;
587
+ border: 1px solid #e0e0e0;
588
+ margin-bottom: 20px;
589
+ }
590
+
591
+ .empty-state {
592
+ text-align: center;
593
+ padding: 60px 20px;
594
+ background: white;
595
+ border-radius: 8px;
596
+ border: 1px solid #e0e0e0;
597
+ }
598
+
599
+ .data-card {
600
+ margin-top: 20px;
601
+
602
+ .card-header {
603
+ display: flex;
604
+ justify-content: space-between;
605
+ align-items: center;
606
+ }
607
+
608
+ .form-data-display {
609
+ background-color: #f5f7fa;
610
+ padding: 15px;
611
+ border-radius: 4px;
612
+ font-size: 12px;
613
+ line-height: 1.5;
614
+ max-height: 400px;
615
+ overflow-y: auto;
616
+ }
617
+ }
618
+
619
+ @media (max-width: 768px) {
620
+ .config-select {
621
+ width: 100% !important;
622
+ margin-bottom: 10px;
623
+ }
624
+
625
+ .el-button {
626
+ width: 100%;
627
+ margin-bottom: 10px;
628
+ }
629
+ }
630
+ </style>
631
+