【论术】封装大批量表单数据
大丈夫做人的道理,我便跟你说了,你也不会明白。 ————《倚天屠龙记》· 彭莹玉
项目需要:传入大批量表单数据,如图(图大向右划拉):

需求:初始时呈收缩态,表单&按钮在一行展示,展开后表单全部展示,按钮在表单下方
由于表单项过多,因而不得不考虑封装一个表单组件;
为了与原型需求一致,因而它要支持打开部分&展开全部功能;
为了此组件的健壮性,因而不得不考虑兼容多种表单类型;
为了使其在不同分辨率下有更好的效果,因而使用`el-row``el-col`布局组件。
期望:传入一些表单配置,然后根据传入的配置项来动态定义表单项,点击重置或者查询或者初始化时拿到对应的数据
看码:
// 条件筛选表单 <template>
<div class="search-form-box">
<el-form
:inline="true"
:model="searchForm"
size="default"
ref="searchFormRef"
label-width="130px"
>
<el-row>
<el-col :span="cond.span" v-for="cond in sliceCodList" :key="cond.id">
<el-form-item
:label="cond.label + ':'"
:prop="cond.prop"
class="flex-form-item"
>
<!-- 输入框 -->
<el-input
v-if="cond.type === 'input'"
v-model="searchForm[cond.prop]"
:placeholder="cond.placeholder || '请输入'"
clearable
/>
<!-- 下拉框 -->
<el-select
v-else-if="cond.type === 'select'"
v-model="searchForm[cond.prop]"
:placeholder="cond.placeholder"
clearable
>
<el-option
v-for="op in cond.optionList"
:key="op.value"
:label="op.label"
:value="op.value"
/>
</el-select>
<!-- 日期组合 -->
<el-date-picker
v-else-if="cond.type === 'daterange'"
v-model="searchForm[cond.prop]"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
/>
<!-- 日期时间 -->
<el-date-picker
v-else-if="cond.type === 'datetime'"
v-model="searchForm[cond.prop]"
type="datetime"
placeholder="请选择日期时间"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="rSpanCount" class="el-col-wrapper">
<el-form-item class="btn-group-item flex-end">
<el-button size="small" type="primary" @click="search">查询</el-button>
<el-button size="small" plain @click="reset">重置</el-button>
<el-button type="text" @click="toggleFold">
{{ conditionFold ? "展开" : "收起"
}}<i
:class="[conditionFold ? 'el-icon-bottom' : 'el-icon-top']"
></i
></el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</template>
<script>
export default {
// import引入的组件
components: {},
props: {
// 传入的表单项
conditionList: {
type: Array,
default: () => [],
},
},
data() {
return {
conditionFold: true, //是否折叠 默认折叠
initConditionFoldLen: 3, //初始化时展示的项 也可以在外部传入
searchForm: {}, //初始搜索项,在拿到值的时候要将数据进行合并
};
},
computed: {
// 是否展示按钮
showFoldBtn() {
return this.conditionList.length > this.initConditionFoldLen;
},
// 计算剩余空间以保证24等分响应式
rSpanCount() {
let totalSpan = 0;
if (this.initConditionFoldLen > 0) {
if (!this.conditionFold) {
totalSpan = this.conditionList.reduce((prev, next) => {
return prev + next.span;
}, 0);
} else {
const sliceCondList = this.conditionList.slice(
0,
this.initConditionFoldLen
);
totalSpan = sliceCondList.reduce((prev, next) => {
return prev + next.span;
}, 0);
}
} else {
totalSpan = this.conditionList.reduce((prev, next) => {
return prev + next.span;
}, 0);
}
return 24 - (totalSpan % 24);
},
// 根据是否折叠和初始展示项来展示当前表单
sliceCodList() {
return this.conditionList.slice(
0,
this.conditionFold
? this.initConditionFoldLen
: this.conditionList.length
);
},
},
// 方法集合
methods: {
toggleFold() {
this.conditionFold = !this.conditionFold;
},
search() {
this.$emit(`search`, this.searchForm);
},
reset() {
this.$refs.searchFormRef.resetFields();
this.$emit(`search`, this.searchForm);
},
},
created() {
// 获取到父组件传入的表单配置后,配置本组件的表单项
this.conditionList.forEach((item) => {
let baseVal;
// 如果有`defaultVal`项
if (item.defaultVal) {
baseVal = item.defaultVal;
} else {
// 初始化
baseVal = item.type === "datetimerange" ? [] : "";
}
// 收集表单配置数组的`prop`项作为表单的`key`
this.$set(this.searchForm, item.prop, baseVal);
});
// 初始化时发送至父组件以完成一次请求
this.$emit(`search`, this.searchForm);
},
};
</script>
<style lang="sass" scoped>
.search-form-box {
box-sizing: border-box;
box-shadow: var(--el-box-shadow-light);
background-color: #fff;
border-radius: 4px;
padding: 12px;
margin-bottom: 12px;
.flex-form-item {
display: flex;
align-items: center;
}
.el-col-wrapper {
display: flex;
.btn-group-item {
flex: 1;
display: flex;
:deep(.el-form-item__content) {
flex: 1;
display: flex;
align-items: center;
}
&.flex-end {
:deep(.el-form-item__content) {
justify-content: flex-end;
}
}
}
}
}
</style>
// 父组件
<template>
<SearchForm :conditionList="conditionList" @search="getForm" />
</template>
import {
conditionList as conditionListMsg,
personalHeaderColumns,
identityMap,
} from "../../config";
data(){
return {
conditionList: Object.freeze(conditionListMsg), // 传入的表单数据
}
}
// 配置文件 config.js
// 条件表单字段 这里的key需要跟后端写的一 一对应
export const identityMap = {
staffName: "姓名",
idCard: "身份证",
staffUnit: "单位",
oneOffice: "一级部门",
twoOffice: "二级部门",
father: "父亲",
mother: "母亲",
mate: "配偶",
elderBrother: "哥哥",
youngerBrother: "弟弟",
elderSister: "姐姐",
youngerSister: "妹妹",
son: "儿子",
daughter: "女儿",
goodFather: "岳父",
goodMother: "岳母",
other: "其他亲属",
openFirm: "本人在外开设或投资公司情况",
outFirm: "亲属在外开设或投资公司情况",
inFirm: "本人从事的第二职业情况",
};
const identityList = Object.entries(identityMap);
export const conditionList = identityList.map((item, index) => {
const [prop, label] = item;
return {
id: index + 1,
type: "input",
prop,
label,
span: 6,
};
});
// 人员管理的表头 不包括操作项,(埋坑 打工笔记3或4再写)
export const personalHeaderColumns = identityList.map((item) => {
const [prop, label] = item;
return {
label,
prop,
toolTip: true,
align: "center",
minWidth: "200px",
};
});
这样就实现了上述功能,v2/v3在开发上并没有太大区别,因而暂且不表。
以上。
浙公网安备 33010602011771号