processSubmitDialog.vue 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147
  1. <template>
  2. <ele-modal
  3. custom-class="ele-dialog-form long-dialog-form"
  4. :centered="true"
  5. :visible="processSubmitDialogFlag"
  6. :title="title"
  7. append-to-body
  8. :close-on-click-modal="false"
  9. :width="modelWidth"
  10. :before-close="cancel"
  11. :maxable="true"
  12. :resizable="true"
  13. >
  14. <div style="display: flex; height: 100%; justify-content: space-between">
  15. <div class="form-box">
  16. <el-form
  17. ref="form1"
  18. :rules="rules"
  19. class="el-form-box"
  20. :model="form"
  21. label-width="90px"
  22. :label-position="'left'"
  23. style="padding: 10px"
  24. >
  25. <el-row>
  26. <el-col :span="24">
  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="24">
  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> </el-row
  60. ></el-form>
  61. <fm-generate-form
  62. :preview="true"
  63. class="el-form-box"
  64. v-if="Object.keys(form?.formJson || {}).length !== 0"
  65. :data="jsonData"
  66. :value="form.valueJson"
  67. ref="generateForm"
  68. >
  69. <template v-slot:blank_adopzrdd="scope">
  70. <el-button
  71. type="primary"
  72. size="small"
  73. @click="addNewRow('blank_adopzrdd')"
  74. style="margin-bottom: 10px"
  75. >添加报销事项</el-button
  76. >
  77. <div
  78. v-for="(item, index) in scope.model.blank_adopzrdd"
  79. :key="index"
  80. >
  81. <div class="blank_adopzrdd">
  82. <span>{{ index + 1 }}报销事项:</span>
  83. <el-input
  84. v-model="scope.model.blank_adopzrdd[index].remark"
  85. type="textarea"
  86. style="width: calc(100% - 80px)"
  87. ></el-input>
  88. </div>
  89. <div class="blank_adopzrdd">
  90. <span @click="delNewRow('blank_adopzrdd', index)"
  91. ><i
  92. class="el-icon-delete"
  93. style="color: #f56c6c; cursor: pointer"
  94. ></i
  95. >金额:</span
  96. >
  97. <el-input
  98. v-model="scope.model.blank_adopzrdd[index].price"
  99. type="number"
  100. style="width: calc(100% - 80px)"
  101. @change="changePrice(scope.model.blank_adopzrdd)"
  102. ></el-input>
  103. </div>
  104. <div class="blank_adopzrdd">
  105. <span>附件:</span>
  106. <fileMain v-model="scope.model.blank_adopzrdd[index].file" ></fileMain>
  107. </div>
  108. </div>
  109. </template>
  110. <!-- 客户名称 -->
  111. <template v-slot:eom_contact="scope">
  112. <div class="eom_contact">
  113. <el-input
  114. v-model="scope.model.eom_contact.name"
  115. style="width: 100%"
  116. @click.native="addContact('eom_contact')"
  117. ></el-input>
  118. </div>
  119. </template>
  120. <!-- 关联工单 -->
  121. <template v-slot:manage_workorder="scope">
  122. <div class="manage_workorder">
  123. <el-input
  124. v-model="scope.model.manage_workorder.code"
  125. style="width: 100%"
  126. @click.native="addWorkOrder('manage_workorder')"
  127. placeholder="点击选择关联工单"
  128. ></el-input>
  129. </div>
  130. </template>
  131. <!-- 差旅交通 -->
  132. <template v-slot:blank_business_component="scope">
  133. <businessComponent
  134. ref="blank_business_component"
  135. id="blank_business_component"
  136. :generateForm="$refs.generateForm"
  137. :info="scope.model"
  138. ></businessComponent>
  139. </template>
  140. <!-- 印章使用 -->
  141. <template v-slot:blank_use_seal="scope">
  142. <useSealComponent
  143. ref="blank_use_seal"
  144. id="blank_use_seal"
  145. :generateForm="$refs.generateForm"
  146. :info="scope.model"
  147. ></useSealComponent>
  148. </template>
  149. <!-- 资质使用 -->
  150. <template v-slot:blank_use_qualification="scope">
  151. <useQualificationComponent
  152. ref="blank_use_qualification"
  153. id="blank_use_qualification"
  154. :generateForm="$refs.generateForm"
  155. :info="scope.model"
  156. ></useQualificationComponent>
  157. </template>
  158. <!-- 产品规格 -->
  159. <template v-slot:blank_product_specification="scope">
  160. <productSpecificationComponent
  161. ref="blank_product_specification"
  162. id="blank_product_specification"
  163. :generateForm="$refs.generateForm"
  164. :info="scope.model"
  165. ></productSpecificationComponent>
  166. </template>
  167. <!-- 事件 -->
  168. <template v-slot:blank_event_component="scope">
  169. <eventComponent
  170. ref="blank_event_component"
  171. id="blank_event_component"
  172. :generateForm="$refs.generateForm"
  173. :info="scope.model"
  174. ></eventComponent>
  175. </template>
  176. <!-- 补发 -->
  177. <template v-slot:blank_reissue_component="scope">
  178. <reissueComponent
  179. ref="blank_reissue_component"
  180. id="blank_reissue_component"
  181. :generateForm="$refs.generateForm"
  182. :info="scope.model"
  183. ></reissueComponent>
  184. </template>
  185. <!-- 申领单(临床/非临床) -->
  186. <template v-slot:blank_application_component="scope">
  187. <applicationComponent
  188. ref="blank_application_component"
  189. id="blank_application_component"
  190. :generateForm="$refs.generateForm"
  191. :info="scope.model"
  192. ></applicationComponent>
  193. </template>
  194. <!-- 采购申请单(行政采购) -->
  195. <template v-slot:blank_purchase_requisition="scope">
  196. <purchaseRequisitionComponent
  197. ref="blank_purchase_requisition"
  198. id="blank_purchase_requisition"
  199. :generateForm="$refs.generateForm"
  200. :info="scope.model"
  201. ></purchaseRequisitionComponent>
  202. </template>
  203. <!-- 出差申请单 -->
  204. <template v-slot:blank_business_trip="scope">
  205. <businessTripComponent
  206. ref="blank_business_trip"
  207. id="blank_business_trip"
  208. :generateForm="$refs.generateForm"
  209. :info="scope.model"
  210. ></businessTripComponent>
  211. </template>
  212. </fm-generate-form>
  213. </div>
  214. <div
  215. style="
  216. align-self: center;
  217. display: flex;
  218. color: #1890ff;
  219. cursor: pointer;
  220. width: 15px;
  221. "
  222. @click="() => (isRight = !isRight)"
  223. >
  224. <span
  225. style="
  226. align-self: center;
  227. transform: scale(1.5);
  228. "
  229. :class="isRight ? 'el-icon-caret-left' : 'el-icon-caret-right'"
  230. >
  231. </span>
  232. <span style="writing-mode: vertical-rl">选择流程</span>
  233. </div>
  234. <div style="flex: 1" v-if="isRight">
  235. <el-form
  236. ref="form"
  237. :rules="rules"
  238. class="el-form-box"
  239. :model="form"
  240. label-width="80px"
  241. >
  242. <el-row>
  243. <el-col :span="12">
  244. <el-form-item label="流程分类">
  245. <ele-tree-select
  246. @change="changeLCFL"
  247. clearable
  248. ref="processTypeRef"
  249. filterable
  250. :data="LCFLList"
  251. v-model="form.LCFL"
  252. childrenKey="children"
  253. valueKey="id"
  254. labelKey="name"
  255. placeholder="请选择"
  256. default-expand-all
  257. />
  258. </el-form-item>
  259. </el-col>
  260. <el-col :span="12">
  261. <el-form-item label="发起流程">
  262. <el-select
  263. filterable
  264. v-model="form.FQLC"
  265. @change="changeFQLC"
  266. style="width: 100%"
  267. >
  268. <el-option
  269. v-for="item in processList"
  270. :key="item.id"
  271. :value="item.id"
  272. :label="item.name"
  273. ></el-option>
  274. </el-select>
  275. </el-form-item>
  276. </el-col>
  277. </el-row>
  278. <el-row>
  279. <el-col :span="12">
  280. <el-form-item label="流程名称">
  281. <el-input v-model="form.name" clearable></el-input>
  282. </el-form-item>
  283. </el-col>
  284. <el-col :span="12">
  285. <el-form-item label="流程标识">
  286. <el-input v-model="form.key" disabled></el-input>
  287. </el-form-item>
  288. </el-col>
  289. </el-row>
  290. <headerTitle
  291. title="流程执行人/流程图"
  292. style="margin-top: 30px"
  293. ></headerTitle>
  294. <el-table
  295. :data="datasource"
  296. height="150px"
  297. border
  298. style="margin-bottom: 10px"
  299. >
  300. <el-table-column
  301. label="任务节点"
  302. align="center"
  303. prop="taskDefinitionName"
  304. width="140"
  305. fixed
  306. />
  307. <el-table-column
  308. label="执行人"
  309. align="center"
  310. prop="options"
  311. min-width="140px"
  312. >
  313. <template v-slot="scope">
  314. <div
  315. v-if="
  316. scope.row.type !== 60 &&
  317. scope.row.type !== 70 &&
  318. scope.row.options.length > 0
  319. "
  320. >
  321. <el-tag
  322. size="medium"
  323. :key="option"
  324. v-for="option in scope.row.options"
  325. >
  326. {{ getAssignRuleOptionName(scope.row, option) }}
  327. </el-tag>
  328. </div>
  329. <el-tag
  330. size="medium"
  331. v-if="
  332. scope.row.type === 60 ||
  333. scope.row.type === 70 ||
  334. scope.row.type === 80
  335. "
  336. >
  337. {{ getAssignRuleOptionName(scope.row) }}
  338. </el-tag>
  339. </template>
  340. </el-table-column>
  341. </el-table>
  342. <my-process-viewer
  343. style="min-width: 100%; height: 200px"
  344. key="designer"
  345. v-model="bpmnXML"
  346. />
  347. </el-form>
  348. </div>
  349. </div>
  350. <div slot="footer">
  351. <el-form :model="form">
  352. <el-form-item label="通知人:">
  353. <el-button
  354. style="float: left; margin-top: 5px"
  355. icon="el-icon-circle-plus-outline"
  356. round
  357. @click="handleEditDataScope"
  358. ></el-button>
  359. <div style="display: flex; flex-direction: row; flex-wrap: wrap">
  360. <el-tag
  361. style="float: left; margin: 5px 5px 0 5px"
  362. v-for="(item, index) in form.noticeScope"
  363. :key="item.name"
  364. effect="plain"
  365. closable
  366. :title="item.name"
  367. @close="handleCloseTag(index)"
  368. >
  369. {{
  370. item.name.length > 3
  371. ? item.name[0] + item.name[1] + item.name[2] + '...'
  372. : item.name
  373. }}
  374. </el-tag>
  375. </div>
  376. <!-- <ele-tree-select-->
  377. <!-- @change="handleTreeChange"-->
  378. <!-- filterable-->
  379. <!-- style="width: 100%"-->
  380. <!-- ref="treeSelect"-->
  381. <!-- multiple-->
  382. <!-- clearable-->
  383. <!-- :data="treeData"-->
  384. <!-- v-model="treeList"-->
  385. <!-- placeholder="请选择"-->
  386. <!-- valueKey="id"-->
  387. <!-- labelKey="name"-->
  388. <!-- :checkStrictly="true"-->
  389. <!-- />-->
  390. </el-form-item>
  391. </el-form>
  392. <!-- <el-button-->
  393. <!-- type="primary"-->
  394. <!-- size="small"-->
  395. <!-- v-if="active == 0"-->
  396. <!-- @click="() => ((active = 1), (isRight = true))"-->
  397. <!-- >下一步-->
  398. <!-- </el-button>-->
  399. <!-- <el-button-->
  400. <!-- type="primary"-->
  401. <!-- size="small"-->
  402. <!-- v-if="active == 1"-->
  403. <!-- @click="() => (active = 0)"-->
  404. <!-- >上一步-->
  405. <!-- </el-button>-->
  406. <el-button type="primary" size="small" v-click-once @click="submit"
  407. >提交</el-button
  408. >
  409. <el-button size="small" @click="cancel">关闭</el-button>
  410. <!-- <visibility-range-dialog-->
  411. <!-- :visibilityRangeDialogFlag.sync="visibilityRangeDialogFlag"-->
  412. <!-- v-if="visibilityRangeDialogFlag"-->
  413. <!-- @getTreeList="getTreeList"-->
  414. <!-- ref="visibilityRangeDialogRef"-->
  415. <!-- ></visibility-range-dialog>-->
  416. <staffSelection
  417. ref="staffSelection"
  418. @confirm="getTreeList"
  419. ></staffSelection>
  420. </div>
  421. <parentList
  422. ref="parentRef"
  423. @changeParent="handleConcatConfirm"
  424. ></parentList>
  425. <SHGDListDialog
  426. ref="SHGDListDialogRef"
  427. @changeParent="getSHGDData"
  428. ></SHGDListDialog>
  429. </ele-modal>
  430. </template>
  431. <script>
  432. import {
  433. getModelPage,
  434. getProcessDefinitionBpmnXML,
  435. getProcessDefinitionInfo,
  436. getTaskAssignRuleList,
  437. listAllUserBind,
  438. listSimpleUserGroups,
  439. processInstanceCreateAPI
  440. } from './api';
  441. import { treeClassifyCodeEnum } from '@/enum/dict';
  442. import { listRoles } from '@/api/system/role';
  443. import { listOrganizations } from '@/api/system/organization';
  444. import dictMixins from '@/mixins/dictMixins';
  445. import { getByCode } from '@/api/system/dictionary-data';
  446. import { getGroupUserTree, getProduceTreeByCode } from '@/api/main';
  447. import visibilityRangeDialog from './visibilityRangeDialog.vue';
  448. import { getModel } from '@/api/bpm/model';
  449. import { getProcessDefinitionList } from '@/api/bpm/definition';
  450. import { getToken } from '@/utils/token-util';
  451. import { mapGetters } from 'vuex';
  452. import staffSelection from '@/components/staffSelection/staffSelection.vue';
  453. import { topLevel1, topLevel2, topLevel3 } from '@/enum/dict';
  454. import dayjs from 'dayjs';
  455. import parentList from './components/parentList.vue';
  456. import { number } from 'echarts';
  457. import { del } from 'vue';
  458. import businessComponent from './components/businessComponent.vue';
  459. import useSealComponent from './components/useSealComponent.vue';
  460. import useQualificationComponent from './components/useQualificationComponent.vue';
  461. import productSpecificationComponent from './components/productSpecificationComponent.vue';
  462. import eventComponent from './components/eventComponent.vue';
  463. import reissueComponent from './components/reissueComponent.vue';
  464. import SHGDListDialog from './components/SHGDListDialog.vue';
  465. import applicationComponent from './components/applicationComponent.vue';
  466. import purchaseRequisitionComponent from './components/purchaseRequisitionComponent.vue';
  467. import businessTripComponent from './components/businessTripComponent.vue';
  468. import { parameterGetByCode } from '@/api/main/index.js';
  469. export default {
  470. name: 'processSubmitDialog',
  471. components: {
  472. visibilityRangeDialog,
  473. staffSelection,
  474. parentList,
  475. businessComponent,
  476. useSealComponent,
  477. useQualificationComponent,
  478. productSpecificationComponent,
  479. eventComponent,
  480. reissueComponent,
  481. SHGDListDialog,
  482. applicationComponent,
  483. purchaseRequisitionComponent,
  484. businessTripComponent
  485. },
  486. mixins: [dictMixins],
  487. props: {
  488. processSubmitDialogFlag: {
  489. type: Boolean,
  490. default: false
  491. }
  492. },
  493. watch: {
  494. filterText(val) {
  495. this.$refs.tree.filter(val);
  496. }
  497. },
  498. data() {
  499. return {
  500. visibilityRangeDialogFlag: false,
  501. isRight: false,
  502. jsonData: {},
  503. form: {
  504. LCFL: '',
  505. FQLC: '',
  506. processDefinitionId: '',
  507. name: '',
  508. businessId: '',
  509. noticeScope: [],
  510. formJson: {},
  511. valueJson: {},
  512. businessKey: ''
  513. },
  514. title: '',
  515. active: 0,
  516. bpmnXML: null,
  517. filterText: null,
  518. treeList: [],
  519. treeData: [],
  520. defaultProps: {
  521. children: 'children',
  522. label: 'name'
  523. },
  524. LCFLList: [],
  525. processList: [],
  526. datasource: [],
  527. roleOptions: [],
  528. deptOptions: [],
  529. deptTreeOptions: [],
  530. postOptions: [],
  531. userOptions: [],
  532. userGroupOptions: [],
  533. dictList: {},
  534. rules: {},
  535. editForm: {
  536. start: '',
  537. end: '',
  538. days: ''
  539. },
  540. componentRef: [
  541. 'blank_business_component',
  542. 'blank_use_seal',
  543. 'blank_use_qualification',
  544. 'blank_product_specification',
  545. 'blank_event_component',
  546. 'blank_reissue_component',
  547. 'blank_application_component',
  548. 'blank_purchase_requisition',
  549. 'blank_business_trip'
  550. ]
  551. };
  552. },
  553. computed: {
  554. ...mapGetters(['user']),
  555. modelWidth() {
  556. let width =
  557. this.jsonData.config?.platform &&
  558. this.jsonData.config.platform === 'pc'
  559. ? 1100
  560. : 450;
  561. if (this.isRight) {
  562. return width + 350 + 'px';
  563. } else {
  564. return width + 'px';
  565. }
  566. }
  567. },
  568. async created() {
  569. let typeObj = await getProduceTreeByCode(
  570. treeClassifyCodeEnum['PROCESSTYPE']
  571. );
  572. // await this.getTreeData();
  573. this.LCFLList = typeObj[0].children;
  574. // 获得角色列表
  575. this.roleOptions = [];
  576. listRoles({
  577. current: 1,
  578. size: 9999
  579. }).then((data) => {
  580. this.roleOptions.push(...data.list);
  581. });
  582. // 获得部门列表
  583. this.deptOptions = [];
  584. this.deptTreeOptions = [];
  585. listOrganizations().then((data) => {
  586. this.deptOptions.push(...data);
  587. this.deptTreeOptions.push(...this.handleTree(data, 'id'));
  588. });
  589. // 获得岗位列表 暂无岗位概念
  590. this.postOptions = [];
  591. /*listSimplePosts().then(response => {
  592. this.postOptions.push(...response.data);
  593. });*/
  594. // 获得用户列表
  595. this.userOptions = [];
  596. listAllUserBind().then((data) => {
  597. this.userOptions.push(...data);
  598. });
  599. // 获得用户组列表
  600. this.userGroupOptions = [];
  601. listSimpleUserGroups().then((response) => {
  602. this.userGroupOptions.push(...response);
  603. });
  604. //this.dictEnum['工作流任务分配自定义脚本']
  605. await this.getDictList(this.dictEnum['工作流任务分配自定义脚本']);
  606. await this.getDictList(this.dictEnum['工种类型']);
  607. await this.getDictList(this.dictEnum['协同办公分类']);
  608. },
  609. mounted() {
  610. //this.isRight = false
  611. },
  612. methods: {
  613. async addNewRow(key) {
  614. console.log(key);
  615. let data = await this.$refs.generateForm.getData(false);
  616. data[key].push({
  617. price: '',
  618. remark: ''
  619. });
  620. this.$refs.generateForm.setData({
  621. key: data[key]
  622. });
  623. },
  624. async delNewRow(key, index) {
  625. let data = await this.$refs.generateForm.getData(false);
  626. data[key] = data[key].filter((item, index1) => index1 != index);
  627. this.$refs.generateForm.setData({
  628. [key]: data[key]
  629. });
  630. this.changePrice(data[key]);
  631. },
  632. changePrice(data) {
  633. let num = 0;
  634. data.forEach((item) => {
  635. num += Number(item.price);
  636. });
  637. this.$refs.generateForm.setData({
  638. input_jd9ouzyh: num
  639. });
  640. },
  641. // 获取组件的中文名称,用于错误提示
  642. getComponentName(componentKey) {
  643. const nameMap = {
  644. blank_business_component: '差旅交通',
  645. blank_use_seal: '印章使用',
  646. blank_use_qualification: '资质使用',
  647. blank_product_specification: '产品规格',
  648. blank_event_component: '事件',
  649. blank_reissue_component: '补发信息',
  650. blank_application_component: '申领单',
  651. blank_purchase_requisition: '采购申请单',
  652. blank_business_trip: '出差申请单'
  653. };
  654. return nameMap[componentKey] || componentKey;
  655. },
  656. async addContact(type) {
  657. console.log(type);
  658. let data = await this.$refs.generateForm.getData(false);
  659. console.log('data', data);
  660. data[type] = {
  661. id: '',
  662. name: ''
  663. };
  664. this.$refs.generateForm.setData({
  665. type: data[type]
  666. });
  667. let item = {
  668. id: data[type].id
  669. };
  670. this.$refs.parentRef.open(item);
  671. },
  672. async addWorkOrder(type) {
  673. this.$refs.SHGDListDialogRef.open();
  674. },
  675. getSHGDData(workOrder) {
  676. if (!workOrder?.code) {
  677. this.$message.warning('选中的工单缺少编码,请重新选择');
  678. return;
  679. }
  680. this.$refs.generateForm.getData(false).then((currentFormData) => {
  681. currentFormData.manage_workorder = {
  682. code: workOrder.code,
  683. id: workOrder.id || '',
  684. name: workOrder.name || ''
  685. };
  686. this.$refs.generateForm.setData({
  687. manage_workorder: currentFormData.manage_workorder
  688. });
  689. this.form.valueJson.manage_workorder =
  690. currentFormData.manage_workorder;
  691. });
  692. },
  693. async handleConcatConfirm(item) {
  694. console.log('选择的客户', item);
  695. let data = await this.$refs.generateForm.getData(false);
  696. data['eom_contact'] = {
  697. id: item.id,
  698. name: item.name
  699. };
  700. this.$refs.generateForm.setData({
  701. eom_contact: data['eom_contact']
  702. });
  703. console.log('data~~~~', data);
  704. },
  705. async init(row = {}) {
  706. this.title = row.name; //'新建' + row.name + '单';
  707. this.form = _.cloneDeep(row);
  708. this.form.formId = row.id;
  709. this.$set(this.form, 'noticeScope', []);
  710. this.$set(this.form, 'LCFL', '');
  711. this.$set(this.form, 'FQLC', '');
  712. this.$set(this.form, 'name', '');
  713. this.$set(this.form, 'key', '');
  714. this.$set(this.form, 'valueJson', {});
  715. this.jsonData = JSON.parse(this.form.formJson.makingJson);
  716. console.log('jsonData', this.jsonData);
  717. this.jsonData.config.dataSource &&
  718. this.jsonData.config.dataSource.forEach((item) => {
  719. item.headers = {
  720. Authorization: getToken()
  721. };
  722. // item.url = item.url && item.url.replace('/api', this.APIUrl);
  723. });
  724. this.jsonData.list.forEach((item) => {
  725. if (item.type == 'deptAndUserCascader') {
  726. }
  727. if (item.type == 'deptCascader') {
  728. if (item.options.isDefaultLoginUser) {
  729. this.form.valueJson[item.model] = this.user.info.groupIdList;
  730. }
  731. }
  732. if (item.type == 'userSelect') {
  733. if (item.options.isDefaultLoginUser) {
  734. this.form.valueJson[item.model] = this.user.info.userId;
  735. }
  736. }
  737. if (item.type == 'imgupload') {
  738. // this.form.valueJson[item.model].length &&
  739. // this.form.valueJson[item.model].forEach((item) => {
  740. // //item.objectUrl = this.APIUrl +'/kd-aiot' + item.storePath
  741. // // item.objectUrl = item.url;
  742. // // console.log(item);
  743. // });
  744. }
  745. });
  746. await this.getProcessDefinitionBpmnXMLInfo(this.form.processModelId);
  747. await this.getTaskAssignRuleListInfo({
  748. modelId: this.form.processModelId,
  749. processDefinitionId: this.form.processDefinitionId
  750. });
  751. await this.getDefaultInfo(row.processModelId);
  752. },
  753. async getDefaultInfo(businessKey) {
  754. let info = await getModel(businessKey);
  755. //let info = await getProcessDefinitionInfo({ id: businessKey });
  756. parameterGetByCode({
  757. code: 'wt_collaborative_bpm'
  758. }).then((res) => {
  759. if (!res.value || res.value == '1') {
  760. this.form.FQLC = info?.id;
  761. this.form.name = this.title;
  762. this.form.key = info?.key;
  763. }
  764. });
  765. this.form.LCFL = info?.category;
  766. if (this.form.LCFL) await this.getProcessList(this.form.LCFL);
  767. },
  768. async getProcessList(val) {
  769. let params = {
  770. pageNo: 1,
  771. pageSize: 999,
  772. processTypeId: val
  773. };
  774. const { list } = await getModelPage(params);
  775. this.processList = list.filter((item) => item.processDefinition);
  776. },
  777. async getProcessDefinitionBpmnXML(val) {
  778. this.bpmnXML = await getProcessDefinitionBpmnXML(val);
  779. },
  780. async getProcessDefinitionBpmnXMLInfo(val) {
  781. // 加载流程图
  782. let res = await getModel(val);
  783. this.bpmnXML = res.bpmnXml;
  784. },
  785. async getTaskAssignRuleListInfo(find) {
  786. this.datasource = await getTaskAssignRuleList({
  787. modelId: find.modelId,
  788. processDefinitionId: find.processDefinitionId
  789. });
  790. },
  791. handleEditDataScope() {
  792. this.$refs.staffSelection.open(this.form.noticeScope);
  793. // this.visibilityRangeDialogFlag = true;
  794. // this.$nextTick(() => {
  795. // this.$refs.visibilityRangeDialogRef.init(this.form);
  796. // });
  797. },
  798. getTreeList(list) {
  799. list.forEach((item) => {
  800. item.type = 1;
  801. });
  802. this.form.noticeScope = list;
  803. },
  804. handleCloseTag(index) {
  805. this.form.noticeScope.splice(index, 1);
  806. },
  807. getAssignRuleOptionName(row, option) {
  808. if (row.type == 10) {
  809. for (const roleOption of this.roleOptions) {
  810. if (roleOption.id === option) {
  811. return roleOption.name;
  812. }
  813. }
  814. } else if (row.type == 11) {
  815. for (const roleOption of this.roleOptions) {
  816. if (roleOption.id === option) {
  817. return roleOption.name;
  818. }
  819. }
  820. } else if (row.type === 20 || row.type === 21) {
  821. for (const deptOption of this.deptOptions) {
  822. if (deptOption.id === option) {
  823. return deptOption.name;
  824. }
  825. }
  826. } else if (row.type === 22) {
  827. option = option + ''; // 转换成 string
  828. return this.getDictV(this.dictEnum['工种类型'], option);
  829. } else if (row.type === 30 || row.type === 31 || row.type === 32) {
  830. for (const userOption of this.userOptions) {
  831. if (userOption.id === option) {
  832. return userOption.nickname || userOption.name;
  833. }
  834. }
  835. } else if (row.type === 40) {
  836. for (const userGroupOption of this.userGroupOptions) {
  837. if (userGroupOption.id === option) {
  838. return userGroupOption.name;
  839. }
  840. }
  841. } else if (row.type === 50) {
  842. option = option + ''; // 转换成 string
  843. return this.getDictV(
  844. this.dictEnum['工作流任务分配自定义脚本'],
  845. option
  846. );
  847. } else if (row.type === 60) {
  848. return row.variableName;
  849. } else if (row.type === 70) {
  850. let data = JSON.parse(row.variableName);
  851. if (data.direction == 1) {
  852. return topLevel2.find((item) => item.value == data.topLevel)?.label;
  853. } else {
  854. return topLevel1.find((item) => item.value == data.topLevel)?.label;
  855. }
  856. } else if (row.type === 80) {
  857. let data = JSON.parse(row.variableName);
  858. return topLevel3.find((item) => item.value == data.topLevel)?.label;
  859. }
  860. return '未知(' + option + ')';
  861. },
  862. async getTreeData() {
  863. this.treeData = await getGroupUserTree();
  864. },
  865. filterNode(value, data) {
  866. if (!value) return true;
  867. return data.name.indexOf(value) !== -1;
  868. },
  869. /**
  870. * 构造树型结构数据
  871. * @param {*} data 数据源
  872. * @param {*} id id字段 默认 'id'
  873. * @param {*} parentId 父节点字段 默认 'parentId'
  874. * @param {*} children 孩子节点字段 默认 'children'
  875. * @param {*} rootId 根Id 默认 0
  876. */
  877. handleTree(data, id, parentId, children, rootId) {
  878. id = id || 'id';
  879. parentId = parentId || 'parentId';
  880. children = children || 'children';
  881. rootId =
  882. rootId ||
  883. Math.min.apply(
  884. Math,
  885. data.map((item) => {
  886. return item[parentId];
  887. })
  888. ) ||
  889. 0;
  890. //对源数据深度克隆
  891. const cloneData = JSON.parse(JSON.stringify(data));
  892. //循环所有项
  893. const treeData = cloneData.filter((father) => {
  894. let branchArr = cloneData.filter((child) => {
  895. //返回每一项的子级数组
  896. return father[id] == child[parentId];
  897. });
  898. branchArr.length > 0 ? (father.children = branchArr) : '';
  899. //返回第一层
  900. return father[parentId] == rootId;
  901. });
  902. return treeData !== '' ? treeData : data;
  903. },
  904. getDictV(code, val) {
  905. if (!this.dictList[code]) return '';
  906. return this.dictList[code].find((item) => item.value == val)?.label;
  907. },
  908. async getDictList(code) {
  909. let { data: res } = await getByCode(code);
  910. this.dictList[code] = res.map((item) => {
  911. let values = Object.keys(item);
  912. return {
  913. value: values[0],
  914. label: item[values[0]]
  915. };
  916. });
  917. },
  918. generateFormValid(validate = true) {
  919. return this.$refs.generateForm
  920. .getData(validate)
  921. .then((data) => {
  922. return data;
  923. })
  924. .catch((err) => {
  925. this.$message.error(err);
  926. console.log(err);
  927. throw err;
  928. });
  929. },
  930. handleTreeChange() {
  931. this.$nextTick(() => {
  932. this.form.noticeScope =
  933. this.$refs.treeSelect.$refs.tree.getCheckedNodes();
  934. console.log(this.form.noticeScope);
  935. });
  936. },
  937. async changeLCFL(val) {
  938. this.bpmnXML = null;
  939. this.form.processDefinitionId = null;
  940. this.form.FQLC = null;
  941. await this.getProcessList(val);
  942. },
  943. async changeFQLC(val) {
  944. if (!val) return;
  945. let find = this.processList.find((item) => item.id === val) || {};
  946. this.form.name = find.name;
  947. this.form.key = find.key;
  948. this.form.processDefinitionId = find.processDefinition.id;
  949. this.form.processModelId = val;
  950. await this.getProcessDefinitionBpmnXML(find.processDefinition.id);
  951. await this.getTaskAssignRuleListInfo({
  952. modelId: find.id,
  953. processDefinitionId: find.processDefinition.id
  954. });
  955. },
  956. async submit() {
  957. try {
  958. // console.log('this.form~~~', this.$refs.businessComponentRef.form);
  959. // const businessComponentForm = this.$refs.businessComponentRef.form;
  960. let data = await this.$refs.generateForm.getData(false);
  961. // data['blank_business_component'] = businessComponentForm.blank_business_component;
  962. // this.$refs.generateForm.setData({
  963. // 'blank_business_component': data['blank_business_component']
  964. // });
  965. // 获取所有组件的引用
  966. let validArr = [];
  967. // 过滤出存在于componentRef中的键
  968. Object.keys(data).forEach((key) => {
  969. if (this.componentRef.includes(key)) {
  970. validArr.push(key);
  971. }
  972. });
  973. // 检查每个组件的数据是否为空
  974. let emptyComponents = [];
  975. validArr.forEach((item) => {
  976. const val = data[item];
  977. // 为空(null/undefined/空字符串)或为数组且长度为0,均视为未填写
  978. if (
  979. val === null ||
  980. val === undefined ||
  981. val === '' ||
  982. (Array.isArray(val) && val.length === 0)
  983. ) {
  984. emptyComponents.push(item);
  985. }
  986. });
  987. // 如果有未填写的组件,显示提示信息
  988. if (emptyComponents.length > 0) {
  989. this.$message.warning(
  990. `请填写完整信息:${emptyComponents
  991. .map((comp) => this.getComponentName(comp))
  992. .join('、')}`
  993. );
  994. // this.$message.warning(`请填写完整信息`);
  995. return false;
  996. }
  997. // 使用Promise.all并行校验所有组件
  998. // try {
  999. // await Promise.all(validArr.map(key => {
  1000. // if (this.$refs[key] && typeof this.$refs[key].validateForm === 'function') {
  1001. // return this.$refs[key].validateForm();
  1002. // }
  1003. // return Promise.resolve(true); // 如果组件不存在或没有validateForm方法,默认通过
  1004. // }));
  1005. // console.log('所有组件校验通过');
  1006. // } catch (error) {
  1007. // console.error('表单校验失败:', error);
  1008. // this.$message.error('表单校验失败,请检查必填项');
  1009. // return false; // 任一组件校验失败则整体失败
  1010. // }
  1011. // console.log('data~~~~', data);
  1012. this.form.valueJson = await this.generateFormValid();
  1013. this.form.processType = '1';
  1014. console.log('formformformform', this.form);
  1015. console.log('this.form.dictList', this.dictList);
  1016. await processInstanceCreateAPI({
  1017. ...this.form,
  1018. variables: {
  1019. ...this.form.valueJson,
  1020. businessCode: this.form.code,
  1021. businessName: this.form.name,
  1022. businessType: this.dictList['collaborative_type']?.find(
  1023. (item) => item.value == this.form.dictType
  1024. )?.label
  1025. }
  1026. });
  1027. this.$message('提交审核成功');
  1028. this.$emit('reload');
  1029. this.cancel();
  1030. } catch (error) {
  1031. console.error('提交失败:', error);
  1032. // 错误已经在generateFormValid中处理,这里不需要重复处理
  1033. }
  1034. },
  1035. cancel() {
  1036. this.$emit('update:processSubmitDialogFlag', false);
  1037. },
  1038. getDays(start, end) {
  1039. const startDay = dayjs(start);
  1040. const endDay = dayjs(end);
  1041. const diffInMilliseconds = endDay.diff(startDay);
  1042. // 计算天数
  1043. const days = Math.floor(diffInMilliseconds / (1000 * 60 * 60 * 24));
  1044. // 计算剩余小时数
  1045. const hours = Math.floor(
  1046. (diffInMilliseconds % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
  1047. );
  1048. // 计算剩余分钟数
  1049. const minutes = Math.floor(
  1050. (diffInMilliseconds % (1000 * 60 * 60)) / (1000 * 60)
  1051. );
  1052. // 计算剩余秒数
  1053. const seconds = Math.floor((diffInMilliseconds % (1000 * 60)) / 1000);
  1054. let result = '';
  1055. if (days > 0) result += `${days} 天 `;
  1056. if (hours > 0) result += `${hours} 小时 `;
  1057. if (minutes > 0) result += `${minutes} 分钟 `;
  1058. if (seconds > 0) result += `${seconds} 秒`;
  1059. return result.trim();
  1060. }
  1061. }
  1062. };
  1063. </script>
  1064. <style scoped lang="scss">
  1065. .box {
  1066. display: flex;
  1067. height: 450px;
  1068. .left-box {
  1069. width: 55%;
  1070. border-right: 1px solid #e2e4e7;
  1071. padding-right: 15px;
  1072. height: 100%;
  1073. .el-tree {
  1074. height: 85%;
  1075. overflow-y: auto;
  1076. }
  1077. }
  1078. .right-box {
  1079. flex: 1;
  1080. padding-left: 20px;
  1081. height: 100%;
  1082. .right-box-item {
  1083. margin-top: 5px;
  1084. display: flex;
  1085. justify-content: space-between;
  1086. align-items: center;
  1087. }
  1088. }
  1089. }
  1090. .form-box {
  1091. // max-height: 500px;
  1092. min-width: 400px;
  1093. overflow: auto;
  1094. background: #4298fd0d;
  1095. }
  1096. ::v-deep .el-dialog {
  1097. min-width: 400px;
  1098. .el-dialog__header {
  1099. background: #1890ffd6;
  1100. }
  1101. .el-dialog__title,
  1102. .el-dialog__close {
  1103. color: #ffffff;
  1104. }
  1105. }
  1106. .blank_adopzrdd {
  1107. display: flex;
  1108. align-items: center;
  1109. > span {
  1110. display: inline-block;
  1111. width: 80px;
  1112. }
  1113. margin-bottom: 10px;
  1114. }
  1115. </style>