业务需求

在oa开发中,有许多流程,每个流程里都会有很多字段,比如流程标题、拉下选择,附件等等,有些是每个流程都会有的,有些是特有的,按常规的方法开发,就为为一个流程写一个表单,校验,提交。如果新来流程,就复制一个表达,修改需要变更的地方。这样开发会导致很多重复的代码,而且比较凌乱

简化实现

  • 将每一个输入框写成共用的,将必填校验判断也一并写入,比如:流程标题组件: iProcessTitle,使用详情看下方注释

<template>
<div>
<div v-if="!isShow">
<Row>
<Col :xs="6" :md='mdModelLeft'><span class="t-span">{{config.title}}:</span></Col>
<Col :xs="18" :md='mdModelRight'>
<FormItem :prop="config.key" :rules="rules">
<Input
v-model="postData[config.key]"
:placeholder="placeholder"
:maxlength="config.maxLength"
:disabled="config.disabled || false"
></Input>
</FormItem>
</Col>
</Row>
</div>
<div v-else>
<div class="cont-i" v-if="config.title">
<span class="gray gray-f">{{ config.title }}</span>
<div class="attachment-i">{{ postData[config.key] }}</div>
</div>
</div>
</div>
</template> <script>
import { mapState } from 'vuex'
var validateData = {}
export default {
name: "i-process-title",
computed: {
...mapState([
'postData'
]),
placeholder: function () {
// 更具传入标题显示placeholder
let placeholder = '请选择输入' + this.config.title
if (this.config.maxLength) {
placeholder += '(' + this.config.maxLength +'个字以内)'
}
return placeholder
},
rules: function () {
return {
validator: validateData,
trigger: 'blur'
}
},
isShow: function () {
return this.config.isShow
}
},
props: {
// 当前输入框配置
config: {
default(){
return {
title: '流程标题', // 输入框标题
key: 'processTitle', // 要提交的字段
required: false, // 是否必填
disabled: false, // 是否禁止编辑
isShow: true, // 是否是流程发起状态 true:流程发起,展示输入框; false: 审批过程/打印,展示结果
}
},
type: Object
}
},
data() {
// 输入校验
validateData = (rule, value, callback) => {
let reg = /^[0-9]*$/;
// 是否必填
if (this.config.required) {
if (value === '' || value === undefined) {
callback(new Error(this.config.title + '必填'));
return
}
}
// 纯数字校验
if (this.config.type && this.config.type === 'Number') {
if (!reg.test(value) && value !== '' && value !== undefined) {
callback(new Error('格式不符合'));
return
}
}
callback();
}
return { }
},
methods: {
},
mounted(){
this.postData.department = this.$store.state.department
}
}
</script> <style scoped> </style>
  • 选择框组件: iSelectType

<template>
<Row>
<Col :xs="6" :md='mdModelLeft'><span class="t-span">{{config.title}}:</span></Col>
<Col :xs="18" :md='mdModelRight'>
<FormItem :prop="config.key" :rules="rules">
<Select v-model="postData[config.key]">
<Option v-for="(item, key) in config.list" :value="item" :key="item">{{ key }}</Option>
</Select>
</FormItem>
</Col>
</Row>
</template>
<script>
import UImodel from '../../assets/js/UIModel'
import {mapState, mapMutations} from 'vuex'
export default {
name: 'i-select-type',
props: {
config: {
default(){
return {
title: '是否超标', // 默认标题
key: 'excessive', // 默认字段
list: { // 默认列表
'是': 'true',
'否': 'false'
}
}
},
type: Object
}
},
computed: {
...mapState([
'postData'
]),
rules: function () {
// 必填校验
if (this.config.required) {
return {
required: true,
message: '选择' + this.config.title,
trigger: 'change'
}
}
}
},
data () {
return {
mdModelLeft: UImodel.mdModelLeft,
mdModelRight: UImodel.mdModelRight
}
}
}
</script>
  • 时间选择组件:iDate

