vue2-client 1.12.37 → 1.12.39

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