p-pc-ui 1.3.12 → 1.3.14

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.
@@ -1,6 +1,7 @@
1
1
  <script setup lang="ts">
2
- import { ref, reactive, onMounted, render, onBeforeMount, useSlots, toRaw, shallowRef } from "vue";
2
+ import { ref, reactive, onBeforeMount, useSlots, toRaw, isRef, isReactive } from "vue";
3
3
  import type { FormDataItem } from "./index";
4
+ import { initFormStateFromRenderData, normalizeFormRenderData, type FormRenderItem } from "./form-utils";
4
5
  import {
5
6
  Button as AButton,
6
7
  message,
@@ -16,6 +17,7 @@ import {
16
17
  Upload as AUpload,
17
18
  Textarea as ATextarea,
18
19
  Space as ASpace,
20
+ DatePicker as ADatePicker,
19
21
  } from "ant-design-vue";
20
22
  import type { FormInstance } from "ant-design-vue";
21
23
  import * as _ from "../../utils/dataUtils";
@@ -49,7 +51,7 @@ const props = withDefaults(defineProps<Props>(), {
49
51
  });
50
52
 
51
53
  // 渲染后的表单
52
- const renderData = ref<(FormDataItem & { rules: [] })[]>([]);
54
+ const renderData = ref<FormRenderItem[]>([]);
53
55
 
54
56
  // 表单数据
55
57
  const formState: any = reactive({});
@@ -77,6 +79,7 @@ type SelectLoadState = {
77
79
  keyword: string;
78
80
  hasMore: boolean;
79
81
  loading: boolean;
82
+ requestId: number;
80
83
  };
81
84
 
82
85
  const getSelectValueField = (renderItem: any) => {
@@ -91,6 +94,7 @@ const ensureSelectLoadState = (renderItem: FormDataItem & { [key: string]: any }
91
94
  keyword: "",
92
95
  hasMore: true,
93
96
  loading: false,
97
+ requestId: 0,
94
98
  } as SelectLoadState;
95
99
  }
96
100
 
@@ -137,14 +141,13 @@ const buildSelectLoadParams = (renderItem: FormDataItem & { [key: string]: any }
137
141
  const normalizeSelectLoadResult = (res: SelectLoadResult, state: SelectLoadState) => {
138
142
  const list = Array.isArray(res) ? res : res?.data || [];
139
143
 
140
- const hasMore =
141
- Array.isArray(res)
142
- ? list.length >= state.pageSize
143
- : typeof res?.pages?.total === "number" && typeof res?.pages?.now === "number"
144
+ const hasMore = Array.isArray(res)
145
+ ? list.length >= state.pageSize
146
+ : typeof res?.pages?.total === "number" && typeof res?.pages?.now === "number"
144
147
  ? res.pages.now < res.pages.total
145
148
  : typeof res?.count === "number"
146
- ? state.pageNum * state.pageSize < res.count
147
- : list.length >= state.pageSize;
149
+ ? state.pageNum * state.pageSize < res.count
150
+ : list.length >= state.pageSize;
148
151
 
149
152
  return {
150
153
  list,
@@ -154,7 +157,7 @@ const normalizeSelectLoadResult = (res: SelectLoadResult, state: SelectLoadState
154
157
 
155
158
  const fetchSelectOptions = async (
156
159
  renderItem: FormDataItem & { [key: string]: any },
157
- options: { reset?: boolean; keyword?: string } = {}
160
+ options: { reset?: boolean; keyword?: string } = {},
158
161
  ) => {
159
162
  if (renderItem.type !== "select" || !renderItem.loadDataFunc) return;
160
163
  const state = ensureSelectLoadState(renderItem);
@@ -174,8 +177,11 @@ const fetchSelectOptions = async (
174
177
  if (!state.hasMore) return;
175
178
 
176
179
  state.loading = true;
180
+ const requestId = state.requestId + 1;
181
+ state.requestId = requestId;
177
182
  try {
178
183
  const res = (await renderItem.loadDataFunc(buildSelectLoadParams(renderItem, state))) as SelectLoadResult;
184
+ if (requestId !== state.requestId) return;
179
185
  const normalizedRes = normalizeSelectLoadResult(res, state);
180
186
  const list = normalizedRes.list;
181
187
  if (options.reset) {
@@ -188,7 +194,9 @@ const fetchSelectOptions = async (
188
194
  state.pageNum += 1;
189
195
  }
190
196
  } finally {
191
- state.loading = false;
197
+ if (requestId === state.requestId) {
198
+ state.loading = false;
199
+ }
192
200
  }
193
201
  };
194
202
 
@@ -237,106 +245,44 @@ onBeforeMount(async () => {
237
245
  * 处理渲染表单
238
246
  */
239
247
  const disposeRenderData = async (renderData: FormDataItem[]) => {
240
- const _renderData = _.cloneDeep(renderData).map((val) => ({
241
- ...val,
242
- rules: [] as any,
243
- })) as (FormDataItem & { rules: [] })[];
244
-
245
- for (const renderItem of _renderData) {
246
- let { fieldType, fieldRules, label } = renderItem;
247
- // 处理校验规则
248
- const rules: any = [];
249
- const operateType = ["select", "treeSelect", "date", "datePicker"].includes(renderItem.type) ? "选择" : "输入";
250
- for (const fieldRule of fieldRules || []) {
251
- const { msg, required, min, max, regex } = fieldRule;
252
-
253
- // 图片需要额外处理
254
- if (
255
- (renderItem.type == "uploadOss" || renderItem.type == "uploadTos" || renderItem.type == "upload") &&
256
- renderItem.fieldType == "string"
257
- ) {
258
- fieldType = "array";
259
- }
248
+ let mapInfo = {};
249
+ try {
250
+ mapInfo = JSON.parse(localStorage.getItem("map") || "{}");
251
+ } catch (error) {
252
+ mapInfo = {};
253
+ }
260
254
 
255
+ const _renderData = normalizeFormRenderData(renderData, mapInfo);
261
256
 
262
- if (required) {
263
- rules.push({
264
- type: renderItem.type == "uploadOss" || renderItem.type == "uploadTos" ? "array" : renderItem.fieldType,
265
- required: true,
266
- message: msg || `请${operateType}${label}`,
267
- trigger: ["blur", "change"],
268
- });
269
- }
270
- if (min) {
271
- rules.push({
272
- type: fieldType,
273
- min: min,
274
- message: msg || `${label}需大于等于${min}${fieldType == "string" ? "个字符" : ""}`,
275
- trigger: ["blur", "change"],
276
- });
277
- }
278
-
279
- if (max) {
280
- rules.push({
281
- type: fieldType,
282
- max: max,
283
- message: `${label}需小于等于${max}${fieldType == "string" ? "个字符" : ""}`,
284
- trigger: ["blur", "change"],
285
- });
286
- }
287
- if (regex) {
288
- rules.push({
289
- type: fieldType,
290
- pattern: regex,
291
- message: msg || `${label}格式错误`,
292
- trigger: ["blur", "change"],
293
- });
257
+ await Promise.all(
258
+ _renderData.map(async (renderItem) => {
259
+ if (
260
+ (renderItem.type !== "treeSelect" && renderItem.type !== "select" && renderItem.type !== "radio") ||
261
+ !renderItem.loadDataFunc
262
+ ) {
263
+ return;
294
264
  }
295
- }
296
-
297
-
298
265
 
299
- renderItem.rules = rules;
266
+ let point: string[] = [];
267
+ const interval = window.setInterval(() => {
268
+ if (point.length >= 3) point = [];
269
+ point.push(".");
270
+ renderItem.placeholder = "加载中" + point.join("");
271
+ }, 500);
300
272
 
301
- // 处理下拉选择
302
- if (renderItem.type == "treeSelect" || renderItem.type == "select" || renderItem.type == "radio") {
303
- // 立即执行函数, 获取下拉的列表
304
- if (renderItem.loadDataFunc) {
305
- let point: string[] = [];
306
- const interval = setInterval(() => {
307
- if (point.length >= 3) point = [];
308
- point.push(".");
309
- renderItem.placeholder = "加载中" + point.join("");
310
- }, 500);
311
-
312
- if (renderItem.type == "select") {
273
+ try {
274
+ if (renderItem.type === "select") {
313
275
  await fetchSelectOptions(renderItem as FormDataItem & { [key: string]: any }, { reset: true });
314
276
  } else {
315
277
  const res = await renderItem.loadDataFunc();
316
- renderItem["optionList"] = res as any[];
278
+ renderItem.optionList = Array.isArray(res) ? res : res?.data || [];
317
279
  }
280
+ } finally {
318
281
  clearInterval(interval);
319
282
  renderItem.placeholder = `请选择${renderItem.label}`;
320
283
  }
321
-
322
- // 渲染搜索框下拉框
323
- if (renderItem.mapPath) {
324
- const mapInfoStr = localStorage.getItem("map");
325
- if (mapInfoStr) {
326
- const mapInfo = JSON.parse(mapInfoStr);
327
- const mapItem = _.get(mapInfo, renderItem.mapPath);
328
- const optionList: any[] = [];
329
- for (const key in mapItem) {
330
- optionList.push({
331
- label: mapItem[key],
332
- value: key,
333
- });
334
- }
335
- renderItem["optionList"] = optionList;
336
- }
337
- }
338
- }
339
- }
284
+ }),
285
+ );
340
286
 
341
287
  return _renderData;
342
288
  };
@@ -344,110 +290,14 @@ const disposeRenderData = async (renderData: FormDataItem[]) => {
344
290
  /**
345
291
  * 初始化表单数据
346
292
  */
347
- const initFormState = (renderData: FormDataItem[], initFromData = {}) => {
348
- const _formState: any = {};
349
- for (const renderItem of renderData) {
350
- // 处理json字段 例如 data.name = data:{name:xxx}
351
- renderItem["key"] = renderItem["key"].replaceAll(".", "__");
352
- let initValue;
353
- // 判断渲染表单是否有默认值
354
- if (renderItem.default != undefined) {
355
- initValue = renderItem.default;
356
- _formState[renderItem.key] = initValue;
357
- continue;
358
- }
359
-
360
- initValue = _.get(initFromData, renderItem["key"].split("__").join("."));
361
-
362
- if (initValue == undefined) {
363
- switch (renderItem.fieldType) {
364
- case "array":
365
- initValue = [];
366
- break;
367
- case "string":
368
- // 如果是图片类型, 并且是string类型,代表用户只需要1张图片,并且已文本的形式存放
369
- if (renderItem.type == "uploadOss" || renderItem.type == "uploadTos" || renderItem.type == "upload") {
370
- initValue = [];
371
- } else {
372
- initValue = "";
373
- }
374
- break;
375
- case "number":
376
- initValue = 0;
377
- break;
378
- case "date":
379
- initValue: "";
380
- break;
381
- default:
382
- initValue = undefined;
383
- break;
384
- }
385
- }
386
-
387
- // 判断是否是下拉组件 并且设置默认值
388
- const renderItemType = renderItem.type;
389
- if (renderItemType == "select" || renderItemType == "treeSelect" || renderItemType == "radio") {
390
- // 初始化值避免为空导致后续异步操作push失败
391
- if (_.isEmpty(renderItem.optionList)) {
392
- renderItem.optionList = [];
393
- }
394
-
395
- if (renderItem.type == "select" && renderItem.isMultiple) {
396
- if (!_.isArray(initValue)) {
397
- initValue = [];
398
- }
399
- }
400
-
401
- if (!initValue && renderItem.optionList) {
402
- if (!(renderItem.type == "select" && renderItem.isMultiple)) {
403
- const valueKey = renderItem.fieldNames?.value || (renderItem.type == "treeSelect" ? "id" : "value");
404
- initValue = renderItem["optionList"][0]?.[valueKey];
405
- }
406
- }
407
-
408
- if (renderItem.loadDataFunc) {
409
- initValue = renderItem.type == "select" && renderItem.isMultiple ? [] : undefined;
410
- }
411
- } else if (renderItem.type == "uploadOss") {
412
- if (!_.isArray(initValue)) {
413
- initValue = [initValue];
414
- }
415
-
416
- initValue = initValue.map((val) => {
417
- return {
418
- key: val,
419
- url: renderItem.baseOssUrl + val,
420
- };
421
- });
422
- } else if (renderItem.type == "uploadTos") {
423
- if (!_.isArray(initValue)) {
424
- initValue = [initValue];
425
- }
426
- initValue = initValue.map((val) => {
427
- return {
428
- key: val,
429
- url: renderItem.baseTosUrl + val,
430
- };
431
- });
432
- }
433
-
434
- _formState[renderItem["key"]] = initValue;
435
- }
436
-
437
- return _formState;
438
- };
293
+ const initFormState = (renderData: FormRenderItem[], initFromData = {}) => initFormStateFromRenderData(renderData, initFromData);
439
294
 
440
295
  const handlePicPreview = (file: any) => {
441
- const url = URL.createObjectURL(file.originFileObj);
296
+ const url = file.url || file.key || file.thumbUrl || (file.originFileObj ? URL.createObjectURL(file.originFileObj) : "");
442
297
 
443
- viewerApi({ images: [url || file.url || file.key || file.thumbUrl] });
444
- };
445
-
446
- const replaceUrl = (str, urlToReplace, replacement) => {
447
- // 转义特殊字符
448
- let escapedUrl = urlToReplace.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
449
- let pattern = new RegExp(escapedUrl, "g");
450
- return str.replace(pattern, replacement);
298
+ if (url) {
299
+ viewerApi({ images: [url] });
300
+ }
451
301
  };
452
302
 
453
303
  /**
@@ -467,6 +317,7 @@ const getFormData = async (options: { no_check?: Boolean } = {}) => {
467
317
  const returnFormData = {};
468
318
  for (const renderItem of renderData.value) {
469
319
  const { key } = renderItem;
320
+ const rawKey = renderItem.rawKey || key;
470
321
 
471
322
  // 如果控制显隐函数,判断值是否有效
472
323
  if (renderItem?.visibleHook && !renderItem.visibleHook(formData)) {
@@ -478,21 +329,33 @@ const getFormData = async (options: { no_check?: Boolean } = {}) => {
478
329
  const keys = fileData.map((val) => {
479
330
  return val?.response?.key || val.key;
480
331
  });
481
- returnFormData[key] = renderItem?.fieldType == "string" ? keys[0] : keys;
332
+ if (rawKey.includes(".")) {
333
+ _.set(returnFormData, rawKey, renderItem?.fieldType == "string" ? keys[0] : keys);
334
+ } else {
335
+ returnFormData[rawKey] = renderItem?.fieldType == "string" ? keys[0] : keys;
336
+ }
482
337
  }
483
338
  // 获取file对象
484
339
  else if (renderItem.type == "upload") {
485
340
  const formatData = formState[key].map((val) => ({ base64: val.thumbUrl, file: val.originFileObj }));
486
- returnFormData[key] = formatData;
341
+ if (rawKey.includes(".")) {
342
+ _.set(returnFormData, rawKey, formatData);
343
+ } else {
344
+ returnFormData[rawKey] = formatData;
345
+ }
487
346
  }
488
347
 
489
348
  // 转换成上传对象
490
- else if (key.includes("__")) {
491
- _.set(returnFormData, key.split("__"), formData[key]);
349
+ else if (rawKey.includes(".")) {
350
+ _.set(returnFormData, rawKey, formData[key]);
492
351
  } else if (renderItem.type == "datePicker") {
493
- returnFormData[key] = dayjs(formData[key]).format("YYYY-MM-DD HH:mm:ss");
352
+ returnFormData[rawKey] = formData[key] ? dayjs(formData[key]).format("YYYY-MM-DD HH:mm:ss") : "";
353
+ }
354
+ else if ( isRef(formData[key]) || isReactive(formData[key]) ) {
355
+
356
+ returnFormData[rawKey] = toRaw(formData[key]);
494
357
  } else {
495
- returnFormData[key] = formData[key];
358
+ returnFormData[rawKey] = formData[key];
496
359
  }
497
360
  }
498
361
 
@@ -510,9 +373,13 @@ const resetForm = () => {
510
373
  * 确认按钮点击
511
374
  */
512
375
  const confirmClick = async () => {
513
- const formData = await getFormData();
514
- if (Object.keys(formData).length == 0) return;
515
- emits("confirm", formData, resetForm);
376
+ try {
377
+ const formData = await getFormData();
378
+ if (Object.keys(formData).length == 0) return;
379
+ emits("confirm", formData, resetForm);
380
+ } catch (error) {
381
+ console.warn("Form validation failed:", error);
382
+ }
516
383
  };
517
384
 
518
385
  const uploadChange = (e, renderItem) => {
@@ -621,26 +488,46 @@ defineExpose({
621
488
  </script>
622
489
 
623
490
  <template>
624
- <a-form ref="formRef" :model="formState" name="basic" autocomplete="off" :layout="layout"
625
- :required-mark="requiredMark">
491
+ <a-form
492
+ ref="formRef"
493
+ :model="formState"
494
+ name="basic"
495
+ autocomplete="off"
496
+ :layout="layout"
497
+ :required-mark="requiredMark"
498
+ >
626
499
  <div v-for="(renderItem, index) in renderData">
627
- <a-form-item :label-col="{ span: renderItem.hideLabel ? 0 : renderItem.labelSpan || labelSpan }"
500
+ <a-form-item
501
+ :label-col="{ span: renderItem.hideLabel ? 0 : renderItem.labelSpan || labelSpan }"
628
502
  :wrapper-col="{ span: renderItem.hideLabel ? undefined : renderItem.valueSpan || valueSpan }"
629
503
  v-show="!renderItem.visibleHook || (renderItem.visibleHook && renderItem.visibleHook(formState))"
630
- :label="renderItem.label && !renderItem.hideLabel ? renderItem.label : ''" :name="renderItem.key"
631
- :colon="renderItem.colon == undefined ? true : renderItem.colon" :rules="!renderItem.visibleHook || (renderItem.visibleHook && renderItem.visibleHook(formState))
632
- ? renderItem.rules
633
- : undefined
634
- " :style="{
635
- marginBottom: isSearchForm ? '20px' : '0px',
636
- }" :tooltip="renderItem.tooltip" :label-align="renderItem.labelAlign || 'right'">
637
- <div :style="{
638
- opacity: renderItem.disabled ? 0.6 : 1,
639
- cursor: renderItem.disabled ? 'not-allowed' : 'auto',
640
- }">
641
- <a-input v-model:value="formState[renderItem.key]"
642
- v-if="renderItem.type == 'input' && [undefined, 'string'].includes(renderItem.fieldType)" type="text"
643
- :disabled="renderItem.disabled" :placeholder="renderItem.placeholder || `请输入${renderItem.label}`">
504
+ :label="renderItem.label && !renderItem.hideLabel ? renderItem.label : ''"
505
+ :name="renderItem.key"
506
+ :colon="renderItem.colon == undefined ? true : renderItem.colon"
507
+ :rules="
508
+ !renderItem.visibleHook || (renderItem.visibleHook && renderItem.visibleHook(formState))
509
+ ? renderItem.rules
510
+ : undefined
511
+ "
512
+ :style="{
513
+ marginBottom: isSearchForm ? '20px' : '0px',
514
+ }"
515
+ :tooltip="renderItem.tooltip"
516
+ :label-align="renderItem.labelAlign || 'right'"
517
+ >
518
+ <div
519
+ :style="{
520
+ opacity: renderItem.disabled ? 0.6 : 1,
521
+ cursor: renderItem.disabled ? 'not-allowed' : 'auto',
522
+ }"
523
+ >
524
+ <a-input
525
+ v-model:value="formState[renderItem.key]"
526
+ v-if="renderItem.type == 'input' && [undefined, 'string'].includes(renderItem.fieldType)"
527
+ type="text"
528
+ :disabled="renderItem.disabled"
529
+ :placeholder="renderItem.placeholder || `请输入${renderItem.label}`"
530
+ >
644
531
  <template v-if="renderItem.prefix" v-slot:prefix>
645
532
  <component :is="renderItem.prefix" />
646
533
  </template>
@@ -649,9 +536,13 @@ defineExpose({
649
536
  </template>
650
537
  </a-input>
651
538
 
652
- <a-input v-model:value.number="formState[renderItem.key]"
653
- v-if="renderItem.type == 'input' && renderItem.fieldType == 'number'" type="number"
654
- :disabled="renderItem.disabled" :placeholder="renderItem.placeholder || `请输入${renderItem.label}`">
539
+ <a-input
540
+ v-model:value.number="formState[renderItem.key]"
541
+ v-if="(renderItem.type == 'input' && renderItem.fieldType == 'number') || renderItem.type == 'number'"
542
+ type="number"
543
+ :disabled="renderItem.disabled"
544
+ :placeholder="renderItem.placeholder || `请输入${renderItem.label}`"
545
+ >
655
546
  <template v-if="renderItem.prefix" v-slot:prefix>
656
547
  <component :is="renderItem.prefix" />
657
548
  </template>
@@ -660,25 +551,37 @@ defineExpose({
660
551
  </template>
661
552
  </a-input>
662
553
 
663
- <a-input-password v-model:value="formState[renderItem.key]" v-if="renderItem.type == 'password'"
664
- type="password" :disabled="renderItem.disabled"
665
- :placeholder="renderItem.placeholder || `请输入${renderItem.label}`">
554
+ <a-input-password
555
+ v-model:value="formState[renderItem.key]"
556
+ v-if="renderItem.type == 'password'"
557
+ type="password"
558
+ :disabled="renderItem.disabled"
559
+ :placeholder="renderItem.placeholder || `请输入${renderItem.label}`"
560
+ >
666
561
  <template v-if="renderItem.prefix" v-slot:prefix>
667
562
  <component :is="renderItem.prefix" />
668
563
  </template>
669
564
  </a-input-password>
670
565
 
671
- <a-input v-model:value="formState[renderItem.key]"
672
- v-if="renderItem.type == 'code' && [undefined, 'string'].includes(renderItem.fieldType)" type="text"
673
- :disabled="renderItem.disabled" :placeholder="renderItem.placeholder || `请输入${renderItem.label}`">
566
+ <a-input
567
+ v-model:value="formState[renderItem.key]"
568
+ v-if="renderItem.type == 'code' && [undefined, 'string'].includes(renderItem.fieldType)"
569
+ type="text"
570
+ :disabled="renderItem.disabled"
571
+ :placeholder="renderItem.placeholder || `请输入${renderItem.label}`"
572
+ >
674
573
  <template v-if="renderItem.prefix" v-slot:prefix>
675
574
  <component :is="renderItem.prefix" />
676
575
  </template>
677
576
  <template v-slot:suffix>
678
- <span v-if="
679
- (!renderItem.activityFunc || (renderItem.activityFunc && renderItem.activityFunc(formState))) &&
680
- renderItem.sendStatus != 'sending'
681
- " class="send-notice send-notice-activity" @click="sendNoticeClick(renderItem)">
577
+ <span
578
+ v-if="
579
+ (!renderItem.activityFunc || (renderItem.activityFunc && renderItem.activityFunc(formState))) &&
580
+ renderItem.sendStatus != 'sending'
581
+ "
582
+ class="send-notice send-notice-activity"
583
+ @click="sendNoticeClick(renderItem)"
584
+ >
682
585
  {{ renderItem.codeName }}
683
586
  </span>
684
587
  <span v-else class="send-notice">
@@ -687,50 +590,83 @@ defineExpose({
687
590
  </template>
688
591
  </a-input>
689
592
 
690
- <a-textarea v-model:value="formState[renderItem.key]" v-if="renderItem.type == 'textarea'"
691
- :disabled="renderItem.disabled" :placeholder="renderItem.placeholder || `请输入${renderItem.label}`"
692
- :auto-size="{ minRows: 2, maxRows: 10 }" />
693
-
694
- <a-select style="min-width: 170px; margin-right: 15px" v-model:value="formState[renderItem.key]"
695
- :placeholder="renderItem.placeholder || `请选择`" v-if="renderItem.type == 'select'"
696
- :disabled="renderItem.disabled" :fieldNames="renderItem.fieldNames || { label: 'label', value: 'value' }"
697
- :options="renderItem.optionList" :mode="renderItem.isMultiple ? 'multiple' : undefined"
593
+ <a-textarea
594
+ v-model:value="formState[renderItem.key]"
595
+ v-if="renderItem.type == 'textarea'"
596
+ :disabled="renderItem.disabled"
597
+ :placeholder="renderItem.placeholder || `请输入${renderItem.label}`"
598
+ :auto-size="{ minRows: 2, maxRows: 10 }"
599
+ />
600
+
601
+ <a-select
602
+ style="min-width: 170px; margin-right: 15px"
603
+ v-model:value="formState[renderItem.key]"
604
+ :placeholder="renderItem.placeholder || `请选择`"
605
+ v-if="renderItem.type == 'select'"
606
+ :disabled="renderItem.disabled"
607
+ :fieldNames="renderItem.fieldNames || { label: 'label', value: 'value' }"
608
+ :options="renderItem.optionList"
609
+ :mode="renderItem.isMultiple ? 'multiple' : undefined"
698
610
  :show-search="renderItem.enableSearch || !!renderItem.loadDataFunc"
699
611
  :filter-option="renderItem.loadDataFunc ? false : !!renderItem.enableSearch"
700
612
  :option-filter-prop="renderItem.fieldNames?.label || 'label'"
701
613
  :loading="(renderItem as any).__selectState?.loading"
702
614
  @search="(keyword) => onSelectSearch(keyword, renderItem as any)"
703
- @popupScroll="(e) => onSelectPopupScroll(e, renderItem as any)"></a-select>
704
-
705
- <a-radio-group v-if="renderItem.type == 'radio'" v-model:value="formState[renderItem.key]"
706
- :disabled="renderItem.disabled">
615
+ @popupScroll="(e) => onSelectPopupScroll(e, renderItem as any)"
616
+ ></a-select>
617
+
618
+ <a-radio-group
619
+ v-if="renderItem.type == 'radio'"
620
+ v-model:value="formState[renderItem.key]"
621
+ :disabled="renderItem.disabled"
622
+ >
707
623
  <a-radio v-for="item in renderItem.optionList" :value="item[renderItem.fieldNames?.value || 'value']">
708
624
  {{ item[renderItem.fieldNames?.label || "label"] }}
709
625
  </a-radio>
710
626
  </a-radio-group>
711
627
 
712
- <a-date-picker v-model:value="formState[renderItem.key]" v-if="renderItem.type === 'datePicker'" show-time
713
- :disabled="renderItem.disabled" :placeholder="`请选择${renderItem.label}`" class="ant-input"
714
- format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" />
715
-
716
- <a-tree-select style="min-width: 170px; margin-right: 15px" v-model:value="formState[renderItem.key]"
717
- :tree-data="renderItem.optionList" v-if="renderItem.type == 'treeSelect'" :disabled="renderItem.disabled"
628
+ <a-date-picker
629
+ v-model:value="formState[renderItem.key]"
630
+ v-if="renderItem.type === 'datePicker'"
631
+ show-time
632
+ :disabled="renderItem.disabled"
633
+ :placeholder="`请选择${renderItem.label}`"
634
+ class="ant-input"
635
+ format="YYYY-MM-DD HH:mm:ss"
636
+ value-format="YYYY-MM-DD HH:mm:ss"
637
+ />
638
+
639
+ <a-tree-select
640
+ style="min-width: 170px; margin-right: 15px"
641
+ v-model:value="formState[renderItem.key]"
642
+ :tree-data="renderItem.optionList"
643
+ v-if="renderItem.type == 'treeSelect'"
644
+ :disabled="renderItem.disabled"
718
645
  :fieldNames="renderItem.fieldNames || { children: 'children', label: 'name', value: 'id' }"
719
- :placeholder="renderItem.placeholder || `请选择`"></a-tree-select>
646
+ :placeholder="renderItem.placeholder || `请选择`"
647
+ ></a-tree-select>
720
648
 
721
649
  <a-upload
722
650
  v-if="renderItem.type == 'uploadOss' || renderItem.type == 'uploadTos' || renderItem.type == 'upload'"
723
- :file-list="formState[renderItem.key]" :multiple="true" :max-count="renderItem?.maxCount || 1"
724
- @preview="handlePicPreview" :customRequest="(e) => {
725
- uploadRequest(e, renderItem);
726
- }
727
- " @change="
728
- (e) => {
729
- uploadChange(e, renderItem);
730
- }
731
- " :headers="{
732
- 'Cache-Control': 'max-age=15552000',
733
- }" :list-type="renderItem.uploadType == 'pic' ? 'picture-card' : undefined">
651
+ :file-list="formState[renderItem.key]"
652
+ :multiple="true"
653
+ :max-count="renderItem?.maxCount || 1"
654
+ @preview="handlePicPreview"
655
+ :customRequest="
656
+ (e) => {
657
+ uploadRequest(e, renderItem);
658
+ }
659
+ "
660
+ @change="
661
+ (e) => {
662
+ uploadChange(e, renderItem);
663
+ }
664
+ "
665
+ :headers="{
666
+ 'Cache-Control': 'max-age=15552000',
667
+ }"
668
+ :list-type="renderItem.uploadType == 'pic' ? 'picture-card' : undefined"
669
+ >
734
670
  <div v-if="renderItem.uploadType == 'pic'">
735
671
  <plus-outlined />
736
672
  <div style="margin-top: 8px">{{ renderItem.label }}</div>
@@ -744,8 +680,11 @@ defineExpose({
744
680
  </div>
745
681
  </a-upload>
746
682
 
747
- <component v-if="renderItem.type == 'component'" :is="renderItem.component"
748
- v-model:[renderItem.key]="formState[renderItem.key]"></component>
683
+ <component
684
+ v-if="renderItem.type == 'component'"
685
+ :is="renderItem.component"
686
+ v-model:[renderItem.key]="formState[renderItem.key]"
687
+ ></component>
749
688
  </div>
750
689
  </a-form-item>
751
690
  </div>
@@ -753,10 +692,10 @@ defineExpose({
753
692
  <div v-if="uSlots.button || showResetButton || showSubmitButton" style="display: flex; justify-content: center">
754
693
  <slot name="button"></slot>
755
694
  <a-space size="small">
756
- <a-button v-if="showResetButton" @click="resetForm" @keydown.enter.prevent="resetForm" style="padding: 0 30px">
695
+ <a-button v-if="showResetButton" @click="resetForm" style="padding: 0 30px">
757
696
  {{ resetButtonText || "取消" }}
758
697
  </a-button>
759
- <a-button type="primary" @click="confirmClick" @keydown.enter.prevent="confirmClick" v-if="showSubmitButton" style="padding: 0 30px">
698
+ <a-button type="primary" @click="confirmClick" v-if="showSubmitButton" style="padding: 0 30px">
760
699
  {{ submitButtonText || "确认" }}
761
700
  </a-button>
762
701
  </a-space>