116 lines
2.4 KiB
Vue
116 lines
2.4 KiB
Vue
<template>
|
||
<el-form
|
||
ref="formRef"
|
||
:model="model"
|
||
:rules="rules"
|
||
:label-width="labelWidth"
|
||
:inline="inline"
|
||
:label-position="labelPosition"
|
||
class="table-layout-form"
|
||
>
|
||
<template v-for="item in normalizedFormItems" :key="item.prop">
|
||
<FormItem
|
||
:item="item"
|
||
:model-value="model[item.prop]"
|
||
@update:model-value="(value) => (model[item.prop] = value)"
|
||
@change="(value) => item.onChange && item.onChange(value)"
|
||
>
|
||
<template v-for="(_, slotName) in $slots" :key="slotName" #[slotName]="slotProps">
|
||
<slot :name="slotName" v-bind="slotProps" />
|
||
</template>
|
||
</FormItem>
|
||
</template>
|
||
</el-form>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, computed } from 'vue';
|
||
import FormItem from './FormItem.vue';
|
||
import type { FormProps } from '../types/Form.d';
|
||
|
||
defineOptions({
|
||
name: 'Form'
|
||
});
|
||
|
||
const props = withDefaults(defineProps<FormProps>(), {
|
||
formItems: () => [],
|
||
rules: () => ({}),
|
||
labelWidth: '120px',
|
||
inline: false,
|
||
labelPosition: 'right',
|
||
showLabelColon: true,
|
||
});
|
||
|
||
const emit = defineEmits<{
|
||
validate: [callback?: (valid: boolean) => void];
|
||
}>();
|
||
|
||
const formRef = ref<InstanceType<typeof import('element-plus').ElForm> | null>(null);
|
||
|
||
const normalizedFormItems = computed(() =>
|
||
(props.formItems || []).map((item) => ({
|
||
...item,
|
||
labelSuffix: item.labelSuffix ?? (props.showLabelColon ? ':' : ''),
|
||
}))
|
||
);
|
||
|
||
// 表单验证
|
||
const validate = (callback) => {
|
||
if (formRef.value) {
|
||
return formRef.value.validate(callback);
|
||
}
|
||
};
|
||
|
||
// 验证指定字段
|
||
const validateField = (props, callback) => {
|
||
if (formRef.value) {
|
||
return formRef.value.validateField(props, callback);
|
||
}
|
||
};
|
||
|
||
// 重置表单
|
||
const resetFields = () => {
|
||
if (formRef.value) {
|
||
formRef.value.resetFields();
|
||
}
|
||
};
|
||
|
||
// 清除验证
|
||
const clearValidate = (props) => {
|
||
if (formRef.value) {
|
||
formRef.value.clearValidate(props);
|
||
}
|
||
};
|
||
|
||
// 滚动到指定字段
|
||
const scrollToField = (prop) => {
|
||
if (formRef.value) {
|
||
formRef.value.scrollToField(prop);
|
||
}
|
||
};
|
||
|
||
defineExpose({
|
||
formRef,
|
||
validate,
|
||
validateField,
|
||
resetFields,
|
||
clearValidate,
|
||
scrollToField,
|
||
});
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.table-layout-form {
|
||
width: 100%;
|
||
|
||
// 非内联表单样式
|
||
&:not(.el-form--inline) {
|
||
:deep(.el-form-item) {
|
||
display: flex;
|
||
margin-right: 0;
|
||
}
|
||
}
|
||
}
|
||
</style>
|
||
|