processSubmitDialog.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. <template>
  2. <ele-modal
  3. custom-class="ele-dialog-form long-dialog-form"
  4. :centered="true"
  5. :visible="processSubmitDialogFlag"
  6. title="提交审核"
  7. append-to-body
  8. :close-on-click-modal="false"
  9. width="60%"
  10. :before-close="cancel"
  11. >
  12. <el-steps :active="active" align-center style="transform: scale(0.8)">
  13. <el-step title="流程发起"></el-step>
  14. <el-step title="流程通知"></el-step>
  15. </el-steps>
  16. <el-form
  17. ref="form"
  18. :rules="rules"
  19. class="el-form-box"
  20. :model="form"
  21. label-width="80px"
  22. >
  23. <el-row v-show="active == 0">
  24. <el-col :span="12">
  25. <el-form-item label="流程分类">
  26. <ele-tree-select
  27. @change="changeLCFL"
  28. clearable
  29. ref="processTypeRef"
  30. filterable
  31. :data="LCFLList"
  32. v-model="form.LCFL"
  33. childrenKey="children"
  34. valueKey="id"
  35. labelKey="name"
  36. placeholder="请选择"
  37. default-expand-all
  38. />
  39. </el-form-item>
  40. </el-col>
  41. <el-col :span="12">
  42. <el-form-item label="发起流程">
  43. <el-select
  44. filterable
  45. v-model="form.FQLC"
  46. @change="changeFQLC"
  47. style="width: 100%"
  48. >
  49. <el-option
  50. v-for="item in processList"
  51. :key="item.id"
  52. :value="item.id"
  53. :label="item.name"
  54. ></el-option>
  55. </el-select>
  56. </el-form-item>
  57. </el-col>
  58. </el-row>
  59. <el-row v-show="active == 0">
  60. <el-col :span="12">
  61. <el-form-item label="流程名称">
  62. <el-input v-model="form.name" clearable></el-input>
  63. </el-form-item>
  64. </el-col>
  65. <el-col :span="12">
  66. <el-form-item label="流程标识">
  67. <el-input v-model="form.key" disabled></el-input>
  68. </el-form-item>
  69. </el-col>
  70. </el-row>
  71. <headerTitle
  72. v-show="active == 0"
  73. title="流程执行人/流程图"
  74. style="margin-top: 30px"
  75. ></headerTitle>
  76. <el-table
  77. v-show="active == 0"
  78. :data="datasource"
  79. border
  80. style="margin-bottom: 10px"
  81. >
  82. <el-table-column
  83. label="任务节点"
  84. align="center"
  85. prop="taskDefinitionName"
  86. width="140"
  87. fixed
  88. />
  89. <el-table-column
  90. label="执行人"
  91. align="center"
  92. prop="options"
  93. min-width="140px"
  94. >
  95. <template v-slot="scope">
  96. <div v-if="scope.row.type !== 60 && scope.row.options.length > 0">
  97. <el-tag
  98. size="medium"
  99. :key="option"
  100. v-for="option in scope.row.options"
  101. >
  102. {{ getAssignRuleOptionName(scope.row, option) }}
  103. </el-tag>
  104. </div>
  105. <el-tag size="medium" v-if="scope.row.type === 60">
  106. {{ getAssignRuleOptionName(scope.row) }}
  107. </el-tag>
  108. </template>
  109. </el-table-column>
  110. </el-table>
  111. <my-process-viewer
  112. v-show="active == 0"
  113. style="min-width: 100%; height: 300px"
  114. key="designer"
  115. v-model="bpmnXML"
  116. />
  117. <el-table v-show="active == 1" :data="form.noticeScope" border>
  118. <el-table-column
  119. label="类型"
  120. align="center"
  121. prop="taskDefinitionName"
  122. width="140"
  123. fixed
  124. />
  125. <el-table-column
  126. label="结果"
  127. align="center"
  128. prop="options"
  129. min-width="140px"
  130. >
  131. </el-table-column>
  132. </el-table>
  133. </el-form>
  134. <div slot="footer">
  135. <el-button
  136. type="primary"
  137. size="small"
  138. v-if="active == 0"
  139. @click="() => (active = 1)"
  140. >下一步
  141. </el-button
  142. >
  143. <el-button
  144. type="primary"
  145. size="small"
  146. v-if="active == 1"
  147. @click="() => (active = 0)"
  148. >上一步
  149. </el-button
  150. >
  151. <el-button type="primary" size="small" @click="submit">完成</el-button>
  152. <el-button size="small" @click="cancel">关闭</el-button>
  153. </div>
  154. </ele-modal>
  155. </template>
  156. <script>
  157. import {
  158. getModelPage,
  159. getProcessDefinitionBpmnXML,
  160. getProcessDefinitionInfo,
  161. getTaskAssignRuleList,
  162. processInstanceCreateAPI,
  163. listAllUserBind,
  164. listSimpleUserGroups
  165. } from './api';
  166. import {treeClassifyCodeEnum} from '@/enum/dict';
  167. import {listRoles} from '@/api/system/role';
  168. import {listOrganizations} from '@/api/system/organization';
  169. import dictMixins from '@/mixins/dictMixins';
  170. import {getByCode} from '@/api/system/dictionary-data';
  171. import {getProduceTreeByCode} from "@/api/main";
  172. export default {
  173. name: 'processSubmitDialog',
  174. mixins: [dictMixins],
  175. props: {
  176. processSubmitDialogFlag: {
  177. type: Boolean,
  178. default: false
  179. },
  180. },
  181. data() {
  182. return {
  183. form: {
  184. LCFL: '',
  185. FQLC: '',
  186. processDefinitionId: '',
  187. name: '',
  188. businessId: '',
  189. noticeScope: [],
  190. businessKey: ''
  191. },
  192. active: 0,
  193. bpmnXML: null,
  194. LCFLList: [],
  195. processList: [],
  196. datasource: [],
  197. roleOptions: [],
  198. deptOptions: [],
  199. deptTreeOptions: [],
  200. postOptions: [],
  201. userOptions: [],
  202. userGroupOptions: [],
  203. dictList: {},
  204. rules: {}
  205. };
  206. },
  207. async created() {
  208. let typeObj = await getProduceTreeByCode(
  209. treeClassifyCodeEnum['PROCESSTYPE']
  210. );
  211. this.LCFLList = typeObj[0].children;
  212. // 获得角色列表
  213. this.roleOptions = [];
  214. listRoles({
  215. current: 1,
  216. size: 9999
  217. }).then((data) => {
  218. this.roleOptions.push(...data.list);
  219. });
  220. // 获得部门列表
  221. this.deptOptions = [];
  222. this.deptTreeOptions = [];
  223. listOrganizations().then((data) => {
  224. this.deptOptions.push(...data);
  225. this.deptTreeOptions.push(...this.handleTree(data, 'id'));
  226. });
  227. // 获得岗位列表 暂无岗位概念
  228. this.postOptions = [];
  229. /*listSimplePosts().then(response => {
  230. this.postOptions.push(...response.data);
  231. });*/
  232. // 获得用户列表
  233. this.userOptions = [];
  234. listAllUserBind().then((data) => {
  235. this.userOptions.push(...data);
  236. });
  237. // 获得用户组列表
  238. this.userGroupOptions = [];
  239. listSimpleUserGroups().then((response) => {
  240. this.userGroupOptions.push(...response);
  241. });
  242. //this.dictEnum['工作流任务分配自定义脚本']
  243. await this.getDictList(this.dictEnum['工作流任务分配自定义脚本']);
  244. await this.getDictList(this.dictEnum['工种类型']);
  245. },
  246. methods: {
  247. init(row = {}) {
  248. this.form = Object.assign( this.form, row);
  249. this.getDefaultInfo(row.businessKey)
  250. },
  251. async getDefaultInfo(businessKey) {
  252. let info = await getProcessDefinitionInfo({code: businessKey})
  253. this.form.LCFL = info?.category
  254. this.form.FQLC = info?.modelId
  255. this.form.name = info?.name
  256. this.form.key = info?.key
  257. this.form.processDefinitionId = info?.id
  258. if (this.form.LCFL) await this.getProcessList(this.form.LCFL)
  259. if (this.form.FQLC) {
  260. await this.getProcessDefinitionBpmnXMLInfo(info.id)
  261. await this.getTaskAssignRuleListInfo({modelId: info.modelId, processDefinitionId: info.id})
  262. }
  263. },
  264. async changeLCFL(val) {
  265. this.bpmnXML = null;
  266. this.form.processDefinitionId = null;
  267. this.form.FQLC = null;
  268. await this.getProcessList(val)
  269. },
  270. async getProcessList(val) {
  271. let params = {
  272. pageNo: 1,
  273. pageSize: 999,
  274. processTypeId: val
  275. }
  276. const {list} = await getModelPage(params);
  277. this.processList = list.filter(
  278. (item) => item.processDefinition
  279. );
  280. },
  281. async changeFQLC(val) {
  282. if (!val) return;
  283. let find = this.processList.find((item) => item.id === val) || {};
  284. this.form.name = find.name;
  285. this.form.key = find.key;
  286. this.form.processDefinitionId = find.processDefinition.id
  287. await this.getProcessDefinitionBpmnXMLInfo(find.processDefinition.id)
  288. await this.getTaskAssignRuleListInfo({modelId: find.id, processDefinitionId: find.processDefinition.id})
  289. },
  290. async getProcessDefinitionBpmnXMLInfo(val) {
  291. // 加载流程图
  292. this.bpmnXML = await getProcessDefinitionBpmnXML(val);
  293. },
  294. async getTaskAssignRuleListInfo(find) {
  295. this.datasource = await getTaskAssignRuleList({
  296. modelId: find.modelId,
  297. processDefinitionId: find.processDefinitionId
  298. });
  299. },
  300. getAssignRuleOptionName(row, option) {
  301. if (row.type == 10) {
  302. for (const roleOption of this.roleOptions) {
  303. if (roleOption.id === option) {
  304. return roleOption.name;
  305. }
  306. }
  307. } else if (row.type === 20 || row.type === 21) {
  308. for (const deptOption of this.deptOptions) {
  309. if (deptOption.id === option) {
  310. return deptOption.name;
  311. }
  312. }
  313. } else if (row.type === 22) {
  314. option = option + ''; // 转换成 string
  315. return this.getDictV(this.dictEnum['工种类型'], option);
  316. } else if (row.type === 30 || row.type === 31 || row.type === 32) {
  317. for (const userOption of this.userOptions) {
  318. if (userOption.id === option) {
  319. return userOption.nickname || userOption.name;
  320. }
  321. }
  322. } else if (row.type === 40) {
  323. for (const userGroupOption of this.userGroupOptions) {
  324. if (userGroupOption.id === option) {
  325. return userGroupOption.name;
  326. }
  327. }
  328. } else if (row.type === 50) {
  329. option = option + ''; // 转换成 string
  330. return this.getDictV(
  331. this.dictEnum['工作流任务分配自定义脚本'],
  332. option
  333. );
  334. } else if (row.type === 60) {
  335. return row.variableName;
  336. }
  337. return '未知(' + option + ')';
  338. },
  339. /**
  340. * 构造树型结构数据
  341. * @param {*} data 数据源
  342. * @param {*} id id字段 默认 'id'
  343. * @param {*} parentId 父节点字段 默认 'parentId'
  344. * @param {*} children 孩子节点字段 默认 'children'
  345. * @param {*} rootId 根Id 默认 0
  346. */
  347. handleTree(data, id, parentId, children, rootId) {
  348. id = id || 'id';
  349. parentId = parentId || 'parentId';
  350. children = children || 'children';
  351. rootId =
  352. rootId ||
  353. Math.min.apply(
  354. Math,
  355. data.map((item) => {
  356. return item[parentId];
  357. })
  358. ) ||
  359. 0;
  360. //对源数据深度克隆
  361. const cloneData = JSON.parse(JSON.stringify(data));
  362. //循环所有项
  363. const treeData = cloneData.filter((father) => {
  364. let branchArr = cloneData.filter((child) => {
  365. //返回每一项的子级数组
  366. return father[id] == child[parentId];
  367. });
  368. branchArr.length > 0 ? (father.children = branchArr) : '';
  369. //返回第一层
  370. return father[parentId] == rootId;
  371. });
  372. return treeData !== '' ? treeData : data;
  373. },
  374. getDictV(code, val) {
  375. if (!this.dictList[code]) return '';
  376. return this.dictList[code].find((item) => item.value == val)?.label;
  377. },
  378. async getDictList(code) {
  379. let {data: res} = await getByCode(code);
  380. this.dictList[code] = res.map((item) => {
  381. let values = Object.keys(item);
  382. return {
  383. value: values[0],
  384. label: item[values[0]]
  385. };
  386. });
  387. },
  388. async submit() {
  389. await processInstanceCreateAPI(this.form);
  390. this.$message('提交审核成功')
  391. this.$emit('reload')
  392. this.cancel()
  393. },
  394. cancel() {
  395. this.$emit('update:processSubmitDialogFlag', false);
  396. }
  397. }
  398. };
  399. </script>
  400. <style scoped lang="scss"></style>