vue2-client 1.10.32 → 1.10.35

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.
Files changed (27) hide show
  1. package/package.json +1 -1
  2. package/src/App.vue +196 -196
  3. package/src/base-client/components/common/XAddNativeForm/demo.vue +43 -43
  4. package/src/base-client/components/common/XAddReport/XAddReport.vue +1 -1
  5. package/src/base-client/components/common/XConversation/XConversation.vue +12 -0
  6. package/src/base-client/components/common/XDataCard/XDataCard.vue +17 -16
  7. package/src/base-client/components/common/XForm/XFormItem.vue +1248 -1286
  8. package/src/base-client/components/common/XFormCol/XFormCol.vue +157 -157
  9. package/src/base-client/components/common/XFormGroup/XFormGroup.vue +301 -301
  10. package/src/base-client/components/common/XFormTable/XFormTable.vue +12 -0
  11. package/src/base-client/components/common/XFormTable/demo.vue +2 -2
  12. package/src/base-client/components/common/XIntervalPicker/XIntervalPicker.vue +121 -0
  13. package/src/base-client/components/common/XReportDrawer/XReportDrawer.vue +1 -1
  14. package/src/base-client/components/common/XReportGrid/XReport.vue +1079 -1070
  15. package/src/base-client/components/common/XReportGrid/XReportDemo.vue +46 -47
  16. package/src/base-client/components/common/XReportGrid/XReportDesign.vue +628 -628
  17. package/src/base-client/components/common/XReportGrid/XReportJsonRender.vue +380 -380
  18. package/src/base-client/components/common/XReportGrid/XReportTrGroup.vue +1104 -1104
  19. package/src/base-client/components/common/XReportGrid/print.js +184 -184
  20. package/src/base-client/components/common/XTab/XTab.vue +57 -25
  21. package/src/components/cache/AKeepAlive.js +11 -4
  22. package/src/layouts/BlankView.vue +59 -3
  23. package/src/pages/ReportGrid/index.vue +76 -76
  24. package/src/router/async/router.map.js +95 -148
  25. package/src/router/guards.js +260 -263
  26. package/src/utils/microAppUtils.js +49 -40
  27. package/src/utils/routerUtil.js +526 -450
