慢直播
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

452 lines
16 KiB

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('<p><span style="color: red;">撤销:</span>撤销终止此流程</p><p><span style="color: red;">撤回:</span>撤回到发起人重新提交,若当前流程不存在发起人节点,功能同撤销</p>', '请选择撤销/撤回操作', {
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 = `<span title='${assigneeName}'>${assigneeName}</span><br>`
if (createTime) tooltip += `<span title='${createTime}'>${this.dateFormat(new Date(createTime), 'yyyy-MM-dd hh:mm')}</span><br>`
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 += `<span title='${comment}'>${comment}</span>`
}
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)
},
}
}