<template>
|
<div class="app-container">
|
<el-result v-if="isSuccess" icon="success" title="操作成功" subTitle="您的任务已处理完成">
|
<template slot="extra">
|
</template>
|
</el-result>
|
|
<el-card v-else class="box-card" >
|
<div slot="header" class="clearfix header-container">
|
<div class="header-title el-icon-document">{{`任务办理:` + processName}}</div>
|
<div class="header-subtitle">{{projectName + '——' + flowName}}</div>
|
<!-- <el-button class="header-close-btn" size="mini" type="danger" @click="goBack">关闭</el-button> -->
|
</div>
|
<el-tabs tab-position="top" v-model="activeName" @tab-click="handleClick">
|
<!--表单信息-->
|
<el-tab-pane label="表单信息" name="1">
|
<!--初始化流程加载表单信息-->
|
<el-col :span="24" v-loading="formLoading" class="tab-min-height">
|
<div v-if="formDataList && formDataList.length > 0">
|
<div v-for="(formDataObj, index) in formDataList" :key="index" class="form-warp" style="position: relative">
|
<el-row>
|
<el-col :xs="24" :sm="18">
|
<div v-if="formDataObj.current">
|
<!-- 当前节点可协同、转办等操作 -->
|
<div class="op-list mobile-op-list">
|
<el-button size="mini" type="primary" :disabled="formDataObj.taskStatus === '挂起' || submitLoading" v-loading="submitLoading" @click="submitForm">确认并提交</el-button>
|
<el-button size="mini" type="primary" v-if="!isWait" :disabled="formDataObj.taskStatus === '挂起'" @click="openDelegation(formDataList[0].beforeNodeName)">转办</el-button>
|
<el-button v-if="formDataObj.canJump && !isWait" :disabled="formDataObj.taskStatus === '挂起'" size="mini" type="primary" @click="jumpTask()">跳过</el-button>
|
<el-button v-if="formDataObj.canWait && !isWait" :disabled="formDataObj.taskStatus === '挂起'" size="mini" type="primary" @click="waitTask()">容缺</el-button>
|
<el-button v-if="formDataObj.canHangup && formDataObj.taskStatus !== '挂起' && !isWait" size="mini" type="primary" @click="hangup">挂起</el-button>
|
<el-button v-if="formDataObj.canHangup && formDataObj.taskStatus === '挂起' && !isWait" size="mini" type="primary" @click="cancelHangup">结束挂起</el-button>
|
</div>
|
<div class="current">当前阶段:<span>{{formDataObj.beforeNodeName}}</span><span v-if="formDataObj.taskStatus === 'HANGUP'">(挂起中)</span></div>
|
</div>
|
<div v-else-if="formDataList.length > 1">
|
<!-- 前置节点可驳回 -->
|
<div class="reject-but mobile-reject-but">
|
<el-button type="danger" size="mini" @click="openRejectTask(formDataObj.beforeNodeName)">驳 回</el-button>
|
</div>
|
<div class="before">前置阶段:<span>{{formDataObj.beforeNodeName}}</span></div>
|
</div>
|
<div v-if="formDataObj != null && formDataObj.formJsonObj != null">
|
<v-form-render :form-data="formDataObj.formJsonObj.formJson" :ref="'form' + index"/>
|
</div>
|
<div v-else>
|
<el-alert title="未绑定表单" type="warning" :closable="false"></el-alert>
|
</div>
|
<div v-if="formDataList.length <= 1">
|
<div class="before_none">前置阶段:<span>不存在前置阶段</span></div>
|
<el-alert title="不存在前置阶段" type="warning" :closable="false"></el-alert>
|
</div>
|
</el-col>
|
<el-col :xs="24" :sm="6">
|
<log-time-line v-if="formDataObj.events.length > 0" :log-list="formDataObj.events"/>
|
</el-col>
|
</el-row>
|
</div>
|
</div>
|
</el-col>
|
</el-tab-pane>
|
<!--流程图-->
|
<!-- <el-tab-pane label="流程图" name="2">-->
|
<!-- <div v-loading="imgLoading" class="tab-min-height">-->
|
<!-- <bpmn-viewer :flowData="flowData" :procInsId="procInsId"/>-->
|
<!-- </div>-->
|
<!-- </el-tab-pane>-->
|
</el-tabs>
|
</el-card>
|
|
<!--选择流程接收人-->
|
<el-dialog :title="taskTitle" :visible.sync="taskOpen" width="90%" append-to-body>
|
<flow-user v-if="checkSendUser" :checkType="checkType" @handleUserSelect="handleUserSelect"/>
|
<flow-role v-if="checkSendRole" @handleRoleSelect="handleRoleSelect"/>
|
<span slot="footer" class="dialog-footer">
|
<el-button @click="taskOpen = false">取 消</el-button>
|
<el-button type="primary" @click="submitTask">提 交</el-button>
|
</span>
|
</el-dialog>
|
|
<!--驳回弹窗-->
|
<el-dialog :title="`驳回:` + rejectForm.taskName" :visible.sync="rejectShow" width="90%" :destroy-on-close="true" :close-on-click-modal="false">
|
<div>
|
<el-input type="textarea" :rows="3" placeholder="审核建议" v-model="rejectForm.comment"></el-input>
|
</div>
|
<div class="opBut">
|
<el-button type="danger" size="small" :disabled="rejectLoading" v-loading="rejectLoading" @click="rejectTask">驳回</el-button>
|
</div>
|
</el-dialog>
|
|
<!--转办弹窗-->
|
<el-dialog :title="`转办:` + delegationForm.taskName" :visible.sync="delegationShow" width="90%" :destroy-on-close="true" :close-on-click-modal="false">
|
<div>
|
<el-form :model="delegationForm" :rules="delegationFormRules" ref="delegationForm" label-width="80px" class="demo-ruleForm">
|
<el-alert title="请选择要转办的用户对象" type="info" :closable="false" style="margin-bottom: 8px" show-icon></el-alert>
|
<el-form-item label="用户类型" prop="peopleType">
|
<el-select v-model="delegationForm.peopleType" @change="peopleTypeChange" placeholder="请选择用户类型" style="width: 100%">
|
<el-option label="指定人员" value="FIX_USER"></el-option>
|
<el-option label="候选人员" value="USER"></el-option>
|
<el-option label="候选部门" value="DEPT"></el-option>
|
<el-option label="候选角色" value="ROLE"></el-option>
|
</el-select>
|
</el-form-item>
|
<el-form-item v-if="delegationForm.peopleType === 'DEPT'" label="候选部门" prop="targetId">
|
<MyDept ref="dept" :checkeds="delegationDeptSelect" :title="`选择转办部门`" :show="deptShow" @close="closeDept" @submit="getDeptSelect" :key="deptKey"/>
|
<div class="tag-group">
|
<el-tag v-for="dept in delegationDeptSelect" :key="dept.id" type="info" closable @close="removeDept(dept)">{{dept.label}}</el-tag>
|
<el-button type="text" @click="editDept">选择</el-button>
|
</div>
|
</el-form-item>
|
<el-form-item v-if="delegationForm.peopleType === 'FIX_USER'" label="指定人员" prop="targetId">
|
<single-user ref="singleUser" :select-user="delegationForm.targetId" :title="`选择转办接收人员`" :show="singleUserShow" @close="closeSingleUser" @submit="getSingleUserSelect" :key="singleUserKey"/>
|
<div class="tag-group">
|
<el-tag v-for="user in delegationUserSelect" :key="user.userId" type="info" closable @close="removeSingleUser(user)">{{user.nickName}}</el-tag>
|
<el-button type="text" @click="editSingleUser">选择</el-button>
|
</div>
|
</el-form-item>
|
<el-form-item v-if="delegationForm.peopleType === 'USER'" label="候选人员" prop="targetId">
|
<mult-user ref="multUser" :select-user="delegationUserSelect" :title="`选择转办接收人员`" :show="multUserShow" @close="closeMultUser" @submit="getMultUserSelect" :key="multUserKey"/>
|
<div class="tag-group">
|
<el-tag v-for="user in delegationUserSelect" :key="user.userId" type="info" closable @close="removeMultUser(user)">{{user.nickName}}</el-tag>
|
<el-button type="text" @click="editMultUser">选择</el-button>
|
</div>
|
</el-form-item>
|
<el-form-item v-if="delegationForm.peopleType === 'ROLE'" label="候选角色" prop="targetId">
|
<my-role ref="role" :select-values="delegationRoleSelect" :title="`选择转办角色`" :show="roleShow" @close="closeRole" @submit="getRoleSelect" :key="roleKey"/>
|
<div class="tag-group">
|
<el-tag v-for="role in delegationRoleSelect" :key="role.roleId" type="info" closable @close="removeRole(role)">{{role.roleName}}</el-tag>
|
<el-button type="text" @click="editRole">选择</el-button>
|
</div>
|
</el-form-item>
|
</el-form>
|
</div>
|
<div class="opBut">
|
<el-button type="danger" size="small" :disabled="delegationButLoading" v-loading="delegationButLoading" @click="delegation">转 办</el-button>
|
</div>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script>
|
import { flowXmlAndNode } from "@/api/flowable/definition";
|
import BpmnViewer from '@/components/Process/viewer';
|
import MyDept from '@/components/flow/Dept/MyDept'
|
import SingleUser from '@/components/flow/User/SingleUser'
|
import MultUser from '@/components/flow/User/MultUser'
|
import MyRole from '@/components/flow/Role/MyRole'
|
import FlowUser from '@/components/flow/User'
|
import FlowRole from '@/components/flow/Role'
|
import { completeSubmitFormTask, waitCompleteSubmitFormTask, rejectTask } from "@/api/flowable/process";
|
import { flowTaskForm } from "@/api/flowable/todo";
|
import LogTimeLine from "@/views/projectProcess/components/LogTimeLine";
|
import { cancelTaskHangup, taskDelegation, taskHangup, taskJump, taskWait } from "@/api/projectProcess/projectProcess";
|
import { setToken } from "@/utils/auth";
|
|
export default {
|
name: "WebViewSend",
|
components: {
|
BpmnViewer, MyRole, MyDept, SingleUser, MultUser, LogTimeLine, FlowUser, FlowRole
|
},
|
data() {
|
return {
|
isWait: false,
|
isSuccess: false,
|
rejectLoading: false,
|
submitLoading: false,
|
delegationButLoading: false,
|
formLoading: false,
|
imgLoading: false,
|
roleKey: 'role',
|
deptKey: 'dept',
|
multUserKey: 0,
|
singleUserKey: 'single',
|
projectName: '',
|
flowName: '',
|
processName: '',
|
roleShow: false,
|
delegationRoleSelect: [],
|
multUserShow: false,
|
singleUserShow: false,
|
delegationUserSelect: [],
|
deptShow: false,
|
delegationDeptSelect: [],
|
delegationFormRules: {
|
peopleType: [{ required: true, message: '请选择用户类型', trigger: 'change' }],
|
targetId: [{ required: true, message: '请选择转办对象', trigger: 'blur' }],
|
},
|
delegationForm: {
|
taskId: '',
|
peopleType: '',
|
targetId: '',
|
taskName: '',
|
processInsId: '',
|
projectId: '',
|
},
|
delegationShow: false,
|
rejectShow: false,
|
formDataList: [],
|
taskId: '',
|
flowData: {},
|
activeName: '1',
|
procInsId: "",
|
deployId: "",
|
projectId: "",
|
taskTitle: null,
|
taskOpen: false,
|
checkSendUser: false,
|
checkSendRole: false,
|
checkType: '',
|
checkValues: null,
|
formData: {},
|
multiInstanceVars: '',
|
formJson: {},
|
rejectForm: {
|
comment: '',
|
taskId: '',
|
taskName: ''
|
}
|
};
|
},
|
async created() {
|
await this.initPage();
|
if (this.taskId) {
|
this.getFlowFormData(this.taskId);
|
}
|
},
|
methods: {
|
async initPage() {
|
try {
|
const urlToken = this.getUrlParam('token');
|
console.log(urlToken)
|
|
if (urlToken) {
|
const token = decodeURIComponent(urlToken);
|
setToken(token);
|
this.$store.commit('SET_TOKEN', token);
|
}
|
|
this.deployId = decodeURIComponent(this.getUrlParam('deployId'));
|
this.taskId = decodeURIComponent(this.getUrlParam('taskId'));
|
this.procInsId = decodeURIComponent(this.getUrlParam('procInsId'));
|
this.projectName = decodeURIComponent(this.getUrlParam('projectName'));
|
this.flowName = decodeURIComponent(this.getUrlParam('flowName'));
|
this.processName = decodeURIComponent(this.getUrlParam('processName'));
|
this.projectId = decodeURIComponent(this.getUrlParam('projectId'));
|
this.isWait = this.getUrlParam('isWait') === 'true';
|
} catch (err) {
|
console.error('页面初始化失败:', err);
|
}
|
},
|
getUrlParam(name) {
|
const reg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`);
|
const r = window.location.search.substr(1).match(reg);
|
return r != null ? r[2] : '';
|
},
|
handleClick(tab) {
|
if (tab.name === '2') {
|
this.imgLoading = true;
|
flowXmlAndNode({ processInsId: this.procInsId, deployId: this.deployId }).then(res => {
|
this.imgLoading = false;
|
this.flowData = res.data;
|
});
|
}
|
},
|
getFlowFormData(taskId) {
|
this.formLoading = true;
|
flowTaskForm({ taskId }).then(res => {
|
this.formDataList = res.data;
|
if (this.formDataList && this.formDataList.length > 0) {
|
this.$nextTick(() => {
|
this.formDataList.forEach((formDataObj, index) => {
|
if (this.$refs['form' + index] && formDataObj.formJsonObj) {
|
this.$refs['form' + index][0].setFormJson(formDataObj.formJsonObj.formJson);
|
this.$refs['form' + index][0].setFormData(formDataObj.formJsonObj);
|
}
|
});
|
if (this.formDataList[0].formJsonObj) {
|
this.formJson = this.formDataList[0].formJsonObj.formJson;
|
}
|
});
|
}
|
this.formLoading = false;
|
}).catch(() => {
|
this.formLoading = false;
|
});
|
},
|
submitForm() {
|
this.$confirm(`确定要提交任务【${this.processName}】吗?`, '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
}).then(() => {
|
if (this.$refs['form0']) {
|
this.$refs['form0'][0].getFormData().then(formData => {
|
this.submitLoading = true;
|
this.formData = formData;
|
const param = { formJson: this.formJson };
|
Object.assign(param, formData);
|
const api = this.isWait ? waitCompleteSubmitFormTask : completeSubmitFormTask;
|
api(this.taskId, param).then(res => {
|
this.isSuccess = true;
|
this.submitLoading = false;
|
}).catch(() => { this.submitLoading = false; });
|
});
|
} else {
|
const api = this.isWait ? waitCompleteSubmitFormTask : completeSubmitFormTask;
|
api(this.taskId, {}).then(res => {
|
this.isSuccess = true;
|
});
|
}
|
});
|
},
|
openRejectTask(taskName) {
|
this.rejectForm.taskName = taskName;
|
this.rejectForm.taskId = this.taskId;
|
this.rejectShow = true;
|
},
|
rejectTask() {
|
this.$confirm(`确定要驳回任务【${this.rejectForm.taskName}】吗?`, '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
}).then(() => {
|
this.rejectLoading = true;
|
rejectTask(this.rejectForm).then(res => {
|
this.rejectShow = false;
|
this.isSuccess = true;
|
}).finally(() => { this.rejectLoading = false; });
|
});
|
},
|
openDelegation(taskName) {
|
this.delegationForm.taskName = taskName;
|
this.delegationForm.taskId = this.taskId;
|
this.delegationShow = true;
|
},
|
delegation() {
|
this.$refs['delegationForm'].validate((valid) => {
|
if (valid) {
|
this.delegationForm.projectId = this.projectId;
|
this.delegationForm.processInsId = this.procInsId;
|
this.delegationButLoading = true;
|
taskDelegation(this.delegationForm).then(res => {
|
this.isSuccess = true;
|
this.delegationShow = false;
|
}).finally(() => { this.delegationButLoading = false; });
|
}
|
});
|
},
|
// 其他辅助方法(转办相关)
|
peopleTypeChange(val) {
|
if (val === 'DEPT') { this.deptShow = true; }
|
else if (val === 'FIX_USER') { this.singleUserShow = true; }
|
else if (val === 'USER') { this.multUserShow = true; }
|
else if (val === 'ROLE') { this.roleShow = true; }
|
},
|
getDeptSelect(list) { this.delegationDeptSelect = list; this.delegationForm.targetId = list.map(i => i.id).join(","); this.deptShow = false; },
|
getMultUserSelect(list) { this.delegationUserSelect = list; this.delegationForm.targetId = list.map(i => i.userId).join(","); this.multUserShow = false; },
|
getRoleSelect(list) { this.delegationRoleSelect = list; this.delegationForm.targetId = list.map(i => i.roleId).join(","); this.roleShow = false; },
|
getSingleUserSelect(user) { this.delegationUserSelect = user ? [user] : []; this.delegationForm.targetId = user ? user.userId : ''; this.singleUserShow = false; },
|
editDept() { this.deptShow = true; },
|
editSingleUser() { this.singleUserShow = true; },
|
editRole() { this.roleShow = true; },
|
editMultUser() { this.multUserShow = true; },
|
removeDept(dept) { this.delegationDeptSelect = this.delegationDeptSelect.filter(i => i.id !== dept.id); },
|
removeRole(role) { this.delegationRoleSelect = this.delegationRoleSelect.filter(i => i.roleId !== role.roleId); },
|
removeMultUser(user) { this.delegationUserSelect = this.delegationUserSelect.filter(i => i.userId !== user.userId); },
|
removeSingleUser() { this.delegationUserSelect = []; this.delegationForm.targetId = ''; },
|
closeDept() { this.deptShow = false; },
|
closeSingleUser() { this.singleUserShow = false; },
|
closeRole() { this.roleShow = false; },
|
closeMultUser() { this.multUserShow = false; },
|
// 挂起/容缺/跳过
|
hangup() {
|
this.$prompt('备注说明', '确定要挂起此任务吗').then(({ value }) => {
|
taskHangup({ taskId: this.taskId, projectId: this.projectId, processInsId: this.procInsId, reason: value }).then(() => { this.isSuccess = true; }); });
|
},
|
cancelHangup() {
|
this.$confirm('确定要取消挂起吗?').then(() => {
|
cancelTaskHangup({ taskId: this.taskId, projectId: this.projectId, processInsId: this.procInsId }).then(() => { this.isSuccess = true; }); });
|
},
|
waitTask() {
|
this.$prompt('备注说明', '确定要容缺此任务吗').then(({ value }) => {
|
taskWait({ taskId: this.taskId, projectId: this.projectId, processInsId: this.procInsId, desc: value }).then(() => { this.isSuccess = true; }); });
|
},
|
jumpTask() {
|
this.$prompt('备注说明', '确定要跳过此任务吗').then(({ value }) => {
|
taskJump({ taskId: this.taskId, projectId: this.projectId, processInsId: this.procInsId, desc: value }).then(() => { this.isSuccess = true; }); });
|
},
|
|
goBack() {
|
// WebView 模式下通常不需要复杂的 goBack 逻辑,或者可以通知父容器
|
console.log('Task completed');
|
},
|
// 处理接收人选择
|
handleUserSelect(selection) {
|
if (selection) {
|
if (selection instanceof Array) {
|
const selectVal = selection.map(item => item.userId);
|
this.checkValues = this.multiInstanceVars ? selectVal : selectVal.join(',');
|
} else {
|
this.checkValues = selection.userId;
|
}
|
}
|
},
|
handleRoleSelect(selection) {
|
if (selection) {
|
if (selection instanceof Array) {
|
this.checkValues = selection.map(item => item.roleId).join(',');
|
} else {
|
this.checkValues = selection;
|
}
|
}
|
},
|
submitTask() {
|
if (!this.checkValues && (this.checkSendUser || this.checkSendRole)) {
|
this.$message.error("请选择接收对象!");
|
return;
|
}
|
const param = { formJson: this.formJson };
|
Object.assign(param, this.formData);
|
this.$set(param, this.multiInstanceVars || "approval", this.checkValues);
|
completeSubmitFormTask(this.taskId, param).then(res => {
|
this.isSuccess = true;
|
});
|
}
|
}
|
};
|
</script>
|
|
<style lang="scss" scoped>
|
.header-container {
|
display: flex;
|
flex-wrap: wrap;
|
align-items: center;
|
gap: 10px;
|
|
.header-title {
|
flex: 1;
|
min-width: 150px;
|
font-weight: bold;
|
color: #409EFF;
|
}
|
|
.header-subtitle {
|
flex: 2;
|
min-width: 200px;
|
color: #303133;
|
font-size: 14px;
|
}
|
}
|
|
.tag-group {
|
display: flex;
|
flex-wrap: wrap;
|
align-items: center;
|
gap: 5px;
|
}
|
|
@media screen and (max-width: 768px) {
|
.header-container {
|
flex-direction: column;
|
align-items: flex-start;
|
.header-subtitle { min-width: 100%; margin-bottom: 5px; }
|
}
|
|
.mobile-op-list, .mobile-reject-but {
|
position: static !important;
|
display: flex;
|
flex-wrap: wrap;
|
gap: 5px;
|
margin-bottom: 10px;
|
padding: 10px;
|
background: #f8f9fa;
|
border-radius: 4px;
|
|
.el-button {
|
margin-left: 0 !important;
|
flex: 1;
|
min-width: 80px;
|
}
|
}
|
|
.form-warp {
|
padding: 10px !important;
|
}
|
}
|
|
.form-warp {
|
padding: 20px;
|
margin-top: 5px;
|
margin-bottom: 20px;
|
box-shadow: rgba(67, 71, 85, 0.27) 0px 0px 0.1em, rgba(90, 125, 188, 0.05) 0px 0.1em 0.5em;
|
}
|
|
.opBut {
|
display: flex; justify-content: center; align-items: center; width: 100%; margin-top: 15px;
|
}
|
|
.current, .before, .before_none {
|
margin-bottom: 15px;
|
color: #E6A23C;
|
span { font-weight: bold; }
|
}
|
.current span { color: #409EFF; }
|
.before span, .before_none span { color: #F56C6C; }
|
|
.tab-min-height {
|
min-height: 400px;
|
}
|
|
.op-list, .reject-but {
|
position: absolute;
|
top: 10px;
|
right: 10px;
|
z-index: 10;
|
}
|
</style>
|