vue2-client 1.17.31 → 1.17.32

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 (26) hide show
  1. package/.env.message +19 -19
  2. package/package.json +112 -112
  3. package/src/assets/svg/female.svg +1 -1
  4. package/src/assets/svg/male.svg +1 -1
  5. package/src/base-client/components/common/HIS/HButtons/HButtons.vue +491 -491
  6. package/src/base-client/components/common/HIS/HFormGroup/index.js +3 -3
  7. package/src/base-client/components/common/HIS/HTab/HTab.vue +443 -443
  8. package/src/base-client/components/common/ImagePreviewModal/index.js +3 -3
  9. package/src/base-client/components/common/Upload/Upload.vue +344 -344
  10. package/src/base-client/components/common/XAddNativeForm/XAddNativeForm.vue +1288 -1288
  11. package/src/base-client/components/common/XCollapse/XCollapse.vue +833 -833
  12. package/src/base-client/components/common/XFormTable/demo.vue +89 -89
  13. package/src/base-client/components/common/XReportGrid/XReportTrGroup.vue +1 -1
  14. package/src/base-client/components/common/XTab/XTab.vue +612 -612
  15. package/src/base-client/components/common/XTable/XTableWrapper.vue +674 -674
  16. package/src/base-client/components/common/XTimeline/XTimeline.vue +477 -477
  17. package/src/base-client/components/his/XHisEditor/XHisEditor.vue +705 -705
  18. package/src/base-client/components/his/XList/XList.vue +938 -938
  19. package/src/base-client/components/his/XTimeSelect/XTimeSelect.vue +354 -354
  20. package/src/base-client/components/his/XTitle/XTitle.vue +314 -314
  21. package/src/base-client/components/his/XTreeRows/XTreeRows.vue +341 -341
  22. package/src/base-client/components/his/threeTestOrders/editor.vue +113 -113
  23. package/src/pages/userInfoDetailManage/ExceptionRecordQuery/index.vue +45 -45
  24. package/src/router/async/router.map.js +133 -133
  25. package/src-base-client/components/common/HIS/HForm/HForm.vue +347 -0
  26. package/src-base-client/components/common/XCollapse/XCollapse.vue +0 -0
