handle.vue 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149
  1. <template>
  2. <div class="app-container">
  3. <div v-if="isLoadingStatus"></div>
  4. <div v-else>
  5. <el-alert
  6. v-if="
  7. activeIndex !== nodeStepList.length &&
  8. processStructureValue.workOrder.is_end === 1
  9. "
  10. style="margin-top: 15px"
  11. :title="alertMessage"
  12. type="error"
  13. :closable="false"
  14. />
  15. <el-card class="box-card" style="margin-top: 15px">
  16. <div slot="header" class="clearfix">
  17. <span>公共信息</span>
  18. </div>
  19. <div class="text item">
  20. <el-form label-width="100px">
  21. <el-row>
  22. <el-col :span="4">
  23. <el-form-item label="编号(ID):" style="margin-bottom: 5px">
  24. <span>{{ this.workOrderId }}</span>
  25. </el-form-item>
  26. </el-col>
  27. <el-col :span="10">
  28. <el-form-item label="标题:" style="margin-bottom: 5px">
  29. <span>{{ processStructureValue.workOrder.title }}</span>
  30. </el-form-item>
  31. </el-col>
  32. <el-col :span="10">
  33. <el-form-item label="优先级:" style="margin-bottom: 0">
  34. <span v-if="processStructureValue.workOrder.priority === 2">
  35. <el-tag type="warning">紧急</el-tag>
  36. </span>
  37. <span
  38. v-else-if="processStructureValue.workOrder.priority === 3"
  39. >
  40. <el-tag type="danger">非常紧急</el-tag>
  41. </span>
  42. <span v-else>
  43. <el-tag type="success">一般</el-tag>
  44. </span>
  45. </el-form-item>
  46. </el-col>
  47. </el-row>
  48. </el-form>
  49. </div>
  50. </el-card>
  51. <el-card class="box-card" style="margin-top: 15px">
  52. <div slot="header" class="clearfix">
  53. <span>表单信息</span>
  54. </div>
  55. <div class="text item">
  56. <template v-for="(tplItem, tplIndex) in processStructureValue.tpls">
  57. <fm-generate-form
  58. v-show="
  59. currentNode.hideTpls === undefined ||
  60. currentNode.hideTpls === null ||
  61. currentNode.hideTpls.indexOf(tplItem.form_structure.id) === -1
  62. "
  63. :key="tplIndex"
  64. :ref="'generateForm-' + tplItem.id"
  65. :preview="true"
  66. :remote="remoteFunc"
  67. :value="tplItem.form_data"
  68. :data="tplItem.form_structure"
  69. :organ-list="organList"
  70. />
  71. </template>
  72. </div>
  73. <hr
  74. v-if="is_end == 0"
  75. style="
  76. background-color: #d9d9d9;
  77. border: 0;
  78. height: 1px;
  79. margin-bottom: 15px;
  80. "
  81. />
  82. <div class="text item" style="margin-top: 18px; text-align: center;">
  83. <!-- 只要没有结束就可以评论 -->
  84. <el-button round type="info" @click="handleCommit" v-if="is_end == 0"
  85. >评论</el-button
  86. >
  87. <template v-if="is_end == 0 && processStructureValue.userAuthority">
  88. <!-- 没有结束,自己审批 -->
  89. <el-button
  90. type="warning"
  91. round
  92. @click="handleInversion(endNodeDetail)"
  93. >转交</el-button
  94. >
  95. <el-button
  96. v-for="(item, index) in btn_group"
  97. :key="index"
  98. :type="item.className"
  99. @click="submitAction(item)"
  100. round
  101. >{{ item.labelShow }}</el-button
  102. >
  103. <!-- 拒绝按钮内置 -->
  104. <el-button
  105. v-if="endNodeDetail.id"
  106. type="danger"
  107. round
  108. @click="submitAction(endNodeDetail)"
  109. >{{ endNodeDetail.label }}</el-button
  110. >
  111. </template>
  112. </div>
  113. </el-card>
  114. <el-card class="box-card" style="margin-top: 15px">
  115. <div slot="header" class="clearfix">
  116. <span>流程</span>
  117. </div>
  118. <div class="text item">
  119. <el-timeline
  120. v-if="
  121. currentNode.clazz !== undefined &&
  122. currentNode.clazz !== null &&
  123. currentNode.clazz !== ''
  124. "
  125. >
  126. <el-timeline-item
  127. v-for="(item, index) in circulationList"
  128. :key="index"
  129. :icon="formatIcon(item, index, 'icon')"
  130. :class="activeIndex >= index ? 'large-icon' : ''"
  131. size="large"
  132. >
  133. <div class="step-title">
  134. {{ item.state || item.label }}
  135. <span class="apply-time">
  136. {{
  137. item.create_time
  138. ? dayjs(item.create_time).format("MM-DD HH:mm")
  139. : null
  140. }}
  141. </span>
  142. </div>
  143. <template v-if="!item.create_time">
  144. <p
  145. class="apply-status"
  146. v-if="item.assignUsers && item.assignUsers.length > 0"
  147. >
  148. <!-- 判断是否是自己审批 -->
  149. <template
  150. v-if="
  151. item.assignUsers[0].userId == userInfo.userId &&
  152. activeIndex == index
  153. "
  154. >
  155. 我(审批中)
  156. </template>
  157. <template v-else>
  158. <template v-if="item.isCounterSign">
  159. <span
  160. v-for="(au, aIndex) in item.assignUsers"
  161. :key="aIndex"
  162. >
  163. {{ au.username
  164. }}{{
  165. aIndex < item.assignUsers.length - 1 ? "," : null
  166. }}
  167. </span>
  168. </template>
  169. <template v-else>
  170. {{ item.assignUsers[0].username }}
  171. </template>
  172. {{ activeIndex == index ? `(审批中)` : null }}
  173. </template>
  174. </p>
  175. </template>
  176. <template v-else>
  177. <p class="apply-status" v-if="item.processor">
  178. {{ item.processor
  179. }}{{ item.circulation ? `(${item.circulation})` : null }}
  180. </p>
  181. <template v-if="item.remarks && item.remarks.trim()">
  182. <p
  183. class="remarks"
  184. v-html="dataModelFormatBr(item.remarks)"
  185. ></p>
  186. </template>
  187. <!-- 判断是否有添加图片 -->
  188. <div
  189. class="imgUploader"
  190. v-if="
  191. item.fileUrl &&
  192. item.fileUrl.file &&
  193. item.fileUrl.image.length > 0
  194. "
  195. >
  196. <el-image
  197. v-for="(file, index) in item.fileUrl.image"
  198. :key="index"
  199. style="width: 40px; height: 40px; margin-right: 12px;"
  200. :src="file"
  201. :preview-src-list="item.fileUrl.image"
  202. >
  203. </el-image>
  204. </div>
  205. <!-- 判断是否有添加的文件 -->
  206. <div
  207. v-if="
  208. item.fileUrl &&
  209. item.fileUrl.file &&
  210. item.fileUrl.file.length > 0
  211. "
  212. >
  213. <div
  214. v-for="(uploadUrlItem, uploadUrlIndex) in item.fileUrl.file"
  215. :key="uploadUrlIndex"
  216. style="margin-bottom: 3px"
  217. class="fileUploader"
  218. >
  219. <i style="color: #909399;" class="el-icon-document" />
  220. <span style="margin-right: 10px;">{{
  221. uploadUrlItem.name || uploadUrlItem.url
  222. }}</span>
  223. <el-button
  224. round
  225. size="mini"
  226. @click="onDownload(uploadUrlItem, 'download')"
  227. >下载</el-button
  228. >
  229. <el-button
  230. round
  231. type="primary"
  232. @click="onDownload(uploadUrlItem)"
  233. v-if="checkFileSuffix(uploadUrlItem.url)"
  234. size="mini"
  235. >预览</el-button
  236. >
  237. </div>
  238. </div>
  239. </template>
  240. <!-- 有抄送人并且,本节点已经审批完成了 -->
  241. <template
  242. v-if="
  243. item.cc_user && item.cc_user.length > 0 && activeIndex > index
  244. "
  245. >
  246. <!-- 已抄送1人 -->
  247. <div class="ccUsers" @click="onCCChange(item)">
  248. <span>已抄送{{ item.cc_user.length }}人</span>
  249. <el-icon
  250. v-show="!item.ccStatus"
  251. style="color: #CCCCCC"
  252. name="arrow-down"
  253. />
  254. <el-icon
  255. v-show="item.ccStatus"
  256. style="color: #CCCCCC"
  257. name="arrow-up"
  258. />
  259. </div>
  260. <div class="ccUserDetail" v-if="item.ccStatus">
  261. <span>{{ item.cc_user.join(",") }}</span>
  262. </div>
  263. </template>
  264. </el-timeline-item>
  265. </el-timeline>
  266. </div>
  267. </el-card>
  268. </div>
  269. <el-dialog title="转交工单" :visible.sync="dialogVisible" width="40%">
  270. <TransferInversion
  271. v-if="dialogVisible"
  272. :selectItem="selectItem"
  273. @getList="getProcessNodeList"
  274. @close="dialogVisible = false"
  275. />
  276. </el-dialog>
  277. <el-dialog :title="submitTitle" :visible.sync="dialogSubmit" width="40%">
  278. <TransferSubmit
  279. v-if="dialogSubmit"
  280. :type="submitType"
  281. :submitItem="submitItem"
  282. @getList="getProcessNodeList"
  283. @close="dialogSubmit = false"
  284. />
  285. </el-dialog>
  286. </div>
  287. </template>
  288. <script>
  289. import Upload from "./model/upload";
  290. import Vue from "vue";
  291. import { GenerateForm } from "@/components/VueFormMaking";
  292. import "form-making/dist/FormMaking.css";
  293. Vue.component(GenerateForm.name, GenerateForm);
  294. import dayjs from "dayjs";
  295. import {
  296. processStructure,
  297. handleWorkOrder,
  298. activeOrder,
  299. asyncPlayLog,
  300. queryUserInfo,
  301. queryAllOrgan,
  302. orderComment
  303. } from "@/api/process/work-order";
  304. import store from "@/store";
  305. import { getInfo } from "@/api/user";
  306. import { listUser } from "@/api/system/sysuser";
  307. import TransferInversion from "./model/transferInversion";
  308. import TransferSubmit from "./model/transferSubmit.vue";
  309. import load from "@/utils/loading";
  310. import { mapGetters } from "vuex";
  311. export default {
  312. components: {
  313. TransferInversion,
  314. TransferSubmit,
  315. Upload
  316. },
  317. data() {
  318. const query = this.$route.query;
  319. return {
  320. submitTitle: "提交信息",
  321. dialogSubmit: false,
  322. submitType: "commit",
  323. submitItem: {},
  324. workOrderId: query.workOrderId,
  325. processId: query.processId,
  326. isLoadingStatus: true,
  327. currentNode: {
  328. hideTpls: null,
  329. writeTpls: null
  330. },
  331. isActiveProcessing: false,
  332. tpls: [],
  333. organList: [],
  334. dataList: {
  335. remarks: "" // 备注信息
  336. },
  337. fileUrl: [],
  338. userInfo: {},
  339. alertMessage: "",
  340. nodeStepList: [],
  341. circulationHistoryList: [],
  342. circulationList: [],
  343. activeIndex: 0,
  344. processStructureValue: {
  345. workOrder: { title: "" }
  346. },
  347. ownerApply: false, // 是否是自己提交的申请
  348. endNodeDetail: {}, // 结束结节信息
  349. ruleForm: {
  350. title: "",
  351. process: "",
  352. classify: "",
  353. state_id: "",
  354. state: "",
  355. source_state: "",
  356. processor: "",
  357. process_method: "",
  358. tpls: [],
  359. tasks: []
  360. },
  361. userIds: null,
  362. tenantId: 1,
  363. btn_group: [],
  364. is_end: 0, // 是否结束
  365. remoteFunc: {
  366. // 获取用户列表
  367. userList(resolve) {
  368. listUser({
  369. pageSize: 999999
  370. }).then(response => {
  371. const options = response.data.list;
  372. resolve(options);
  373. });
  374. }
  375. },
  376. dialogVisible: false,
  377. selectItem: {
  378. work_order_id: "",
  379. node_id: null,
  380. nodeList: [],
  381. users: []
  382. }
  383. };
  384. },
  385. computed: {
  386. ...mapGetters(["userId"])
  387. },
  388. async mounted() {
  389. await this.getUserInfo();
  390. await this.getAllOrgan();
  391. await this.getProcessNodeList();
  392. // 获取用户信息
  393. try {
  394. let user = await getInfo();
  395. this.userInfo = user.data;
  396. this.ownerApply =
  397. this.processStructureValue.workOrder.creator == user.data.userId
  398. ? true
  399. : false;
  400. } catch {
  401. //
  402. }
  403. console.log({
  404. is_end: this.is_end,
  405. ownerApply: this.ownerApply,
  406. userAuthority: this.processStructureValue.userAuthority
  407. });
  408. },
  409. methods: {
  410. dayjs,
  411. // 获取学校列表
  412. onDownload(item, type) {
  413. if (type == "download") {
  414. window.location.href = item.url;
  415. return;
  416. }
  417. let urlArr = item.url.split(".");
  418. let suffix = urlArr[urlArr.length - 1];
  419. if (suffix != "pdf") {
  420. this.previewUrl =
  421. "https://view.officeapps.live.com/op/view.aspx?src=" + item.url;
  422. window.open(this.previewUrl);
  423. return;
  424. } else {
  425. this.previewUrl =
  426. this.validManageUrl() + "/pdf/web/viewer.html?file=" + item.url;
  427. window.open(this.previewUrl);
  428. return;
  429. }
  430. },
  431. // 教务地址
  432. validManageUrl() {
  433. let url = window.location.href;
  434. let returnUrl = "";
  435. if (/dev/.test(url)) {
  436. // dev 环境
  437. returnUrl = "http://mandev.dayaedu.com";
  438. } else if (/test/.test(url)) {
  439. // dev 环境
  440. returnUrl = "http://mantest.dayaedu.com";
  441. } else if (/online/.test(url)) {
  442. //线上
  443. returnUrl = "https://manonline.dayaedu.com";
  444. } else {
  445. // 默认dev环境
  446. returnUrl = "http://mandev.dayaedu.com";
  447. }
  448. return returnUrl;
  449. },
  450. checkFileSuffix(url) {
  451. let urlArr = url.split(".");
  452. let suffix = urlArr[urlArr.length - 1];
  453. if (
  454. suffix == "xlsx" ||
  455. suffix == "xls" ||
  456. suffix == "doc" ||
  457. suffix == "docx" ||
  458. suffix == "pdf"
  459. ) {
  460. return true;
  461. } else {
  462. return false;
  463. }
  464. },
  465. async handleCommit() {
  466. console.log("handleCommit", true);
  467. this.submitTitle = "添加评论";
  468. this.submitType = "commit";
  469. this.submitItem = {
  470. workOrderId: parseInt(this.workOrderId)
  471. };
  472. this.dialogSubmit = true;
  473. },
  474. async handleInversion() {
  475. let workOrder = this.processStructureValue.workOrder;
  476. this.selectItem.work_order_id = workOrder.id;
  477. this.selectItem.nodeList = workOrder.state || [];
  478. this.selectItem.nodeList.forEach(item => {
  479. item.text = item.label;
  480. });
  481. if (this.selectItem.nodeList.length === 1) {
  482. this.selectItem.node_id = this.selectItem.nodeList[0].id;
  483. }
  484. if (this.selectItem.users.length <= 0) {
  485. load.startLoading();
  486. await listUser({
  487. pageSize: 999999
  488. }).then(response => {
  489. this.selectItem.users = response.data.list;
  490. });
  491. load.endLoading();
  492. }
  493. this.dialogVisible = true;
  494. },
  495. async getUserInfo() {
  496. await queryUserInfo().then(res => {
  497. // console.log(res);
  498. if (res.code == 200) {
  499. this.userIds = res.data.id;
  500. this.tenantId = res.data.tenantId;
  501. } else {
  502. this.$message.error(res.data);
  503. }
  504. });
  505. },
  506. async getProcessNodeList() {
  507. await processStructure({
  508. processId: this.processId,
  509. workOrderId: this.workOrderId,
  510. userId: this.userIds
  511. }).then(response => {
  512. let tempData = response.data.tpls;
  513. // 获取对应模板中,下拉框的key, value
  514. let selectList = this.getSelectValueObject(tempData);
  515. // 获取对应模板中,需要隐藏的字段
  516. let hiddenFormList = this.getSelectValueObject(
  517. tempData,
  518. "hiddenForm",
  519. selectList
  520. );
  521. tempData.forEach((temp, index) => {
  522. let tempList = temp.form_structure.list || [];
  523. tempList.forEach(item => {
  524. if (hiddenFormList[index].length > 0) {
  525. if (item.type != "text" && !item.options.relationStatus) {
  526. item.hidden = true;
  527. } else {
  528. item.hidden = false;
  529. }
  530. // item.hidden = false
  531. if (hiddenFormList[index].includes(item.model)) {
  532. item.hidden = false;
  533. }
  534. } else {
  535. item.hidden = false;
  536. }
  537. // 子表单
  538. if (item.type == "subform") {
  539. let childList = item.columns || [];
  540. let subFormStatus = true;
  541. childList.forEach(child => {
  542. let childList = child.list || [];
  543. childList.forEach(c => {
  544. if (hiddenFormList[index].length > 0) {
  545. if (c.type != "text" && !c.options.relationStatus) {
  546. c.hidden = true;
  547. } else {
  548. c.hidden = false;
  549. subFormStatus = false;
  550. }
  551. if (hiddenFormList[index].includes(c.model)) {
  552. c.hidden = false;
  553. subFormStatus = false;
  554. }
  555. } else {
  556. c.hidden = false;
  557. subFormStatus = false;
  558. }
  559. });
  560. });
  561. item.hidden = subFormStatus;
  562. }
  563. });
  564. });
  565. this.isActiveProcessing = false;
  566. this.processStructureValue = response.data;
  567. this.is_end = this.processStructureValue.workOrder.is_end;
  568. this.circulationHistoryList = this.processStructureValue.circulationHistory;
  569. this.circulationList = JSON.parse(
  570. JSON.stringify(this.circulationHistoryList)
  571. );
  572. this.circulationHistoryList.forEach(item => {
  573. const file = item.file_url ? JSON.parse(item.file_url) : [];
  574. const tempFile = {
  575. image: [],
  576. file: []
  577. };
  578. // console.log(file)
  579. file.forEach(item => {
  580. if (item.type == "image") {
  581. tempFile.image.push(item.url);
  582. } else if (item.type == "file") {
  583. tempFile.file.push(item);
  584. }
  585. });
  586. item.fileUrl = tempFile;
  587. });
  588. this.circulationList.forEach(item => {
  589. const file = item.file_url ? JSON.parse(item.file_url) : [];
  590. const tempFile = {
  591. image: [],
  592. file: []
  593. };
  594. // console.log(file)
  595. file.forEach(item => {
  596. if (item.type == "image") {
  597. tempFile.image.push(item.url);
  598. } else if (item.type == "file") {
  599. tempFile.file.push(item);
  600. }
  601. });
  602. item.fileUrl = tempFile;
  603. });
  604. // console.log(this.circulationHistoryList, "circulationHistoryList");
  605. // 获取当前展示节点列表
  606. // this.nodeStepList = this.processStructureValue.circulationHistory
  607. // 获取当前展示节点列表
  608. this.nodeStepList = [];
  609. let nodes = this.processStructureValue.nodes;
  610. this.principals = "处理中";
  611. for (var i = 0; i < nodes.length; i++) {
  612. // console.log(
  613. // nodes[i].id,
  614. // this.processStructureValue.workOrder.current_state,
  615. // "xji"
  616. // );
  617. if (
  618. nodes[i].id === this.processStructureValue.workOrder.current_state
  619. ) {
  620. // 当前节点
  621. this.nodeStepList.push(nodes[i]);
  622. this.activeIndex = this.nodeStepList.length - 1;
  623. if (i + 1 === nodes.length) {
  624. this.activeIndex = this.nodeStepList.length;
  625. }
  626. this.currentNode = nodes[i];
  627. // 处理是认谁在处理,已处理完成则显示处理中
  628. const assignUsers = nodes[i].assignUsers;
  629. if (assignUsers && assignUsers.length > 0) {
  630. this.principals = assignUsers[0].username + "处理中";
  631. }
  632. } else if (!nodes[i].isHideNode) {
  633. // 非隐藏节点
  634. this.nodeStepList.push(nodes[i]);
  635. }
  636. // 判断节点里面是否有结束节点,而且一个流程里面只能有一个结束结点,
  637. if (nodes[i].clazz == "end") {
  638. this.endNodeDetail = JSON.parse(JSON.stringify(nodes[i]));
  639. this.endNodeDetail.target = nodes[i].id;
  640. this.endNodeDetail.flowProperties = 0; // 拒绝属性
  641. this.endNodeDetail.label = "拒绝";
  642. }
  643. }
  644. this.circulationList.reverse();
  645. // 如果审批流程没有结束则,流程和历史记录合并显示;结束了,就只显示历史记录
  646. if (!this.processStructureValue.workOrder.is_end) {
  647. this.circulationList.forEach(cir => {
  648. this.nodeStepList.forEach(node => {
  649. if (cir.source == node.id) {
  650. cir.label = node.label;
  651. cir.assignType = node.assignType;
  652. cir.assignValue = node.assignValue;
  653. cir.assignUsers = node.assignUsers;
  654. cir.id = node.id;
  655. }
  656. });
  657. });
  658. let tempNodes = [];
  659. this.nodeStepList.forEach(node => {
  660. let count = 0;
  661. this.circulationList.forEach(cir => {
  662. if (node.id === cir.source) {
  663. count += 1;
  664. }
  665. });
  666. if (count <= 0) {
  667. tempNodes.push(node);
  668. }
  669. });
  670. this.circulationList.push(...tempNodes);
  671. this.circulationList.forEach((cir, index) => {
  672. if (cir.id == this.processStructureValue.workOrder.current_state) {
  673. this.activeIndex = index;
  674. if (index + 1 == this.circulationList.length) {
  675. this.activeIndex = this.circulationList.length;
  676. }
  677. }
  678. });
  679. } else {
  680. this.activeIndex = this.circulationList.length;
  681. }
  682. // 添加抄送状态
  683. this.circulationList.forEach(res => {
  684. res.ccStatus = true;
  685. });
  686. // console.log(this.nodeStepList);
  687. // console.log(this.circulationList, "this.circulationList");
  688. // if(this.processStructureValue.nodes) {
  689. // for (var i = 0; i < this.processStructureValue.nodes.length; i++) {
  690. // if (this.processStructureValue.nodes[i].id === this.processStructureValue.workOrder.current_state) {
  691. // // 当前节点
  692. // this.nodeStepList.push(this.processStructureValue.nodes[i])
  693. // this.activeIndex = this.nodeStepList.length - 1
  694. // if (i + 1 === this.processStructureValue.nodes.length) {
  695. // this.activeIndex = this.nodeStepList.length
  696. // }
  697. // this.currentNode = this.processStructureValue.nodes[i]
  698. // } else if (!this.processStructureValue.nodes[i].isHideNode) {
  699. // // 非隐藏节点
  700. // this.nodeStepList.push(this.processStructureValue.nodes[i])
  701. // }
  702. // }
  703. // }
  704. // 如果回退到初始节点则可编辑。
  705. if (this.activeIndex === 0 && this.currentNode.clazz === "start") {
  706. this.currentNode.writeTpls = [];
  707. for (var tplTmp of this.processStructureValue.tpls) {
  708. this.currentNode.writeTpls.push(tplTmp.form_structure.id);
  709. }
  710. }
  711. // 判断是否需要主动处理
  712. for (var stateValue of this.processStructureValue.workOrder.state) {
  713. if (
  714. this.processStructureValue.workOrder.current_state ===
  715. stateValue.id &&
  716. stateValue.processor.length > 1
  717. ) {
  718. this.isActiveProcessing = true;
  719. break;
  720. }
  721. }
  722. // const nodes = this.processStructureValue.nodes;
  723. // for (var i = 0; i < nodes.length; i++) {
  724. // // 判断节点里面是否有结束节点,而且一个流程里面只能有一个结束结点,
  725. // if (nodes[i].clazz == "end") {
  726. // this.endNodeDetail = JSON.parse(JSON.stringify(nodes[i]));
  727. // this.endNodeDetail.target = nodes[i].id;
  728. // this.endNodeDetail.flowProperties = 0; // 拒绝属性
  729. // this.endNodeDetail.label = "拒绝";
  730. // }
  731. // }
  732. let psv = response.data.edges || [];
  733. let btn_group = [];
  734. psv.forEach(item => {
  735. // 过滤其它类型的操作
  736. if (
  737. this.processStructureValue.workOrder.is_end === 0 &&
  738. item.source === this.currentNode.id &&
  739. item.flowProperties == 1
  740. ) {
  741. if (item.flowProperties == 1) {
  742. item.className = "primary";
  743. item.labelShow = "同意";
  744. } else if (item.flowProperties == 0) {
  745. item.className = "danger";
  746. } else if (item.flowProperties == 2) {
  747. item.className = "primary";
  748. }
  749. btn_group.push(item);
  750. } else {
  751. item.className = "primary";
  752. }
  753. });
  754. this.btn_group = btn_group;
  755. this.isLoadingStatus = false;
  756. // console.log(this.circulationList, "circulationList");
  757. // console.log(this.currentNode, "currentNode ");
  758. this.getAlertMessage();
  759. });
  760. },
  761. getSelectValueObject(tpls, type = "value", tplValues = []) {
  762. const tempData = tpls || [];
  763. let selectList = [];
  764. tempData.forEach((temp, index) => {
  765. let tempList = temp.form_structure.list || [];
  766. let tempSelectList = tplValues[index] || [];
  767. let listArray = [];
  768. tempList.forEach(list => {
  769. if (list.type == "select") {
  770. if (type == "value") {
  771. const result = this.getFormDataDetail(temp.form_data, list.model);
  772. if (result.status) {
  773. listArray.push(result);
  774. }
  775. } else {
  776. let selectOptions = [];
  777. let selectValue = [];
  778. tempSelectList.forEach(tsl => {
  779. if (tsl.model == list.model) {
  780. selectOptions = list.options.options || [];
  781. selectValue = tsl.value || [];
  782. }
  783. });
  784. selectOptions.forEach(so => {
  785. if (selectValue.includes(so.value)) {
  786. let tempRo = so.relationOptions || [];
  787. listArray.push(...tempRo);
  788. }
  789. });
  790. }
  791. }
  792. if (list.type == "subform") {
  793. let childList = list.columns || [];
  794. childList.forEach(child => {
  795. let childList = child.list || [];
  796. childList.forEach(c => {
  797. if (c.type == "select") {
  798. if (type == "value") {
  799. const originObj = JSON.parse(JSON.stringify(c));
  800. const result = this.getFormDataDetail(
  801. temp.form_data,
  802. originObj.model
  803. );
  804. if (result.status) {
  805. listArray.push(result);
  806. }
  807. } else {
  808. let selectOptions = [];
  809. let selectValue = [];
  810. tempSelectList.forEach(tsl => {
  811. if (tsl.model == c.model) {
  812. selectOptions = c.options.options || [];
  813. selectValue = tsl.value || [];
  814. }
  815. });
  816. selectOptions.forEach(so => {
  817. if (selectValue.includes(so.value)) {
  818. let tempRo = so.relationOptions || [];
  819. listArray.push(...tempRo);
  820. }
  821. });
  822. }
  823. }
  824. });
  825. });
  826. }
  827. });
  828. selectList.push(listArray);
  829. });
  830. return selectList;
  831. },
  832. // 获取对应元素的值
  833. getFormDataDetail(formData, model) {
  834. let modelStatus = {
  835. status: false,
  836. value: null
  837. };
  838. for (let data in formData) {
  839. if (typeof formData[data] == "object") {
  840. // 没有子表单里面有子表单
  841. for (let child in formData[data]) {
  842. if (child == model) {
  843. modelStatus = {
  844. status: true,
  845. model: child,
  846. value: formData[data][child]
  847. ? formData[data][child].split(",")
  848. : []
  849. };
  850. }
  851. }
  852. } else {
  853. if (data == model) {
  854. modelStatus = {
  855. status: true,
  856. model: data,
  857. value: formData[data] ? formData[data].split(",") : []
  858. };
  859. }
  860. }
  861. }
  862. return modelStatus;
  863. },
  864. submitAction(item) {
  865. var promiseList = [];
  866. this.tpls = [];
  867. for (var tpl of this.processStructureValue.tpls) {
  868. this.tpls.push({
  869. tplDataId: tpl.id,
  870. tplId: tpl.form_structure.id
  871. });
  872. promiseList.push(this.$refs["generateForm-" + tpl.id][0].getData());
  873. }
  874. console.log({
  875. tasks: this.processStructureValue.process.task,
  876. source_state: this.processStructureValue.workOrder.current_state,
  877. target_state: item.target,
  878. circulation: item.label,
  879. flow_properties:
  880. item.flowProperties === undefined ? 2 : parseInt(item.flowProperties),
  881. work_order_id: parseInt(this.$route.query.workOrderId),
  882. remarks: this.dataList.remarks,
  883. fileUrl: JSON.stringify(this.fileUrl || []),
  884. tpls: this.tpls
  885. });
  886. const flow =
  887. item.flowProperties === undefined ? 2 : parseInt(item.flowProperties);
  888. let str = "同意";
  889. if (flow == 1) {
  890. str = "同意";
  891. this.submitTitle = "确认同意";
  892. this.submitType = "argee";
  893. } else if (flow == 0) {
  894. str = "拒绝";
  895. this.submitTitle = "确认拒绝";
  896. this.submitType = "reject";
  897. } else {
  898. str = "操作";
  899. this.submitTitle = "操作";
  900. this.submitType = "operation";
  901. }
  902. const tips = `您是否${str}此审批?`;
  903. // this.$confirm(tips, "提示", {
  904. // confirmButtonText: "确定",
  905. // cancelButtonText: "取消",
  906. // type: "warning"
  907. // }).then(() => {
  908. Promise.all(promiseList).then(values => {
  909. for (var tplDataIndex in this.tpls) {
  910. this.tpls[tplDataIndex].tplValue = values[tplDataIndex];
  911. }
  912. let fileList = [];
  913. this.tpls &&
  914. this.tpls.forEach(tpl => {
  915. for (let val in tpl.tplValue) {
  916. if (val.indexOf("file") != -1) {
  917. const file = tpl.tplValue[val] || [];
  918. file.forEach(item => {
  919. fileList.push(item.url);
  920. });
  921. }
  922. }
  923. });
  924. this.submitItem = {
  925. tasks: this.processStructureValue.process.task,
  926. source_state: this.processStructureValue.workOrder.current_state,
  927. target_state: item.target,
  928. circulation: item.label,
  929. flow_properties:
  930. item.flowProperties === undefined
  931. ? 2
  932. : parseInt(item.flowProperties),
  933. work_order_id: parseInt(this.$route.query.workOrderId),
  934. tpls: this.tpls,
  935. fileList,
  936. tips
  937. };
  938. this.dialogSubmit = true;
  939. });
  940. // });
  941. },
  942. // 获取提示消息
  943. getAlertMessage() {
  944. if (this.processStructureValue.workOrder.is_end === 1) {
  945. this.alertMessage = "当前工单已结束。";
  946. }
  947. },
  948. // activeOrderActive() {
  949. // var jsonData = [{
  950. // id: this.nodeStepList[this.activeIndex].id,
  951. // label: this.nodeStepList[this.activeIndex].label,
  952. // process_method: 'person',
  953. // processor: [this.userId]
  954. // }]
  955. // activeOrder(jsonData, this.$route.query.workOrderId).then(() => {
  956. // this.getProcessNodeList()
  957. // })
  958. // },
  959. async getAllOrgan() {
  960. await queryAllOrgan({ tenantId: this.tenantId }).then(res => {
  961. if (res.code == 200) {
  962. const result = res.data;
  963. const filterOrganId = [
  964. 36,
  965. 39,
  966. 41,
  967. 42,
  968. 43,
  969. 44,
  970. 45,
  971. 46,
  972. 47,
  973. 48,
  974. 49,
  975. 50,
  976. 52,
  977. 54,
  978. 55,
  979. 56
  980. ];
  981. let tempOrgan = [];
  982. // 过滤不会显示的分部
  983. result.forEach(item => {
  984. if (!filterOrganId.includes(item.id)) {
  985. tempOrgan.push(item);
  986. }
  987. });
  988. this.organList = tempOrgan;
  989. }
  990. });
  991. },
  992. dataModelFormatBr(str) {
  993. return str ? str.replace(/\n/g, "<br />") : str;
  994. },
  995. formatIcon(item, index, type) {
  996. // 格式化ICON
  997. // console.log(item, index)
  998. // console.log(this.activeIndex)
  999. if (this.activeIndex >= index) {
  1000. if (item.circulation == "转交") {
  1001. return "icon-transfer";
  1002. } else if (this.activeIndex == index) {
  1003. return "icon-wait";
  1004. } else if (item.status == 0) {
  1005. return "el-icon-error";
  1006. } else {
  1007. return "el-icon-success";
  1008. }
  1009. }
  1010. // #fd803a
  1011. return "";
  1012. }
  1013. }
  1014. };
  1015. </script>
  1016. <style lang="scss" scoped>
  1017. /deep/ .el-step__title {
  1018. font-size: 13px;
  1019. line-height: 1.3;
  1020. width: 100%;
  1021. padding-top: 10px;
  1022. padding-right: 10px;
  1023. }
  1024. // /deep/.el-step__icon.is-text {
  1025. // border: 0;
  1026. // }
  1027. .step-title {
  1028. color: #000;
  1029. font-size: 16px;
  1030. }
  1031. .apply-time {
  1032. font-size: #999;
  1033. color: #999;
  1034. padding-left: 10px;
  1035. }
  1036. .apply-status {
  1037. line-height: 1.5;
  1038. color: #999;
  1039. margin: 5px 0;
  1040. }
  1041. .remarks {
  1042. background: #f5f5f5;
  1043. padding: 8px;
  1044. color: #323233;
  1045. border-radius: 6px;
  1046. line-height: 1.5;
  1047. }
  1048. .imgUploader {
  1049. background: #f5f5f5;
  1050. margin-top: 8px;
  1051. padding: 8px;
  1052. border-radius: 6px;
  1053. .el-image {
  1054. vertical-align: middle;
  1055. }
  1056. }
  1057. .fileUploader {
  1058. margin-top: 8px;
  1059. background: #f5f5f5;
  1060. padding: 6px;
  1061. border-radius: 4px;
  1062. }
  1063. /deep/.icon-transfer,
  1064. /deep/.icon-wait {
  1065. display: flex;
  1066. align-items: center;
  1067. box-sizing: content-box;
  1068. background-color: #fff;
  1069. padding: 2px 0;
  1070. height: 23px;
  1071. &::before {
  1072. content: " ";
  1073. display: inline-block;
  1074. width: 23px;
  1075. height: 23px;
  1076. background: url("../../../assets/system-transfer.png") no-repeat center;
  1077. background-size: contain;
  1078. }
  1079. }
  1080. /deep/.icon-wait {
  1081. &::before {
  1082. content: " ";
  1083. display: inline-block;
  1084. width: 23px;
  1085. height: 23px;
  1086. background: url("../../../assets/system-wait.png") no-repeat center;
  1087. background-size: contain;
  1088. }
  1089. }
  1090. .large-icon {
  1091. /deep/.el-timeline-item__node--large {
  1092. top: -8px;
  1093. left: -7px;
  1094. width: 24px;
  1095. height: 24px;
  1096. background-color: transparent;
  1097. }
  1098. /deep/.el-icon-success,
  1099. /deep/.el-icon-error {
  1100. font-size: 24px;
  1101. color: #22b4a9;
  1102. background-color: #fff;
  1103. padding: 2px 0;
  1104. }
  1105. /deep/.el-icon-error {
  1106. color: #ff2e2e;
  1107. }
  1108. }
  1109. </style>