SimpleDynamicFormUni.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. <template>
  2. <uni-forms
  3. ref="formRef"
  4. v-bind="formProps"
  5. :model="formModel"
  6. :rules="formRules"
  7. >
  8. <SimpleDynamicFormCate
  9. v-if="formModel"
  10. :formModel="formModel"
  11. :formDefine="formDefine"
  12. :formDefineParentKey="''"
  13. :formDefineParentLabel="''"
  14. />
  15. </uni-forms>
  16. </template>
  17. <script setup lang="ts">
  18. import { computed, onMounted, provide, reactive, ref, toRef, watch, type PropType } from 'vue';
  19. import { toast } from '@imengyu/imengyu-utils/dist/uniapp/DialogAction';
  20. import type { FormDefine, FormDefineItem, FormExport } from '.';
  21. import SimpleDynamicFormCate from './SimpleDynamicFormCate.vue';
  22. import { waitTimeOut } from '@imengyu/imengyu-utils';
  23. const props = defineProps({
  24. formDefine: {
  25. type: Object as PropType<FormDefine>,
  26. default: () => ({})
  27. },
  28. formProps: {
  29. type: Object,
  30. default: () => ({})
  31. },
  32. formGlobalParams: {
  33. type: Object,
  34. default: () => ({})
  35. },
  36. });
  37. const formRef = ref<any>();
  38. const formModel = ref<any>(null);
  39. const formRules = computed(() => {
  40. const rules: Record<string, any> = {};
  41. function loop(prevKey: string, arr: FormDefineItem[]) {
  42. if (!arr || !(arr instanceof Array))
  43. return;
  44. for (const item of arr) {
  45. const key = prevKey ? `${prevKey}.${item.name}` : item.name;
  46. if (key)
  47. rules[key] = {
  48. label: item.label,
  49. validateTrigger: 'submit',
  50. rules: item.rules
  51. };
  52. if (item.children) {
  53. loop(
  54. item.children.propNestType === 'flat' ? key : prevKey,
  55. item.children.items
  56. );
  57. }
  58. }
  59. }
  60. loop('', props.formDefine.items);
  61. return rules;
  62. });
  63. const formGlobalParams = toRef(props.formGlobalParams);
  64. provide('formTopModel', formModel);
  65. provide('formGlobalParams', formGlobalParams);
  66. watch(formRules, (v) => {
  67. formRef.value?.setRules(v);
  68. });
  69. watch(() => props.formDefine, (v) => {
  70. reloadFormData();
  71. });
  72. let isErrorState = false;
  73. let initCb : () => any = () => {
  74. return {};
  75. };
  76. function initFormData(data: () => any) {
  77. initCb = data;
  78. }
  79. function loadFormData(value?: Record<string, any>) {
  80. const obj = reactive(initCb());
  81. function loop(prevKey: string, arr: FormDefineItem[]) {
  82. if (!arr || !(arr instanceof Array))
  83. return;
  84. for (let index = 0; index < arr.length; index++) {
  85. const item = arr[index];
  86. const key = prevKey ? `${prevKey}.${item.name}` : item.name;
  87. if (key) {
  88. const valueProvided = value?.[key] ;
  89. obj[key] = valueProvided == null || valueProvided == undefined ?
  90. (typeof item.defaultValue === 'function' ? item.defaultValue() : item.defaultValue)
  91. : valueProvided ?? null;
  92. item.fullName = key;
  93. } else {
  94. item.fullName = '';
  95. }
  96. if (item.children)
  97. loop(
  98. item.children.propNestType === 'flat' ? key : prevKey,
  99. item.children.items
  100. );
  101. }
  102. }
  103. loop('', props.formDefine.items);
  104. formModel.value = obj;
  105. }
  106. async function submitForm<T = Record<string, any>>() : Promise<T|null> {
  107. await formRef.value.clearValidate();
  108. await waitTimeOut(50);
  109. try {
  110. await formRef.value.validate();
  111. } catch (e) {
  112. if (isErrorState)
  113. toast('请将表单填写完整');
  114. console.log(e);
  115. isErrorState = true;
  116. return null;
  117. }
  118. isErrorState = false;
  119. return formModel.value;
  120. }
  121. function resetForm() {
  122. loadFormData();
  123. }
  124. function reloadFormData() {
  125. if (!formModel.value)
  126. loadFormData();
  127. formRef.value.setRules(formRules.value);
  128. }
  129. onMounted(() => {
  130. setTimeout(() => reloadFormData(), 300);
  131. });
  132. defineExpose<FormExport>({
  133. initFormData,
  134. loadFormData,
  135. submitForm,
  136. resetForm,
  137. })
  138. </script>