import { getFormByProcessId, startProcess, detail, completeTask, transferTask, delegateTask, rollbackTask, terminateProcess, addMultiInstance, withdrawTask } from '@/api/plugin/workflow/process' import Layout from '@/page/index/' import defaultValues from './default-values' import Print from '../util/print' import Watermark from '../util/watermark' import { mapGetters } from 'vuex' export default { mixins: [defaultValues], computed: { ...mapGetters(['tag', 'userInfo', 'permission']), }, data() { return { process: {}, // 流程定义/流程实例信息 buttonList: [], // 配置按钮信息 flow: [], // 流转信息 userSelectType: '', // 人员选择类型 transfer转办 delegate委托 copy抄送 assignee审核人 checkType: 'radio', // 人员选择check类型 radio单选 checkbox多选 comment: '', // 评论 bpmnOption: {}, // 流程图配置信息 defaultChecked: '', // 人员选择默认选中 waiting: true, // 骨架屏加载中 } }, methods: { // 动态路由跳转 dynamicRoute(row, type, async = false) { const { id, taskId, processInstanceId, processId, formKey, formUrl } = row let param = Buffer.from(JSON.stringify({ processId: id, taskId, processInsId: processInstanceId || processId })).toString('base64') if (formKey && formKey.startsWith('wf_ex_')) { if (formUrl) { // 配置了自定义路由 this.$router.push(formUrl + `?p=${param}`) } else { // 动态添加路由 this.$router.addRoutes([{ path: `/workflow/process/external`, component: Layout, children: [{ path: `${formKey.substring(6)}/${type}`, name: type == 'start' ? '发起流程' : '流程详情', component: () => import( /* webpackChunkName: "views" */ `@/views/plugin/workflow/process/external/${formKey.substring(6)}/${type}.vue`), }] }]) this.$router.push(`/workflow/process/external/${formKey.substring(6)}/${type}?p=${param}`) } } else { if (async) { return new Promise((resolve) => { resolve({ row, type, param }) }) } else { this.$router.push(`/workflow/process/${type}/${param}`) } } }, // 根据可读可写,过滤avue column filterAvueColumn(column, taskForm, isExForm = false, props = { label: 'label', prop: 'prop' }) { const _this = this if (!column || column.length == 0) return { column, vars: [] } const values = [] const vars = [] column.forEach(col => { let c = taskForm.find(s => s.id == col[props.prop]) if (c && c.readable) { // /** // * @deprecated 与节点配置可读可写冲突 // */ // if (!c) { // 未重新点击节点设计表单字段可读可写。 // if ((this.process.isOwner && this.process.status == 'todo') || !this.process.hasOwnProperty('isOwner')) c = { readable: true, writable: true } // else c = { readable: true, writable: false } // } let event = ['change', 'blur', 'click', 'focus'] if (c.writable) { // 可写,记录需要提交的字段、处理字段默认值 vars.push(col[props.prop]) if (col.value) col.value = _this.getDefaultValues(col.value) if (!isExForm) { // 非外置表单 处理事件 event.forEach(e => { if (col[e]) col[e] = eval((col[e] + '').replace(/this/g, '_this')) }) if (col.event) Object.keys(col.event).forEach(key => col.event[key] = eval((col.event[key] + '').replace(/this/g, '_this'))) } } else { // 不可写,清除校验、默认值、事件 if (col.type == 'dynamic') { col.children.addBtn = false col.children.delBtn = false } else { col.readonly = true col.disabled = true } delete col.rules delete col.value delete col.event event.forEach(e => delete col[e]) } if (col.type == 'dynamic') { // 处理子表单 col.children.column = _this.filterAvueColumn(col.children.column, taskForm).column } if (col.rules && col.pattern) { // 处理正则 col.rules.forEach(c => { if (c.pattern) c.pattern = new RegExp(col.pattern) }) } values.push(col) } }) return { column: values, vars } }, /** * 获取流程发起表单 * @param processId 流程定义id * @returns Promise({"process": "流程定义信息", "startForm": "开始节点表单"}) */ getStartForm(processId) { return new Promise((resolve, reject) => { getFormByProcessId({ processId }).then(res => { const { process } = res.data.data process.hideComment = true this.process = process this.tag.label = '发起流程 - ' + process.name resolve(res.data.data) }).catch(() => { reject() }) }) }, /** * 发起流程 * @param form {"processId": "流程定义id", ...表单自定义字段变量} */ handleStartProcess() { this.loading = true this.$refs.form.validate((valid, done, msg) => { let form = this.deepClone(this.form) if (this.$refs.examineForm && this.$refs.examineForm.examineForm) { const { copyUser, assignee } = this.$refs.examineForm.examineForm form = { ...form, copyUser, assignee } } if (valid) { startProcess(form).then(() => { this.$message.success("发起成功") this.handleCloseTag('/plugin/workflow/process/send') done() this.loading = false }).catch(() => { done() this.loading = false }) } else { done() this.loading = false if (msg) { const key = Object.keys(msg)[0] const rules = msg[key] this.$message.error(rules.map(r => r.message).join(' | ')) } } }) }, /** * 获取流程任务详情 * @param taskId 任务id * @param processInsId 流程实例id * @returns Promise({"process": "流程实例信息", "form": "表单信息", "flow": "流转信息", "button": "配置按钮信息", "bpmnOption": "流程图配置"}) */ getTaskDetail(taskId, processInsId) { return new Promise((resolve, reject) => { detail({ taskId, processInsId }).then(res => { const { process, form, flow, button } = res.data.data const { xml } = process const bpmnOption = { mode: 'view', xml, flows: this.handleResolveFlows(flow) } this.process = process this.flow = flow this.buttonList = button this.bpmnOption = bpmnOption this.tag.label = '流程详情 - ' + process.processDefinitionName resolve({ process, form, flow, button, bpmnOption }) }).catch(() => { reject() }) }) }, /** * 任务审核 * @param pass 驳回/通过 */ handleCompleteTask(pass, variables) { return new Promise((resolve, reject) => { const { comment, copyUser, assignee, attachment } = this.$refs.examineForm.examineForm if (!pass && !comment) { this.$message.error("请填写批复意见") this.submitLoading = false reject() return } const { taskId, processInstanceId, processDefinitionName, processDefinitionId } = this.process const param = { taskId, processInstanceId, processDefinitionName, processDefinitionId, pass, comment, copyUser, assignee, variables, attachment } completeTask(param).then(() => { resolve() }).catch(() => { reject() }) }) }, /** * 驳回到指定节点 * @param nodeId 节点id */ handleRollbackTask(nodeId) { const { taskId } = this.process rollbackTask({ comment: this.comment, nodeId, taskId }).then(() => { this.$message.success("回退成功") this.handleCloseTag('/plugin/workflow/process/todo') }) }, /** * 终止流程 */ handleTerminateProcess() { const comment = this.comment if (!comment) { this.$message.error("请填写批复意见") return } this.$confirm('确定要终止此流程吗?', '警告', { type: 'warning' }).then(() => { const { taskId } = this.process terminateProcess({ taskId, comment }).then(() => { this.$message.success("操作成功") this.handleCloseTag('/plugin/workflow/process/todo') }) }).catch(() => { }) }, // 人员选择弹窗 handleUserSelect({ type, checkType }) { if (!this.comment && ['transfer', 'delegate'].includes(type)) { this.$message.error("请填写批复意见") return } if (type == 'assignee') this.defaultChecked = this.$refs.examineForm.examineForm.assignee else if (type == 'copy') this.defaultChecked = this.$refs.examineForm.examineForm.copyUser this.$refs['user-select'].visible = true this.userSelectType = type this.checkType = checkType }, // 选人回调 handleUserSelectConfirm(id, name) { const { comment, copyUser } = this.$refs.examineForm.examineForm const { taskId, processInstanceId, processDefinitionName, processDefinitionId } = this.process const type = this.userSelectType const param = { taskId, processInstanceId, processDefinitionName, processDefinitionId, assignee: id, comment, copyUser } if (type == 'transfer') { transferTask(param).then(() => { // 转办 this.$message.success("转办成功") this.handleCloseTag('/plugin/workflow/process/todo') }) } else if (type == 'delegate') { // 委托 delegateTask(param).then(() => { this.$message.success("委托成功") this.handleCloseTag('/plugin/workflow/process/todo') }) } else if (type == 'addInstance') { // 加签 addMultiInstance(param).then(() => { this.$message.success("加签成功") }) } else if (type == 'copy') { // 抄送 this.$refs.examineForm.examineForm.copyUser = id this.$refs.examineForm.examineForm.$copyUser = name } else if (type == 'assignee') { // 指定下一步审批人 this.$refs.examineForm.examineForm.assignee = id this.$refs.examineForm.examineForm.$assignee = name } this.$refs['user-select'].visible = false }, handleWithdrawTask() { const { taskId } = this.process this.$confirm('

撤销:撤销终止此流程

撤回:撤回到发起人重新提交,若当前流程不存在发起人节点,功能同撤销

', '请选择撤销/撤回操作', { type: 'warning', distinguishCancelAndClose: true, confirmButtonText: '撤销', cancelButtonText: '撤回', dangerouslyUseHTMLString: true }).then(() => { withdrawTask({ taskId, withdrawType: 'wf_withdraw_end' }).then(() => { this.$message.success("操作成功") this.handleCloseTag('/plugin/workflow/process/todo') }) }).catch((action) => { if (action == 'cancel') { withdrawTask({ taskId, withdrawType: 'wf_withdraw_start' }).then(() => { this.$message.success("操作成功") this.handleCloseTag('/plugin/workflow/process/todo') }) } }) }, handlePrint() { // 打印 const loading = this.$loading({ lock: true, text: 'Loading', spinner: 'el-icon-loading', background: 'rgba(0, 0, 0, 0.7)' }); const option = this.deepClone(this.option) this.option.detail = true if (this.option.column) { this.option.column.forEach(col => { this.handleTemporaryPrintOption(col) }) } if (this.option.group) { this.option.group.forEach(g => { g.column.forEach(col => { this.handleTemporaryPrintOption(col) }) }) } setTimeout(() => { loading.close() // const watermarkText = this.userInfo.user_name + " " + this.userInfo.dept_name // Watermark.set({ watermark_txt: watermarkText }) // 添加水印 Print('#printBody') this.option = option Watermark.remove() // 删除水印 }, 500) }, // 生成打印临时option handleTemporaryPrintOption(obj) { if (!obj.type) return obj.span = 24 if (obj.type == 'dynamic') { obj.children.type = 'form' obj.children.column.forEach(col => { this.handleTemporaryPrintOption(col) }) } }, // 关闭当前tag,并跳转 handleCloseTag(path) { this.$store.commit('DEL_TAG', this.tag) if (path) this.$router.push(path) }, handleResolveFlows(flow) { const flows = [] flow.forEach(f => { const { assigneeName, createTime, endTime, comments } = f const ff = { id: f.historyActivityId, class: (!endTime && f.historyActivityType != 'candidate') ? 'nodePrimary': '' } let tooltip = '' if (assigneeName) { tooltip = `${assigneeName}
` if (createTime) tooltip += `${this.dateFormat(new Date(createTime), 'yyyy-MM-dd hh:mm')}
` if (comments && comments.length > 0) { let comment let { type, fullMessage } = comments[0] if (type == 'assigneeComment') { comment = '变更审核人:' + fullMessage ff.class = 'nodeWarn' } if (type == 'dispatchComment') { comment = '调度:' + fullMessage ff.class = 'nodeWarn' } if (type == 'transferComment') { comment = '转办:' + fullMessage ff.class = 'nodeWarn' } if (type == 'delegateComment') { comment = '委托:' + fullMessage ff.class = 'nodeWarn' } if (type == 'rollbackComment') { comment = '驳回:' + fullMessage ff.class = 'nodeError' } if (type == 'terminateComment') { comment = '终止:' + fullMessage ff.class = 'nodeError' } if (type == 'addMultiInstanceComment') { comment = '加签:' + fullMessage ff.class = 'nodeWarn' } if (type == 'deleteMultiInstanceComment') { comment = '减签:' + fullMessage ff.class = 'nodeError' } if (type == 'withdrawComment') { comment = '撤销:' + fullMessage ff.class = 'nodeWarn' } if (type == 'comment') { comment = '审批:' + fullMessage ff.class = 'nodeSuccess' } tooltip += `${comment}` } ff.tooltip = tooltip } if (f.historyActivityType == 'sequenceFlow') ff.class = 'lineWarn' else if (!ff.class && f.historyActivityType != 'candidate') ff.class = 'nodeSuccess' const index = flows.findIndex(fl => fl.id == f.historyActivityId) if (index != -1) flows.splice(index, 1, ff) else flows.push(ff) }) return flows }, // 上传组件预览 handleUploadPreview(file, column, done) { const { url } = file const { video, img } = this.$typeList if (video.test(url) || img.test(url)) done() else window.open(url) }, } }