index.vue 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096
  1. <template>
  2. <div class="processApproval" ref="processApprovalDom">
  3. <div class="left-card">
  4. <div class="top">
  5. <div class="commons-title title">
  6. {{ getFlowName() }}
  7. </div>
  8. <div class="line"></div>
  9. <!-- 报价单 -->
  10. <template v-if="flowForm.flowKey == 'sale_quotation_flow'">
  11. <PriceSheetEHSD ref="makeDom" :queryData="queryData.data"></PriceSheetEHSD>
  12. </template>
  13. <!-- 样品单 -->
  14. <template v-else-if="flowForm.flowKey == 'sample_flow'">
  15. <SampleEHSD ref="makeDom" :queryData="queryData.data"></SampleEHSD>
  16. </template>
  17. <!-- 样品单变更 -->
  18. <template v-else-if="flowForm.flowKey == 'sample_update_flow'">
  19. <SampleChangeEHSD ref="makeDom" :queryData="queryData.data"></SampleChangeEHSD>
  20. </template>
  21. <!-- 销售合同 -->
  22. <template v-else-if="flowForm.flowKey == 'contract_flow'">
  23. <ContractEHSD ref="makeDom" :queryData="queryData.data" @auxiliaryChange="(e) => getAuxiliaryData(e)"></ContractEHSD>
  24. </template>
  25. <!-- 售后 -->
  26. <AfterSales ref="makeDom" :queryData="queryData.data" v-else-if="flowForm.flowKey == 'after_sales_flow'">
  27. </AfterSales>
  28. <!-- 销售合同变更 -->
  29. <template v-else-if="flowForm.flowKey == 'contract_update_flow'">
  30. <ContractChangeEHSD ref="makeDom" :queryData="queryData.data" @auxiliaryChange="(e) => getAuxiliaryData(e)"></ContractChangeEHSD>
  31. </template>
  32. <!-- 申购 -->
  33. <SendSubscribe ref="makeDom" @auxiliaryChange="(e) => getAuxiliaryData(e)" v-else-if="flowForm.flowKey == 'subscribe_flow'"
  34. :queryData="queryData.data"></SendSubscribe>
  35. <!-- 样品单采购、交接单采购 -->
  36. <template v-else-if="flowForm.flowKey == 'ehsd_purchase_flow'">
  37. <PurchaseEHSD ref="makeDom" :queryData="queryData.data" v-if="flowForm.submitType === '10'" @auxiliaryChange="(e) => getAuxiliaryData(e)">
  38. </PurchaseEHSD>
  39. <!-- <SendPurchase
  40. ref="makeDom"
  41. :queryData="queryData.data"
  42. v-else
  43. @auxiliaryChange="(e) => getAuxiliaryData(e)"
  44. ></SendPurchase> -->
  45. </template>
  46. <template v-else-if="flowForm.flowKey == 'purchase_flow'">
  47. <SendPurchase ref="makeDom" :queryData="queryData.data" @auxiliaryChange="(e) => getAuxiliaryData(e)"></SendPurchase>
  48. </template>
  49. <PurchaseChangeEHSD ref="makeDom" :queryData="queryData.data" v-else-if="flowForm.flowKey == 'ehsd_purchase_update_flow'"
  50. @auxiliaryChange="(e) => getAuxiliaryData(e)"></PurchaseChangeEHSD>
  51. <!-- 采购付款 -->
  52. <PurchasePayment ref="makeDom" @auxiliaryChange="(e) => getAuxiliaryData(e)" v-else-if="flowForm.flowKey == 'pay_flow'"
  53. :queryData="queryData.data"></PurchasePayment>
  54. <!-- 请款 -->
  55. <SendFunds ref="makeDom" v-else-if="flowForm.flowKey == 'account_request_funds_flow'" :queryData="queryData.data"></SendFunds>
  56. <!-- 取消到账认领 -->
  57. <CancelClaim ref="makeDom" v-else-if="flowForm.flowKey == 'claim_del_flow'" :queryData="queryData.data"></CancelClaim>
  58. </div>
  59. <!-- <div class="bottom" v-if="isShowSubmitDom">
  60. <div class="commons-title title">处理意见</div>
  61. <el-form :model="flowForm" :rules="flowRules" ref="flowFormDom">
  62. <el-form-item prop="remark" label-width="0px" label="">
  63. <el-input
  64. type="textarea"
  65. placeholder="请输入"
  66. v-model="flowForm.remark"
  67. >
  68. </el-input>
  69. </el-form-item>
  70. <el-form-item prop="remark" label-width="80px" label="附件上传">
  71. <el-upload
  72. v-model:fileList="flowForm.fileList"
  73. :action="uploadUrl"
  74. :data="uploadData"
  75. multiple
  76. :before-upload="uploadFile"
  77. :on-success="handleSuccess"
  78. :on-preview="onPreviewFile"
  79. >
  80. <el-button>选择</el-button>
  81. </el-upload>
  82. </el-form-item>
  83. <el-form-item>
  84. <el-button
  85. type="primary"
  86. v-if="approvalRecordData.buttonInfoList.length == 0"
  87. @click="handleSubmit"
  88. :loading="btnLoading"
  89. >提交</el-button
  90. >
  91. <el-button
  92. type="primary"
  93. v-else
  94. v-for="i in approvalRecordData.buttonInfoList"
  95. :key="i.type"
  96. :loading="btnLoading"
  97. @click="handleSubmit(i.type)"
  98. >{{ i.name }}</el-button
  99. >
  100. </el-form-item>
  101. </el-form>
  102. </div> -->
  103. </div>
  104. <div class="right-card">
  105. <el-tabs v-model="activeName" class="demo-tabs">
  106. <el-tab-pane label="处理意见" name="first" v-if="isShowSubmitDom">
  107. <div style="overflow: auto; height: calc(100vh - 200px)">
  108. <div style="padding-bottom:50px" v-if="showChart">
  109. <div style="margin-bottom:10px;">
  110. <TitleInfo :content="'利润走势图'"></TitleInfo>
  111. </div>
  112. <div ref="chartDom" style="height:150px"></div>
  113. </div>
  114. <div style="margin-bottom:10px">
  115. <TitleInfo :content="'办理'"></TitleInfo>
  116. </div>
  117. <el-form :model="flowForm" :rules="flowRules" ref="flowFormDom">
  118. <el-form-item prop="remark" label-width="0px" label="">
  119. <el-input type="textarea" placeholder="请输入" :rows="3" v-model="flowForm.remark">
  120. </el-input>
  121. </el-form-item>
  122. <el-form-item prop="remark" label-width="80px" label="附件上传">
  123. <div style="width:100%">
  124. <el-upload v-model:fileList="flowForm.fileList" :action="uploadUrl" :data="uploadData" multiple :before-upload="uploadFile"
  125. :on-success="handleSuccess" :on-preview="onPreviewFile">
  126. <el-button>选择</el-button>
  127. </el-upload>
  128. </div>
  129. </el-form-item>
  130. <el-form-item>
  131. <div v-if="approvalRecordData.buttonInfoList.length == 0">
  132. <el-button type="primary" @click="handleSubmit" :loading="btnLoading">提交</el-button>
  133. <el-button type="primary" v-if="StagFlowKey.includes(flowForm.flowKey)" @click="handleSubmitStag"
  134. :loading="btnLoading">暂存</el-button>
  135. </div>
  136. <el-button type="primary" v-else v-for="i in approvalRecordData.buttonInfoList" :key="i.type" :loading="btnLoading"
  137. @click="handleSubmit(i.type)" style="margin-bottom:10px">{{ i.name }}</el-button>
  138. </el-form-item>
  139. </el-form>
  140. </div>
  141. </el-tab-pane>
  142. <el-tab-pane label="审批记录" name="second">
  143. <ul class="flow-chart" ref="flowChartDom">
  144. <li v-for="item in recordList" :key="item.id" :class="
  145. !route.query.id
  146. ? ''
  147. : item.status == 2
  148. ? 'flow-orange'
  149. : item.status == 3 && !route.query.id
  150. ? 'flow-orange'
  151. : item.status == 3 && route.query.id
  152. ? 'flow-grey'
  153. : ''
  154. ">
  155. <div class="left-icon">
  156. <i class="iconfont icon-iconm_daick"></i>
  157. <i class="iconfont icon-icomx_quertj1 right-btm-status"></i>
  158. </div>
  159. <div class="right-conetnt">
  160. <div class="name">{{ item.nodeName }}</div>
  161. <div class="remark">
  162. <div class="label">
  163. <span v-if="item.status != 3">办理人:</span>{{ item.processedUser
  164. }}<span class="time">{{ item.processedDate }}</span>
  165. </div>
  166. {{ item.remark }}
  167. <div v-for="j in fileObj[item.flowExampleDetailId]" v-if="fileObj[item.flowExampleDetailId]">
  168. <a @click="proxy.download(j.fileUrl, j.fileName)" style="color: #409eff; line-height: 30px">{{ j.fileName }}</a>
  169. </div>
  170. </div>
  171. </div>
  172. <div class="line"></div>
  173. </li>
  174. </ul>
  175. </el-tab-pane>
  176. <!-- <el-tab-pane label="决策辅助" name="three" v-if="auxiliaryData.length > 0">
  177. <div style="overflow: auto; height: calc(100vh - 200px)">
  178. <auxiliary :data="auxiliaryData"></auxiliary>
  179. </div>
  180. </el-tab-pane> -->
  181. </el-tabs>
  182. </div>
  183. <el-dialog title="下一处理人" width="400" v-model="dialogVisible" v-if="dialogVisible" :show-close="false" :close-on-click-modal="false"
  184. :close-on-press-escape="false">
  185. <el-form :model="flowForm">
  186. <el-form-item prop="remark" label="处理人">
  187. <el-select v-model="flowForm.handleUserId" placeholder="请选择" filterable style="width: 100%">
  188. <el-option v-for="item in nextHandleUser" :label="item.nickName" :value="item.userId">
  189. </el-option>
  190. </el-select>
  191. </el-form-item>
  192. <el-form-item>
  193. <div style="width: 100%; text-align: center">
  194. <el-button type="primary" @click="handleSelectUser">提交</el-button>
  195. </div>
  196. </el-form-item>
  197. </el-form>
  198. </el-dialog>
  199. </div>
  200. </template>
  201. <script setup name="ProcessApproval">
  202. import useTagsViewStore from "@/store/modules/tagsView.js";
  203. import { useRouter, useRoute } from "vue-router";
  204. // 消息提示
  205. import { ElMessage, ElMessageBox } from "element-plus";
  206. //决策辅助
  207. import auxiliary from "./auxiliary";
  208. // 报价单-EHSD
  209. import PriceSheetEHSD from "@/components/process/EHSD/PriceSheet";
  210. // 销售合同-EHSD
  211. import ContractEHSD from "@/components/process/EHSD/Contract";
  212. // 销售合同变更-EHSD
  213. import ContractChangeEHSD from "@/components/process/EHSD/ContractChange";
  214. // 样品单-EHSD
  215. import SampleEHSD from "@/components/process/EHSD/Sample";
  216. // 样品单变更-EHSD
  217. import SampleChangeEHSD from "@/components/process/EHSD/SampleChange";
  218. // 采购交接单-EHSD
  219. import PurchaseEHSD from "@/components/process/EHSD/Purchase";
  220. // 采购交接单-EHSD
  221. import PurchaseChangeEHSD from "@/components/process/EHSD/PurchaseChange";
  222. // 取消认领-EHSD
  223. import CancelClaim from "@/components/process/EHSD/CancelClaim";
  224. // 售后管理-EHSD
  225. import AfterSales from "@/components/process/EHSD/AfterSales";
  226. //申购发起
  227. import SendSubscribe from "@/components/process/SendSubscribe";
  228. //采购发起
  229. import SendPurchase from "@/components/process/SendPurchase";
  230. //请款发起
  231. import SendFunds from "@/components/process/SendFunds";
  232. // 采购付款
  233. import PurchasePayment from "@/components/process/PurchasePayment";
  234. import { computed, nextTick, ref, watch } from "vue";
  235. import useUserStore from "@/store/modules/user";
  236. const userInfo = useUserStore();
  237. import $bus from "@/bus/index.js";
  238. import * as echarts from "echarts";
  239. import TitleInfo from "@/components/TitleInfo/index.vue";
  240. const router = useRouter();
  241. const route = useRoute();
  242. // 传参
  243. const props = defineProps({
  244. query: Object,
  245. });
  246. // tab切换逻辑
  247. const activeName = ref("first");
  248. let auxiliaryData = ref([]);
  249. const getAuxiliaryData = (data) => {
  250. auxiliaryData.value = data;
  251. };
  252. const btnLoading = ref(false);
  253. // 意见表单
  254. const flowForm = reactive({
  255. flowKey: "",
  256. tenantType: "",
  257. handleUserId: "",
  258. remark: "",
  259. data: {},
  260. fileList: [],
  261. });
  262. const uploadData = ref({});
  263. const flowRules = reactive({
  264. // remark: [{ required: true, message: "请输入处理意见", trigger: "blur" }],
  265. });
  266. //组件实例
  267. const { proxy } = getCurrentInstance();
  268. const makeDom = ref(null);
  269. const flowFormDom = ref(null);
  270. let dialogVisible = ref(false);
  271. const nextHandleUser = ref([]);
  272. const handleType = ref(null);
  273. const handleSelectUser = () => {
  274. if (!flowForm.handleUserId) {
  275. return ElMessage({
  276. message: "请选择下一节点处理人!",
  277. type: "info",
  278. });
  279. }
  280. handleSubmit(handleType.value);
  281. };
  282. const handleResult = (res) => {
  283. if (res.userList == null && res.success) {
  284. skipPage();
  285. } else if (res.userList && res.userList.length > 0) {
  286. dialogVisible.value = true;
  287. nextHandleUser.value = res.userList;
  288. } else {
  289. return ElMessage({
  290. message: "请联系管理员!",
  291. type: "info",
  292. });
  293. }
  294. };
  295. const uploadFile = async (file) => {
  296. const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
  297. uploadData.value = res.uploadBody;
  298. file.id = res.id;
  299. file.fileName = res.fileName;
  300. file.fileUrl = res.fileUrl;
  301. file.uploadState = true;
  302. return true;
  303. };
  304. const handleSuccess = (any, UploadFile) => {
  305. UploadFile.raw.uploadState = false;
  306. };
  307. const onPreviewFile = (file) => {
  308. window.open(file.raw.fileUrl, "_blank");
  309. };
  310. const StagFlowKey = ref(["after_sales_flow"]);
  311. // 暂存
  312. const handleSubmitStag = async (_type) => {
  313. try {
  314. // 调用发起组件的提交事件
  315. const flag = await makeDom.value.handleSubmit(true);
  316. if (flag) {
  317. flowFormDom.value.validate((valid) => {
  318. btnLoading.value = true;
  319. if (valid) {
  320. const data = { ...makeDom.value.getFormData() };
  321. flowForm.fileList = flowForm.fileList.map((item) => {
  322. return {
  323. ...item,
  324. ...item.raw,
  325. };
  326. });
  327. if (flowForm.flowKey == "after_sales_flow") {
  328. proxy.post("/afterSales/add", data).then(
  329. (res) => {
  330. skipPage();
  331. },
  332. (err) => {
  333. btnLoading.value = false;
  334. }
  335. );
  336. }
  337. }
  338. });
  339. }
  340. } catch (err) {
  341. console.log("数据未填完整!", err);
  342. }
  343. };
  344. // 提交逻辑
  345. const handleSubmit = async (_type) => {
  346. handleType.value = _type ? _type : undefined;
  347. try {
  348. // 调用发起组件的提交事件
  349. const flag = await makeDom.value.handleSubmit();
  350. if (flag) {
  351. flowFormDom.value.validate((valid) => {
  352. btnLoading.value = true;
  353. if (valid) {
  354. const data = { ...makeDom.value.getFormData() };
  355. if (flowForm.flowKey == "subscribe_flow") {
  356. } else if (flowForm.flowKey == "account_request_funds_flow") {
  357. } else if (flowForm.flowKey == "sale_quotation_flow") {
  358. if (flowForm.tenantType === "EHSD") {
  359. data.ehsdJson = JSON.stringify({
  360. deliveryTime: data.deliveryTime,
  361. });
  362. data.quotationProductList = data.quotationProductList.map(
  363. (item) => {
  364. let ehsdJson = JSON.stringify({
  365. packMethod: item.packMethod,
  366. tradeMethods: item.tradeMethods,
  367. });
  368. return {
  369. ...item,
  370. ehsdJson: ehsdJson,
  371. };
  372. }
  373. );
  374. }
  375. } else if (flowForm.flowKey == "contract_flow") {
  376. // data.dataJson = JSON.stringify(proxy.deepClone(data));
  377. if (data.fileList && data.fileList.length > 0) {
  378. data.fileList = data.fileList.map((item) => {
  379. return {
  380. id: item.raw.id,
  381. fileName: item.raw.fileName,
  382. fileUrl: item.raw.fileUrl,
  383. };
  384. });
  385. } else {
  386. data.fileList = [];
  387. }
  388. if (data.packageFileList && data.packageFileList.length > 0) {
  389. data.packageFileList = data.packageFileList.map((item) => {
  390. return {
  391. id: item.raw.id,
  392. fileName: item.raw.fileName,
  393. fileUrl: item.raw.fileUrl,
  394. };
  395. });
  396. } else {
  397. data.packageFileList = [];
  398. }
  399. data.ehsdJson = JSON.stringify({
  400. deliveryTime: data.deliveryTime,
  401. });
  402. data.contractProductList = data.contractProductList.map((item) => {
  403. let ehsdJson = JSON.stringify({
  404. packMethod: item.packMethod,
  405. tradeMethods: item.tradeMethods,
  406. });
  407. return {
  408. ...item,
  409. ehsdJson: ehsdJson,
  410. };
  411. });
  412. } else if (flowForm.flowKey == "contract_update_flow") {
  413. // data.dataJson = JSON.stringify(proxy.deepClone(data));
  414. if (data.fileList && data.fileList.length > 0) {
  415. data.fileList = data.fileList.map((item) => {
  416. return {
  417. id: item.raw.id,
  418. fileName: item.raw.fileName,
  419. fileUrl: item.raw.fileUrl,
  420. };
  421. });
  422. } else {
  423. data.fileList = [];
  424. }
  425. if (data.packageFileList && data.packageFileList.length > 0) {
  426. data.packageFileList = data.packageFileList.map((item) => {
  427. return {
  428. id: item.raw.id,
  429. fileName: item.raw.fileName,
  430. fileUrl: item.raw.fileUrl,
  431. };
  432. });
  433. } else {
  434. data.packageFileList = [];
  435. }
  436. data.ehsdJson = JSON.stringify({
  437. deliveryTime: data.deliveryTime,
  438. });
  439. data.contractProductList = data.contractProductList.map((item) => {
  440. let ehsdJson = JSON.stringify({
  441. packMethod: item.packMethod,
  442. tradeMethods: item.tradeMethods,
  443. });
  444. return {
  445. ...item,
  446. ehsdJson: ehsdJson,
  447. };
  448. });
  449. } else if (flowForm.flowKey == "sample_flow") {
  450. // data.dataJson = JSON.stringify(proxy.deepClone(data));
  451. if (data.fileList && data.fileList.length > 0) {
  452. data.fileList = data.fileList.map((item) => {
  453. return {
  454. id: item.raw.id,
  455. fileName: item.raw.fileName,
  456. fileUrl: item.raw.fileUrl,
  457. };
  458. });
  459. } else {
  460. data.fileList = [];
  461. }
  462. if (data.packageFileList && data.packageFileList.length > 0) {
  463. data.packageFileList = data.packageFileList.map((item) => {
  464. return {
  465. id: item.raw.id,
  466. fileName: item.raw.fileName,
  467. fileUrl: item.raw.fileUrl,
  468. };
  469. });
  470. } else {
  471. data.packageFileList = [];
  472. }
  473. data.ehsdJson = JSON.stringify({
  474. deliveryTime: data.deliveryTime,
  475. });
  476. data.sampleProductList = data.sampleProductList.map((item) => {
  477. let ehsdJson = JSON.stringify({
  478. packMethod: item.packMethod,
  479. tradeMethods: item.tradeMethods,
  480. });
  481. return {
  482. ...item,
  483. ehsdJson: ehsdJson,
  484. };
  485. });
  486. } else if (flowForm.flowKey == "sample_update_flow") {
  487. // data.dataJson = JSON.stringify(proxy.deepClone(data));
  488. if (data.fileList && data.fileList.length > 0) {
  489. data.fileList = data.fileList.map((item) => {
  490. return {
  491. id: item.raw.id,
  492. fileName: item.raw.fileName,
  493. fileUrl: item.raw.fileUrl,
  494. };
  495. });
  496. } else {
  497. data.fileList = [];
  498. }
  499. if (data.packageFileList && data.packageFileList.length > 0) {
  500. data.packageFileList = data.packageFileList.map((item) => {
  501. return {
  502. id: item.raw.id,
  503. fileName: item.raw.fileName,
  504. fileUrl: item.raw.fileUrl,
  505. };
  506. });
  507. } else {
  508. data.packageFileList = [];
  509. }
  510. data.ehsdJson = JSON.stringify({
  511. deliveryTime: data.deliveryTime,
  512. });
  513. data.sampleProductList = data.sampleProductList.map((item) => {
  514. let ehsdJson = JSON.stringify({
  515. packMethod: item.packMethod,
  516. tradeMethods: item.tradeMethods,
  517. });
  518. return {
  519. ...item,
  520. ehsdJson: ehsdJson,
  521. };
  522. });
  523. }
  524. flowForm.fileList = flowForm.fileList.map((item) => {
  525. return {
  526. ...item,
  527. ...item.raw,
  528. };
  529. });
  530. if (route.query.processType == 10 || route.query.processType == 30) {
  531. // if (_type && _type == 1) {
  532. // proxy
  533. // .post("/flowExample/setStartData", {
  534. // exampleId: route.query.id,
  535. // startData: data,
  536. // })
  537. // .then();
  538. // }
  539. proxy
  540. .post("/flowProcess/jump", {
  541. ...flowForm,
  542. data,
  543. handleType: _type,
  544. version: route.query.version,
  545. flowId: route.query.id,
  546. skipSetData: true,
  547. })
  548. .then(
  549. (res) => {
  550. handleResult(res);
  551. },
  552. (err) => {
  553. btnLoading.value = false;
  554. }
  555. );
  556. return;
  557. } else {
  558. proxy
  559. .post("/flowProcess/initiate", {
  560. ...flowForm,
  561. data,
  562. skipSetData: true,
  563. })
  564. .then(
  565. (res) => {
  566. handleResult(res);
  567. },
  568. (err) => {
  569. btnLoading.value = false;
  570. }
  571. );
  572. }
  573. }
  574. });
  575. }
  576. } catch (err) {
  577. console.log("数据未填完整!", err);
  578. setTimeout(() => {
  579. const errorDiv = document.getElementsByClassName("is-error");
  580. errorDiv[0].scrollIntoView({
  581. behavior: "smooth",
  582. block: "center",
  583. inline: "nearest",
  584. });
  585. }, 0);
  586. }
  587. };
  588. // 页面跳转
  589. const skipPage = () => {
  590. const useTagsStore = useTagsViewStore();
  591. useTagsStore.delVisitedView(router.currentRoute.value);
  592. if (route.query.processType) {
  593. router.replace({
  594. path: "/oa/1/backlog",
  595. });
  596. } else {
  597. ElMessage({
  598. message: "操作成功!",
  599. type: "success",
  600. });
  601. if (flowForm.flowKey == "subscribe_flow") {
  602. router.replace({
  603. path: "/ehsd/procurement/subscribe",
  604. });
  605. } else if (flowForm.flowKey == "purchase_flow") {
  606. router.replace({
  607. name: "Purchase",
  608. });
  609. } else if (flowForm.flowKey == "account_request_funds_flow") {
  610. router.replace({
  611. path: "/ehsd/fundManage/funds",
  612. });
  613. } else if (flowForm.flowKey == "pay_flow") {
  614. router.replace({
  615. path: "/ehsd/purchasePayment/payment",
  616. });
  617. } else if (flowForm.flowKey == "sale_quotation_flow") {
  618. if (flowForm.tenantType === "EHSD") {
  619. router.replace({
  620. path: "/ehsd/saleContract/quotation",
  621. });
  622. }
  623. } else if (
  624. flowForm.flowKey == "contract_flow" ||
  625. flowForm.flowKey == "contract_update_flow"
  626. ) {
  627. router.replace({
  628. path: "/ehsd/saleContract/contract",
  629. });
  630. } else if (
  631. flowForm.flowKey == "sample_flow" ||
  632. flowForm.flowKey == "sample_update_flow"
  633. ) {
  634. router.replace({
  635. path: "/ehsd/saleContract/sample",
  636. });
  637. } else if (
  638. flowForm.flowKey == "ehsd_purchase_flow" ||
  639. flowForm.flowKey == "ehsd_purchase_update_flow"
  640. ) {
  641. router.replace({
  642. path: "/ehsd/procurement/purchased",
  643. });
  644. } else if (flowForm.flowKey == "claim_del_flow") {
  645. router.replace({
  646. name: "Claim",
  647. });
  648. } else if (flowForm.flowKey == "after_sales_flow") {
  649. router.replace({
  650. name: "C_afterSales",
  651. });
  652. }
  653. }
  654. $bus.emit("refreshTableData");
  655. };
  656. let queryData = reactive({
  657. data: {},
  658. });
  659. // 记录
  660. const recordList = ref([]);
  661. const fileIds = ref([]);
  662. const fileObj = ref({});
  663. const approvalRecordData = ref({
  664. buttonInfoList: [],
  665. });
  666. const getRecords = (_id) => {
  667. if (_id) {
  668. proxy
  669. .post("/flowExample/getApprovalRecord", {
  670. id: _id,
  671. })
  672. .then((res) => {
  673. recordList.value = res.recordList;
  674. queryData.data.recordList = res.recordList;
  675. approvalRecordData.value = res;
  676. fileIds.value = res.recordList.map((item) => {
  677. return item.flowExampleDetailId;
  678. });
  679. proxy
  680. .post("fileInfo/getList", { businessIdList: fileIds.value })
  681. .then((res2) => {
  682. console.log(res2);
  683. fileObj.value = res2;
  684. });
  685. console.log(fileObj.value);
  686. });
  687. } else {
  688. proxy
  689. .post("/flowExample/getFlowNode", {
  690. flowKey: flowForm.flowKey,
  691. })
  692. .then((res) => {
  693. recordList.value = res;
  694. });
  695. }
  696. };
  697. const isShowSubmitDom = ref(true);
  698. const chartDom = ref(null);
  699. const chartData = ref([]);
  700. let myChart = null;
  701. const optionTwo = reactive({
  702. data: {
  703. tooltip: {
  704. trigger: "axis",
  705. },
  706. // legend: {
  707. // data: ["价格"],
  708. // },
  709. grid: {
  710. left: "3%",
  711. right: "6%",
  712. top: "10%",
  713. bottom: "3%",
  714. containLabel: true,
  715. },
  716. tooltip: {
  717. show: true,
  718. trigger: "axis",
  719. // 格式化函数
  720. // valueFormatter: (val) => {
  721. // return val + "aaa";
  722. // },
  723. formatter: (params, ticket, callback) => {
  724. return `
  725. ${params[0].axisValue}
  726. <br/>
  727. ${params[0].seriesName}:${params[0].data}
  728. <br/> 毛利率:${chartData.value[params[0].dataIndex].grossRate}%
  729. <br/> 对比上一版本利润:CNY ${
  730. chartData.value[params[0].dataIndex].compareLastGross
  731. }
  732. <br/> 销售合同金额:${
  733. chartData.value[params[0].dataIndex].contractCurrency
  734. } ${chartData.value[params[0].dataIndex].contractAmount}
  735. <br/> 采购合同金额:CNY ${
  736. chartData.value[params[0].dataIndex].purchaseAmount
  737. }`;
  738. },
  739. textStyle: {
  740. fontSize: 12,
  741. },
  742. },
  743. // toolbox: {
  744. // feature: {
  745. // saveAsImage: {},
  746. // },
  747. // },
  748. xAxis: {
  749. type: "category",
  750. boundaryGap: false,
  751. data: [],
  752. },
  753. yAxis: {
  754. type: "value",
  755. },
  756. series: [
  757. {
  758. name: "毛利",
  759. type: "line",
  760. data: [],
  761. },
  762. ],
  763. },
  764. });
  765. const showChart = ref(false);
  766. onMounted(async () => {
  767. if (
  768. (userInfo.roles.includes("ceo") ||
  769. userInfo.roles.includes("salesDirector") ||
  770. userInfo.roles.includes("financeOfficer") ||
  771. userInfo.roles.includes("approve_ accountant")) &&
  772. (route.query.processType == 10 || route.query.processType == 30) &&
  773. [
  774. "contract_flow",
  775. "contract_update_flow",
  776. "sample_flow",
  777. "sample_update_flow",
  778. "ehsd_purchase_flow",
  779. "ehsd_purchase_update_flow",
  780. ].includes(route.query.flowKey)
  781. ) {
  782. showChart.value = true;
  783. }
  784. // 路由进入
  785. if (route.query && route.query.flowKey) {
  786. //processType 10 为修改 20为查看 30回退发起
  787. if (route.query.processType == 20) {
  788. activeName.value = "second";
  789. isShowSubmitDom.value = false;
  790. }
  791. if (
  792. route.query.processType == 10 ||
  793. route.query.processType == 20 ||
  794. route.query.processType == 30
  795. ) {
  796. // await proxy
  797. // .post("/flowProcess/getStartData", { flowId: route.query.id })
  798. // .then((res) => {
  799. // queryData.data = { ...res };
  800. // });
  801. } else {
  802. queryData.data = { ...route.query };
  803. }
  804. flowForm.flowKey = route.query.flowKey;
  805. flowForm.tenantType = route.query.tenantType;
  806. flowForm.submitType = route.query.submitType;
  807. getRecords(route.query.id);
  808. }
  809. $bus.on("getGrossData", (data) => {
  810. nextTick(() => {
  811. if (data && data.length > 1 && showChart.value) {
  812. myChart = echarts.init(chartDom.value);
  813. window.addEventListener("resize", () => {
  814. myChart.resize();
  815. });
  816. chartData.value = data;
  817. // chartData.value = data.slice(1, data.length);
  818. optionTwo.data.xAxis.data = chartData.value.map((item) => {
  819. return item.createTime.slice(0, 10);
  820. });
  821. optionTwo.data.series[0].data = chartData.value.map((item) => {
  822. return item.gross;
  823. });
  824. myChart.setOption(optionTwo.data);
  825. myChart.resize();
  826. } else {
  827. return;
  828. }
  829. });
  830. });
  831. });
  832. onBeforeUnmount(() => {
  833. // 取消订阅特定事件
  834. $bus.off("getGrossData");
  835. });
  836. watch(
  837. () => props.query,
  838. () => {
  839. if (props.query) {
  840. if (props.query.processType == 20) {
  841. isShowSubmitDom.value = false;
  842. activeName.value = "second";
  843. }
  844. if (
  845. props.query.processType == 10 ||
  846. props.query.processType == 20 ||
  847. props.query.processType == 30
  848. ) {
  849. // await proxy
  850. // .post("/flowProcess/getStartData", { flowId: props.query.id })
  851. // .then((res) => {
  852. // queryData.data = { ...res };
  853. // });
  854. queryData.data = { ...props.query };
  855. } else {
  856. queryData.data = { ...props.query };
  857. }
  858. flowForm.flowKey = props.query.flowKey;
  859. flowForm.tenantType = props.query.tenantType;
  860. flowForm.submitType = props.query.submitType;
  861. getRecords(props.query.id);
  862. }
  863. },
  864. {
  865. deep: true,
  866. immediate: true,
  867. }
  868. );
  869. const getFlowName = () => {
  870. let name = "流程(审批)";
  871. if (route.query && route.query.flowName) {
  872. name = route.query.flowName;
  873. } else if (props.query && props.query.flowName) {
  874. name = props.query.flowName;
  875. }
  876. return name;
  877. };
  878. // 动态计算高度
  879. const processApprovalDom = ref(null);
  880. const flowChartDom = ref(null);
  881. const getTableHeight = () => {
  882. if (route.query.currentContractId) {
  883. processApprovalDom.value.style.height = window.innerHeight - 180 + "px";
  884. flowChartDom.value.style.height = window.innerHeight - 250 + "px";
  885. } else {
  886. processApprovalDom.value.style.height = window.innerHeight - 130 + "px";
  887. flowChartDom.value.style.height = window.innerHeight - 200 + "px";
  888. }
  889. };
  890. nextTick(() => {
  891. getTableHeight();
  892. });
  893. window.addEventListener("resize", () => {
  894. getTableHeight();
  895. });
  896. </script>
  897. <style>
  898. /* .el-upload-list {
  899. float: left;
  900. margin: 0 !important;
  901. }
  902. .el-upload-list li {
  903. width: 200px;
  904. margin-left: 10px;
  905. }
  906. .el-upload--text {
  907. float: left;
  908. } */
  909. </style>
  910. <style lang="scss" scoped>
  911. .processApproval {
  912. display: flex;
  913. justify-content: space-between;
  914. margin-top: 20px;
  915. padding: 0 20px;
  916. height: calc(100vh - 130px);
  917. .left-card {
  918. // background: #fff;
  919. border-radius: 4px;
  920. // padding: 20px;
  921. // flex: 1;
  922. width: calc(100% - 350px - 10px);
  923. margin-right: 10px;
  924. display: flex;
  925. flex-direction: column;
  926. .top {
  927. /* 宽度和高度 */
  928. flex: 1;
  929. overflow-y: auto;
  930. background: #fff;
  931. padding: 20px 20px 0px 20px;
  932. .line {
  933. border-bottom: 1px solid #ddd;
  934. margin-bottom: 20px;
  935. }
  936. }
  937. .bottom {
  938. margin-top: 10px;
  939. height: 220px;
  940. background: #fff;
  941. padding: 20px 20px 0px 20px;
  942. overflow: auto;
  943. }
  944. }
  945. .right-card {
  946. background: #fff;
  947. border-radius: 4px;
  948. // padding: 0 20px 20px;
  949. padding: 0 20px 5px;
  950. width: 350px;
  951. box-sizing: border-box;
  952. .flow-chart {
  953. overflow: auto;
  954. height: calc(100vh - 200px);
  955. padding: 0;
  956. margin: 0;
  957. li {
  958. margin: 0;
  959. padding: 0 0 20px;
  960. list-style: none;
  961. display: flex;
  962. justify-content: space-between;
  963. position: relative;
  964. .right-conetnt {
  965. flex: 1;
  966. .name {
  967. font-size: 12px;
  968. color: #39c55a;
  969. margin-bottom: 10px;
  970. span {
  971. color: #999;
  972. }
  973. }
  974. .time {
  975. float: right;
  976. }
  977. .remark {
  978. padding: 10px;
  979. color: #666666;
  980. font-size: 12px;
  981. background: #f1f1f1;
  982. border-radius: 2px;
  983. .label {
  984. color: #999;
  985. margin-bottom: 10px;
  986. }
  987. }
  988. }
  989. .left-icon {
  990. width: 40px;
  991. height: 40px;
  992. text-align: center;
  993. line-height: 40px;
  994. background: #0084ff;
  995. border-radius: 10px;
  996. color: #fff;
  997. font-size: 20px;
  998. position: relative;
  999. margin-right: 27px;
  1000. z-index: 2;
  1001. .right-btm-status {
  1002. position: absolute;
  1003. bottom: 0px;
  1004. right: -10px;
  1005. height: 20px;
  1006. width: 20px;
  1007. line-height: 16px;
  1008. border-radius: 10px;
  1009. background: #39c55a;
  1010. border: 2px solid #fff;
  1011. font-size: 12px;
  1012. box-sizing: border-box;
  1013. }
  1014. }
  1015. }
  1016. li::before {
  1017. content: "";
  1018. position: absolute;
  1019. top: 0;
  1020. left: 20px;
  1021. width: 2px;
  1022. height: 100%;
  1023. background: #ddd;
  1024. z-index: 1;
  1025. }
  1026. li:last-child::before {
  1027. display: none;
  1028. }
  1029. .flow-orange {
  1030. .right-btm-status {
  1031. background: #ff9a00 !important;
  1032. }
  1033. .name {
  1034. color: #ff9a00 !important;
  1035. }
  1036. .left-icon {
  1037. background: #ff9a00 !important;
  1038. }
  1039. }
  1040. .flow-grey {
  1041. .right-btm-status {
  1042. background: #999 !important;
  1043. }
  1044. .name {
  1045. color: #999 !important;
  1046. }
  1047. .left-icon {
  1048. background: #999 !important;
  1049. }
  1050. }
  1051. .flow-red {
  1052. .right-btm-status {
  1053. background: #ff4d4f !important;
  1054. }
  1055. .name {
  1056. color: #ff4d4f !important;
  1057. }
  1058. .left-icon {
  1059. background: #ff4d4f !important;
  1060. }
  1061. }
  1062. }
  1063. }
  1064. }
  1065. </style>