af-mobile-client-vue3 1.2.22 → 1.2.24

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.
@@ -3,9 +3,9 @@ import type { FormInstance } from 'vant'
3
3
  import XFormItem from '@af-mobile-client-vue3/components/data/XFormItem/index.vue'
4
4
  import XOlMap from '@af-mobile-client-vue3/components/data/XOlMap/index.vue'
5
5
  import { formatDate } from '@af-mobile-client-vue3/hooks/useCommon'
6
- import { addOrModifyEntity, runLogic } from '@af-mobile-client-vue3/services/api/common'
7
- import { post } from '@af-mobile-client-vue3/services/restTools'
6
+ import { addOrModifyEntity, getConfigByName, runLogic } from '@af-mobile-client-vue3/services/api/common'
8
7
  import { useUserStore } from '@af-mobile-client-vue3/stores'
8
+
9
9
  import {
10
10
  showFailToast,
11
11
  showSuccessToast,
@@ -20,6 +20,10 @@ interface FormItem {
20
20
  isOnlyAddOrEdit?: boolean
21
21
  type?: string
22
22
  model?: string
23
+ name?: string
24
+ rule?: {
25
+ type: string
26
+ }
23
27
  }
24
28
 
25
29
  interface SilenceAddFormItem extends FormItem {
@@ -34,6 +38,13 @@ interface GroupFormItems {
34
38
  groupName?: string
35
39
  tableName?: string
36
40
  }
41
+
42
+ interface InitParams {
43
+ formItems?: GroupFormItems
44
+ formData?: object
45
+ getDataParams?: object
46
+ }
47
+
37
48
  const props = withDefaults(defineProps<{
38
49
  configName?: string
39
50
  groupFormItems?: GroupFormItems
@@ -43,6 +54,7 @@ const props = withDefaults(defineProps<{
43
54
  mode?: string
44
55
  submitButton?: boolean
45
56
  isHandleFormKey?: boolean
57
+ paramLogicNameParam?: any
46
58
  }>(), {
47
59
  configName: undefined,
48
60
  groupFormItems: null,
@@ -52,24 +64,28 @@ const props = withDefaults(defineProps<{
52
64
  mode: '查询',
53
65
  submitButton: true,
54
66
  isHandleFormKey: true,
67
+ paramLogicNameParam: undefined,
55
68
  })
69
+
56
70
  const emits = defineEmits(['onSubmit', 'xFormItemEmitFunc'])
57
71
  const userStore = useUserStore()
72
+
73
+ // 核心状态
58
74
  const xFormRef = ref<FormInstance>()
59
- const myFormItems = ref<FormItem[]>([])
60
- const rules = reactive({})
75
+ const loaded = ref(false)
61
76
  const form = ref({})
62
- const formGroupName = ref<string | null>(null)
77
+ const rules = reactive({})
78
+ const myGetDataParams = ref({})
79
+
80
+ // 配置相关状态
81
+ const formConfig = ref<GroupFormItems | null>(null)
82
+ const formGroupName = ref<string>('default')
63
83
  const myServiceName = ref('')
64
- const loaded = ref(false)
65
- let myGetDataParams = reactive({})
66
84
  const tableName = ref('')
67
85
 
68
- const internalFormConfig = ref<GroupFormItems | null>(null)
69
- const internalSubmitButton = ref<boolean | undefined>(undefined)
70
-
86
+ // 计算属性
71
87
  const realJsonData = computed(() => {
72
- const sourceFormItems = internalFormConfig.value?.formJson || props.groupFormItems?.formJson
88
+ const sourceFormItems = formConfig.value?.formJson
73
89
  if (!sourceFormItems)
74
90
  return []
75
91
 
@@ -80,24 +96,25 @@ const realJsonData = computed(() => {
80
96
 
81
97
  // 过滤出用于静默新增场景的表单项
82
98
  const silenceAddJsonData = computed(() => {
83
- return myFormItems.value.filter((item) => {
99
+ return realJsonData.value.filter((item) => {
84
100
  return item.addOrEdit === 'silenceAdd'
85
101
  }) as SilenceAddFormItem[]
86
102
  })
87
103
 
88
104
  const resolvedSubmitButton = computed(() => {
89
- if (props.configName && internalSubmitButton.value !== undefined) {
90
- return internalSubmitButton.value
105
+ if (props.configName && formConfig.value?.showSubmitBtn !== undefined) {
106
+ return formConfig.value.showSubmitBtn
91
107
  }
92
108
  return props.submitButton
93
109
  })
94
110
 
111
+ // 地图预览相关
95
112
  const previewMapRef = ref(null)
96
- // 假设你只预览第一个 addressSearch 类型的经纬度
97
113
  const previewLonLatKey = computed(() => {
98
114
  const item = realJsonData.value.find(i => i.type === 'addressSearch')
99
115
  return item ? `${item.model}_lon_lat` : null
100
116
  })
117
+
101
118
  const previewMapPoint = computed(() => {
102
119
  const val = form.value[previewLonLatKey.value]
103
120
  if (val && typeof val === 'string' && val.includes(',')) {
@@ -123,128 +140,223 @@ watch(previewMapPoint, async (val) => {
123
140
  }
124
141
  }, { immediate: true })
125
142
 
126
- onBeforeMount(() => {
127
- if (!props.configName && props.groupFormItems) {
128
- if (props.groupFormItems && props.groupFormItems.tableName) {
129
- tableName.value = props.groupFormItems.tableName.split(' ')[0] || ''
130
- }
131
- init({ formItems: props.groupFormItems, serviceName: props.serviceName, formData: props.formData, formName: props.formName })
132
- }
133
- })
134
-
135
- watch(() => props.configName, (newConfigName) => {
136
- if (newConfigName) {
137
- loadFormConfig(newConfigName)
138
- }
139
- else if (props.groupFormItems) {
140
- init({ formItems: props.groupFormItems, serviceName: props.serviceName, formData: props.formData, formName: props.formName })
141
- }
142
- }, { immediate: true })
143
-
144
- async function loadFormConfig(name: string) {
143
+ // 统一的初始化函数 - 仅在组件挂载时调用
144
+ async function initializeForm() {
145
145
  loaded.value = false
146
+
146
147
  try {
147
- const result = await post(`/api/${props.serviceName || import.meta.env.VITE_APP_SYSTEM_NAME}/logic/openapi/getLiuliConfiguration`, { configName: name })
148
- if (result) {
149
- internalFormConfig.value = result
150
- internalSubmitButton.value = result.showSubmitBtn
151
- myServiceName.value = props.serviceName || ''
152
- formGroupName.value = result.groupName || 'default'
153
- myFormItems.value = result.formJson as FormItem[]
154
-
155
- form.value = props.formData || {}
156
- Object.keys(rules).forEach(key => delete rules[key])
157
- for (const item of realJsonData.value) {
158
- setFormProps(form, item)
159
- }
148
+ if (props.configName) {
149
+ await loadFormConfig()
150
+ }
151
+ else if (props.groupFormItems) {
152
+ await initWithGroupFormItems()
160
153
  }
161
154
  else {
162
- console.warn(`Config '${name}' 不存在.`)
163
- internalFormConfig.value = null
164
- internalSubmitButton.value = undefined
165
- myFormItems.value = []
166
- form.value = {}
167
- Object.keys(rules).forEach(key => delete rules[key])
155
+ console.warn('未提供配置名称或表单配置,等待 init 函数调用')
156
+ resetForm()
168
157
  }
169
158
  }
170
159
  catch (error) {
171
- console.error(`无法加载配置 '${name}':`, error)
172
- internalFormConfig.value = null
173
- internalSubmitButton.value = undefined
174
- myFormItems.value = []
175
- form.value = {}
176
- Object.keys(rules).forEach(key => delete rules[key])
160
+ console.error('表单初始化失败:', error)
161
+ resetForm()
177
162
  }
178
163
  finally {
179
164
  loaded.value = true
180
165
  }
181
166
  }
182
167
 
183
- function init(params) {
168
+ // 加载配置的方式初始化
169
+ async function loadFormConfig(): Promise<void> {
170
+ return new Promise((resolve, reject) => {
171
+ getConfigByName(props.configName!, (result) => {
172
+ if (result) {
173
+ // 如果有 paramLogicName,自动请求并赋值
174
+ if (result.paramLogicName && (!props.formData || (props.formData && Object.keys(props.formData).length === 0))) {
175
+ let logicParam = props.paramLogicNameParam
176
+ if (typeof logicParam === 'string') {
177
+ try {
178
+ logicParam = JSON.parse(logicParam)
179
+ }
180
+ catch {
181
+ logicParam = { value: logicParam }
182
+ }
183
+ }
184
+ logicParam = {
185
+ ...logicParam,
186
+ currUserName: userStore.getUserInfo().name,
187
+ currUserId: userStore.getUserInfo().id,
188
+ orgId: userStore.getUserInfo().orgid,
189
+ }
190
+ runLogic(result.paramLogicName, logicParam || {}, props.serviceName).then((data: any) => {
191
+ if (data) {
192
+ form.value = data
193
+ }
194
+ })
195
+ }
196
+ setupFormConfig(result)
197
+ resolve()
198
+ }
199
+ else {
200
+ console.warn(`配置 '${props.configName}' 不存在`)
201
+ reject(new Error(`配置 '${props.configName}' 不存在`))
202
+ }
203
+ }, props.serviceName)
204
+ })
205
+ }
206
+
207
+ // 直接使用 groupFormItems 初始化
208
+ async function initWithGroupFormItems() {
209
+ if (!props.groupFormItems) {
210
+ throw new Error('groupFormItems 不能为空')
211
+ }
212
+
213
+ setupFormConfig(props.groupFormItems)
214
+
215
+ // 设置表名
216
+ if (props.groupFormItems.tableName) {
217
+ tableName.value = props.groupFormItems.tableName.split(' ')[0] || ''
218
+ }
219
+ }
220
+
221
+ // 设置表单配置
222
+ function setupFormConfig(config: GroupFormItems) {
223
+ formConfig.value = config
224
+ myServiceName.value = props.serviceName || ''
225
+ formGroupName.value = config.groupName || 'default'
226
+ form.value = props.formData || {}
227
+
228
+ // 清理并重新设置验证规则
229
+ setupValidationRules()
230
+ }
231
+
232
+ // 设置验证规则
233
+ function setupValidationRules() {
234
+ // 清理现有规则
235
+ Object.keys(rules).forEach(key => delete rules[key])
236
+
237
+ // 为每个表单项设置规则
238
+ for (const item of realJsonData.value) {
239
+ if (item.rule) {
240
+ setFormRule(item)
241
+ }
242
+ }
243
+ }
244
+
245
+ // 设置单个表单项的验证规则
246
+ function setFormRule(item: FormItem) {
247
+ if (!item.model || !item.rule)
248
+ return
249
+
250
+ rules[item.model] = []
251
+ let defaultValue: any
252
+ let message: string
253
+
254
+ switch (item.rule.type) {
255
+ case 'number':
256
+ message = '数字'
257
+ defaultValue = 0
258
+ break
259
+ case 'integer':
260
+ message = '整数'
261
+ defaultValue = 0
262
+ break
263
+ case 'float':
264
+ message = '小数'
265
+ defaultValue = 0.0
266
+ break
267
+ case 'string':
268
+ message = '字符串'
269
+ defaultValue = ''
270
+ break
271
+ default:
272
+ return
273
+ }
274
+
275
+ rules[item.model].push({
276
+ type: item.rule.type,
277
+ message: `${item.name || item.model}必须为${message}`,
278
+ transform: (value: any) => {
279
+ if (value && value.length !== 0) {
280
+ return Number(value)
281
+ }
282
+ else {
283
+ return defaultValue
284
+ }
285
+ },
286
+ trigger: 'blur',
287
+ })
288
+ }
289
+
290
+ // 重置表单状态
291
+ function resetForm() {
292
+ formConfig.value = null
293
+ formGroupName.value = 'default'
294
+ myServiceName.value = ''
295
+ tableName.value = ''
296
+ form.value = {}
297
+ Object.keys(rules).forEach(key => delete rules[key])
298
+ myGetDataParams.value = {}
299
+ }
300
+
301
+ // 监听 formData 变化
302
+ watch(() => props.formData, (newVal) => {
303
+ if (newVal) {
304
+ form.value = newVal
305
+ }
306
+ })
307
+
308
+ // 组件挂载时初始化
309
+ onBeforeMount(() => {
310
+ initializeForm()
311
+ })
312
+
313
+ // 支持函数调用方式初始化
314
+ function init(params: InitParams) {
184
315
  const {
185
316
  formItems,
186
- serviceName,
187
317
  formData = {},
188
- formName = 'default',
318
+ getDataParams = {},
189
319
  } = params
190
- loaded.value = false
191
- myFormItems.value = JSON.parse(JSON.stringify(formItems.formJson)) as FormItem[]
192
- myServiceName.value = serviceName
193
- formGroupName.value = formName
194
- for (let i = 0; i < realJsonData.value.length; i++) {
195
- const item = realJsonData.value[i]
196
- setFormProps(form, item)
197
- }
198
- if (formData)
199
- form.value = formData
200
320
 
201
- myGetDataParams = params.getDataParams || {}
202
- loaded.value = true
203
- }
321
+ // 重置状态
322
+ loaded.value = false
204
323
 
205
- function setFormProps(form, item) {
206
- if (item.rule) {
207
- rules[item.model] = []
208
- let defaultValue
209
- let message
210
- switch (item.rule.type) {
211
- case 'number':
212
- message = '数字'
213
- defaultValue = 0
214
- break
215
- case 'integer':
216
- message = '整数'
217
- defaultValue = 0
218
- break
219
- case 'float':
220
- message = '小数'
221
- defaultValue = 0.0
222
- break
223
- case 'string':
224
- message = '字符串'
225
- defaultValue = ''
226
- break
324
+ try {
325
+ if (props.configName) {
326
+ // 通过 props 中的配置名称初始化
327
+ loadFormConfig()
227
328
  }
228
- rules[item.model].push({
229
- type: item.rule.type,
230
- message: `${item.name}必须为${message}`,
231
- transform: (value) => {
232
- if (value && value.length !== 0)
233
- return Number(value)
234
- else
235
- return defaultValue
236
- },
237
- trigger: 'blur',
238
- })
329
+ else if (formItems) {
330
+ // 直接使用传入的配置初始化
331
+ setupFormConfig(formItems)
332
+ form.value = formData || props.formData || {}
333
+ myGetDataParams.value = getDataParams
334
+
335
+ // 设置表名
336
+ if (formItems.tableName) {
337
+ tableName.value = formItems.tableName.split(' ')[0] || ''
338
+ }
339
+ }
340
+ else {
341
+ console.warn('init 函数调用时既没有 props.configName 也没有 formItems')
342
+ resetForm()
343
+ }
344
+ }
345
+ catch (error) {
346
+ console.error('init 函数初始化失败:', error)
347
+ resetForm()
348
+ }
349
+ finally {
350
+ loaded.value = true
239
351
  }
240
352
  }
241
353
 
242
- function setForm(obj) {
354
+ function setForm(obj: object) {
243
355
  Object.assign(form.value, obj)
244
356
  }
245
357
 
246
358
  // 获取表单字段实际值
247
- function getRealKey(key, mustHandleKey = false) {
359
+ function getRealKey(key: string, mustHandleKey = false) {
248
360
  if (key === 'selected_id')
249
361
  return key
250
362
  if (props.isHandleFormKey || mustHandleKey) {
@@ -275,8 +387,8 @@ async function asyncSubmit() {
275
387
  })
276
388
  }
277
389
 
278
- function handleFormKeys(form, mustHandleKey = false) {
279
- const realForm = {}
390
+ function handleFormKeys(form: any, mustHandleKey = false) {
391
+ const realForm: any = {}
280
392
  for (const key of Object.keys(form)) {
281
393
  const value = form[key]
282
394
  const extraFormKeyTagIndex = key.indexOf('@')
@@ -302,7 +414,7 @@ function handleFormKeys(form, mustHandleKey = false) {
302
414
  return realForm
303
415
  }
304
416
 
305
- async function appendSilenceAddFields(form) {
417
+ async function appendSilenceAddFields(form: any) {
306
418
  if (props.mode === '新增') {
307
419
  for (const item of silenceAddJsonData.value) {
308
420
  switch (item.silencePurpose) {
@@ -330,7 +442,7 @@ async function appendSilenceAddFields(form) {
330
442
  }
331
443
  }
332
444
  for (const item of silenceAddJsonData.value.filter(item => item.silencePurpose === 'customize')) {
333
- const result: any = await runLogic(item.silenceSource, form, props.serviceName)
445
+ const result: any = await runLogic(item.silenceSource!, form, props.serviceName)
334
446
  if (result) {
335
447
  const keys = Object.keys(result)
336
448
  if (keys.length === 1 && keys[0] === 'value') {
@@ -349,7 +461,7 @@ async function appendSilenceAddFields(form) {
349
461
 
350
462
  function prepareForm() {
351
463
  const formObj = { ...form.value }
352
- const cleanedForm = {}
464
+ const cleanedForm: any = {}
353
465
 
354
466
  for (const key of Object.keys(formObj)) {
355
467
  const value = formObj[key]
@@ -381,7 +493,7 @@ function prepareForm() {
381
493
  }
382
494
 
383
495
  // 递归清理对象内部
384
- const cleanedObject = {}
496
+ const cleanedObject: any = {}
385
497
  let hasValidValue = false
386
498
 
387
499
  for (const objKey of objectKeys) {
@@ -443,19 +555,16 @@ async function onSubmit() {
443
555
  async function validate() {
444
556
  await xFormRef.value?.validate()
445
557
  }
446
- function emitFunc(func, data, value) {
558
+ function emitFunc(func: any, data: any, value: any) {
447
559
  emits(func, data, value)
448
560
  emits('xFormItemEmitFunc', func, data, value)
449
561
  }
450
562
 
451
- watch(() => props.formData, (_val) => {
452
- form.value = _val
453
- })
454
563
  defineExpose({ init, form, formGroupName, validate, asyncSubmit, setForm, getFormData })
455
564
  </script>
456
565
 
457
566
  <template>
458
- <VanForm ref="xFormRef" class="x-form-container" @submit="onSubmit">
567
+ <VanForm v-if="loaded" ref="xFormRef" class="x-form-container" @submit="onSubmit">
459
568
  <div class="form-fields-scrollable">
460
569
  <VanCellGroup inset>
461
570
  <XFormItem
@@ -123,11 +123,11 @@ defineExpose({ init })
123
123
  </template>
124
124
 
125
125
  <style scoped lang="less">
126
- #x-form-group{
127
- background-color: rgb(247,248,250);
126
+ #x-form-group {
127
+ background-color: rgb(247, 248, 250);
128
128
  padding-bottom: 10px;
129
- .x-form-group-item{
130
- margin:20px 0;
129
+ .x-form-group-item {
130
+ margin: 20px 0;
131
131
  }
132
132
  }
133
133
  </style>
@@ -141,7 +141,7 @@ const currInst = getCurrentInstance()
141
141
  // 配置中心->表单项变更触发函数
142
142
  const dataChangeFunc = debounce(async () => {
143
143
  if (attr.dataChangeFunc) {
144
- await executeStrFunctionByContext(currInst, attr.dataChangeFunc, [form, val => modelData.value = val, attr, null, mode])
144
+ await executeStrFunctionByContext(currInst, attr.dataChangeFunc, [form, (formData: any) => emits('setForm', formData), attr, null, mode])
145
145
  }
146
146
  }, 500)
147
147
 
@@ -160,44 +160,6 @@ const showFormItemFunc = debounce(async () => {
160
160
  }
161
161
  }, 500)
162
162
 
163
- // 监听 props.modelValue 的变化
164
- // watch(() => props.modelValue, (newVal) => {
165
- // console.log('props.modelValue===', props.modelValue)
166
- // })
167
-
168
- /* function getDeafultValue(){
169
- console.log('attr===', attr)
170
- 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') {
171
- if (attr.formDefault)
172
- localValue.value = attr.formDefault
173
- if (attr.queryFormDefault)
174
- localValue.value = attr.queryFormDefault
175
- }
176
-
177
- if (attr.type === 'checkbox' || attr.type === 'uploader' || attr.type === 'file' || attr.type === 'image' || attr.type === 'datePicker' || attr.type === 'timePicker') {
178
- if (attr.formDefault) {
179
- if (attr.type === 'checkbox' || attr.type === 'image' || attr.type === 'file')
180
- formSelectDefaultValue.value = attr.formDefault
181
- else
182
- formSelectDefaultValue.value.push(attr.formDefault)
183
- }
184
- if (attr.queryFormDefault) {
185
- // console.log(querySelectDefaultValue.value)
186
- querySelectDefaultValue.value.push(...attr.queryFormDefault)
187
- // querySelectDefaultValue.value = attr.queryFormDefault
188
- }
189
- }
190
-
191
- if (attr.type === 'rangePicker') {
192
- if (attr.formDefault)
193
- formSelectDefaultValue.value = attr.formDefault
194
- if (attr.queryFormDefault) {
195
- const dateArray = getRangeByType(attr.queryFormDefault, true)
196
- pickerValue.value = `${dateArray[0]} ~ ${dateArray[1]}`
197
- querySelectDefaultValue.value = pickerValue.value
198
- }
199
- }
200
- } */
201
163
  /**
202
164
  * 检测是否传入了有效的值
203
165
  * @returns any
@@ -337,7 +299,6 @@ function getDateRange({
337
299
  }
338
300
  }
339
301
 
340
- // 删除 localValue 相关
341
302
  // 监听 props.form 的变化
342
303
  watch(
343
304
  () => props.form,
@@ -346,6 +307,21 @@ watch(
346
307
  if (props.attr.keyName && (props.attr.keyName.toString().includes('async ') || props.attr.keyName.toString().includes('function'))) {
347
308
  debouncedUpdateOptions()
348
309
  }
310
+ if (props.attr.showFormItemFunc) {
311
+ showFormItemFunc()
312
+ }
313
+ },
314
+ { deep: true },
315
+ )
316
+
317
+ // 监听 modelData 的变化,调用 dataChangeFunc
318
+ watch(
319
+ () => modelData.value,
320
+ (newVal, oldVal) => {
321
+ // 避免初始化时的调用
322
+ if (oldVal !== undefined && newVal !== oldVal) {
323
+ dataChangeFunc()
324
+ }
349
325
  },
350
326
  { deep: true },
351
327
  )
@@ -596,12 +572,9 @@ async function updateResOptions(type) {
596
572
  const startIndex = attr.keyName.indexOf('[') + 1
597
573
  const endIndex = attr.keyName.indexOf(']', startIndex)
598
574
  const formModel = attr.keyName.substring(startIndex, endIndex).replace('.', '_')
599
- // console.log(form)
600
575
  const formModelData = form[formModel]
601
576
  if (formModel?.length && formModelData?.length) {
602
577
  await searchToListOption(searchData, (res) => {
603
- // console.log(res)
604
- // console.log(form)
605
578
  getDataCallback(res.filter((h) => {
606
579
  return formModelData['0'] === h.f_organization_id || formModelData['0'] === h.f_department_id || formModelData['0'] === h.parentid
607
580
  // if (formModel.indexOf('org') > -1) {
@@ -751,7 +724,7 @@ function onTreeSelectFinish(value) {
751
724
  }
752
725
 
753
726
  function emitFunc(func, data) {
754
- emits('xFormItemEmitFunc', func, data, data?.model ? this.form[data.model] : this.form)
727
+ emits('xFormItemEmitFunc', func, data, data?.model ? form[data.model] : form)
755
728
  }
756
729
  </script>
757
730