@@ -1,1286 +1,1248 @@
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
- <a-input
554
- v-if="mode === '新增/修改'"
555
- v-model="form[attr.model]"
556
- :whitespace="true"
557
- :read-only="readOnly"
558
- :disabled="disabled && !readOnly"
559
- style="width:100%"
560
- @blur="attr.inputOnBlurFunc && emitFunc(attr.inputOnBlurFunc,attr)"
561
- :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
562
- :ref="`${attr.model}input`"/>
563
- <a-input-group v-else compact>
564
- <a-input
565
- v-model="form[attr.model][0]"
566
- class="intervalPicker-begin"
567
- placeholder="起始值"/>
568
- <a-input
569
- class="intervalPicker-center"
570
- style="backgroundColor: #fff"
571
- placeholder="~"
572
- disabled
573
- />
574
- <a-input
575
- v-model="form[attr.model][1]"
576
- class="intervalPicker-end"
577
- placeholder="结束值"/>
578
- </a-input-group>
579
- </a-form-model-item>
580
- </x-form-col>
581
- <!-- 车牌号选择 -->
582
- <x-form-col
583
- v-else-if="attr.type === 'licensePlate' && show"
584
- :labelCol="labelCol"
585
- :flex="attr.flex">
586
- <a-form-model-item
587
- :ref="attr.model"
588
- :label="showLabel?attr.name:undefined"
589
- :style="layout === 'inline'&& attr.occupyCol && attr.occupyCol > 1? {width:`calc(100% - ${attr.occupyCol * 1.533}rem)`}:{}"
590
- :prop="attr.prop ? attr.prop : attr.model">
591
- <!-- 如果配置了后置按钮插槽 -->
592
- <a-input
593
- v-if="mode ==='查询'"
594
- v-model="form[attr.model]"
595
- :whitespace="true"
596
- :read-only="readOnly"
597
- :disabled="disabled && !readOnly"
598
- style="width:100%"
599
- @blur="attr.inputOnBlurFunc && emitFunc(attr.inputOnBlurFunc,attr)"
600
- :placeholder="attr.placeholder ? attr.placeholder : '请输入'+attr.name.replace(/\s*/g, '')"
601
- :ref="`${attr.model}input`"/>
602
- <x-license-plate
603
- v-else
604
- v-model="form[attr.model]"
605
- @change="attr.dataChangeFunc && debouncedDataChangeFunc()"
606
- ></x-license-plate>
607
- </a-form-model-item>
608
- </x-form-col>
609
- <!-- 录音 -->
610
- <x-form-col
611
- v-else-if="attr.type === 'recording' && show"
612
- :labelCol="labelCol"
613
- :flex="attr.flex">
614
- <recording
615
- ref="recording"
616
- @recordingData="recordingData"
617
- >
618
- </recording>
619
- </x-form-col>
620
- <!-- 表格录入 -->
621
- <x-form-col
622
- v-else-if="attr.type === 'rowEdit' && show"
623
- :labelCol="labelCol"
624
- :flex="attr.flex">
625
- <a-form-model-item
626
- :ref="attr.model"
627
- :label="showLabel?attr.name:undefined"
628
- :prop="attr.prop ? attr.prop : attr.model">
629
- <x-form-table
630
- :key="'childTable_' + attr.model"
631
- :title="attr.name"
632
- :queryParamsName="attr.crud"
633
- :localEditMode="true"
634
- :fixed-query-form="childTableFixedQueryForm(attr)"
635
- :service-name="serviceName"
636
- @hook:mounted="(h)=>onComponentMounted(h, attr)"
637
- :ref="'childXFormTable_' + attr.model">
638
- </x-form-table>
639
- </a-form-model-item>
640
- </x-form-col>
641
- </template>
642
- <script>
643
- import { debounce } from 'ant-design-vue/lib/vc-table/src/utils'
644
- import XFormCol from '@vue2-client/base-client/components/common/XFormCol'
645
- import XBadge from '@vue2-client/base-client/components/common/XBadge'
646
- import CitySelect from '@vue2-client/base-client/components/common/CitySelect'
647
- import PersonSetting from '@vue2-client/base-client/components/common/PersonSetting'
648
- import AddressSearchCombobox from '@vue2-client/base-client/components/common/AddressSearchCombobox'
649
- import Upload from '@vue2-client/base-client/components/common/Upload'
650
- import moment from 'moment'
651
- import { getConfigByName, runLogic, getConfigByNameAsync } from '@vue2-client/services/api/common'
652
- import * as util from '@vue2-client/utils/util'
653
- import XTreeSelect from '@vue2-client/base-client/components/common/XForm/XTreeSelect'
654
- import { searchToListOption, searchToOption } from '@vue2-client/services/v3Api'
655
- import { mapState } from 'vuex'
656
- import { executeStrFunctionByContext } from '@vue2-client/utils/runEvalFunction'
657
- import XLicensePlate from '@vue2-client/base-client/components/common/XLicensePlate/XLicensePlate.vue'
658
- import XStatusButton from './XStatusButton.vue'
659
- import XClickChangeBtn from './itemComponent/XClickChangeBtn'
660
- import 'moment/locale/zh-cn'
661
- import XFormDatePicker from '@vue2-client/base-client/components/common/XDatePicker/index.vue'
662
-
663
- export default {
664
- name: 'XFormItem',
665
- components: {
666
- XFormDatePicker,
667
- XFormTable: () => import('@vue2-client/base-client/components/common/XFormTable/XFormTable.vue'),
668
- Recording: () => import('@vue2-client/base-client/components/common/Recording/Recording.vue'),
669
- XReport: () => import('@vue2-client/base-client/components/common/XReportGrid/XReport.vue'),
670
- XLicensePlate,
671
- XTreeSelect,
672
- XFormCol,
673
- XBadge,
674
- CitySelect,
675
- PersonSetting,
676
- AddressSearchCombobox,
677
- Upload,
678
- XStatusButton,
679
- XClickChangeBtn
680
- },
681
- data () {
682
- // 检索去抖
683
- this.fetchFunction = debounce(this.fetchFunction, 800)
684
- return {
685
- option: [],
686
- // 最后检索版本
687
- lastFetchId: 0,
688
- // 检索中
689
- searching: false,
690
- searchResult: '',
691
- optionForFunc: [],
692
- // 控制当前表单项是否展示
693
- show: true,
694
- // moment
695
- moment,
696
- // 行选择器浮层是否显示
697
- rowChoosePopoverVisible: false,
698
- // 行选择器CRUD固定查询值
699
- rowChooseFixedQueryValue: undefined
700
- }
701
- },
702
- props: {
703
- attr: {
704
- type: Object,
705
- default:
706
- () => {
707
- return {}
708
- }
709
- },
710
- form: {
711
- type: Object,
712
- required:
713
- true
714
- },
715
- disabled: {
716
- type: Boolean,
717
- default:
718
- () => {
719
- return false
720
- }
721
- },
722
- readOnly: {
723
- type: Boolean,
724
- default:
725
- () => {
726
- return false
727
- }
728
- },
729
- mode: {
730
- type: String,
731
- default:
732
- () => {
733
- return '查询'
734
- }
735
- },
736
- files: {
737
- type: Array,
738
- default:
739
- () => {
740
- return []
741
- }
742
- },
743
- images: {
744
- type: Array,
745
- default:
746
- () => {
747
- return []
748
- }
749
- },
750
- serviceName: {
751
- type: String,
752
- default:
753
- undefined
754
- },
755
- // 调用logic获取数据源的追加参数
756
- getDataParams: {
757
- type: Object,
758
- default:
759
- undefined
760
- },
761
- // 布局
762
- layout: {
763
- type: String,
764
- default:
765
- 'horizontal'
766
- },
767
- // 环境
768
- env: {
769
- type: String,
770
- default:
771
- () => {
772
- return 'prod'
773
- }
774
- },
775
- // 设置表单值
776
- setForm: {
777
- type: Function,
778
- default: (val) => {
779
- console.log(val)
780
- }
781
- },
782
- showLabel: {
783
- type: Boolean,
784
- default:
785
- () => {
786
- return true
787
- }
788
- },
789
- labelCol: {
790
- type: Object,
791
- default: () => { return { span: 8 } }
792
- }
793
- },
794
- provide () {
795
- return {
796
- FormItemContext: this
797
- }
798
- },
799
- created () {
800
- this.init()
801
- if (this.attr.keyName && (this.attr?.keyName?.toString().indexOf('async ') !== -1 || this.attr?.keyName?.toString()?.indexOf('function') !== -1)) {
802
- this.debouncedUpdateOptions = debounce(this.updateOptions, 200)
803
- }
804
- if (this.attr.dataChangeFunc) {
805
- this.debouncedDataChangeFunc = debounce(this.dataChangeFunc, 200)
806
- // 执行一次
807
- this.dataChangeFunc()
808
- }
809
- if (this.attr.showFormItemFunc) {
810
- this.debouncedShowFormItemFunc = debounce(this.showFormItemFunc, 100)
811
- // 执行一次
812
- this.showFormItemFunc()
813
- }
814
- if (this.attr.showQueryFormItemFunc) {
815
- this.debouncedShowQueryFormItemFunc = debounce(this.showQueryFormItemFunc, 100)
816
- // 执行一次
817
- this.showFormItemFunc()
818
- }
819
- // 人员联动框增加监听
820
- if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString().endsWith(']联动人员')) {
821
- this.debouncedUserLinkFunc = debounce(() => this.updateResOptions('人员'), 200)
822
- }
823
- if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString().endsWith(']联动部门')) {
824
- this.debouncedDepLinkFunc = debounce(() => this.updateResOptions('部门'), 200)
825
- }
826
- // xTreeSelect 自己调用 mounted
827
- if (this.attr.type !== 'treeSelect') {
828
- this.$emit('mounted')
829
- }
830
- },
831
- computed: {
832
- ...mapState('account', { currUser: 'user' }),
833
- queryParamsName () {
834
- if (this.attr.keyName.startsWith('function')) {
835
- // 调用异步函数获取内容
836
- return executeStrFunctionByContext(this, this.attr.keyName, [this.form, runLogic, this.mode, getConfigByNameAsync])
837
- } else {
838
- // 按现有方式处理
839
- return this.attr.keyName.split('@')[this.attr.keyName.split('@').length - 1]
840
- }
841
- },
842
- // 判断弹出时是否Cover,弹出只支持Cover以及CRUD
843
- isCover () {
844
- // 如果 queryParamsName 为空,返回空
845
- if (!this.queryParamsName) {
846
- return false
847
- }
848
- const result = this.queryParamsName.endsWith('Cover')
849
- return result
850
- },
851
- },
852
- watch: {
853
- attr: {
854
- handler () {
855
- this.init()
856
- },
857
- deep: true
858
- },
859
- form: {
860
- handler (newVal, oldVal) {
861
- // 如果是从函数获取 options
862
- if (this.attr.keyName && (this.attr.keyName.toString().indexOf('async ') !== -1 || this.attr.keyName.toString().indexOf('function') !== -1)) {
863
- this.debouncedUpdateOptions()
864
- }
865
- // 如果有自定义是否展示表单项函数
866
- if (this.attr.showFormItemFunc) {
867
- this.debouncedShowFormItemFunc()
868
- }
869
- // 如果有自定义是否展示查询表单项函数
870
- if (this.attr.showQueryFormItemFunc) {
871
- this.debouncedShowQueryFormItemFunc()
872
- }
873
- // 地址搜索框赋值
874
- if (this.attr.type === 'addressSearch') {
875
- this.$refs.addressSearchCombobox.addressInput = this.form[this.attr.model]
876
- }
877
- // 数据源来自人员联动时更新数据
878
- if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString().endsWith(']联动人员')) {
879
- this.debouncedUserLinkFunc()
880
- }
881
- // 数据源来自人员联动时更新数据
882
- if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString().endsWith(']联动部门')) {
883
- this.debouncedDepLinkFunc()
884
- }
885
- },
886
- deep: true
887
- }
888
- },
889
- inject: {
890
- getComponentByName: {
891
- default: () => () => {
892
- console.warn('getComponentByName is not provided')
893
- return null // 或者返回一个默认的函数
894
- },
895
- },
896
- registerComponent: {
897
- default: () => () => {
898
- console.warn('registerComponent is not provided')
899
- return null // 或者返回一个默认的函数
900
- },
901
- },
902
- getSelf: {
903
- default: () => () => {
904
- console.warn('getSelf is not provided')
905
- return null // 或者返回一个默认的函数
906
- },
907
- },
908
- },
909
- methods: {
910
- // 把内部的crud表单录入放到表单中,以便外部可以调用
911
- onComponentMounted (h, attr) {
912
- console.log('crud表单', h)
913
- if (attr.crud) {
914
- this.registerComponent(attr.model, this.$refs['childXFormTable_' + attr.model])
915
- }
916
- },
917
- childTableFixedQueryForm (item) {
918
- console.log('传递的form', this.form)
919
- if (this.modifyModelData?.primaryKeyData) {
920
- const fixedForm = {}
921
- fixedForm[item.childTableForeignKeyName] = Object.values(this.modifyModelData.primaryKeyData)[0]
922
- return fixedForm
923
- }
924
- return null
925
- },
926
- // 动态生成事件绑定对象
927
- generateDynamicEvents (inputOnAfterFunc, attr) {
928
- const events = {}
929
- const states = this.parseStates(attr.inputOnAfterName, inputOnAfterFunc)
930
-
931
- states.forEach((state) => {
932
- // 动态绑定事件名到 emitFunc
933
- events[state.event] = () => {
934
- console.info('事件名', state.event)
935
- this.emitFunc(state.event, attr)
936
- }
937
- })
938
-
939
- return events // 返回 { state1Event: handler, state2Event: handler, ... }
940
- },
941
- parseStates (input, events) {
942
- const eventNames = events.split('|')
943
- return input.split('|').map((label, index) => ({
944
- label,
945
- event: eventNames[index] // 如果没有提供事件名称,则使用默认值
946
- }))
947
- },
948
- focusInput () {
949
- if (this.attr.defaultFocus) {
950
- this.$nextTick(h => {
951
- const el = this.$refs[`${this.attr.model}input`]?.$el
952
- let inputEl
953
- if (el) {
954
- if (el.tagName.toLowerCase() === 'input') {
955
- inputEl = el
956
- } else {
957
- inputEl = el.querySelector('input')
958
- }
959
- }
960
- if (inputEl) {
961
- inputEl.focus()
962
- if (inputEl.type === 'number') {
963
- if (inputEl.valueAsNumber) {
964
- inputEl.setSelectionRange(0, inputEl.valueAsNumber.toString().length)
965
- }
966
- } else {
967
- if (inputEl.value) {
968
- inputEl.setSelectionRange(0, inputEl.value.length)
969
- }
970
- }
971
- }
972
- })
973
- }
974
- },
975
- // 更新人员下拉框数据
976
- async updateResOptions (type) {
977
- if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString()?.endsWith(`]联动${type}`)) {
978
- const searchData = { source: `获取${type}`, userid: this.currUser.id }
979
- const startIndex = this.attr.keyName.indexOf('[') + 1
980
- const endIndex = this.attr.keyName.indexOf(']', startIndex)
981
- const fromModel = this.attr.keyName.substring(startIndex, endIndex).replace('.', '_')
982
- const formModelData = this.form[fromModel]
983
- if (fromModel?.length && formModelData?.length) {
984
- await searchToListOption(searchData, res => {
985
- this.getDataCallback(
986
- res.filter(h => {
987
- if (fromModel.indexOf('org') > -1) {
988
- return formModelData?.includes(h.orgid || h.f_organization_id || h.parentid)
989
- } else {
990
- return formModelData?.includes(h?.parentid)
991
- }
992
- }
993
- )
994
- )
995
- })
996
- }
997
- }
998
- },
999
- // js 函数作为数据源
1000
- async updateOptions () {
1001
- if (this.attr.keyName && (this.attr.keyName.indexOf('async ') !== -1 || this.attr.keyName.indexOf('function ') !== -1)) {
1002
- this.optionForFunc = await executeStrFunctionByContext(this, this.attr.keyName, [this.form, runLogic, this.mode, getConfigByNameAsync])
1003
- }
1004
- },
1005
- async dataChangeFunc () {
1006
- if (this.attr.dataChangeFunc) {
1007
- await executeStrFunctionByContext(this, this.attr.dataChangeFunc, [this.form, this.setForm, this.attr, util, this.mode, runLogic, getConfigByNameAsync])
1008
- }
1009
- },
1010
- async showFormItemFunc () {
1011
- if (this.attr.showFormItemFunc) {
1012
- const obj = executeStrFunctionByContext(this, this.attr.showFormItemFunc, [this.form, this.setForm, this.attr, util, this.mode])
1013
- // 判断是 bool 还是 obj 兼容
1014
- if (typeof obj === 'boolean') {
1015
- this.show = obj
1016
- } else if (obj && typeof obj === 'object') {
1017
- // obj 是一个对象,并且不是数组
1018
- this.show = obj?.show
1019
- this.readOnly = obj?.readOnly
1020
- }
1021
- } else {
1022
- this.show = true
1023
- }
1024
- },
1025
- async showQueryFormItemFunc () {
1026
- if (this.attr.showQueryFormItemFunc) {
1027
- const obj = executeStrFunctionByContext(this, this.attr.showQueryFormItemFunc, [this.form, this.setForm, this.attr, util, this.mode])
1028
- // 判断是 bool 还是 obj 兼容
1029
- if (typeof obj === 'boolean') {
1030
- this.show = obj
1031
- } else if (obj && typeof obj === 'object') {
1032
- // obj 是一个对象,并且不是数组
1033
- this.show = obj?.show
1034
- this.readOnly = obj?.readOnly
1035
- }
1036
- } else {
1037
- this.show = true
1038
- }
1039
- },
1040
- init () {
1041
- if (!this.attr.flex) {
1042
- if (this.mode === '新增/修改') {
1043
- if (['horizontal', 'vertical'].includes(this.layout) || ['textarea', 'file', 'image'].includes(this.attr.type)) {
1044
- // 新增修改表单 horizontal 模式下默认为一行
1045
- this.attr.flex = {
1046
- xs: 24,
1047
- sm: 24,
1048
- md: 24,
1049
- lg: 24,
1050
- xl: 24,
1051
- xxl: 24,
1052
- fullWidth: true
1053
- }
1054
- } else {
1055
- // 新增修改表单 vertical 模式下默认为1列
1056
- this.attr.flex = {
1057
- xs: 24,
1058
- sm: 12,
1059
- md: 8,
1060
- lg: 8,
1061
- xl: 6,
1062
- xxl: 6
1063
- }
1064
- }
1065
- } else {
1066
- this.attr.flex = {
1067
- xs: 24,
1068
- sm: 24,
1069
- md: 8,
1070
- lg: 6,
1071
- xl: 6,
1072
- xxl: 6
1073
- }
1074
- }
1075
- }
1076
- if (this.attr.keyName && typeof this.attr.keyName === 'string') {
1077
- if (this.attr.keyName.indexOf('logic@') !== -1) {
1078
- this.getData({}, res => this.getDataCallback(res))
1079
- } else if (this.attr.keyName.indexOf('search@') !== -1) {
1080
- // `tool.getFullTree(this.getRights().where(row.getType()==$organization$))`
1081
- // 判断是否根据角色查询
1082
- let source = this.attr.keyName.substring(7)
1083
- const userid = this.currUser.id
1084
- let roleName = 'roleName'
1085
- if (source.startsWith('根据角色[') && source.endsWith(']获取人员')) {
1086
- const startIndex = source.indexOf('[') + 1
1087
- const endIndex = source.indexOf(']', startIndex)
1088
- roleName = source.substring(startIndex, endIndex)
1089
- source = '根据角色获取人员'
1090
- }
1091
- const searchData = { source, userid, roleName }
1092
- // 判断是否根据某个表单项联动 仅返回列表结构并筛选
1093
- if (source.startsWith('根据表单项[') && source.endsWith(']联动人员')) {
1094
- this.updateResOptions('人员')
1095
- } else if (source.startsWith('根据表单项[') && source.endsWith(']联动部门')) {
1096
- this.updateResOptions('部门')
1097
- } else if (this.attr.type === 'select' || this.attr.type === 'checkbox') {
1098
- // 仅获取最内层数据
1099
- searchToListOption(searchData, res => this.getDataCallback(res))
1100
- } else {
1101
- // 其他资源通用逻辑
1102
- searchToOption(searchData, res => this.getDataCallback(res))
1103
- }
1104
- } else if (this.attr.keyName.indexOf('config@') !== -1) {
1105
- const configName = this.attr.keyName.substring(7)
1106
- getConfigByName(configName, this.serviceName, res => {
1107
- this.getDataCallback(res.value)
1108
- }, this.env === 'dev')
1109
- } else if (this.attr.keyName.indexOf('async ') !== -1 || this.attr.keyName.indexOf('function ') !== -1) {
1110
- this.updateOptions()
1111
- }
1112
- }
1113
- this.focusInput()
1114
- },
1115
- addressSearchComboboxSelect (data) {
1116
- this.form = Object.assign(this.form, JSON.parse(data))
1117
- },
1118
- onDivisionsChange (data) {
1119
- this.emitFunc('addressSearchComboboxSelect', {
1120
- key: this.attr.model,
1121
- value: data
1122
- })
1123
- },
1124
- getDataCallback (res) {
1125
- this.option = res
1126
- if (this.attr.type === 'treeSelect') {
1127
- this.$refs.xTreeSelect.init({
1128
- option: this.option,
1129
- form: this.form,
1130
- queryType: this.attr.queryType,
1131
- name: this.attr.name,
1132
- model: this.attr.model,
1133
- mode: this.mode,
1134
- disabled: this.disabled
1135
- })
1136
- } else if (this.attr.type === 'radio' || ['radioGroup', 'clickChange'].includes(this.attr.showMode)) {
1137
- this.initRadioValue()
1138
- }
1139
- },
1140
- initRadioValue () {
1141
- const model = this.attr.model
1142
- if (this.mode === '新增/修改' && (this.form[model] === undefined || this.form[model] === null) && !this.attr.prop) {
1143
- if (this.attr.keys && this.attr.keys.length > 1) {
1144
- this.form[model] = this.attr.keys[0].value
1145
- } else if (this.option.length > 1) {
1146
- this.form[model] = this.option[0].value
1147
- }
1148
- }
1149
- },
1150
- // 文件框时设置上传组件的值
1151
- setFiles (fileIds) {
1152
- if (!this.form[this.attr.model]) {
1153
- this.form[this.attr.model] = []
1154
- }
1155
- this.form[this.attr.model] = [...fileIds]
1156
- },
1157
- // 懒加载检索方法
1158
- fetchFunction (value) {
1159
- this.lastFetchId += 1
1160
- const fetchId = this.lastFetchId
1161
- this.option = []
1162
- this.searching = true
1163
- this.getData({
1164
- word: value
1165
- }, res => {
1166
- if (fetchId !== this.lastFetchId) {
1167
- return
1168
- }
1169
- this.option = res
1170
- this.searching = false
1171
- })
1172
- },
1173
- // 获取数据
1174
- getData (value, callbackFun) {
1175
- if (value !== '') {
1176
- const logicName = this.attr.keyName
1177
- const logic = logicName.substring(6)
1178
- // 调用logic前设置参数
1179
- if (this.getDataParams && this.getDataParams[this.attr.model]) {
1180
- Object.assign(value, this.getDataParams[this.attr.model])
1181
- }
1182
- runLogic(logic, Object.assign(value, {
1183
- orgId: this.currUser.orgid,
1184
- userId: this.currUser.id
1185
- }), this.serviceName, this.env === 'dev').then(res => {
1186
- callbackFun(res)
1187
- }).catch(e => {
1188
- callbackFun([])
1189
- console.error('获取数据失败:' + e)
1190
- })
1191
- }
1192
- },
1193
- filterOption (input, option) {
1194
- const child = option.componentOptions.children[0]
1195
- if (child.text) {
1196
- return child.text.toLowerCase().indexOf(input.toLowerCase()) >= 0
1197
- } else if (child.elm.innerText) {
1198
- return child.elm.innerText.toLowerCase().indexOf(input.toLowerCase()) >= 0
1199
- } else {
1200
- return child.child.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
1201
- }
1202
- },
1203
- // 表单项变更函数中调用 控制表单组中表单项组名为 groupName 的表单是否展示
1204
- // func:x-form-show(显示)/x-form-no-show(不显示)
1205
- emitShowFormFunc (func, groupName) {
1206
- this.emitFunc(func, groupName)
1207
- },
1208
- emitFunc (func, data) {
1209
- this.$emit('x-form-item-emit-func', func, data, data?.model ? this.form[data.model] : this.form)
1210
- },
1211
- itemMounted (h) {
1212
- this.$emit('mounted', h)
1213
- },
1214
- rowChoose (rows) {
1215
- this.$emit('rowChoose', rows, this.attr, this.closeRowChooseInput)
1216
- },
1217
- searchRowChooseData () {
1218
- if (this.searching) {
1219
- return
1220
- }
1221
- this.lastFetchId += 1
1222
- const fetchId = this.lastFetchId
1223
- this.searching = true
1224
- if (fetchId !== this.lastFetchId) {
1225
- return
1226
- }
1227
- this.rowChooseFixedQueryValue = []
1228
- this.rowChooseFixedQueryValue[this.attr.model] = this.form[this.attr.model]
1229
- this.$nextTick(() => {
1230
- this.$refs.rowChooseTable.refresh(true)
1231
- })
1232
- },
1233
- showCloseRowChooseInput () {
1234
- this.rowChoosePopoverVisible = true
1235
- },
1236
- closeRowChooseInput () {
1237
- this.rowChoosePopoverVisible = false
1238
- },
1239
- rowChooseSearchAfterQuery () {
1240
- this.searching = false
1241
- },
1242
- // 获取 recording 转换后的数据
1243
- getRecodingData () {
1244
- return this.$refs.recording.getRecordingData()
1245
- },
1246
- recordingData (data) {
1247
- this.emitFunc('recordingData', data)
1248
- },
1249
- getPopupContainer (triggerNode) {
1250
- return document.body
1251
- // return triggerNode.parentNode
1252
- }
1253
- }
1254
- }
1255
- </script>
1256
-
1257
- <style lang="less" scoped>
1258
- .custom-dropdown {
1259
- position: absolute;
1260
- z-index: 1050;
1261
- }
1262
-
1263
- .intervalPicker-begin {
1264
- width: calc(50% - 14px);
1265
- }
1266
-
1267
- .intervalPicker-center {
1268
- width: 30px;
1269
- border-left: 0;
1270
- pointer-events: none;
1271
- }
1272
-
1273
- .intervalPicker-end {
1274
- width: calc(50% - 14px);
1275
- border-left: 0;
1276
- }
1277
-
1278
- //.label-box{
1279
- // width: 80%;
1280
- // display: inline-block;
1281
- // height: auto;
1282
- // white-space: break-spaces;
1283
- // line-height: 18px;
1284
- // text-align: left;
1285
- //}
1286
- </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' || (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: () => { return { span: 8 } }
778
+ }
779
+ },
780
+ provide () {
781
+ return {
782
+ FormItemContext: this
783
+ }
784
+ },
785
+ created () {
786
+ this.init()
787
+ if (this.attr.keyName && (this.attr?.keyName?.toString().indexOf('async ') !== -1 || this.attr?.keyName?.toString()?.indexOf('function') !== -1)) {
788
+ this.debouncedUpdateOptions = debounce(this.updateOptions, 200)
789
+ }
790
+ if (this.attr.dataChangeFunc) {
791
+ this.debouncedDataChangeFunc = debounce(this.dataChangeFunc, 200)
792
+ // 执行一次
793
+ this.dataChangeFunc()
794
+ }
795
+ if (this.attr.showFormItemFunc) {
796
+ this.debouncedShowFormItemFunc = debounce(this.showFormItemFunc, 100)
797
+ // 执行一次
798
+ this.showFormItemFunc()
799
+ }
800
+ if (this.attr.showQueryFormItemFunc) {
801
+ this.debouncedShowQueryFormItemFunc = debounce(this.showQueryFormItemFunc, 100)
802
+ // 执行一次
803
+ this.showFormItemFunc()
804
+ }
805
+ // 人员联动框增加监听
806
+ if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString().endsWith(']联动人员')) {
807
+ this.debouncedUserLinkFunc = debounce(() => this.updateResOptions('人员'), 200)
808
+ }
809
+ if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString().endsWith(']联动部门')) {
810
+ this.debouncedDepLinkFunc = debounce(() => this.updateResOptions('部门'), 200)
811
+ }
812
+ // xTreeSelect 自己调用 mounted
813
+ if (this.attr.type !== 'treeSelect') {
814
+ this.$emit('mounted')
815
+ }
816
+ },
817
+ computed: {
818
+ ...mapState('account', { currUser: 'user' }),
819
+ queryParamsName () {
820
+ if (this.attr.keyName.startsWith('function')) {
821
+ // 调用异步函数获取内容
822
+ return executeStrFunctionByContext(this, this.attr.keyName, [this.form, runLogic, this.mode, getConfigByNameAsync])
823
+ } else {
824
+ // 按现有方式处理
825
+ return this.attr.keyName.split('@')[this.attr.keyName.split('@').length - 1]
826
+ }
827
+ },
828
+ // 判断弹出时是否Cover,弹出只支持Cover以及CRUD
829
+ isCover () {
830
+ // 如果 queryParamsName 为空,返回空
831
+ if (!this.queryParamsName) {
832
+ return false
833
+ }
834
+ const result = this.queryParamsName.endsWith('Cover')
835
+ return result
836
+ },
837
+ },
838
+ watch: {
839
+ attr: {
840
+ handler () {
841
+ this.init()
842
+ },
843
+ deep: true
844
+ },
845
+ form: {
846
+ handler (newVal, oldVal) {
847
+ // 如果是从函数获取 options
848
+ if (this.attr.keyName && (this.attr.keyName.toString().indexOf('async ') !== -1 || this.attr.keyName.toString().indexOf('function') !== -1)) {
849
+ this.debouncedUpdateOptions()
850
+ }
851
+ // 如果有自定义是否展示表单项函数
852
+ if (this.attr.showFormItemFunc) {
853
+ this.debouncedShowFormItemFunc()
854
+ }
855
+ // 如果有自定义是否展示查询表单项函数
856
+ if (this.attr.showQueryFormItemFunc) {
857
+ this.debouncedShowQueryFormItemFunc()
858
+ }
859
+ // 地址搜索框赋值
860
+ if (this.attr.type === 'addressSearch') {
861
+ this.$refs.addressSearchCombobox.addressInput = this.form[this.attr.model]
862
+ }
863
+ // 数据源来自人员联动时更新数据
864
+ if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString().endsWith(']联动人员')) {
865
+ this.debouncedUserLinkFunc()
866
+ }
867
+ // 数据源来自人员联动时更新数据
868
+ if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString().endsWith(']联动部门')) {
869
+ this.debouncedDepLinkFunc()
870
+ }
871
+ },
872
+ deep: true
873
+ }
874
+ },
875
+ inject: {
876
+ getComponentByName: {
877
+ default: () => () => {
878
+ console.warn('getComponentByName is not provided')
879
+ return null // 或者返回一个默认的函数
880
+ },
881
+ },
882
+ registerComponent: {
883
+ default: () => () => {
884
+ console.warn('registerComponent is not provided')
885
+ return null // 或者返回一个默认的函数
886
+ },
887
+ },
888
+ getSelf: {
889
+ default: () => () => {
890
+ console.warn('getSelf is not provided')
891
+ return null // 或者返回一个默认的函数
892
+ },
893
+ },
894
+ },
895
+ methods: {
896
+ // 把内部的crud表单录入放到表单中,以便外部可以调用
897
+ onComponentMounted (h, attr) {
898
+ console.log('crud表单', h)
899
+ if (attr.crud) {
900
+ this.registerComponent(attr.model, this.$refs['childXFormTable_' + attr.model])
901
+ }
902
+ },
903
+ childTableFixedQueryForm (item) {
904
+ console.log('传递的form', this.form)
905
+ if (this.modifyModelData?.primaryKeyData) {
906
+ const fixedForm = {}
907
+ fixedForm[item.childTableForeignKeyName] = Object.values(this.modifyModelData.primaryKeyData)[0]
908
+ return fixedForm
909
+ }
910
+ return null
911
+ },
912
+ // 动态生成事件绑定对象
913
+ generateDynamicEvents (inputOnAfterFunc, attr) {
914
+ const events = {}
915
+ const states = this.parseStates(attr.inputOnAfterName, inputOnAfterFunc)
916
+
917
+ states.forEach((state) => {
918
+ // 动态绑定事件名到 emitFunc
919
+ events[state.event] = () => {
920
+ console.info('事件名', state.event)
921
+ this.emitFunc(state.event, attr)
922
+ }
923
+ })
924
+
925
+ return events // 返回 { state1Event: handler, state2Event: handler, ... }
926
+ },
927
+ parseStates (input, events) {
928
+ const eventNames = events.split('|')
929
+ return input.split('|').map((label, index) => ({
930
+ label,
931
+ event: eventNames[index] // 如果没有提供事件名称,则使用默认值
932
+ }))
933
+ },
934
+ focusInput () {
935
+ if (this.attr.defaultFocus) {
936
+ this.$nextTick(h => {
937
+ const el = this.$refs[`${this.attr.model}input`]?.$el
938
+ let inputEl
939
+ if (el) {
940
+ if (el.tagName.toLowerCase() === 'input') {
941
+ inputEl = el
942
+ } else {
943
+ inputEl = el.querySelector('input')
944
+ }
945
+ }
946
+ if (inputEl) {
947
+ inputEl.focus()
948
+ if (inputEl.type === 'number') {
949
+ if (inputEl.valueAsNumber) {
950
+ inputEl.setSelectionRange(0, inputEl.valueAsNumber.toString().length)
951
+ }
952
+ } else {
953
+ if (inputEl.value) {
954
+ inputEl.setSelectionRange(0, inputEl.value.length)
955
+ }
956
+ }
957
+ }
958
+ })
959
+ }
960
+ },
961
+ // 更新人员下拉框数据
962
+ async updateResOptions (type) {
963
+ if (this?.attr?.keyName?.toString()?.startsWith('search@根据表单项[') && this?.attr?.keyName?.toString()?.endsWith(`]联动${type}`)) {
964
+ const searchData = { source: `获取${type}`, userid: this.currUser.id }
965
+ const startIndex = this.attr.keyName.indexOf('[') + 1
966
+ const endIndex = this.attr.keyName.indexOf(']', startIndex)
967
+ const fromModel = this.attr.keyName.substring(startIndex, endIndex).replace('.', '_')
968
+ const formModelData = this.form[fromModel]
969
+ if (fromModel?.length && formModelData?.length) {
970
+ await searchToListOption(searchData, res => {
971
+ this.getDataCallback(
972
+ res.filter(h => {
973
+ if (fromModel.indexOf('org') > -1) {
974
+ return formModelData?.includes(h.orgid || h.f_organization_id || h.parentid)
975
+ } else {
976
+ return formModelData?.includes(h?.parentid)
977
+ }
978
+ }
979
+ )
980
+ )
981
+ })
982
+ }
983
+ }
984
+ },
985
+ // js 函数作为数据源
986
+ async updateOptions () {
987
+ if (this.attr.keyName && (this.attr.keyName.indexOf('async ') !== -1 || this.attr.keyName.indexOf('function ') !== -1)) {
988
+ this.optionForFunc = await executeStrFunctionByContext(this, this.attr.keyName, [this.form, runLogic, this.mode, getConfigByNameAsync])
989
+ }
990
+ },
991
+ async dataChangeFunc () {
992
+ if (this.attr.dataChangeFunc) {
993
+ await executeStrFunctionByContext(this, this.attr.dataChangeFunc, [this.form, this.setForm, this.attr, util, this.mode, runLogic, getConfigByNameAsync])
994
+ }
995
+ },
996
+ async showFormItemFunc () {
997
+ if (this.attr.showFormItemFunc) {
998
+ const obj = executeStrFunctionByContext(this, this.attr.showFormItemFunc, [this.form, this.setForm, this.attr, util, this.mode])
999
+ // 判断是 bool 还是 obj 兼容
1000
+ if (typeof obj === 'boolean') {
1001
+ this.show = obj
1002
+ } else if (obj && typeof obj === 'object') {
1003
+ // obj 是一个对象,并且不是数组
1004
+ this.show = obj?.show
1005
+ this.readOnly = obj?.readOnly
1006
+ }
1007
+ } else {
1008
+ this.show = true
1009
+ }
1010
+ },
1011
+ async showQueryFormItemFunc () {
1012
+ if (this.attr.showQueryFormItemFunc) {
1013
+ const obj = executeStrFunctionByContext(this, this.attr.showQueryFormItemFunc, [this.form, this.setForm, this.attr, util, this.mode])
1014
+ // 判断是 bool 还是 obj 兼容
1015
+ if (typeof obj === 'boolean') {
1016
+ this.show = obj
1017
+ } else if (obj && typeof obj === 'object') {
1018
+ // obj 是一个对象,并且不是数组
1019
+ this.show = obj?.show
1020
+ this.readOnly = obj?.readOnly
1021
+ }
1022
+ } else {
1023
+ this.show = true
1024
+ }
1025
+ },
1026
+ init () {
1027
+ if (!this.attr.flex) {
1028
+ if (this.mode === '新增/修改') {
1029
+ if (['horizontal', 'vertical'].includes(this.layout) || ['textarea', 'file', 'image'].includes(this.attr.type)) {
1030
+ // 新增修改表单 horizontal 模式下默认为一行
1031
+ this.attr.flex = {
1032
+ xs: 24,
1033
+ sm: 24,
1034
+ md: 24,
1035
+ lg: 24,
1036
+ xl: 24,
1037
+ xxl: 24,
1038
+ fullWidth: true
1039
+ }
1040
+ } else {
1041
+ // 新增修改表单 vertical 模式下默认为1列
1042
+ this.attr.flex = {
1043
+ xs: 24,
1044
+ sm: 12,
1045
+ md: 8,
1046
+ lg: 8,
1047
+ xl: 6,
1048
+ xxl: 6
1049
+ }
1050
+ }
1051
+ } else {
1052
+ this.attr.flex = {
1053
+ xs: 24,
1054
+ sm: 24,
1055
+ md: 8,
1056
+ lg: 6,
1057
+ xl: 6,
1058
+ xxl: 6
1059
+ }
1060
+ }
1061
+ }
1062
+ if (this.attr.keyName && typeof this.attr.keyName === 'string') {
1063
+ if (this.attr.keyName.indexOf('logic@') !== -1) {
1064
+ this.getData({}, res => this.getDataCallback(res))
1065
+ } else if (this.attr.keyName.indexOf('search@') !== -1) {
1066
+ // `tool.getFullTree(this.getRights().where(row.getType()==$organization$))`
1067
+ // 判断是否根据角色查询
1068
+ let source = this.attr.keyName.substring(7)
1069
+ const userid = this.currUser.id
1070
+ let roleName = 'roleName'
1071
+ if (source.startsWith('根据角色[') && source.endsWith(']获取人员')) {
1072
+ const startIndex = source.indexOf('[') + 1
1073
+ const endIndex = source.indexOf(']', startIndex)
1074
+ roleName = source.substring(startIndex, endIndex)
1075
+ source = '根据角色获取人员'
1076
+ }
1077
+ const searchData = { source, userid, roleName }
1078
+ // 判断是否根据某个表单项联动 仅返回列表结构并筛选
1079
+ if (source.startsWith('根据表单项[') && source.endsWith(']联动人员')) {
1080
+ this.updateResOptions('人员')
1081
+ } else if (source.startsWith('根据表单项[') && source.endsWith(']联动部门')) {
1082
+ this.updateResOptions('部门')
1083
+ } else if (this.attr.type === 'select' || this.attr.type === 'checkbox') {
1084
+ // 仅获取最内层数据
1085
+ searchToListOption(searchData, res => this.getDataCallback(res))
1086
+ } else {
1087
+ // 其他资源通用逻辑
1088
+ searchToOption(searchData, res => this.getDataCallback(res))
1089
+ }
1090
+ } else if (this.attr.keyName.indexOf('config@') !== -1) {
1091
+ const configName = this.attr.keyName.substring(7)
1092
+ getConfigByName(configName, this.serviceName, res => {
1093
+ this.getDataCallback(res.value)
1094
+ }, this.env === 'dev')
1095
+ } else if (this.attr.keyName.indexOf('async ') !== -1 || this.attr.keyName.indexOf('function ') !== -1) {
1096
+ this.updateOptions()
1097
+ }
1098
+ }
1099
+ this.focusInput()
1100
+ },
1101
+ addressSearchComboboxSelect (data) {
1102
+ this.form = Object.assign(this.form, JSON.parse(data))
1103
+ },
1104
+ onDivisionsChange (data) {
1105
+ this.emitFunc('addressSearchComboboxSelect', {
1106
+ key: this.attr.model,
1107
+ value: data
1108
+ })
1109
+ },
1110
+ getDataCallback (res) {
1111
+ this.option = res
1112
+ if (this.attr.type === 'treeSelect') {
1113
+ this.$refs.xTreeSelect.init({
1114
+ option: this.option,
1115
+ form: this.form,
1116
+ queryType: this.attr.queryType,
1117
+ name: this.attr.name,
1118
+ model: this.attr.model,
1119
+ mode: this.mode,
1120
+ disabled: this.disabled
1121
+ })
1122
+ } else if (this.attr.type === 'radio' || ['radioGroup', 'clickChange'].includes(this.attr.showMode)) {
1123
+ this.initRadioValue()
1124
+ }
1125
+ },
1126
+ initRadioValue () {
1127
+ const model = this.attr.model
1128
+ if (this.mode === '新增/修改' && (this.form[model] === undefined || this.form[model] === null) && !this.attr.prop) {
1129
+ if (this.attr.keys && this.attr.keys.length > 1) {
1130
+ this.form[model] = this.attr.keys[0].value
1131
+ } else if (this.option.length > 1) {
1132
+ this.form[model] = this.option[0].value
1133
+ }
1134
+ }
1135
+ },
1136
+ // 文件框时设置上传组件的值
1137
+ setFiles (fileIds) {
1138
+ if (!this.form[this.attr.model]) {
1139
+ this.form[this.attr.model] = []
1140
+ }
1141
+ this.form[this.attr.model] = [...fileIds]
1142
+ },
1143
+ // 懒加载检索方法
1144
+ fetchFunction (value) {
1145
+ this.lastFetchId += 1
1146
+ const fetchId = this.lastFetchId
1147
+ this.option = []
1148
+ this.searching = true
1149
+ this.getData({
1150
+ word: value
1151
+ }, res => {
1152
+ if (fetchId !== this.lastFetchId) {
1153
+ return
1154
+ }
1155
+ this.option = res
1156
+ this.searching = false
1157
+ })
1158
+ },
1159
+ // 获取数据
1160
+ getData (value, callbackFun) {
1161
+ if (value !== '') {
1162
+ const logicName = this.attr.keyName
1163
+ const logic = logicName.substring(6)
1164
+ // 调用logic前设置参数
1165
+ if (this.getDataParams && this.getDataParams[this.attr.model]) {
1166
+ Object.assign(value, this.getDataParams[this.attr.model])
1167
+ }
1168
+ runLogic(logic, Object.assign(value, {
1169
+ orgId: this.currUser.orgid,
1170
+ userId: this.currUser.id
1171
+ }), this.serviceName, this.env === 'dev').then(res => {
1172
+ callbackFun(res)
1173
+ }).catch(e => {
1174
+ callbackFun([])
1175
+ console.error('获取数据失败:' + e)
1176
+ })
1177
+ }
1178
+ },
1179
+ filterOption (input, option) {
1180
+ const child = option.componentOptions.children[0]
1181
+ if (child.text) {
1182
+ return child.text.toLowerCase().indexOf(input.toLowerCase()) >= 0
1183
+ } else if (child.elm.innerText) {
1184
+ return child.elm.innerText.toLowerCase().indexOf(input.toLowerCase()) >= 0
1185
+ } else {
1186
+ return child.child.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
1187
+ }
1188
+ },
1189
+ // 表单项变更函数中调用 控制表单组中表单项组名为 groupName 的表单是否展示
1190
+ // func:x-form-show(显示)/x-form-no-show(不显示)
1191
+ emitShowFormFunc (func, groupName) {
1192
+ this.emitFunc(func, groupName)
1193
+ },
1194
+ emitFunc (func, data) {
1195
+ this.$emit('x-form-item-emit-func', func, data, data?.model ? this.form[data.model] : this.form)
1196
+ },
1197
+ itemMounted (h) {
1198
+ this.$emit('mounted', h)
1199
+ },
1200
+ rowChoose (rows) {
1201
+ this.$emit('rowChoose', rows, this.attr, this.closeRowChooseInput)
1202
+ },
1203
+ searchRowChooseData () {
1204
+ if (this.searching) {
1205
+ return
1206
+ }
1207
+ this.lastFetchId += 1
1208
+ const fetchId = this.lastFetchId
1209
+ this.searching = true
1210
+ if (fetchId !== this.lastFetchId) {
1211
+ return
1212
+ }
1213
+ this.rowChooseFixedQueryValue = []
1214
+ this.rowChooseFixedQueryValue[this.attr.model] = this.form[this.attr.model]
1215
+ this.$nextTick(() => {
1216
+ this.$refs.rowChooseTable.refresh(true)
1217
+ })
1218
+ },
1219
+ showCloseRowChooseInput () {
1220
+ this.rowChoosePopoverVisible = true
1221
+ },
1222
+ closeRowChooseInput () {
1223
+ this.rowChoosePopoverVisible = false
1224
+ },
1225
+ rowChooseSearchAfterQuery () {
1226
+ this.searching = false
1227
+ },
1228
+ // 获取 recording 转换后的数据
1229
+ getRecodingData () {
1230
+ return this.$refs.recording.getRecordingData()
1231
+ },
1232
+ recordingData (data) {
1233
+ this.emitFunc('recordingData', data)
1234
+ },
1235
+ getPopupContainer (triggerNode) {
1236
+ return document.body
1237
+ // return triggerNode.parentNode
1238
+ }
1239
+ }
1240
+ }
1241
+ </script>
1242
+
1243
+ <style lang="less" scoped>
1244
+ .custom-dropdown {
1245
+ position: absolute;
1246
+ z-index: 1050;
1247
+ }
1248
+ </style>