@@ -1,1288 +1,1288 @@
1
- <template>
2
- <div id="XAddNativeForm">
3
- <a-form-model
4
- v-if="loaded"
5
- ref="selectForm"
6
- :zIndex="1001"
7
- :model="form"
8
- v-bind="formItemLayoutGen"
9
- :layout="layout">
10
- <template v-for="(item, key) in childTableData">
11
- <a-row
12
- v-if="childTablePriority"
13
- :gutter="16"
14
- :key="'childTableRow' + key">
15
- <a-card :title="item.name" :bordered="false" size="small">
16
- <x-form-table
17
- :key="'childTable_' + item.model"
18
- :title="item.name"
19
- :queryParamsName="item.childTableConfigName"
20
- :localEditMode="true"
21
- :fixed-query-form="childTableFixedQueryForm(item)"
22
- :service-name="serviceName"
23
- @innerXFormTableEmit="innerXFormTableEmit"
24
- @afterTableInit="childTableMounted(item)"
25
- :ref="'childXFormTable_' + item.model">
26
- </x-form-table>
27
- </a-card>
28
- </a-row>
29
- </template>
30
- <template v-if="isSimpleInlineMode">
31
- <a-row
32
- v-for="(row, rowIndex) in simpleInlineRows"
33
- :key="'simple-row-' + rowIndex"
34
- :gutter="0"
35
- type="flex">
36
- <a-col
37
- v-for="(item, itemIndex) in row.items"
38
- :key="'simple-item-' + itemIndex"
39
- :span="item.span">
40
- <x-form-item
41
- class="simple-inline-item"
42
- :attr="item.formItem"
43
- :disabled="itemDisabled(item.formItem)"
44
- :read-only="readonly(item.formItem)"
45
- :files="files"
46
- :form="form"
47
- :images="images"
48
- :service-name="serviceName"
49
- mode="新增/修改"
50
- layout="simple-inline"
51
- :rules="rules[`${item.formItem.name}${item.formItem.model}`]"
52
- :get-data-params="getDataParams"
53
- :env="env"
54
- :enablePopupToBody="enablePopupToBody"
55
- @x-form-item-emit-func="emitFunc"
56
- @rowChoose="rowChoose"
57
- :setForm="setForm"
58
- :style="{ margin: 0, padding: '2px' }"
59
- />
60
- </a-col>
61
- </a-row>
62
- </template>
63
- <a-row ref="GroupItemRow" v-if="!isSimpleInlineMode">
64
- <a-col :span="3" v-if="!inXFormGroup && !(groups[0].groupName === DEFAULT_GROUP_NAME)">
65
- <a-tabs tab-position="left" v-model="activeTab" @change="scrollToGroup">
66
- <a-tab-pane
67
- v-for="(groupsItem,groupsIndex) in groups"
68
- :tab="groupsItem.groupName"
69
- :key="groupsIndex">
70
- </a-tab-pane>
71
- </a-tabs>
72
- </a-col>
73
- <a-col
74
- :span="(!inXFormGroup && !(groups[0].groupName === DEFAULT_GROUP_NAME)) ? 21: 24">
75
- <a-row
76
- :gutter="16"
77
- type="flex"
78
- :key="groupsIndex"
79
- v-for="(groupsItem,groupsIndex) in groups"
80
- >
81
- <a-col
82
- :span="24"
83
- :style="{ marginTop: groupsIndex === 0 ? '' : '8px',fontSize:inXFormGroup?'15px':'14px', marginLeft:'-5px' }"
84
- v-if="groupsItem.groupName !== DEFAULT_GROUP_NAME">
85
- <span class="xFormGroupTitle" :ref="`group-title-${groupsIndex}`">{{ groupsItem.groupName }}</span>
86
- </a-col>
87
- <x-form-item
88
- v-for="(item, index) in groupsItem.realJsonData"
89
- :key="index"
90
- :attr="item"
91
- :disabled="itemDisabled(item)"
92
- :read-only="readonly(item)"
93
- :files="files"
94
- v-bind="formItemLayoutGen"
95
- :style="layout === 'inline' ? { marginTop:'5px' } : undefined"
96
- :form="form"
97
- :images="images"
98
- :enablePopupToBody="enablePopupToBody"
99
- :service-name="serviceName"
100
- mode="新增/修改"
101
- :layout="layout"
102
- :rules="rules[`${item.name}${item.model}`]"
103
- :get-data-params="getDataParams"
104
- :env="env"
105
- @x-form-item-emit-func="emitFunc"
106
- @rowChoose="rowChoose"
107
- :setForm="setForm"
108
- />
109
- </a-row>
110
- </a-col>
111
- </a-row>
112
- <a-row :gutter="16" v-for="(groupItem, groupIndex) in groupJsonData" :key="groupIndex" v-if="!isSimpleInlineMode">
113
- <a-card v-if="groupItem.groupItems.length > 0" :title="groupItem.name" :bordered="false" size="small">
114
- <x-form-item
115
- v-for="(item, index) in groupItem.groupItems"
116
- :key="index"
117
- :attr="item"
118
- :disabled="itemDisabled(item)"
119
- :readonly="readonly(item)"
120
- :files="files"
121
- v-bind="formItemLayoutGen"
122
- :style="layout ==='inline'?{marginTop:'5px'}:undefined"
123
- :form="form[groupItem.model]"
124
- :images="images"
125
- :service-name="serviceName"
126
- mode="新增/修改"
127
- :rules="rules[`${item.name}${item.model}`]"
128
- :get-data-params="getDataParams"
129
- :env="env"
130
- :setForm="setForm"
131
- @rowChoose="rowChoose"
132
- />
133
- </a-card>
134
- <template v-else>
135
- <slot
136
- name="groupFormItems"
137
- :form="form"
138
- :model="groupItem.model"
139
- :rules="rules"
140
- :modifyModelData="modifyModelData"></slot>
141
- </template>
142
- </a-row>
143
- <a-row :gutter="16" v-for="(item, key) in simpleFormJsonData" :key="'row' + key" v-if="!isSimpleInlineMode">
144
- <a-card v-if="item.value.length > 0" :title="item.name" :bordered="false" size="small">
145
- <x-form-item
146
- v-for="(formItem, formItemIndex) in item.value"
147
- :key="key + formItemIndex"
148
- :attr="formItem"
149
- :disabled="itemDisabled(formItem)"
150
- :readonly="readonly(formItem)"
151
- :files="files"
152
- :enablePopupToBody="enablePopupToBody"
153
- v-bind="formItemLayoutGen"
154
- :style="layout ==='inline'?{marginTop:'5px'}:undefined"
155
- :form="form[groupItem.model]"
156
- :images="images"
157
- :service-name="serviceName"
158
- mode="新增/修改"
159
- :rules="rules[`${item.name}${item.model}`]"
160
- :get-data-params="getDataParams"
161
- :env="env"
162
- :setForm="setForm"
163
- @rowChoose="rowChoose"
164
- />
165
- </a-card>
166
- </a-row>
167
- <template v-for="(item, key) in childTableData">
168
- <a-row
169
- v-if="!childTablePriority"
170
- :gutter="16"
171
- :key="'childTableRow' + key">
172
- <a-card :title="item.name" :bordered="false" size="small">
173
- <x-form-table
174
- :key="'childTable_' + item.model"
175
- :title="item.name"
176
- :queryParamsName="item.childTableConfigName"
177
- :localEditMode="true"
178
- @innerXFormTableEmit="innerXFormTableEmit"
179
- :fixed-query-form="childTableFixedQueryForm(item)"
180
- :service-name="serviceName"
181
- @afterTableInit="childTableMounted(item)"
182
- :ref="'childXFormTable_' + item.model">
183
- </x-form-table>
184
- </a-card>
185
- </a-row>
186
- </template>
187
- <a-row type="flex" :justify="btnPlace" :style="{paddingLeft: '16px',paddingRight: '16px'}">
188
- <slot name="footer" :loading="loading">
189
- <a-button v-if="showSubmitBtn" :loading="loading" type="primary" @click="onSubmit()">{{ btnName }}</a-button>
190
- </slot>
191
- </a-row>
192
- </a-form-model>
193
- </div>
194
- </template>
195
- <script>
196
- import XFormItem from '@vue2-client/base-client/components/common/XForm/XFormItem'
197
- import { formatDate, setDataByRealKey } from '@vue2-client/utils/util'
198
- import * as util from '@vue2-client/utils/util'
199
- import { mapState } from 'vuex'
200
- import { addOrModify, getConfigByName, getConfigByNameAsync, runLogic } from '@vue2-client/services/api/common'
201
- import { checkIdNumber, REG_EMAIL, REG_LANDLINE, REG_PHONE } from '@vue2-client/utils/reg'
202
- import moment from 'moment/moment'
203
- import { executeStrFunction, executeStrFunctionByContext } from '@vue2-client/utils/runEvalFunction'
204
- import formValidationMixin from '@vue2-client/mixins/formValidationMixin'
205
-
206
- const DEFAULT_GROUP_NAME = '__default__'
207
- export default {
208
- name: 'XAddNativeForm',
209
- components: {
210
- XFormItem,
211
- XFormTable: () => import('@vue2-client/base-client/components/common/XFormTable/XFormTable.vue')
212
- },
213
- inject: {
214
- inXFormGroup: {
215
- default: false
216
- },
217
- formGroupContext: {
218
- default: null
219
- },
220
- formDataChange: {
221
- default: null
222
- }
223
- },
224
- props: {
225
- // 是否启用 horizontal 模式的自定义配置
226
- enableHorizontalCustom: {
227
- type: Boolean,
228
- default: false
229
- },
230
- // 是否启用时间弹出到最外层
231
- enablePopupToBody: {
232
- type: Boolean,
233
- default: false
234
- }
235
- },
236
- data () {
237
- return {
238
- DEFAULT_GROUP_NAME,
239
- // 预览模式
240
- viewMode: false,
241
- // 是否处理表单Key值
242
- isHandleFormKey: true,
243
- // 内容加载是否完成
244
- loaded: false,
245
- // 业务类型
246
- businessType: '',
247
- // 业务标题
248
- title: '',
249
- // 新增或修改业务是否执行中
250
- loading: false,
251
- // 表单Model
252
- form: {},
253
- // 配置名称
254
- configName: undefined,
255
- // 配置内容,用于查询配置生成器的预览
256
- configContent: undefined,
257
- // 表单项集合
258
- formItems: [],
259
- // 服务名称
260
- serviceName: undefined,
261
- // 是否显示提交按钮
262
- showSubmitBtn: true,
263
- // 修改有文件的表单时使用
264
- files: [],
265
- images: [],
266
- // 校验
267
- rules: {},
268
- // 调用logic获取数据源的追加参数
269
- getDataParams: {},
270
- // 动态简易表单集合
271
- simpleFormJsonData: {},
272
- // 待修改的数据集
273
- modifyModelData: {},
274
- // 当前环境
275
- env: 'prod',
276
- // 表单主键
277
- primaryKey: null,
278
- // 表单模式 horizontal | vertical | inline
279
- layout: 'horizontal',
280
- // 提交按钮名称
281
- btnName: '提交',
282
- // 提交按钮位置 start / center / end
283
- btnPlace: 'center',
284
- // 子表是否排在前面
285
- childTablePriority: false,
286
- // simple-inline布局配置
287
- simpleInline: null
288
- }
289
- },
290
- computed: {
291
- // 过滤出用于新增/修改场景的表单项
292
- realJsonData: function () {
293
- return this.formItems.filter((item) => {
294
- return item.addOrEdit && item.addOrEdit !== 'no' && item.addOrEdit !== 'silenceAdd' && item.addOrEdit !== 'version' && !this.itemDisabled(item)
295
- })
296
- },
297
- // 表单项组 / 不是 数据组
298
- groups: function () {
299
- if (!this.realJsonData || this.realJsonData.length === 0) {
300
- return [{
301
- groupName: DEFAULT_GROUP_NAME,
302
- realJsonData: this.realJsonData,
303
- xAddFormLayout: 'horizontal'
304
- }]
305
- }
306
- const uniqueGroups = new Set(this.realJsonData.map(item => item.group).filter(Boolean))
307
- const allGroup = Array.from(uniqueGroups).map(group => {
308
- return {
309
- groupName: group,
310
- realJsonData: this.realJsonData.filter(item => item.group === group),
311
- xAddFormLayout: 'horizontal'
312
- }
313
- })
314
- // 判断每一组得formJson 长度相加是否等于 realJsonData 长度 避免错误数据
315
- if (allGroup.reduce((total, item) => total + item.realJsonData.length, 0) === this.realJsonData.length) {
316
- return allGroup
317
- } else {
318
- return [{
319
- groupName: DEFAULT_GROUP_NAME,
320
- realJsonData: this.realJsonData,
321
- xAddFormLayout: 'horizontal'
322
- }]
323
- }
324
- },
325
- // 拥有自定义校验函数得表单项
326
- customValidateItems: function () {
327
- return this.formItems.filter((item) => {
328
- return item?.rule?.type === 'customJs'
329
- })
330
- },
331
- // 过滤出用于新增/修改场景的表单项
332
- groupJsonData: function () {
333
- return this.formItems.filter((item) => {
334
- return item.type === 'group'
335
- }).map((item) => {
336
- item.groupItems = item.groupItems.filter((item) => {
337
- return item.addOrEdit && item.addOrEdit !== 'no' && item.addOrEdit !== 'silenceAdd' && item.addOrEdit !== 'version' && !this.itemDisabled(item)
338
- }).map((groupItem) => {
339
- // 只保留第一个下划线后面的内容
340
- // 多层校验规则需要将prop设置为 key1.key2.....
341
- groupItem.prop = `${item.model}.${groupItem.model.substring(groupItem.model.indexOf('_') + 1)}`
342
- groupItem.model = groupItem.model.substring(groupItem.model.indexOf('_') + 1)
343
- return groupItem
344
- })
345
- return item
346
- }
347
- )
348
- },
349
- // 过滤出用于子表数据新增/修改场景的表单项
350
- childTableData: function () {
351
- return this.formItems.filter((item) => {
352
- return item.type === 'childTable'
353
- })
354
- },
355
- // 过滤出用于form子表数据新增/修改场景的表单项
356
- childFormData: function () {
357
- return this.formItems.filter((item) => {
358
- return item.type === 'rowEdit'
359
- })
360
- },
361
- // 过滤出用于静默新增场景的表单项
362
- silenceAddJsonData: function () {
363
- return this.formItems.filter(function (item) {
364
- return item.addOrEdit === 'silenceAdd'
365
- })
366
- },
367
- // 过滤出版本号表单项
368
- versionJsonData: function () {
369
- return this.formItems.filter(function (item) {
370
- return item.addOrEdit === 'version'
371
- })
372
- },
373
- formItemLayoutGen () {
374
- if (this.layout === 'simple-inline') {
375
- return {
376
- labelCol: { span: 0 },
377
- wrapperCol: { span: 24 }
378
- }
379
- }
380
- if (this.layout === 'horizontal') {
381
- // 如果启用了自定义配置,从 formItemLayout 读取(支持 0 值)
382
- if (this.enableHorizontalCustom && this.formItemLayout) {
383
- return {
384
- labelCol: {
385
- span: (this.formItemLayout.labelCol ?? 4),
386
- offset: (this.formItemLayout.offset ?? 2)
387
- },
388
- wrapperCol: { span: (this.formItemLayout.wrapperCol ?? 14) },
389
- }
390
- }
391
- // 默认配置
392
- return {
393
- labelCol: { span: 4, offset: 2 },
394
- wrapperCol: { span: 14 },
395
- }
396
- } else if (this.layout === 'vertical') {
397
- return {}
398
- } else {
399
- if (!this.formItemLayout.labelCol || !this.formItemLayout.wrapperCol) {
400
- return {
401
- labelCol: { span: 8 },
402
- wrapperCol: { span: 16 },
403
- }
404
- }
405
- return {
406
- labelCol: { span: this.formItemLayout.labelCol },
407
- wrapperCol: { span: this.formItemLayout.wrapperCol },
408
- }
409
- }
410
- },
411
- // simple-inline模式判断
412
- isSimpleInlineMode () {
413
- return this.layout === 'simple-inline' && this.simpleInline
414
- },
415
- // simple-inline布局行数据
416
- simpleInlineRows () {
417
- if (!this.isSimpleInlineMode) return []
418
- return this.simpleInline.rows.map(row => ({
419
- ...row,
420
- items: row.items.map(item => ({
421
- ...item,
422
- formItem: this.realJsonData.find(f =>
423
- f.model === item.key && f.name === item.title
424
- )
425
- })).filter(item => item.formItem)
426
- }))
427
- },
428
- ...mapState('account', { currUser: 'user' })
429
- },
430
- provide () {
431
- return {
432
- getComponentByName: this.getComponentByName,
433
- registerComponent: this.registerComponent,
434
- XFormContext: this,
435
- // 移除必填项
436
- removeRequired: this.removeRequired,
437
- // 设置必填项
438
- setRequired: this.setRequired,
439
- getSelf: () => this,
440
- }
441
- },
442
- watch: {
443
- form: {
444
- handler (val) {
445
- if (this.formDataChange && typeof this.formDataChange === 'function') {
446
- this.formDataChange(val)
447
- }
448
- },
449
- deep: true
450
- }
451
- },
452
- /** //todo 本来想要实现 配置 自定义函数时,表单项得红星提示,根据自定义校验函数得返回值来判断
453
- * 但是监听不到父组件formgorup得其他form得变化,所以暂时不实现
454
- */
455
- //
456
- // watch: {
457
- // form: {
458
- // handler (val) {
459
- // // 遍历表单配置
460
- // if (this.customValidateItems.length > 0) {
461
- // for (const item of this.customValidateItems) {
462
- // const itemIndex = this.formItems.findIndex(formItem => formItem.model === item.model)
463
- // if (itemIndex < 0) {
464
- // continue
465
- // }
466
- // try {
467
- // this.customJsValidate(null, val[item.model], (res) => {
468
- // // 如果返回error则设置错误信息
469
- // if (res instanceof Error) {
470
- // // 设置表单项的错误状态
471
- // this.$set(this.formItems[itemIndex], 'tempRequired', true)
472
- // } else {
473
- // // 清除错误状态
474
- // this.$set(this.formItems[itemIndex], 'tempRequired', true)
475
- // }
476
- // }, item)
477
- // } catch (e) {
478
- // console.error(e)
479
- // this.$set(this.formItems[itemIndex], 'tempRequired', true)
480
- // }
481
- // }
482
- // console.log('customValidateItems', JSON.stringify(this.customValidateItems))
483
- // }
484
- // },
485
- // deep: true
486
- // }
487
- // },
488
- mixins: [formValidationMixin],
489
- methods: {
490
- runLogic,
491
- getConfigByNameAsync,
492
- getConfigByName,
493
- init (params) {
494
- const {
495
- configName,
496
- configContent,
497
- formItems,
498
- formJson,
499
- viewMode,
500
- isHandleFormKey,
501
- isKeyHandle = true,
502
- showSubmitBtn = true,
503
- serviceName,
504
- primaryKey,
505
- modifyModelData = {},
506
- businessType,
507
- title,
508
- fixedAddForm = {},
509
- getDataParams = {},
510
- simpleFormJsonData = {},
511
- env = 'prod',
512
- layout,
513
- xAddFormLayout = 'horizontal',
514
- formItemLayout = {},
515
- btnName = '提交',
516
- childTablePriority = false,
517
- btnPlace = 'center',
518
- simpleInline = null,
519
- paramLogicName,
520
- paramLogicNameParam
521
- } = params
522
- this.loaded = false
523
- // 兼容需要省略 传递 layout: res.xAddFormLayout 可以使用 ...res 展开运算符 直接转递
524
- if (xAddFormLayout && layout === undefined) {
525
- this.layout = xAddFormLayout
526
- } else {
527
- this.layout = layout
528
- }
529
- this.formItemLayout = formItemLayout
530
- if ((isHandleFormKey === null || isHandleFormKey === undefined) && !isKeyHandle) {
531
- this.isHandleFormKey = isKeyHandle
532
- } else if (isHandleFormKey) {
533
- this.isHandleFormKey = isHandleFormKey
534
- } else {
535
- this.isHandleFormKey = isKeyHandle
536
- }
537
- this.childTablePriority = childTablePriority
538
- this.configName = configName
539
- this.configContent = configContent
540
- this.formItems = this.getFromItem(formItems, formJson)
541
- this.viewMode = viewMode
542
- this.showSubmitBtn = showSubmitBtn
543
- this.primaryKey = primaryKey
544
- this.serviceName = serviceName
545
- this.businessType = businessType
546
- this.title = title
547
- this.getDataParams = getDataParams
548
- this.simpleFormJsonData = simpleFormJsonData
549
- this.env = env
550
- this.btnName = btnName
551
- this.btnPlace = btnPlace
552
- this.simpleInline = simpleInline
553
- // 如果 fixedAddForm 有 selected_id 值,并且设置了处理表单key值,则多给 selected_id 加前缀 避免处理错误
554
- if (fixedAddForm.selected_id && this.isHandleFormKey) {
555
- fixedAddForm._selected_id = fixedAddForm.selected_id
556
- delete fixedAddForm.selected_id
557
- }
558
- // 设置普通表单项的相关参数
559
- const formData = Object.assign({}, fixedAddForm)
560
- if (paramLogicName) {
561
- runLogic(paramLogicName, paramLogicNameParam, this.serviceName).then(res => {
562
- Object.assign(formData, res)
563
- })
564
- }
565
- for (let i = 0; i < this.realJsonData.length; i++) {
566
- const item = this.realJsonData[i]
567
- this.setFormProps(formData, item, null)
568
- }
569
- // 设置表单分组项目相关参数
570
- for (let i = 0; i < this.groupJsonData.length; i++) {
571
- const groupItem = this.groupJsonData[i]
572
- formData[groupItem.model] = {}
573
- for (let j = 0; j < groupItem.groupItems.length; j++) {
574
- const item = groupItem.groupItems[j]
575
- this.setFormProps(formData[groupItem.model], item, item.prop)
576
- }
577
- }
578
- // 设置动态简易表单项的相关参数
579
- for (const key in this.simpleFormJsonData) {
580
- for (const item of this.simpleFormJsonData[key].value) {
581
- item.model = key + '@' + item.model
582
- this.setFormProps(formData, item, null)
583
- }
584
- }
585
-
586
- this.form = formData
587
- // 修改场景下对表单项赋值
588
- if (modifyModelData && modifyModelData.data) {
589
- this.modifyModelData = modifyModelData
590
- if (Object.keys(modifyModelData.data).length > 0) {
591
- this.getModifyModelData(modifyModelData)
592
- }
593
- }
594
- // 处理表单得附件
595
- if (modifyModelData && modifyModelData.files) {
596
- this.files = modifyModelData.files
597
- }
598
- if (modifyModelData && modifyModelData.images) {
599
- this.images = modifyModelData.images
600
- }
601
- this.loaded = true
602
- },
603
- scrollToGroup (index) {
604
- const groupElement = this.$refs[`group-title-${index}`][0]
605
- if (groupElement) {
606
- groupElement.scrollIntoView({ behavior: 'smooth' })
607
- }
608
- },
609
- registerComponent (componentName, component) {
610
- console.log('内部注册', this.$options.name, componentName)
611
- this.$refs[componentName] = component
612
- console.log('内部注册完成', this.$refs)
613
- },
614
- // 根据名字从注册到组件中获取组件
615
- getComponentByName (componentName) {
616
- console.log('内部取组件', this.$options.name, componentName)
617
- console.log('内部组件内容', this.$refs)
618
- return this.$refs[componentName]
619
- },
620
- // 兼容需要省略 传递 [formItems: res.formJson ] 可以使用 ...res 展开运算符 直接转递
621
- getFromItem (formItems, formJson) {
622
- const _formItems = formItems || formJson
623
- if (typeof formItems === 'string') {
624
- return JSON.parse(_formItems)
625
- } else {
626
- return JSON.parse(JSON.stringify(_formItems))
627
- }
628
- },
629
- innerXFormTableEmit (fun, record, id, actionType, index) {
630
- this.$emit(fun, record, id, actionType, index)
631
- },
632
- // 时间组件赋默认值
633
- // .type, item.formDefault
634
- getDateRange ({ type, formDefault: defaultValue, formValueFormat }) {
635
- // const format = type === 'datePicker' ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss'
636
- let format = 'YYYY-MM-DD HH:mm:ss'
637
- if (formValueFormat) {
638
- format = formValueFormat
639
- }
640
- let start
641
- switch (defaultValue) {
642
- case 'curYear':
643
- start = moment().startOf('year').format(format)
644
- break
645
- case 'curMonth':
646
- start = moment().startOf('month').format(format)
647
- break
648
- case 'curDay':
649
- start = moment().startOf('day').format(format)
650
- break
651
- case 'curTime':
652
- start = moment().format(format)
653
- break
654
- default:
655
- return defaultValue
656
- }
657
- return start
658
- },
659
- setFormProps (formData, item, groupItem) {
660
- const rulesKey = `${item.name}${item.model}`
661
- if (formData[item.model] === undefined || formData[item.model] === null) {
662
- formData[item.model] = undefined
663
- }
664
- if (!formData[item.model] && item.formDefault) {
665
- if (['datePicker', 'rangePicker', 'yearPicker', 'monthPicker', 'yearRangePicker', 'monthRangePicker'].includes(item.type)) {
666
- formData[item.model] = this.getDateRange(item)
667
- } else if (['treeSelect', 'select', 'checkbox'].includes(item.type) && ['curOrgId', 'curDepId', 'curUserId'].includes(item.formDefault)) {
668
- if (item.formDefault === 'curOrgId') {
669
- formData[item.model] = item.type === 'select' ? this.currUser.orgid : [this.currUser.orgid]
670
- }
671
- if (item.formDefault === 'curDepId') {
672
- formData[item.model] = item.type === 'select' ? this.currUser.depids : [this.currUser.depids]
673
- }
674
- if (item.formDefault === 'curUserId') {
675
- formData[item.model] = item.type === 'select' ? this.currUser.id : [this.currUser.id]
676
- }
677
- } else if (['addressSearch'].includes(item.type)) {
678
- formData[item.model] = item.formDefault
679
- formData[`${item.model}_lng_lat`] = item.formDefault_lng_lat
680
- } else {
681
- formData[item.model] = item.formDefault
682
- }
683
- }
684
- // 处理表单校验情况
685
- if (item.rule) {
686
- if (groupItem) {
687
- this.rules[groupItem] = []
688
- } else {
689
- this.rules[rulesKey] = []
690
- }
691
- const required = item.rule.required ? item.rule.required === true || item.rule.required === 'true' : false
692
- let trigger
693
- let message
694
- if (required) {
695
- switch (item.type) {
696
- case 'select':
697
- case 'checkbox':
698
- case 'radio':
699
- case 'treeSelect':
700
- case 'rangePicker':
701
- case 'monthPicker':
702
- case 'yearPicker':
703
- case 'datePicker':
704
- case 'file':
705
- case 'image':
706
- case 'citySelect':
707
- case 'addressSearch':
708
- case 'personSetting':
709
- message = '请选择' + item.name
710
- trigger = 'change'
711
- break
712
- default:
713
- message = '请输入' + item.name
714
- trigger = 'blur'
715
- }
716
- if (groupItem) {
717
- this.rules[groupItem].push({
718
- required: true,
719
- message: message,
720
- trigger: trigger
721
- })
722
- } else {
723
- this.rules[rulesKey].push({
724
- required: true,
725
- message: message,
726
- trigger: trigger
727
- })
728
- }
729
- }
730
-
731
- switch (item.rule.type) {
732
- case 'number':
733
- case 'integer':
734
- case 'float':
735
- // eslint-disable-next-line no-case-declarations
736
- let defaultValue
737
- // eslint-disable-next-line no-case-declarations
738
- let message
739
- switch (item.rule.type) {
740
- case 'number':
741
- item.numberInput = true
742
- message = '数字'
743
- defaultValue = 0
744
- break
745
- case 'integer':
746
- item.numberInput = true
747
- message = '整数'
748
- defaultValue = 0
749
- break
750
- case 'float':
751
- item.numberInput = true
752
- message = '小数'
753
- defaultValue = 0.0
754
- break
755
- }
756
- if (groupItem) {
757
- this.rules[groupItem].push({
758
- type: item.rule.type,
759
- message: item.name + '必须为' + message,
760
- transform: (value) => {
761
- if (value && value.length !== 0) {
762
- return Number(value)
763
- } else {
764
- return defaultValue
765
- }
766
- },
767
- trigger: 'blur'
768
- })
769
- } else {
770
- this.rules[rulesKey].push({
771
- type: item.rule.type,
772
- message: item.name + '必须为' + message,
773
- transform: (value) => {
774
- if (value && value.length !== 0) {
775
- return Number(value)
776
- } else {
777
- return defaultValue
778
- }
779
- },
780
- trigger: 'blur'
781
- })
782
- }
783
- break
784
- case 'email': {
785
- const validator = (rule, value, callback) => {
786
- if (value && !REG_EMAIL.test(value)) {
787
- callback(new Error('请输入正确的邮箱地址'))
788
- } else {
789
- callback()
790
- }
791
- }
792
- this.rules[groupItem || rulesKey].push({
793
- type: 'email',
794
- validator: validator,
795
- message: '请输入正确的邮箱地址',
796
- trigger: 'blur'
797
- })
798
- break
799
- }
800
- case 'userPhone': {
801
- this.rules[groupItem || rulesKey].push({
802
- type: 'userPhone',
803
- validator: (rule, value, callback) => {
804
- if (value && !REG_PHONE.test(value)) {
805
- callback(new Error('请输入正确的手机号码'))
806
- } else {
807
- callback()
808
- }
809
- },
810
- message: '请输入正确的手机号码',
811
- trigger: 'blur'
812
- })
813
- break
814
- }
815
- case 'idNumber': {
816
- this.rules[groupItem || rulesKey].push({
817
- validator: (rule, value, callback) => {
818
- if (value && !checkIdNumber(value)) {
819
- callback(new Error('请输入正确的身份证号码'))
820
- } else {
821
- callback()
822
- }
823
- },
824
- trigger: 'blur'
825
- })
826
- break
827
- }
828
- case 'landlineNumber': {
829
- this.rules[rulesKey].push({
830
- validator: (rule, value, callback) => {
831
- if (value && !REG_LANDLINE.test(value)) {
832
- callback(new Error('请输入正确的座机号码'))
833
- } else {
834
- callback()
835
- }
836
- },
837
- trigger: 'blur'
838
- })
839
- break
840
- }
841
- // 大于0
842
- case 'greaterThanZero': {
843
- item.numberInput = true
844
- this.rules[rulesKey].push({
845
- validator: (rule, value, callback) => {
846
- if (isNaN(value) || value <= 0) {
847
- callback(new Error('请输入一个大于0的数字'))
848
- } else {
849
- callback()
850
- }
851
- },
852
- trigger: 'blur'
853
- })
854
- break
855
- }
856
- // 大于等于0
857
- case 'greaterThanOrEqualZero': {
858
- item.numberInput = true
859
- this.rules[rulesKey].push({
860
- validator: (rule, value, callback) => {
861
- if (isNaN(value) || value < 0) {
862
- callback(new Error('请输入一个大于等于0的数字'))
863
- } else {
864
- callback()
865
- }
866
- },
867
- trigger: 'blur'
868
- })
869
- break
870
- }
871
- case 'stringLength': {
872
- this.rules[rulesKey].push({
873
- validator: (rule, value, callback) => {
874
- if (value && value.length < item.rule.minLen) {
875
- callback(new Error('长度不能少于' + item.rule.minLen + '个字符'))
876
- } else if (value && value.length > item.rule.maxLen) {
877
- callback(new Error('长度不能超过' + item.rule.maxLen + '个字符'))
878
- } else {
879
- callback()
880
- }
881
- },
882
- trigger: 'blur'
883
- })
884
- break
885
- }
886
- case 'customJs': {
887
- this.rules[rulesKey].push({
888
- validator: (rule, value, callback) => {
889
- this.customJsValidate(rule, value, callback, item)
890
- },
891
- trigger: 'blur'
892
- })
893
- break
894
- }
895
- }
896
- }
897
- },
898
- childTableMounted (item) {
899
- // 子表初始化时,设置表格数据
900
- if (this.form[item.model] && this.form[item.model].length > 0) {
901
- this.$refs[`childXFormTable_${item.model}`][0].setTableData(this.form[item.model])
902
- }
903
- },
904
- customJsValidate (rule, value, callback, item) {
905
- if (item.rule.customValidatorFunc) {
906
- executeStrFunctionByContext(this, item.rule.customValidatorFunc, [rule, value, callback, this.form, item, this.util, runLogic, getConfigByNameAsync])
907
- } else {
908
- callback()
909
- }
910
- },
911
- itemDisabled (value) {
912
- return (this.businessType === '新增' && value.addOrEdit === 'edit') ||
913
- (this.businessType === '修改' && value.addOrEdit === 'add')
914
- },
915
- readonly (value) {
916
- return value.addOrEdit === 'readonly'
917
- },
918
- async onSubmit () {
919
- const valid = await this.validateForm()
920
- if (!valid) return false
921
- if (this.viewMode) {
922
- this.$message.info('预览模式禁止新增和修改')
923
- return false
924
- }
925
- this.loading = true
926
- const requestForm = this.prepareForm()
927
- await this.appendSilenceAddFields(requestForm)
928
- const realForm = this.handleFormKeys(requestForm)
929
- // 增加子表数据
930
- if (this.childTableData.length > 0) {
931
- for (const item of this.childTableData) {
932
- const childModel = item.model
933
- const childDataRef = this.$refs['childXFormTable_' + item.model][0].getTableData()
934
- const childData = []
935
- for (const item of childDataRef) {
936
- childData.push(JSON.parse(JSON.stringify(item)))
937
- }
938
- for (let i = 0; i < childData.length; i++) {
939
- childData[i] = this.handleFormKeys(childData[i])
940
- // 外键不需要带表别名,所以此处放到表单处理后赋值
941
- if (realForm.id) {
942
- childData[i][item.childTableForeignKeyName] = realForm.id
943
- }
944
- }
945
- realForm[childModel] = childData
946
- }
947
- }
948
- // 增加form子表数据
949
- if (this.childFormData.length > 0) {
950
- for (const item of this.childFormData) {
951
- const childModel = item.model
952
- const childData = this.$refs[item.model].getTableData()
953
- for (let i = 0; i < childData.length; i++) {
954
- childData[i] = this.handleFormKeys(childData[i], true)
955
- // 外键不需要带表别名,所以此处放到表单处理后赋值
956
- if (realForm.id) {
957
- childData[i][item.foreignKey] = realForm.id
958
- }
959
- }
960
- realForm[childModel] = childData
961
- }
962
- }
963
- if (this.$listeners.onSubmit) {
964
- // 交由父级处理
965
- this.$emit('onSubmit', {
966
- businessType: this.businessType,
967
- serviceName: this.serviceName,
968
- realForm: realForm,
969
- currUserName: this.currUser.name,
970
- currUserId: this.currUser.id,
971
- orgId: this.currUser.orgid
972
- })
973
- } else {
974
- this.defaultSubmit(realForm)
975
- }
976
- },
977
-
978
- async asyncSubmit () {
979
- return new Promise((resolve, reject) => {
980
- this.$refs.selectForm.validate(async valid => {
981
- if (!valid) {
982
- reject(new Error('Form validation failed'))
983
- return
984
- }
985
- this.loading = true
986
- const requestForm = this.prepareForm()
987
- await this.appendSilenceAddFields(requestForm)
988
- const realForm = this.handleFormKeys(requestForm)
989
- resolve({
990
- realForm,
991
- businessType: this.businessType,
992
- serviceName: this.serviceName,
993
- currUserName: this.currUser.name,
994
- currUserId: this.currUser.id,
995
- orgId: this.currUser.orgid
996
- })
997
- })
998
- })
999
- },
1000
-
1001
- validateForm () {
1002
- return new Promise((resolve) => {
1003
- this.$refs.selectForm.validate(valid => resolve(valid))
1004
- })
1005
- },
1006
-
1007
- childTableFixedQueryForm (item) {
1008
- if (this.modifyModelData?.primaryKeyData) {
1009
- const fixedForm = {}
1010
- fixedForm[item.childTableForeignKeyName] = Object.values(this.modifyModelData.primaryKeyData)[0]
1011
- return fixedForm
1012
- }
1013
- return null
1014
- },
1015
-
1016
- prepareForm () {
1017
- const form = { ...this.form }
1018
- for (const key of Object.keys(form)) {
1019
- const value = form[key]
1020
- if (value === null || (typeof value === 'object' && Object.keys(value).length === 0)) {
1021
- form[key] = undefined
1022
- }
1023
- }
1024
- return form
1025
- },
1026
-
1027
- async appendSilenceAddFields (form) {
1028
- if (this.businessType === '新增') {
1029
- for (const item of this.silenceAddJsonData) {
1030
- switch (item.silencePurpose) {
1031
- case 'createTime':
1032
- form[item.model] = formatDate('now')
1033
- break
1034
- case 'operator':
1035
- form[item.model] = this.currUser.name
1036
- break
1037
- case 'operatorId':
1038
- form[item.model] = this.currUser.id
1039
- break
1040
- case 'orgId':
1041
- form[item.model] = this.currUser.orgid
1042
- break
1043
- case 'orgName':
1044
- form[item.model] = this.currUser.orgs
1045
- break
1046
- case 'depId':
1047
- form[item.model] = this.currUser.depids
1048
- break
1049
- case 'depName':
1050
- form[item.model] = this.currUser.deps
1051
- break
1052
- }
1053
- }
1054
- for (const item of this.silenceAddJsonData.filter((item) => item.silencePurpose === 'customize')) {
1055
- const result = await runLogic(item.silenceSource, form, this.serviceName)
1056
- if (result) {
1057
- const keys = Object.keys(result)
1058
- if (keys.length === 1 && keys[0] === 'value') {
1059
- form[item.model] = result.value
1060
- } else {
1061
- form[item.model] = result
1062
- }
1063
- } else {
1064
- form[item.model] = result
1065
- }
1066
- }
1067
- }
1068
- },
1069
-
1070
- handleFormKeys (form, mustHandleKey = false) {
1071
- const realForm = {}
1072
- for (const key of Object.keys(form)) {
1073
- const value = form[key]
1074
- const extraFormKeyTagIndex = key.indexOf('@')
1075
- if (extraFormKeyTagIndex !== -1) {
1076
- const extraFormKey = key.substring(0, extraFormKeyTagIndex)
1077
- const realKey = key.substring(extraFormKeyTagIndex + 1)
1078
- if (!realForm[extraFormKey]) {
1079
- realForm[extraFormKey] = {}
1080
- }
1081
- realForm[extraFormKey][realKey] = value
1082
- } else {
1083
- const realKey = this.isHandleFormKey || mustHandleKey ? this.getRealKey(key, mustHandleKey) : key
1084
- // 如果发生重名,不覆盖,把key的别名带上
1085
- if (realForm[realKey]) {
1086
- realForm[key] = value
1087
- } else {
1088
- realForm[realKey] = value
1089
- }
1090
- }
1091
- }
1092
- return realForm
1093
- },
1094
- // 默认提交事件
1095
- defaultSubmit (realForm, callback) {
1096
- // 新增移除id
1097
- if (this.businessType === '新增') {
1098
- delete realForm.id
1099
- }
1100
- // 组织请求
1101
- const requestParameters = {
1102
- queryParamsName: this.configName,
1103
- queryParams: this.configContent,
1104
- form: realForm,
1105
- businessType: this.businessType,
1106
- operator: this.currUser.name
1107
- }
1108
- addOrModify(requestParameters, this.serviceName, this.env === 'dev').then(data => {
1109
- this.$message.success(this.businessType + '成功!')
1110
- // commit
1111
- this.$emit('afterSubmit', { type: this.businessType, id: data.id, data: data, form: requestParameters.form })
1112
- this.loading = false
1113
- if (callback) {
1114
- callback()
1115
- }
1116
- }).catch(e => {
1117
- this.loading = false
1118
- this.$message.error(this.businessType + '失败:' + e)
1119
- })
1120
- },
1121
- // 获取表单字段实际值
1122
- getRealKey (key, mustHandleKey = false) {
1123
- if (key === 'selected_id') return key
1124
- if (this.isHandleFormKey || mustHandleKey) {
1125
- return key.substring(key.indexOf('_') + 1)
1126
- } else {
1127
- return key
1128
- }
1129
- },
1130
- /**
1131
- * 获取被修改记录数据
1132
- * @param modifyModelData 被修改记录的数据
1133
- */
1134
- getModifyModelData (modifyModelData) {
1135
- if (modifyModelData.primaryKeyData) {
1136
- this.form = Object.assign(this.form, modifyModelData.primaryKeyData)
1137
- }
1138
- // 对动态简易表单项特殊处理
1139
- for (const key in modifyModelData.data) {
1140
- const realKey = this.isHandleFormKey ? this.getRealKey(key) : key
1141
- if (this.simpleFormJsonData[realKey]) {
1142
- const extraForm = JSON.parse(modifyModelData.data[key])
1143
- for (const key in extraForm) {
1144
- const model = realKey + '@' + key
1145
- this.form[model] = extraForm[key]
1146
- }
1147
- }
1148
- }
1149
- // 对普通表单项处理
1150
- for (let i = 0; i < this.realJsonData.length; i++) {
1151
- if (['FilesId', 'Images'].includes(this.realJsonData[i])) {
1152
- // 附件需要跳过 因为会通过 modifyModelData中的files,images属性给upload赋值
1153
- // 新增修改表单每次提交时只会提交最新添加的文件
1154
- continue
1155
- }
1156
- const item = this.realJsonData[i]
1157
- // 地址选择器 需要传递 经纬度字段, 配置中添加 `${item.model}_lng_lat` CRUD 只需勾选 SQL生成查询项
1158
- if (['addressSearch'].includes(item.type)) {
1159
- this.form[item.model] = modifyModelData.data[item.model] + ''
1160
- this.form[`${item.model}_lng_lat`] = modifyModelData.data[`${item.model}_lng_lat`] + ''
1161
- continue
1162
- }
1163
- if (modifyModelData.data[item.model] || modifyModelData.data[item.model] === 0) {
1164
- if (modifyModelData.data[item.model] instanceof Array) {
1165
- this.form[item.model] = modifyModelData.data[item.model]
1166
- } else {
1167
- this.form[item.model] = modifyModelData.data[item.model] + ''
1168
- }
1169
- }
1170
- }
1171
- // 对分组表单进行处理
1172
- for (let i = 0; i < this.groupJsonData.length; i++) {
1173
- const item = this.groupJsonData[i]
1174
- try {
1175
- if (modifyModelData.data[item.model]) {
1176
- this.form[item.model] = JSON.parse(modifyModelData.data[item.model])
1177
- }
1178
- } catch (e) {
1179
- if (modifyModelData.data[item.model]) {
1180
- this.form[item.model] = modifyModelData.data[item.model]
1181
- }
1182
- }
1183
- }
1184
- // 追加版本号信息
1185
- for (const item of this.versionJsonData) {
1186
- if (!modifyModelData.data[item.model]) {
1187
- this.form[item.model] = 0
1188
- } else {
1189
- this.form[item.model] = modifyModelData.data[item.model] + ''
1190
- }
1191
- }
1192
- },
1193
- setForm (obj) {
1194
- this.form = Object.assign(this.form, obj)
1195
- // 给子表赋外键条件
1196
- if (this.childFormData.length > 0) {
1197
- for (const item of this.childFormData) {
1198
- const child = this.$refs[item.model]
1199
- // 获取子表别名,以便在条件上添加别名
1200
- const alias = child.realQueryConfig.tableAliasName
1201
- // 有主键,且主键有值,添加主键条件
1202
- if (this.primaryKey && this.form[this.primaryKey]) {
1203
- const foreignKey = item.foreignKey
1204
- const fixedQueryForm = { [alias + '_' + foreignKey]: this.form[this.primaryKey] }
1205
- if (!child.fixedQueryForm) {
1206
- child.fixedQueryForm = fixedQueryForm
1207
- } else {
1208
- Object.assign(child.fixedQueryForm, fixedQueryForm)
1209
- }
1210
- child.refreshTable()
1211
- }
1212
- }
1213
- }
1214
- },
1215
- setFormWithKey (obj) {
1216
- setDataByRealKey(this.form, obj)
1217
- },
1218
- setFormWithNoKey (obj) {
1219
- setDataByRealKey(this.form, obj)
1220
- },
1221
- emitFunc (func, data, value) {
1222
- this.$emit(func, data, value)
1223
- this.$emit('x-form-item-emit-func', func, data, value)
1224
- },
1225
- // 直接转发事件的函数
1226
- emitEvent (event, ...args) {
1227
- this.$emit(event, ...args)
1228
- },
1229
- close () {
1230
- this.loaded = false
1231
- },
1232
- /**
1233
- * 行选择事件
1234
- * @param row 选中行集合
1235
- * @param attr 表单项属性
1236
- */
1237
- async rowChoose (row, attr, callback) {
1238
- // 如果配置了自定义函数
1239
- if (attr.dataChangeFunc) {
1240
- await executeStrFunction(attr.dataChangeFunc, [this.form, this.setForm, {
1241
- ...attr,
1242
- selectRows: row
1243
- }, util, this.mode, runLogic, getConfigByNameAsync])
1244
- } else {
1245
- // 默认填充选中行数据到当前表单
1246
- setDataByRealKey(this.form, row[0])
1247
- }
1248
- if (callback) {
1249
- callback()
1250
- }
1251
- },
1252
- }
1253
- }
1254
- </script>
1255
-
1256
- <style scoped lang="less">
1257
- :deep(.ant-form-inline .ant-form-item ) {
1258
- display: block !important;
1259
- }
1260
-
1261
- :deep(.ant-form-item-with-help) {
1262
- margin-bottom: 0;
1263
- }
1264
-
1265
- .xFormGroupTitle {
1266
- font-weight: bold;
1267
- color: @primary-color;
1268
- }
1269
-
1270
- .simple-inline-item {
1271
- max-width: 100% !important;
1272
- }
1273
-
1274
- /* simple-inline模式样式 */
1275
- :deep(.simple-inline-item .ant-form-item) {
1276
- margin: 0 !important;
1277
- padding: 2px !important;
1278
-
1279
- .ant-form-item-label {
1280
- display: none !important;
1281
- }
1282
-
1283
- .ant-form-item-control-wrapper,
1284
- .ant-form-item-control {
1285
- width: 100% !important;
1286
- }
1287
- }
1288
- </style>
1
+ <template>
2
+ <div id="XAddNativeForm">
3
+ <a-form-model
4
+ v-if="loaded"
5
+ ref="selectForm"
6
+ :zIndex="1001"
7
+ :model="form"
8
+ v-bind="formItemLayoutGen"
9
+ :layout="layout">
10
+ <template v-for="(item, key) in childTableData">
11
+ <a-row
12
+ v-if="childTablePriority"
13
+ :gutter="16"
14
+ :key="'childTableRow' + key">
15
+ <a-card :title="item.name" :bordered="false" size="small">
16
+ <x-form-table
17
+ :key="'childTable_' + item.model"
18
+ :title="item.name"
19
+ :queryParamsName="item.childTableConfigName"
20
+ :localEditMode="true"
21
+ :fixed-query-form="childTableFixedQueryForm(item)"
22
+ :service-name="serviceName"
23
+ @innerXFormTableEmit="innerXFormTableEmit"
24
+ @afterTableInit="childTableMounted(item)"
25
+ :ref="'childXFormTable_' + item.model">
26
+ </x-form-table>
27
+ </a-card>
28
+ </a-row>
29
+ </template>
30
+ <template v-if="isSimpleInlineMode">
31
+ <a-row
32
+ v-for="(row, rowIndex) in simpleInlineRows"
33
+ :key="'simple-row-' + rowIndex"
34
+ :gutter="0"
35
+ type="flex">
36
+ <a-col
37
+ v-for="(item, itemIndex) in row.items"
38
+ :key="'simple-item-' + itemIndex"
39
+ :span="item.span">
40
+ <x-form-item
41
+ class="simple-inline-item"
42
+ :attr="item.formItem"
43
+ :disabled="itemDisabled(item.formItem)"
44
+ :read-only="readonly(item.formItem)"
45
+ :files="files"
46
+ :form="form"
47
+ :images="images"
48
+ :service-name="serviceName"
49
+ mode="新增/修改"
50
+ layout="simple-inline"
51
+ :rules="rules[`${item.formItem.name}${item.formItem.model}`]"
52
+ :get-data-params="getDataParams"
53
+ :env="env"
54
+ :enablePopupToBody="enablePopupToBody"
55
+ @x-form-item-emit-func="emitFunc"
56
+ @rowChoose="rowChoose"
57
+ :setForm="setForm"
58
+ :style="{ margin: 0, padding: '2px' }"
59
+ />
60
+ </a-col>
61
+ </a-row>
62
+ </template>
63
+ <a-row ref="GroupItemRow" v-if="!isSimpleInlineMode">
64
+ <a-col :span="3" v-if="!inXFormGroup && !(groups[0].groupName === DEFAULT_GROUP_NAME)">
65
+ <a-tabs tab-position="left" v-model="activeTab" @change="scrollToGroup">
66
+ <a-tab-pane
67
+ v-for="(groupsItem,groupsIndex) in groups"
68
+ :tab="groupsItem.groupName"
69
+ :key="groupsIndex">
70
+ </a-tab-pane>
71
+ </a-tabs>
72
+ </a-col>
73
+ <a-col
74
+ :span="(!inXFormGroup && !(groups[0].groupName === DEFAULT_GROUP_NAME)) ? 21: 24">
75
+ <a-row
76
+ :gutter="16"
77
+ type="flex"
78
+ :key="groupsIndex"
79
+ v-for="(groupsItem,groupsIndex) in groups"
80
+ >
81
+ <a-col
82
+ :span="24"
83
+ :style="{ marginTop: groupsIndex === 0 ? '' : '8px',fontSize:inXFormGroup?'15px':'14px', marginLeft:'-5px' }"
84
+ v-if="groupsItem.groupName !== DEFAULT_GROUP_NAME">
85
+ <span class="xFormGroupTitle" :ref="`group-title-${groupsIndex}`">{{ groupsItem.groupName }}</span>
86
+ </a-col>
87
+ <x-form-item
88
+ v-for="(item, index) in groupsItem.realJsonData"
89
+ :key="index"
90
+ :attr="item"
91
+ :disabled="itemDisabled(item)"
92
+ :read-only="readonly(item)"
93
+ :files="files"
94
+ v-bind="formItemLayoutGen"
95
+ :style="layout === 'inline' ? { marginTop:'5px' } : undefined"
96
+ :form="form"
97
+ :images="images"
98
+ :enablePopupToBody="enablePopupToBody"
99
+ :service-name="serviceName"
100
+ mode="新增/修改"
101
+ :layout="layout"
102
+ :rules="rules[`${item.name}${item.model}`]"
103
+ :get-data-params="getDataParams"
104
+ :env="env"
105
+ @x-form-item-emit-func="emitFunc"
106
+ @rowChoose="rowChoose"
107
+ :setForm="setForm"
108
+ />
109
+ </a-row>
110
+ </a-col>
111
+ </a-row>
112
+ <a-row :gutter="16" v-for="(groupItem, groupIndex) in groupJsonData" :key="groupIndex" v-if="!isSimpleInlineMode">
113
+ <a-card v-if="groupItem.groupItems.length > 0" :title="groupItem.name" :bordered="false" size="small">
114
+ <x-form-item
115
+ v-for="(item, index) in groupItem.groupItems"
116
+ :key="index"
117
+ :attr="item"
118
+ :disabled="itemDisabled(item)"
119
+ :readonly="readonly(item)"
120
+ :files="files"
121
+ v-bind="formItemLayoutGen"
122
+ :style="layout ==='inline'?{marginTop:'5px'}:undefined"
123
+ :form="form[groupItem.model]"
124
+ :images="images"
125
+ :service-name="serviceName"
126
+ mode="新增/修改"
127
+ :rules="rules[`${item.name}${item.model}`]"
128
+ :get-data-params="getDataParams"
129
+ :env="env"
130
+ :setForm="setForm"
131
+ @rowChoose="rowChoose"
132
+ />
133
+ </a-card>
134
+ <template v-else>
135
+ <slot
136
+ name="groupFormItems"
137
+ :form="form"
138
+ :model="groupItem.model"
139
+ :rules="rules"
140
+ :modifyModelData="modifyModelData"></slot>
141
+ </template>
142
+ </a-row>
143
+ <a-row :gutter="16" v-for="(item, key) in simpleFormJsonData" :key="'row' + key" v-if="!isSimpleInlineMode">
144
+ <a-card v-if="item.value.length > 0" :title="item.name" :bordered="false" size="small">
145
+ <x-form-item
146
+ v-for="(formItem, formItemIndex) in item.value"
147
+ :key="key + formItemIndex"
148
+ :attr="formItem"
149
+ :disabled="itemDisabled(formItem)"
150
+ :readonly="readonly(formItem)"
151
+ :files="files"
152
+ :enablePopupToBody="enablePopupToBody"
153
+ v-bind="formItemLayoutGen"
154
+ :style="layout ==='inline'?{marginTop:'5px'}:undefined"
155
+ :form="form[groupItem.model]"
156
+ :images="images"
157
+ :service-name="serviceName"
158
+ mode="新增/修改"
159
+ :rules="rules[`${item.name}${item.model}`]"
160
+ :get-data-params="getDataParams"
161
+ :env="env"
162
+ :setForm="setForm"
163
+ @rowChoose="rowChoose"
164
+ />
165
+ </a-card>
166
+ </a-row>
167
+ <template v-for="(item, key) in childTableData">
168
+ <a-row
169
+ v-if="!childTablePriority"
170
+ :gutter="16"
171
+ :key="'childTableRow' + key">
172
+ <a-card :title="item.name" :bordered="false" size="small">
173
+ <x-form-table
174
+ :key="'childTable_' + item.model"
175
+ :title="item.name"
176
+ :queryParamsName="item.childTableConfigName"
177
+ :localEditMode="true"
178
+ @innerXFormTableEmit="innerXFormTableEmit"
179
+ :fixed-query-form="childTableFixedQueryForm(item)"
180
+ :service-name="serviceName"
181
+ @afterTableInit="childTableMounted(item)"
182
+ :ref="'childXFormTable_' + item.model">
183
+ </x-form-table>
184
+ </a-card>
185
+ </a-row>
186
+ </template>
187
+ <a-row type="flex" :justify="btnPlace" :style="{paddingLeft: '16px',paddingRight: '16px'}">
188
+ <slot name="footer" :loading="loading">
189
+ <a-button v-if="showSubmitBtn" :loading="loading" type="primary" @click="onSubmit()">{{ btnName }}</a-button>
190
+ </slot>
191
+ </a-row>
192
+ </a-form-model>
193
+ </div>
194
+ </template>
195
+ <script>
196
+ import XFormItem from '@vue2-client/base-client/components/common/XForm/XFormItem'
197
+ import { formatDate, setDataByRealKey } from '@vue2-client/utils/util'
198
+ import * as util from '@vue2-client/utils/util'
199
+ import { mapState } from 'vuex'
200
+ import { addOrModify, getConfigByName, getConfigByNameAsync, runLogic } from '@vue2-client/services/api/common'
201
+ import { checkIdNumber, REG_EMAIL, REG_LANDLINE, REG_PHONE } from '@vue2-client/utils/reg'
202
+ import moment from 'moment/moment'
203
+ import { executeStrFunction, executeStrFunctionByContext } from '@vue2-client/utils/runEvalFunction'
204
+ import formValidationMixin from '@vue2-client/mixins/formValidationMixin'
205
+
206
+ const DEFAULT_GROUP_NAME = '__default__'
207
+ export default {
208
+ name: 'XAddNativeForm',
209
+ components: {
210
+ XFormItem,
211
+ XFormTable: () => import('@vue2-client/base-client/components/common/XFormTable/XFormTable.vue')
212
+ },
213
+ inject: {
214
+ inXFormGroup: {
215
+ default: false
216
+ },
217
+ formGroupContext: {
218
+ default: null
219
+ },
220
+ formDataChange: {
221
+ default: null
222
+ }
223
+ },
224
+ props: {
225
+ // 是否启用 horizontal 模式的自定义配置
226
+ enableHorizontalCustom: {
227
+ type: Boolean,
228
+ default: false
229
+ },
230
+ // 是否启用时间弹出到最外层
231
+ enablePopupToBody: {
232
+ type: Boolean,
233
+ default: false
234
+ }
235
+ },
236
+ data () {
237
+ return {
238
+ DEFAULT_GROUP_NAME,
239
+ // 预览模式
240
+ viewMode: false,
241
+ // 是否处理表单Key值
242
+ isHandleFormKey: true,
243
+ // 内容加载是否完成
244
+ loaded: false,
245
+ // 业务类型
246
+ businessType: '',
247
+ // 业务标题
248
+ title: '',
249
+ // 新增或修改业务是否执行中
250
+ loading: false,
251
+ // 表单Model
252
+ form: {},
253
+ // 配置名称
254
+ configName: undefined,
255
+ // 配置内容,用于查询配置生成器的预览
256
+ configContent: undefined,
257
+ // 表单项集合
258
+ formItems: [],
259
+ // 服务名称
260
+ serviceName: undefined,
261
+ // 是否显示提交按钮
262
+ showSubmitBtn: true,
263
+ // 修改有文件的表单时使用
264
+ files: [],
265
+ images: [],
266
+ // 校验
267
+ rules: {},
268
+ // 调用logic获取数据源的追加参数
269
+ getDataParams: {},
270
+ // 动态简易表单集合
271
+ simpleFormJsonData: {},
272
+ // 待修改的数据集
273
+ modifyModelData: {},
274
+ // 当前环境
275
+ env: 'prod',
276
+ // 表单主键
277
+ primaryKey: null,
278
+ // 表单模式 horizontal | vertical | inline
279
+ layout: 'horizontal',
280
+ // 提交按钮名称
281
+ btnName: '提交',
282
+ // 提交按钮位置 start / center / end
283
+ btnPlace: 'center',
284
+ // 子表是否排在前面
285
+ childTablePriority: false,
286
+ // simple-inline布局配置
287
+ simpleInline: null
288
+ }
289
+ },
290
+ computed: {
291
+ // 过滤出用于新增/修改场景的表单项
292
+ realJsonData: function () {
293
+ return this.formItems.filter((item) => {
294
+ return item.addOrEdit && item.addOrEdit !== 'no' && item.addOrEdit !== 'silenceAdd' && item.addOrEdit !== 'version' && !this.itemDisabled(item)
295
+ })
296
+ },
297
+ // 表单项组 / 不是 数据组
298
+ groups: function () {
299
+ if (!this.realJsonData || this.realJsonData.length === 0) {
300
+ return [{
301
+ groupName: DEFAULT_GROUP_NAME,
302
+ realJsonData: this.realJsonData,
303
+ xAddFormLayout: 'horizontal'
304
+ }]
305
+ }
306
+ const uniqueGroups = new Set(this.realJsonData.map(item => item.group).filter(Boolean))
307
+ const allGroup = Array.from(uniqueGroups).map(group => {
308
+ return {
309
+ groupName: group,
310
+ realJsonData: this.realJsonData.filter(item => item.group === group),
311
+ xAddFormLayout: 'horizontal'
312
+ }
313
+ })
314
+ // 判断每一组得formJson 长度相加是否等于 realJsonData 长度 避免错误数据
315
+ if (allGroup.reduce((total, item) => total + item.realJsonData.length, 0) === this.realJsonData.length) {
316
+ return allGroup
317
+ } else {
318
+ return [{
319
+ groupName: DEFAULT_GROUP_NAME,
320
+ realJsonData: this.realJsonData,
321
+ xAddFormLayout: 'horizontal'
322
+ }]
323
+ }
324
+ },
325
+ // 拥有自定义校验函数得表单项
326
+ customValidateItems: function () {
327
+ return this.formItems.filter((item) => {
328
+ return item?.rule?.type === 'customJs'
329
+ })
330
+ },
331
+ // 过滤出用于新增/修改场景的表单项
332
+ groupJsonData: function () {
333
+ return this.formItems.filter((item) => {
334
+ return item.type === 'group'
335
+ }).map((item) => {
336
+ item.groupItems = item.groupItems.filter((item) => {
337
+ return item.addOrEdit && item.addOrEdit !== 'no' && item.addOrEdit !== 'silenceAdd' && item.addOrEdit !== 'version' && !this.itemDisabled(item)
338
+ }).map((groupItem) => {
339
+ // 只保留第一个下划线后面的内容
340
+ // 多层校验规则需要将prop设置为 key1.key2.....
341
+ groupItem.prop = `${item.model}.${groupItem.model.substring(groupItem.model.indexOf('_') + 1)}`
342
+ groupItem.model = groupItem.model.substring(groupItem.model.indexOf('_') + 1)
343
+ return groupItem
344
+ })
345
+ return item
346
+ }
347
+ )
348
+ },
349
+ // 过滤出用于子表数据新增/修改场景的表单项
350
+ childTableData: function () {
351
+ return this.formItems.filter((item) => {
352
+ return item.type === 'childTable'
353
+ })
354
+ },
355
+ // 过滤出用于form子表数据新增/修改场景的表单项
356
+ childFormData: function () {
357
+ return this.formItems.filter((item) => {
358
+ return item.type === 'rowEdit'
359
+ })
360
+ },
361
+ // 过滤出用于静默新增场景的表单项
362
+ silenceAddJsonData: function () {
363
+ return this.formItems.filter(function (item) {
364
+ return item.addOrEdit === 'silenceAdd'
365
+ })
366
+ },
367
+ // 过滤出版本号表单项
368
+ versionJsonData: function () {
369
+ return this.formItems.filter(function (item) {
370
+ return item.addOrEdit === 'version'
371
+ })
372
+ },
373
+ formItemLayoutGen () {
374
+ if (this.layout === 'simple-inline') {
375
+ return {
376
+ labelCol: { span: 0 },
377
+ wrapperCol: { span: 24 }
378
+ }
379
+ }
380
+ if (this.layout === 'horizontal') {
381
+ // 如果启用了自定义配置,从 formItemLayout 读取(支持 0 值)
382
+ if (this.enableHorizontalCustom && this.formItemLayout) {
383
+ return {
384
+ labelCol: {
385
+ span: (this.formItemLayout.labelCol ?? 4),
386
+ offset: (this.formItemLayout.offset ?? 2)
387
+ },
388
+ wrapperCol: { span: (this.formItemLayout.wrapperCol ?? 14) },
389
+ }
390
+ }
391
+ // 默认配置
392
+ return {
393
+ labelCol: { span: 4, offset: 2 },
394
+ wrapperCol: { span: 14 },
395
+ }
396
+ } else if (this.layout === 'vertical') {
397
+ return {}
398
+ } else {
399
+ if (!this.formItemLayout.labelCol || !this.formItemLayout.wrapperCol) {
400
+ return {
401
+ labelCol: { span: 8 },
402
+ wrapperCol: { span: 16 },
403
+ }
404
+ }
405
+ return {
406
+ labelCol: { span: this.formItemLayout.labelCol },
407
+ wrapperCol: { span: this.formItemLayout.wrapperCol },
408
+ }
409
+ }
410
+ },
411
+ // simple-inline模式判断
412
+ isSimpleInlineMode () {
413
+ return this.layout === 'simple-inline' && this.simpleInline
414
+ },
415
+ // simple-inline布局行数据
416
+ simpleInlineRows () {
417
+ if (!this.isSimpleInlineMode) return []
418
+ return this.simpleInline.rows.map(row => ({
419
+ ...row,
420
+ items: row.items.map(item => ({
421
+ ...item,
422
+ formItem: this.realJsonData.find(f =>
423
+ f.model === item.key && f.name === item.title
424
+ )
425
+ })).filter(item => item.formItem)
426
+ }))
427
+ },
428
+ ...mapState('account', { currUser: 'user' })
429
+ },
430
+ provide () {
431
+ return {
432
+ getComponentByName: this.getComponentByName,
433
+ registerComponent: this.registerComponent,
434
+ XFormContext: this,
435
+ // 移除必填项
436
+ removeRequired: this.removeRequired,
437
+ // 设置必填项
438
+ setRequired: this.setRequired,
439
+ getSelf: () => this,
440
+ }
441
+ },
442
+ watch: {
443
+ form: {
444
+ handler (val) {
445
+ if (this.formDataChange && typeof this.formDataChange === 'function') {
446
+ this.formDataChange(val)
447
+ }
448
+ },
449
+ deep: true
450
+ }
451
+ },
452
+ /** //todo 本来想要实现 配置 自定义函数时,表单项得红星提示,根据自定义校验函数得返回值来判断
453
+ * 但是监听不到父组件formgorup得其他form得变化,所以暂时不实现
454
+ */
455
+ //
456
+ // watch: {
457
+ // form: {
458
+ // handler (val) {
459
+ // // 遍历表单配置
460
+ // if (this.customValidateItems.length > 0) {
461
+ // for (const item of this.customValidateItems) {
462
+ // const itemIndex = this.formItems.findIndex(formItem => formItem.model === item.model)
463
+ // if (itemIndex < 0) {
464
+ // continue
465
+ // }
466
+ // try {
467
+ // this.customJsValidate(null, val[item.model], (res) => {
468
+ // // 如果返回error则设置错误信息
469
+ // if (res instanceof Error) {
470
+ // // 设置表单项的错误状态
471
+ // this.$set(this.formItems[itemIndex], 'tempRequired', true)
472
+ // } else {
473
+ // // 清除错误状态
474
+ // this.$set(this.formItems[itemIndex], 'tempRequired', true)
475
+ // }
476
+ // }, item)
477
+ // } catch (e) {
478
+ // console.error(e)
479
+ // this.$set(this.formItems[itemIndex], 'tempRequired', true)
480
+ // }
481
+ // }
482
+ // console.log('customValidateItems', JSON.stringify(this.customValidateItems))
483
+ // }
484
+ // },
485
+ // deep: true
486
+ // }
487
+ // },
488
+ mixins: [formValidationMixin],
489
+ methods: {
490
+ runLogic,
491
+ getConfigByNameAsync,
492
+ getConfigByName,
493
+ init (params) {
494
+ const {
495
+ configName,
496
+ configContent,
497
+ formItems,
498
+ formJson,
499
+ viewMode,
500
+ isHandleFormKey,
501
+ isKeyHandle = true,
502
+ showSubmitBtn = true,
503
+ serviceName,
504
+ primaryKey,
505
+ modifyModelData = {},
506
+ businessType,
507
+ title,
508
+ fixedAddForm = {},
509
+ getDataParams = {},
510
+ simpleFormJsonData = {},
511
+ env = 'prod',
512
+ layout,
513
+ xAddFormLayout = 'horizontal',
514
+ formItemLayout = {},
515
+ btnName = '提交',
516
+ childTablePriority = false,
517
+ btnPlace = 'center',
518
+ simpleInline = null,
519
+ paramLogicName,
520
+ paramLogicNameParam
521
+ } = params
522
+ this.loaded = false
523
+ // 兼容需要省略 传递 layout: res.xAddFormLayout 可以使用 ...res 展开运算符 直接转递
524
+ if (xAddFormLayout && layout === undefined) {
525
+ this.layout = xAddFormLayout
526
+ } else {
527
+ this.layout = layout
528
+ }
529
+ this.formItemLayout = formItemLayout
530
+ if ((isHandleFormKey === null || isHandleFormKey === undefined) && !isKeyHandle) {
531
+ this.isHandleFormKey = isKeyHandle
532
+ } else if (isHandleFormKey) {
533
+ this.isHandleFormKey = isHandleFormKey
534
+ } else {
535
+ this.isHandleFormKey = isKeyHandle
536
+ }
537
+ this.childTablePriority = childTablePriority
538
+ this.configName = configName
539
+ this.configContent = configContent
540
+ this.formItems = this.getFromItem(formItems, formJson)
541
+ this.viewMode = viewMode
542
+ this.showSubmitBtn = showSubmitBtn
543
+ this.primaryKey = primaryKey
544
+ this.serviceName = serviceName
545
+ this.businessType = businessType
546
+ this.title = title
547
+ this.getDataParams = getDataParams
548
+ this.simpleFormJsonData = simpleFormJsonData
549
+ this.env = env
550
+ this.btnName = btnName
551
+ this.btnPlace = btnPlace
552
+ this.simpleInline = simpleInline
553
+ // 如果 fixedAddForm 有 selected_id 值,并且设置了处理表单key值,则多给 selected_id 加前缀 避免处理错误
554
+ if (fixedAddForm.selected_id && this.isHandleFormKey) {
555
+ fixedAddForm._selected_id = fixedAddForm.selected_id
556
+ delete fixedAddForm.selected_id
557
+ }
558
+ // 设置普通表单项的相关参数
559
+ const formData = Object.assign({}, fixedAddForm)
560
+ if (paramLogicName) {
561
+ runLogic(paramLogicName, paramLogicNameParam, this.serviceName).then(res => {
562
+ Object.assign(formData, res)
563
+ })
564
+ }
565
+ for (let i = 0; i < this.realJsonData.length; i++) {
566
+ const item = this.realJsonData[i]
567
+ this.setFormProps(formData, item, null)
568
+ }
569
+ // 设置表单分组项目相关参数
570
+ for (let i = 0; i < this.groupJsonData.length; i++) {
571
+ const groupItem = this.groupJsonData[i]
572
+ formData[groupItem.model] = {}
573
+ for (let j = 0; j < groupItem.groupItems.length; j++) {
574
+ const item = groupItem.groupItems[j]
575
+ this.setFormProps(formData[groupItem.model], item, item.prop)
576
+ }
577
+ }
578
+ // 设置动态简易表单项的相关参数
579
+ for (const key in this.simpleFormJsonData) {
580
+ for (const item of this.simpleFormJsonData[key].value) {
581
+ item.model = key + '@' + item.model
582
+ this.setFormProps(formData, item, null)
583
+ }
584
+ }
585
+
586
+ this.form = formData
587
+ // 修改场景下对表单项赋值
588
+ if (modifyModelData && modifyModelData.data) {
589
+ this.modifyModelData = modifyModelData
590
+ if (Object.keys(modifyModelData.data).length > 0) {
591
+ this.getModifyModelData(modifyModelData)
592
+ }
593
+ }
594
+ // 处理表单得附件
595
+ if (modifyModelData && modifyModelData.files) {
596
+ this.files = modifyModelData.files
597
+ }
598
+ if (modifyModelData && modifyModelData.images) {
599
+ this.images = modifyModelData.images
600
+ }
601
+ this.loaded = true
602
+ },
603
+ scrollToGroup (index) {
604
+ const groupElement = this.$refs[`group-title-${index}`][0]
605
+ if (groupElement) {
606
+ groupElement.scrollIntoView({ behavior: 'smooth' })
607
+ }
608
+ },
609
+ registerComponent (componentName, component) {
610
+ console.log('内部注册', this.$options.name, componentName)
611
+ this.$refs[componentName] = component
612
+ console.log('内部注册完成', this.$refs)
613
+ },
614
+ // 根据名字从注册到组件中获取组件
615
+ getComponentByName (componentName) {
616
+ console.log('内部取组件', this.$options.name, componentName)
617
+ console.log('内部组件内容', this.$refs)
618
+ return this.$refs[componentName]
619
+ },
620
+ // 兼容需要省略 传递 [formItems: res.formJson ] 可以使用 ...res 展开运算符 直接转递
621
+ getFromItem (formItems, formJson) {
622
+ const _formItems = formItems || formJson
623
+ if (typeof formItems === 'string') {
624
+ return JSON.parse(_formItems)
625
+ } else {
626
+ return JSON.parse(JSON.stringify(_formItems))
627
+ }
628
+ },
629
+ innerXFormTableEmit (fun, record, id, actionType, index) {
630
+ this.$emit(fun, record, id, actionType, index)
631
+ },
632
+ // 时间组件赋默认值
633
+ // .type, item.formDefault
634
+ getDateRange ({ type, formDefault: defaultValue, formValueFormat }) {
635
+ // const format = type === 'datePicker' ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss'
636
+ let format = 'YYYY-MM-DD HH:mm:ss'
637
+ if (formValueFormat) {
638
+ format = formValueFormat
639
+ }
640
+ let start
641
+ switch (defaultValue) {
642
+ case 'curYear':
643
+ start = moment().startOf('year').format(format)
644
+ break
645
+ case 'curMonth':
646
+ start = moment().startOf('month').format(format)
647
+ break
648
+ case 'curDay':
649
+ start = moment().startOf('day').format(format)
650
+ break
651
+ case 'curTime':
652
+ start = moment().format(format)
653
+ break
654
+ default:
655
+ return defaultValue
656
+ }
657
+ return start
658
+ },
659
+ setFormProps (formData, item, groupItem) {
660
+ const rulesKey = `${item.name}${item.model}`
661
+ if (formData[item.model] === undefined || formData[item.model] === null) {
662
+ formData[item.model] = undefined
663
+ }
664
+ if (!formData[item.model] && item.formDefault) {
665
+ if (['datePicker', 'rangePicker', 'yearPicker', 'monthPicker', 'yearRangePicker', 'monthRangePicker'].includes(item.type)) {
666
+ formData[item.model] = this.getDateRange(item)
667
+ } else if (['treeSelect', 'select', 'checkbox'].includes(item.type) && ['curOrgId', 'curDepId', 'curUserId'].includes(item.formDefault)) {
668
+ if (item.formDefault === 'curOrgId') {
669
+ formData[item.model] = item.type === 'select' ? this.currUser.orgid : [this.currUser.orgid]
670
+ }
671
+ if (item.formDefault === 'curDepId') {
672
+ formData[item.model] = item.type === 'select' ? this.currUser.depids : [this.currUser.depids]
673
+ }
674
+ if (item.formDefault === 'curUserId') {
675
+ formData[item.model] = item.type === 'select' ? this.currUser.id : [this.currUser.id]
676
+ }
677
+ } else if (['addressSearch'].includes(item.type)) {
678
+ formData[item.model] = item.formDefault
679
+ formData[`${item.model}_lng_lat`] = item.formDefault_lng_lat
680
+ } else {
681
+ formData[item.model] = item.formDefault
682
+ }
683
+ }
684
+ // 处理表单校验情况
685
+ if (item.rule) {
686
+ if (groupItem) {
687
+ this.rules[groupItem] = []
688
+ } else {
689
+ this.rules[rulesKey] = []
690
+ }
691
+ const required = item.rule.required ? item.rule.required === true || item.rule.required === 'true' : false
692
+ let trigger
693
+ let message
694
+ if (required) {
695
+ switch (item.type) {
696
+ case 'select':
697
+ case 'checkbox':
698
+ case 'radio':
699
+ case 'treeSelect':
700
+ case 'rangePicker':
701
+ case 'monthPicker':
702
+ case 'yearPicker':
703
+ case 'datePicker':
704
+ case 'file':
705
+ case 'image':
706
+ case 'citySelect':
707
+ case 'addressSearch':
708
+ case 'personSetting':
709
+ message = '请选择' + item.name
710
+ trigger = 'change'
711
+ break
712
+ default:
713
+ message = '请输入' + item.name
714
+ trigger = 'blur'
715
+ }
716
+ if (groupItem) {
717
+ this.rules[groupItem].push({
718
+ required: true,
719
+ message: message,
720
+ trigger: trigger
721
+ })
722
+ } else {
723
+ this.rules[rulesKey].push({
724
+ required: true,
725
+ message: message,
726
+ trigger: trigger
727
+ })
728
+ }
729
+ }
730
+
731
+ switch (item.rule.type) {
732
+ case 'number':
733
+ case 'integer':
734
+ case 'float':
735
+ // eslint-disable-next-line no-case-declarations
736
+ let defaultValue
737
+ // eslint-disable-next-line no-case-declarations
738
+ let message
739
+ switch (item.rule.type) {
740
+ case 'number':
741
+ item.numberInput = true
742
+ message = '数字'
743
+ defaultValue = 0
744
+ break
745
+ case 'integer':
746
+ item.numberInput = true
747
+ message = '整数'
748
+ defaultValue = 0
749
+ break
750
+ case 'float':
751
+ item.numberInput = true
752
+ message = '小数'
753
+ defaultValue = 0.0
754
+ break
755
+ }
756
+ if (groupItem) {
757
+ this.rules[groupItem].push({
758
+ type: item.rule.type,
759
+ message: item.name + '必须为' + message,
760
+ transform: (value) => {
761
+ if (value && value.length !== 0) {
762
+ return Number(value)
763
+ } else {
764
+ return defaultValue
765
+ }
766
+ },
767
+ trigger: 'blur'
768
+ })
769
+ } else {
770
+ this.rules[rulesKey].push({
771
+ type: item.rule.type,
772
+ message: item.name + '必须为' + message,
773
+ transform: (value) => {
774
+ if (value && value.length !== 0) {
775
+ return Number(value)
776
+ } else {
777
+ return defaultValue
778
+ }
779
+ },
780
+ trigger: 'blur'
781
+ })
782
+ }
783
+ break
784
+ case 'email': {
785
+ const validator = (rule, value, callback) => {
786
+ if (value && !REG_EMAIL.test(value)) {
787
+ callback(new Error('请输入正确的邮箱地址'))
788
+ } else {
789
+ callback()
790
+ }
791
+ }
792
+ this.rules[groupItem || rulesKey].push({
793
+ type: 'email',
794
+ validator: validator,
795
+ message: '请输入正确的邮箱地址',
796
+ trigger: 'blur'
797
+ })
798
+ break
799
+ }
800
+ case 'userPhone': {
801
+ this.rules[groupItem || rulesKey].push({
802
+ type: 'userPhone',
803
+ validator: (rule, value, callback) => {
804
+ if (value && !REG_PHONE.test(value)) {
805
+ callback(new Error('请输入正确的手机号码'))
806
+ } else {
807
+ callback()
808
+ }
809
+ },
810
+ message: '请输入正确的手机号码',
811
+ trigger: 'blur'
812
+ })
813
+ break
814
+ }
815
+ case 'idNumber': {
816
+ this.rules[groupItem || rulesKey].push({
817
+ validator: (rule, value, callback) => {
818
+ if (value && !checkIdNumber(value)) {
819
+ callback(new Error('请输入正确的身份证号码'))
820
+ } else {
821
+ callback()
822
+ }
823
+ },
824
+ trigger: 'blur'
825
+ })
826
+ break
827
+ }
828
+ case 'landlineNumber': {
829
+ this.rules[rulesKey].push({
830
+ validator: (rule, value, callback) => {
831
+ if (value && !REG_LANDLINE.test(value)) {
832
+ callback(new Error('请输入正确的座机号码'))
833
+ } else {
834
+ callback()
835
+ }
836
+ },
837
+ trigger: 'blur'
838
+ })
839
+ break
840
+ }
841
+ // 大于0
842
+ case 'greaterThanZero': {
843
+ item.numberInput = true
844
+ this.rules[rulesKey].push({
845
+ validator: (rule, value, callback) => {
846
+ if (isNaN(value) || value <= 0) {
847
+ callback(new Error('请输入一个大于0的数字'))
848
+ } else {
849
+ callback()
850
+ }
851
+ },
852
+ trigger: 'blur'
853
+ })
854
+ break
855
+ }
856
+ // 大于等于0
857
+ case 'greaterThanOrEqualZero': {
858
+ item.numberInput = true
859
+ this.rules[rulesKey].push({
860
+ validator: (rule, value, callback) => {
861
+ if (isNaN(value) || value < 0) {
862
+ callback(new Error('请输入一个大于等于0的数字'))
863
+ } else {
864
+ callback()
865
+ }
866
+ },
867
+ trigger: 'blur'
868
+ })
869
+ break
870
+ }
871
+ case 'stringLength': {
872
+ this.rules[rulesKey].push({
873
+ validator: (rule, value, callback) => {
874
+ if (value && value.length < item.rule.minLen) {
875
+ callback(new Error('长度不能少于' + item.rule.minLen + '个字符'))
876
+ } else if (value && value.length > item.rule.maxLen) {
877
+ callback(new Error('长度不能超过' + item.rule.maxLen + '个字符'))
878
+ } else {
879
+ callback()
880
+ }
881
+ },
882
+ trigger: 'blur'
883
+ })
884
+ break
885
+ }
886
+ case 'customJs': {
887
+ this.rules[rulesKey].push({
888
+ validator: (rule, value, callback) => {
889
+ this.customJsValidate(rule, value, callback, item)
890
+ },
891
+ trigger: 'blur'
892
+ })
893
+ break
894
+ }
895
+ }
896
+ }
897
+ },
898
+ childTableMounted (item) {
899
+ // 子表初始化时,设置表格数据
900
+ if (this.form[item.model] && this.form[item.model].length > 0) {
901
+ this.$refs[`childXFormTable_${item.model}`][0].setTableData(this.form[item.model])
902
+ }
903
+ },
904
+ customJsValidate (rule, value, callback, item) {
905
+ if (item.rule.customValidatorFunc) {
906
+ executeStrFunctionByContext(this, item.rule.customValidatorFunc, [rule, value, callback, this.form, item, this.util, runLogic, getConfigByNameAsync])
907
+ } else {
908
+ callback()
909
+ }
910
+ },
911
+ itemDisabled (value) {
912
+ return (this.businessType === '新增' && value.addOrEdit === 'edit') ||
913
+ (this.businessType === '修改' && value.addOrEdit === 'add')
914
+ },
915
+ readonly (value) {
916
+ return value.addOrEdit === 'readonly'
917
+ },
918
+ async onSubmit () {
919
+ const valid = await this.validateForm()
920
+ if (!valid) return false
921
+ if (this.viewMode) {
922
+ this.$message.info('预览模式禁止新增和修改')
923
+ return false
924
+ }
925
+ this.loading = true
926
+ const requestForm = this.prepareForm()
927
+ await this.appendSilenceAddFields(requestForm)
928
+ const realForm = this.handleFormKeys(requestForm)
929
+ // 增加子表数据
930
+ if (this.childTableData.length > 0) {
931
+ for (const item of this.childTableData) {
932
+ const childModel = item.model
933
+ const childDataRef = this.$refs['childXFormTable_' + item.model][0].getTableData()
934
+ const childData = []
935
+ for (const item of childDataRef) {
936
+ childData.push(JSON.parse(JSON.stringify(item)))
937
+ }
938
+ for (let i = 0; i < childData.length; i++) {
939
+ childData[i] = this.handleFormKeys(childData[i])
940
+ // 外键不需要带表别名,所以此处放到表单处理后赋值
941
+ if (realForm.id) {
942
+ childData[i][item.childTableForeignKeyName] = realForm.id
943
+ }
944
+ }
945
+ realForm[childModel] = childData
946
+ }
947
+ }
948
+ // 增加form子表数据
949
+ if (this.childFormData.length > 0) {
950
+ for (const item of this.childFormData) {
951
+ const childModel = item.model
952
+ const childData = this.$refs[item.model].getTableData()
953
+ for (let i = 0; i < childData.length; i++) {
954
+ childData[i] = this.handleFormKeys(childData[i], true)
955
+ // 外键不需要带表别名,所以此处放到表单处理后赋值
956
+ if (realForm.id) {
957
+ childData[i][item.foreignKey] = realForm.id
958
+ }
959
+ }
960
+ realForm[childModel] = childData
961
+ }
962
+ }
963
+ if (this.$listeners.onSubmit) {
964
+ // 交由父级处理
965
+ this.$emit('onSubmit', {
966
+ businessType: this.businessType,
967
+ serviceName: this.serviceName,
968
+ realForm: realForm,
969
+ currUserName: this.currUser.name,
970
+ currUserId: this.currUser.id,
971
+ orgId: this.currUser.orgid
972
+ })
973
+ } else {
974
+ this.defaultSubmit(realForm)
975
+ }
976
+ },
977
+
978
+ async asyncSubmit () {
979
+ return new Promise((resolve, reject) => {
980
+ this.$refs.selectForm.validate(async valid => {
981
+ if (!valid) {
982
+ reject(new Error('Form validation failed'))
983
+ return
984
+ }
985
+ this.loading = true
986
+ const requestForm = this.prepareForm()
987
+ await this.appendSilenceAddFields(requestForm)
988
+ const realForm = this.handleFormKeys(requestForm)
989
+ resolve({
990
+ realForm,
991
+ businessType: this.businessType,
992
+ serviceName: this.serviceName,
993
+ currUserName: this.currUser.name,
994
+ currUserId: this.currUser.id,
995
+ orgId: this.currUser.orgid
996
+ })
997
+ })
998
+ })
999
+ },
1000
+
1001
+ validateForm () {
1002
+ return new Promise((resolve) => {
1003
+ this.$refs.selectForm.validate(valid => resolve(valid))
1004
+ })
1005
+ },
1006
+
1007
+ childTableFixedQueryForm (item) {
1008
+ if (this.modifyModelData?.primaryKeyData) {
1009
+ const fixedForm = {}
1010
+ fixedForm[item.childTableForeignKeyName] = Object.values(this.modifyModelData.primaryKeyData)[0]
1011
+ return fixedForm
1012
+ }
1013
+ return null
1014
+ },
1015
+
1016
+ prepareForm () {
1017
+ const form = { ...this.form }
1018
+ for (const key of Object.keys(form)) {
1019
+ const value = form[key]
1020
+ if (value === null || (typeof value === 'object' && Object.keys(value).length === 0)) {
1021
+ form[key] = undefined
1022
+ }
1023
+ }
1024
+ return form
1025
+ },
1026
+
1027
+ async appendSilenceAddFields (form) {
1028
+ if (this.businessType === '新增') {
1029
+ for (const item of this.silenceAddJsonData) {
1030
+ switch (item.silencePurpose) {
1031
+ case 'createTime':
1032
+ form[item.model] = formatDate('now')
1033
+ break
1034
+ case 'operator':
1035
+ form[item.model] = this.currUser.name
1036
+ break
1037
+ case 'operatorId':
1038
+ form[item.model] = this.currUser.id
1039
+ break
1040
+ case 'orgId':
1041
+ form[item.model] = this.currUser.orgid
1042
+ break
1043
+ case 'orgName':
1044
+ form[item.model] = this.currUser.orgs
1045
+ break
1046
+ case 'depId':
1047
+ form[item.model] = this.currUser.depids
1048
+ break
1049
+ case 'depName':
1050
+ form[item.model] = this.currUser.deps
1051
+ break
1052
+ }
1053
+ }
1054
+ for (const item of this.silenceAddJsonData.filter((item) => item.silencePurpose === 'customize')) {
1055
+ const result = await runLogic(item.silenceSource, form, this.serviceName)
1056
+ if (result) {
1057
+ const keys = Object.keys(result)
1058
+ if (keys.length === 1 && keys[0] === 'value') {
1059
+ form[item.model] = result.value
1060
+ } else {
1061
+ form[item.model] = result
1062
+ }
1063
+ } else {
1064
+ form[item.model] = result
1065
+ }
1066
+ }
1067
+ }
1068
+ },
1069
+
1070
+ handleFormKeys (form, mustHandleKey = false) {
1071
+ const realForm = {}
1072
+ for (const key of Object.keys(form)) {
1073
+ const value = form[key]
1074
+ const extraFormKeyTagIndex = key.indexOf('@')
1075
+ if (extraFormKeyTagIndex !== -1) {
1076
+ const extraFormKey = key.substring(0, extraFormKeyTagIndex)
1077
+ const realKey = key.substring(extraFormKeyTagIndex + 1)
1078
+ if (!realForm[extraFormKey]) {
1079
+ realForm[extraFormKey] = {}
1080
+ }
1081
+ realForm[extraFormKey][realKey] = value
1082
+ } else {
1083
+ const realKey = this.isHandleFormKey || mustHandleKey ? this.getRealKey(key, mustHandleKey) : key
1084
+ // 如果发生重名,不覆盖,把key的别名带上
1085
+ if (realForm[realKey]) {
1086
+ realForm[key] = value
1087
+ } else {
1088
+ realForm[realKey] = value
1089
+ }
1090
+ }
1091
+ }
1092
+ return realForm
1093
+ },
1094
+ // 默认提交事件
1095
+ defaultSubmit (realForm, callback) {
1096
+ // 新增移除id
1097
+ if (this.businessType === '新增') {
1098
+ delete realForm.id
1099
+ }
1100
+ // 组织请求
1101
+ const requestParameters = {
1102
+ queryParamsName: this.configName,
1103
+ queryParams: this.configContent,
1104
+ form: realForm,
1105
+ businessType: this.businessType,
1106
+ operator: this.currUser.name
1107
+ }
1108
+ addOrModify(requestParameters, this.serviceName, this.env === 'dev').then(data => {
1109
+ this.$message.success(this.businessType + '成功!')
1110
+ // commit
1111
+ this.$emit('afterSubmit', { type: this.businessType, id: data.id, data: data, form: requestParameters.form })
1112
+ this.loading = false
1113
+ if (callback) {
1114
+ callback()
1115
+ }
1116
+ }).catch(e => {
1117
+ this.loading = false
1118
+ this.$message.error(this.businessType + '失败:' + e)
1119
+ })
1120
+ },
1121
+ // 获取表单字段实际值
1122
+ getRealKey (key, mustHandleKey = false) {
1123
+ if (key === 'selected_id') return key
1124
+ if (this.isHandleFormKey || mustHandleKey) {
1125
+ return key.substring(key.indexOf('_') + 1)
1126
+ } else {
1127
+ return key
1128
+ }
1129
+ },
1130
+ /**
1131
+ * 获取被修改记录数据
1132
+ * @param modifyModelData 被修改记录的数据
1133
+ */
1134
+ getModifyModelData (modifyModelData) {
1135
+ if (modifyModelData.primaryKeyData) {
1136
+ this.form = Object.assign(this.form, modifyModelData.primaryKeyData)
1137
+ }
1138
+ // 对动态简易表单项特殊处理
1139
+ for (const key in modifyModelData.data) {
1140
+ const realKey = this.isHandleFormKey ? this.getRealKey(key) : key
1141
+ if (this.simpleFormJsonData[realKey]) {
1142
+ const extraForm = JSON.parse(modifyModelData.data[key])
1143
+ for (const key in extraForm) {
1144
+ const model = realKey + '@' + key
1145
+ this.form[model] = extraForm[key]
1146
+ }
1147
+ }
1148
+ }
1149
+ // 对普通表单项处理
1150
+ for (let i = 0; i < this.realJsonData.length; i++) {
1151
+ if (['FilesId', 'Images'].includes(this.realJsonData[i])) {
1152
+ // 附件需要跳过 因为会通过 modifyModelData中的files,images属性给upload赋值
1153
+ // 新增修改表单每次提交时只会提交最新添加的文件
1154
+ continue
1155
+ }
1156
+ const item = this.realJsonData[i]
1157
+ // 地址选择器 需要传递 经纬度字段, 配置中添加 `${item.model}_lng_lat` CRUD 只需勾选 SQL生成查询项
1158
+ if (['addressSearch'].includes(item.type)) {
1159
+ this.form[item.model] = modifyModelData.data[item.model] + ''
1160
+ this.form[`${item.model}_lng_lat`] = modifyModelData.data[`${item.model}_lng_lat`] + ''
1161
+ continue
1162
+ }
1163
+ if (modifyModelData.data[item.model] || modifyModelData.data[item.model] === 0) {
1164
+ if (modifyModelData.data[item.model] instanceof Array) {
1165
+ this.form[item.model] = modifyModelData.data[item.model]
1166
+ } else {
1167
+ this.form[item.model] = modifyModelData.data[item.model] + ''
1168
+ }
1169
+ }
1170
+ }
1171
+ // 对分组表单进行处理
1172
+ for (let i = 0; i < this.groupJsonData.length; i++) {
1173
+ const item = this.groupJsonData[i]
1174
+ try {
1175
+ if (modifyModelData.data[item.model]) {
1176
+ this.form[item.model] = JSON.parse(modifyModelData.data[item.model])
1177
+ }
1178
+ } catch (e) {
1179
+ if (modifyModelData.data[item.model]) {
1180
+ this.form[item.model] = modifyModelData.data[item.model]
1181
+ }
1182
+ }
1183
+ }
1184
+ // 追加版本号信息
1185
+ for (const item of this.versionJsonData) {
1186
+ if (!modifyModelData.data[item.model]) {
1187
+ this.form[item.model] = 0
1188
+ } else {
1189
+ this.form[item.model] = modifyModelData.data[item.model] + ''
1190
+ }
1191
+ }
1192
+ },
1193
+ setForm (obj) {
1194
+ this.form = Object.assign(this.form, obj)
1195
+ // 给子表赋外键条件
1196
+ if (this.childFormData.length > 0) {
1197
+ for (const item of this.childFormData) {
1198
+ const child = this.$refs[item.model]
1199
+ // 获取子表别名,以便在条件上添加别名
1200
+ const alias = child.realQueryConfig.tableAliasName
1201
+ // 有主键,且主键有值,添加主键条件
1202
+ if (this.primaryKey && this.form[this.primaryKey]) {
1203
+ const foreignKey = item.foreignKey
1204
+ const fixedQueryForm = { [alias + '_' + foreignKey]: this.form[this.primaryKey] }
1205
+ if (!child.fixedQueryForm) {
1206
+ child.fixedQueryForm = fixedQueryForm
1207
+ } else {
1208
+ Object.assign(child.fixedQueryForm, fixedQueryForm)
1209
+ }
1210
+ child.refreshTable()
1211
+ }
1212
+ }
1213
+ }
1214
+ },
1215
+ setFormWithKey (obj) {
1216
+ setDataByRealKey(this.form, obj)
1217
+ },
1218
+ setFormWithNoKey (obj) {
1219
+ setDataByRealKey(this.form, obj)
1220
+ },
1221
+ emitFunc (func, data, value) {
1222
+ this.$emit(func, data, value)
1223
+ this.$emit('x-form-item-emit-func', func, data, value)
1224
+ },
1225
+ // 直接转发事件的函数
1226
+ emitEvent (event, ...args) {
1227
+ this.$emit(event, ...args)
1228
+ },
1229
+ close () {
1230
+ this.loaded = false
1231
+ },
1232
+ /**
1233
+ * 行选择事件
1234
+ * @param row 选中行集合
1235
+ * @param attr 表单项属性
1236
+ */
1237
+ async rowChoose (row, attr, callback) {
1238
+ // 如果配置了自定义函数
1239
+ if (attr.dataChangeFunc) {
1240
+ await executeStrFunction(attr.dataChangeFunc, [this.form, this.setForm, {
1241
+ ...attr,
1242
+ selectRows: row
1243
+ }, util, this.mode, runLogic, getConfigByNameAsync])
1244
+ } else {
1245
+ // 默认填充选中行数据到当前表单
1246
+ setDataByRealKey(this.form, row[0])
1247
+ }
1248
+ if (callback) {
1249
+ callback()
1250
+ }
1251
+ },
1252
+ }
1253
+ }
1254
+ </script>
1255
+
1256
+ <style scoped lang="less">
1257
+ :deep(.ant-form-inline .ant-form-item ) {
1258
+ display: block !important;
1259
+ }
1260
+
1261
+ :deep(.ant-form-item-with-help) {
1262
+ margin-bottom: 0;
1263
+ }
1264
+
1265
+ .xFormGroupTitle {
1266
+ font-weight: bold;
1267
+ color: @primary-color;
1268
+ }
1269
+
1270
+ .simple-inline-item {
1271
+ max-width: 100% !important;
1272
+ }
1273
+
1274
+ /* simple-inline模式样式 */
1275
+ :deep(.simple-inline-item .ant-form-item) {
1276
+ margin: 0 !important;
1277
+ padding: 2px !important;
1278
+
1279
+ .ant-form-item-label {
1280
+ display: none !important;
1281
+ }
1282
+
1283
+ .ant-form-item-control-wrapper,
1284
+ .ant-form-item-control {
1285
+ width: 100% !important;
1286
+ }
1287
+ }
1288
+ </style>