index.vue 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088
  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: "AfterSales",
  651. });
  652. }
  653. }
  654. };
  655. let queryData = reactive({
  656. data: {},
  657. });
  658. // 记录
  659. const recordList = ref([]);
  660. const fileIds = ref([]);
  661. const fileObj = ref({});
  662. const approvalRecordData = ref({
  663. buttonInfoList: [],
  664. });
  665. const getRecords = (_id) => {
  666. if (_id) {
  667. proxy
  668. .post("/flowExample/getApprovalRecord", {
  669. id: _id,
  670. })
  671. .then((res) => {
  672. recordList.value = res.recordList;
  673. queryData.data.recordList = res.recordList;
  674. approvalRecordData.value = res;
  675. fileIds.value = res.recordList.map((item) => {
  676. return item.flowExampleDetailId;
  677. });
  678. proxy
  679. .post("fileInfo/getList", { businessIdList: fileIds.value })
  680. .then((res2) => {
  681. console.log(res2);
  682. fileObj.value = res2;
  683. });
  684. console.log(fileObj.value);
  685. });
  686. } else {
  687. proxy
  688. .post("/flowExample/getFlowNode", {
  689. flowKey: flowForm.flowKey,
  690. })
  691. .then((res) => {
  692. recordList.value = res;
  693. });
  694. }
  695. };
  696. const isShowSubmitDom = ref(true);
  697. const chartDom = ref(null);
  698. const chartData = ref([]);
  699. let myChart = null;
  700. const optionTwo = reactive({
  701. data: {
  702. tooltip: {
  703. trigger: "axis",
  704. },
  705. // legend: {
  706. // data: ["价格"],
  707. // },
  708. grid: {
  709. left: "3%",
  710. right: "6%",
  711. top: "10%",
  712. bottom: "3%",
  713. containLabel: true,
  714. },
  715. tooltip: {
  716. show: true,
  717. trigger: "axis",
  718. // 格式化函数
  719. // valueFormatter: (val) => {
  720. // return val + "aaa";
  721. // },
  722. formatter: (params, ticket, callback) => {
  723. return `
  724. ${params[0].axisValue}
  725. <br/>
  726. ${params[0].seriesName}:${params[0].data}
  727. <br/> 毛利率:${chartData.value[params[0].dataIndex].grossRate}%
  728. <br/> 对比上一版本利润:CNY ${
  729. chartData.value[params[0].dataIndex].compareLastGross
  730. }
  731. <br/> 销售合同金额:${
  732. chartData.value[params[0].dataIndex].contractCurrency
  733. } ${chartData.value[params[0].dataIndex].contractAmount}
  734. <br/> 采购合同金额:CNY ${
  735. chartData.value[params[0].dataIndex].purchaseAmount
  736. }`;
  737. },
  738. textStyle: {
  739. fontSize: 12,
  740. },
  741. },
  742. // toolbox: {
  743. // feature: {
  744. // saveAsImage: {},
  745. // },
  746. // },
  747. xAxis: {
  748. type: "category",
  749. boundaryGap: false,
  750. data: [],
  751. },
  752. yAxis: {
  753. type: "value",
  754. },
  755. series: [
  756. {
  757. name: "毛利",
  758. type: "line",
  759. data: [],
  760. },
  761. ],
  762. },
  763. });
  764. const showChart = ref(false);
  765. onMounted(async () => {
  766. if (
  767. (userInfo.roles.includes("ceo") ||
  768. userInfo.roles.includes("salesDirector") ||
  769. userInfo.roles.includes("financeOfficer") ||
  770. userInfo.roles.includes("approve_ accountant")) &&
  771. (route.query.processType == 10 || route.query.processType == 30) &&
  772. route.query.flowKey != "after_sales_flow"
  773. ) {
  774. showChart.value = true;
  775. }
  776. // 路由进入
  777. if (route.query && route.query.flowKey) {
  778. //processType 10 为修改 20为查看 30回退发起
  779. if (route.query.processType == 20) {
  780. activeName.value = "second";
  781. isShowSubmitDom.value = false;
  782. }
  783. if (
  784. route.query.processType == 10 ||
  785. route.query.processType == 20 ||
  786. route.query.processType == 30
  787. ) {
  788. // await proxy
  789. // .post("/flowProcess/getStartData", { flowId: route.query.id })
  790. // .then((res) => {
  791. // queryData.data = { ...res };
  792. // });
  793. } else {
  794. queryData.data = { ...route.query };
  795. }
  796. flowForm.flowKey = route.query.flowKey;
  797. flowForm.tenantType = route.query.tenantType;
  798. flowForm.submitType = route.query.submitType;
  799. getRecords(route.query.id);
  800. }
  801. $bus.on("getGrossData", (data) => {
  802. nextTick(() => {
  803. if (data && data.length > 1 && showChart.value) {
  804. myChart = echarts.init(chartDom.value);
  805. window.addEventListener("resize", () => {
  806. myChart.resize();
  807. });
  808. chartData.value = data;
  809. // chartData.value = data.slice(1, data.length);
  810. optionTwo.data.xAxis.data = chartData.value.map((item) => {
  811. return item.createTime.slice(0, 10);
  812. });
  813. optionTwo.data.series[0].data = chartData.value.map((item) => {
  814. return item.gross;
  815. });
  816. myChart.setOption(optionTwo.data);
  817. myChart.resize();
  818. } else {
  819. return;
  820. }
  821. });
  822. });
  823. });
  824. onBeforeUnmount(() => {
  825. // 取消订阅特定事件
  826. $bus.off("getGrossData");
  827. });
  828. watch(
  829. () => props.query,
  830. () => {
  831. if (props.query) {
  832. if (props.query.processType == 20) {
  833. isShowSubmitDom.value = false;
  834. activeName.value = "second";
  835. }
  836. if (
  837. props.query.processType == 10 ||
  838. props.query.processType == 20 ||
  839. props.query.processType == 30
  840. ) {
  841. // await proxy
  842. // .post("/flowProcess/getStartData", { flowId: props.query.id })
  843. // .then((res) => {
  844. // queryData.data = { ...res };
  845. // });
  846. queryData.data = { ...props.query };
  847. } else {
  848. queryData.data = { ...props.query };
  849. }
  850. flowForm.flowKey = props.query.flowKey;
  851. flowForm.tenantType = props.query.tenantType;
  852. flowForm.submitType = props.query.submitType;
  853. getRecords(props.query.id);
  854. }
  855. },
  856. {
  857. deep: true,
  858. immediate: true,
  859. }
  860. );
  861. const getFlowName = () => {
  862. let name = "流程(审批)";
  863. if (route.query && route.query.flowName) {
  864. name = route.query.flowName;
  865. } else if (props.query && props.query.flowName) {
  866. name = props.query.flowName;
  867. }
  868. return name;
  869. };
  870. // 动态计算高度
  871. const processApprovalDom = ref(null);
  872. const flowChartDom = ref(null);
  873. const getTableHeight = () => {
  874. if (route.query.currentContractId) {
  875. processApprovalDom.value.style.height = window.innerHeight - 180 + "px";
  876. flowChartDom.value.style.height = window.innerHeight - 250 + "px";
  877. } else {
  878. processApprovalDom.value.style.height = window.innerHeight - 130 + "px";
  879. flowChartDom.value.style.height = window.innerHeight - 200 + "px";
  880. }
  881. };
  882. nextTick(() => {
  883. getTableHeight();
  884. });
  885. window.addEventListener("resize", () => {
  886. getTableHeight();
  887. });
  888. </script>
  889. <style>
  890. /* .el-upload-list {
  891. float: left;
  892. margin: 0 !important;
  893. }
  894. .el-upload-list li {
  895. width: 200px;
  896. margin-left: 10px;
  897. }
  898. .el-upload--text {
  899. float: left;
  900. } */
  901. </style>
  902. <style lang="scss" scoped>
  903. .processApproval {
  904. display: flex;
  905. justify-content: space-between;
  906. margin-top: 20px;
  907. padding: 0 20px;
  908. height: calc(100vh - 130px);
  909. .left-card {
  910. // background: #fff;
  911. border-radius: 4px;
  912. // padding: 20px;
  913. // flex: 1;
  914. width: calc(100% - 350px - 10px);
  915. margin-right: 10px;
  916. display: flex;
  917. flex-direction: column;
  918. .top {
  919. /* 宽度和高度 */
  920. flex: 1;
  921. overflow-y: auto;
  922. background: #fff;
  923. padding: 20px 20px 0px 20px;
  924. .line {
  925. border-bottom: 1px solid #ddd;
  926. margin-bottom: 20px;
  927. }
  928. }
  929. .bottom {
  930. margin-top: 10px;
  931. height: 220px;
  932. background: #fff;
  933. padding: 20px 20px 0px 20px;
  934. overflow: auto;
  935. }
  936. }
  937. .right-card {
  938. background: #fff;
  939. border-radius: 4px;
  940. // padding: 0 20px 20px;
  941. padding: 0 20px 5px;
  942. width: 350px;
  943. box-sizing: border-box;
  944. .flow-chart {
  945. overflow: auto;
  946. height: calc(100vh - 200px);
  947. padding: 0;
  948. margin: 0;
  949. li {
  950. margin: 0;
  951. padding: 0 0 20px;
  952. list-style: none;
  953. display: flex;
  954. justify-content: space-between;
  955. position: relative;
  956. .right-conetnt {
  957. flex: 1;
  958. .name {
  959. font-size: 12px;
  960. color: #39c55a;
  961. margin-bottom: 10px;
  962. span {
  963. color: #999;
  964. }
  965. }
  966. .time {
  967. float: right;
  968. }
  969. .remark {
  970. padding: 10px;
  971. color: #666666;
  972. font-size: 12px;
  973. background: #f1f1f1;
  974. border-radius: 2px;
  975. .label {
  976. color: #999;
  977. margin-bottom: 10px;
  978. }
  979. }
  980. }
  981. .left-icon {
  982. width: 40px;
  983. height: 40px;
  984. text-align: center;
  985. line-height: 40px;
  986. background: #0084ff;
  987. border-radius: 10px;
  988. color: #fff;
  989. font-size: 20px;
  990. position: relative;
  991. margin-right: 27px;
  992. z-index: 2;
  993. .right-btm-status {
  994. position: absolute;
  995. bottom: 0px;
  996. right: -10px;
  997. height: 20px;
  998. width: 20px;
  999. line-height: 16px;
  1000. border-radius: 10px;
  1001. background: #39c55a;
  1002. border: 2px solid #fff;
  1003. font-size: 12px;
  1004. box-sizing: border-box;
  1005. }
  1006. }
  1007. }
  1008. li::before {
  1009. content: "";
  1010. position: absolute;
  1011. top: 0;
  1012. left: 20px;
  1013. width: 2px;
  1014. height: 100%;
  1015. background: #ddd;
  1016. z-index: 1;
  1017. }
  1018. li:last-child::before {
  1019. display: none;
  1020. }
  1021. .flow-orange {
  1022. .right-btm-status {
  1023. background: #ff9a00 !important;
  1024. }
  1025. .name {
  1026. color: #ff9a00 !important;
  1027. }
  1028. .left-icon {
  1029. background: #ff9a00 !important;
  1030. }
  1031. }
  1032. .flow-grey {
  1033. .right-btm-status {
  1034. background: #999 !important;
  1035. }
  1036. .name {
  1037. color: #999 !important;
  1038. }
  1039. .left-icon {
  1040. background: #999 !important;
  1041. }
  1042. }
  1043. .flow-red {
  1044. .right-btm-status {
  1045. background: #ff4d4f !important;
  1046. }
  1047. .name {
  1048. color: #ff4d4f !important;
  1049. }
  1050. .left-icon {
  1051. background: #ff4d4f !important;
  1052. }
  1053. }
  1054. }
  1055. }
  1056. }
  1057. </style>