vue2-client 1.16.97 → 1.16.99

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.
@@ -1,1530 +1,1530 @@
1
- <template>
2
- <!-- 输入框 -->
3
- <x-form-col
4
- v-if="attr.type === 'input' && show"
5
- :occupyCol="attr.occupyCol"
6
- :labelCol="labelCol"
7
- :flex="attr.flex">
8
- <a-form-model-item
9
- v-bind="bindOther"
10
- :rules="rules"
11
- :ref="attr.model"
12
- :label="showLabel?attr.name:undefined"
13
- :prop="attr.prop ? attr.prop : attr.model">
14
- <!-- 如果配置了后置按钮插槽 -->
15
- <a-input-group
16
- v-if="((attr.inputOnAfterName && attr.inputOnAfterFunc) || (attr.inputOnAfterIcon && attr.inputOnAfterIconFunc)) && mode !== '查询'"
17
- style="display: flex; width: 100%; padding: 4px 0"
18
- compact>
19
- <a-input
20
- v-model="form[attr.model]"
21
- :read-only="readOnly"
22
- :disabled="disabled && !readOnly"
23
- :whitespace="true"
24
- @input="attr.dataChangeFunc && debouncedDataChangeFunc()"
25
- :suffix="attr.inputSuffix && mode !== '新增' ? attr.inputSuffix : ''"
26
- @blur="mode !== '查询' && attr.inputOnBlurFunc && emitFunc(attr.inputOnBlurFunc,attr)"
27
- @keyup.enter="mode !== '查询' && attr.inputOnEnterFunc && emitFunc(attr.inputOnEnterFunc, attr)"
28
- :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
29
- :ref="`${attr.model}input`"/>
30
- <a-button
31
- v-if="attr.inputOnAfterName && attr.inputOnAfterFunc && !attr.inputOnAfterName.includes('|')"
32
- style="width: auto; min-width: 4rem;max-width: 6rem"
33
- type="primary"
34
- @click="emitFunc(attr.inputOnAfterFunc,attr)">
35
- {{ attr.inputOnAfterName }}
36
- </a-button>
37
- <!-- 仅可以配置 一个按钮 以及 一个图标插槽 -->
38
- <a-button
39
- style="width: 2rem; flex-shrink: 0;"
40
- v-else-if="attr.inputOnAfterIcon"
41
- :type="attr.inputOnAfterIcon && attr.inputOnAfterName ? 'primary' :''"
42
- :icon="attr.inputOnAfterIcon || 'question'"
43
- @click="emitFunc(attr.inputOnAfterIconFunc,attr)">
44
- </a-button>
45
- <!-- 状态按钮 -->
46
- <x-status-button
47
- v-else
48
- :states="parseStates(attr.inputOnAfterName, attr.inputOnAfterFunc)"
49
- v-on="generateDynamicEvents(attr.inputOnAfterFunc, attr)"
50
- style="width: auto; min-width: 4rem; max-width: 6rem"
51
- />
52
- </a-input-group>
53
- <a-input-number
54
- v-else-if="attr.numberInput && !readOnly"
55
- v-model="form[attr.model]"
56
- :whitespace="true"
57
- @change="attr.dataChangeFunc && debouncedDataChangeFunc()"
58
- :disabled="disabled && !readOnly"
59
- style="width:100%"
60
- @blur="mode !== '查询' && attr.inputOnBlurFunc && emitFunc(attr.inputOnBlurFunc,attr)"
61
- @keyup.enter="mode !== '查询' && attr.inputOnEnterFunc && emitFunc(attr.inputOnEnterFunc, attr)"
62
- :suffix="attr.inputSuffix && mode !== '新增' ? attr.inputSuffix : ''"
63
- :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
64
- :ref="`${attr.model}input`"/>
65
- <a-input
66
- v-else
67
- v-model="form[attr.model]"
68
- :whitespace="true"
69
- :read-only="readOnly"
70
- :disabled="disabled && !readOnly"
71
- @input="attr.dataChangeFunc && debouncedDataChangeFunc()"
72
- :suffix="attr.inputSuffix && mode !== '新增' ? attr.inputSuffix : ''"
73
- style="width:100%"
74
- @blur="mode !== '查询' && attr.inputOnBlurFunc && emitFunc(attr.inputOnBlurFunc,attr)"
75
- @keyup.enter="mode !== '查询' && attr.inputOnEnterFunc && emitFunc(attr.inputOnEnterFunc, attr)"
76
- :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
77
- :ref="`${attr.model}input`"/>
78
- </a-form-model-item>
79
- </x-form-col>
80
- <!-- 下拉框 -->
81
- <x-form-col
82
- v-else-if="attr.type === 'select' && show"
83
- :labelCol="labelCol"
84
- :flex="attr.flex">
85
- <a-form-model-item
86
- v-bind="bindOther"
87
- :rules="rules"
88
- v-if="!attr.showMode || mode === '查询' || attr.showMode === 'select' "
89
- :ref="attr.model"
90
- :label="showLabel?attr.name:undefined"
91
- :prop="attr.prop ? attr.prop : attr.model">
92
- <!-- <span slot="label" class="label-box">{{ showLabel?attr.name:undefined }}</span>-->
93
- <a-select
94
- v-if="!attr.lazyLoad || attr.lazyLoad === 'false'"
95
- v-model="form[attr.model]"
96
- :disabled="disabled || readOnly"
97
- @change="handleSelectChange"
98
- :filter-option="filterOption"
99
- :getPopupContainer="getPopupContainer"
100
- dropdownClassName="custom-dropdown"
101
- :dropdownMatchSelectWidth="false"
102
- :dropdownStyle="{ position: 'absolute'}"
103
- :placeholder="attr.placeholder ? attr.placeholder : '请选择'"
104
- show-search
105
- :allowClear="true"
106
- :getCalendarContainer="(triggerNode) => triggerNode.parentNode"
107
- >
108
- <a-select-option
109
- v-if="mode === '查询'"
110
- key="999999"
111
- value="">全部
112
- </a-select-option>
113
- <template v-if="attr.keys">
114
- <a-select-option
115
- v-for="(item,index) in attr.keys"
116
- :key="index.value"
117
- :value="item.value + ''">
118
- {{ item.label }}
119
- </a-select-option>
120
- </template>
121
- <template v-else>
122
- <template
123
- v-if="attr.keyName.indexOf('logic@') !== -1 || attr.keyName.indexOf('config@') !== -1
124
- ||attr.keyName.indexOf('search@') !== -1 || attr.keyName.indexOf('search@') !== -1">
125
- <a-select-option
126
- v-for="(item,index) in option"
127
- :key="index.value"
128
- :value="item.value + ''">
129
- <template v-if="attr.keyName.indexOf('config@') !== -1 && item.status">
130
- <!-- 徽标(badge) -->
131
- <a-badge v-if="item.status !== 'gary'" :color="item.status" :text="item.label"/>
132
- <a-badge v-else color="#D9D9D9" :text="item.label"/>
133
- </template>
134
- <template v-else>
135
- {{ item.label }}
136
- </template>
137
- </a-select-option>
138
- </template>
139
- <template
140
- v-else-if="attr.keyName.indexOf('async ') !== -1 || attr.keyName.indexOf('function ') !== -1">
141
- <a-select-option
142
- v-for="(item,index) in optionForFunc"
143
- :key="index.value"
144
- :value="item.value + ''">
145
- <template>
146
- {{ item.label }}
147
- </template>
148
- </a-select-option>
149
- </template>
150
- <template v-else>
151
- <a-select-option
152
- v-for="item in $appdata.getDictionaryList(attr.keyName)"
153
- :key="item.value"
154
- :value="item.value + ''">
155
- <!-- 徽标(badge) -->
156
- <x-badge
157
- :badge-key="attr.keyName"
158
- :replaceText="item.text"
159
- :value="item.value"
160
- :service-name="serviceName"
161
- :env="env"/>
162
- </a-select-option>
163
- </template>
164
- </template>
165
- </a-select>
166
- <a-select
167
- v-else
168
- v-model="form[attr.model]"
169
- :disabled="disabled || readOnly"
170
- @change="handleSelectChange"
171
- :filter-option="filterOption"
172
- :getPopupContainer="getPopupContainer"
173
- dropdownClassName="custom-dropdown"
174
- :dropdownMatchSelectWidth="false"
175
- :dropdownStyle="{ position: 'absolute'}"
176
- :placeholder="attr.placeholder ? attr.placeholder : '搜索' + attr.name"
177
- show-search
178
- @search="fetchFunction"
179
- >
180
- <template #notFoundContent>
181
- <a-spin v-if="searching" size="small"/>
182
- </template>
183
- <a-select-option
184
- v-if="mode === '查询'"
185
- key="999999"
186
- value="">全部
187
- </a-select-option>
188
- <a-select-option
189
- v-for="(item,index) in option"
190
- :key="index"
191
- :value="item.value + ''">{{ item.label }}
192
- </a-select-option>
193
- </a-select>
194
- </a-form-model-item>
195
- <a-form-model-item
196
- :disabled="disabled || readOnly"
197
- v-bind="bindOther"
198
- :rules="rules"
199
- v-else-if="attr.showMode === 'radioGroup'"
200
- :ref="attr.model"
201
- :label="showLabel?attr.name:undefined"
202
- :prop="attr.prop ? attr.prop : attr.model">
203
- <a-radio-group v-model="form[attr.model]">
204
- <a-radio-button v-for="modeItem in option" :key="modeItem.value" :value="modeItem.value">
205
- {{ modeItem.label }}
206
- </a-radio-button>
207
- </a-radio-group>
208
- </a-form-model-item>
209
- <a-form-model-item
210
- v-bind="bindOther"
211
- v-else-if="attr.showMode === 'clickChange' && option.length > 0"
212
- :ref="attr.model"
213
- :label="showLabel?attr.name:undefined"
214
- :prop="attr.prop ? attr.prop : attr.model">
215
- <XClickChangeBtn></XClickChangeBtn>
216
- </a-form-model-item>
217
- </x-form-col>
218
- <!-- 多选框 -->
219
- <x-form-col
220
- v-else-if="attr.type === 'checkbox' && show"
221
- :labelCol="labelCol"
222
- :flex="attr.flex">
223
- <a-form-model-item
224
- v-bind="bindOther"
225
- :rules="rules"
226
- v-if="!attr.showMode || mode === '查询' || attr.showMode === 'select' "
227
- :ref="attr.model"
228
- :label="showLabel?attr.name:undefined"
229
- :prop="attr.prop ? attr.prop : attr.model">
230
- <a-select
231
- class="multiple_select"
232
- style="width:100%"
233
- v-if="!attr.lazyLoad || attr.lazyLoad === 'false'"
234
- v-model="form[attr.model]"
235
- :disabled="disabled"
236
- :filter-option="filterOption"
237
- :getPopupContainer="getPopupContainer"
238
- :placeholder="attr.placeholder ? attr.placeholder : '请选择'"
239
- @change="handleCheckboxChange"
240
- mode="multiple"
241
- show-search
242
- allowClear
243
- >
244
- <template v-if="attr.keys">
245
- <a-select-option
246
- v-for="(item,index) in attr.keys"
247
- :key="index"
248
- :value="item.value + ''">
249
- {{ item.label }}
250
- </a-select-option>
251
- </template>
252
- <template v-else>
253
- <template
254
- v-if="attr.keyName.indexOf('logic@') !== -1 || attr.keyName.indexOf('config@') !== -1
255
- ||attr.keyName.indexOf('search@') !== -1 || attr.keyName.indexOf('search@') !== -1">
256
- <a-select-option
257
- v-for="(item,index) in option"
258
- :key="index"
259
- :value="item.value">{{ item.label }}
260
- </a-select-option>
261
- </template>
262
- <template v-else>
263
- <a-select-option
264
- v-for="item in $appdata.getDictionaryList(attr.keyName)"
265
- :key="item.value"
266
- :value="item.value + ''">{{ item.text }}
267
- </a-select-option>
268
- </template>
269
- </template>
270
- </a-select>
271
- <a-select
272
- v-else
273
- class="multiple_select"
274
- v-model="form[attr.model]"
275
- :disabled="disabled"
276
- :filter-option="filterOption"
277
- :getPopupContainer="getPopupContainer"
278
- :placeholder="attr.placeholder ? attr.placeholder : '搜索' + attr.name"
279
- mode="multiple"
280
- style="width:100%"
281
- @change="handleCheckboxChange"
282
- show-search
283
- allowClear
284
- @search="fetchFunction"
285
- >
286
- <template #notFoundContent>
287
- <a-spin v-if="searching" size="small"/>
288
- </template>
289
- <a-select-option
290
- v-for="(item,index) in option"
291
- :key="index"
292
- :value="item.value + ''">{{ item.label }}
293
- </a-select-option>
294
- </a-select>
295
- </a-form-model-item>
296
- <a-form-model-item
297
- v-bind="bindOther"
298
- :rules="rules"
299
- v-else
300
- :ref="attr.model"
301
- :label="showLabel?attr.name:undefined"
302
- :prop="attr.prop ? attr.prop : attr.model">
303
- <a-checkbox-group
304
- v-model="form[attr.model]"
305
- :options="option"
306
- @change="handleCheckboxChange"
307
- />
308
- </a-form-model-item>
309
- </x-form-col>
310
- <!-- 单选框 -->
311
- <x-form-col
312
- v-else-if="attr.type === 'radio' && show"
313
- :labelCol="labelCol"
314
- :flex="attr.flex">
315
- <a-form-model-item
316
- v-bind="bindOther"
317
- :rules="rules"
318
- v-if="!attr.showMode || attr.type === 'radio' "
319
- :ref="attr.model"
320
- :label="showLabel?attr.name:undefined"
321
- :prop="attr.prop ? attr.prop : attr.model">
322
- <a-radio-group
323
- v-model="form[attr.model]"
324
- @change="handleRadioChange"
325
- >
326
- <template v-if="attr.keys">
327
- <a-radio v-for="(item,index) in attr.keys" :key="index" :value="item.value">
328
- {{ item.label }}
329
- </a-radio>
330
- </template>
331
- <template v-else>
332
- <template
333
- v-if="attr.keyName.indexOf('logic@') !== -1 || attr.keyName.indexOf('config@') !== -1
334
- ||attr.keyName.indexOf('search@') !== -1 || attr.keyName.indexOf('search@') !== -1">
335
- <a-radio v-for="(item,index) in option" :key="index" :value="item.value">
336
- {{ item.label }}
337
- </a-radio>
338
- </template>
339
- <template v-else>
340
- <a-radio v-for="(item,index) in $appdata.getDictionaryList(attr.keyName)" :key="index" :value="item.value">
341
- {{ item.text }}
342
- </a-radio>
343
- </template>
344
- </template>
345
- </a-radio-group>
346
- </a-form-model-item>
347
- <a-form-model-item
348
- v-bind="bindOther"
349
- :rules="rules"
350
- v-else-if="attr.showMode === 'radioGroup'"
351
- :ref="attr.model"
352
- :label="showLabel?attr.name:undefined"
353
- :prop="attr.prop ? attr.prop : attr.model">
354
- <a-radio-group v-model="form[attr.model]">
355
- <a-radio-button v-for="modeItem in option" :key="modeItem.value" :value="modeItem.value">
356
- {{ modeItem.label }}
357
- </a-radio-button>
358
- </a-radio-group>
359
- </a-form-model-item>
360
- <a-form-model-item
361
- v-bind="bindOther"
362
- :rules="rules"
363
- v-else-if="attr.showMode === 'clickChange' && option.length > 0"
364
- :ref="attr.model"
365
- :label="showLabel?attr.name:undefined"
366
- :prop="attr.prop ? attr.prop : attr.model">
367
- <XClickChangeBtn></XClickChangeBtn>
368
- </a-form-model-item>
369
- </x-form-col>
370
- <!-- 时间 日期 框整合 -->
371
- <x-form-col
372
- v-else-if="['datePicker', 'rangePicker', 'yearPicker', 'monthPicker', 'yearRangePicker', 'monthRangePicker'].includes(attr.type) && show"
373
- :labelCol="labelCol"
374
- :flex="attr.flex">
375
- <a-form-model-item
376
- v-bind="bindOther"
377
- :rules="rules"
378
- :ref="attr.model"
379
- :label="showLabel?attr.name:undefined"
380
- :prop="attr.prop ? attr.prop : attr.model">
381
- <XFormDatePicker
382
- :attr="attr"
383
- :mode="mode"
384
- :enablePopupToBody="enablePopupToBody"
385
- :getCalendarContainer="getPopupContainer"
386
- :disabled="disabled"
387
- :readOnly="readOnly"
388
- :showLabel="showLabel"
389
- @change="attr.dataChangeFunc && debouncedDataChangeFunc()"
390
- v-model="form[attr.model]"/>
391
- </a-form-model-item>
392
- </x-form-col>
393
- <!-- 文本域 -->
394
- <x-form-col
395
- v-else-if="attr.type === 'textarea' && show"
396
- :labelCol="labelCol"
397
- :flex="attr.flex">
398
- <!-- :style="layout === 'inline'?{width:'calc(100% - 60px)'}:{}"-->
399
- <a-form-model-item
400
- v-bind="bindOther"
401
- :rules="rules"
402
- :ref="attr.model"
403
- :label="showLabel?attr.name:undefined"
404
- :prop="attr.prop ? attr.prop : attr.model">
405
- <a-textarea
406
- v-model="form[attr.model]"
407
- style="width: 100%;"
408
- :disabled="disabled"
409
- :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
410
- :rows="4"/>
411
- </a-form-model-item>
412
- </x-form-col>
413
- <!-- 文件上传 -->
414
- <x-form-col
415
- v-else-if="(attr.type === 'file' || attr.type === 'image') && show"
416
- :labelCol="labelCol"
417
- :flex="attr.flex">
418
- <a-form-model-item
419
- v-bind="bindOther"
420
- :rules="rules"
421
- :ref="attr.model"
422
- :label="showLabel?attr.name:undefined"
423
- :prop="attr.prop ? attr.prop : attr.model">
424
- <upload
425
- :files="files"
426
- :read-only="readOnly"
427
- :images="images"
428
- :model="attr"
429
- v-bind="attr"
430
- :service-name="serviceName"
431
- @setFiles="setFiles"></upload>
432
- </a-form-model-item>
433
- </x-form-col>
434
- <!-- 省市区选择框 -->
435
- <x-form-col
436
- v-else-if="attr.type === 'citySelect' && show"
437
- :labelCol="labelCol"
438
- :flex="attr.flex">
439
- <a-form-model-item
440
- v-bind="bindOther"
441
- :rules="rules"
442
- :ref="attr.model"
443
- :label="showLabel?attr.name:undefined"
444
- :prop="attr.prop ? attr.prop : attr.model">
445
- <citySelect
446
- @change="attr.dataChangeFunc && debouncedDataChangeFunc()"
447
- ref="citySelect"
448
- v-model="form[attr.model]"
449
- :contexts="attr.contexts"
450
- :value-type="attr.valueType"
451
- :default-value="form[attr.model]"></citySelect>
452
- </a-form-model-item>
453
- </x-form-col>
454
- <!-- 地点搜索框 -->
455
- <x-form-col
456
- v-else-if="(attr.type === 'addressSearch' || attr.type === 'coordinateSearch') && show"
457
- :labelCol="labelCol"
458
- :occupyCol="attr.occupyCol"
459
- :flex="attr.flex">
460
- <a-form-model-item
461
- v-bind="bindOther"
462
- :rules="rules"
463
- :ref="attr.model"
464
- :label="showLabel?attr.name:undefined"
465
- :prop="attr.prop ? attr.prop : attr.model">
466
- <address-search-combobox
467
- :emitFunc="emitFunc"
468
- :attr="attr"
469
- :read-only="readOnly"
470
- :searchResult="form[attr.model]"
471
- :address="{ address: form[attr.model], coords: form[`${attr.model}_lng_lat`] }"
472
- :resultKeys="{ address: attr.model, coords: `${attr.model}_lng_lat` }"
473
- ref="addressSearchCombobox"
474
- searchResultType="Object"
475
- @onSelect="addressSearchComboboxSelect"
476
- @onDivisionsChange="onDivisionsChange"
477
- ></address-search-combobox>
478
- </a-form-model-item>
479
- </x-form-col>
480
- <!-- 颜色选择器 -->
481
- <x-form-col
482
- v-else-if="attr.type === 'colorPicker' && show"
483
- :labelCol="labelCol"
484
- :flex="attr.flex">
485
- <a-form-model-item
486
- v-bind="bindOther"
487
- :rules="rules"
488
- :ref="attr.model"
489
- :label="showLabel?attr.name:undefined"
490
- :prop="attr.prop ? attr.prop : attr.model">
491
- <color-picker-combobox
492
- :value="form[attr.model]"
493
- :read-only="readOnly"
494
- @onSelect="colorPickerComboboxSelect"
495
- />
496
- </a-form-model-item>
497
- </x-form-col>
498
- <!-- 人员选择框 -->
499
- <x-form-col
500
- v-else-if="attr.type === 'personSetting' && show"
501
- :labelCol="labelCol"
502
- :flex="attr.flex">
503
- <a-form-model-item
504
- v-bind="bindOther"
505
- :rules="rules"
506
- :ref="attr.model"
507
- :label="showLabel?attr.name:undefined"
508
- :prop="attr.prop ? attr.prop : attr.model">
509
- <PersonSetting v-model="form[attr.model]"></PersonSetting>
510
- </a-form-model-item>
511
- </x-form-col>
512
- <!-- 树形选择框 -->
513
- <x-form-col
514
- v-else-if="attr.type === 'treeSelect' && show"
515
- :labelCol="labelCol"
516
- :flex="attr.flex">
517
- <x-tree-select
518
- :rules="rules"
519
- @onChange="handleTreeSelectChange"
520
- v-model="form[attr.model]"
521
- :attr="attr"
522
- @mounted="itemMounted"
523
- ref="xTreeSelect">
524
- </x-tree-select>
525
- </x-form-col>
526
- <!-- 列表选择框 -->
527
- <x-form-col
528
- v-else-if="attr.type === 'listSelect' && show"
529
- :labelCol="labelCol"
530
- :flex="attr.flex">
531
- <a-form-model-item
532
- v-bind="bindOther"
533
- :rules="rules"
534
- :ref="attr.model"
535
- :label="showLabel?attr.name:undefined"
536
- :style="layout === 'inline'&& attr.occupyCol && attr.occupyCol > 1? {width:`calc(100% - ${attr.occupyCol * 1.533}rem)`}:{}"
537
- :prop="attr.prop ? attr.prop : attr.model">
538
- <a-popover
539
- ref="rowChoosePopover"
540
- :visible="rowChoosePopoverVisible"
541
- title="选择数据"
542
- placement="bottom"
543
- trigger="focus"
544
- :arrowPointAtCenter="true"
545
- :overlayStyle="{ width: '1000px', height: '30vh' }">
546
- <template #content>
547
- <x-report
548
- v-if="isCover"
549
- :use-oss-for-img="false"
550
- :config-name="queryParamsName"
551
- :service-name="serviceName"
552
- :show-img-in-cell="true"
553
- :display-only="true"
554
- :edit-mode="false"
555
- :show-save-button="true"
556
- :no-padding="true"
557
- :dont-format="true"
558
- @rowChoose="rowChoose"
559
- @cancel="closeRowChooseInput"
560
- >
561
- </x-report>
562
- <x-form-table
563
- v-else
564
- title="请选择数据"
565
- :queryParamsName="queryParamsName"
566
- :rowSelectMode="true"
567
- :allowSelectRowNum="1"
568
- :service-name="serviceName"
569
- :fixed-query-form="rowChooseFixedQueryValue"
570
- @rowChoose="rowChoose"
571
- @afterQuery="rowChooseSearchAfterQuery"
572
- ref="rowChooseTable">
573
- <template #button>
574
- <a-button @click="closeRowChooseInput">
575
- 关闭
576
- </a-button>
577
- </template>
578
- </x-form-table>
579
- </template>
580
- <a-input
581
- v-model="form[attr.model]"
582
- :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
583
- @change="searchRowChooseData"
584
- @focus="showCloseRowChooseInput"/>
585
- </a-popover>
586
- </a-form-model-item>
587
- </x-form-col>
588
- <!-- 评分框 -->
589
- <x-form-col
590
- v-else-if="attr.type === 'rate' && show"
591
- :labelCol="labelCol"
592
- :flex="attr.flex">
593
- <a-form-model-item
594
- v-bind="bindOther"
595
- :rules="rules"
596
- :ref="attr.model"
597
- :label="showLabel?attr.name:undefined"
598
- :prop="attr.prop ? attr.prop : attr.model">
599
- <x-rate
600
- v-model="form[attr.model]"
601
- :mode="mode"
602
- :disabled="disabled"
603
- :query-type="attr.queryType"
604
- :display-count="attr.displayCount"
605
- :max-count="attr.maxCount"
606
- :allow-half="attr.allowHalf"
607
- :icon="attr.rateIcon"
608
- :placeholder="attr.placeholder ? attr.placeholder : '请选择'+attr.name.replace(/\s*/g, '')"
609
- @change="attr.dataChangeFunc && debouncedDataChangeFunc()"
610
- />
611
- </a-form-model-item>
612
- </x-form-col>
613
- <!-- 区间选择器 -->
614
- <x-form-col
615
- v-else-if="attr.type === 'intervalPicker' && show"
616
- :labelCol="labelCol"
617
- :flex="attr.flex">
618
- <a-form-model-item
619
- v-bind="bindOther"
620
- :rules="rules"
621
- :ref="attr.model"
622
- :label="showLabel?attr.name:undefined"
623
- :prop="attr.prop ? attr.prop : attr.model">
624
- <x-interval-picker
625
- v-model="form[attr.model]"
626
- :mode="mode"
627
- :read-only="readOnly"
628
- :disabled="disabled && !readOnly"
629
- :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
630
- :start-placeholder="attr.startPlaceholder || '起始值'"
631
- :end-placeholder="attr.endPlaceholder || '结束值'"
632
- @blur="attr.inputOnBlurFunc && emitFunc(attr.inputOnBlurFunc,attr)"
633
- />
634
- </a-form-model-item>
635
- </x-form-col>
636
- <!-- 车牌号选择 -->
637
- <x-form-col
638
- v-else-if="attr.type === 'licensePlate' && show"
639
- :labelCol="labelCol"
640
- :flex="attr.flex">
641
- <a-form-model-item
642
- v-bind="bindOther"
643
- :rules="rules"
644
- :ref="attr.model"
645
- :label="showLabel?attr.name:undefined"
646
- :style="layout === 'inline'&& attr.occupyCol && attr.occupyCol > 1? {width:`calc(100% - ${attr.occupyCol * 1.533}rem)`}:{}"
647
- :prop="attr.prop ? attr.prop : attr.model">
648
- <!-- 如果配置了后置按钮插槽 -->
649
- <a-input
650
- v-if="mode ==='查询'"
651
- v-model="form[attr.model]"
652
- :whitespace="true"
653
- :read-only="readOnly"
654
- :disabled="disabled && !readOnly"
655
- style="width:100%"
656
- @blur="attr.inputOnBlurFunc && emitFunc(attr.inputOnBlurFunc,attr)"
657
- :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
658
- :ref="`${attr.model}input`"/>
659
- <x-license-plate
660
- v-else
661
- v-model="form[attr.model]"
662
- @change="attr.dataChangeFunc && debouncedDataChangeFunc()"
663
- ></x-license-plate>
664
- </a-form-model-item>
665
- </x-form-col>
666
- <!-- 录音 -->
667
- <x-form-col
668
- v-else-if="attr.type === 'recording' && show"
669
- :labelCol="labelCol"
670
- :flex="attr.flex">
671
- <recording
672
- ref="recording"
673
- @recordingData="recordingData"
674
- >
675
- </recording>
676
- </x-form-col>
677
- <!-- 表格录入 -->
678
- <x-form-col
679
- v-else-if="attr.type === 'rowEdit' && show"
680
- :labelCol="labelCol"
681
- :flex="attr.flex">
682
- <a-form-model-item
683
- v-bind="bindOther"
684
- :rules="rules"
685
- :ref="attr.model"
686
- :label="showLabel?attr.name:undefined"
687
- :prop="attr.prop ? attr.prop : attr.model">
688
- <x-form-table
689
- :key="'childTable_' + attr.model"
690
- :title="attr.name"
691
- :queryParamsName="attr.crud"
692
- :localEditMode="true"
693
- :fixed-query-form="childTableFixedQueryForm(attr)"
694
- :service-name="serviceName"
695
- @hook:mounted="(h)=>onComponentMounted(h, attr)"
696
- :ref="'childXFormTable_' + attr.model">
697
- </x-form-table>
698
- </a-form-model-item>
699
- </x-form-col>
700
- </template>
701
- <script>
702
- import { debounce } from 'ant-design-vue/lib/vc-table/src/utils'
703
- import XFormCol from '@vue2-client/base-client/components/common/XFormCol'
704
- import XBadge from '@vue2-client/base-client/components/common/XBadge'
705
- import CitySelect from '@vue2-client/base-client/components/common/CitySelect'
706
- import PersonSetting from '@vue2-client/base-client/components/common/PersonSetting'
707
- import AddressSearchCombobox from '@vue2-client/base-client/components/common/AddressSearchCombobox'
708
- import Upload from '@vue2-client/base-client/components/common/Upload'
709
- import moment from 'moment'
710
- import { getConfigByName, runLogic, getConfigByNameAsync } from '@vue2-client/services/api/common'
711
- import * as util from '@vue2-client/utils/util'
712
- import XTreeSelect from '@vue2-client/base-client/components/common/XForm/XTreeSelect'
713
- import { searchToListOption, searchToOption } from '@vue2-client/services/v3Api'
714
- import { mapState } from 'vuex'
715
- import { executeStrFunctionByContext } from '@vue2-client/utils/runEvalFunction'
716
- import XLicensePlate from '@vue2-client/base-client/components/common/XLicensePlate/XLicensePlate.vue'
717
- import XStatusButton from './XStatusButton.vue'
718
- import XClickChangeBtn from './itemComponent/XClickChangeBtn'
719
- import 'moment/locale/zh-cn'
720
- import XFormDatePicker from '@vue2-client/base-client/components/common/XDatePicker/index.vue'
721
- import XIntervalPicker from '@vue2-client/base-client/components/common/XIntervalPicker/XIntervalPicker.vue'
722
- import XRate from '@vue2-client/base-client/components/common/XRate/index.vue'
723
- import { post } from '@vue2-client/services/api/restTools'
724
- import ColorPickerCombobox from '@vue2-client/base-client/components/common/ColorPickerCombobox/ColorPickerCombobox.vue'
725
- import { createSelectValueTypeHandler } from '@vue2-client/base-client/plugins/selectValueTypeHelper'
726
-
727
- export default {
728
- name: 'XFormItem',
729
- components: {
730
- XFormDatePicker,
731
- XFormTable: () => import('@vue2-client/base-client/components/common/XFormTable/XFormTable.vue'),
732
- Recording: () => import('@vue2-client/base-client/components/common/Recording/Recording.vue'),
733
- XReport: () => import('@vue2-client/base-client/components/common/XReportGrid/XReport.vue'),
734
- XLicensePlate,
735
- XTreeSelect,
736
- XFormCol,
737
- XBadge,
738
- CitySelect,
739
- PersonSetting,
740
- AddressSearchCombobox,
741
- Upload,
742
- XStatusButton,
743
- XClickChangeBtn,
744
- XIntervalPicker,
745
- XRate,
746
- ColorPickerCombobox
747
- },
748
- data () {
749
- // 检索去抖
750
- this.fetchFunction = debounce(this.fetchFunction, 800)
751
- // 初始化selectValueType处理器
752
- this.selectValueTypeHandler = createSelectValueTypeHandler(this)
753
- return {
754
- option: [],
755
- // 最后检索版本
756
- lastFetchId: 0,
757
- // 检索中
758
- searching: false,
759
- searchResult: '',
760
- optionForFunc: [],
761
- // 控制当前表单项是否展示
762
- show: true,
763
- // moment
764
- moment,
765
- // 行选择器浮层是否显示
766
- rowChoosePopoverVisible: false,
767
- // 行选择器CRUD固定查询值
768
- rowChooseFixedQueryValue: undefined,
769
- bindOther: {}
770
- }
771
- },
772
- props: {
773
- attr: {
774
- type: Object,
775
- default:
776
- () => {
777
- return {}
778
- }
779
- },
780
- form: {
781
- type: Object,
782
- required:
783
- true
784
- },
785
- disabled: {
786
- type: Boolean,
787
- default:
788
- () => {
789
- return false
790
- }
791
- },
792
- readOnly: {
793
- type: Boolean,
794
- default:
795
- () => {
796
- return false
797
- }
798
- },
799
- mode: {
800
- type: String,
801
- default:
802
- () => {
803
- return '查询'
804
- }
805
- },
806
- files: {
807
- type: Array,
808
- default:
809
- () => {
810
- return []
811
- }
812
- },
813
- images: {
814
- type: Array,
815
- default:
816
- () => {
817
- return []
818
- }
819
- },
820
- // 是否启用时间弹出到最外层
821
- enablePopupToBody: {
822
- type: Boolean,
823
- default: false
824
- },
825
- serviceName: {
826
- type: String,
827
- default:
828
- undefined
829
- },
830
- // 调用logic获取数据源的追加参数
831
- getDataParams: {
832
- type: Object,
833
- default:
834
- undefined
835
- },
836
- // 布局
837
- layout: {
838
- type: String,
839
- default:
840
- 'horizontal'
841
- },
842
- // 环境
843
- env: {
844
- type: String,
845
- default:
846
- () => {
847
- return 'prod'
848
- }
849
- },
850
- // 设置表单值
851
- setForm: {
852
- type: Function,
853
- default: (val) => {
854
- console.log(val)
855
- }
856
- },
857
- showLabel: {
858
- type: Boolean,
859
- default:
860
- () => {
861
- return true
862
- }
863
- },
864
- labelCol: {
865
- type: Object,
866
- default: () => {
867
- return { span: 8 }
868
- }
869
- },
870
- rules: {
871
- type: Array,
872
- default:
873
- () => {
874
- return undefined
875
- }
876
- }
877
- },
878
- provide () {
879
- return {
880
- FormItemContext: this
881
- }
882
- },
883
- created () {
884
- this.init()
885
- if (this.attr.keyName && (this.attr?.keyName?.toString().indexOf('async ') !== -1 || this.attr?.keyName?.toString()?.indexOf('function') !== -1)) {
886
- this.debouncedUpdateOptions = debounce(this.updateOptions, 200)
887
- }
888
- if (this.attr.dataChangeFunc) {
889
- this.debouncedDataChangeFunc = debounce(this.dataChangeFunc, 200)
890
- // 执行一次
891
- this.dataChangeFunc()
892
- }
893
- if (this.attr.showFormItemFunc) {
894
- this.debouncedShowFormItemFunc = debounce(this.showFormItemFunc, 100)
895
- // 执行一次
896
- this.showFormItemFunc()
897
- }
898
- if (this.attr.showQueryFormItemFunc) {
899
- this.debouncedShowQueryFormItemFunc = debounce(this.showQueryFormItemFunc, 100)
900
- // 执行一次
901
- this.showQueryFormItemFunc()
902
- }
903
- // 人员联动框增加监听
904
- if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString().endsWith(']联动人员')) {
905
- this.debouncedUserLinkFunc = debounce(() => this.updateResOptions('人员'), 200)
906
- }
907
- if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString().endsWith(']联动部门')) {
908
- this.debouncedDepLinkFunc = debounce(() => this.updateResOptions('部门'), 200)
909
- }
910
- // xTreeSelect 自己调用 mounted
911
- if (this.attr.type !== 'treeSelect') {
912
- this.$emit('mounted', this.attr)
913
- }
914
- },
915
- computed: {
916
- ...mapState('account', { currUser: 'user', curRoles: 'roles', curPermissions: 'permissions' }),
917
- queryParamsName () {
918
- if (this.attr.keyName.startsWith('function')) {
919
- // 调用异步函数获取内容
920
- const obj = executeStrFunctionByContext(this, this.attr.keyName, [this.form, runLogic, this.mode, getConfigByNameAsync])
921
- // 处理同步返回值
922
- return this.handleQueryParamsResult(obj)
923
- } else if (this.attr.keyName.startsWith('async ')) {
924
- console.warn('此处不支持异步操作')
925
- return ''
926
- } else {
927
- // 按现有方式处理
928
- return this.attr.keyName.split('@')[this.attr.keyName.split('@').length - 1]
929
- }
930
- },
931
- // 判断弹出时是否Cover,弹出只支持Cover以及CRUD
932
- isCover () {
933
- // 如果 queryParamsName 为空,返回空
934
- if (!this.queryParamsName) {
935
- return false
936
- }
937
- const result = this.queryParamsName.endsWith('Cover')
938
- return result
939
- },
940
- },
941
- watch: {
942
- attr: {
943
- handler () {
944
- this.init()
945
- },
946
- deep: true
947
- },
948
- form: {
949
- handler (newVal, oldVal) {
950
- // 如果是从函数获取 options
951
- if (this.attr.keyName && (this.attr.keyName.toString().indexOf('async ') !== -1 || this.attr.keyName.toString().indexOf('function') !== -1)) {
952
- this.debouncedUpdateOptions()
953
- }
954
- // 如果有自定义是否展示表单项函数
955
- if (this.attr.showFormItemFunc) {
956
- this.debouncedShowFormItemFunc()
957
- }
958
- // 如果有自定义是否展示查询表单项函数
959
- if (this.attr.showQueryFormItemFunc) {
960
- this.debouncedShowQueryFormItemFunc()
961
- }
962
- // 地址搜索框赋值
963
- if (this.attr.type === 'addressSearch' || this.attr.type === 'coordinateSearch') {
964
- this.$refs.addressSearchCombobox.addressInput = this.form[this.attr.model]
965
- }
966
- // 数据源来自人员联动时更新数据
967
- if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString().endsWith(']联动人员')) {
968
- this.debouncedUserLinkFunc()
969
- }
970
- // 数据源来自人员联动时更新数据
971
- if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString().endsWith(']联动部门')) {
972
- this.debouncedDepLinkFunc()
973
- }
974
- },
975
- deep: true
976
- }
977
- },
978
- inject: {
979
- getComponentByName: {
980
- default: () => () => {
981
- console.warn('getComponentByName is not provided')
982
- return null // 或者返回一个默认的函数
983
- },
984
- },
985
- registerComponent: {
986
- default: () => () => {
987
- console.warn('registerComponent is not provided')
988
- return null // 或者返回一个默认的函数
989
- },
990
- },
991
- getSelf: {
992
- default: () => () => {
993
- console.warn('getSelf is not provided')
994
- return null // 或者返回一个默认的函数
995
- },
996
- },
997
- XFormContext: {
998
- default: () => () => {
999
- console.warn('XFormContext is not provided')
1000
- return null // 或者返回一个默认的函数
1001
- },
1002
- },
1003
- setRequired: {
1004
- default: () => () => {
1005
- console.warn('setRequired is not provided')
1006
- return null // 或者返回一个默认的函数
1007
- },
1008
- },
1009
- removeRequired: {
1010
- default: () => () => {
1011
- console.warn('removeRequired is not provided')
1012
- return null // 或者返回一个默认的函数
1013
- },
1014
- }
1015
- },
1016
- methods: {
1017
- // 处理 queryParams 结果并更新 rowChooseFixedQueryValue
1018
- handleQueryParamsResult (obj) {
1019
- let configName = ''
1020
- if (obj && typeof obj === 'object') {
1021
- // obj 是一个对象,并且不是数组
1022
- if (Object.prototype.hasOwnProperty.call(obj, 'configName')) {
1023
- configName = obj?.configName
1024
- }
1025
- if (Object.prototype.hasOwnProperty.call(obj, 'fixedQueryForm')) {
1026
- if (obj?.fixedQueryForm && typeof obj?.fixedQueryForm === 'object') {
1027
- this.rowChooseFixedQueryValue = Object.assign({}, this.rowChooseFixedQueryValue, obj.fixedQueryForm)
1028
- }
1029
- }
1030
- } else if (obj && typeof obj === 'string') {
1031
- configName = obj
1032
- }
1033
- return configName
1034
- },
1035
- // 根据selectValueType预处理options数据
1036
- processOptionsForValueType (options) {
1037
- return this.selectValueTypeHandler.processOptions(options, this.attr.selectValueType)
1038
- },
1039
-
1040
- // 处理both模式的数据,为表单添加label字段
1041
- processBothModeData () {
1042
- this.selectValueTypeHandler.processBothMode(
1043
- this.form,
1044
- this.attr.model,
1045
- this.attr.selectValueType,
1046
- this.option
1047
- )
1048
- },
1049
-
1050
- // 根据value查找对应的label(支持单选和多选)
1051
- findLabelByValue (value) {
1052
- return this.selectValueTypeHandler.findLabel(value, this.option)
1053
- },
1054
-
1055
- // 统一的表单项change处理逻辑
1056
- handleFormItemChange () {
1057
- // 处理both模式
1058
- if (this.attr.selectValueType === 'both') {
1059
- this.$nextTick(() => {
1060
- this.selectValueTypeHandler.processBothMode(
1061
- this.form,
1062
- this.attr.model,
1063
- this.form[this.attr.model],
1064
- this.option
1065
- )
1066
- })
1067
- }
1068
- // 处理label模式
1069
- if (this.attr.selectValueType === 'label') {
1070
- this.$nextTick(() => {
1071
- this.selectValueTypeHandler.processLabelMode(
1072
- this.form,
1073
- this.attr.model,
1074
- this.form[this.attr.model],
1075
- this.option
1076
- )
1077
- })
1078
- }
1079
- // 处理原有的dataChangeFunc
1080
- if (this.attr.dataChangeFunc) {
1081
- this.debouncedDataChangeFunc()
1082
- }
1083
- },
1084
-
1085
- // Select组件change处理
1086
- handleSelectChange () {
1087
- this.handleFormItemChange()
1088
- },
1089
-
1090
- // Checkbox组件change处理
1091
- handleCheckboxChange () {
1092
- this.handleFormItemChange()
1093
- },
1094
-
1095
- // Radio组件change处理
1096
- handleRadioChange () {
1097
- this.handleFormItemChange()
1098
- },
1099
-
1100
- // TreeSelect组件change处理(通过XTreeSelect组件回调)
1101
- handleTreeSelectChange () {
1102
- this.handleFormItemChange()
1103
- },
1104
-
1105
- // 把内部的crud表单录入放到表单中,以便外部可以调用
1106
- onComponentMounted (h, attr) {
1107
- console.log('crud表单', h)
1108
- if (attr.crud) {
1109
- this.registerComponent(attr.model, this.$refs['childXFormTable_' + attr.model])
1110
- }
1111
- },
1112
- childTableFixedQueryForm (item) {
1113
- console.log('传递的form', this.form)
1114
- if (this.modifyModelData?.primaryKeyData) {
1115
- const fixedForm = {}
1116
- fixedForm[item.childTableForeignKeyName] = Object.values(this.modifyModelData.primaryKeyData)[0]
1117
- return fixedForm
1118
- }
1119
- return null
1120
- },
1121
- // 动态生成事件绑定对象
1122
- generateDynamicEvents (inputOnAfterFunc, attr) {
1123
- const events = {}
1124
- const states = this.parseStates(attr.inputOnAfterName, inputOnAfterFunc)
1125
-
1126
- states.forEach((state) => {
1127
- // 动态绑定事件名到 emitFunc
1128
- events[state.event] = () => {
1129
- console.info('事件名', state.event)
1130
- this.emitFunc(state.event, attr)
1131
- }
1132
- })
1133
-
1134
- return events // 返回 { state1Event: handler, state2Event: handler, ... }
1135
- },
1136
- parseStates (input, events) {
1137
- const eventNames = events.split('|')
1138
- return input.split('|').map((label, index) => ({
1139
- label,
1140
- event: eventNames[index] // 如果没有提供事件名称,则使用默认值
1141
- }))
1142
- },
1143
- focusInput () {
1144
- if (this.attr.defaultFocus) {
1145
- this.$nextTick(h => {
1146
- const el = this.$refs[`${this.attr.model}input`]?.$el
1147
- let inputEl
1148
- if (el) {
1149
- if (el.tagName.toLowerCase() === 'input') {
1150
- inputEl = el
1151
- } else {
1152
- inputEl = el.querySelector('input')
1153
- }
1154
- }
1155
- if (inputEl) {
1156
- inputEl.focus()
1157
- if (inputEl.type === 'number') {
1158
- if (inputEl.valueAsNumber) {
1159
- inputEl.setSelectionRange(0, inputEl.valueAsNumber.toString().length)
1160
- }
1161
- } else {
1162
- if (inputEl.value) {
1163
- inputEl.setSelectionRange(0, inputEl.value.length)
1164
- }
1165
- }
1166
- }
1167
- })
1168
- }
1169
- },
1170
- // 更新人员下拉框数据
1171
- async updateResOptions (type) {
1172
- if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString()?.endsWith(`]联动${type}`)) {
1173
- const startIndex = this.attr.keyName.indexOf('[') + 1
1174
- const endIndex = this.attr.keyName.indexOf(']', startIndex)
1175
- const fromModel = this.attr.keyName.substring(startIndex, endIndex).replace('.', '_')
1176
- // 获取表单字段的实际值(优先使用originData中的原始值)
1177
- const rawFieldValue = this.form.originData && this.form.originData[fromModel]
1178
- ? this.form.originData[fromModel]
1179
- : this.form[fromModel]
1180
-
1181
- // 确保数据为数组格式(用于filter参数)
1182
- const filterValues = Array.isArray(rawFieldValue)
1183
- ? rawFieldValue
1184
- : [rawFieldValue]
1185
- if (fromModel?.length && filterValues?.length) {
1186
- const searchData = {
1187
- source: `获取${type}`,
1188
- userid: this.currUser.id,
1189
- filter: filterValues,
1190
- filterType: fromModel.indexOf('org') > -1 ? 'org' : 'dep'
1191
- }
1192
- const tempArray = []
1193
- await searchToListOption(searchData, res => {
1194
- this.getDataCallback(
1195
- res.filter(h => {
1196
- if (fromModel.indexOf('org') > -1) {
1197
- if (type === '部门') {
1198
- if (filterValues?.includes(h.orgid || h.f_organization_id) || filterValues?.includes(h.parentid) || tempArray.includes(h.parentid)) {
1199
- tempArray.push(h.value)
1200
- return true
1201
- }
1202
- return false
1203
- } else {
1204
- return filterValues?.includes(h.orgid || h.f_organization_id || h.parentid)
1205
- }
1206
- } else {
1207
- return filterValues?.includes(h?.parentid)
1208
- }
1209
- }
1210
- )
1211
- )
1212
- })
1213
- }
1214
- }
1215
- },
1216
- // js 函数作为数据源
1217
- async updateOptions () {
1218
- if (this.attr.keyName && (this.attr.keyName.indexOf('async ') !== -1 || this.attr.keyName.indexOf('function ') !== -1)) {
1219
- const rawOptions = await executeStrFunctionByContext(this, this.attr.keyName, [this.form, runLogic, this.mode, getConfigByNameAsync, post])
1220
- // 根据selectValueType预处理options数据
1221
- this.optionForFunc = this.processOptionsForValueType(rawOptions)
1222
- }
1223
- },
1224
- async dataChangeFunc () {
1225
- if (this.attr.dataChangeFunc) {
1226
- await executeStrFunctionByContext(this, this.attr.dataChangeFunc, [this.form, this.setForm, this.attr, util, this.mode, runLogic, getConfigByNameAsync])
1227
- }
1228
- },
1229
- async showFormItemFunc () {
1230
- if (this.attr.showFormItemFunc) {
1231
- const obj = executeStrFunctionByContext(this, this.attr.showFormItemFunc, [this.form, this.setForm, this.attr, util, this.mode, this.curPermissions, this.curRoles])
1232
- // 判断是 bool 还是 obj 兼容
1233
- if (typeof obj === 'boolean') {
1234
- this.show = obj
1235
- } else if (obj && typeof obj === 'object') {
1236
- // obj 是一个对象,并且不是数组
1237
- if (Object.prototype.hasOwnProperty.call(obj, 'show')) {
1238
- this.show = obj?.show
1239
- }
1240
- if (Object.prototype.hasOwnProperty.call(obj, 'readOnly')) {
1241
- this.readOnly = obj?.readOnly
1242
- }
1243
- if (Object.prototype.hasOwnProperty.call(obj, 'disabled')) {
1244
- this.disabled = obj?.disabled
1245
- }
1246
- }
1247
- } else {
1248
- this.show = true
1249
- }
1250
- },
1251
- async showQueryFormItemFunc () {
1252
- if (this.attr.showQueryFormItemFunc) {
1253
- const obj = executeStrFunctionByContext(this, this.attr.showQueryFormItemFunc, [this.form, this.setForm, this.attr, util, this.mode, this.curPermissions, this.curRoles])
1254
- // 判断是 bool 还是 obj 兼容
1255
- if (typeof obj === 'boolean') {
1256
- this.show = obj
1257
- } else if (obj && typeof obj === 'object') {
1258
- // obj 是一个对象,并且不是数组
1259
- if (Object.prototype.hasOwnProperty.call(obj, 'show')) {
1260
- this.show = obj?.show
1261
- }
1262
- if (Object.prototype.hasOwnProperty.call(obj, 'readOnly')) {
1263
- this.readOnly = obj?.readOnly
1264
- }
1265
- if (Object.prototype.hasOwnProperty.call(obj, 'disabled')) {
1266
- this.disabled = obj?.disabled
1267
- }
1268
- }
1269
- } else {
1270
- this.show = true
1271
- }
1272
- },
1273
- init () {
1274
- if (!this.attr.flex) {
1275
- if (this.mode === '新增/修改') {
1276
- if (['horizontal', 'vertical'].includes(this.layout) || ['textarea', 'file', 'image'].includes(this.attr.type)) {
1277
- // 新增修改表单 horizontal 模式下默认为一行
1278
- this.attr.flex = {
1279
- xs: 24,
1280
- sm: 24,
1281
- md: 24,
1282
- lg: 24,
1283
- xl: 24,
1284
- xxl: 24,
1285
- fullWidth: true
1286
- }
1287
- } else {
1288
- // 新增修改表单 vertical 模式下默认为1列
1289
- this.attr.flex = {
1290
- xs: 24,
1291
- sm: 12,
1292
- md: 8,
1293
- lg: 8,
1294
- xl: 6,
1295
- xxl: 6
1296
- }
1297
- }
1298
- } else {
1299
- this.attr.flex = {
1300
- xs: 24,
1301
- sm: 24,
1302
- md: 8,
1303
- lg: 6,
1304
- xl: 6,
1305
- xxl: 6
1306
- }
1307
- }
1308
- }
1309
- if (this.attr.keyName && typeof this.attr.keyName === 'string') {
1310
- if (this.attr.keyName.indexOf('logic@') !== -1) {
1311
- this.getData({}, res => this.getDataCallback(res))
1312
- } else if (this.attr.keyName.indexOf('search@') !== -1) {
1313
- // `tool.getFullTree(this.getRights().where(row.getType()==$organization$))`
1314
- // 判断是否根据角色查询
1315
- let source = this.attr.keyName.substring(7)
1316
- const userid = this.currUser.id
1317
- let roleName = 'roleName'
1318
- if (source.startsWith('根据角色[') && source.endsWith(']获取人员')) {
1319
- const startIndex = source.indexOf('[') + 1
1320
- const endIndex = source.indexOf(']', startIndex)
1321
- roleName = source.substring(startIndex, endIndex)
1322
- source = '根据角色获取人员'
1323
- }
1324
- const searchData = { source, userid, roleName }
1325
- // 判断是否根据某个表单项联动 仅返回列表结构并筛选
1326
- if (source.startsWith('根据表单项[') && source.endsWith(']联动人员')) {
1327
- this.updateResOptions('人员')
1328
- } else if (source.startsWith('根据表单项[') && source.endsWith(']联动部门')) {
1329
- this.updateResOptions('部门')
1330
- } else if (this.attr.type === 'select' || this.attr.type === 'checkbox') {
1331
- // 仅获取最内层数据
1332
- searchToListOption(searchData, res => this.getDataCallback(res))
1333
- } else {
1334
- // 其他资源通用逻辑
1335
- searchToOption(searchData, res => this.getDataCallback(res))
1336
- }
1337
- } else if (this.attr.keyName.indexOf('config@') !== -1) {
1338
- const configName = this.attr.keyName.substring(7)
1339
- getConfigByName(configName, this.serviceName, res => {
1340
- this.getDataCallback(res.value)
1341
- }, this.env === 'dev')
1342
- } else if (this.attr.keyName.indexOf('async ') !== -1 || this.attr.keyName.indexOf('function ') !== -1) {
1343
- this.updateOptions()
1344
- }
1345
- } else if (this.attr.keys) {
1346
- // 对静态配置的keys也进行预处理
1347
- this.getDataCallback(this.attr.keys)
1348
- }
1349
- this.focusInput()
1350
- },
1351
- addressSearchComboboxSelect (data) {
1352
- this.form = Object.assign(this.form, JSON.parse(data))
1353
- },
1354
- onDivisionsChange (data) {
1355
- this.emitFunc('addressSearchComboboxSelect', {
1356
- key: this.attr.model,
1357
- value: data
1358
- })
1359
- },
1360
- getDataCallback (res) {
1361
- // 根据selectValueType预处理options数据
1362
- this.option = this.processOptionsForValueType(res)
1363
-
1364
- if (this.attr.type === 'treeSelect') {
1365
- this.$nextTick(() => {
1366
- this.$refs.xTreeSelect.init({
1367
- option: this.option,
1368
- form: this.form,
1369
- queryType: this.attr.queryType,
1370
- name: this.attr.name,
1371
- model: this.attr.model,
1372
- mode: this.mode,
1373
- disabled: this.disabled
1374
- })
1375
- })
1376
- } else if (this.attr.type === 'radio' || ['radioGroup', 'clickChange'].includes(this.attr.showMode)) {
1377
- this.initRadioValue()
1378
- }
1379
- },
1380
- initRadioValue () {
1381
- const model = this.attr.model
1382
- if (this.mode === '新增/修改' && (this.form[model] === undefined || this.form[model] === null) && !this.attr.prop) {
1383
- if (this.attr.keys && this.attr.keys.length > 1) {
1384
- this.form[model] = this.attr.keys[0].value
1385
- } else if (this.option.length > 1) {
1386
- this.form[model] = this.option[0].value
1387
- }
1388
- }
1389
- },
1390
- // 文件框时设置上传组件的值
1391
- setFiles (fileIds) {
1392
- if (!this.form[this.attr.model]) {
1393
- this.form[this.attr.model] = []
1394
- }
1395
- this.form[this.attr.model] = [...fileIds]
1396
- },
1397
- // 懒加载检索方法
1398
- fetchFunction (value) {
1399
- this.lastFetchId += 1
1400
- const fetchId = this.lastFetchId
1401
- this.option = []
1402
- this.searching = true
1403
- this.getData({
1404
- word: value
1405
- }, res => {
1406
- if (fetchId !== this.lastFetchId) {
1407
- return
1408
- }
1409
- this.option = res
1410
- this.searching = false
1411
- })
1412
- },
1413
- // 获取数据
1414
- getData (value, callbackFun) {
1415
- if (value !== '') {
1416
- const logicName = this.attr.keyName
1417
- const logic = logicName.substring(6)
1418
- // 调用logic前设置参数
1419
- if (this.getDataParams && this.getDataParams[this.attr.model]) {
1420
- Object.assign(value, this.getDataParams[this.attr.model])
1421
- }
1422
- runLogic(logic, Object.assign(value, {
1423
- orgId: this.currUser.orgid,
1424
- userId: this.currUser.id
1425
- }), this.serviceName, this.env === 'dev').then(res => {
1426
- callbackFun(res)
1427
- }).catch(e => {
1428
- callbackFun([])
1429
- console.error('获取数据失败:' + e)
1430
- })
1431
- }
1432
- },
1433
- filterOption (input, option) {
1434
- const child = option.componentOptions.children[0]
1435
- if (child.text) {
1436
- return child.text.toLowerCase().indexOf(input.toLowerCase()) >= 0
1437
- } else if (child.elm.innerText) {
1438
- return child.elm.innerText.toLowerCase().indexOf(input.toLowerCase()) >= 0
1439
- } else {
1440
- return child.child.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
1441
- }
1442
- },
1443
- // 表单项变更函数中调用 控制表单组中表单项组名为 groupName 的表单是否展示
1444
- // func:x-form-show(显示)/x-form-no-show(不显示)
1445
- emitShowFormFunc (func, groupName) {
1446
- this.emitFunc(func, groupName)
1447
- },
1448
- emitFunc (func, data) {
1449
- this.$emit('x-form-item-emit-func', func, data, data?.model ? this.form[data.model] : this.form)
1450
- },
1451
- itemMounted (h) {
1452
- this.$emit('mounted', h)
1453
- },
1454
- rowChoose (rows) {
1455
- this.$emit('rowChoose', rows, this.attr, this.closeRowChooseInput)
1456
- },
1457
- searchRowChooseData () {
1458
- if (this.searching) {
1459
- return
1460
- }
1461
- this.lastFetchId += 1
1462
- const fetchId = this.lastFetchId
1463
- this.searching = true
1464
- if (fetchId !== this.lastFetchId) {
1465
- return
1466
- }
1467
- this.rowChooseFixedQueryValue = []
1468
- this.rowChooseFixedQueryValue[this.attr.model] = this.form[this.attr.model]
1469
- this.$nextTick(() => {
1470
- this.$refs.rowChooseTable.refresh(true)
1471
- })
1472
- },
1473
- showCloseRowChooseInput () {
1474
- this.rowChoosePopoverVisible = true
1475
- },
1476
- closeRowChooseInput () {
1477
- this.rowChoosePopoverVisible = false
1478
- },
1479
- rowChooseSearchAfterQuery () {
1480
- this.searching = false
1481
- },
1482
- // 获取 recording 转换后的数据
1483
- getRecodingData () {
1484
- return this.$refs.recording.getRecordingData()
1485
- },
1486
- recordingData (data) {
1487
- this.emitFunc('recordingData', data)
1488
- },
1489
- getPopupContainer (triggerNode) {
1490
- // 行编辑模式特殊处理
1491
- if (typeof this.$vnode?.key === 'string' && this.$vnode.key.startsWith('editRow')) {
1492
- // 限制最多向上查找5层
1493
- let parent = triggerNode.parentNode
1494
- let depth = 0
1495
- const maxDepth = 10
1496
-
1497
- while (parent && parent !== document.body && depth < maxDepth) {
1498
- if (parent.tagName === 'TBODY') {
1499
- return parent
1500
- }
1501
- parent = parent.parentNode
1502
- depth++
1503
- }
1504
- // 如果5层内没找到,回退到body
1505
- return document.body
1506
- }
1507
- return triggerNode.parentNode
1508
- },
1509
- colorPickerComboboxSelect (val) {
1510
- this.form[this.attr.model] = val
1511
- },
1512
- }
1513
- }
1514
- </script>
1515
-
1516
- <style lang="less" scoped>
1517
- .custom-dropdown {
1518
- position: absolute;
1519
- z-index: 1050;
1520
- }
1521
-
1522
- .multiple_select {
1523
- vertical-align: middle;
1524
- :deep(.ant-select-selection) {
1525
- max-height: 32px;
1526
- overflow-y: scroll;
1527
- }
1528
- }
1529
-
1530
- </style>
1
+ <template>
2
+ <!-- 输入框 -->
3
+ <x-form-col
4
+ v-if="attr.type === 'input' && show"
5
+ :occupyCol="attr.occupyCol"
6
+ :labelCol="labelCol"
7
+ :flex="attr.flex">
8
+ <a-form-model-item
9
+ v-bind="bindOther"
10
+ :rules="rules"
11
+ :ref="attr.model"
12
+ :label="showLabel?attr.name:undefined"
13
+ :prop="attr.prop ? attr.prop : attr.model">
14
+ <!-- 如果配置了后置按钮插槽 -->
15
+ <a-input-group
16
+ v-if="((attr.inputOnAfterName && attr.inputOnAfterFunc) || (attr.inputOnAfterIcon && attr.inputOnAfterIconFunc)) && mode !== '查询'"
17
+ style="display: flex; width: 100%; padding: 4px 0"
18
+ compact>
19
+ <a-input
20
+ v-model="form[attr.model]"
21
+ :read-only="readOnly"
22
+ :disabled="disabled && !readOnly"
23
+ :whitespace="true"
24
+ @input="attr.dataChangeFunc && debouncedDataChangeFunc()"
25
+ :suffix="attr.inputSuffix && mode !== '新增' ? attr.inputSuffix : ''"
26
+ @blur="mode !== '查询' && attr.inputOnBlurFunc && emitFunc(attr.inputOnBlurFunc,attr)"
27
+ @keyup.enter="mode !== '查询' && attr.inputOnEnterFunc && emitFunc(attr.inputOnEnterFunc, attr)"
28
+ :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
29
+ :ref="`${attr.model}input`"/>
30
+ <a-button
31
+ v-if="attr.inputOnAfterName && attr.inputOnAfterFunc && !attr.inputOnAfterName.includes('|')"
32
+ style="width: auto; min-width: 4rem;max-width: 6rem"
33
+ type="primary"
34
+ @click="emitFunc(attr.inputOnAfterFunc,attr)">
35
+ {{ attr.inputOnAfterName }}
36
+ </a-button>
37
+ <!-- 仅可以配置 一个按钮 以及 一个图标插槽 -->
38
+ <a-button
39
+ style="width: 2rem; flex-shrink: 0;"
40
+ v-else-if="attr.inputOnAfterIcon"
41
+ :type="attr.inputOnAfterIcon && attr.inputOnAfterName ? 'primary' :''"
42
+ :icon="attr.inputOnAfterIcon || 'question'"
43
+ @click="emitFunc(attr.inputOnAfterIconFunc,attr)">
44
+ </a-button>
45
+ <!-- 状态按钮 -->
46
+ <x-status-button
47
+ v-else
48
+ :states="parseStates(attr.inputOnAfterName, attr.inputOnAfterFunc)"
49
+ v-on="generateDynamicEvents(attr.inputOnAfterFunc, attr)"
50
+ style="width: auto; min-width: 4rem; max-width: 6rem"
51
+ />
52
+ </a-input-group>
53
+ <a-input-number
54
+ v-else-if="attr.numberInput && !readOnly"
55
+ v-model="form[attr.model]"
56
+ :whitespace="true"
57
+ @change="attr.dataChangeFunc && debouncedDataChangeFunc()"
58
+ :disabled="disabled && !readOnly"
59
+ style="width:100%"
60
+ @blur="mode !== '查询' && attr.inputOnBlurFunc && emitFunc(attr.inputOnBlurFunc,attr)"
61
+ @keyup.enter="mode !== '查询' && attr.inputOnEnterFunc && emitFunc(attr.inputOnEnterFunc, attr)"
62
+ :suffix="attr.inputSuffix && mode !== '新增' ? attr.inputSuffix : ''"
63
+ :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
64
+ :ref="`${attr.model}input`"/>
65
+ <a-input
66
+ v-else
67
+ v-model="form[attr.model]"
68
+ :whitespace="true"
69
+ :read-only="readOnly"
70
+ :disabled="disabled && !readOnly"
71
+ @input="attr.dataChangeFunc && debouncedDataChangeFunc()"
72
+ :suffix="attr.inputSuffix && mode !== '新增' ? attr.inputSuffix : ''"
73
+ style="width:100%"
74
+ @blur="mode !== '查询' && attr.inputOnBlurFunc && emitFunc(attr.inputOnBlurFunc,attr)"
75
+ @keyup.enter="mode !== '查询' && attr.inputOnEnterFunc && emitFunc(attr.inputOnEnterFunc, attr)"
76
+ :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
77
+ :ref="`${attr.model}input`"/>
78
+ </a-form-model-item>
79
+ </x-form-col>
80
+ <!-- 下拉框 -->
81
+ <x-form-col
82
+ v-else-if="attr.type === 'select' && show"
83
+ :labelCol="labelCol"
84
+ :flex="attr.flex">
85
+ <a-form-model-item
86
+ v-bind="bindOther"
87
+ :rules="rules"
88
+ v-if="!attr.showMode || mode === '查询' || attr.showMode === 'select' "
89
+ :ref="attr.model"
90
+ :label="showLabel?attr.name:undefined"
91
+ :prop="attr.prop ? attr.prop : attr.model">
92
+ <!-- <span slot="label" class="label-box">{{ showLabel?attr.name:undefined }}</span>-->
93
+ <a-select
94
+ v-if="!attr.lazyLoad || attr.lazyLoad === 'false'"
95
+ v-model="form[attr.model]"
96
+ :disabled="disabled || readOnly"
97
+ @change="handleSelectChange"
98
+ :filter-option="filterOption"
99
+ :getPopupContainer="getPopupContainer"
100
+ dropdownClassName="custom-dropdown"
101
+ :dropdownMatchSelectWidth="false"
102
+ :dropdownStyle="{ position: 'absolute'}"
103
+ :placeholder="attr.placeholder ? attr.placeholder : '请选择'"
104
+ show-search
105
+ :allowClear="true"
106
+ :getCalendarContainer="(triggerNode) => triggerNode.parentNode"
107
+ >
108
+ <a-select-option
109
+ v-if="mode === '查询'"
110
+ key="999999"
111
+ value="">全部
112
+ </a-select-option>
113
+ <template v-if="attr.keys">
114
+ <a-select-option
115
+ v-for="(item,index) in attr.keys"
116
+ :key="index.value"
117
+ :value="item.value + ''">
118
+ {{ item.label }}
119
+ </a-select-option>
120
+ </template>
121
+ <template v-else>
122
+ <template
123
+ v-if="attr.keyName.indexOf('logic@') !== -1 || attr.keyName.indexOf('config@') !== -1
124
+ ||attr.keyName.indexOf('search@') !== -1 || attr.keyName.indexOf('search@') !== -1">
125
+ <a-select-option
126
+ v-for="(item,index) in option"
127
+ :key="index.value"
128
+ :value="item.value + ''">
129
+ <template v-if="attr.keyName.indexOf('config@') !== -1 && item.status">
130
+ <!-- 徽标(badge) -->
131
+ <a-badge v-if="item.status !== 'gary'" :color="item.status" :text="item.label"/>
132
+ <a-badge v-else color="#D9D9D9" :text="item.label"/>
133
+ </template>
134
+ <template v-else>
135
+ {{ item.label }}
136
+ </template>
137
+ </a-select-option>
138
+ </template>
139
+ <template
140
+ v-else-if="attr.keyName.indexOf('async ') !== -1 || attr.keyName.indexOf('function ') !== -1">
141
+ <a-select-option
142
+ v-for="(item,index) in optionForFunc"
143
+ :key="index.value"
144
+ :value="item.value + ''">
145
+ <template>
146
+ {{ item.label }}
147
+ </template>
148
+ </a-select-option>
149
+ </template>
150
+ <template v-else>
151
+ <a-select-option
152
+ v-for="item in $appdata.getDictionaryList(attr.keyName)"
153
+ :key="item.value"
154
+ :value="item.value + ''">
155
+ <!-- 徽标(badge) -->
156
+ <x-badge
157
+ :badge-key="attr.keyName"
158
+ :replaceText="item.text"
159
+ :value="item.value"
160
+ :service-name="serviceName"
161
+ :env="env"/>
162
+ </a-select-option>
163
+ </template>
164
+ </template>
165
+ </a-select>
166
+ <a-select
167
+ v-else
168
+ v-model="form[attr.model]"
169
+ :disabled="disabled || readOnly"
170
+ @change="handleSelectChange"
171
+ :filter-option="filterOption"
172
+ :getPopupContainer="getPopupContainer"
173
+ dropdownClassName="custom-dropdown"
174
+ :dropdownMatchSelectWidth="false"
175
+ :dropdownStyle="{ position: 'absolute'}"
176
+ :placeholder="attr.placeholder ? attr.placeholder : '搜索' + attr.name"
177
+ show-search
178
+ @search="fetchFunction"
179
+ >
180
+ <template #notFoundContent>
181
+ <a-spin v-if="searching" size="small"/>
182
+ </template>
183
+ <a-select-option
184
+ v-if="mode === '查询'"
185
+ key="999999"
186
+ value="">全部
187
+ </a-select-option>
188
+ <a-select-option
189
+ v-for="(item,index) in option"
190
+ :key="index"
191
+ :value="item.value + ''">{{ item.label }}
192
+ </a-select-option>
193
+ </a-select>
194
+ </a-form-model-item>
195
+ <a-form-model-item
196
+ :disabled="disabled || readOnly"
197
+ v-bind="bindOther"
198
+ :rules="rules"
199
+ v-else-if="attr.showMode === 'radioGroup'"
200
+ :ref="attr.model"
201
+ :label="showLabel?attr.name:undefined"
202
+ :prop="attr.prop ? attr.prop : attr.model">
203
+ <a-radio-group v-model="form[attr.model]">
204
+ <a-radio-button v-for="modeItem in option" :key="modeItem.value" :value="modeItem.value">
205
+ {{ modeItem.label }}
206
+ </a-radio-button>
207
+ </a-radio-group>
208
+ </a-form-model-item>
209
+ <a-form-model-item
210
+ v-bind="bindOther"
211
+ v-else-if="attr.showMode === 'clickChange' && option.length > 0"
212
+ :ref="attr.model"
213
+ :label="showLabel?attr.name:undefined"
214
+ :prop="attr.prop ? attr.prop : attr.model">
215
+ <XClickChangeBtn></XClickChangeBtn>
216
+ </a-form-model-item>
217
+ </x-form-col>
218
+ <!-- 多选框 -->
219
+ <x-form-col
220
+ v-else-if="attr.type === 'checkbox' && show"
221
+ :labelCol="labelCol"
222
+ :flex="attr.flex">
223
+ <a-form-model-item
224
+ v-bind="bindOther"
225
+ :rules="rules"
226
+ v-if="!attr.showMode || mode === '查询' || attr.showMode === 'select' "
227
+ :ref="attr.model"
228
+ :label="showLabel?attr.name:undefined"
229
+ :prop="attr.prop ? attr.prop : attr.model">
230
+ <a-select
231
+ class="multiple_select"
232
+ style="width:100%"
233
+ v-if="!attr.lazyLoad || attr.lazyLoad === 'false'"
234
+ v-model="form[attr.model]"
235
+ :disabled="disabled"
236
+ :filter-option="filterOption"
237
+ :getPopupContainer="getPopupContainer"
238
+ :placeholder="attr.placeholder ? attr.placeholder : '请选择'"
239
+ @change="handleCheckboxChange"
240
+ :mode="mode=== '新增/修改' && attr.chooseForm === 'singleChoice' ? 'default' : 'multiple'"
241
+ show-search
242
+ allowClear
243
+ >
244
+ <template v-if="attr.keys">
245
+ <a-select-option
246
+ v-for="(item,index) in attr.keys"
247
+ :key="index"
248
+ :value="item.value + ''">
249
+ {{ item.label }}
250
+ </a-select-option>
251
+ </template>
252
+ <template v-else>
253
+ <template
254
+ v-if="attr.keyName.indexOf('logic@') !== -1 || attr.keyName.indexOf('config@') !== -1
255
+ ||attr.keyName.indexOf('search@') !== -1 || attr.keyName.indexOf('search@') !== -1">
256
+ <a-select-option
257
+ v-for="(item,index) in option"
258
+ :key="index"
259
+ :value="item.value">{{ item.label }}
260
+ </a-select-option>
261
+ </template>
262
+ <template v-else>
263
+ <a-select-option
264
+ v-for="item in $appdata.getDictionaryList(attr.keyName)"
265
+ :key="item.value"
266
+ :value="item.value + ''">{{ item.text }}
267
+ </a-select-option>
268
+ </template>
269
+ </template>
270
+ </a-select>
271
+ <a-select
272
+ v-else
273
+ class="multiple_select"
274
+ v-model="form[attr.model]"
275
+ :disabled="disabled"
276
+ :filter-option="filterOption"
277
+ :getPopupContainer="getPopupContainer"
278
+ :placeholder="attr.placeholder ? attr.placeholder : '搜索' + attr.name"
279
+ :mode="mode=== '新增/修改' && attr.chooseForm === 'singleChoice' ? 'default' : 'multiple'"
280
+ style="width:100%"
281
+ @change="handleCheckboxChange"
282
+ show-search
283
+ allowClear
284
+ @search="fetchFunction"
285
+ >
286
+ <template #notFoundContent>
287
+ <a-spin v-if="searching" size="small"/>
288
+ </template>
289
+ <a-select-option
290
+ v-for="(item,index) in option"
291
+ :key="index"
292
+ :value="item.value + ''">{{ item.label }}
293
+ </a-select-option>
294
+ </a-select>
295
+ </a-form-model-item>
296
+ <a-form-model-item
297
+ v-bind="bindOther"
298
+ :rules="rules"
299
+ v-else
300
+ :ref="attr.model"
301
+ :label="showLabel?attr.name:undefined"
302
+ :prop="attr.prop ? attr.prop : attr.model">
303
+ <a-checkbox-group
304
+ v-model="form[attr.model]"
305
+ :options="option"
306
+ @change="handleCheckboxChange"
307
+ />
308
+ </a-form-model-item>
309
+ </x-form-col>
310
+ <!-- 单选框 -->
311
+ <x-form-col
312
+ v-else-if="attr.type === 'radio' && show"
313
+ :labelCol="labelCol"
314
+ :flex="attr.flex">
315
+ <a-form-model-item
316
+ v-bind="bindOther"
317
+ :rules="rules"
318
+ v-if="!attr.showMode || attr.type === 'radio' "
319
+ :ref="attr.model"
320
+ :label="showLabel?attr.name:undefined"
321
+ :prop="attr.prop ? attr.prop : attr.model">
322
+ <a-radio-group
323
+ v-model="form[attr.model]"
324
+ @change="handleRadioChange"
325
+ >
326
+ <template v-if="attr.keys">
327
+ <a-radio v-for="(item,index) in attr.keys" :key="index" :value="item.value">
328
+ {{ item.label }}
329
+ </a-radio>
330
+ </template>
331
+ <template v-else>
332
+ <template
333
+ v-if="attr.keyName.indexOf('logic@') !== -1 || attr.keyName.indexOf('config@') !== -1
334
+ ||attr.keyName.indexOf('search@') !== -1 || attr.keyName.indexOf('search@') !== -1">
335
+ <a-radio v-for="(item,index) in option" :key="index" :value="item.value">
336
+ {{ item.label }}
337
+ </a-radio>
338
+ </template>
339
+ <template v-else>
340
+ <a-radio v-for="(item,index) in $appdata.getDictionaryList(attr.keyName)" :key="index" :value="item.value">
341
+ {{ item.text }}
342
+ </a-radio>
343
+ </template>
344
+ </template>
345
+ </a-radio-group>
346
+ </a-form-model-item>
347
+ <a-form-model-item
348
+ v-bind="bindOther"
349
+ :rules="rules"
350
+ v-else-if="attr.showMode === 'radioGroup'"
351
+ :ref="attr.model"
352
+ :label="showLabel?attr.name:undefined"
353
+ :prop="attr.prop ? attr.prop : attr.model">
354
+ <a-radio-group v-model="form[attr.model]">
355
+ <a-radio-button v-for="modeItem in option" :key="modeItem.value" :value="modeItem.value">
356
+ {{ modeItem.label }}
357
+ </a-radio-button>
358
+ </a-radio-group>
359
+ </a-form-model-item>
360
+ <a-form-model-item
361
+ v-bind="bindOther"
362
+ :rules="rules"
363
+ v-else-if="attr.showMode === 'clickChange' && option.length > 0"
364
+ :ref="attr.model"
365
+ :label="showLabel?attr.name:undefined"
366
+ :prop="attr.prop ? attr.prop : attr.model">
367
+ <XClickChangeBtn></XClickChangeBtn>
368
+ </a-form-model-item>
369
+ </x-form-col>
370
+ <!-- 时间 日期 框整合 -->
371
+ <x-form-col
372
+ v-else-if="['datePicker', 'rangePicker', 'yearPicker', 'monthPicker', 'yearRangePicker', 'monthRangePicker'].includes(attr.type) && show"
373
+ :labelCol="labelCol"
374
+ :flex="attr.flex">
375
+ <a-form-model-item
376
+ v-bind="bindOther"
377
+ :rules="rules"
378
+ :ref="attr.model"
379
+ :label="showLabel?attr.name:undefined"
380
+ :prop="attr.prop ? attr.prop : attr.model">
381
+ <XFormDatePicker
382
+ :attr="attr"
383
+ :mode="mode"
384
+ :enablePopupToBody="enablePopupToBody"
385
+ :getCalendarContainer="getPopupContainer"
386
+ :disabled="disabled"
387
+ :readOnly="readOnly"
388
+ :showLabel="showLabel"
389
+ @change="attr.dataChangeFunc && debouncedDataChangeFunc()"
390
+ v-model="form[attr.model]"/>
391
+ </a-form-model-item>
392
+ </x-form-col>
393
+ <!-- 文本域 -->
394
+ <x-form-col
395
+ v-else-if="attr.type === 'textarea' && show"
396
+ :labelCol="labelCol"
397
+ :flex="attr.flex">
398
+ <!-- :style="layout === 'inline'?{width:'calc(100% - 60px)'}:{}"-->
399
+ <a-form-model-item
400
+ v-bind="bindOther"
401
+ :rules="rules"
402
+ :ref="attr.model"
403
+ :label="showLabel?attr.name:undefined"
404
+ :prop="attr.prop ? attr.prop : attr.model">
405
+ <a-textarea
406
+ v-model="form[attr.model]"
407
+ style="width: 100%;"
408
+ :disabled="disabled"
409
+ :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
410
+ :rows="4"/>
411
+ </a-form-model-item>
412
+ </x-form-col>
413
+ <!-- 文件上传 -->
414
+ <x-form-col
415
+ v-else-if="(attr.type === 'file' || attr.type === 'image') && show"
416
+ :labelCol="labelCol"
417
+ :flex="attr.flex">
418
+ <a-form-model-item
419
+ v-bind="bindOther"
420
+ :rules="rules"
421
+ :ref="attr.model"
422
+ :label="showLabel?attr.name:undefined"
423
+ :prop="attr.prop ? attr.prop : attr.model">
424
+ <upload
425
+ :files="files"
426
+ :read-only="readOnly"
427
+ :images="images"
428
+ :model="attr"
429
+ v-bind="attr"
430
+ :service-name="serviceName"
431
+ @setFiles="setFiles"></upload>
432
+ </a-form-model-item>
433
+ </x-form-col>
434
+ <!-- 省市区选择框 -->
435
+ <x-form-col
436
+ v-else-if="attr.type === 'citySelect' && show"
437
+ :labelCol="labelCol"
438
+ :flex="attr.flex">
439
+ <a-form-model-item
440
+ v-bind="bindOther"
441
+ :rules="rules"
442
+ :ref="attr.model"
443
+ :label="showLabel?attr.name:undefined"
444
+ :prop="attr.prop ? attr.prop : attr.model">
445
+ <citySelect
446
+ @change="attr.dataChangeFunc && debouncedDataChangeFunc()"
447
+ ref="citySelect"
448
+ v-model="form[attr.model]"
449
+ :contexts="attr.contexts"
450
+ :value-type="attr.valueType"
451
+ :default-value="form[attr.model]"></citySelect>
452
+ </a-form-model-item>
453
+ </x-form-col>
454
+ <!-- 地点搜索框 -->
455
+ <x-form-col
456
+ v-else-if="(attr.type === 'addressSearch' || attr.type === 'coordinateSearch') && show"
457
+ :labelCol="labelCol"
458
+ :occupyCol="attr.occupyCol"
459
+ :flex="attr.flex">
460
+ <a-form-model-item
461
+ v-bind="bindOther"
462
+ :rules="rules"
463
+ :ref="attr.model"
464
+ :label="showLabel?attr.name:undefined"
465
+ :prop="attr.prop ? attr.prop : attr.model">
466
+ <address-search-combobox
467
+ :emitFunc="emitFunc"
468
+ :attr="attr"
469
+ :read-only="readOnly"
470
+ :searchResult="form[attr.model]"
471
+ :address="{ address: form[attr.model], coords: form[`${attr.model}_lng_lat`] }"
472
+ :resultKeys="{ address: attr.model, coords: `${attr.model}_lng_lat` }"
473
+ ref="addressSearchCombobox"
474
+ searchResultType="Object"
475
+ @onSelect="addressSearchComboboxSelect"
476
+ @onDivisionsChange="onDivisionsChange"
477
+ ></address-search-combobox>
478
+ </a-form-model-item>
479
+ </x-form-col>
480
+ <!-- 颜色选择器 -->
481
+ <x-form-col
482
+ v-else-if="attr.type === 'colorPicker' && show"
483
+ :labelCol="labelCol"
484
+ :flex="attr.flex">
485
+ <a-form-model-item
486
+ v-bind="bindOther"
487
+ :rules="rules"
488
+ :ref="attr.model"
489
+ :label="showLabel?attr.name:undefined"
490
+ :prop="attr.prop ? attr.prop : attr.model">
491
+ <color-picker-combobox
492
+ :value="form[attr.model]"
493
+ :read-only="readOnly"
494
+ @onSelect="colorPickerComboboxSelect"
495
+ />
496
+ </a-form-model-item>
497
+ </x-form-col>
498
+ <!-- 人员选择框 -->
499
+ <x-form-col
500
+ v-else-if="attr.type === 'personSetting' && show"
501
+ :labelCol="labelCol"
502
+ :flex="attr.flex">
503
+ <a-form-model-item
504
+ v-bind="bindOther"
505
+ :rules="rules"
506
+ :ref="attr.model"
507
+ :label="showLabel?attr.name:undefined"
508
+ :prop="attr.prop ? attr.prop : attr.model">
509
+ <PersonSetting v-model="form[attr.model]"></PersonSetting>
510
+ </a-form-model-item>
511
+ </x-form-col>
512
+ <!-- 树形选择框 -->
513
+ <x-form-col
514
+ v-else-if="attr.type === 'treeSelect' && show"
515
+ :labelCol="labelCol"
516
+ :flex="attr.flex">
517
+ <x-tree-select
518
+ :rules="rules"
519
+ @onChange="handleTreeSelectChange"
520
+ v-model="form[attr.model]"
521
+ :attr="attr"
522
+ @mounted="itemMounted"
523
+ ref="xTreeSelect">
524
+ </x-tree-select>
525
+ </x-form-col>
526
+ <!-- 列表选择框 -->
527
+ <x-form-col
528
+ v-else-if="attr.type === 'listSelect' && show"
529
+ :labelCol="labelCol"
530
+ :flex="attr.flex">
531
+ <a-form-model-item
532
+ v-bind="bindOther"
533
+ :rules="rules"
534
+ :ref="attr.model"
535
+ :label="showLabel?attr.name:undefined"
536
+ :style="layout === 'inline'&& attr.occupyCol && attr.occupyCol > 1? {width:`calc(100% - ${attr.occupyCol * 1.533}rem)`}:{}"
537
+ :prop="attr.prop ? attr.prop : attr.model">
538
+ <a-popover
539
+ ref="rowChoosePopover"
540
+ :visible="rowChoosePopoverVisible"
541
+ title="选择数据"
542
+ placement="bottom"
543
+ trigger="focus"
544
+ :arrowPointAtCenter="true"
545
+ :overlayStyle="{ width: '1000px', height: '30vh' }">
546
+ <template #content>
547
+ <x-report
548
+ v-if="isCover"
549
+ :use-oss-for-img="false"
550
+ :config-name="queryParamsName"
551
+ :service-name="serviceName"
552
+ :show-img-in-cell="true"
553
+ :display-only="true"
554
+ :edit-mode="false"
555
+ :show-save-button="true"
556
+ :no-padding="true"
557
+ :dont-format="true"
558
+ @rowChoose="rowChoose"
559
+ @cancel="closeRowChooseInput"
560
+ >
561
+ </x-report>
562
+ <x-form-table
563
+ v-else
564
+ title="请选择数据"
565
+ :queryParamsName="queryParamsName"
566
+ :rowSelectMode="true"
567
+ :allowSelectRowNum="1"
568
+ :service-name="serviceName"
569
+ :fixed-query-form="rowChooseFixedQueryValue"
570
+ @rowChoose="rowChoose"
571
+ @afterQuery="rowChooseSearchAfterQuery"
572
+ ref="rowChooseTable">
573
+ <template #button>
574
+ <a-button @click="closeRowChooseInput">
575
+ 关闭
576
+ </a-button>
577
+ </template>
578
+ </x-form-table>
579
+ </template>
580
+ <a-input
581
+ v-model="form[attr.model]"
582
+ :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
583
+ @change="searchRowChooseData"
584
+ @focus="showCloseRowChooseInput"/>
585
+ </a-popover>
586
+ </a-form-model-item>
587
+ </x-form-col>
588
+ <!-- 评分框 -->
589
+ <x-form-col
590
+ v-else-if="attr.type === 'rate' && show"
591
+ :labelCol="labelCol"
592
+ :flex="attr.flex">
593
+ <a-form-model-item
594
+ v-bind="bindOther"
595
+ :rules="rules"
596
+ :ref="attr.model"
597
+ :label="showLabel?attr.name:undefined"
598
+ :prop="attr.prop ? attr.prop : attr.model">
599
+ <x-rate
600
+ v-model="form[attr.model]"
601
+ :mode="mode"
602
+ :disabled="disabled"
603
+ :query-type="attr.queryType"
604
+ :display-count="attr.displayCount"
605
+ :max-count="attr.maxCount"
606
+ :allow-half="attr.allowHalf"
607
+ :icon="attr.rateIcon"
608
+ :placeholder="attr.placeholder ? attr.placeholder : '请选择'+attr.name.replace(/\s*/g, '')"
609
+ @change="attr.dataChangeFunc && debouncedDataChangeFunc()"
610
+ />
611
+ </a-form-model-item>
612
+ </x-form-col>
613
+ <!-- 区间选择器 -->
614
+ <x-form-col
615
+ v-else-if="attr.type === 'intervalPicker' && show"
616
+ :labelCol="labelCol"
617
+ :flex="attr.flex">
618
+ <a-form-model-item
619
+ v-bind="bindOther"
620
+ :rules="rules"
621
+ :ref="attr.model"
622
+ :label="showLabel?attr.name:undefined"
623
+ :prop="attr.prop ? attr.prop : attr.model">
624
+ <x-interval-picker
625
+ v-model="form[attr.model]"
626
+ :mode="mode"
627
+ :read-only="readOnly"
628
+ :disabled="disabled && !readOnly"
629
+ :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
630
+ :start-placeholder="attr.startPlaceholder || '起始值'"
631
+ :end-placeholder="attr.endPlaceholder || '结束值'"
632
+ @blur="attr.inputOnBlurFunc && emitFunc(attr.inputOnBlurFunc,attr)"
633
+ />
634
+ </a-form-model-item>
635
+ </x-form-col>
636
+ <!-- 车牌号选择 -->
637
+ <x-form-col
638
+ v-else-if="attr.type === 'licensePlate' && show"
639
+ :labelCol="labelCol"
640
+ :flex="attr.flex">
641
+ <a-form-model-item
642
+ v-bind="bindOther"
643
+ :rules="rules"
644
+ :ref="attr.model"
645
+ :label="showLabel?attr.name:undefined"
646
+ :style="layout === 'inline'&& attr.occupyCol && attr.occupyCol > 1? {width:`calc(100% - ${attr.occupyCol * 1.533}rem)`}:{}"
647
+ :prop="attr.prop ? attr.prop : attr.model">
648
+ <!-- 如果配置了后置按钮插槽 -->
649
+ <a-input
650
+ v-if="mode ==='查询'"
651
+ v-model="form[attr.model]"
652
+ :whitespace="true"
653
+ :read-only="readOnly"
654
+ :disabled="disabled && !readOnly"
655
+ style="width:100%"
656
+ @blur="attr.inputOnBlurFunc && emitFunc(attr.inputOnBlurFunc,attr)"
657
+ :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
658
+ :ref="`${attr.model}input`"/>
659
+ <x-license-plate
660
+ v-else
661
+ v-model="form[attr.model]"
662
+ @change="attr.dataChangeFunc && debouncedDataChangeFunc()"
663
+ ></x-license-plate>
664
+ </a-form-model-item>
665
+ </x-form-col>
666
+ <!-- 录音 -->
667
+ <x-form-col
668
+ v-else-if="attr.type === 'recording' && show"
669
+ :labelCol="labelCol"
670
+ :flex="attr.flex">
671
+ <recording
672
+ ref="recording"
673
+ @recordingData="recordingData"
674
+ >
675
+ </recording>
676
+ </x-form-col>
677
+ <!-- 表格录入 -->
678
+ <x-form-col
679
+ v-else-if="attr.type === 'rowEdit' && show"
680
+ :labelCol="labelCol"
681
+ :flex="attr.flex">
682
+ <a-form-model-item
683
+ v-bind="bindOther"
684
+ :rules="rules"
685
+ :ref="attr.model"
686
+ :label="showLabel?attr.name:undefined"
687
+ :prop="attr.prop ? attr.prop : attr.model">
688
+ <x-form-table
689
+ :key="'childTable_' + attr.model"
690
+ :title="attr.name"
691
+ :queryParamsName="attr.crud"
692
+ :localEditMode="true"
693
+ :fixed-query-form="childTableFixedQueryForm(attr)"
694
+ :service-name="serviceName"
695
+ @hook:mounted="(h)=>onComponentMounted(h, attr)"
696
+ :ref="'childXFormTable_' + attr.model">
697
+ </x-form-table>
698
+ </a-form-model-item>
699
+ </x-form-col>
700
+ </template>
701
+ <script>
702
+ import { debounce } from 'ant-design-vue/lib/vc-table/src/utils'
703
+ import XFormCol from '@vue2-client/base-client/components/common/XFormCol'
704
+ import XBadge from '@vue2-client/base-client/components/common/XBadge'
705
+ import CitySelect from '@vue2-client/base-client/components/common/CitySelect'
706
+ import PersonSetting from '@vue2-client/base-client/components/common/PersonSetting'
707
+ import AddressSearchCombobox from '@vue2-client/base-client/components/common/AddressSearchCombobox'
708
+ import Upload from '@vue2-client/base-client/components/common/Upload'
709
+ import moment from 'moment'
710
+ import { getConfigByName, runLogic, getConfigByNameAsync } from '@vue2-client/services/api/common'
711
+ import * as util from '@vue2-client/utils/util'
712
+ import XTreeSelect from '@vue2-client/base-client/components/common/XForm/XTreeSelect'
713
+ import { searchToListOption, searchToOption } from '@vue2-client/services/v3Api'
714
+ import { mapState } from 'vuex'
715
+ import { executeStrFunctionByContext } from '@vue2-client/utils/runEvalFunction'
716
+ import XLicensePlate from '@vue2-client/base-client/components/common/XLicensePlate/XLicensePlate.vue'
717
+ import XStatusButton from './XStatusButton.vue'
718
+ import XClickChangeBtn from './itemComponent/XClickChangeBtn'
719
+ import 'moment/locale/zh-cn'
720
+ import XFormDatePicker from '@vue2-client/base-client/components/common/XDatePicker/index.vue'
721
+ import XIntervalPicker from '@vue2-client/base-client/components/common/XIntervalPicker/XIntervalPicker.vue'
722
+ import XRate from '@vue2-client/base-client/components/common/XRate/index.vue'
723
+ import { post } from '@vue2-client/services/api/restTools'
724
+ import ColorPickerCombobox from '@vue2-client/base-client/components/common/ColorPickerCombobox/ColorPickerCombobox.vue'
725
+ import { createSelectValueTypeHandler } from '@vue2-client/base-client/plugins/selectValueTypeHelper'
726
+
727
+ export default {
728
+ name: 'XFormItem',
729
+ components: {
730
+ XFormDatePicker,
731
+ XFormTable: () => import('@vue2-client/base-client/components/common/XFormTable/XFormTable.vue'),
732
+ Recording: () => import('@vue2-client/base-client/components/common/Recording/Recording.vue'),
733
+ XReport: () => import('@vue2-client/base-client/components/common/XReportGrid/XReport.vue'),
734
+ XLicensePlate,
735
+ XTreeSelect,
736
+ XFormCol,
737
+ XBadge,
738
+ CitySelect,
739
+ PersonSetting,
740
+ AddressSearchCombobox,
741
+ Upload,
742
+ XStatusButton,
743
+ XClickChangeBtn,
744
+ XIntervalPicker,
745
+ XRate,
746
+ ColorPickerCombobox
747
+ },
748
+ data () {
749
+ // 检索去抖
750
+ this.fetchFunction = debounce(this.fetchFunction, 800)
751
+ // 初始化selectValueType处理器
752
+ this.selectValueTypeHandler = createSelectValueTypeHandler(this)
753
+ return {
754
+ option: [],
755
+ // 最后检索版本
756
+ lastFetchId: 0,
757
+ // 检索中
758
+ searching: false,
759
+ searchResult: '',
760
+ optionForFunc: [],
761
+ // 控制当前表单项是否展示
762
+ show: true,
763
+ // moment
764
+ moment,
765
+ // 行选择器浮层是否显示
766
+ rowChoosePopoverVisible: false,
767
+ // 行选择器CRUD固定查询值
768
+ rowChooseFixedQueryValue: undefined,
769
+ bindOther: {}
770
+ }
771
+ },
772
+ props: {
773
+ attr: {
774
+ type: Object,
775
+ default:
776
+ () => {
777
+ return {}
778
+ }
779
+ },
780
+ form: {
781
+ type: Object,
782
+ required:
783
+ true
784
+ },
785
+ disabled: {
786
+ type: Boolean,
787
+ default:
788
+ () => {
789
+ return false
790
+ }
791
+ },
792
+ readOnly: {
793
+ type: Boolean,
794
+ default:
795
+ () => {
796
+ return false
797
+ }
798
+ },
799
+ mode: {
800
+ type: String,
801
+ default:
802
+ () => {
803
+ return '查询'
804
+ }
805
+ },
806
+ files: {
807
+ type: Array,
808
+ default:
809
+ () => {
810
+ return []
811
+ }
812
+ },
813
+ images: {
814
+ type: Array,
815
+ default:
816
+ () => {
817
+ return []
818
+ }
819
+ },
820
+ // 是否启用时间弹出到最外层
821
+ enablePopupToBody: {
822
+ type: Boolean,
823
+ default: false
824
+ },
825
+ serviceName: {
826
+ type: String,
827
+ default:
828
+ undefined
829
+ },
830
+ // 调用logic获取数据源的追加参数
831
+ getDataParams: {
832
+ type: Object,
833
+ default:
834
+ undefined
835
+ },
836
+ // 布局
837
+ layout: {
838
+ type: String,
839
+ default:
840
+ 'horizontal'
841
+ },
842
+ // 环境
843
+ env: {
844
+ type: String,
845
+ default:
846
+ () => {
847
+ return 'prod'
848
+ }
849
+ },
850
+ // 设置表单值
851
+ setForm: {
852
+ type: Function,
853
+ default: (val) => {
854
+ console.log(val)
855
+ }
856
+ },
857
+ showLabel: {
858
+ type: Boolean,
859
+ default:
860
+ () => {
861
+ return true
862
+ }
863
+ },
864
+ labelCol: {
865
+ type: Object,
866
+ default: () => {
867
+ return { span: 8 }
868
+ }
869
+ },
870
+ rules: {
871
+ type: Array,
872
+ default:
873
+ () => {
874
+ return undefined
875
+ }
876
+ }
877
+ },
878
+ provide () {
879
+ return {
880
+ FormItemContext: this
881
+ }
882
+ },
883
+ created () {
884
+ this.init()
885
+ if (this.attr.keyName && (this.attr?.keyName?.toString().indexOf('async ') !== -1 || this.attr?.keyName?.toString()?.indexOf('function') !== -1)) {
886
+ this.debouncedUpdateOptions = debounce(this.updateOptions, 200)
887
+ }
888
+ if (this.attr.dataChangeFunc) {
889
+ this.debouncedDataChangeFunc = debounce(this.dataChangeFunc, 200)
890
+ // 执行一次
891
+ this.dataChangeFunc()
892
+ }
893
+ if (this.attr.showFormItemFunc) {
894
+ this.debouncedShowFormItemFunc = debounce(this.showFormItemFunc, 100)
895
+ // 执行一次
896
+ this.showFormItemFunc()
897
+ }
898
+ if (this.attr.showQueryFormItemFunc) {
899
+ this.debouncedShowQueryFormItemFunc = debounce(this.showQueryFormItemFunc, 100)
900
+ // 执行一次
901
+ this.showQueryFormItemFunc()
902
+ }
903
+ // 人员联动框增加监听
904
+ if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString().endsWith(']联动人员')) {
905
+ this.debouncedUserLinkFunc = debounce(() => this.updateResOptions('人员'), 200)
906
+ }
907
+ if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString().endsWith(']联动部门')) {
908
+ this.debouncedDepLinkFunc = debounce(() => this.updateResOptions('部门'), 200)
909
+ }
910
+ // xTreeSelect 自己调用 mounted
911
+ if (this.attr.type !== 'treeSelect') {
912
+ this.$emit('mounted', this.attr)
913
+ }
914
+ },
915
+ computed: {
916
+ ...mapState('account', { currUser: 'user', curRoles: 'roles', curPermissions: 'permissions' }),
917
+ queryParamsName () {
918
+ if (this.attr.keyName.startsWith('function')) {
919
+ // 调用异步函数获取内容
920
+ const obj = executeStrFunctionByContext(this, this.attr.keyName, [this.form, runLogic, this.mode, getConfigByNameAsync])
921
+ // 处理同步返回值
922
+ return this.handleQueryParamsResult(obj)
923
+ } else if (this.attr.keyName.startsWith('async ')) {
924
+ console.warn('此处不支持异步操作')
925
+ return ''
926
+ } else {
927
+ // 按现有方式处理
928
+ return this.attr.keyName.split('@')[this.attr.keyName.split('@').length - 1]
929
+ }
930
+ },
931
+ // 判断弹出时是否Cover,弹出只支持Cover以及CRUD
932
+ isCover () {
933
+ // 如果 queryParamsName 为空,返回空
934
+ if (!this.queryParamsName) {
935
+ return false
936
+ }
937
+ const result = this.queryParamsName.endsWith('Cover')
938
+ return result
939
+ },
940
+ },
941
+ watch: {
942
+ attr: {
943
+ handler () {
944
+ this.init()
945
+ },
946
+ deep: true
947
+ },
948
+ form: {
949
+ handler (newVal, oldVal) {
950
+ // 如果是从函数获取 options
951
+ if (this.attr.keyName && (this.attr.keyName.toString().indexOf('async ') !== -1 || this.attr.keyName.toString().indexOf('function') !== -1)) {
952
+ this.debouncedUpdateOptions()
953
+ }
954
+ // 如果有自定义是否展示表单项函数
955
+ if (this.attr.showFormItemFunc) {
956
+ this.debouncedShowFormItemFunc()
957
+ }
958
+ // 如果有自定义是否展示查询表单项函数
959
+ if (this.attr.showQueryFormItemFunc) {
960
+ this.debouncedShowQueryFormItemFunc()
961
+ }
962
+ // 地址搜索框赋值
963
+ if (this.attr.type === 'addressSearch' || this.attr.type === 'coordinateSearch') {
964
+ this.$refs.addressSearchCombobox.addressInput = this.form[this.attr.model]
965
+ }
966
+ // 数据源来自人员联动时更新数据
967
+ if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString().endsWith(']联动人员')) {
968
+ this.debouncedUserLinkFunc()
969
+ }
970
+ // 数据源来自人员联动时更新数据
971
+ if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString().endsWith(']联动部门')) {
972
+ this.debouncedDepLinkFunc()
973
+ }
974
+ },
975
+ deep: true
976
+ }
977
+ },
978
+ inject: {
979
+ getComponentByName: {
980
+ default: () => () => {
981
+ console.warn('getComponentByName is not provided')
982
+ return null // 或者返回一个默认的函数
983
+ },
984
+ },
985
+ registerComponent: {
986
+ default: () => () => {
987
+ console.warn('registerComponent is not provided')
988
+ return null // 或者返回一个默认的函数
989
+ },
990
+ },
991
+ getSelf: {
992
+ default: () => () => {
993
+ console.warn('getSelf is not provided')
994
+ return null // 或者返回一个默认的函数
995
+ },
996
+ },
997
+ XFormContext: {
998
+ default: () => () => {
999
+ console.warn('XFormContext is not provided')
1000
+ return null // 或者返回一个默认的函数
1001
+ },
1002
+ },
1003
+ setRequired: {
1004
+ default: () => () => {
1005
+ console.warn('setRequired is not provided')
1006
+ return null // 或者返回一个默认的函数
1007
+ },
1008
+ },
1009
+ removeRequired: {
1010
+ default: () => () => {
1011
+ console.warn('removeRequired is not provided')
1012
+ return null // 或者返回一个默认的函数
1013
+ },
1014
+ }
1015
+ },
1016
+ methods: {
1017
+ // 处理 queryParams 结果并更新 rowChooseFixedQueryValue
1018
+ handleQueryParamsResult (obj) {
1019
+ let configName = ''
1020
+ if (obj && typeof obj === 'object') {
1021
+ // obj 是一个对象,并且不是数组
1022
+ if (Object.prototype.hasOwnProperty.call(obj, 'configName')) {
1023
+ configName = obj?.configName
1024
+ }
1025
+ if (Object.prototype.hasOwnProperty.call(obj, 'fixedQueryForm')) {
1026
+ if (obj?.fixedQueryForm && typeof obj?.fixedQueryForm === 'object') {
1027
+ this.rowChooseFixedQueryValue = Object.assign({}, this.rowChooseFixedQueryValue, obj.fixedQueryForm)
1028
+ }
1029
+ }
1030
+ } else if (obj && typeof obj === 'string') {
1031
+ configName = obj
1032
+ }
1033
+ return configName
1034
+ },
1035
+ // 根据selectValueType预处理options数据
1036
+ processOptionsForValueType (options) {
1037
+ return this.selectValueTypeHandler.processOptions(options, this.attr.selectValueType)
1038
+ },
1039
+
1040
+ // 处理both模式的数据,为表单添加label字段
1041
+ processBothModeData () {
1042
+ this.selectValueTypeHandler.processBothMode(
1043
+ this.form,
1044
+ this.attr.model,
1045
+ this.attr.selectValueType,
1046
+ this.option
1047
+ )
1048
+ },
1049
+
1050
+ // 根据value查找对应的label(支持单选和多选)
1051
+ findLabelByValue (value) {
1052
+ return this.selectValueTypeHandler.findLabel(value, this.option)
1053
+ },
1054
+
1055
+ // 统一的表单项change处理逻辑
1056
+ handleFormItemChange () {
1057
+ // 处理both模式
1058
+ if (this.attr.selectValueType === 'both') {
1059
+ this.$nextTick(() => {
1060
+ this.selectValueTypeHandler.processBothMode(
1061
+ this.form,
1062
+ this.attr.model,
1063
+ this.form[this.attr.model],
1064
+ this.option
1065
+ )
1066
+ })
1067
+ }
1068
+ // 处理label模式
1069
+ if (this.attr.selectValueType === 'label') {
1070
+ this.$nextTick(() => {
1071
+ this.selectValueTypeHandler.processLabelMode(
1072
+ this.form,
1073
+ this.attr.model,
1074
+ this.form[this.attr.model],
1075
+ this.option
1076
+ )
1077
+ })
1078
+ }
1079
+ // 处理原有的dataChangeFunc
1080
+ if (this.attr.dataChangeFunc) {
1081
+ this.debouncedDataChangeFunc()
1082
+ }
1083
+ },
1084
+
1085
+ // Select组件change处理
1086
+ handleSelectChange () {
1087
+ this.handleFormItemChange()
1088
+ },
1089
+
1090
+ // Checkbox组件change处理
1091
+ handleCheckboxChange () {
1092
+ this.handleFormItemChange()
1093
+ },
1094
+
1095
+ // Radio组件change处理
1096
+ handleRadioChange () {
1097
+ this.handleFormItemChange()
1098
+ },
1099
+
1100
+ // TreeSelect组件change处理(通过XTreeSelect组件回调)
1101
+ handleTreeSelectChange () {
1102
+ this.handleFormItemChange()
1103
+ },
1104
+
1105
+ // 把内部的crud表单录入放到表单中,以便外部可以调用
1106
+ onComponentMounted (h, attr) {
1107
+ console.log('crud表单', h)
1108
+ if (attr.crud) {
1109
+ this.registerComponent(attr.model, this.$refs['childXFormTable_' + attr.model])
1110
+ }
1111
+ },
1112
+ childTableFixedQueryForm (item) {
1113
+ console.log('传递的form', this.form)
1114
+ if (this.modifyModelData?.primaryKeyData) {
1115
+ const fixedForm = {}
1116
+ fixedForm[item.childTableForeignKeyName] = Object.values(this.modifyModelData.primaryKeyData)[0]
1117
+ return fixedForm
1118
+ }
1119
+ return null
1120
+ },
1121
+ // 动态生成事件绑定对象
1122
+ generateDynamicEvents (inputOnAfterFunc, attr) {
1123
+ const events = {}
1124
+ const states = this.parseStates(attr.inputOnAfterName, inputOnAfterFunc)
1125
+
1126
+ states.forEach((state) => {
1127
+ // 动态绑定事件名到 emitFunc
1128
+ events[state.event] = () => {
1129
+ console.info('事件名', state.event)
1130
+ this.emitFunc(state.event, attr)
1131
+ }
1132
+ })
1133
+
1134
+ return events // 返回 { state1Event: handler, state2Event: handler, ... }
1135
+ },
1136
+ parseStates (input, events) {
1137
+ const eventNames = events.split('|')
1138
+ return input.split('|').map((label, index) => ({
1139
+ label,
1140
+ event: eventNames[index] // 如果没有提供事件名称,则使用默认值
1141
+ }))
1142
+ },
1143
+ focusInput () {
1144
+ if (this.attr.defaultFocus) {
1145
+ this.$nextTick(h => {
1146
+ const el = this.$refs[`${this.attr.model}input`]?.$el
1147
+ let inputEl
1148
+ if (el) {
1149
+ if (el.tagName.toLowerCase() === 'input') {
1150
+ inputEl = el
1151
+ } else {
1152
+ inputEl = el.querySelector('input')
1153
+ }
1154
+ }
1155
+ if (inputEl) {
1156
+ inputEl.focus()
1157
+ if (inputEl.type === 'number') {
1158
+ if (inputEl.valueAsNumber) {
1159
+ inputEl.setSelectionRange(0, inputEl.valueAsNumber.toString().length)
1160
+ }
1161
+ } else {
1162
+ if (inputEl.value) {
1163
+ inputEl.setSelectionRange(0, inputEl.value.length)
1164
+ }
1165
+ }
1166
+ }
1167
+ })
1168
+ }
1169
+ },
1170
+ // 更新人员下拉框数据
1171
+ async updateResOptions (type) {
1172
+ if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString()?.endsWith(`]联动${type}`)) {
1173
+ const startIndex = this.attr.keyName.indexOf('[') + 1
1174
+ const endIndex = this.attr.keyName.indexOf(']', startIndex)
1175
+ const fromModel = this.attr.keyName.substring(startIndex, endIndex).replace('.', '_')
1176
+ // 获取表单字段的实际值(优先使用originData中的原始值)
1177
+ const rawFieldValue = this.form.originData && this.form.originData[fromModel]
1178
+ ? this.form.originData[fromModel]
1179
+ : this.form[fromModel]
1180
+
1181
+ // 确保数据为数组格式(用于filter参数)
1182
+ const filterValues = Array.isArray(rawFieldValue)
1183
+ ? rawFieldValue
1184
+ : [rawFieldValue]
1185
+ if (fromModel?.length && filterValues?.length) {
1186
+ const searchData = {
1187
+ source: `获取${type}`,
1188
+ userid: this.currUser.id,
1189
+ filter: filterValues,
1190
+ filterType: fromModel.indexOf('org') > -1 ? 'org' : 'dep'
1191
+ }
1192
+ const tempArray = []
1193
+ await searchToListOption(searchData, res => {
1194
+ this.getDataCallback(
1195
+ res.filter(h => {
1196
+ if (fromModel.indexOf('org') > -1) {
1197
+ if (type === '部门') {
1198
+ if (filterValues?.includes(h.orgid || h.f_organization_id) || filterValues?.includes(h.parentid) || tempArray.includes(h.parentid)) {
1199
+ tempArray.push(h.value)
1200
+ return true
1201
+ }
1202
+ return false
1203
+ } else {
1204
+ return filterValues?.includes(h.orgid || h.f_organization_id || h.parentid)
1205
+ }
1206
+ } else {
1207
+ return filterValues?.includes(h?.parentid)
1208
+ }
1209
+ }
1210
+ )
1211
+ )
1212
+ })
1213
+ }
1214
+ }
1215
+ },
1216
+ // js 函数作为数据源
1217
+ async updateOptions () {
1218
+ if (this.attr.keyName && (this.attr.keyName.indexOf('async ') !== -1 || this.attr.keyName.indexOf('function ') !== -1)) {
1219
+ const rawOptions = await executeStrFunctionByContext(this, this.attr.keyName, [this.form, runLogic, this.mode, getConfigByNameAsync, post])
1220
+ // 根据selectValueType预处理options数据
1221
+ this.optionForFunc = this.processOptionsForValueType(rawOptions)
1222
+ }
1223
+ },
1224
+ async dataChangeFunc () {
1225
+ if (this.attr.dataChangeFunc) {
1226
+ await executeStrFunctionByContext(this, this.attr.dataChangeFunc, [this.form, this.setForm, this.attr, util, this.mode, runLogic, getConfigByNameAsync])
1227
+ }
1228
+ },
1229
+ async showFormItemFunc () {
1230
+ if (this.attr.showFormItemFunc) {
1231
+ const obj = executeStrFunctionByContext(this, this.attr.showFormItemFunc, [this.form, this.setForm, this.attr, util, this.mode, this.curPermissions, this.curRoles])
1232
+ // 判断是 bool 还是 obj 兼容
1233
+ if (typeof obj === 'boolean') {
1234
+ this.show = obj
1235
+ } else if (obj && typeof obj === 'object') {
1236
+ // obj 是一个对象,并且不是数组
1237
+ if (Object.prototype.hasOwnProperty.call(obj, 'show')) {
1238
+ this.show = obj?.show
1239
+ }
1240
+ if (Object.prototype.hasOwnProperty.call(obj, 'readOnly')) {
1241
+ this.readOnly = obj?.readOnly
1242
+ }
1243
+ if (Object.prototype.hasOwnProperty.call(obj, 'disabled')) {
1244
+ this.disabled = obj?.disabled
1245
+ }
1246
+ }
1247
+ } else {
1248
+ this.show = true
1249
+ }
1250
+ },
1251
+ async showQueryFormItemFunc () {
1252
+ if (this.attr.showQueryFormItemFunc) {
1253
+ const obj = executeStrFunctionByContext(this, this.attr.showQueryFormItemFunc, [this.form, this.setForm, this.attr, util, this.mode, this.curPermissions, this.curRoles])
1254
+ // 判断是 bool 还是 obj 兼容
1255
+ if (typeof obj === 'boolean') {
1256
+ this.show = obj
1257
+ } else if (obj && typeof obj === 'object') {
1258
+ // obj 是一个对象,并且不是数组
1259
+ if (Object.prototype.hasOwnProperty.call(obj, 'show')) {
1260
+ this.show = obj?.show
1261
+ }
1262
+ if (Object.prototype.hasOwnProperty.call(obj, 'readOnly')) {
1263
+ this.readOnly = obj?.readOnly
1264
+ }
1265
+ if (Object.prototype.hasOwnProperty.call(obj, 'disabled')) {
1266
+ this.disabled = obj?.disabled
1267
+ }
1268
+ }
1269
+ } else {
1270
+ this.show = true
1271
+ }
1272
+ },
1273
+ init () {
1274
+ if (!this.attr.flex) {
1275
+ if (this.mode === '新增/修改') {
1276
+ if (['horizontal', 'vertical'].includes(this.layout) || ['textarea', 'file', 'image'].includes(this.attr.type)) {
1277
+ // 新增修改表单 horizontal 模式下默认为一行
1278
+ this.attr.flex = {
1279
+ xs: 24,
1280
+ sm: 24,
1281
+ md: 24,
1282
+ lg: 24,
1283
+ xl: 24,
1284
+ xxl: 24,
1285
+ fullWidth: true
1286
+ }
1287
+ } else {
1288
+ // 新增修改表单 vertical 模式下默认为1列
1289
+ this.attr.flex = {
1290
+ xs: 24,
1291
+ sm: 12,
1292
+ md: 8,
1293
+ lg: 8,
1294
+ xl: 6,
1295
+ xxl: 6
1296
+ }
1297
+ }
1298
+ } else {
1299
+ this.attr.flex = {
1300
+ xs: 24,
1301
+ sm: 24,
1302
+ md: 8,
1303
+ lg: 6,
1304
+ xl: 6,
1305
+ xxl: 6
1306
+ }
1307
+ }
1308
+ }
1309
+ if (this.attr.keyName && typeof this.attr.keyName === 'string') {
1310
+ if (this.attr.keyName.indexOf('logic@') !== -1) {
1311
+ this.getData({}, res => this.getDataCallback(res))
1312
+ } else if (this.attr.keyName.indexOf('search@') !== -1) {
1313
+ // `tool.getFullTree(this.getRights().where(row.getType()==$organization$))`
1314
+ // 判断是否根据角色查询
1315
+ let source = this.attr.keyName.substring(7)
1316
+ const userid = this.currUser.id
1317
+ let roleName = 'roleName'
1318
+ if (source.startsWith('根据角色[') && source.endsWith(']获取人员')) {
1319
+ const startIndex = source.indexOf('[') + 1
1320
+ const endIndex = source.indexOf(']', startIndex)
1321
+ roleName = source.substring(startIndex, endIndex)
1322
+ source = '根据角色获取人员'
1323
+ }
1324
+ const searchData = { source, userid, roleName }
1325
+ // 判断是否根据某个表单项联动 仅返回列表结构并筛选
1326
+ if (source.startsWith('根据表单项[') && source.endsWith(']联动人员')) {
1327
+ this.updateResOptions('人员')
1328
+ } else if (source.startsWith('根据表单项[') && source.endsWith(']联动部门')) {
1329
+ this.updateResOptions('部门')
1330
+ } else if (this.attr.type === 'select' || this.attr.type === 'checkbox') {
1331
+ // 仅获取最内层数据
1332
+ searchToListOption(searchData, res => this.getDataCallback(res))
1333
+ } else {
1334
+ // 其他资源通用逻辑
1335
+ searchToOption(searchData, res => this.getDataCallback(res))
1336
+ }
1337
+ } else if (this.attr.keyName.indexOf('config@') !== -1) {
1338
+ const configName = this.attr.keyName.substring(7)
1339
+ getConfigByName(configName, this.serviceName, res => {
1340
+ this.getDataCallback(res.value)
1341
+ }, this.env === 'dev')
1342
+ } else if (this.attr.keyName.indexOf('async ') !== -1 || this.attr.keyName.indexOf('function ') !== -1) {
1343
+ this.updateOptions()
1344
+ }
1345
+ } else if (this.attr.keys) {
1346
+ // 对静态配置的keys也进行预处理
1347
+ this.getDataCallback(this.attr.keys)
1348
+ }
1349
+ this.focusInput()
1350
+ },
1351
+ addressSearchComboboxSelect (data) {
1352
+ this.form = Object.assign(this.form, JSON.parse(data))
1353
+ },
1354
+ onDivisionsChange (data) {
1355
+ this.emitFunc('addressSearchComboboxSelect', {
1356
+ key: this.attr.model,
1357
+ value: data
1358
+ })
1359
+ },
1360
+ getDataCallback (res) {
1361
+ // 根据selectValueType预处理options数据
1362
+ this.option = this.processOptionsForValueType(res)
1363
+
1364
+ if (this.attr.type === 'treeSelect') {
1365
+ this.$nextTick(() => {
1366
+ this.$refs.xTreeSelect.init({
1367
+ option: this.option,
1368
+ form: this.form,
1369
+ queryType: this.attr.queryType,
1370
+ name: this.attr.name,
1371
+ model: this.attr.model,
1372
+ mode: this.mode,
1373
+ disabled: this.disabled
1374
+ })
1375
+ })
1376
+ } else if (this.attr.type === 'radio' || ['radioGroup', 'clickChange'].includes(this.attr.showMode)) {
1377
+ this.initRadioValue()
1378
+ }
1379
+ },
1380
+ initRadioValue () {
1381
+ const model = this.attr.model
1382
+ if (this.mode === '新增/修改' && (this.form[model] === undefined || this.form[model] === null) && !this.attr.prop) {
1383
+ if (this.attr.keys && this.attr.keys.length > 1) {
1384
+ this.form[model] = this.attr.keys[0].value
1385
+ } else if (this.option.length > 1) {
1386
+ this.form[model] = this.option[0].value
1387
+ }
1388
+ }
1389
+ },
1390
+ // 文件框时设置上传组件的值
1391
+ setFiles (fileIds) {
1392
+ if (!this.form[this.attr.model]) {
1393
+ this.form[this.attr.model] = []
1394
+ }
1395
+ this.form[this.attr.model] = [...fileIds]
1396
+ },
1397
+ // 懒加载检索方法
1398
+ fetchFunction (value) {
1399
+ this.lastFetchId += 1
1400
+ const fetchId = this.lastFetchId
1401
+ this.option = []
1402
+ this.searching = true
1403
+ this.getData({
1404
+ word: value
1405
+ }, res => {
1406
+ if (fetchId !== this.lastFetchId) {
1407
+ return
1408
+ }
1409
+ this.option = res
1410
+ this.searching = false
1411
+ })
1412
+ },
1413
+ // 获取数据
1414
+ getData (value, callbackFun) {
1415
+ if (value !== '') {
1416
+ const logicName = this.attr.keyName
1417
+ const logic = logicName.substring(6)
1418
+ // 调用logic前设置参数
1419
+ if (this.getDataParams && this.getDataParams[this.attr.model]) {
1420
+ Object.assign(value, this.getDataParams[this.attr.model])
1421
+ }
1422
+ runLogic(logic, Object.assign(value, {
1423
+ orgId: this.currUser.orgid,
1424
+ userId: this.currUser.id
1425
+ }), this.serviceName, this.env === 'dev').then(res => {
1426
+ callbackFun(res)
1427
+ }).catch(e => {
1428
+ callbackFun([])
1429
+ console.error('获取数据失败:' + e)
1430
+ })
1431
+ }
1432
+ },
1433
+ filterOption (input, option) {
1434
+ const child = option.componentOptions.children[0]
1435
+ if (child.text) {
1436
+ return child.text.toLowerCase().indexOf(input.toLowerCase()) >= 0
1437
+ } else if (child.elm.innerText) {
1438
+ return child.elm.innerText.toLowerCase().indexOf(input.toLowerCase()) >= 0
1439
+ } else {
1440
+ return child.child.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
1441
+ }
1442
+ },
1443
+ // 表单项变更函数中调用 控制表单组中表单项组名为 groupName 的表单是否展示
1444
+ // func:x-form-show(显示)/x-form-no-show(不显示)
1445
+ emitShowFormFunc (func, groupName) {
1446
+ this.emitFunc(func, groupName)
1447
+ },
1448
+ emitFunc (func, data) {
1449
+ this.$emit('x-form-item-emit-func', func, data, data?.model ? this.form[data.model] : this.form)
1450
+ },
1451
+ itemMounted (h) {
1452
+ this.$emit('mounted', h)
1453
+ },
1454
+ rowChoose (rows) {
1455
+ this.$emit('rowChoose', rows, this.attr, this.closeRowChooseInput)
1456
+ },
1457
+ searchRowChooseData () {
1458
+ if (this.searching) {
1459
+ return
1460
+ }
1461
+ this.lastFetchId += 1
1462
+ const fetchId = this.lastFetchId
1463
+ this.searching = true
1464
+ if (fetchId !== this.lastFetchId) {
1465
+ return
1466
+ }
1467
+ this.rowChooseFixedQueryValue = []
1468
+ this.rowChooseFixedQueryValue[this.attr.model] = this.form[this.attr.model]
1469
+ this.$nextTick(() => {
1470
+ this.$refs.rowChooseTable.refresh(true)
1471
+ })
1472
+ },
1473
+ showCloseRowChooseInput () {
1474
+ this.rowChoosePopoverVisible = true
1475
+ },
1476
+ closeRowChooseInput () {
1477
+ this.rowChoosePopoverVisible = false
1478
+ },
1479
+ rowChooseSearchAfterQuery () {
1480
+ this.searching = false
1481
+ },
1482
+ // 获取 recording 转换后的数据
1483
+ getRecodingData () {
1484
+ return this.$refs.recording.getRecordingData()
1485
+ },
1486
+ recordingData (data) {
1487
+ this.emitFunc('recordingData', data)
1488
+ },
1489
+ getPopupContainer (triggerNode) {
1490
+ // 行编辑模式特殊处理
1491
+ if (typeof this.$vnode?.key === 'string' && this.$vnode.key.startsWith('editRow')) {
1492
+ // 限制最多向上查找5层
1493
+ let parent = triggerNode.parentNode
1494
+ let depth = 0
1495
+ const maxDepth = 10
1496
+
1497
+ while (parent && parent !== document.body && depth < maxDepth) {
1498
+ if (parent.tagName === 'TBODY') {
1499
+ return parent
1500
+ }
1501
+ parent = parent.parentNode
1502
+ depth++
1503
+ }
1504
+ // 如果5层内没找到,回退到body
1505
+ return document.body
1506
+ }
1507
+ return triggerNode.parentNode
1508
+ },
1509
+ colorPickerComboboxSelect (val) {
1510
+ this.form[this.attr.model] = val
1511
+ },
1512
+ }
1513
+ }
1514
+ </script>
1515
+
1516
+ <style lang="less" scoped>
1517
+ .custom-dropdown {
1518
+ position: absolute;
1519
+ z-index: 1050;
1520
+ }
1521
+
1522
+ .multiple_select {
1523
+ vertical-align: middle;
1524
+ :deep(.ant-select-selection) {
1525
+ max-height: 32px;
1526
+ overflow-y: scroll;
1527
+ }
1528
+ }
1529
+
1530
+ </style>