Commit 9a876cff3d247a137b0bd0c9d1a896150a2b4c52

Authored by liuxiaolu
1 parent 6388950a

feat:【工作流】添加vue2版本的退回和委派前端代码

yudao-ui-admin/src/api/bpm/task.js
... ... @@ -61,3 +61,25 @@ export function getTaskListByProcessInstanceId(processInstanceId) {
61 61 method: 'get',
62 62 })
63 63 }
  64 +export function getReturnList(taskId) {
  65 + return request({
  66 + url: '/bpm/task/get-return-list?taskId='+ taskId,
  67 + method: 'get',
  68 + })
  69 +}
  70 +
  71 +
  72 +export function returnTask(data) {
  73 + return request({
  74 + url: '/bpm/task/return',
  75 + method: 'PUT',
  76 + data: data
  77 + })
  78 +}
  79 +export function delegateTask(data) {
  80 + return request({
  81 + url: '/bpm/task/delegate',
  82 + method: 'PUT',
  83 + data: data
  84 + })
  85 +}
... ...
yudao-ui-admin/src/components/bpmnProcessDesigner/package/designer/ProcessViewer.vue
... ... @@ -233,6 +233,10 @@ export default {
233 233 return 'highlight-reject';
234 234 } else if (result === 4) { // 已取消
235 235 return 'highlight-cancel';
  236 + } else if (result === 5) { // 已退回
  237 + return 'highlight-back';
  238 + } else if (result === 6) { // 已委派
  239 + return 'highlight-todo';
236 240 }
237 241 return '';
238 242 },
... ... @@ -475,7 +479,33 @@ export default {
475 479 :deep(.highlight-cancel.djs-connection > .djs-visual > path) {
476 480 stroke: grey !important;
477 481 }
  482 +/**驳回 */
  483 +.highlight-back.djs-connection > .djs-visual > path {
  484 + stroke: #FFBA00 !important;
  485 + stroke-dasharray: 4px !important;
  486 + fill-opacity: 0.2 !important;
  487 +}
  488 +
  489 +.highlight-back.djs-shape .djs-visual > :nth-child(1) {
  490 + fill: #FFBA00 !important;
  491 + stroke: #FFBA00 !important;
  492 + stroke-dasharray: 4px !important;
  493 + fill-opacity: 0.2 !important;
  494 +}
478 495  
  496 +:deep(.highlight-back.djs-connection > .djs-visual > path) {
  497 + stroke: #FFBA00 !important;
  498 + stroke-dasharray: 4px !important;
  499 + fill-opacity: 0.2 !important;
  500 + marker-end: url(#sequenceflow-end-_E7DFDF-_E7DFDF-803g1kf6zwzmcig1y2ulm5egr);
  501 +}
  502 +
  503 +:deep(.highlight-back.djs-shape .djs-visual > :nth-child(1)) {
  504 + fill: #FFBA00 !important;
  505 + stroke: #FFBA00 !important;
  506 + stroke-dasharray: 4px !important;
  507 + fill-opacity: 0.2 !important;
  508 +}
479 509 .element-overlays {
480 510 box-sizing: border-box;
481 511 padding: 8px;
... ...
yudao-ui-admin/src/views/bpm/processInstance/detail.vue
... ... @@ -5,7 +5,7 @@
5 5 <div slot="header" class="clearfix">
6 6 <span class="el-icon-picture-outline">审批任务【{{ item.name }}】</span>
7 7 </div>
8   - <el-col :span="16" :offset="6" >
  8 + <el-col :span="16" :offset="6">
9 9 <el-form :ref="'form' + index" :model="auditForms[index]" :rules="auditRule" label-width="100px">
10 10 <el-form-item label="流程名" v-if="processInstance && processInstance.name">
11 11 {{ processInstance.name }}
... ... @@ -15,15 +15,20 @@
15 15 <el-tag type="info" size="mini">{{ processInstance.startUser.deptName }}</el-tag>
16 16 </el-form-item>
17 17 <el-form-item label="审批建议" prop="reason">
18   - <el-input type="textarea" v-model="auditForms[index].reason" placeholder="请输入审批建议" />
  18 + <el-input type="textarea" v-model="auditForms[index].reason" placeholder="请输入审批建议"/>
19 19 </el-form-item>
20 20 </el-form>
21 21 <div style="margin-left: 10%; margin-bottom: 20px; font-size: 14px;">
22   - <el-button icon="el-icon-edit-outline" type="success" size="mini" @click="handleAudit(item, true)">通过</el-button>
23   - <el-button icon="el-icon-circle-close" type="danger" size="mini" @click="handleAudit(item, false)">不通过</el-button>
24   - <el-button icon="el-icon-edit-outline" type="primary" size="mini" @click="handleUpdateAssignee(item)">转办</el-button>
25   - <el-button icon="el-icon-edit-outline" type="primary" size="mini" @click="handleDelegate(item)">委派</el-button>
26   - <el-button icon="el-icon-refresh-left" type="warning" size="mini" @click="handleBack(item)">退回</el-button>
  22 + <el-button icon="el-icon-edit-outline" type="success" size="mini" @click="handleAudit(item, true)">通过
  23 + </el-button>
  24 + <el-button icon="el-icon-circle-close" type="danger" size="mini" @click="handleAudit(item, false)">不通过
  25 + </el-button>
  26 + <el-button icon="el-icon-edit-outline" type="primary" size="mini" @click="handleUpdateAssignee(item)">转办
  27 + </el-button>
  28 + <el-button icon="el-icon-edit-outline" type="primary" size="mini" @click="handleDelegate(item)">委派
  29 + </el-button>
  30 + <el-button icon="el-icon-refresh-left" type="warning" size="mini" @click="handleBackList(item)">退回
  31 + </el-button>
27 32 </div>
28 33 </el-col>
29 34 </el-card>
... ... @@ -34,8 +39,8 @@
34 39 </div>
35 40 <el-col v-if="this.processInstance.processDefinition && this.processInstance.processDefinition.formType === 10"
36 41 :span="16" :offset="6">
37   - <div >
38   - <parser :key="new Date().getTime()" :form-conf="detailForm" />
  42 + <div>
  43 + <parser :key="new Date().getTime()" :form-conf="detailForm"/>
39 44 </div>
40 45 </el-col>
41 46 <div v-if="this.processInstance.processDefinition && this.processInstance.processDefinition.formType === 20">
... ... @@ -48,7 +53,7 @@
48 53 <div slot="header" class="clearfix">
49 54 <span class="el-icon-picture-outline">审批记录</span>
50 55 </div>
51   - <el-col :span="16" :offset="4" >
  56 + <el-col :span="16" :offset="4">
52 57 <div class="block">
53 58 <el-timeline>
54 59 <el-timeline-item v-for="(item, index) in tasks" :key="index"
... ... @@ -62,9 +67,12 @@
62 67 <label style="font-weight: normal" v-if="item.createTime">创建时间:</label>
63 68 <label style="color:#8a909c; font-weight: normal">{{ parseTime(item.createTime) }}</label>
64 69 <label v-if="item.endTime" style="margin-left: 30px;font-weight: normal">审批时间:</label>
65   - <label v-if="item.endTime" style="color:#8a909c;font-weight: normal"> {{ parseTime(item.endTime) }}</label>
  70 + <label v-if="item.endTime" style="color:#8a909c;font-weight: normal"> {{
  71 + parseTime(item.endTime)
  72 + }}</label>
66 73 <label v-if="item.durationInMillis" style="margin-left: 30px;font-weight: normal">耗时:</label>
67   - <label v-if="item.durationInMillis" style="color:#8a909c;font-weight: normal"> {{ getDateStar(item.durationInMillis) }} </label>
  74 + <label v-if="item.durationInMillis" style="color:#8a909c;font-weight: normal">
  75 + {{ getDateStar(item.durationInMillis) }} </label>
68 76 <p v-if="item.reason">
69 77 <el-tag :type="getTimelineItemType(item)">{{ item.reason }}</el-tag>
70 78 </p>
... ... @@ -81,15 +89,16 @@
81 89 <span class="el-icon-picture-outline">流程图</span>
82 90 </div>
83 91 <my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" :activityData="activityList"
84   - :processInstanceData="processInstance" :taskData="tasks" />
  92 + :processInstanceData="processInstance" :taskData="tasks"/>
85 93 </el-card>
86 94  
87   - <!-- 对话框(转派审批人) -->
88   - <el-dialog title="转派审批人" :visible.sync="updateAssignee.open" width="500px" append-to-body>
  95 + <!-- 对话框(转办审批人) -->
  96 + <el-dialog title="转办审批人" :visible.sync="updateAssignee.open" width="500px" append-to-body>
89 97 <el-form ref="updateAssigneeForm" :model="updateAssignee.form" :rules="updateAssignee.rules" label-width="110px">
90 98 <el-form-item label="新审批人" prop="assigneeUserId">
91 99 <el-select v-model="updateAssignee.form.assigneeUserId" clearable style="width: 100%">
92   - <el-option v-for="item in userOptions" :key="parseInt(item.id)" :label="item.nickname" :value="parseInt(item.id)" />
  100 + <el-option v-for="item in userOptions" :key="parseInt(item.id)" :label="item.nickname"
  101 + :value="parseInt(item.id)"/>
93 102 </el-select>
94 103 </el-form-item>
95 104 </el-form>
... ... @@ -98,17 +107,64 @@
98 107 <el-button @click="cancelUpdateAssigneeForm">取 消</el-button>
99 108 </div>
100 109 </el-dialog>
  110 + <!-- 对话框(委派审批人) -->
  111 + <el-dialog title="委派审批人" :visible.sync="updateDelegate.open" width="500px" append-to-body>
  112 + <el-form ref="updateDelegateForm" :model="updateDelegate.form" :rules="updateDelegate.rules" label-width="110px">
  113 + <el-form-item label="新审批人" prop="assigneeUserId">
  114 + <el-select v-model="updateDelegate.form.delegateUserId" clearable style="width: 100%">
  115 + <el-option v-for="item in userOptions" :key="parseInt(item.id)" :label="item.nickname"
  116 + :value="parseInt(item.id)"/>
  117 + </el-select>
  118 + </el-form-item>
  119 + <el-form-item label="委派理由" prop="reason">
  120 + <el-input v-model="updateDelegate.form.reason" clearable placeholder="请输入委派理由"/>
  121 + </el-form-item>
  122 + </el-form>
  123 + <div slot="footer" class="dialog-footer">
  124 + <el-button type="primary" @click="submitUpdateDelegateForm">确 定</el-button>
  125 + <el-button @click="cancelUpdateDelegateForm">取 消</el-button>
  126 + </div>
  127 + </el-dialog>
  128 + <!--退回流程-->
  129 + <el-dialog title="退回流程" :visible.sync="returnOpen" width="40%" append-to-body>
  130 + <el-form ref="formRef" v-loading="formLoading" :model="formData" :rules="formRules" label-width="110px">
  131 + <el-form-item label="退回节点" prop="targetDefinitionKey">
  132 + <el-select v-model="formData.targetDefinitionKey" clearable style="width: 100%">
  133 + <el-option
  134 + v-for="item in returnList"
  135 + :key="item.definitionKey"
  136 + :label="item.name"
  137 + :value="item.definitionKey"
  138 + />
  139 + </el-select>
  140 + </el-form-item>
  141 + <el-form-item label="回退理由" prop="reason">
  142 + <el-input v-model="formData.reason" clearable placeholder="请输入回退理由"/>
  143 + </el-form-item>
  144 + </el-form>
  145 + <span slot="footer" class="dialog-footer">
  146 + <el-button @click="returnOpen = false">取 消</el-button>
  147 + <el-button :disabled="formLoading" type="primary" @click="submitReturn">确 定</el-button>
  148 + </span>
  149 + </el-dialog>
101 150 </div>
102 151 </template>
103 152  
104 153 <script>
105 154 import {getProcessDefinitionBpmnXML} from "@/api/bpm/definition";
106   -import {DICT_TYPE, getDictDatas} from "@/utils/dict";
107 155 import store from "@/store";
108 156 import {decodeFields} from "@/utils/formGenerator";
109 157 import Parser from '@/components/parser/Parser'
110 158 import {getProcessInstance} from "@/api/bpm/processInstance";
111   -import {approveTask, getTaskListByProcessInstanceId, rejectTask, updateTaskAssignee} from "@/api/bpm/task";
  159 +import {
  160 + approveTask,
  161 + delegateTask,
  162 + getReturnList,
  163 + getTaskListByProcessInstanceId,
  164 + rejectTask,
  165 + returnTask,
  166 + updateTaskAssignee,
  167 +} from "@/api/bpm/task";
112 168 import {getDate} from "@/utils/dateUtils";
113 169 import {listSimpleUsers} from "@/api/system/user";
114 170 import {getActivityList} from "@/api/bpm/activity";
... ... @@ -127,12 +183,23 @@ export default {
127 183 // 流程实例
128 184 id: undefined, // 流程实例的编号
129 185 processInstance: {},
130   -
  186 + formLoading: false,
131 187 // 流程表单详情
132 188 detailForm: {
133 189 fields: []
134 190 },
135   -
  191 + //回退列表数据
  192 + returnList: [],
  193 + formData: {
  194 + id: '',
  195 + targetDefinitionKey: undefined,
  196 + reason: ''
  197 + },
  198 + formRules: {
  199 + targetDefinitionKey: [{required: true, message: '必须选择回退节点', trigger: 'change'}],
  200 + reason: [{required: true, message: '回退理由不能为空', trigger: 'blur'}]
  201 + },
  202 + returnOpen: false,
136 203 // BPMN 数据
137 204 bpmnXML: null,
138 205 bpmnControlForm: {
... ... @@ -148,9 +215,8 @@ export default {
148 215 runningTasks: [],
149 216 auditForms: [],
150 217 auditRule: {
151   - reason: [{ required: true, message: "审批建议不能为空", trigger: "blur" }],
  218 + reason: [{required: true, message: "审批建议不能为空", trigger: "blur"}],
152 219 },
153   -
154 220 // 转派审批人
155 221 userOptions: [],
156 222 updateAssignee: {
... ... @@ -159,7 +225,18 @@ export default {
159 225 assigneeUserId: undefined,
160 226 },
161 227 rules: {
162   - assigneeUserId: [{ required: true, message: "新审批人不能为空", trigger: "change" }],
  228 + assigneeUserId: [{required: true, message: "新审批人不能为空", trigger: "change"}],
  229 + }
  230 + },
  231 + updateDelegate: {
  232 + open: false,
  233 + form: {
  234 + delegateUserId: undefined,
  235 + reason: ''
  236 + },
  237 + rules: {
  238 + delegateUserId: [{required: true, message: "新审批人不能为空", trigger: "change"}],
  239 + reason: [{required: true, message: '委派理由不能为空', trigger: 'blur'}]
163 240 }
164 241 }
165 242 };
... ... @@ -193,7 +270,7 @@ export default {
193 270  
194 271 //将业务表单,注册为动态组件
195 272 const path = this.processInstance.processDefinition.formCustomViewPath;
196   - Vue.component("async-biz-form-component", function(resolve) {
  273 + Vue.component("async-biz-form-component", function (resolve) {
197 274 require([`@/views${path}`], resolve);
198 275 });
199 276  
... ... @@ -260,7 +337,7 @@ export default {
260 337 // 需要审核的记录
261 338 const userId = store.getters.userId;
262 339 this.tasks.forEach(task => {
263   - if (task.result !== 1) { // 只有待处理才需要
  340 + if (task.result !== 1 && task.result !== 6) { // 只有待处理才需要
264 341 return;
265 342 }
266 343 if (!task.assigneeUser || task.assigneeUser.id !== userId) { // 自己不是处理人
... ... @@ -292,6 +369,9 @@ export default {
292 369 if (item.result === 4) {
293 370 return 'el-icon-remove-outline';
294 371 }
  372 + if (item.result === 5) {
  373 + return 'el-icon-back'
  374 + }
295 375 return '';
296 376 },
297 377 getTimelineItemType(item) {
... ... @@ -307,6 +387,12 @@ export default {
307 387 if (item.result === 4) {
308 388 return 'info';
309 389 }
  390 + if (item.result === 5) {
  391 + return 'warning';
  392 + }
  393 + if (item.result === 6) {
  394 + return 'default'
  395 + }
310 396 return '';
311 397 },
312 398 /** 处理审批通过和不通过的操作 */
... ... @@ -333,7 +419,7 @@ export default {
333 419 }
334 420 });
335 421 },
336   - /** 处理转派审批人 */
  422 + /** 处理转办审批人 */
337 423 handleUpdateAssignee(task) {
338 424 // 设置表单
339 425 this.resetUpdateAssigneeForm();
... ... @@ -341,25 +427,25 @@ export default {
341 427 // 设置为打开
342 428 this.updateAssignee.open = true;
343 429 },
344   - /** 提交转派审批人 */
  430 + /** 提交转办审批人 */
345 431 submitUpdateAssigneeForm() {
346 432 this.$refs['updateAssigneeForm'].validate(valid => {
347 433 if (!valid) {
348 434 return;
349 435 }
350 436 updateTaskAssignee(this.updateAssignee.form).then(response => {
351   - this.$modal.msgSuccess("转派任务成功!");
  437 + this.$modal.msgSuccess("转办任务成功!");
352 438 this.updateAssignee.open = false;
353 439 this.getDetail(); // 获得最新详情
354 440 });
355 441 });
356 442 },
357   - /** 取消转派审批人 */
  443 + /** 取消转办审批人 */
358 444 cancelUpdateAssigneeForm() {
359 445 this.updateAssignee.open = false;
360 446 this.resetUpdateAssigneeForm();
361 447 },
362   - /** 重置转派审批人 */
  448 + /** 重置转办审批人 */
363 449 resetUpdateAssigneeForm() {
364 450 this.updateAssignee.form = {
365 451 id: undefined,
... ... @@ -367,22 +453,72 @@ export default {
367 453 };
368 454 this.resetForm("updateAssigneeForm");
369 455 },
370   - /** 处理审批退回的操作 */
  456 + /** 处理审批委派的操作 */
371 457 handleDelegate(task) {
372   - this.$modal.msgError("暂不支持【委派】功能,可以使用【转派】替代!");
  458 + //this.$modal.msgError("暂不支持【委派】功能,可以使用【转派】替代!");
  459 + this.resetUpdateDelegateForm();
  460 + this.updateDelegate.form.id = task.id;
  461 + // 设置为打开
  462 + this.updateDelegate.open = true;
  463 + },
  464 + /** 提交委派审批人 */
  465 + submitUpdateDelegateForm() {
  466 + this.$refs['updateDelegateForm'].validate(valid => {
  467 + if (!valid) {
  468 + return;
  469 + }
  470 + delegateTask(this.updateDelegate.form).then(response => {
  471 + this.$modal.msgSuccess("委派任务成功!");
  472 + this.updateDelegate.open = false;
  473 + this.getDetail(); // 获得最新详情
  474 + });
  475 + });
  476 + },
  477 + /** 取消委派审批人 */
  478 + cancelUpdateDelegateForm() {
  479 + this.updateDelegate.open = false;
  480 + this.resetUpdateDelegateForm();
  481 + },
  482 + /** 重置委派审批人 */
  483 + resetUpdateDelegateForm() {
  484 + this.updateDelegate.form = {
  485 + id: undefined,
  486 + delegateUserId: undefined,
  487 + };
  488 + this.resetForm("updateDelegateForm");
373 489 },
374 490 /** 处理审批退回的操作 */
375   - handleBack(task) {
376   - this.$modal.msgError("暂不支持【退回】功能!");
  491 + /** 返回退回节点列表 */
  492 + handleBackList(task) {
377 493 // 可参考 http://blog.wya1.com/article/636697030/details/7296
378   - // const data = {
379   - // id: task.id,
380   - // assigneeUserId: 1
381   - // }
382   - // backTask(data).then(response => {
383   - // this.$modal.msgSuccess("回退成功!");
384   - // this.getDetail(); // 获得最新详情
385   - // });
  494 + getReturnList(task.id).then(response => {
  495 + this.returnList = response.data;
  496 + if (this.returnList.length == 0) {
  497 + this.$modal.msgError("当前没有可回退的节点!");
  498 + return;
  499 + }
  500 + this.formData.id = task.id;
  501 + this.returnOpen = true;
  502 + });
  503 +
  504 + },
  505 + /** 提交退回任务 */
  506 + submitReturn() {
  507 + if (!this.formData.targetDefinitionKey) {
  508 + this.$modal.msgError("请选择退回节点!");
  509 + }
  510 + this.$refs['formRef'].validate(valid => {
  511 + if (!valid) {
  512 + return;
  513 + }
  514 + returnTask(this.formData).then(res => {
  515 + if (res.data) {
  516 + this.$modal.msgSuccess("回退成功!");
  517 + this.returnOpen = false;
  518 + this.getDetail();
  519 + }
  520 + });
  521 + });
386 522 }
387 523 }
388 524 };
... ...