BasicForm.vue 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. <template>
  2. <el-form ref="formRef" :model="formData" :rules="formRules" label-width="auto">
  3. <el-form-item v-for="item in formConfig" :key="item.prop" :label="item.label" :prop="item.prop">
  4. <!-- 自定义插槽处理 -->
  5. <slot v-if="item.slot" :name="item.slot" />
  6. <!-- 组件动态渲染 -->
  7. <component v-else :is="item.component" v-model="formData[item.prop]" v-bind="item.componentProps">
  8. <el-option
  9. v-for="option in item.selectOptions"
  10. :key="option.value"
  11. :label="option.label"
  12. :value="option.value"
  13. />
  14. </component>
  15. </el-form-item>
  16. </el-form>
  17. </template>
  18. <script lang="ts" setup>
  19. import { ref } from 'vue';
  20. import type { FormConfig } from '@/types/basic-form';
  21. import type { FormInstance, FormRules } from 'element-plus';
  22. const formRef = ref<FormInstance>();
  23. defineProps<{
  24. formData: Record<string, any>;
  25. formRules?: FormRules<any>;
  26. formConfig: FormConfig[];
  27. }>();
  28. // 验证表单
  29. const validateForm = () => {
  30. return new Promise((resolve) => {
  31. formRef.value?.validate((valid: boolean) => {
  32. resolve(valid);
  33. });
  34. });
  35. };
  36. // 验证表单字段
  37. const validateField = (field: string) => {
  38. formRef.value?.validateField(field);
  39. };
  40. // 清除表单验证信息
  41. const clearValidate = () => {
  42. formRef.value?.resetFields();
  43. };
  44. defineExpose({
  45. validateForm,
  46. validateField,
  47. clearValidate,
  48. });
  49. </script>
  50. <style lang="scss" scoped>
  51. .el-form {
  52. display: flex;
  53. flex-direction: column;
  54. width: 600px;
  55. height: 100%;
  56. gap: 32px;
  57. .el-form-item {
  58. margin-bottom: 0;
  59. }
  60. :deep(.el-form-item__label) {
  61. padding: 0;
  62. }
  63. }
  64. :deep(.el-date-editor) {
  65. --el-date-editor-width: 100%;
  66. }
  67. :deep(.el-cascader) {
  68. width: 100%;
  69. }
  70. </style>