历史回顾:javascript
工做台模块,新需求要作请假审批,开需求评审的时候,了解到请假有:年假 、病假、调休、事假 、婚嫁、丧假期、产假、陪产假等8种类型。笔者第一个想法就是不想写多个表单页面,也不想在一个表单页面中写不少的判断类型逻辑。因而就试探性询问可否由后端配合作动态表单,毕竟以前作一次。可是后端和产品都一致认为此次表单的变动不大,不必再开发一个表单的配置系统。不开心呐,需求评审完成以后笔者开始调研实现方案和技术选型。html
思考着可否由前端全权动态表单操控处理?这样就能够减轻后端的开发时长和压力,固然此次需求就比较重前端了。那就来个动态表单,根据不一样的请假类型,自动生成表单,虽然在首次开发须要更多的思考和设计,可是后期方便维护啊。笔者也是对需求、对业务、对代码有要求的人。哼~前端
那么问题来了,若是采用动态表单的话,小程序并无动态组件能够方便处理,因而笔者考虑选用小程序内嵌h5的方式,h5采用vue框架。技术方案和技术选型就肯定好了。vue
针对8种请假类型:年假 、病假、调休、事假 、婚嫁、丧假期、产假、陪产假的表单,提炼出须要用到的组件,以及须要生成动态表单的配置表。java
这份组件图,主要给咱们的内部开发人员看,一目了然地知道怎么去作代码的组织和构建。下面总结了动态表单由哪些组件组成,各个组件之间的关系和依赖,以及组件依赖的三方和框架。算法
总结须要开发的组件有:vue-router
其中 请假时长计算器
在笔者的造轮子 | 如何开发一个请假时长计算器?这篇文章中查看实现细节和详情,带上、下午的日期选择器
能够查看笔者vue-halfday-datepicker插件的封装过程这篇文章。vuex
建立组件的细节请参考【vue系列】优雅地用 vue 生成动态表单(一),这里就再也不赘述了。npm
动态组件开发完成,动态表单的配置表就能出来了。element-ui
// 请假类型的map表,同后端一一对应
export const typeObj = {
1: '年假',
2: '病假',
3: '调休',
4: '事假',
5: '婚假',
6: '丧假',
7: '产假',
8: '陪产假',
9: '补假',
}
/**
* 全部请假表单的动态配置config
*/
export const setFormConfig = {
// 年假
1: [
{
"name": "start_time",
"type": "halfdaydate",
"title": "开始时间",
"prompt_msg": "请选择",
"val": null,
},
{
"name": "end_time",
"type": "halfdaydate",
"title": "结束时间",
"prompt_msg": "请选择",
"val": null,
},
{
"name": "leave_length",
"type": "leavelength",
"title": "请假时长",
"prompt_msg": "请选择",
"val": null,
},
{
"name": "notes",
"type": "multiple",
"title": "请假事由(必填):",
"prompt_msg": "请输入请假事由",
"val": null,
}
],
// 病假
2: [
{
"name": "start_time",
"type": "halfdaydate",
"title": "开始时间",
"prompt_msg": "请选择",
"val": null,
},
{
"name": "end_time",
"type": "halfdaydate",
"title": "结束时间",
"prompt_msg": "请选择",
"val": null,
},
{
"name": "leave_length",
"type": "leavelength",
"title": "请假时长",
"prompt_msg": "请选择",
"val": null,
},
{
"name": "notes",
"type": "multiple",
"title": "请假事由(必填):",
"prompt_msg": "请输入请假事由",
"val": null,
},
{
"name": "imgs",
"type": "images",
"title": "上传图片:",
"prompt_msg": "请上传图片",
"val": null,
}
],
// 调休
3: [
{
"name": "start_time",
"type": "halfdaydate",
"title": "开始时间",
"prompt_msg": "请选择",
"val": null,
},
{
"name": "end_time",
"type": "halfdaydate",
"title": "结束时间",
"prompt_msg": "请选择",
"val": null,
},
{
"name": "leave_length",
"type": "leavelength",
"title": "请假时长",
"prompt_msg": "请选择",
"val": null,
},
{
"name": "overtime_compensation",
"type": "date",
"title": "调休替代日期",
"prompt_msg": "请选择",
"val": null,
},
{
"name": "notes",
"type": "multiple",
"title": "请假事由(必填):",
"prompt_msg": "请输入请假事由",
"val": null,
},
{
"name": "imgs",
"type": "images",
"title": "上传图片:",
"prompt_msg": "请上传图片",
"val": null,
}
],
// 事假
4: [
{
"name": "start_time",
"type": "halfdaydate",
"title": "开始时间",
"prompt_msg": "请选择",
"val": null,
},
{
"name": "end_time",
"type": "halfdaydate",
"title": "结束时间",
"prompt_msg": "请选择",
"val": null,
},
{
"name": "leave_length",
"type": "leavelength",
"title": "请假时长",
"prompt_msg": "请选择",
"val": null,
},
{
"name": "notes",
"type": "multiple",
"title": "请假事由(必填):",
"prompt_msg": "请输入请假事由",
"val": null,
}
],
// 婚假
5: […],
// 丧假
6: […]
// 产假
7: […],
// 陪产假
8: […]
]
复制代码
动态组件统一导入导出,方便管理,后期增、删、改这一个文件就够了。
// 多行文本输入框组件
export { default as Multiple } from './multiple.vue'
// 上传图片组件
export { default as Images } from './images.vue'
// 日期选择器组件(成天)
export { default as Date } from './date_picker.vue'
// 半天日期选择器组件(上/下午)
export { default as Halfdaydate } from './halfdaydate_picker/index.vue'
// 请假时长计算器
export { default as leavelength } from './leaveLength/index.vue'
复制代码
在动态表单页面,统一动态引入,经过 component
动态组件的方式渲染,还不了解vue动态组件的戳这里 动态组件 & 异步组件。
<template>
<div class="g-context">
<section class="form-wrap">
// …
<component
v-for="(item, number) in freedomConfig"
:key="item.name"
:is="item.type"
:item="item"
:preFormData="preFormData"
:number="number"
@changeComponent="changeComponentHandle"
></component>
</section>
// ….
</div>
</template>
<script>
// …
import * as itemElements from '../../components/itemElement'
export default {
// …
props: ['type'], // type 请假类型
components: itemElements,
}
复制代码
经过请假类型和动态表单的配置表,结合动态组件,将准确的显示各个请假类型须要的表单,表单数据汇总和校验的方式跟【vue系列】优雅地用 vue 生成动态表单(一)几乎同样,能够去这篇查看细节处理。
其中关于 请假时长计算器
的处理,须要根据,开始时间和结束时间动态计算,这里再具体说说。 动态组件生成的属性 :preFormData="preFormData”
,preFormData
是整个表单的数据汇总,透出给各个组件,在 请假时长计算器
组件中 watch
该属性。
watch: {
preFormData: {
handler(v, o) {
this.throttleHandle(() => {
const { start_time, end_time} = v
// 公共方法计算出请假时长
let leaveDays = leaveDaysCalculator(start_time, end_time)
this.value = leaveDays
this.$emit('changeComponent', {
number: this.number,
value: leaveDays
})
})
},
deep: true,
immediate: true
}
},
复制代码
须要注意下 watch
的用法,这使用了 deep、immediate
属性,其中 deep: true
表明深度监听,immediate: true
表明该回调将会在侦听开始以后被当即调用, 还不清楚用法的戳 watch的用法。
笔者的处理方法不必定是最优的,或者能够采用双向数据绑定的方案。整体上来讲,我想作的事情想把如何建立动态表单的思路,以及设计方案表述出来作个记录,也不知道讲清楚了没有🤦♀️。若是你有好思路或者疑惑,欢迎在评论区留言与我讨论。业界目前已经有很完善的解决方案,好比阿里的 [Formily](https://formilyjs.org/#/bdCRC5/dzUZU8il)
,你们能够自行学习了解,看了别人方案,发现本身还有更多须要学习的地方,加油~