af-mobile-client-vue3 1.0.90 → 1.0.92-appraise
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.
- package/package.json +109 -108
- package/src/assets/img/banner/appraise-banner-1.png +0 -0
- package/src/assets/img/banner/appraise-banner-2.png +0 -0
- package/src/components/data/XCellList/index.vue +35 -22
- package/src/components/data/XForm/index.vue +1 -1
- package/src/components/data/XFormItem/index.vue +997 -962
- package/src/router/routes.ts +6 -0
- package/src/views/component/XCellListView/index.vue +2 -2
- package/src/views/component/XFormAppraiseView/index.vue +169 -0
- package/src/views/component/XFormGroupView/index.vue +2 -2
- package/src/views/component/index.vue +4 -0
|
@@ -1,962 +1,997 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
Area as VanArea,
|
|
4
|
-
Calendar as VanCalendar,
|
|
5
|
-
Checkbox as VanCheckbox,
|
|
6
|
-
DatePicker as VanDatePicker,
|
|
7
|
-
Field as VanField,
|
|
8
|
-
Picker as VanPicker,
|
|
9
|
-
PickerGroup as VanPickerGroup,
|
|
10
|
-
Popup as VanPopup,
|
|
11
|
-
Radio as VanRadio,
|
|
12
|
-
RadioGroup as VanRadioGroup,
|
|
13
|
-
Rate as VanRate,
|
|
14
|
-
Slider as VanSlider,
|
|
15
|
-
Stepper as VanStepper,
|
|
16
|
-
Switch as VanSwitch,
|
|
17
|
-
TimePicker as VanTimePicker,
|
|
18
|
-
CheckboxGroup as vanCheckboxGroup,
|
|
19
|
-
} from 'vant'
|
|
20
|
-
import { computed, defineEmits, defineProps, getCurrentInstance, onBeforeMount, ref, watch } from 'vue'
|
|
21
|
-
import { areaList } from '@vant/area-data'
|
|
22
|
-
import { runLogic } from '@af-mobile-client-vue3/services/api/common'
|
|
23
|
-
import Uploader from '@af-mobile-client-vue3/components/core/Uploader/index.vue'
|
|
24
|
-
import XSelect from '@af-mobile-client-vue3/components/core/XSelect/index.vue'
|
|
25
|
-
import XMultiSelect from '@af-mobile-client-vue3/components/core/XMultiSelect/index.vue'
|
|
26
|
-
import XGridDropOption from '@af-mobile-client-vue3/components/core/XGridDropOption/index.vue'
|
|
27
|
-
import type { Numeric } from 'vant/es/utils'
|
|
28
|
-
import { getDict } from '@af-mobile-client-vue3/utils/dictUtil'
|
|
29
|
-
import { executeStrFunctionByContext } from '@af-mobile-client-vue3/utils/runEvalFunction'
|
|
30
|
-
import { useUserStore } from '@af-mobile-client-vue3/stores/modules/user'
|
|
31
|
-
import { debounce } from 'lodash-es'
|
|
32
|
-
import { searchToListOption, searchToOption } from '@af-mobile-client-vue3/services/v3Api'
|
|
33
|
-
|
|
34
|
-
const props = defineProps({
|
|
35
|
-
attr: {
|
|
36
|
-
type: Object,
|
|
37
|
-
},
|
|
38
|
-
form: {
|
|
39
|
-
type: Object,
|
|
40
|
-
},
|
|
41
|
-
datePickerFilter: {
|
|
42
|
-
type: Function,
|
|
43
|
-
default: () => true,
|
|
44
|
-
},
|
|
45
|
-
datePickerFormatter: {
|
|
46
|
-
type: Function,
|
|
47
|
-
default: (type, val) => val,
|
|
48
|
-
},
|
|
49
|
-
mode: {
|
|
50
|
-
type: String,
|
|
51
|
-
default: '查询',
|
|
52
|
-
},
|
|
53
|
-
serviceName: {
|
|
54
|
-
type: String,
|
|
55
|
-
default: undefined,
|
|
56
|
-
},
|
|
57
|
-
// 调用logic获取数据源的追加参数
|
|
58
|
-
getDataParams: {
|
|
59
|
-
type: Object,
|
|
60
|
-
default: undefined,
|
|
61
|
-
},
|
|
62
|
-
disabled: {
|
|
63
|
-
type: Boolean,
|
|
64
|
-
default: false,
|
|
65
|
-
},
|
|
66
|
-
rules: {
|
|
67
|
-
type: Object,
|
|
68
|
-
default: () => {},
|
|
69
|
-
},
|
|
70
|
-
modelValue: {
|
|
71
|
-
type: [String, Number, Boolean, Array, Object],
|
|
72
|
-
default: undefined,
|
|
73
|
-
},
|
|
74
|
-
showLabel: {
|
|
75
|
-
type: Boolean,
|
|
76
|
-
default: true,
|
|
77
|
-
},
|
|
78
|
-
// radio/checkbox/select/mul-select 选项数据结构
|
|
79
|
-
columnsField: {
|
|
80
|
-
type: Object,
|
|
81
|
-
default: () => {
|
|
82
|
-
return { text: 'label', value: 'value' }
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
|
-
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
const emits = defineEmits(['update:modelValue'])
|
|
89
|
-
// 判断并初始化防抖函数
|
|
90
|
-
let debouncedUserLinkFunc: Function | null = null
|
|
91
|
-
let debouncedDepLinkFunc: Function | null = null
|
|
92
|
-
|
|
93
|
-
const { attr, form, mode, serviceName, getDataParams, columnsField } = props
|
|
94
|
-
const calendarShow = ref(false)
|
|
95
|
-
const option = ref([])
|
|
96
|
-
const pickerValue = ref(undefined)
|
|
97
|
-
const datePickerValue = ref(undefined)
|
|
98
|
-
const timePickerValue = ref(undefined)
|
|
99
|
-
const area = ref<any>(undefined)
|
|
100
|
-
const showPicker = ref(false)
|
|
101
|
-
const showDatePicker = ref(false)
|
|
102
|
-
const showTimePicker = ref(false)
|
|
103
|
-
const showArea = ref(false)
|
|
104
|
-
const errorMessage = ref('')
|
|
105
|
-
|
|
106
|
-
// 表单默认值
|
|
107
|
-
// 输入-非查询
|
|
108
|
-
const formInputDefaultValue = ref('')
|
|
109
|
-
// 输入-查询
|
|
110
|
-
const queryInputDefaultValue = ref('')
|
|
111
|
-
// 选择-非查询
|
|
112
|
-
const formSelectDefaultValue = ref([])
|
|
113
|
-
// 选择-查询
|
|
114
|
-
const querySelectDefaultValue = ref([])
|
|
115
|
-
|
|
116
|
-
// eslint-disable-next-line ts/no-use-before-define
|
|
117
|
-
const currUser = computed(() => userState.f.resources.id)
|
|
118
|
-
// 是否展示当前项
|
|
119
|
-
const showItem = ref(true)
|
|
120
|
-
|
|
121
|
-
// 当前组件实例(不推荐使用,可能会在后续的版本更迭中调整,暂时用来绑定函数的上下文)
|
|
122
|
-
const currInst = getCurrentInstance()
|
|
123
|
-
|
|
124
|
-
// 配置中心->表单项变更触发函数
|
|
125
|
-
const dataChangeFunc = debounce(async () => {
|
|
126
|
-
if (attr.dataChangeFunc)
|
|
127
|
-
await executeStrFunctionByContext(currInst, attr.dataChangeFunc, [form, attr, null, mode])
|
|
128
|
-
}, 500)
|
|
129
|
-
|
|
130
|
-
// 配置中心->表单项展示函数
|
|
131
|
-
const showFormItemFunc = debounce(async () => {
|
|
132
|
-
if (attr.showFormItemFunc) {
|
|
133
|
-
const obj = await executeStrFunctionByContext(currInst, attr.showFormItemFunc, [form, attr, null, mode])
|
|
134
|
-
// 判断是 bool 还是 obj 兼容
|
|
135
|
-
if (typeof obj === 'boolean') {
|
|
136
|
-
showItem.value = obj
|
|
137
|
-
}
|
|
138
|
-
else if (obj && typeof obj === 'object') {
|
|
139
|
-
// obj 是一个对象,并且不是数组
|
|
140
|
-
showItem.value = obj?.show
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}, 500)
|
|
144
|
-
|
|
145
|
-
const localValue = computed({
|
|
146
|
-
get() {
|
|
147
|
-
// if (props.modelValue !== undefined) {
|
|
148
|
-
// return props.modelValue
|
|
149
|
-
// }
|
|
150
|
-
switch (attr.type) {
|
|
151
|
-
case 'uploader':
|
|
152
|
-
if (mode === '查询') {
|
|
153
|
-
// console.log(querySelectDefaultValue.value)
|
|
154
|
-
return props.modelValue !== undefined ? props.modelValue : querySelectDefaultValue.value
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
return props.modelValue !== undefined ? props.modelValue : formSelectDefaultValue.value
|
|
158
|
-
}
|
|
159
|
-
case 'switch':
|
|
160
|
-
return props.modelValue !== undefined ? props.modelValue : false
|
|
161
|
-
case 'checkbox':
|
|
162
|
-
case 'file':
|
|
163
|
-
case 'image':
|
|
164
|
-
case 'timePicker':
|
|
165
|
-
case 'datePicker':
|
|
166
|
-
if (mode === '查询') {
|
|
167
|
-
// console.log(querySelectDefaultValue.value)
|
|
168
|
-
return props.modelValue !== undefined ? props.modelValue : querySelectDefaultValue.value
|
|
169
|
-
}
|
|
170
|
-
else {
|
|
171
|
-
// console.log(formSelectDefaultValue.value)
|
|
172
|
-
return props.modelValue !== undefined ? props.modelValue : formSelectDefaultValue.value
|
|
173
|
-
}
|
|
174
|
-
// case 'datePicker':
|
|
175
|
-
// if (mode === '查询') {
|
|
176
|
-
// // console.log(querySelectDefaultValue.value)
|
|
177
|
-
// return props.modelValue !== undefined ? props.modelValue : querySelectDefaultValue.value
|
|
178
|
-
// }
|
|
179
|
-
// else {
|
|
180
|
-
// if (props.modelValue !== undefined) {
|
|
181
|
-
// // 拆分日期和时间
|
|
182
|
-
// const [dateStr, timeStr] = props.modelValue.split(' ')
|
|
183
|
-
// // 拆分日期部分
|
|
184
|
-
// const date = dateStr.split('-')
|
|
185
|
-
// // 拆分时间部分
|
|
186
|
-
// const time = timeStr.split(':')
|
|
187
|
-
// // 赋值给 dateTimePickerValue
|
|
188
|
-
// // eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
|
189
|
-
// dateTimePickerValue.value = {
|
|
190
|
-
// date,
|
|
191
|
-
// time,
|
|
192
|
-
// }
|
|
193
|
-
// return dateTimePickerValue.value
|
|
194
|
-
// }
|
|
195
|
-
// return formSelectDefaultValue.value
|
|
196
|
-
// }
|
|
197
|
-
case 'radio':
|
|
198
|
-
case 'rate':
|
|
199
|
-
case 'slider':
|
|
200
|
-
case 'area':
|
|
201
|
-
case 'citySelect':
|
|
202
|
-
case 'calendar':
|
|
203
|
-
case 'textarea':
|
|
204
|
-
case 'intervalPicker':
|
|
205
|
-
case 'input':
|
|
206
|
-
case 'select':
|
|
207
|
-
if (mode === '查询')
|
|
208
|
-
return props.modelValue !== undefined ? props.modelValue : queryInputDefaultValue.value
|
|
209
|
-
else
|
|
210
|
-
return props.modelValue !== undefined ? props.modelValue : formInputDefaultValue.value
|
|
211
|
-
case 'stepper':
|
|
212
|
-
return props.modelValue !== undefined ? props.modelValue : 1
|
|
213
|
-
case 'rangePicker':
|
|
214
|
-
if (props.modelValue && Array.isArray(props.modelValue) && props.modelValue.length > 1)
|
|
215
|
-
return `${props.modelValue[0]} ~ ${props.modelValue[1]}`
|
|
216
|
-
|
|
217
|
-
else
|
|
218
|
-
return props.modelValue
|
|
219
|
-
|
|
220
|
-
default:
|
|
221
|
-
return undefined
|
|
222
|
-
}
|
|
223
|
-
},
|
|
224
|
-
set(newValue) {
|
|
225
|
-
emits('update:modelValue', newValue)
|
|
226
|
-
dataChangeFunc()
|
|
227
|
-
},
|
|
228
|
-
})
|
|
229
|
-
|
|
230
|
-
// 表单校验的类型校验
|
|
231
|
-
function formTypeCheck(attr, value) {
|
|
232
|
-
switch (attr.rule.type) {
|
|
233
|
-
case 'string':
|
|
234
|
-
if (value.length === 0) {
|
|
235
|
-
errorMessage.value = `${attr.name}必须为有效的字符串`
|
|
236
|
-
return
|
|
237
|
-
}
|
|
238
|
-
break
|
|
239
|
-
case 'number':
|
|
240
|
-
if (!/^[+-]?(\d+(\.\d*)?|\.\d+)$/.test(value)) {
|
|
241
|
-
errorMessage.value = `${attr.name}必须为数字`
|
|
242
|
-
return
|
|
243
|
-
}
|
|
244
|
-
break
|
|
245
|
-
case 'boolean':
|
|
246
|
-
case 'array':
|
|
247
|
-
case 'regexp':
|
|
248
|
-
if (value) {
|
|
249
|
-
errorMessage.value = ''
|
|
250
|
-
return
|
|
251
|
-
}
|
|
252
|
-
break
|
|
253
|
-
case 'integer':
|
|
254
|
-
if (!/^-?\d+$/.test(value)) {
|
|
255
|
-
errorMessage.value = `${attr.name}必须为整数`
|
|
256
|
-
return
|
|
257
|
-
}
|
|
258
|
-
break
|
|
259
|
-
case 'float':
|
|
260
|
-
if (!/^-?\d+\.\d+$/.test(value)) {
|
|
261
|
-
errorMessage.value = `${attr.name}必须为小数`
|
|
262
|
-
return
|
|
263
|
-
}
|
|
264
|
-
break
|
|
265
|
-
case 'email':
|
|
266
|
-
if (!/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(value)) {
|
|
267
|
-
errorMessage.value = `请输入正确的邮箱地址`
|
|
268
|
-
return
|
|
269
|
-
}
|
|
270
|
-
break
|
|
271
|
-
case 'idNumber':
|
|
272
|
-
if (!/^(^\d{15}$|^\d{17}([0-9]|X)$)$/.test(value)) {
|
|
273
|
-
errorMessage.value = `请输入正确的身份证号码`
|
|
274
|
-
return
|
|
275
|
-
}
|
|
276
|
-
break
|
|
277
|
-
case 'userPhone':
|
|
278
|
-
if (!/^1[3-9]\d{9}$/.test(value)) {
|
|
279
|
-
errorMessage.value = `请输入正确的手机号码`
|
|
280
|
-
return
|
|
281
|
-
}
|
|
282
|
-
break
|
|
283
|
-
case 'landlineNumber':
|
|
284
|
-
if (!/^(0\d{2,3}[-\s]?)\d{7,8}$/.test(value)) {
|
|
285
|
-
errorMessage.value = `请输入正确的座机号码`
|
|
286
|
-
return
|
|
287
|
-
}
|
|
288
|
-
break
|
|
289
|
-
case 'greaterThanZero':
|
|
290
|
-
if (!/^(?:[1-9]\d*(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/.test(value)) {
|
|
291
|
-
errorMessage.value = `请输入一个大于0的数字`
|
|
292
|
-
return
|
|
293
|
-
}
|
|
294
|
-
break
|
|
295
|
-
case 'greaterThanOrEqualZero':
|
|
296
|
-
if (!/^(?:\d+|\d*\.\d+)$/.test(value)) {
|
|
297
|
-
errorMessage.value = `请输入一个大于等于0的数字`
|
|
298
|
-
return
|
|
299
|
-
}
|
|
300
|
-
break
|
|
301
|
-
case 'stringLength':
|
|
302
|
-
if (!(value.length >= attr.rule.minLen && value.length < attr.rule.maxLen)) {
|
|
303
|
-
errorMessage.value = `长度必须在${attr.rule.minLen}~${attr.rule.maxLen}之间`
|
|
304
|
-
return
|
|
305
|
-
}
|
|
306
|
-
break
|
|
307
|
-
case 'customJs':
|
|
308
|
-
// eslint-disable-next-line no-case-declarations
|
|
309
|
-
const funcStr = attr.rule.customValidatorFunc
|
|
310
|
-
// 输入的数据是否符合条件
|
|
311
|
-
// eslint-disable-next-line no-case-declarations
|
|
312
|
-
const status = ref(true)
|
|
313
|
-
// 提取函数体部分
|
|
314
|
-
// eslint-disable-next-line no-case-declarations
|
|
315
|
-
const funcBodyMatch = funcStr.match(/function\s*\(.*?\)\s*{([\s\S]*)}/)
|
|
316
|
-
if (!funcBodyMatch)
|
|
317
|
-
throw new Error('自定义校验函数不合法')
|
|
318
|
-
// eslint-disable-next-line no-case-declarations
|
|
319
|
-
const funcBody = funcBodyMatch[1].trim() // 提取函数体
|
|
320
|
-
// 使用 new Function 创建函数
|
|
321
|
-
// eslint-disable-next-line no-new-func,no-case-declarations
|
|
322
|
-
const customValidatorFunc = new Function('rule', 'value', 'callback', 'form', 'attr', 'util', funcBody)
|
|
323
|
-
// 定义 callback 函数
|
|
324
|
-
// eslint-disable-next-line no-case-declarations
|
|
325
|
-
const callback = (error) => {
|
|
326
|
-
if (error) {
|
|
327
|
-
errorMessage.value = `${error}`
|
|
328
|
-
status.value = false // 表示有错误发生
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
// 调用自定义校验函数
|
|
332
|
-
customValidatorFunc(
|
|
333
|
-
attr.rule,
|
|
334
|
-
value,
|
|
335
|
-
callback,
|
|
336
|
-
form,
|
|
337
|
-
attr,
|
|
338
|
-
{}, // util 对象(可以根据需要传递)
|
|
339
|
-
)
|
|
340
|
-
if (!status.value)
|
|
341
|
-
return
|
|
342
|
-
break
|
|
343
|
-
default:
|
|
344
|
-
errorMessage.value = ''
|
|
345
|
-
break
|
|
346
|
-
}
|
|
347
|
-
errorMessage.value = ''
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
onBeforeMount(() => {
|
|
351
|
-
init()
|
|
352
|
-
showFormItemFunc()
|
|
353
|
-
dataChangeFunc()
|
|
354
|
-
if (attr?.keyName?.toString()?.startsWith('search@根据表单项[') && attr?.keyName?.toString().endsWith(']联动人员'))
|
|
355
|
-
debouncedUserLinkFunc = debounce(() => updateResOptions('人员'), 200)
|
|
356
|
-
|
|
357
|
-
if (attr?.keyName?.toString()?.startsWith('search@根据表单项[') && attr?.keyName?.toString().endsWith(']联动部门'))
|
|
358
|
-
debouncedDepLinkFunc = debounce(() => updateResOptions('部门'), 200)
|
|
359
|
-
})
|
|
360
|
-
// 是否展示表单左侧label文字
|
|
361
|
-
const labelData = computed(() => {
|
|
362
|
-
return props.showLabel ? attr.name : null
|
|
363
|
-
})
|
|
364
|
-
//
|
|
365
|
-
const
|
|
366
|
-
return attr.
|
|
367
|
-
})
|
|
368
|
-
//
|
|
369
|
-
const
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
else
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
const
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
//
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
//
|
|
515
|
-
const
|
|
516
|
-
//
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
showDatePicker.value =
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
if (file.
|
|
559
|
-
delete file.
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
//
|
|
572
|
-
if (attr?.keyName?.toString()?.startsWith('search@根据表单项[') && attr?.keyName?.toString().endsWith(']
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
:
|
|
711
|
-
:
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
:
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
:
|
|
755
|
-
:
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
readonly
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
v-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
:
|
|
805
|
-
:
|
|
806
|
-
:
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
:
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
:
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
:
|
|
950
|
-
:
|
|
951
|
-
|
|
952
|
-
:
|
|
953
|
-
:
|
|
954
|
-
:
|
|
955
|
-
|
|
956
|
-
/>
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
Area as VanArea,
|
|
4
|
+
Calendar as VanCalendar,
|
|
5
|
+
Checkbox as VanCheckbox,
|
|
6
|
+
DatePicker as VanDatePicker,
|
|
7
|
+
Field as VanField,
|
|
8
|
+
Picker as VanPicker,
|
|
9
|
+
PickerGroup as VanPickerGroup,
|
|
10
|
+
Popup as VanPopup,
|
|
11
|
+
Radio as VanRadio,
|
|
12
|
+
RadioGroup as VanRadioGroup,
|
|
13
|
+
Rate as VanRate,
|
|
14
|
+
Slider as VanSlider,
|
|
15
|
+
Stepper as VanStepper,
|
|
16
|
+
Switch as VanSwitch,
|
|
17
|
+
TimePicker as VanTimePicker,
|
|
18
|
+
CheckboxGroup as vanCheckboxGroup,
|
|
19
|
+
} from 'vant'
|
|
20
|
+
import { computed, defineEmits, defineProps, getCurrentInstance, onBeforeMount, ref, watch } from 'vue'
|
|
21
|
+
import { areaList } from '@vant/area-data'
|
|
22
|
+
import { runLogic } from '@af-mobile-client-vue3/services/api/common'
|
|
23
|
+
import Uploader from '@af-mobile-client-vue3/components/core/Uploader/index.vue'
|
|
24
|
+
import XSelect from '@af-mobile-client-vue3/components/core/XSelect/index.vue'
|
|
25
|
+
import XMultiSelect from '@af-mobile-client-vue3/components/core/XMultiSelect/index.vue'
|
|
26
|
+
import XGridDropOption from '@af-mobile-client-vue3/components/core/XGridDropOption/index.vue'
|
|
27
|
+
import type { Numeric } from 'vant/es/utils'
|
|
28
|
+
import { getDict } from '@af-mobile-client-vue3/utils/dictUtil'
|
|
29
|
+
import { executeStrFunctionByContext } from '@af-mobile-client-vue3/utils/runEvalFunction'
|
|
30
|
+
import { useUserStore } from '@af-mobile-client-vue3/stores/modules/user'
|
|
31
|
+
import { debounce } from 'lodash-es'
|
|
32
|
+
import { searchToListOption, searchToOption } from '@af-mobile-client-vue3/services/v3Api'
|
|
33
|
+
|
|
34
|
+
const props = defineProps({
|
|
35
|
+
attr: {
|
|
36
|
+
type: Object,
|
|
37
|
+
},
|
|
38
|
+
form: {
|
|
39
|
+
type: Object,
|
|
40
|
+
},
|
|
41
|
+
datePickerFilter: {
|
|
42
|
+
type: Function,
|
|
43
|
+
default: () => true,
|
|
44
|
+
},
|
|
45
|
+
datePickerFormatter: {
|
|
46
|
+
type: Function,
|
|
47
|
+
default: (type, val) => val,
|
|
48
|
+
},
|
|
49
|
+
mode: {
|
|
50
|
+
type: String,
|
|
51
|
+
default: '查询',
|
|
52
|
+
},
|
|
53
|
+
serviceName: {
|
|
54
|
+
type: String,
|
|
55
|
+
default: undefined,
|
|
56
|
+
},
|
|
57
|
+
// 调用logic获取数据源的追加参数
|
|
58
|
+
getDataParams: {
|
|
59
|
+
type: Object,
|
|
60
|
+
default: undefined,
|
|
61
|
+
},
|
|
62
|
+
disabled: {
|
|
63
|
+
type: Boolean,
|
|
64
|
+
default: false,
|
|
65
|
+
},
|
|
66
|
+
rules: {
|
|
67
|
+
type: Object,
|
|
68
|
+
default: () => {},
|
|
69
|
+
},
|
|
70
|
+
modelValue: {
|
|
71
|
+
type: [String, Number, Boolean, Array, Object],
|
|
72
|
+
default: undefined,
|
|
73
|
+
},
|
|
74
|
+
showLabel: {
|
|
75
|
+
type: Boolean,
|
|
76
|
+
default: true,
|
|
77
|
+
},
|
|
78
|
+
// radio/checkbox/select/mul-select 选项数据结构
|
|
79
|
+
columnsField: {
|
|
80
|
+
type: Object,
|
|
81
|
+
default: () => {
|
|
82
|
+
return { text: 'label', value: 'value' }
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
const emits = defineEmits(['update:modelValue'])
|
|
89
|
+
// 判断并初始化防抖函数
|
|
90
|
+
let debouncedUserLinkFunc: Function | null = null
|
|
91
|
+
let debouncedDepLinkFunc: Function | null = null
|
|
92
|
+
|
|
93
|
+
const { attr, form, mode, serviceName, getDataParams, columnsField } = props
|
|
94
|
+
const calendarShow = ref(false)
|
|
95
|
+
const option = ref([])
|
|
96
|
+
const pickerValue = ref(undefined)
|
|
97
|
+
const datePickerValue = ref(undefined)
|
|
98
|
+
const timePickerValue = ref(undefined)
|
|
99
|
+
const area = ref<any>(undefined)
|
|
100
|
+
const showPicker = ref(false)
|
|
101
|
+
const showDatePicker = ref(false)
|
|
102
|
+
const showTimePicker = ref(false)
|
|
103
|
+
const showArea = ref(false)
|
|
104
|
+
const errorMessage = ref('')
|
|
105
|
+
|
|
106
|
+
// 表单默认值
|
|
107
|
+
// 输入-非查询
|
|
108
|
+
const formInputDefaultValue = ref('')
|
|
109
|
+
// 输入-查询
|
|
110
|
+
const queryInputDefaultValue = ref('')
|
|
111
|
+
// 选择-非查询
|
|
112
|
+
const formSelectDefaultValue = ref([])
|
|
113
|
+
// 选择-查询
|
|
114
|
+
const querySelectDefaultValue = ref([])
|
|
115
|
+
|
|
116
|
+
// eslint-disable-next-line ts/no-use-before-define
|
|
117
|
+
const currUser = computed(() => userState.f.resources.id)
|
|
118
|
+
// 是否展示当前项
|
|
119
|
+
const showItem = ref(true)
|
|
120
|
+
|
|
121
|
+
// 当前组件实例(不推荐使用,可能会在后续的版本更迭中调整,暂时用来绑定函数的上下文)
|
|
122
|
+
const currInst = getCurrentInstance()
|
|
123
|
+
|
|
124
|
+
// 配置中心->表单项变更触发函数
|
|
125
|
+
const dataChangeFunc = debounce(async () => {
|
|
126
|
+
if (attr.dataChangeFunc)
|
|
127
|
+
await executeStrFunctionByContext(currInst, attr.dataChangeFunc, [form, attr, null, mode])
|
|
128
|
+
}, 500)
|
|
129
|
+
|
|
130
|
+
// 配置中心->表单项展示函数
|
|
131
|
+
const showFormItemFunc = debounce(async () => {
|
|
132
|
+
if (attr.showFormItemFunc) {
|
|
133
|
+
const obj = await executeStrFunctionByContext(currInst, attr.showFormItemFunc, [form, attr, null, mode])
|
|
134
|
+
// 判断是 bool 还是 obj 兼容
|
|
135
|
+
if (typeof obj === 'boolean') {
|
|
136
|
+
showItem.value = obj
|
|
137
|
+
}
|
|
138
|
+
else if (obj && typeof obj === 'object') {
|
|
139
|
+
// obj 是一个对象,并且不是数组
|
|
140
|
+
showItem.value = obj?.show
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}, 500)
|
|
144
|
+
|
|
145
|
+
const localValue = computed({
|
|
146
|
+
get() {
|
|
147
|
+
// if (props.modelValue !== undefined) {
|
|
148
|
+
// return props.modelValue
|
|
149
|
+
// }
|
|
150
|
+
switch (attr.type) {
|
|
151
|
+
case 'uploader':
|
|
152
|
+
if (mode === '查询') {
|
|
153
|
+
// console.log(querySelectDefaultValue.value)
|
|
154
|
+
return props.modelValue !== undefined ? props.modelValue : querySelectDefaultValue.value
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
return props.modelValue !== undefined ? props.modelValue : formSelectDefaultValue.value
|
|
158
|
+
}
|
|
159
|
+
case 'switch':
|
|
160
|
+
return props.modelValue !== undefined ? props.modelValue : false
|
|
161
|
+
case 'checkbox':
|
|
162
|
+
case 'file':
|
|
163
|
+
case 'image':
|
|
164
|
+
case 'timePicker':
|
|
165
|
+
case 'datePicker':
|
|
166
|
+
if (mode === '查询') {
|
|
167
|
+
// console.log(querySelectDefaultValue.value)
|
|
168
|
+
return props.modelValue !== undefined ? props.modelValue : querySelectDefaultValue.value
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
// console.log(formSelectDefaultValue.value)
|
|
172
|
+
return props.modelValue !== undefined ? props.modelValue : formSelectDefaultValue.value
|
|
173
|
+
}
|
|
174
|
+
// case 'datePicker':
|
|
175
|
+
// if (mode === '查询') {
|
|
176
|
+
// // console.log(querySelectDefaultValue.value)
|
|
177
|
+
// return props.modelValue !== undefined ? props.modelValue : querySelectDefaultValue.value
|
|
178
|
+
// }
|
|
179
|
+
// else {
|
|
180
|
+
// if (props.modelValue !== undefined) {
|
|
181
|
+
// // 拆分日期和时间
|
|
182
|
+
// const [dateStr, timeStr] = props.modelValue.split(' ')
|
|
183
|
+
// // 拆分日期部分
|
|
184
|
+
// const date = dateStr.split('-')
|
|
185
|
+
// // 拆分时间部分
|
|
186
|
+
// const time = timeStr.split(':')
|
|
187
|
+
// // 赋值给 dateTimePickerValue
|
|
188
|
+
// // eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
|
189
|
+
// dateTimePickerValue.value = {
|
|
190
|
+
// date,
|
|
191
|
+
// time,
|
|
192
|
+
// }
|
|
193
|
+
// return dateTimePickerValue.value
|
|
194
|
+
// }
|
|
195
|
+
// return formSelectDefaultValue.value
|
|
196
|
+
// }
|
|
197
|
+
case 'radio':
|
|
198
|
+
case 'rate':
|
|
199
|
+
case 'slider':
|
|
200
|
+
case 'area':
|
|
201
|
+
case 'citySelect':
|
|
202
|
+
case 'calendar':
|
|
203
|
+
case 'textarea':
|
|
204
|
+
case 'intervalPicker':
|
|
205
|
+
case 'input':
|
|
206
|
+
case 'select':
|
|
207
|
+
if (mode === '查询')
|
|
208
|
+
return props.modelValue !== undefined ? props.modelValue : queryInputDefaultValue.value
|
|
209
|
+
else
|
|
210
|
+
return props.modelValue !== undefined ? props.modelValue : formInputDefaultValue.value
|
|
211
|
+
case 'stepper':
|
|
212
|
+
return props.modelValue !== undefined ? props.modelValue : 1
|
|
213
|
+
case 'rangePicker':
|
|
214
|
+
if (props.modelValue && Array.isArray(props.modelValue) && props.modelValue.length > 1)
|
|
215
|
+
return `${props.modelValue[0]} ~ ${props.modelValue[1]}`
|
|
216
|
+
|
|
217
|
+
else
|
|
218
|
+
return props.modelValue
|
|
219
|
+
|
|
220
|
+
default:
|
|
221
|
+
return undefined
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
set(newValue) {
|
|
225
|
+
emits('update:modelValue', newValue)
|
|
226
|
+
dataChangeFunc()
|
|
227
|
+
},
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
// 表单校验的类型校验
|
|
231
|
+
function formTypeCheck(attr, value) {
|
|
232
|
+
switch (attr.rule.type) {
|
|
233
|
+
case 'string':
|
|
234
|
+
if (value.length === 0) {
|
|
235
|
+
errorMessage.value = `${attr.name}必须为有效的字符串`
|
|
236
|
+
return
|
|
237
|
+
}
|
|
238
|
+
break
|
|
239
|
+
case 'number':
|
|
240
|
+
if (!/^[+-]?(\d+(\.\d*)?|\.\d+)$/.test(value)) {
|
|
241
|
+
errorMessage.value = `${attr.name}必须为数字`
|
|
242
|
+
return
|
|
243
|
+
}
|
|
244
|
+
break
|
|
245
|
+
case 'boolean':
|
|
246
|
+
case 'array':
|
|
247
|
+
case 'regexp':
|
|
248
|
+
if (value) {
|
|
249
|
+
errorMessage.value = ''
|
|
250
|
+
return
|
|
251
|
+
}
|
|
252
|
+
break
|
|
253
|
+
case 'integer':
|
|
254
|
+
if (!/^-?\d+$/.test(value)) {
|
|
255
|
+
errorMessage.value = `${attr.name}必须为整数`
|
|
256
|
+
return
|
|
257
|
+
}
|
|
258
|
+
break
|
|
259
|
+
case 'float':
|
|
260
|
+
if (!/^-?\d+\.\d+$/.test(value)) {
|
|
261
|
+
errorMessage.value = `${attr.name}必须为小数`
|
|
262
|
+
return
|
|
263
|
+
}
|
|
264
|
+
break
|
|
265
|
+
case 'email':
|
|
266
|
+
if (!/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(value)) {
|
|
267
|
+
errorMessage.value = `请输入正确的邮箱地址`
|
|
268
|
+
return
|
|
269
|
+
}
|
|
270
|
+
break
|
|
271
|
+
case 'idNumber':
|
|
272
|
+
if (!/^(^\d{15}$|^\d{17}([0-9]|X)$)$/.test(value)) {
|
|
273
|
+
errorMessage.value = `请输入正确的身份证号码`
|
|
274
|
+
return
|
|
275
|
+
}
|
|
276
|
+
break
|
|
277
|
+
case 'userPhone':
|
|
278
|
+
if (!/^1[3-9]\d{9}$/.test(value)) {
|
|
279
|
+
errorMessage.value = `请输入正确的手机号码`
|
|
280
|
+
return
|
|
281
|
+
}
|
|
282
|
+
break
|
|
283
|
+
case 'landlineNumber':
|
|
284
|
+
if (!/^(0\d{2,3}[-\s]?)\d{7,8}$/.test(value)) {
|
|
285
|
+
errorMessage.value = `请输入正确的座机号码`
|
|
286
|
+
return
|
|
287
|
+
}
|
|
288
|
+
break
|
|
289
|
+
case 'greaterThanZero':
|
|
290
|
+
if (!/^(?:[1-9]\d*(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/.test(value)) {
|
|
291
|
+
errorMessage.value = `请输入一个大于0的数字`
|
|
292
|
+
return
|
|
293
|
+
}
|
|
294
|
+
break
|
|
295
|
+
case 'greaterThanOrEqualZero':
|
|
296
|
+
if (!/^(?:\d+|\d*\.\d+)$/.test(value)) {
|
|
297
|
+
errorMessage.value = `请输入一个大于等于0的数字`
|
|
298
|
+
return
|
|
299
|
+
}
|
|
300
|
+
break
|
|
301
|
+
case 'stringLength':
|
|
302
|
+
if (!(value.length >= attr.rule.minLen && value.length < attr.rule.maxLen)) {
|
|
303
|
+
errorMessage.value = `长度必须在${attr.rule.minLen}~${attr.rule.maxLen}之间`
|
|
304
|
+
return
|
|
305
|
+
}
|
|
306
|
+
break
|
|
307
|
+
case 'customJs':
|
|
308
|
+
// eslint-disable-next-line no-case-declarations
|
|
309
|
+
const funcStr = attr.rule.customValidatorFunc
|
|
310
|
+
// 输入的数据是否符合条件
|
|
311
|
+
// eslint-disable-next-line no-case-declarations
|
|
312
|
+
const status = ref(true)
|
|
313
|
+
// 提取函数体部分
|
|
314
|
+
// eslint-disable-next-line no-case-declarations
|
|
315
|
+
const funcBodyMatch = funcStr.match(/function\s*\(.*?\)\s*{([\s\S]*)}/)
|
|
316
|
+
if (!funcBodyMatch)
|
|
317
|
+
throw new Error('自定义校验函数不合法')
|
|
318
|
+
// eslint-disable-next-line no-case-declarations
|
|
319
|
+
const funcBody = funcBodyMatch[1].trim() // 提取函数体
|
|
320
|
+
// 使用 new Function 创建函数
|
|
321
|
+
// eslint-disable-next-line no-new-func,no-case-declarations
|
|
322
|
+
const customValidatorFunc = new Function('rule', 'value', 'callback', 'form', 'attr', 'util', funcBody)
|
|
323
|
+
// 定义 callback 函数
|
|
324
|
+
// eslint-disable-next-line no-case-declarations
|
|
325
|
+
const callback = (error) => {
|
|
326
|
+
if (error) {
|
|
327
|
+
errorMessage.value = `${error}`
|
|
328
|
+
status.value = false // 表示有错误发生
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
// 调用自定义校验函数
|
|
332
|
+
customValidatorFunc(
|
|
333
|
+
attr.rule,
|
|
334
|
+
value,
|
|
335
|
+
callback,
|
|
336
|
+
form,
|
|
337
|
+
attr,
|
|
338
|
+
{}, // util 对象(可以根据需要传递)
|
|
339
|
+
)
|
|
340
|
+
if (!status.value)
|
|
341
|
+
return
|
|
342
|
+
break
|
|
343
|
+
default:
|
|
344
|
+
errorMessage.value = ''
|
|
345
|
+
break
|
|
346
|
+
}
|
|
347
|
+
errorMessage.value = ''
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
onBeforeMount(() => {
|
|
351
|
+
init()
|
|
352
|
+
showFormItemFunc()
|
|
353
|
+
dataChangeFunc()
|
|
354
|
+
if (attr?.keyName?.toString()?.startsWith('search@根据表单项[') && attr?.keyName?.toString().endsWith(']联动人员'))
|
|
355
|
+
debouncedUserLinkFunc = debounce(() => updateResOptions('人员'), 200)
|
|
356
|
+
|
|
357
|
+
if (attr?.keyName?.toString()?.startsWith('search@根据表单项[') && attr?.keyName?.toString().endsWith(']联动部门'))
|
|
358
|
+
debouncedDepLinkFunc = debounce(() => updateResOptions('部门'), 200)
|
|
359
|
+
})
|
|
360
|
+
// 是否展示表单左侧label文字
|
|
361
|
+
const labelData = computed(() => {
|
|
362
|
+
return props.showLabel ? attr.name : null
|
|
363
|
+
})
|
|
364
|
+
// 是否展示表单左侧label文字
|
|
365
|
+
const labelAlign = computed(() => {
|
|
366
|
+
return attr.labelAlign ? attr.labelAlign : 'top'
|
|
367
|
+
})
|
|
368
|
+
// 是否只读
|
|
369
|
+
const readonly = computed(() => {
|
|
370
|
+
return attr.addOrEdit === 'readonly' || mode === '预览'
|
|
371
|
+
})
|
|
372
|
+
// 提示内容
|
|
373
|
+
const placeholder = computed(() => {
|
|
374
|
+
if (attr.addOrEdit === 'readonly')
|
|
375
|
+
return ' 暂无内容 ~ '
|
|
376
|
+
else
|
|
377
|
+
return attr.placeholder ? attr.placeholder : `请选择${attr.name}`
|
|
378
|
+
})
|
|
379
|
+
// 登录信息 (可以在配置的动态函数中使用 this.setupState 获取到当前组件内的全部函数和变量 例:this.setupState.userState)
|
|
380
|
+
const userState = useUserStore().getLogin()
|
|
381
|
+
|
|
382
|
+
const formatDate = date => `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`
|
|
383
|
+
|
|
384
|
+
function onCalendarConfirm(values) {
|
|
385
|
+
localValue.value = [formatDate(values[0]), formatDate(values[1])]
|
|
386
|
+
calendarShow.value = false
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function init() {
|
|
390
|
+
if (attr.keyName && typeof attr.keyName === 'string') {
|
|
391
|
+
if (attr.keyName && attr.keyName.includes('logic@')) {
|
|
392
|
+
getData({}, (res) => {
|
|
393
|
+
option.value = res
|
|
394
|
+
initRadioValue()
|
|
395
|
+
})
|
|
396
|
+
}
|
|
397
|
+
else if (attr.keyName && attr.keyName.includes('config@')) {
|
|
398
|
+
const configName = attr.keyName.substring(7)
|
|
399
|
+
getDict(configName, (result) => {
|
|
400
|
+
if (result)
|
|
401
|
+
option.value = result
|
|
402
|
+
}, serviceName)
|
|
403
|
+
}
|
|
404
|
+
else if (attr.keyName && attr.keyName.includes('search@')) {
|
|
405
|
+
let source = attr.keyName.substring(7)
|
|
406
|
+
const userid = currUser.value
|
|
407
|
+
let roleName = 'roleName'
|
|
408
|
+
if (source.startsWith('根据角色[') && source.endsWith(']获取人员')) {
|
|
409
|
+
const startIndex = source.indexOf('[') + 1
|
|
410
|
+
const endIndex = source.indexOf(']', startIndex)
|
|
411
|
+
roleName = source.substring(startIndex, endIndex)
|
|
412
|
+
source = '根据角色获取人员'
|
|
413
|
+
}
|
|
414
|
+
const searchData = { source, userid, roleName }
|
|
415
|
+
if (source.startsWith('根据表单项[') && source.endsWith(']联动人员'))
|
|
416
|
+
updateResOptions('人员')
|
|
417
|
+
else if (source.startsWith('根据表单项[') && source.endsWith(']联动部门'))
|
|
418
|
+
updateResOptions('部门')
|
|
419
|
+
else if (attr.type === 'select' || attr.type === 'checkbox')
|
|
420
|
+
searchToListOption(searchData, res => getDataCallback(res))
|
|
421
|
+
else
|
|
422
|
+
searchToOption(searchData, res => getDataCallback(res))
|
|
423
|
+
}
|
|
424
|
+
else {
|
|
425
|
+
initRadioValue()
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
if (attr.type === 'radio' || attr.type === 'rate' || attr.type === 'slider' || attr.type === 'area' || attr.type === 'citySelect' || attr.type === 'calendar' || attr.type === 'textarea' || attr.type === 'intervalPicker' || attr.type === 'input' || attr.type === 'select') {
|
|
429
|
+
if (attr.formDefault)
|
|
430
|
+
formInputDefaultValue.value = attr.formDefault
|
|
431
|
+
if (attr.queryFormDefault)
|
|
432
|
+
queryInputDefaultValue.value = attr.queryFormDefault
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
if (attr.type === 'checkbox' || attr.type === 'uploader' || attr.type === 'file' || attr.type === 'image' || attr.type === 'datePicker' || attr.type === 'timePicker') {
|
|
436
|
+
if (attr.formDefault) {
|
|
437
|
+
if (attr.type === 'checkbox' || attr.type === 'image' || attr.type === 'file')
|
|
438
|
+
formSelectDefaultValue.value = attr.formDefault
|
|
439
|
+
else
|
|
440
|
+
formSelectDefaultValue.value.push(attr.formDefault)
|
|
441
|
+
}
|
|
442
|
+
if (attr.queryFormDefault) {
|
|
443
|
+
// console.log(querySelectDefaultValue.value)
|
|
444
|
+
querySelectDefaultValue.value.push(attr.queryFormDefault)
|
|
445
|
+
// querySelectDefaultValue.value = attr.queryFormDefault
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
function getDataCallback(res) {
|
|
451
|
+
option.value = res
|
|
452
|
+
if (attr.type === 'radio')
|
|
453
|
+
initRadioValue()
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
async function updateResOptions(type) {
|
|
457
|
+
if (attr?.keyName?.toString()?.startsWith('search@根据表单项[') && attr?.keyName?.toString()?.endsWith(`]联动${type}`)) {
|
|
458
|
+
const searchData = { source: `获取${type}`, userid: currUser.value }
|
|
459
|
+
const startIndex = attr.keyName.indexOf('[') + 1
|
|
460
|
+
const endIndex = attr.keyName.indexOf(']', startIndex)
|
|
461
|
+
const formModel = attr.keyName.substring(startIndex, endIndex).replace('.', '_')
|
|
462
|
+
// console.log(form)
|
|
463
|
+
const formModelData = form[formModel]
|
|
464
|
+
if (formModel?.length && formModelData?.length) {
|
|
465
|
+
await searchToListOption(searchData, (res) => {
|
|
466
|
+
// console.log(res)
|
|
467
|
+
// console.log(form)
|
|
468
|
+
getDataCallback(res.filter((h) => {
|
|
469
|
+
return formModelData['0'] === h.f_organization_id || formModelData['0'] === h.f_department_id || formModelData['0'] === h.parentid
|
|
470
|
+
// if (formModel.indexOf('org') > -1) {
|
|
471
|
+
// return formModelData?.includes(h.orgid || h.f_organization_id || h.parentid)
|
|
472
|
+
// } else {
|
|
473
|
+
// return formModelData?.includes(h?.parentid)
|
|
474
|
+
// }
|
|
475
|
+
}))
|
|
476
|
+
})
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
function initRadioValue() {
|
|
482
|
+
if ((mode === '新增' || mode === '修改') && attr.type === 'radio' && !localValue.value) {
|
|
483
|
+
if (attr.keys && attr.keys.length > 0)
|
|
484
|
+
localValue.value = attr.keys[0].value
|
|
485
|
+
else if (option.value && option.value.length > 0)
|
|
486
|
+
localValue.value = option.value[0].value
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
function getData(value, callback) {
|
|
491
|
+
if (value !== '') {
|
|
492
|
+
const logicName = attr.keyName
|
|
493
|
+
const logic = logicName.substring(6)
|
|
494
|
+
// 调用logic前设置参数
|
|
495
|
+
if (getDataParams && getDataParams[attr.model])
|
|
496
|
+
Object.assign(value, getDataParams[attr.model])
|
|
497
|
+
|
|
498
|
+
runLogic(logic, value, serviceName).then((res) => {
|
|
499
|
+
callback(res)
|
|
500
|
+
})
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
function onPickerConfirm({ selectedOptions }) {
|
|
505
|
+
showPicker.value = false
|
|
506
|
+
pickerValue.value = selectedOptions[0].text
|
|
507
|
+
emits('update:modelValue', [selectedOptions[0].text])
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// 日期时间选择数据
|
|
511
|
+
const dateTimePickerValue = ref(undefined)
|
|
512
|
+
function showDataTimePicker() {
|
|
513
|
+
if (props.modelValue !== undefined && props.modelValue !== '' && props.modelValue !== null) {
|
|
514
|
+
// 拆分日期和时间
|
|
515
|
+
const [dateStr, timeStr] = props.modelValue.split(' ')
|
|
516
|
+
// 拆分日期部分
|
|
517
|
+
const date = dateStr.split('-')
|
|
518
|
+
// 拆分时间部分
|
|
519
|
+
const time = timeStr.split(':')
|
|
520
|
+
// 赋值给 dateTimePickerValue
|
|
521
|
+
dateTimePickerValue.value = {
|
|
522
|
+
date,
|
|
523
|
+
time,
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
else {
|
|
527
|
+
dateTimePickerValue.value = {
|
|
528
|
+
date: ['2015', '01', '01'],
|
|
529
|
+
time: ['00', '00', '00'],
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
showDatePicker.value = true
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
function onDatePickerConfirm({ selectedValues }) {
|
|
536
|
+
showDatePicker.value = false
|
|
537
|
+
localValue.value = selectedValues.join('-')
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
function onTimePickerConfirm({ selectedValues }) {
|
|
541
|
+
showTimePicker.value = false
|
|
542
|
+
timePickerValue.value = selectedValues.join(':')
|
|
543
|
+
emits('update:modelValue', timePickerValue.value)
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
function onAreaConfirm({ selectedOptions }) {
|
|
547
|
+
area.value = `${selectedOptions[0].text}-${selectedOptions[1].text}-${selectedOptions[2].text}`
|
|
548
|
+
showArea.value = false
|
|
549
|
+
emits('update:modelValue', [{
|
|
550
|
+
province: selectedOptions[0].text,
|
|
551
|
+
city: selectedOptions[1].text,
|
|
552
|
+
district: selectedOptions[2].text,
|
|
553
|
+
}])
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
function updateFile(files, _index) {
|
|
557
|
+
files.forEach((file) => {
|
|
558
|
+
if (file.content)
|
|
559
|
+
delete file.content
|
|
560
|
+
if (file.file)
|
|
561
|
+
delete file.file
|
|
562
|
+
if (file.objectUrl)
|
|
563
|
+
delete file.objectUrl
|
|
564
|
+
})
|
|
565
|
+
localValue.value = files
|
|
566
|
+
emits('update:modelValue', localValue.value)
|
|
567
|
+
}
|
|
568
|
+
// 监听表单发生变化后触发展示函数
|
|
569
|
+
watch(() => form, (_oldVal, _newVal) => {
|
|
570
|
+
showFormItemFunc()
|
|
571
|
+
// 数据源来自人员联动时更新数据
|
|
572
|
+
if (attr?.keyName?.toString()?.startsWith('search@根据表单项[') && attr?.keyName?.toString().endsWith(']联动人员'))
|
|
573
|
+
debouncedUserLinkFunc()
|
|
574
|
+
|
|
575
|
+
// 数据源来自部门联动时更新数据
|
|
576
|
+
if (attr?.keyName?.toString()?.startsWith('search@根据表单项[') && attr?.keyName?.toString().endsWith(']联动部门'))
|
|
577
|
+
debouncedDepLinkFunc()
|
|
578
|
+
}, { deep: true })
|
|
579
|
+
|
|
580
|
+
function onDateTimePickerConfirm() {
|
|
581
|
+
showDatePicker.value = false
|
|
582
|
+
const dateStr = dateTimePickerValue.value.date.join('-')
|
|
583
|
+
const timeStr = dateTimePickerValue.value.time.join(':')
|
|
584
|
+
localValue.value = `${dateStr} ${timeStr}`
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
function onPickerCancel() {
|
|
588
|
+
showDatePicker.value = false
|
|
589
|
+
}
|
|
590
|
+
</script>
|
|
591
|
+
|
|
592
|
+
<template>
|
|
593
|
+
<div>
|
|
594
|
+
<!-- switch开关 -->
|
|
595
|
+
<VanField
|
|
596
|
+
v-if="attr.type === 'switch' && showItem"
|
|
597
|
+
name="switch"
|
|
598
|
+
:label="labelData"
|
|
599
|
+
:label-align="labelAlign"
|
|
600
|
+
:input-align="attr.inputAlign ? attr.inputAlign : 'right'"
|
|
601
|
+
:rules="[{ required: attr.rule.required === 'true', message: '请选择' }]"
|
|
602
|
+
>
|
|
603
|
+
<template #input>
|
|
604
|
+
<VanSwitch v-model="localValue" />
|
|
605
|
+
</template>
|
|
606
|
+
</VanField>
|
|
607
|
+
|
|
608
|
+
<!-- 复选框 -->
|
|
609
|
+
<!-- <VanField
|
|
610
|
+
v-if="attr.type === 'checkbox'"
|
|
611
|
+
name="checkbox"
|
|
612
|
+
:label="labelData"
|
|
613
|
+
>
|
|
614
|
+
<template #input>
|
|
615
|
+
<VanCheckbox v-model="localValue" shape="square" />
|
|
616
|
+
</template>
|
|
617
|
+
</VanField> -->
|
|
618
|
+
|
|
619
|
+
<!-- 多选框-checkbox-复选框组 -->
|
|
620
|
+
<template v-if="attr.type === 'checkbox' && showItem">
|
|
621
|
+
<!-- 勾选 -->
|
|
622
|
+
<VanField
|
|
623
|
+
v-if="attr.showMode === 'checkbox' && mode !== '查询'"
|
|
624
|
+
name="checkboxGroup"
|
|
625
|
+
:label="labelData"
|
|
626
|
+
:label-align="labelAlign"
|
|
627
|
+
:input-align="attr.inputAlign ? attr.inputAlign : 'left'"
|
|
628
|
+
:rules="[{ required: attr.rule.required === 'true', message: `请选择${attr.name}` }]"
|
|
629
|
+
>
|
|
630
|
+
<template #input>
|
|
631
|
+
<van-checkbox-group v-model="localValue as any[]" direction="horizontal" shape="square" :disabled="readonly">
|
|
632
|
+
<VanCheckbox v-for="(item, index) in option" :key="index" style="padding: 2px" :name="item[columnsField.value]" :shape="rules?.[attr.model].shape" :value="item[columnsField.value]">
|
|
633
|
+
{{ item[columnsField.text] }}
|
|
634
|
+
</VanCheckbox>
|
|
635
|
+
</van-checkbox-group>
|
|
636
|
+
</template>
|
|
637
|
+
</VanField>
|
|
638
|
+
<VanField
|
|
639
|
+
v-if="attr.showMode === 'checkbox' && mode === '查询'"
|
|
640
|
+
name="checkboxGroup"
|
|
641
|
+
:label="labelData"
|
|
642
|
+
:label-align="labelAlign"
|
|
643
|
+
:input-align="attr.inputAlign ? attr.inputAlign : 'left'"
|
|
644
|
+
:rules="[{ required: attr.rule.required === 'true', message: `请选择${attr.name}` }]"
|
|
645
|
+
>
|
|
646
|
+
<template #input>
|
|
647
|
+
<XGridDropOption
|
|
648
|
+
v-model="(localValue as string[])"
|
|
649
|
+
:column-num="labelData ? 3 : 4"
|
|
650
|
+
:multiple="true"
|
|
651
|
+
:columns="option"
|
|
652
|
+
/>
|
|
653
|
+
</template>
|
|
654
|
+
</VanField>
|
|
655
|
+
<!-- 下拉 -->
|
|
656
|
+
<XMultiSelect
|
|
657
|
+
v-else
|
|
658
|
+
v-model="localValue"
|
|
659
|
+
:label="labelData"
|
|
660
|
+
:readonly="readonly"
|
|
661
|
+
:placeholder="placeholder"
|
|
662
|
+
:columns="option"
|
|
663
|
+
:option="attr.option ? attr.option : columnsField"
|
|
664
|
+
:rules="[{ required: attr.rule.required === 'true', message: `请选择${attr.name}` }]"
|
|
665
|
+
/>
|
|
666
|
+
</template>
|
|
667
|
+
|
|
668
|
+
<!-- 单选框 -->
|
|
669
|
+
<VanField
|
|
670
|
+
v-if="attr.type === 'radio' && mode !== '查询' && showItem"
|
|
671
|
+
name="radio"
|
|
672
|
+
:placeholder="attr.placeholder ? attr.placeholder : `请选择${attr.name}`"
|
|
673
|
+
:label="labelData"
|
|
674
|
+
:label-align="labelAlign"
|
|
675
|
+
:input-align="attr.inputAlign ? attr.inputAlign : 'left'"
|
|
676
|
+
:rules="[{ required: attr.rule.required === 'true', message: `请选择${attr.name}` }]"
|
|
677
|
+
>
|
|
678
|
+
<template #input>
|
|
679
|
+
<VanRadioGroup v-model="localValue" direction="horizontal" :disabled="readonly">
|
|
680
|
+
<VanRadio v-for="(item, index) in option" :key="index" style="padding: 2px" :name="item[columnsField.value]" :value="item[columnsField.value]">
|
|
681
|
+
{{ item[columnsField.text] }}
|
|
682
|
+
</VanRadio>
|
|
683
|
+
</VanRadioGroup>
|
|
684
|
+
</template>
|
|
685
|
+
</VanField>
|
|
686
|
+
|
|
687
|
+
<!-- 单选框-查询 -->
|
|
688
|
+
<VanField
|
|
689
|
+
v-if="attr.type === 'radio' && mode === '查询' && showItem"
|
|
690
|
+
name="radio"
|
|
691
|
+
:placeholder="attr.placeholder ? attr.placeholder : `请选择${attr.name}`"
|
|
692
|
+
:label="labelData"
|
|
693
|
+
:label-align="labelAlign"
|
|
694
|
+
:input-align="attr.inputAlign ? attr.inputAlign : 'left'"
|
|
695
|
+
:rules="[{ required: attr.rule.required === 'true', message: `请选择${attr.name}` }]"
|
|
696
|
+
>
|
|
697
|
+
<template #input>
|
|
698
|
+
<XGridDropOption
|
|
699
|
+
v-model="(localValue as string)"
|
|
700
|
+
:column-num="labelData ? 3 : 4"
|
|
701
|
+
:columns="option"
|
|
702
|
+
/>
|
|
703
|
+
</template>
|
|
704
|
+
</VanField>
|
|
705
|
+
|
|
706
|
+
<!-- 步进器 -->
|
|
707
|
+
<VanField
|
|
708
|
+
v-if="attr.type === 'stepper' && showItem"
|
|
709
|
+
name="stepper"
|
|
710
|
+
:label="labelData"
|
|
711
|
+
:label-align="labelAlign"
|
|
712
|
+
:input-align="attr.inputAlign ? attr.inputAlign : 'center'"
|
|
713
|
+
:rules="[{ required: attr.rule.required === 'true', message: '请选择' }]"
|
|
714
|
+
>
|
|
715
|
+
<template #input>
|
|
716
|
+
<VanStepper :disabled="readonly" v-model="(localValue as string)" />
|
|
717
|
+
</template>
|
|
718
|
+
</VanField>
|
|
719
|
+
|
|
720
|
+
<!-- 评分 -->
|
|
721
|
+
<VanField
|
|
722
|
+
v-if="attr.type === 'rate' && showItem"
|
|
723
|
+
name="rate"
|
|
724
|
+
:label="labelData"
|
|
725
|
+
:label-align="labelAlign"
|
|
726
|
+
:input-align="attr.inputAlign ? attr.inputAlign : 'center'"
|
|
727
|
+
:rules="[{ required: attr.rule.required === 'true', message: '请选择' }]"
|
|
728
|
+
>
|
|
729
|
+
<template #input>
|
|
730
|
+
<VanRate :size="25" :count="attr.displayCount || 5" :readonly="readonly" void-color="#eee" void-icon="star" color="#ffd21e" v-model="(localValue as number)" />
|
|
731
|
+
</template>
|
|
732
|
+
</VanField>
|
|
733
|
+
|
|
734
|
+
<!-- 滑块 -->
|
|
735
|
+
<VanField
|
|
736
|
+
v-if="attr.type === 'slider' && showItem"
|
|
737
|
+
name="slider"
|
|
738
|
+
:label="labelData"
|
|
739
|
+
:label-align="labelAlign"
|
|
740
|
+
:input-align="attr.inputAlign ? attr.inputAlign : 'left'"
|
|
741
|
+
:rules="[{ required: attr.rule.required === 'true', message: '请选择' }]"
|
|
742
|
+
>
|
|
743
|
+
<template #input>
|
|
744
|
+
<VanSlider :readonly="readonly" v-model="(localValue as number)" />
|
|
745
|
+
</template>
|
|
746
|
+
</VanField>
|
|
747
|
+
|
|
748
|
+
<!-- 图片文件上传 -->
|
|
749
|
+
<VanField
|
|
750
|
+
v-if="(attr.type === 'image' || attr.type === 'file') && showItem"
|
|
751
|
+
name="uploader"
|
|
752
|
+
:label="labelData"
|
|
753
|
+
:label-align="labelAlign"
|
|
754
|
+
:input-align="attr.inputAlign ? attr.inputAlign : 'left'"
|
|
755
|
+
:rules="[{ required: attr.rule.required === 'true', message: '请选择' }]"
|
|
756
|
+
>
|
|
757
|
+
<template #input>
|
|
758
|
+
<!-- <van-uploader v-model="localValue" /> -->
|
|
759
|
+
<Uploader
|
|
760
|
+
upload-mode="server"
|
|
761
|
+
:image-list="(localValue as any[])"
|
|
762
|
+
authority="admin"
|
|
763
|
+
@update-file-list="updateFile"
|
|
764
|
+
/>
|
|
765
|
+
</template>
|
|
766
|
+
</VanField>
|
|
767
|
+
|
|
768
|
+
<!-- 选择器 -->
|
|
769
|
+
<VanField
|
|
770
|
+
v-if="attr.type === 'picker' && showItem"
|
|
771
|
+
v-model="pickerValue"
|
|
772
|
+
name="picker"
|
|
773
|
+
:placeholder="attr.placeholder ? attr.placeholder : `请选择${attr.name}`"
|
|
774
|
+
:label="labelData"
|
|
775
|
+
:label-align="labelAlign"
|
|
776
|
+
:input-align="attr.inputAlign ? attr.inputAlign : 'left'"
|
|
777
|
+
readonly
|
|
778
|
+
is-link
|
|
779
|
+
:rules="[{ required: attr.rule.required === 'true', message: '请选择' }]"
|
|
780
|
+
@click="readonly ? null : showPicker = true"
|
|
781
|
+
/>
|
|
782
|
+
<VanPopup v-model:show="showPicker" round position="bottom" teleport="body">
|
|
783
|
+
<VanPicker
|
|
784
|
+
v-model="(localValue as Numeric[])"
|
|
785
|
+
:title="attr.name"
|
|
786
|
+
:columns="attr.selectKey"
|
|
787
|
+
:readonly="readonly"
|
|
788
|
+
:columns-field-names="attr.customFieldName ? attr.customFieldName : { text: 'text', value: 'value', children: 'children' }"
|
|
789
|
+
:confirm-button-text="attr.confirmButtonText || attr.confirmButtonText === '' ? attr.confirmButtonText : '确认'"
|
|
790
|
+
:cancel-button-text="attr.cancelButtonText || attr.cancelButtonText === '' ? attr.cancelButtonText : '取消'"
|
|
791
|
+
@cancel="showPicker = false"
|
|
792
|
+
@confirm="onPickerConfirm"
|
|
793
|
+
/>
|
|
794
|
+
</VanPopup>
|
|
795
|
+
|
|
796
|
+
<!-- 日历选择-查询 -->
|
|
797
|
+
<VanField
|
|
798
|
+
v-if="attr.type === 'rangePicker' && mode === '查询' && showItem"
|
|
799
|
+
v-model="(localValue as string | number)"
|
|
800
|
+
is-link
|
|
801
|
+
readonly
|
|
802
|
+
name="rangePicker"
|
|
803
|
+
:label="labelData"
|
|
804
|
+
:label-align="labelAlign"
|
|
805
|
+
:input-align="attr.inputAlign ? attr.inputAlign : 'left'"
|
|
806
|
+
:placeholder="attr.placeholder ? attr.placeholder : `请选择${attr.name}`"
|
|
807
|
+
:rules="[{ required: attr.rule.required === 'true', message: '请选择' }]"
|
|
808
|
+
@click="calendarShow = true"
|
|
809
|
+
/>
|
|
810
|
+
<VanCalendar
|
|
811
|
+
v-model:show="calendarShow"
|
|
812
|
+
switch-mode="year-month"
|
|
813
|
+
allow-same-day
|
|
814
|
+
type="range"
|
|
815
|
+
teleport="body"
|
|
816
|
+
:show-confirm="attr.showConfirm"
|
|
817
|
+
@confirm="onCalendarConfirm"
|
|
818
|
+
/>
|
|
819
|
+
|
|
820
|
+
<!-- 日期选择-非查询 -->
|
|
821
|
+
<VanField
|
|
822
|
+
v-if="(attr.type === 'datePicker' || attr.type === 'rangePicker') && mode !== '查询' && showItem"
|
|
823
|
+
v-model="(localValue as string | number)"
|
|
824
|
+
name="datePicker"
|
|
825
|
+
:label="labelData"
|
|
826
|
+
:label-align="labelAlign"
|
|
827
|
+
:input-align="attr.inputAlign ? attr.inputAlign : 'left'"
|
|
828
|
+
readonly
|
|
829
|
+
:is-link="true"
|
|
830
|
+
:placeholder="placeholder"
|
|
831
|
+
:rules="[{ required: attr.rule.required === 'true', message: '请选择' }]"
|
|
832
|
+
@click="readonly ? null : showDataTimePicker()"
|
|
833
|
+
/>
|
|
834
|
+
<VanPopup v-model:show="showDatePicker" position="bottom" teleport="body">
|
|
835
|
+
<VanPickerGroup
|
|
836
|
+
:title="attr.name"
|
|
837
|
+
:tabs="['选择日期', '选择时间']"
|
|
838
|
+
next-step-text="下一步"
|
|
839
|
+
:confirm-button-text="attr.confirmButtonText ? attr.confirmButtonText : '确认'"
|
|
840
|
+
:cancel-button-text="attr.cancelButtonText ? attr.cancelButtonText : '取消'"
|
|
841
|
+
@confirm="onDateTimePickerConfirm"
|
|
842
|
+
@cancel="onPickerCancel"
|
|
843
|
+
>
|
|
844
|
+
<VanDatePicker
|
|
845
|
+
v-model="dateTimePickerValue.date"
|
|
846
|
+
:columns-type="attr.columnsType ? attr.columnsType : ['year', 'month', 'day']"
|
|
847
|
+
/>
|
|
848
|
+
<VanTimePicker
|
|
849
|
+
v-model="dateTimePickerValue.time"
|
|
850
|
+
:columns-type="['hour', 'minute', 'second']"
|
|
851
|
+
:min-time="attr.minTime ? attr.minTime : '00:00:00'"
|
|
852
|
+
:max-time="attr.maxTime ? attr.maxTime : '23:59:59'"
|
|
853
|
+
/>
|
|
854
|
+
</VanPickerGroup>
|
|
855
|
+
</VanPopup>
|
|
856
|
+
|
|
857
|
+
<!-- 日期选择-查询 -->
|
|
858
|
+
<VanField
|
|
859
|
+
v-if="attr.type === 'datePicker' && mode === '查询' && showItem"
|
|
860
|
+
v-model="(localValue as string | number)"
|
|
861
|
+
name="datePicker"
|
|
862
|
+
:label="labelData"
|
|
863
|
+
:label-align="labelAlign"
|
|
864
|
+
:input-align="attr.inputAlign ? attr.inputAlign : 'left'"
|
|
865
|
+
readonly
|
|
866
|
+
:is-link="true"
|
|
867
|
+
:placeholder="attr.placeholder ? attr.placeholder : `请选择${attr.name}`"
|
|
868
|
+
:rules="[{ required: attr.rule.required === 'true', message: '请选择' }]"
|
|
869
|
+
@click="showDatePicker = true"
|
|
870
|
+
/>
|
|
871
|
+
<VanPopup v-model:show="showDatePicker" position="bottom" teleport="body">
|
|
872
|
+
<VanPickerGroup
|
|
873
|
+
:title="attr.name"
|
|
874
|
+
:tabs="['选择日期', '选择时间']"
|
|
875
|
+
next-step-text="下一步"
|
|
876
|
+
:confirm-button-text="attr.confirmButtonText ? attr.confirmButtonText : '确认'"
|
|
877
|
+
:cancel-button-text="attr.cancelButtonText ? attr.cancelButtonText : '取消'"
|
|
878
|
+
@confirm="onDateTimePickerConfirm"
|
|
879
|
+
@cancel="onPickerCancel"
|
|
880
|
+
>
|
|
881
|
+
<VanDatePicker
|
|
882
|
+
v-model="dateTimePickerValue.date"
|
|
883
|
+
:columns-type="attr.columnsType ? attr.columnsType : ['year', 'month', 'day']"
|
|
884
|
+
:readonly="attr.readonly ? attr.readonly : false"
|
|
885
|
+
/>
|
|
886
|
+
<VanTimePicker
|
|
887
|
+
v-model="dateTimePickerValue.time"
|
|
888
|
+
:columns-type="['hour', 'minute', 'second']"
|
|
889
|
+
:min-time="attr.minTime ? attr.minTime : '00:00:00'"
|
|
890
|
+
:max-time="attr.maxTime ? attr.maxTime : '23:59:59'"
|
|
891
|
+
:readonly="attr.readonly ? attr.readonly : false"
|
|
892
|
+
/>
|
|
893
|
+
</VanPickerGroup>
|
|
894
|
+
</VanPopup>
|
|
895
|
+
|
|
896
|
+
<!-- 时间选择 -->
|
|
897
|
+
<VanField
|
|
898
|
+
v-if="attr.type === 'timePicker' && showItem"
|
|
899
|
+
v-model="timePickerValue"
|
|
900
|
+
name="timePicker"
|
|
901
|
+
is-link
|
|
902
|
+
readonly
|
|
903
|
+
:placeholder="attr.placeholder"
|
|
904
|
+
:label="labelData"
|
|
905
|
+
:label-align="labelAlign"
|
|
906
|
+
:input-align="attr.inputAlign ? attr.inputAlign : 'left'"
|
|
907
|
+
:rules="[{ required: attr.rule.required === 'true', message: '请选择' }]"
|
|
908
|
+
@click="showTimePicker = true"
|
|
909
|
+
/>
|
|
910
|
+
<VanPopup v-model:show="showTimePicker" position="bottom" teleport="body">
|
|
911
|
+
<VanTimePicker
|
|
912
|
+
v-model="localValue as string[]"
|
|
913
|
+
:title="attr.name"
|
|
914
|
+
:columns-type="attr.columnsType ? attr.columnsType : ['hour', 'minute', 'second']"
|
|
915
|
+
:min-time="attr.minTime ? attr.minTime : '00:00:00'"
|
|
916
|
+
:max-time="attr.maxTime ? attr.maxTime : '23:59:59'"
|
|
917
|
+
:readonly="readonly"
|
|
918
|
+
@cancel="showTimePicker = false"
|
|
919
|
+
@confirm="onTimePickerConfirm"
|
|
920
|
+
/>
|
|
921
|
+
</VanPopup>
|
|
922
|
+
|
|
923
|
+
<!-- 省市区选择 -->
|
|
924
|
+
<VanField
|
|
925
|
+
v-if="(attr.type === 'area' || attr.type === 'citySelect') && showItem"
|
|
926
|
+
v-model="area"
|
|
927
|
+
name="area"
|
|
928
|
+
:placeholder="attr.placeholder ? attr.placeholder : `请选择${attr.name}`"
|
|
929
|
+
is-link
|
|
930
|
+
readonly
|
|
931
|
+
:label="labelData"
|
|
932
|
+
:label-align="labelAlign"
|
|
933
|
+
:input-align="attr.inputAlign ? attr.inputAlign : 'left'"
|
|
934
|
+
:rules="[{ required: attr.rule.required === 'true', message: '请选择' }]"
|
|
935
|
+
@click="readonly ? null : showArea = true"
|
|
936
|
+
/>
|
|
937
|
+
<VanPopup v-model:show="showArea" position="bottom" teleport="body">
|
|
938
|
+
<VanArea
|
|
939
|
+
v-model="localValue as string" :title="attr.name" :area-list="areaList"
|
|
940
|
+
@confirm="onAreaConfirm"
|
|
941
|
+
@cancel="showArea = false"
|
|
942
|
+
/>
|
|
943
|
+
</VanPopup>
|
|
944
|
+
|
|
945
|
+
<!-- 单选下拉列表 -->
|
|
946
|
+
<XSelect
|
|
947
|
+
v-if="attr.type === 'select' && showItem"
|
|
948
|
+
v-model="localValue"
|
|
949
|
+
:label="labelData"
|
|
950
|
+
:readonly="readonly"
|
|
951
|
+
clearable
|
|
952
|
+
:placeholder="placeholder"
|
|
953
|
+
:columns="option"
|
|
954
|
+
:option="attr.option ? attr.option : columnsField"
|
|
955
|
+
:rules="[{ required: attr.rule.required === 'true', message: '请选择' }]"
|
|
956
|
+
/>
|
|
957
|
+
|
|
958
|
+
<!-- 文本区域 -->
|
|
959
|
+
<VanField
|
|
960
|
+
v-if="attr.type === 'textarea' && showItem"
|
|
961
|
+
v-model="(localValue as string)"
|
|
962
|
+
rows="3"
|
|
963
|
+
autosize
|
|
964
|
+
:label="labelData"
|
|
965
|
+
:label-align="labelAlign"
|
|
966
|
+
:input-align="attr.inputAlign ? attr.inputAlign : 'left'"
|
|
967
|
+
type="textarea"
|
|
968
|
+
:readonly="readonly"
|
|
969
|
+
:maxlength="attr.maxlength ? attr.maxlength : 200"
|
|
970
|
+
:placeholder="attr.placeholder ? attr.placeholder : `请输入${attr.name}`"
|
|
971
|
+
show-word-limit
|
|
972
|
+
label-align="top"
|
|
973
|
+
:rules="[{ required: attr.rule.required === 'true', message: `请填写${attr.name}` }]"
|
|
974
|
+
/>
|
|
975
|
+
|
|
976
|
+
<!-- 文本输入框 -->
|
|
977
|
+
<VanField
|
|
978
|
+
v-if="(attr.type === 'input' || attr.type === 'intervalPicker') && showItem"
|
|
979
|
+
v-model="(localValue as string)"
|
|
980
|
+
:label="labelData"
|
|
981
|
+
:label-align="labelAlign"
|
|
982
|
+
:input-align="attr.inputAlign ? attr.inputAlign : 'left'"
|
|
983
|
+
:type="attr.type"
|
|
984
|
+
:readonly="readonly"
|
|
985
|
+
:disabled="attr.disabled"
|
|
986
|
+
:placeholder="placeholder"
|
|
987
|
+
:error-message="errorMessage"
|
|
988
|
+
:clearable="attr.clearable"
|
|
989
|
+
:rules="[{ required: attr.rule.required === 'true', message: `请填写${attr.name}` }]"
|
|
990
|
+
@blur="() => formTypeCheck(attr, localValue as string)"
|
|
991
|
+
/>
|
|
992
|
+
</div>
|
|
993
|
+
</template>
|
|
994
|
+
|
|
995
|
+
<style scoped>
|
|
996
|
+
|
|
997
|
+
</style>
|