details.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. <template>
  2. <div class="content-height p20">
  3. <div class="page-title">
  4. <PageHeader title="调拨详情"> </PageHeader>
  5. </div>
  6. <div>
  7. <StatusStep :activeCode="infoData.auditStatus" :statusList="statusList" />
  8. <div class="content-detail mt10">
  9. <div class="basic-details">
  10. <HeaderTitle title="基本信息" size="16px"></HeaderTitle>
  11. </div>
  12. <div class="mt20">
  13. <el-form label-width="110px">
  14. <el-col :span="8">
  15. <el-form-item label="调拨名称">
  16. <span>{{ infoData.name }}</span>
  17. </el-form-item>
  18. </el-col>
  19. <el-col :span="8">
  20. <el-form-item label="调拨单号">
  21. <span>{{ infoData.allotCode }}</span>
  22. </el-form-item>
  23. </el-col>
  24. <el-col :span="8">
  25. <el-form-item label="创建人">
  26. <span>{{ infoData.allotName }}</span>
  27. </el-form-item>
  28. </el-col>
  29. <el-col :span="8">
  30. <el-form-item label="当前审核人">
  31. <span>{{ infoData.currentApproverName || '-' }}</span>
  32. </el-form-item>
  33. </el-col>
  34. <el-col :span="8">
  35. <el-form-item label="创建时间">
  36. <span>{{ infoData.createTime }}</span>
  37. </el-form-item>
  38. </el-col>
  39. <el-col :span="8">
  40. <el-form-item label="调拨类型">
  41. <span>{{
  42. allocationType.filter((item) => item.code == infoData.type)[0]
  43. ?.label
  44. }}</span>
  45. </el-form-item>
  46. </el-col>
  47. <el-col :span="8">
  48. <el-form-item label="列表维度">
  49. <span>{{
  50. dimensionType.filter((item) => item.code == infoData.inventoryDimension)[0]
  51. ?.label
  52. }}</span>
  53. </el-form-item>
  54. </el-col>
  55. <el-col :span="8">
  56. <el-form-item label="调出库">
  57. <span>{{ infoData.sourceWarehouse }}</span>
  58. </el-form-item>
  59. </el-col>
  60. <el-col :span="8">
  61. <el-form-item label="调入库">
  62. <span>{{ infoData.targetWarehouse }}</span>
  63. </el-form-item>
  64. </el-col>
  65. </el-form>
  66. </div>
  67. </div>
  68. <div class="content-detail mt20">
  69. <HeaderTitle title="调拨明细" size="16px"></HeaderTitle>
  70. <div class="mt20">
  71. <ele-pro-table
  72. ref="table"
  73. :columns="columns"
  74. :datasource="detailList"
  75. :height="300"
  76. :needPage="false"
  77. :cache-key="cacheKeyUrl"
  78. @columns-change="handleColumnChange"
  79. />
  80. </div>
  81. </div>
  82. <div v-if="infoData.type == 2" class="content-detail process-detail mt20">
  83. <HeaderTitle title="流程图" size="16px"></HeaderTitle>
  84. <div class="process-viewer">
  85. <my-process-viewer
  86. key="designer"
  87. v-model="bpmnXML"
  88. v-bind="bpmnControlForm"
  89. :activityData="activityList"
  90. :processInstanceData="processInstance"
  91. :taskData="tasks"
  92. />
  93. </div>
  94. </div>
  95. </div>
  96. </div>
  97. </template>
  98. <script>
  99. import storageApi from '@/api/warehouseManagement/index.js';
  100. import AssetsCell from './components/AssetsCell';
  101. import {
  102. getProcessInstance,
  103. getTaskListByProcessInstanceId,
  104. getProcessDefinitionBpmnXML,
  105. getActivityList
  106. } from '@/api/bpm/index';
  107. // import { getDetail } from '@/api/stockManagement/inventoryAllocation'
  108. import PageHeader from '@/components/PageHeader';
  109. import { allocationType, dimensionType } from '@/utils/dict/warehouse';
  110. import { useDictLabelFilter } from '@/utils/dict';
  111. import StatusStep from '@/components/StatusStep/index.vue';
  112. import tabMixins from '@/mixins/tableColumnsMixin';
  113. export default {
  114. components: { AssetsCell, StatusStep, PageHeader },
  115. mixins: [tabMixins],
  116. data() {
  117. return {
  118. cacheKeyUrl: '202605131648-wms-inventoryAllocationDetails',
  119. allocationType,
  120. dimensionType,
  121. auditStatus: [
  122. { code: 0, label: '未提交', class: 'danger-text' },
  123. { code: 1, label: '审核中', class: 'primary-text' },
  124. { code: 2, label: '已完成', class: 'primary-text' },
  125. { code: 3, label: '已驳回', class: 'danger-text' }
  126. ],
  127. detailList: [],
  128. infoData: {},
  129. // 流程实例
  130. id: undefined, // 流程实例的编号
  131. processInstance: {},
  132. // BPMN 数据
  133. bpmnXML: null,
  134. bpmnControlForm: {
  135. prefix: 'flowable'
  136. },
  137. activityList: [],
  138. // 审批记录
  139. tasksLoad: true,
  140. tasks: []
  141. };
  142. },
  143. created() {
  144. this._getDetail();
  145. },
  146. filters: {
  147. dictFilter: useDictLabelFilter
  148. },
  149. computed: {
  150. statusList() {
  151. const base = [{ label: '创建' }];
  152. /* 库外 */
  153. if (this.infoData.type == 2) {
  154. base.push({ code: 1, label: '审核中' });
  155. }
  156. if (this.infoData.auditStatus == 0) {
  157. base.push({ code: 0, label: '未提交', activeColor: '#cc3300' });
  158. } else {
  159. if ([2].includes(this.infoData.auditStatus)) {
  160. base.push({ code: 2, label: '已完成', activeColor: '#157a2c' });
  161. }
  162. if ([3].includes(this.infoData.auditStatus)) {
  163. base.push({ code: 3, label: '已驳回', activeColor: '#cc3300' });
  164. }
  165. }
  166. console.log(base, 'base');
  167. return base;
  168. },
  169. columns() {
  170. const baseColumns = [
  171. {
  172. columnKey: 'index',
  173. label: '序号',
  174. type: 'index',
  175. width: 55,
  176. align: 'center',
  177. showOverflowTooltip: true
  178. },
  179. {
  180. prop: 'categoryCode',
  181. label: '物品编码',
  182. align: 'center',
  183. showOverflowTooltip: true,
  184. minWidth: 110
  185. },
  186. {
  187. prop: 'categoryName',
  188. label: '物品名称',
  189. align: 'center',
  190. showOverflowTooltip: true,
  191. minWidth: 120
  192. },
  193. {
  194. prop: 'batchNo',
  195. label: '批次号',
  196. align: 'center',
  197. showOverflowTooltip: true,
  198. minWidth: 110,
  199. hide: this.infoData.inventoryDimension == 1
  200. },
  201. {
  202. prop: 'systemBatchNo',
  203. label: '系统内部批次号',
  204. align: 'center',
  205. showOverflowTooltip: true,
  206. minWidth: 180,
  207. hide: this.infoData.inventoryDimension == 1,
  208. formatter: (row) => row.systemBatchNo || '-'
  209. },
  210. {
  211. prop: 'warehouseName',
  212. label: '调出仓库',
  213. align: 'center',
  214. showOverflowTooltip: true,
  215. minWidth: 120
  216. },
  217. {
  218. prop: 'areaName',
  219. label: '调出库区',
  220. align: 'center',
  221. showOverflowTooltip: true,
  222. minWidth: 110
  223. },
  224. {
  225. prop: 'goodsShelfName',
  226. label: '调出货架',
  227. align: 'center',
  228. showOverflowTooltip: true,
  229. minWidth: 110
  230. },
  231. {
  232. prop: 'goodsAllocationName',
  233. label: '调出货位',
  234. align: 'center',
  235. showOverflowTooltip: true,
  236. minWidth: 110
  237. },
  238. {
  239. prop: 'targetWarehouseName',
  240. label: '调入仓库',
  241. align: 'center',
  242. showOverflowTooltip: true,
  243. minWidth: 120
  244. },
  245. {
  246. prop: 'targetAreaName',
  247. label: '调入库区',
  248. align: 'center',
  249. showOverflowTooltip: true,
  250. minWidth: 110
  251. },
  252. {
  253. prop: 'targetGoodsShelfName',
  254. label: '调入货架',
  255. align: 'center',
  256. showOverflowTooltip: true,
  257. minWidth: 110
  258. },
  259. {
  260. prop: 'targetGoodsAllocationName',
  261. label: '调入货位',
  262. align: 'center',
  263. showOverflowTooltip: true,
  264. minWidth: 110
  265. },
  266. {
  267. prop: 'brandNum',
  268. label: '牌号',
  269. align: 'center',
  270. showOverflowTooltip: true,
  271. minWidth: 100
  272. },
  273. {
  274. prop: 'categoryModel',
  275. label: '型号',
  276. align: 'center',
  277. showOverflowTooltip: true,
  278. minWidth: 110
  279. },
  280. {
  281. prop: 'specification',
  282. label: '规格',
  283. align: 'center',
  284. showOverflowTooltip: true,
  285. minWidth: 110
  286. },
  287. {
  288. prop: 'colorKey',
  289. label: '颜色',
  290. align: 'center',
  291. showOverflowTooltip: true,
  292. minWidth: 100
  293. },
  294. {
  295. prop: 'modeKey',
  296. label: '机型',
  297. align: 'center',
  298. showOverflowTooltip: true,
  299. minWidth: 100
  300. },
  301. {
  302. prop: 'packageNo',
  303. label: '包装编码',
  304. align: 'center',
  305. showOverflowTooltip: true,
  306. minWidth: 120,
  307. hide: this.infoData.inventoryDimension != 3
  308. },
  309. {
  310. prop: 'packingQuantity',
  311. label: '包装数量',
  312. align: 'center',
  313. showOverflowTooltip: true,
  314. minWidth: 100,
  315. hide: this.infoData.inventoryDimension != 3
  316. },
  317. {
  318. prop: 'packingUnit',
  319. label: '包装单位',
  320. align: 'center',
  321. showOverflowTooltip: true,
  322. minWidth: 100,
  323. hide: this.infoData.inventoryDimension != 3
  324. },
  325. // {
  326. // prop: 'measureQuantity',
  327. // label: '计量数量',
  328. // align: 'center',
  329. // showOverflowTooltip: true,
  330. // minWidth: 100
  331. // },
  332. {
  333. prop: 'quantity',
  334. label: '调拨数量',
  335. align: 'center',
  336. showOverflowTooltip: true,
  337. minWidth: 100
  338. },
  339. {
  340. prop: 'measureUnit',
  341. label: '计量单位',
  342. align: 'center',
  343. showOverflowTooltip: true,
  344. minWidth: 100
  345. },
  346. {
  347. prop: 'weight',
  348. label: '重量',
  349. align: 'center',
  350. showOverflowTooltip: true,
  351. minWidth: 100
  352. },
  353. {
  354. prop: 'weightUnit',
  355. label: '重量单位',
  356. align: 'center',
  357. showOverflowTooltip: true,
  358. minWidth: 100
  359. }
  360. ];
  361. return baseColumns.filter((item) => !item.hide);
  362. }
  363. },
  364. methods: {
  365. /** 获得流程实例 */
  366. getDetail(id) {
  367. // 获得流程实例相关
  368. this.processInstanceLoading = true;
  369. getProcessInstance(id).then((response) => {
  370. if (!response) {
  371. this.$message.error('查询不到流程信息!');
  372. return;
  373. }
  374. // 设置流程信息
  375. this.processInstance = response;
  376. // //将业务表单,注册为动态组件
  377. // const path = this.processInstance.processDefinition.formCustomViewPath;
  378. // Vue.component("async-biz-form-component", function (resolve) {
  379. // require([`@/views${path}`], resolve);
  380. // });
  381. // 加载流程图
  382. getProcessDefinitionBpmnXML(
  383. this.processInstance.processDefinition.id
  384. ).then((response) => {
  385. this.bpmnXML = response;
  386. });
  387. // 加载活动列表
  388. getActivityList({
  389. processInstanceId: this.processInstance.id
  390. }).then((response) => {
  391. console.log(response, 'response');
  392. this.activityList = response;
  393. });
  394. // 取消加载中
  395. this.processInstanceLoading = false;
  396. });
  397. // 获得流程任务列表(审批记录)
  398. this.tasksLoad = true;
  399. getTaskListByProcessInstanceId(id).then((response) => {
  400. // 审批记录
  401. this.tasks = [];
  402. // 移除已取消的审批
  403. response.forEach((task) => {
  404. if (task.result !== 4) {
  405. this.tasks.push(task);
  406. }
  407. });
  408. // 排序,将未完成的排在前面,已完成的排在后面;
  409. this.tasks.sort((a, b) => {
  410. // 有已完成的情况,按照完成时间倒序
  411. if (a.endTime && b.endTime) {
  412. return b.endTime - a.endTime;
  413. } else if (a.endTime) {
  414. return 1;
  415. } else if (b.endTime) {
  416. return -1;
  417. // 都是未完成,按照创建时间倒序
  418. } else {
  419. return b.createTime - a.createTime;
  420. }
  421. });
  422. // 需要审核的记录
  423. const userId = this.$store.getters.user.info.userId;
  424. this.tasks.forEach((task) => {
  425. if (task.result !== 1 && task.result !== 6) {
  426. // 只有待处理才需要
  427. return;
  428. }
  429. if (!task.assigneeUser || task.assigneeUser.id !== userId) {
  430. // 自己不是处理人
  431. return;
  432. }
  433. });
  434. // 取消加载中
  435. this.tasksLoad = false;
  436. });
  437. },
  438. async _getDetail() {
  439. const res = await storageApi.getAllotDetailList({
  440. applyId: this.$route.query.id
  441. });
  442. const data = await storageApi.getAllotDetail(this.$route.query.id);
  443. this.infoData = data;
  444. this.getDetail(data.flowableTaskId);
  445. if (this.infoData.type == 1) {
  446. // 库内调拨
  447. /* this.infoData.auditStatus = 2; */
  448. this.infoData.auditStatus = data.status;
  449. } else {
  450. // 库外调拨
  451. this.infoData.auditStatus = data.status;
  452. }
  453. this.detailList = res.map((item) => {
  454. return {
  455. ...item,
  456. // categoryCode: this.infoData.categoryCode,
  457. // categoryName: this.infoData.categoryName,
  458. // brandNum: this.infoData.brandNum,
  459. // categoryModel: this.infoData.model,
  460. // specification: this.infoData.specification
  461. };
  462. });
  463. // if (res?.success) {
  464. // this.infoData = res.data.conventionalStockTransfer;
  465. // this.detailList = res.data.stockTransferInfoList.map((i) => ({
  466. // batchNum: i.batchNo,
  467. // ...i
  468. // }));
  469. // }
  470. }
  471. }
  472. };
  473. </script>
  474. <style lang="scss" scoped>
  475. :deep(.el-form-item) {
  476. margin-bottom: 0 !important;
  477. }
  478. .p20 {
  479. padding: 20px;
  480. }
  481. .mt40 {
  482. margin-top: 40px;
  483. }
  484. .mt20 {
  485. margin-top: 20px;
  486. }
  487. .content-detail {
  488. overflow: hidden;
  489. }
  490. .process-detail {
  491. height: 450px;
  492. }
  493. .process-viewer {
  494. height: calc(100% - 40px);
  495. }
  496. .content-height {
  497. height: auto;
  498. background: #fff;
  499. }
  500. </style>