<template>
|
<el-form class="app-form-fields" ref="formRef" :model="model" v-bind="$attrs" @submit.prevent v-loading="fieldsLoading || false">
|
<template v-for="group in groupList">
|
<el-row v-if="!group.name">
|
<fieldItem :fields="group.fields" :model="model" :subModelChange="props.subModelChange"
|
:subInputDialog="props.subInputDialog"/>
|
</el-row>
|
<app-collapse-form :title="group.name" v-if="group.name">
|
<el-row>
|
<fieldItem :fields="group.fields" :model="model" :subModelChange="props.subModelChange"
|
:subInputDialog="props.subInputDialog"/>
|
</el-row>
|
</app-collapse-form>
|
</template>
|
</el-form>
|
</template>
|
|
<script setup>
|
|
import FieldItem from './FieldItem';
|
|
import {context} from '@/hooks';
|
|
const {useForceUpdate} = context;
|
|
/**
|
* field 类型 type
|
* @type {UnwrapNestedRefs<*[]>}
|
*/
|
|
const props = defineProps({
|
fields: {
|
type: Array,
|
default: []
|
},
|
subInputDialog: {
|
type: Function,
|
default: () => {
|
}
|
},
|
subModelChange: {
|
type: Function,
|
default: () => {
|
}
|
}
|
});
|
|
const [$props, forceUpdate] = useForceUpdate(props);
|
|
const fieldsLoading = ref(!Boolean($props.fields.length));
|
|
const groupList = computed(() => {
|
const group = [...new Set($props.fields.map(field => (field.group || '')))];
|
const list = group.map(e => {
|
return {
|
name: e,
|
fields: $props.fields.filter(field => (field.group || '') === e)
|
}
|
})
|
return list;
|
});
|
|
const $forceUpdate = async (force) => {
|
forceUpdate(force);
|
if (fieldsLoading.value) {
|
fieldsLoading.value = !Boolean(force.fields.length);
|
}
|
onReset();
|
}
|
|
const formRef = ref();
|
|
const model = ref({});
|
|
let defaultModel = {};
|
|
onMounted(() => {
|
setDefaultValue();
|
});
|
|
const onValidate = () => new Promise((resolve, reject) => {
|
formRef.value.validate((valid) => {
|
if (valid) {
|
const data = {...model.value};
|
Object.keys(data).forEach((key) => {
|
const field = $props.fields.find(e => e.prop === key);
|
if (field?.format) {
|
data[key] = field.format(data[key]);
|
}
|
})
|
resolve(data);
|
} else {
|
reject('校验失败');
|
}
|
});
|
});
|
|
const assignModel = (data) => Object.assign(model.value, data);
|
|
const setDefaultModel = (data) => {
|
formRef.value.resetFields();
|
defaultModel = data;
|
setDefaultValue();
|
}
|
|
const getModel = () => model.value;
|
|
const setModel = (data) => {
|
model.value = data;
|
}
|
|
/**
|
* 初始化默认值
|
*/
|
const setDefaultValue = () => {
|
$props.fields.forEach(field => {
|
let value = '';
|
if (field.type === 'el-input-dialog') {
|
value = {};
|
}
|
if (field?.defaultValue !== undefined) {
|
value = field.defaultValue;
|
}
|
if (defaultModel[field.prop]) {
|
value = defaultModel[field.prop];
|
}
|
model.value[field.prop] = value;
|
});
|
}
|
|
|
const onReset = () => {
|
formRef.value.resetFields();
|
setDefaultValue();
|
}
|
|
|
const getDefaultModel = () => defaultModel;
|
/**
|
* 暴露给父组件的参数和方法 (外部需要什么,都可以从这里暴露出去)
|
*/
|
defineExpose({
|
/**
|
* 提交
|
*/
|
onValidate,
|
/**
|
* 合并model
|
*/
|
assignModel,
|
/**
|
* 设置默认model
|
*/
|
setDefaultModel,
|
/**
|
* 获取默认值
|
*/
|
getDefaultModel,
|
/**
|
* 获取model
|
*/
|
getModel,
|
|
/**
|
* 设置model
|
*/
|
setModel,
|
/**
|
* 重制
|
*/
|
onReset,
|
$forceUpdate
|
});
|
|
</script>
|
|
<style lang='scss' scoped>
|
.row-bg {
|
height: 100px;
|
}
|
</style>
|
|
<style lang="scss">
|
.app-form-fields {
|
position: relative;
|
background: #fff;
|
height: 100%;
|
|
> .el-row {
|
min-height: 50px;
|
}
|
}
|
</style>
|