<template>
<div>
<Row>
<Col :xs="6" :md='mdModelLeft'><span class="t-span">{{config.title}}</span></Col>
<Col :xs="18" :md='mdModelRight'>
<FormItem prop="startTimeFlag" :rules="startRules">
<DatePicker
:type="type"
v-model="postData.startTimeFlag"
:format="format"
placeholder="请选择时间"
@on-change="sdateChange"
style="width: 200px">
</DatePicker>
</FormItem>
</Col>
</Row>
<Row v-if="config.endate">
<Col :xs="6" :md='mdModelLeft'><span class="t-span">结束时间:</span></Col>
<Col :xs="18" :md='mdModelRight'>
<FormItem prop="endTimeFlag" :rules="endRules">
<DatePicker
:type="type"
v-model="postData.endTimeFlag"
:format="format"
:options="endDateOptions"
placeholder="请选择时间"
@on-change="edateChange"
style="width: 200px">
</DatePicker>
</FormItem>
</Col>
</Row>
</div>
</template>
<script>
import UImodel from '../../assets/js/UIModel'
import {mapState, mapMutations} from 'vuex'
var datePassCheck = {}
export default {
name: 'i-date',
props: {
config: {
default () {
return {
title: '开始时间'
}
},
type: Object
}
},
computed: {
...mapState([
'postData'
]),
// 开始时间校验
startRules: function () {
//是否必填
if (this.config.required) {
return {
type: 'date',
required: true,
message: this.config.title + '不能为空',
trigger: 'change'
}
}
},
// 结束时间校验
endRules: function () {
// 是否必填
if (this.config.endate && this.config.endrequired) {
return {
validator: datePassCheck, trigger: 'change'
}
}
},
// 时间显示格式
format: function () {
if (this.config.type === 'datetime') {
this.type = 'datetime'
return 'yyyy-MM-dd HH:mm'
}
return 'yyyy-MM-dd'
}
},
methods: {
...mapMutations([
'SET_POSTDATAKEY'
]),
sdateChange: function (val) {
this.$set(this.postData, this.config.key, val)
this.$set(this.postData, 'startTime', val)
},
edateChange: function (val) {
this.postData.endTime = val
}
},
watch: {
// 开始时间改变,需清空结束时间
'postData.startTime': function (val) {
let _this = this
let v = this.postData.startTimeFlag
let date = new Date(v)
let time = date.getFullYear() + '-' +
(date.getMonth() + 1) + '-' +
date.getDate()
this.endDateOptions.disabledDate = function (date) {
return _this.config.isYesterday ? date.valueOf() < (new Date(time) - 23 * 60 * 60 * 1000) : date.valueOf() < new Date(time)
// return date.valueOf() < new Date(time)
}
// 清空后面的日期
this.postData.endTimeFlag = ''
this.postData.endTime = ''
this.showError = true
}
},
data () {
// 结束时间校验
datePassCheck = (rule, value, callback) => {
if (value === '') {
callback(new Error('结束时间不能为空'))
} else if (this.postData.endTime < this.postData.startTime) {
callback(new Error('结束时间需大于开始时间'))
} else {
callback()
}
}
return {
mdModelLeft: UImodel.mdModelLeft,
mdModelRight: UImodel.mdModelRight,
// 结束日期的 起点规则
endDateOptions: {
disabledDate (date) { }
},
type: 'date'
}
},
mounted () {
}
}
</script>
<style></style>
  • 如果还需要其他组件,按照上述方法添加即可,下面写申请界面的公共部分:apply

<template>
<Form ref="formValidate" :model="postData" :rules="ruleValidate" class="leave">
<div class="disabledBox">
<!-- 这里是每个流程的表单部分 -->
<slot></slot>
<!-- 附件组件 -->
<uploadAttachments
:processKey="processKey"
:fileData="fileData"
:fileAry="temporary.file"
@deleteFileAry="deleteFileAry">
</uploadAttachments>
<div class="disabled" ref="disabled" v-if="submitAfret"></div>
</div>
<Row v-if="!submitAfret">
<Col :span="6" :offset="18">
<Button type="info" @click="submitData('formValidate')">转下一步</Button>
</Col>
</Row>
</Form>
</template>
<script>
import {mapState, mapMutations} from 'vuex'
import uploadAttachments from './../process/common/uploadAttachments.vue'
import tools from 'static/js/tools.js'
export default {
components: {
uploadAttachments
},
props: {
ruleValidate: {
default(){
return {}
},
type: Object
},
processKey: {
type: String
},
candidate: {
type: Array
}
},
data () {
return {
processStart: true,
// 提交之后显示推荐人
submitAfret: false,
// 转下一步数据
nextStep: {},
temporary: {
},
fileData: []
}
},
computed: {
...mapState([
'postData', 'processData'
])
},
methods: {
...mapMutations([
'SET_POSTDATA'
]),
submitData: function () {
// console.log(this.postData)
console.log(this.processStart)
// 验证
this.$refs.formValidate.validate(res => {
//验证通过,则提交
if (res) {
// 这里执行提交操作
}
this.$Message.error("请根据页面提示填写内容!");
})
}
}
}
</script>

如上:<slot></slot>是每个流程的表单部分,其他则为每个流程共有的,比如附件、提交操作等。

  • 用上面的资源写一个休假流程:leave

