matrix_components 2.0.366 → 2.0.367

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,454 @@
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
+ </el-form>
56
+ </div>
57
+ </div>
58
+ </template>
59
+
60
+ <script setup lang="ts">
61
+ import { ElInput, ElMessage, ElRadioGroup } from 'element-plus'
62
+ import { reactive, ref } from 'vue'
63
+ import { cloneDeep } from 'lodash-es'
64
+
65
+ const props = defineProps({
66
+ readOnly: {
67
+ type: Boolean,
68
+ default: false,
69
+ },
70
+ row: {
71
+ type: Object,
72
+ default: () => ({}),
73
+ },
74
+ })
75
+
76
+ const formRef = ref()
77
+ const row1Ref = ref()
78
+ const row2Ref = ref()
79
+ const row3Ref = ref()
80
+
81
+ // 保存初始数据
82
+ const initialRows = [
83
+ [
84
+ {
85
+ key: 'confidence',
86
+ label: '置信度',
87
+ value: '',
88
+ component: ElInput,
89
+ params: {
90
+ 'v-length.range': {
91
+ min: 0,
92
+ max: 1,
93
+ maxLength: 3,
94
+ },
95
+ rules: [
96
+ {
97
+ required: true,
98
+ message: '请输入',
99
+ },
100
+ ],
101
+ },
102
+ },
103
+ {
104
+ key: 'iou',
105
+ label: '交并比',
106
+ value: '',
107
+ component: ElInput,
108
+ params: {
109
+ 'v-length.range': {
110
+ min: 0,
111
+ max: 1,
112
+ maxLength: 3,
113
+ },
114
+ rules: [
115
+ {
116
+ required: true,
117
+ message: '请输入',
118
+ },
119
+ ],
120
+ },
121
+ },
122
+ ],
123
+ ]
124
+
125
+ const initialRows2 = [
126
+ [
127
+ {
128
+ key: 'timeInterval',
129
+ label: '时间间隔(秒)',
130
+ value: '',
131
+ component: ElInput,
132
+ params: {
133
+ 'v-length.range': {
134
+ min: 0,
135
+ max: 6000,
136
+ int: true,
137
+ },
138
+ rules: [
139
+ {
140
+ required: true,
141
+ message: '请输入',
142
+ },
143
+ ],
144
+ },
145
+ },
146
+ {
147
+ key: 'stuck_threshold',
148
+ label: '视频帧卡顿(秒)',
149
+ value: '',
150
+ component: ElInput,
151
+ params: {
152
+ 'v-length.range': {
153
+ min: 0,
154
+ max: 1000,
155
+ int: true,
156
+ },
157
+ rules: [
158
+ {
159
+ required: true,
160
+ message: '请输入',
161
+ },
162
+ ],
163
+ },
164
+ },
165
+ ],
166
+ [
167
+ {
168
+ key: 'max_retries',
169
+ label: '最大重连次数',
170
+ value: '',
171
+ component: ElInput,
172
+ params: {
173
+ 'v-length.range': {
174
+ min: 0,
175
+ max: 100,
176
+ int: true,
177
+ },
178
+ rules: [
179
+ {
180
+ required: true,
181
+ message: '请输入',
182
+ },
183
+ ],
184
+ },
185
+ },
186
+ {
187
+ value: ' ',
188
+ },
189
+ ],
190
+ ]
191
+
192
+ const initialRows3 = [
193
+ [
194
+ {
195
+ key: 'save_video',
196
+ label: '是否保存视频',
197
+ value: '1',
198
+ component: ElRadioGroup,
199
+ params: {
200
+ rules: [
201
+ {
202
+ required: true,
203
+ message: '请选择',
204
+ trigger: 'change',
205
+ },
206
+ ],
207
+ options: [
208
+ {
209
+ value: '1',
210
+ label: '是',
211
+ },
212
+ {
213
+ value: '0',
214
+ label: '否',
215
+ },
216
+ ],
217
+ },
218
+ },
219
+ {
220
+ key: 'pre_buffer_second',
221
+ label: '帧前缓存(秒)',
222
+ value: '',
223
+ component: ElInput,
224
+ params: {
225
+ 'v-length.range': {
226
+ min: 0,
227
+ max: 1000,
228
+ int: true,
229
+ },
230
+ rules: [
231
+ {
232
+ required: true,
233
+ message: '请输入',
234
+ },
235
+ ],
236
+ },
237
+ },
238
+ ],
239
+ [
240
+ {
241
+ key: 'det_area_mode',
242
+ label: '检测区域工作模式',
243
+ value: 'normal',
244
+ component: ElRadioGroup,
245
+ events: {
246
+ change: detAreaModeChange,
247
+ },
248
+ params: {
249
+ rules: [
250
+ {
251
+ required: true,
252
+ message: '请选择',
253
+ trigger: 'change',
254
+ },
255
+ ],
256
+ options: [
257
+ {
258
+ value: 'normal',
259
+ label: '常规检测(normal)',
260
+ },
261
+ {
262
+ value: 'abnormal',
263
+ label: '非常规检测(abnormal)',
264
+ },
265
+ ],
266
+ },
267
+ },
268
+ ],
269
+ ]
270
+ debugger
271
+ const state = reactive({
272
+ formData: {},
273
+ readOnly: props.readOnly,
274
+ model: props.readOnly ? '' : 'vertical',
275
+ // 使用 cloneDeep 进行深拷贝,保留函数
276
+ rows: cloneDeep(initialRows),
277
+ rows2: cloneDeep(initialRows2),
278
+ rows3: cloneDeep(initialRows3),
279
+ })
280
+
281
+ function detAreaModeChange(value: any) {
282
+ if (value === 'abnormal') {
283
+ if (state.rows3?.length && state.rows3[state.rows3.length - 1]?.[0]?.key === 'det_area_json') {
284
+ state.rows3.pop()
285
+ }
286
+ state.rows3.push([
287
+ {
288
+ key: 'det_area_json',
289
+ label: '感兴趣区域',
290
+ value: '',
291
+ component: ElInput,
292
+ span: 6,
293
+ events: {
294
+ change: (value) => getAreasHandler(value),
295
+ },
296
+ params: {
297
+ rules: [
298
+ {
299
+ required: true,
300
+ message: '请输入',
301
+ trigger: 'change',
302
+ },
303
+ ],
304
+ },
305
+ },
306
+ { value: ' ' },
307
+ ])
308
+ } else {
309
+ state.rows3.pop()
310
+ }
311
+ }
312
+
313
+ function getAreasHandler(value: any) {
314
+ state.rows3[state.rows3.length - 1][0].value = value
315
+ }
316
+
317
+ /**
318
+ * 保存
319
+ */
320
+ async function getFormData() {
321
+ try {
322
+ await formRef.value.validate()
323
+ } catch (error: any) {
324
+ console.log(error)
325
+ ElMessage.error('表单校验失败')
326
+ state.formData = {}
327
+ return false
328
+ }
329
+ const data1 = row1Ref.value?.getKeyValuePairs?.(state.rows)
330
+ const data2 = row2Ref.value?.getKeyValuePairs?.(state.rows2)
331
+ const data3 = row3Ref.value?.getKeyValuePairs?.(state.rows3)
332
+ const data = { ...data1, ...data2, ...data3 }
333
+ state.formData = data
334
+ ElMessage.success('表单校验成功')
335
+ return data
336
+ }
337
+
338
+ /**
339
+ * 重置表单
340
+ */
341
+ function resetFormData() {
342
+ // 直接重新赋值整个数据结构,使用 cloneDeep 保留函数
343
+ state.rows = cloneDeep(initialRows)
344
+ state.rows2 = cloneDeep(initialRows2)
345
+ state.rows3 = cloneDeep(initialRows3)
346
+
347
+ // 重置表单验证状态
348
+ formRef.value?.clearValidate?.()
349
+
350
+ // 清空结果显示
351
+ state.formData = {}
352
+
353
+ ElMessage.success('表单重置成功')
354
+ }
355
+ </script>
356
+
357
+ <style lang="scss" scoped>
358
+ .demo-container {
359
+ padding: 20px;
360
+ max-width: 1400px;
361
+ margin: 0 auto;
362
+ }
363
+
364
+ .control-panel {
365
+ background: #f5f5f5;
366
+ padding: 20px;
367
+ border-radius: 8px;
368
+ margin-bottom: 20px;
369
+
370
+ h3 {
371
+ margin: 0 0 20px 0;
372
+ color: #333;
373
+ }
374
+
375
+ h4 {
376
+ margin: 15px 0 10px 0;
377
+ color: #666;
378
+ font-size: 14px;
379
+ }
380
+ }
381
+
382
+ .config-section,
383
+ .upload-section,
384
+ .action-section {
385
+ margin-bottom: 20px;
386
+ padding: 15px;
387
+ background: white;
388
+ border-radius: 6px;
389
+ border: 1px solid #e0e0e0;
390
+
391
+ .config-select {
392
+ width: 300px;
393
+ margin-right: 10px;
394
+ }
395
+
396
+ input[type='file'] {
397
+ margin-right: 10px;
398
+ }
399
+
400
+ .el-button {
401
+ margin-right: 10px;
402
+ margin-bottom: 5px;
403
+ }
404
+ }
405
+
406
+ .form-container {
407
+ background: white;
408
+ padding: 20px;
409
+ border-radius: 8px;
410
+ border: 1px solid #e0e0e0;
411
+ margin-bottom: 20px;
412
+ }
413
+
414
+ .empty-state {
415
+ text-align: center;
416
+ padding: 60px 20px;
417
+ background: white;
418
+ border-radius: 8px;
419
+ border: 1px solid #e0e0e0;
420
+ }
421
+
422
+ .data-card {
423
+ margin-top: 20px;
424
+
425
+ .card-header {
426
+ display: flex;
427
+ justify-content: space-between;
428
+ align-items: center;
429
+ }
430
+
431
+ .form-data-display {
432
+ background-color: #f5f7fa;
433
+ padding: 15px;
434
+ border-radius: 4px;
435
+ font-size: 12px;
436
+ line-height: 1.5;
437
+ max-height: 400px;
438
+ overflow-y: auto;
439
+ }
440
+ }
441
+
442
+ @media (max-width: 768px) {
443
+ .config-select {
444
+ width: 100% !important;
445
+ margin-bottom: 10px;
446
+ }
447
+
448
+ .el-button {
449
+ width: 100%;
450
+ margin-bottom: 10px;
451
+ }
452
+ }
453
+ </style>
454
+