<template> <el-dialog lock-scroll :title="dialogTitleMap[action]" @open="openDialog" :visible.sync="dialogVisible" top="2%" width="80%" :close-on-click-modal="false" :close-on-press-escape="false" :before-close='handleCancel'> <el-form :model="activitiEntity" :rules="rules" ref="activitiDialog" label-width="100px"> <el-row> <el-col :span="12"> <el-form-item label="流程名稱:" prop="name"> <el-input v-model="activitiEntity.name"></el-input> </el-form-item> </el-col> <el-col :span="10"> <el-form-item label="流程代碼:" prop="code"> <el-input :disabled="action === 'edit'" v-model="activitiEntity.code"></el-input> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="22"> <el-form-item label="流程備註:" prop="memo"> <el-input type="textarea" v-model="activitiEntity.memo"></el-input> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="20"> <el-form-item label="流程列表:"></el-form-item> </el-col> <el-col :span="2"> <el-button @click="addNode">添加流程節點</el-button> </el-col> </el-row> <el-row> <el-col :span="23"> <el-table style="margin-top: -10px;" fit :data="activitiEntity.nodes" :key='tableKey'> <el-table-column align="center" label="序號" width="50px;" type="index"></el-table-column> <el-table-column align="center" label="節點名稱" min-width="150px"> <template slot-scope="scope"> <span v-if="scope.$index === 0 || scope.$index === activitiEntity.nodes.length - 1">{{scope.row.name}}</span> <el-form-item v-else labelWidth="0" :prop="'nodes.'+scope.$index+'.name'" :rules="[{required: true, message: '請填寫節點名稱', trigger: 'blur'}, {validator: nodeNameCheck, trigger: ['blur']}]"> <el-input v-model="scope.row.name"></el-input> </el-form-item> </template> </el-table-column> <el-table-column align="center" label="接收部門" min-width="190px"> <template slot-scope="scope" width="100%"> <span v-if="scope.$index === 0 || scope.$index === 1 || scope.$index === activitiEntity.nodes.length - 1"></span> <el-form-item v-else labelWidth="0" :prop="'nodes.'+scope.$index+'.path'" :rules="{required: true, message: '請選擇接收部門', trigger: ['blur','change']}"> <el-cascader v-model="scope.row.path" :options="orgTree" @change="orgChange(scope.row, (scope.$index), true)" show-all-levels filterable clearable placeholder="請選擇" ></el-cascader> </el-form-item> </template> </el-table-column> <el-table-column align="center" label="消息通知人" min-width="140px"> <template slot-scope="scope" width="100%"> <span v-if="scope.$index === 0 || scope.$index === 1 || scope.$index === activitiEntity.nodes.length - 1"></span> <el-form-item v-else labelWidth="0" :prop="'nodes.'+scope.$index+'.notifier'"> <el-select v-model="scope.row.notifier" placeholder="請選擇" multiple> <el-option v-for="item in userOptions[scope.$index-2]" :key="item.id" :label="item.name" :value="item.id"> </el-option> </el-select> </el-form-item> </template> </el-table-column> <el-table-column align="center" label="辦理時效(工做日)" min-width="110px"> <template slot-scope="scope"> <span v-if="scope.$index === 0 || scope.$index === 1 || scope.$index === activitiEntity.nodes.length - 1"></span> <el-form-item v-else labelWidth="0" :rules="[{validator: nodePositiveIntegerCheck, trigger: ['blur']}]" :prop="'nodes.'+scope.$index+'.limitDays'"> <el-input style="width: 80px;" v-model.number="scope.row.limitDays"></el-input> </el-form-item> </template> </el-table-column> <el-table-column align="center" label="剩餘提醒天數" min-width="100px"> <template slot-scope="scope"> <span v-if="scope.$index === 0 || scope.$index === 1 || scope.$index === activitiEntity.nodes.length - 1"></span> <el-form-item v-else labelWidth="0" :rules="[{validator: nodePositiveIntegerCheck, trigger: ['blur']}]" :prop="'nodes.'+scope.$index+'.remindDays'"> <el-input style="width: 80px;" v-model.number="scope.row.remindDays"></el-input> </el-form-item> </template> </el-table-column> <el-table-column align="center" label="流程順序" min-width="80px"> <template slot-scope="scope"> <el-input style="width: 60px;text-align: right;" disabled v-model="scope.row.sequence"></el-input> </template> </el-table-column> <el-table-column align="center" label="操做" class-name="small-padding" min-width="90px"> <template slot-scope="scope"> <el-button type="text" plain icon="el-icon-minus" v-if="scope.$index !== 0 && scope.$index !== activitiEntity.nodes.length - 1" @click="minusNode(scope.$index)">刪除節點</el-button> </template> </el-table-column> </el-table> </el-col> </el-row> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="handleCancel">返 回</el-button> <el-button icon="el-icon-check" type="primary" @click="handleConfirm('activitiDialog')">確 認</el-button> </div> </el-dialog> </template> <script> import { saveDefinition, updateDefinition, findDefinitionDetail } from '@/api/activiti' import { findListByOrgId } from '@/api/egov' import { getTreeDataDept3 } from '@/api/transferTree' export default { props: ['action', 'activiti', 'dialogVisible'], data() { return { activitiEntity: { code: null, name: null, version: null, memo: null, nodes: [ { name: 'start', receiver: null, limitDays: null, remindDays: null, sequence: 1, path: [], notifier: [] }, { name: 'end', receiver: null, limitDays: null, remindDays: null, sequence: 2, path: [], notifier: [] } ] }, tableKey: '1', dialogTitleMap: { 'add': '流程添加', 'edit': '流程編輯' }, userOptions: [], orgTree: [], rules: { name: [{ required: true, message: '請填寫流程名稱', trigger: 'blur' }], code: [{ required: true, message: '請填寫流程代碼', trigger: 'blur' }] } } }, methods: { nodeNameCheck(rule, value, callback) { if (value === '') { callback(new Error('請輸入節點名稱')) } else if (value === 'start' || value === 'end') { callback(new Error('節點名稱不可爲' + value)) } else { const nodeArr = this.activitiEntity.nodes const indexArr = rule.field ? rule.field.split('.') : [] let index = null if (indexArr && indexArr.length > 1) { index = indexArr[1] } if (nodeArr && nodeArr.length > 0) { for (var i = 0; i < nodeArr.length; i++) { if (value === nodeArr[i].name && ((i + '') !== index)) { callback(new Error('該節點名稱已存在')) break } else if (i === nodeArr.length - 1) { callback() } } } callback() } }, nodePositiveIntegerCheck(rule, value, callback) { if (value) { const reg = /^[1-9]\d*$/ const result = reg.test(value) if (result) { callback() } else { callback(new Error('請輸入整數')) } } else { callback() } }, openDialog() { this.getTransferTreeData() this.action === 'edit' ? this.getAcDetail() : this.resetEntity() }, handleConfirm(formName) { this.action === 'edit' ? this.updateActiviti(formName) : this.saveActiviti(formName) }, getTransferTreeData() { const result = getTreeDataDept3() this.orgTree = result }, getAcDetail() { findDefinitionDetail({ id: this.activiti.id }).then(response => { this.activitiEntity = response.data.result const tt = response.data.result if (response.data.result && tt.content) { const temp = JSON.parse(tt.content) if (temp && temp.nodes) { const nodes = temp.nodes nodes.forEach((n, i) => { if (i > 1) { this.orgChange(n, i, false) } let notifier = n.notifier if (notifier && notifier.length > 0) { const temp = [] for (const t of notifier) { temp.push(t.userId) } notifier = temp } else { notifier = [] } n.notifier = notifier }) this.activitiEntity.nodes = nodes } } }) }, addNode() { const endNode = this.activitiEntity.nodes.pop() this.activitiEntity.nodes.push(this.newNode()) endNode.sequence = this.activitiEntity.nodes.length + 1 this.activitiEntity.nodes.push(endNode) if (endNode.sequence > 3) { this.userOptions.push([]) } }, minusNode(index) { this.activitiEntity.nodes.splice(index, 1) for (let i = index; i < this.activitiEntity.nodes.length; i++) { this.activitiEntity.nodes[i].sequence = i + 1 } if (index > 1) { this.userOptions.splice(index - 2, 1) } }, newNode() { return { name: null, receiver: null, path: [], limitDays: null, remindDays: null, notifier: [], sequence: this.activitiEntity.nodes.length + 1 } }, orgChange(row, ind, isActive) { if (row && row.path) { const val = row.path if (val && val.length > 0) { const index = val.length - 1 row.receiver = val[index] this.getUserOption(val[index], ind, isActive) } else { row.receiver = null } } }, getUserOption(orgId, ind, isActive) { if (orgId && ind > 1) { findListByOrgId({ id: orgId }).then(response => { if (response.data.result && response.data.result.length > 0) { this.userOptions[ind - 2] = response.data.result if (isActive) { this.activitiEntity.nodes[ind].notifier = [] } } }) } }, transferNotifiers() { const nodes = this.activitiEntity.nodes const userOptions = this.userOptions if (nodes && nodes.length > 0) { nodes.forEach((node, ind) => { const notifier = node.notifier if (notifier && notifier.length > 0) { const options = userOptions[ind - 2] notifier.forEach((n, i) => { const obj = options.find((it) => { return it.id === n }) if (obj) { const t = { userId: obj.id, userName: obj.name } this.activitiEntity.nodes[ind].notifier[i] = t } }) } }) } }, saveActiviti(formName) { this.$refs[formName].validate((valid) => { if (valid) { this.activitiEntity['content'] = null this.transferNotifiers() saveDefinition(this.activitiEntity).then(res => { const data = res.data if (data.success) { this.$notify({ title: '成功', message: '新增成功', type: 'success', duration: 2000 }) } else { this.$notify({ title: '失敗', message: '新增失敗', type: 'error', duration: 2000 }) } this.handleCancel() }) } else { return } }) }, updateActiviti(formName) { this.$refs[formName].validate((valid) => { if (valid) { this.activitiEntity['content'] = null this.transferNotifiers() updateDefinition(this.activitiEntity).then(res => { const data = res.data if (data.success) { this.$notify({ title: '成功', message: '更新成功', type: 'success', duration: 2000 }) } else { this.$notify({ title: '失敗', message: '更新失敗', type: 'error', duration: 2000 }) } this.handleCancel() }) } else { return } }) }, resetEntity() { this.userOptions = [] this.activitiEntity = { code: null, name: null, version: null, memo: null, nodes: [ { name: 'start', receiver: null, limitDays: null, remindDays: null, sequence: 1, path: [], notifier: [] }, { name: 'end', receiver: null, limitDays: null, remindDays: null, sequence: 2, path: [], notifier: [] }] } }, handleCancel() { this.$emit('closeDialog') this.resetEntity() this.$nextTick(() => { this.$refs['activitiDialog'].clearValidate() }) } } } </script> <style scoped> .el-form-item--mini.el-form-item, .el-form-item--small.el-form-item { margin-bottom: 15px !important; } .el-cascader { display: block !important; } </style>