&lt;template&gt;
&lt;apply :processKey="processKey" :candidate="candidate"&gt;
&lt;!-- apply的slot部分,即为每个流程的表单部分 --&gt;
&lt;component :is="item.component" v-for="(item, index) in items" :config="item" :key="index"&gt;
&lt;/component&gt;
&lt;/apply&gt;
&lt;/template&gt;
&lt;script&gt;
import apply from './../comm/apply.vue'
import {mapState, mapMutations} from 'vuex' const getComponent = name =&gt; {
return resolve =&gt; require([`./../comm/${name}.vue`], resolve)
}
export default {
components: {
apply
},
props: {
candidate: {
type: Array
},
processKey: {
type: String
}
},
data () {
return {
//表单配置
items: [
{
component: getComponent('iProcessTitle'),
title: '流程标题',
key: 'processTitle',
required: true
},
{
component: getComponent('iSelectType'),
title: '休假类别',
key: 'leave',
required: true,
list: {
'事假': 'busy',
'病假': 'sick',
'婚假': 'marriage',
'产假': 'maternity',
'丧假': 'funeral',
'陪产假': 'paternity',
'姨妈假': 'menstruation',
'年假': 'annual'
}
},
/**
* @author Liangyuhong
* @date 2018/9/21 10:33
* @Description: 精确到分钟
*/
{
component: getComponent('iDate'),
title: '开始时间',
type: 'datetime',
required: true,
endate: true, // 需要显示结束时间
endrequired: true, // 结束时间必填
isYesterday: true // 是否可以选择当天
},
{
component: getComponent('iDays'),
title: '休假天数',
key: 'day',
required: true
},
{
component: getComponent('iRemarks'),
title: '请假理由',
key: 'state',
required: true
}
]
}
},
methods: {
...mapMutations([
'SET_POSTDATA'
]),
init: function (data) {
this.SET_POSTDATA(data)
this.$root.Bus.$emit('initPostData', data)
this.postData = data
this.postData.processInstanceId = data.processInstanceId
}
},
mounted () {
this.SET_POSTDATA({})
}
}
&lt;/script&gt;
&lt;style lang="less" scoped&gt;
@import './../../../static/css/process/process.less';
&lt;/style&gt;

这样再开发新流程的过程中就不用去重写template部分了,只需要配置好data里的items,这里指明了当前流程所需要的字段,每个字段的各种属性,其他的都基本不用动

注:以上为不完全代码,依赖于ivew,提交的数据为postData 。存的全局变量

总结

  • 将每一个输入框都写成单独的,可配置的组件,借助ivew,把校验都放在单个表单组件内部完成
  • 写一个公共组件apply,利用slot提供可变部分传入,把不变的,比如附件,提交这些写入这个组件,提供的便利在于不用在每一个流程去关注提交,校验等等一系列每个流程都需要的操作
  • 具体到某一个流程时只需关注data的items,也就是开发一个流程,只写items就可以完成。

原文地址:https://segmentfault.com/a/1190000017306664

最新文章

  1. input-placeholder
  2. php字符串笔记
  3. 算法:欧几里得求最大公约数(python版)
  4. Guava集合-BiMap
  5. 【LeetCode OJ】Flatten Binary Tree to Linked List
  6. meate 标签使用介绍
  7. JS一个根据时区输出时区时间的函数
  8. git项目添加.gitigore文件
  9. Android入门:用HttpClient模拟HTTP的GET和POST请求
  10. MySQL Partition分区扫盲
  11. 游标-Oracle游标汇总
  12. Robotium跨应用处理方法
  13. winform combobox控件绑定 分类: WinForm 2014-04-17 14:34 118人阅读 评论(0) 收藏
  14. SQL Server中INNER JOIN与子查询IN的性能测试
  15. web service实例
  16. Python并发实践_02_通过yield实现协程
  17. 遍历tr通过name获取对应值用作判断或者赋值
  18. Bytom储蓄分红合约解析
  19. Hystrix 停止开发。。。Spring Cloud 何去何从?
  20. PHP is_writeable 存在bug , 写一个自定函数 判断文件是否可写

热门文章

  1. ABP .net Core MQTT+signalr通讯
  2. 深入理解Vuex 模块化(module)
  3. phoenix-hbase 使用
  4. Zeller 公式:计算任意一天是星期几
  5. Redis数据结构常用命令
  6. ZooKeeper java例子解读
  7. 后盾网lavarel视频项目---lavarel用户认证实例
  8. python-静态方法和类方法及其使用场景
  9. java连接oracle并load sql从xml执行查询
  10. ControlTemplate in WPF —— ItemsControl