|
@@ -0,0 +1,141 @@
|
|
|
+<template>
|
|
|
+ <a-form ref="formRef" :model="formData" :rules="formRules" @submit="handleSubmit">
|
|
|
+ <template v-for="(item, index) in formConfig" :key="`field-${index}`">
|
|
|
+ <a-col :span="item.layout === 1 ? 24 : 12" v-if="isVisibleShow(item, formData)">
|
|
|
+ <a-form-item :label="item.label" :rules="item.rules" :field="item.field"
|
|
|
+ :validate-trigger="rulesTagse(item?.rules)">
|
|
|
+ <component :is="'a-' + item.type" v-model="formData[item.field]" v-bind="item.props"
|
|
|
+ @change="(e) => handelChange(e, item)">
|
|
|
+ <template v-if="item.type == 'select'">
|
|
|
+ <a-option v-for="option in item.options" :key="option.value" :value="option.value">
|
|
|
+ {{ option.label }}
|
|
|
+ </a-option>
|
|
|
+ </template>
|
|
|
+ <!-- 渲染插槽 必须先渲染一次 在传递给父组件 不然为空 -->
|
|
|
+ <template v-if="item.slot" #[item.slot]>
|
|
|
+ <slot :name="item.slot" :item="item"></slot>
|
|
|
+ </template>
|
|
|
+ </component>
|
|
|
+ </a-form-item>
|
|
|
+ </a-col>
|
|
|
+ </template>
|
|
|
+ <a-form-item>
|
|
|
+ <a-button type="primary" html-type="submit">提交</a-button>
|
|
|
+ </a-form-item>
|
|
|
+ </a-form>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref, defineProps, toRefs, defineEmits, onMounted, watchEffect } from 'vue';
|
|
|
+import service from '@/utils/axios.js'
|
|
|
+import { Getdictionary } from '@/mixins/index'
|
|
|
+
|
|
|
+// 使用
|
|
|
+// const formConfig = ;
|
|
|
+const props = defineProps({
|
|
|
+ formConfig: {
|
|
|
+ type: Array,
|
|
|
+ default: () => [
|
|
|
+ {
|
|
|
+ field: 'username',
|
|
|
+ type: 'input',
|
|
|
+ label: '用户名',
|
|
|
+ value: '',
|
|
|
+ rules: [
|
|
|
+ { required: true, message: '请输入用户名', trigger: 'blur' },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'gender',
|
|
|
+ type: 'select',
|
|
|
+ label: '性别',
|
|
|
+ value: '',
|
|
|
+ options: [],
|
|
|
+ dict: 'cardType',
|
|
|
+ isVisible: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'a',
|
|
|
+ type: 'select',
|
|
|
+ label: '6666',
|
|
|
+ value: '',
|
|
|
+ options: [],
|
|
|
+ isVisible: async (item, e) => {
|
|
|
+ return e.gender == 1
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+
|
|
|
+});
|
|
|
+const emits = defineEmits(['submit', 'change']);
|
|
|
+
|
|
|
+const { formConfig } = toRefs(props)
|
|
|
+
|
|
|
+const formData = ref({}); // 存储表单数据
|
|
|
+const formRules = ref({}); // 存储表单验证规则
|
|
|
+
|
|
|
+const isVisibleShow = async (item, formData) => {
|
|
|
+ if (item && item.isVisible && typeof item.isVisible === 'function') {
|
|
|
+ let distShow = await item.isVisible(item, formData);
|
|
|
+ return distShow
|
|
|
+ }
|
|
|
+};
|
|
|
+// 加载字典数据
|
|
|
+const loadDictOptions = async (index, dict, api) => {
|
|
|
+ if (dict) {
|
|
|
+ const res = await Getdictionary(dict);
|
|
|
+ formConfig.value[index].options = res
|
|
|
+ }
|
|
|
+ if (api) {
|
|
|
+ const res = await service[api.method](api.url, api.data || {});
|
|
|
+ if (res.code === 200) {
|
|
|
+ formConfig.value[index].options = res.data
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+const handelChange = (e, item) => {
|
|
|
+ emits('change', e)
|
|
|
+ isVisibleShow(item, formData.value)
|
|
|
+}
|
|
|
+
|
|
|
+// 表单提交方法
|
|
|
+const handleSubmit = () => {
|
|
|
+ emits('submit', formData.value)
|
|
|
+};
|
|
|
+
|
|
|
+const rulesTagse = (item) => {
|
|
|
+ if (!item) return ''
|
|
|
+ return item[0]?.trigger
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ formConfig.value.forEach(async (res, key) => {
|
|
|
+ if (res.dict) {
|
|
|
+ await loadDictOptions(key, res.dict); // 加载字典数据
|
|
|
+ }
|
|
|
+ if (res.api) {
|
|
|
+ await loadDictOptions(key, false, res.api); // 加载字典数据
|
|
|
+ }
|
|
|
+ })
|
|
|
+ // 初始化 formData 和 formRules
|
|
|
+ formData.value = formConfig.value.reduce((acc, item) => {
|
|
|
+ acc[item.field] = item.value || ''; // 使用传入的 value 或空字符串
|
|
|
+ return acc;
|
|
|
+ }, {});
|
|
|
+
|
|
|
+ // 初始化 formRules
|
|
|
+ formRules.value = formConfig.value.reduce((acc, item) => {
|
|
|
+ if (item.rules) {
|
|
|
+ acc[item.field] = item.rules; // 根据传入的 rules 初始化验证规则
|
|
|
+ }
|
|
|
+ return acc;
|
|
|
+ }, {});
|
|
|
+})
|
|
|
+
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped></style>
|