processSubmitDialog.vue 15 KB

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