在oa開發中,有許多流程,每一個流程裏都會有不少字段,好比流程標題、拉下選擇,附件等等,有些是每一個流程都會有的,有些是特有的,按常規的方法開發,就爲爲一個流程寫一個表單,校驗,提交。若是新來流程,就複製一個表達,修改須要變動的地方。這樣開發會致使不少重複的代碼,並且比較凌亂css
<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>
<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>
<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>
<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>
是每一個流程的表單部分,其餘則爲每一個流程共有的,好比附件、提交操做等。vue
<template> <apply :processKey="processKey" :candidate="candidate"> <!-- apply的slot部分,即爲每一個流程的表單部分 --> <component :is="item.component" v-for="(item, index) in items" :config="item" :key="index"> </component> </apply> </template> <script> import apply from './../comm/apply.vue' import {mapState, mapMutations} from 'vuex' const getComponent = name => { return resolve => 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({}) } } </script> <style lang="less" scoped> @import './../../../static/css/process/process.less'; </style>
這樣再開發新流程的過程當中就不用去重寫template部分了,只須要配置好data裏的items,這裏指明瞭當前流程所須要的字段,每一個字段的各類屬性,其餘的都基本不用動vuex
注:以上爲不徹底代碼,依賴於ivew,提交的數據爲postData 。存的全局變量app