flow.vue 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. <template>
  2. <el-dialog title="流程" :before-close="handleClose" :visible.sync="dialogVisible" :close-on-click-modal="false"
  3. :append-to-body="true" width="80%">
  4. <div class="app-container" style="padding: 15px">
  5. <!-- 审批记录 -->
  6. <el-card class="box-card" v-loading="tasksLoad">
  7. <div slot="header" class="clearfix">
  8. <span class="el-icon-picture-outline">审批记录</span>
  9. </div>
  10. <el-col :span="16" :offset="4">
  11. <div class="block">
  12. <el-timeline>
  13. <el-timeline-item v-for="(item, index) in tasks" :key="index" :icon="getTimelineItemIcon(item)"
  14. :type="getTimelineItemType(item)">
  15. <p style="font-weight: 700">任务:{{ item.name }}</p>
  16. <el-card :body-style="{ padding: '10px' }">
  17. <label v-if="item.assigneeUser" style="font-weight: normal; margin-right: 30px">
  18. 审批人:{{ item.assigneeUser.nickname }}
  19. <el-tag type="info" size="mini">{{
  20. item.assigneeUser.deptName
  21. }}</el-tag>
  22. </label>
  23. <label style="font-weight: normal" v-if="item.createTime">创建时间:</label>
  24. <label style="color: #8a909c; font-weight: normal">{{
  25. item.createTime
  26. }}</label>
  27. <label v-if="item.endTime" style="margin-left: 30px; font-weight: normal">审批时间:</label>
  28. <label v-if="item.endTime" style="color: #8a909c; font-weight: normal">
  29. {{ item.endTime }}</label>
  30. <label v-if="item.durationInMillis" style="margin-left: 30px; font-weight: normal">耗时:</label>
  31. <label v-if="item.durationInMillis" style="color: #8a909c; font-weight: normal">
  32. {{ getDateStar(item.durationInMillis) }}
  33. </label>
  34. <p v-if="item.reason">
  35. <el-tag :type="getTimelineItemType(item)">{{
  36. item.reason
  37. }}</el-tag>
  38. </p>
  39. </el-card>
  40. </el-timeline-item>
  41. </el-timeline>
  42. </div>
  43. </el-col>
  44. </el-card>
  45. <!-- 高亮流程图 -->
  46. <el-card class="box-card" v-loading="processInstanceLoading">
  47. <div slot="header" class="clearfix">
  48. <span class="el-icon-picture-outline">流程图1</span>
  49. </div>
  50. <my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" :activityData="activityList"
  51. :processInstanceData="processInstance" :taskData="tasks" />
  52. </el-card>
  53. </div>
  54. </el-dialog>
  55. </template>
  56. <script>
  57. import { getProcessDefinitionBpmnXML } from '@/api/bpm/index';
  58. import store from '@/store';
  59. import { getProcessInstance } from '@/api/bpm/index';
  60. import { getDate } from '@/utils/dateUtils';
  61. import dictMixins from '@/mixins/dictMixins';
  62. import { getTaskListByProcessInstanceId } from '@/api/bpm/index';
  63. import { getActivityList } from '@/api/bpm/index';
  64. // import Vue from 'vue';
  65. // 流程实例的详情页,可用于审批
  66. export default {
  67. name: 'outsourcing',
  68. mixins: [dictMixins],
  69. components: {},
  70. data() {
  71. return {
  72. // 遮罩层
  73. processInstanceLoading: true,
  74. dialogVisible: false,
  75. // 流程实例
  76. id: undefined, // 流程实例的编号
  77. processInstance: {},
  78. // BPMN 数据
  79. bpmnXML: null,
  80. bpmnControlForm: {
  81. prefix: 'flowable'
  82. },
  83. activityList: [],
  84. // 审批记录
  85. tasksLoad: true,
  86. tasks: []
  87. };
  88. },
  89. created() {
  90. // this.id = this.$route.query.id;
  91. // if (!this.id) {
  92. // this.$message.error('未传递 id 参数,无法查看流程信息');
  93. // return;
  94. // }
  95. // this.getDetail();
  96. },
  97. methods: {
  98. open(id) {
  99. this.id = id;
  100. this.dialogVisible = true;
  101. this.getDetail();
  102. },
  103. /** 获得流程实例 */
  104. getDetail() {
  105. // 获得流程实例相关
  106. this.processInstanceLoading = true;
  107. getProcessInstance(this.id).then((response) => {
  108. if (!response) {
  109. this.$message.error('查询不到流程信息!');
  110. return;
  111. }
  112. // 设置流程信息
  113. this.processInstance = response;
  114. // //将业务表单,注册为动态组件
  115. // const path = this.processInstance.processDefinition.formCustomViewPath;
  116. // Vue.component("async-biz-form-component", function (resolve) {
  117. // require([`@/views${path}`], resolve);
  118. // });
  119. // 加载流程图
  120. getProcessDefinitionBpmnXML(
  121. this.processInstance.processDefinition.id
  122. ).then((response) => {
  123. this.bpmnXML = response;
  124. });
  125. // 加载活动列表
  126. getActivityList({
  127. processInstanceId: this.processInstance.id
  128. }).then((response) => {
  129. console.log(response, 'response');
  130. this.activityList = response;
  131. });
  132. // 取消加载中
  133. this.processInstanceLoading = false;
  134. });
  135. // 获得流程任务列表(审批记录)
  136. this.tasksLoad = true;
  137. getTaskListByProcessInstanceId(this.id).then((response) => {
  138. // 审批记录
  139. this.tasks = [];
  140. // 移除已取消的审批
  141. response.forEach((task) => {
  142. if (task.result !== 4) {
  143. this.tasks.push(task);
  144. }
  145. });
  146. // 排序,将未完成的排在前面,已完成的排在后面;
  147. this.tasks.sort((a, b) => {
  148. // 有已完成的情况,按照完成时间倒序
  149. if (a.endTime && b.endTime) {
  150. return b.endTime - a.endTime;
  151. } else if (a.endTime) {
  152. return 1;
  153. } else if (b.endTime) {
  154. return -1;
  155. // 都是未完成,按照创建时间倒序
  156. } else {
  157. return b.createTime - a.createTime;
  158. }
  159. });
  160. // 需要审核的记录
  161. const userId = store.getters.userId;
  162. this.tasks.forEach((task) => {
  163. if (task.result !== 1 && task.result !== 6) {
  164. // 只有待处理才需要
  165. return;
  166. }
  167. if (!task.assigneeUser || task.assigneeUser.id !== userId) {
  168. // 自己不是处理人
  169. return;
  170. }
  171. });
  172. // 取消加载中
  173. this.tasksLoad = false;
  174. });
  175. },
  176. getDateStar(ms) {
  177. return getDate(ms);
  178. },
  179. getTimelineItemIcon(item) {
  180. if (item.result === 1) {
  181. return 'el-icon-time';
  182. }
  183. if (item.result === 2) {
  184. return 'el-icon-check';
  185. }
  186. if (item.result === 3) {
  187. return 'el-icon-close';
  188. }
  189. if (item.result === 4) {
  190. return 'el-icon-remove-outline';
  191. }
  192. if (item.result === 5) {
  193. return 'el-icon-back';
  194. }
  195. return '';
  196. },
  197. getTimelineItemType(item) {
  198. if (item.result === 1) {
  199. return 'primary';
  200. }
  201. if (item.result === 2) {
  202. return 'success';
  203. }
  204. if (item.result === 3) {
  205. return 'danger';
  206. }
  207. if (item.result === 4) {
  208. return 'info';
  209. }
  210. if (item.result === 5) {
  211. return 'warning';
  212. }
  213. if (item.result === 6) {
  214. return 'default';
  215. }
  216. return '';
  217. },
  218. handleClose() {
  219. this.dialogVisible = false;
  220. }
  221. }
  222. };
  223. </script>
  224. <style lang="scss">
  225. .my-process-designer {
  226. height: calc(100vh - 200px);
  227. }
  228. .box-card {
  229. width: 100%;
  230. margin-bottom: 20px;
  231. }
  232. </style>