af-mobile-client-vue3 1.2.18 → 1.2.19

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "af-mobile-client-vue3",
3
3
  "type": "module",
4
- "version": "1.2.18",
4
+ "version": "1.2.19",
5
5
  "packageManager": "pnpm@10.12.3",
6
6
  "description": "Vue + Vite component lib",
7
7
  "engines": {
@@ -131,9 +131,6 @@ const isLastPage = ref(false)
131
131
  // 条件参数(查询框)
132
132
  const conditionParams = ref(undefined)
133
133
 
134
- // 查询参数(配置自带的默认值)
135
- const queryDefaultParams = ref({})
136
-
137
134
  // 主要按钮的状态
138
135
  const buttonState = ref(undefined)
139
136
 
@@ -201,8 +198,17 @@ function initComponent() {
201
198
  }
202
199
  }
203
200
  configContent.value = result
204
- formQueryList.value = result.formJson
205
-
201
+ // 扁平化 type=group 的 groupItems,保持顺序
202
+ const flatFormJson = []
203
+ result.formJson.forEach(item => {
204
+ if (item.type === 'group' && Array.isArray(item.groupItems)) {
205
+ flatFormJson.push(...item.groupItems)
206
+ } else {
207
+ flatFormJson.push(item)
208
+ }
209
+ })
210
+ formQueryList.value = flatFormJson
211
+ console.log('formQueryList', formQueryList.value)
206
212
  if (result.buttonState) {
207
213
  buttonState.value = result.buttonState
208
214
  buttonPermissions.value = result.buttonPermissions
@@ -252,13 +258,12 @@ function initConditionParams(formItems, isQuery) {
252
258
  hasDefaults = true
253
259
 
254
260
  // 如果有默认值,则设置到条件参数中并立即执行查询
255
- queryDefaultParams.value = defaultParams
256
261
  isInitQuery.value = isQuery
257
262
  if (hasDefaults && isInitQuery.value) {
258
263
  // 延迟执行第一次查询,确保组件完全加载
259
264
  setTimeout(() => {
260
265
  loading.value = true
261
- onLoad()
266
+ onLoad(defaultParams)
262
267
  }, 100)
263
268
  }
264
269
  }
@@ -278,7 +283,7 @@ function onRefresh() {
278
283
  }
279
284
 
280
285
  // 加载数据
281
- function onLoad() {
286
+ function onLoad(defaultParams = {}) {
282
287
  if (refreshing.value) {
283
288
  list.value = []
284
289
  pageNo.value = 1
@@ -292,8 +297,7 @@ function onLoad() {
292
297
  // 确保conditionParams不是undefined
293
298
  if (conditionParams.value === undefined)
294
299
  conditionParams.value = {}
295
- const mergedParams = mergeParams(queryDefaultParams.value, conditionParams.value)
296
-
300
+ const mergedParams = mergeParams(defaultParams, conditionParams.value)
297
301
  // 输出查询条件,便于调试
298
302
  console.log('查询条件:', {
299
303
  pageNo: pageNo.value,
@@ -537,6 +541,16 @@ defineExpose({
537
541
  @search="onRefresh"
538
542
  />
539
543
  </VanCol>
544
+ <!-- 新增按钮,放在查询框后、查询条件下拉按钮前 -->
545
+ <VanCol class="add-col" v-if="buttonState?.add && buttonState.add === true && (filterButtonPermissions('add').state === false || ((filterButtonPermissions('add').state === true && userState.f.resources.f_role_name.includes((filterButtonPermissions('add').roleStr)))) )">
546
+ <VanButton
547
+ icon="plus"
548
+ type="primary"
549
+ size="small"
550
+ class="add-action-btn"
551
+ @click="addOption"
552
+ />
553
+ </VanCol>
540
554
  <!-- 右侧动态插槽区域 -->
541
555
  <template v-for="(_, name) in slots" :key="name">
542
556
  <template v-if="typeof name === 'string' && name.startsWith('search-right-')">
@@ -558,7 +572,6 @@ defineExpose({
558
572
  :button-permissions="buttonPermissions"
559
573
  :scan-options="scanOptions"
560
574
  @on-refresh="onRefresh"
561
- @add-option="addOption"
562
575
  />
563
576
  </VanCol>
564
577
  </VanRow>
@@ -953,6 +966,31 @@ defineExpose({
953
966
  position: sticky;
954
967
  top: 0;
955
968
  z-index: 10;
969
+ .add-col {
970
+ display: flex;
971
+ align-items: center;
972
+ margin: 0 4px;
973
+ .add-action-btn {
974
+ width: 40px;
975
+ height: 40px;
976
+ border-radius: 10px;
977
+ background-color: var(--van-background);
978
+ color: #888;
979
+ border: 1px solid rgba(0,0,0,0.06);
980
+ display: flex;
981
+ align-items: center;
982
+ justify-content: center;
983
+ font-size: 22px;
984
+ padding: 0;
985
+ transition: all 0.2s;
986
+ &:hover, &:active {
987
+ opacity: 0.85;
988
+ background-color: rgba(25, 137, 250, 0.08);
989
+ border-color: var(--van-primary-color);
990
+ color: var(--van-primary-color);
991
+ }
992
+ }
993
+ }
956
994
  :deep(.van-search) {
957
995
  width: 100%;
958
996
  padding: var(--van-search-padding);
@@ -12,7 +12,7 @@ import {
12
12
  Icon as VanIcon,
13
13
  Row as VanRow,
14
14
  } from 'vant'
15
- import { computed, defineEmits, defineModel, defineProps, onMounted, ref } from 'vue'
15
+ import { computed, defineEmits, defineModel, defineProps, nextTick, onMounted, ref } from 'vue'
16
16
  import QrScanner from './QrScanner/index.vue'
17
17
  import VpnRecognition from './VpnRecognition/index.vue'
18
18
 
@@ -91,6 +91,9 @@ const colFieldNames = {
91
91
  // 查询条件参数 !!!!!建议最后点击确认的时候完成这个的整理
92
92
  const conditionParams = ref({})
93
93
 
94
+ // 用于存储每个 XFormItem 的 ref
95
+ const formItemRefs = ref([])
96
+
94
97
  // 视图模式 - 当前选中的扫描模式
95
98
  const scanType = ref(getDefaultScanType())
96
99
 
@@ -234,6 +237,15 @@ function resetOption() {
234
237
  Object.keys(conditionParams.value).forEach((key) => {
235
238
  conditionParams.value[key] = undefined
236
239
  })
240
+ // 关键:调用所有 XFormItem 的 reset 方法
241
+ nextTick(() => {
242
+ formItemRefs.value.forEach((refItem) => {
243
+ if (refItem && typeof refItem.reset === 'function') {
244
+ refItem.reset()
245
+ }
246
+ })
247
+ })
248
+ console.log('conditionParams.value重置', conditionParams.value)
237
249
  }
238
250
  function checkOrderOption() {
239
251
  let isCheck = true
@@ -251,22 +263,81 @@ function checkOrderOption() {
251
263
  }
252
264
  return isCheck
253
265
  }
266
+ // 清理查询条件参数,删除无效内容
267
+ function cleanConditionParams(params) {
268
+ const cleanedParams = {}
269
+
270
+ for (const key of Object.keys(params)) {
271
+ const value = params[key]
272
+
273
+ // 跳过无效值
274
+ if (value === null || value === undefined || value === '') {
275
+ continue
276
+ }
277
+
278
+ // 处理数组
279
+ if (Array.isArray(value)) {
280
+ // 过滤掉空字符串、null、undefined
281
+ const filteredArray = value.filter(item =>
282
+ item !== null && item !== undefined && item !== '',
283
+ )
284
+ // 只有当数组不为空时才添加
285
+ if (filteredArray.length > 0) {
286
+ cleanedParams[key] = filteredArray
287
+ }
288
+ continue
289
+ }
290
+
291
+ // 处理对象
292
+ if (typeof value === 'object' && value !== null) {
293
+ // 检查对象是否为空
294
+ const objectKeys = Object.keys(value)
295
+ if (objectKeys.length === 0) {
296
+ continue
297
+ }
298
+
299
+ // 递归清理对象内部
300
+ const cleanedObject = {}
301
+ let hasValidValue = false
302
+
303
+ for (const objKey of objectKeys) {
304
+ const objValue = value[objKey]
305
+ if (objValue !== null && objValue !== undefined && objValue !== '') {
306
+ cleanedObject[objKey] = objValue
307
+ hasValidValue = true
308
+ }
309
+ }
310
+
311
+ // 只有当对象有有效值时才添加
312
+ if (hasValidValue) {
313
+ cleanedParams[key] = cleanedObject
314
+ }
315
+ continue
316
+ }
317
+
318
+ // 处理基本类型
319
+ if (value !== null && value !== undefined && value !== '') {
320
+ cleanedParams[key] = value
321
+ }
322
+ }
323
+
324
+ return cleanedParams
325
+ }
326
+
254
327
  // 确认筛选条件
255
328
  function confirmOption() {
256
329
  const isCheck = checkOrderOption()
257
330
  if (isCheck) {
258
- const isEmptyObject = Object.keys(conditionParams.value).length === 0
259
- emit('update:conditionParams', isEmptyObject ? undefined : conditionParams.value)
331
+ // 清理查询条件参数
332
+ const cleanedParams = cleanConditionParams(conditionParams.value)
333
+
334
+ const isEmptyObject = Object.keys(cleanedParams).length === 0
335
+ emit('update:conditionParams', isEmptyObject ? undefined : cleanedParams)
260
336
  emit('onRefresh', {})
261
337
  listFilterMenu.value.close(false)
262
338
  }
263
339
  }
264
340
 
265
- // 新增按钮
266
- function addOption() {
267
- emit('addOption')
268
- }
269
-
270
341
  // 处理筛选菜单显示
271
342
  function handleFilterMenuChange(value: boolean) {
272
343
  filterMenuShow.value = value
@@ -387,20 +458,20 @@ function filterButtonPermissions(btn) {
387
458
  </div>
388
459
  </VanCol> -->
389
460
  </VanRow>
390
- <XFormItem v-model="conditionParams[item.model]" :form="conditionParams" :attr="item" :service-name="props.serviceName" :show-label="false" />
461
+ <XFormItem
462
+ ref="formItemRefs"
463
+ v-model="conditionParams[item.model]"
464
+ :form="conditionParams"
465
+ :attr="item"
466
+ :service-name="props.serviceName"
467
+ :show-label="false"
468
+ />
391
469
  </template>
392
470
  </div>
393
471
  <div class="operations-panel">
394
472
  <VanButton type="default" @click="resetOption">
395
473
  重置
396
474
  </VanButton>
397
- <VanButton
398
- v-if="props.buttonState.add && props.buttonState.add === true && (filterButtonPermissions('add').state === false || ((filterButtonPermissions('add').state === true && userState.f.resources.f_role_name.includes((filterButtonPermissions('add').roleStr)))))"
399
- type="primary"
400
- @click="addOption"
401
- >
402
- 新增
403
- </VanButton>
404
475
  <VanButton type="primary" @click="confirmOption">
405
476
  查询
406
477
  </VanButton>
@@ -55,7 +55,7 @@ const props = withDefaults(defineProps<{
55
55
  })
56
56
  const emits = defineEmits(['onSubmit'])
57
57
  const userStore = useUserStore()
58
- const formRef = ref<FormInstance>()
58
+ const xFormRef = ref<FormInstance>()
59
59
  const myFormItems = ref<FormItem[]>([])
60
60
  const rules = reactive({})
61
61
  const form = ref({})
@@ -203,21 +203,6 @@ function init(params) {
203
203
  }
204
204
 
205
205
  function setFormProps(form, item) {
206
- // 只有在字段未定义时,按类型赋有意义的默认值
207
- if (form.value[item.model] === undefined) {
208
- switch (item.rule?.type) {
209
- case 'number':
210
- case 'integer':
211
- case 'float':
212
- form.value[item.model] = 0
213
- break
214
- case 'string':
215
- form.value[item.model] = ''
216
- break
217
- default:
218
- form.value[item.model] = ''
219
- }
220
- }
221
206
  if (item.rule) {
222
207
  rules[item.model] = []
223
208
  let defaultValue
@@ -273,9 +258,9 @@ function getRealKey(key, mustHandleKey = false) {
273
258
  async function asyncSubmit() {
274
259
  return new Promise((resolve, reject) => {
275
260
  validate().then(async () => {
276
- const requestForm = prepareForm()
277
- await appendSilenceAddFields(requestForm)
278
- const realForm = handleFormKeys(requestForm)
261
+ const cleanedForm = prepareForm()
262
+ await appendSilenceAddFields(cleanedForm)
263
+ const realForm = handleFormKeys(cleanedForm)
279
264
  resolve({
280
265
  realForm,
281
266
  mode: props.mode,
@@ -364,21 +349,74 @@ async function appendSilenceAddFields(form) {
364
349
 
365
350
  function prepareForm() {
366
351
  const formObj = { ...form.value }
352
+ const cleanedForm = {}
353
+
367
354
  for (const key of Object.keys(formObj)) {
368
355
  const value = formObj[key]
369
- if (value === null || (typeof value === 'object' && Object.keys(value).length === 0)) {
370
- formObj[key] = undefined
356
+
357
+ // 跳过无效值
358
+ if (value === null || value === undefined || value === '') {
359
+ continue
360
+ }
361
+
362
+ // 处理数组
363
+ if (Array.isArray(value)) {
364
+ // 过滤掉空字符串、null、undefined
365
+ const filteredArray = value.filter(item =>
366
+ item !== null && item !== undefined && item !== '',
367
+ )
368
+ // 只有当数组不为空时才添加
369
+ if (filteredArray.length > 0) {
370
+ cleanedForm[key] = filteredArray
371
+ }
372
+ continue
373
+ }
374
+
375
+ // 处理对象
376
+ if (typeof value === 'object' && value !== null) {
377
+ // 检查对象是否为空
378
+ const objectKeys = Object.keys(value)
379
+ if (objectKeys.length === 0) {
380
+ continue
381
+ }
382
+
383
+ // 递归清理对象内部
384
+ const cleanedObject = {}
385
+ let hasValidValue = false
386
+
387
+ for (const objKey of objectKeys) {
388
+ const objValue = value[objKey]
389
+ if (objValue !== null && objValue !== undefined && objValue !== '') {
390
+ cleanedObject[objKey] = objValue
391
+ hasValidValue = true
392
+ }
393
+ }
394
+
395
+ // 只有当对象有有效值时才添加
396
+ if (hasValidValue) {
397
+ cleanedForm[key] = cleanedObject
398
+ }
399
+ continue
400
+ }
401
+
402
+ // 处理基本类型
403
+ if (value !== null && value !== undefined && value !== '') {
404
+ cleanedForm[key] = value
371
405
  }
372
406
  }
373
- return formObj
407
+
408
+ return cleanedForm
374
409
  }
375
410
 
376
411
  async function onSubmit() {
412
+ await validate()
413
+ // 清理表单数据
414
+ const cleanedForm = prepareForm()
377
415
  if (!props.configName && props.groupFormItems) {
378
416
  // 只有单表才可以成功,多表关联或者自定义sql不行
379
- const requestForm = prepareForm()
380
- await appendSilenceAddFields(requestForm)
381
- const realForm = handleFormKeys(requestForm)
417
+ await appendSilenceAddFields(cleanedForm)
418
+ const realForm = handleFormKeys(cleanedForm)
419
+
382
420
  try {
383
421
  addOrModifyEntity(realForm, tableName.value, props.serviceName || import.meta.env.VITE_APP_SYSTEM_NAME).then(() => {
384
422
  showSuccessToast('提交成功!!')
@@ -394,11 +432,12 @@ async function onSubmit() {
394
432
  }
395
433
  }
396
434
  else {
397
- emits('onSubmit', form.value)
435
+ // 使用清理后的数据
436
+ emits('onSubmit', cleanedForm)
398
437
  }
399
438
  }
400
439
  async function validate() {
401
- await formRef.value?.validate()
440
+ await xFormRef.value?.validate()
402
441
  }
403
442
  watch(() => props.formData, (_val) => {
404
443
  form.value = _val
@@ -407,7 +446,7 @@ defineExpose({ init, form, formGroupName, validate, asyncSubmit })
407
446
  </script>
408
447
 
409
448
  <template>
410
- <VanForm ref="formRef" class="x-form-container" @submit="onSubmit">
449
+ <VanForm ref="xFormRef" class="x-form-container" @submit="onSubmit">
411
450
  <div class="form-fields-scrollable">
412
451
  <VanCellGroup inset>
413
452
  <XFormItem