AssetsDialog.vue 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003
  1. <template>
  2. <ele-modal
  3. :visible.sync="visible"
  4. title="物品信息"
  5. width="80vw"
  6. :maxable="true"
  7. >
  8. <el-form :model="searchForm" label-width="100px">
  9. <el-row :gutter="20">
  10. <el-col :span="6">
  11. <el-form-item label="列表维度:" prop="dimension">
  12. <template>
  13. <el-select
  14. style="width: 100%"
  15. @change="changeDimensionHandler"
  16. @keyup.enter.native="doSearch"
  17. v-model="dimension"
  18. placeholder="请选择"
  19. >
  20. <!-- <el-option label="物料维度" value="4"> </el-option> -->
  21. <el-option label="包装维度" value="3"> </el-option>
  22. <el-option label="批次维度" value="2"> </el-option>
  23. <el-option label="物品维度" value="1"> </el-option>
  24. </el-select>
  25. </template>
  26. </el-form-item>
  27. </el-col>
  28. <el-col :span="6">
  29. <el-form-item label="物品编码:">
  30. <el-input
  31. type="text"
  32. placeholder="搜索物品编码"
  33. v-model="searchForm.categoryCode"
  34. @keyup.enter.native="doSearch"
  35. ></el-input>
  36. </el-form-item>
  37. </el-col>
  38. <el-col :span="6">
  39. <el-form-item label="物品名称:">
  40. <el-input
  41. type="text"
  42. placeholder="搜索物品名称"
  43. v-model="searchForm.categoryName"
  44. @keyup.enter.native="doSearch"
  45. ></el-input>
  46. </el-form-item>
  47. </el-col>
  48. <el-col :span="6">
  49. <el-form-item label="批次号:">
  50. <el-input
  51. type="text"
  52. placeholder="搜索批次号"
  53. v-model="searchForm.batchNo"
  54. @keyup.enter.native="doSearch"
  55. ></el-input>
  56. </el-form-item>
  57. </el-col>
  58. <el-col :span="6" v-if="dimension != 1">
  59. <el-form-item label="系统批次:">
  60. <el-input
  61. clearable
  62. type="text"
  63. placeholder="请输入完整系统内部批次号"
  64. v-model.trim="searchForm.systemBatchNo"
  65. @keyup.enter.native="doSearch"
  66. ></el-input>
  67. </el-form-item>
  68. </el-col>
  69. <el-col :span="6">
  70. <el-form-item label="刻码">
  71. <el-input
  72. type="text"
  73. placeholder="搜索物品刻码"
  74. v-model="searchForm.engrave"
  75. @keyup.enter.native="doSearch"
  76. ></el-input>
  77. </el-form-item>
  78. </el-col>
  79. <el-col :span="6">
  80. <el-form-item label="物料代号">
  81. <el-input
  82. type="text"
  83. placeholder="搜索物料代号"
  84. v-model="searchForm.materielDesignation"
  85. @keyup.enter.native="doSearch"
  86. ></el-input>
  87. </el-form-item>
  88. </el-col>
  89. <el-col :span="6">
  90. <el-form-item label="发货码">
  91. <el-input
  92. type="text"
  93. placeholder="搜索发货码"
  94. v-model="searchForm.barcodes"
  95. @keyup.enter.native="doSearch"
  96. ></el-input>
  97. </el-form-item>
  98. </el-col>
  99. <el-col :span="6">
  100. <el-form-item label="牌号">
  101. <el-input
  102. type="text"
  103. placeholder="搜索牌号"
  104. v-model="searchForm.brandNum"
  105. @keyup.enter.native="doSearch"
  106. ></el-input>
  107. </el-form-item>
  108. </el-col>
  109. <el-col :span="6">
  110. <el-form-item label="所属工厂" prop="factoryId">
  111. <el-select
  112. filterable
  113. placeholder="请选择"
  114. v-model="searchForm.factoryId"
  115. clearable
  116. class="w100"
  117. @keyup.enter.native="doSearch"
  118. @change="getWarehouseListHandle"
  119. >
  120. <el-option
  121. v-for="item in factoryList"
  122. :key="item.id"
  123. :label="item.name"
  124. :value="item.id"
  125. ></el-option>
  126. </el-select>
  127. </el-form-item>
  128. </el-col>
  129. <el-col :span="6">
  130. <el-form-item label="仓库">
  131. <el-select
  132. clearable
  133. style="width: 100%"
  134. v-model="searchForm.warehouseId"
  135. placeholder="请选择"
  136. @keyup.enter.native="doSearch"
  137. >
  138. <el-option
  139. v-for="item in warehouseList"
  140. :label="item.name"
  141. :value="item.id"
  142. :key="item.id"
  143. >
  144. </el-option>
  145. </el-select>
  146. </el-form-item>
  147. </el-col>
  148. <el-col :span="6">
  149. <el-form-item label="关键字">
  150. <el-input
  151. clearable
  152. type="text"
  153. placeholder="请输入"
  154. v-model="searchForm.keyWord"
  155. @keyup.enter.native="doSearch"
  156. ></el-input>
  157. </el-form-item>
  158. </el-col>
  159. <el-col :span="6">
  160. <el-form-item label="颜色">
  161. <el-input
  162. clearable
  163. type="text"
  164. placeholder="请输入"
  165. v-model="searchForm.colorKey"
  166. @keyup.enter.native="doSearch"
  167. ></el-input>
  168. </el-form-item>
  169. </el-col>
  170. <el-col>
  171. <div style="float: right">
  172. <el-button type="primary" @click="doSearch">搜索</el-button>
  173. <el-button icon="el-icon-refresh-left" @click="reset"
  174. >重置</el-button
  175. >
  176. </div>
  177. </el-col>
  178. </el-row>
  179. </el-form>
  180. <el-container class="assets-dialog">
  181. <el-aside width="200px" class="wrapper-assets">
  182. <AssetTree
  183. ref="treeList"
  184. :treeIds="treeIds"
  185. @handleNodeClick="handleNodeClick"
  186. />
  187. </el-aside>
  188. <el-main>
  189. <ele-pro-table
  190. row-key="id"
  191. :selection.sync="selectionList"
  192. ref="table"
  193. class="table"
  194. :columns="columns"
  195. :datasource="datasource"
  196. height="calc(100vh - 550px)"
  197. full-height="calc(100vh - 116px)"
  198. tool-class="ele-toolbar-form"
  199. :pageSize="20"
  200. @columns-change="handleColumnChange"
  201. :cache-key="cacheKeyUrl"
  202. >
  203. <template v-slot:outboundNum="{ row }">
  204. <el-input
  205. type="text"
  206. placeholder="请输入"
  207. v-model="row.outboundNum"
  208. @input="handleInput(row, $event)"
  209. :disabled="inputDisabled(row)"
  210. ></el-input>
  211. </template>
  212. </ele-pro-table>
  213. </el-main>
  214. </el-container>
  215. <div slot="footer">
  216. <el-button type="primary" @click="confirm">确定</el-button>
  217. <el-button @click="cancel">关闭</el-button>
  218. </div>
  219. </ele-modal>
  220. </template>
  221. <script>
  222. import warehouseDefinition from '@/api/warehouseManagement/warehouseDefinition';
  223. import storageApi from '@/api/warehouseManagement';
  224. import AssetTree from '../stockManagement/components/assetTree.vue';
  225. import { getWarehouseList } from '@/api/classifyManage/itemInformation';
  226. import { getDetailById, quantityDelivery } from '@/api/classifyManage';
  227. import tabMixins from '@/mixins/tableColumnsMixin';
  228. export default {
  229. mixins: [tabMixins],
  230. components: { AssetTree },
  231. props: {
  232. treeIds: { type: Array, default: () => [] }
  233. },
  234. data() {
  235. return {
  236. factoryList: [],
  237. newColumns: [], // 动态表头
  238. isShowTable: true,
  239. qualityResultOption: [
  240. {
  241. value: 0,
  242. label: '合格'
  243. },
  244. {
  245. value: 1,
  246. label: '不合格'
  247. }
  248. ],
  249. qualityStatusOption: [
  250. {
  251. value: 1,
  252. label: '已质检'
  253. },
  254. {
  255. value: 0,
  256. label: '未质检'
  257. }
  258. ],
  259. visible: false,
  260. tableData: [],
  261. total: 0,
  262. categoryLevelId: '',
  263. searchForm: {
  264. categoryCode: '',
  265. categoryName: '',
  266. batchNo: '',
  267. systemBatchNo: '',
  268. factoryId: '',
  269. brandNum: '',
  270. engrave: '',
  271. barcodes: '',
  272. categoryLevelId: '',
  273. warehouseId: '',
  274. pageNum: 1,
  275. size: 20,
  276. colorKey: ''
  277. },
  278. selectionList: [],
  279. materialType: '',
  280. warehouseList: [],
  281. allWarehouseList:[],
  282. dimension: '1',
  283. productLists: [],
  284. columnsVersion: 1,
  285. diffCacheKeyUrl: 'wms-warehouseManagement-components-AssetsDialog',
  286. cacheKeyUrl: 'wms-warehouseManagement-components-AssetsDialog1',
  287. selection: []
  288. };
  289. },
  290. created() {
  291. console.log('created');
  292. this.getFieldModel();
  293. this.getWarehouse();
  294. this.getFactoryList();
  295. },
  296. mounted() {
  297. // this.$nextTick(() => {
  298. // this.$refs.table.reload();
  299. // });
  300. },
  301. computed: {
  302. inputDisabled() {
  303. let _this = this;
  304. return (row) => {
  305. // console.log(row);
  306. return (
  307. _this.productLists.some((it) => it.categoryId == row.categoryId) ||
  308. _this.dimension == '3' || row.availableQuantity == 0
  309. );
  310. };
  311. },
  312. columns() {
  313. const _this = this;
  314. const version = this.columnsVersion;
  315. let kk = [];
  316. let jj = [];
  317. if (this.dimension == 1) {
  318. kk = this.newColumns.map((item) => {
  319. return {
  320. label: item.label,
  321. align: item.align,
  322. prop: item.prop,
  323. showOverflowTooltip: item.showOverflowTooltip
  324. };
  325. });
  326. } else {
  327. kk = [
  328. {
  329. label: '批次号',
  330. prop: 'batchNo',
  331. showOverflowTooltip: true
  332. },
  333. {
  334. label: '系统内部批次号',
  335. prop: 'systemBatchNo',
  336. minWidth: 180,
  337. showOverflowTooltip: true,
  338. formatter: (row) => row.systemBatchNo || '-'
  339. }
  340. ];
  341. }
  342. if (this.dimension == 3) {
  343. jj = [
  344. {
  345. label: '包装编码',
  346. prop: 'packageNo',
  347. align: 'center',
  348. showOverflowTooltip: true
  349. },
  350. {
  351. label: '包装数量',
  352. prop: 'packingQuantity',
  353. align: 'center',
  354. showOverflowTooltip: true
  355. },
  356. {
  357. label: '包装单位',
  358. prop: 'packingUnit',
  359. align: 'center',
  360. showOverflowTooltip: true
  361. },
  362. {
  363. label: '发货条码',
  364. prop: 'barcodes',
  365. align: 'center',
  366. showOverflowTooltip: true
  367. },
  368. {
  369. label: '物料代号',
  370. prop: 'materielDesignation',
  371. align: 'center',
  372. showOverflowTooltip: true
  373. },
  374. {
  375. label: '客户代号',
  376. prop: 'clientCode',
  377. align: 'center',
  378. showOverflowTooltip: true
  379. },
  380. {
  381. label: '刻码',
  382. prop: 'engrave',
  383. align: 'center',
  384. showOverflowTooltip: true
  385. },
  386. {
  387. label: '仓库',
  388. prop: 'warehouseName',
  389. align: 'center',
  390. showOverflowTooltip: true
  391. }
  392. ];
  393. }
  394. let arr = [
  395. this.dimension == 1
  396. ? {
  397. width: 55,
  398. type: 'selection',
  399. columnKey: 'selection',
  400. fixed: 'left',
  401. align: 'center',
  402. reserveSelection: true,
  403. selectable: (row) => {
  404. return (
  405. !_this.productLists.some((item) =>
  406. _this.isSameStockRecord(item, row)
  407. ) && row.availableQuantity != 0
  408. );
  409. }
  410. }
  411. : {
  412. width: 55,
  413. type: 'selection',
  414. columnKey: 'selection',
  415. fixed: 'left',
  416. align: 'center',
  417. reserveSelection: true,
  418. selectable: (row) => {
  419. return (
  420. !_this.productLists.some((item) =>
  421. _this.isSameStockRecord(item, row)
  422. ) && row.availableQuantity != 0
  423. );
  424. }
  425. },
  426. {
  427. columnKey: 'index',
  428. type: 'index',
  429. width: 50,
  430. align: 'center',
  431. label: '序号',
  432. showOverflowTooltip: true,
  433. fixed: 'left'
  434. },
  435. {
  436. fixed: 'left',
  437. prop: 'categoryCode',
  438. label: '物品编码',
  439. align: 'center',
  440. showOverflowTooltip: true
  441. },
  442. {
  443. fixed: 'left',
  444. prop: 'categoryName',
  445. label: '物品名称',
  446. align: 'center',
  447. showOverflowTooltip: true
  448. },
  449. {
  450. prop: 'outboundNum',
  451. label: '出库数量',
  452. align: 'center',
  453. minWidth: '100',
  454. showOverflowTooltip: true,
  455. slot: 'outboundNum'
  456. },
  457. {
  458. prop: 'lockQuantity',
  459. label: '锁定数量',
  460. align: 'center',
  461. showOverflowTooltip: true
  462. },
  463. {
  464. prop: 'availableQuantity',
  465. label: '可用数量',
  466. align: 'center',
  467. showOverflowTooltip: true,
  468. // formatter: (row) => {
  469. // // 使用整数运算避免浮点数精度丢失
  470. // const measure = Number(row.measureQuantity) || 0;
  471. // const lock = Number(row.lockQuantity) || 0;
  472. // const result = (measure * 100 - lock * 100) / 100;
  473. // return Math.round(result * 100) / 100;
  474. // }
  475. },
  476. {
  477. prop: 'inventoryCycle',
  478. label: '存货周期(天)',
  479. align: 'center',
  480. width: 150,
  481. sortable: true,
  482. showOverflowTooltip: true,
  483. hide: this.dimension == 1
  484. },
  485. {
  486. prop: 'brandNum',
  487. label: '牌号',
  488. align: 'center',
  489. showOverflowTooltip: true
  490. },
  491. {
  492. prop: 'modelKey',
  493. label: '机型',
  494. align: 'center',
  495. showOverflowTooltip: true
  496. },
  497. {
  498. prop: 'colorKey',
  499. label: '颜色',
  500. align: 'center',
  501. showOverflowTooltip: true
  502. },
  503. {
  504. prop: 'categoryModel',
  505. label: '型号',
  506. align: 'center',
  507. showOverflowTooltip: true
  508. },
  509. {
  510. prop: 'specification',
  511. label: '规格',
  512. align: 'center',
  513. showOverflowTooltip: true
  514. },
  515. ...kk,
  516. {
  517. prop: 'level',
  518. label: '级别',
  519. align: 'center',
  520. showOverflowTooltip: true
  521. },
  522. {
  523. prop: 'measureQuantity',
  524. label: '计量数量',
  525. align: 'center',
  526. showOverflowTooltip: true,
  527. formatter: (row) =>
  528. this.dimension == 2 ? row.stockCountBase : row.measureQuantity
  529. },
  530. {
  531. prop: 'measureUnit',
  532. label: '计量单位',
  533. align: 'center',
  534. showOverflowTooltip: true
  535. },
  536. {
  537. prop: 'weight',
  538. label: '重量',
  539. align: 'center',
  540. showOverflowTooltip: true
  541. },
  542. {
  543. prop: 'weightUnit',
  544. label: '重量单位',
  545. align: 'center',
  546. showOverflowTooltip: true
  547. },
  548. ...jj,
  549. {
  550. prop: 'supplierName',
  551. label: '供应商',
  552. align: 'center',
  553. showOverflowTooltip: true
  554. },
  555. {
  556. prop: 'supplierCode',
  557. label: '供应商代号',
  558. align: 'center',
  559. showOverflowTooltip: true
  560. }
  561. ];
  562. return arr.filter((item) => !item.hide);
  563. }
  564. },
  565. watch: {},
  566. methods: {
  567. isSameStockRecord(source, target) {
  568. if (source.id && target.id) {
  569. return source.id == target.id;
  570. }
  571. return (
  572. source.categoryId == target.categoryId &&
  573. source.warehouseId == target.warehouseId &&
  574. source.batchNo == target.batchNo &&
  575. (source.systemBatchNo || '') == (target.systemBatchNo || '')
  576. );
  577. },
  578. //获取工厂列表
  579. async getFactoryList() {
  580. const res = await warehouseDefinition.getFactoryarea({
  581. pageNum: 1,
  582. size: 9999,
  583. type: 1
  584. });
  585. this.factoryList = res.list;
  586. },
  587. async getWarehouse() {
  588. const { data } = await getWarehouseList();
  589. this.allWarehouseList = data;
  590. },
  591. getWarehouseListHandle(val) {
  592. this.searchForm.warehouseId = '';
  593. this.warehouseList = this.allWarehouseList.filter(
  594. (item) => item.factoryId === val
  595. );
  596. },
  597. // 获取动态表头
  598. getFieldModel() {
  599. storageApi.fieldModel({ fieldModel: 't_main_category' }).then((res) => {
  600. let newRes = res.map((m) => {
  601. return {
  602. prop: 'extField.' + m.prop,
  603. label: m.label,
  604. align: 'center',
  605. showOverflowTooltip: true
  606. };
  607. });
  608. this.newColumns = [...newRes];
  609. });
  610. },
  611. // 出库数量限制
  612. handleInput(row, value) {
  613. if (row.outboundNum <= row.availableQuantity) {
  614. // return (row.outboundNum = value.replace(/^(0+)|[^\d]+/g, ''));
  615. // 过滤掉非数字和小数点的字符
  616. const filteredValue = value.replace(/[^0-9.]/g, '');
  617. // 限制只能有一个小数点
  618. const singleDotValue = filteredValue.replace(/(\..*)\./g, '$1');
  619. let finalValue = '';
  620. const dotIndex = singleDotValue.indexOf('.');
  621. if (dotIndex !== -1) {
  622. // 截取小数点后最多两位
  623. finalValue = singleDotValue.slice(0, dotIndex + 3);
  624. } else {
  625. finalValue = singleDotValue;
  626. }
  627. row.outboundNum = finalValue;
  628. const currentIndex = this.selectionList.findIndex(item => item.id === row.id)
  629. if(currentIndex > -1) {
  630. this.$set(this.selectionList, currentIndex, row);
  631. }
  632. return
  633. } else {
  634. row.outboundNum = row.availableQuantity;
  635. const currentIndex = this.selectionList.findIndex(item => item.id === row.id)
  636. if(currentIndex > -1) {
  637. this.$set(this.selectionList, currentIndex, row);
  638. }
  639. }
  640. },
  641. // 切换维度
  642. changeDimensionHandler(e) {
  643. this.searchForm.pageNum = 1;
  644. this.selectionList = [];
  645. if (this.$refs.table) {
  646. this.$refs.table.clearSelection();
  647. }
  648. this.cacheKeyUrl = this.diffCacheKeyUrl + e;
  649. this.getTabColumns();
  650. this.reload();
  651. },
  652. async changeDimension(e) {
  653. this.dimension = e;
  654. if (this.dimension == 1) {
  655. // 物品维度
  656. const data = await storageApi.getProductList({
  657. ...this.searchForm,
  658. isEnabled: 1
  659. });
  660. this.tableData = data.list.map(item => {
  661. const measure = Number(item.measureQuantity) || 0;
  662. const lock = Number(item.lockQuantity) || 0;
  663. const result = (measure * 100 - lock * 100) / 100;
  664. return {
  665. ...item,
  666. availableQuantity: Math.round(result * 100) / 100
  667. }
  668. });
  669. this.total = data.count;
  670. } else if (this.dimension == 2) {
  671. // 批次维度
  672. const data = await storageApi.getBatchList(this.searchForm);
  673. for (let i = 0; i < data.list.length; i++) {
  674. const item = data.list[i];
  675. // 入库计量数量不会随出库变化,可用数量必须使用当前批次库存余额计算
  676. const inventoryBalance = Number(item.availableCountBase) || 0;
  677. const lock = Number(item.lockQuantity) || 0;
  678. const result = (inventoryBalance * 100 - lock * 100) / 100;
  679. item.availableQuantity = Math.round(result * 100) / 100;
  680. item.outboundNum = item.availableQuantity;
  681. }
  682. this.tableData = data.list;
  683. this.total = data.count;
  684. } else if (this.dimension == 4) {
  685. // 物料维度
  686. const data = await storageApi.getMaterialList({
  687. ...this.searchForm
  688. });
  689. this.tableData = data.list.map(item => {
  690. const measure = Number(item.measureQuantity) || 0;
  691. const lock = Number(item.lockQuantity) || 0;
  692. const result = (measure * 100 - lock * 100) / 100;
  693. return {
  694. ...item,
  695. availableQuantity: Math.round(result * 100) / 100
  696. }
  697. });
  698. this.total = data.count;
  699. } else {
  700. // 包装维度
  701. const data = await storageApi.getPackingList(this.searchForm);
  702. for (let i = 0; i < data.list.length; i++) {
  703. const measure = Number(item.measureQuantity) || 0;
  704. const lock = Number(item.lockQuantity) || 0;
  705. const result = (measure * 100 - lock * 100) / 100;
  706. data.list[i].availableQuantity = Math.round(result * 100) / 100;
  707. data.list[i].outboundNum = data.list[i].packingQuantity;
  708. }
  709. this.tableData = data.list;
  710. this.total = data.count;
  711. }
  712. console.log(this.tableData);
  713. this.updateProductOutboundNums(this.tableData);
  714. },
  715. updateProductOutboundNums(list) {
  716. console.log(this.productLists, 'this.productLists');
  717. console.log(this.dimension);
  718. // 物品时有bug,可能有多条,不用find,用filter
  719. if (this.dimension == 1) {
  720. //物品层
  721. for (let i = 0; i < list.length; i++) {
  722. const item = list[i];
  723. const matchedProduct = this.productLists.filter(
  724. (product) => product.categoryId === item.categoryId
  725. );
  726. let num = matchedProduct.reduce(
  727. (pre, cur) => pre + cur.measureQuantity,
  728. 0
  729. );
  730. // console.log(matchedProduct);
  731. if (matchedProduct.length) {
  732. this.$set(item, 'outboundNum', num);
  733. }
  734. const isSelection = this.selectionList.find(
  735. (product) => product.categoryId === item.categoryId
  736. );
  737. if (isSelection) {
  738. this.$set(item, 'outboundNum', isSelection.outboundNum);
  739. }
  740. }
  741. } else {
  742. for (let i = 0; i < list.length; i++) {
  743. const item = list[i];
  744. const matchedProduct = this.productLists.find(
  745. (product) => product.id === item.id
  746. );
  747. if (matchedProduct) {
  748. this.$set(item, 'outboundNum', matchedProduct.measureQuantity);
  749. }
  750. const isSelection = this.selectionList.find(
  751. (product) => product.id === item.id
  752. );
  753. if (isSelection) {
  754. this.$set(item, 'outboundNum', isSelection.outboundNum);
  755. }
  756. }
  757. }
  758. },
  759. open(val) {
  760. let that = this;
  761. this.productLists = val || [];
  762. this.visible = true;
  763. this.$nextTick(() => {
  764. this.$refs.treeList.getTreeData().then((data) => {
  765. // that.$nextTick(() => {
  766. // that.categoryLevelId = data.id;
  767. // that.searchForm.categoryLevelId = data.id;
  768. // that.doSearch();
  769. // });
  770. this.handleNodeClick(data);
  771. });
  772. });
  773. },
  774. async confirm() {
  775. console.log(this.selectionList);
  776. if (!this.selectionList.length) {
  777. this.$message.error('请至少选择一条数据!');
  778. return;
  779. }
  780. if (this.dimension == 1) {
  781. let boolen = this.selectionList.every((item) => item.outboundNum > 0);
  782. if (!boolen) {
  783. this.$message.error('请输入出库数量!');
  784. return;
  785. }
  786. }
  787. console.log(this.selectionList);
  788. let data = null;
  789. if (this.dimension == 3) {
  790. data = await storageApi.getHierarchyList({
  791. ids: this.selectionList.map((item) => item.id).join(','),
  792. type: this.dimension,
  793. warehouseId: this.searchForm.warehouseId,
  794. });
  795. } else if (this.dimension == 2) {
  796. data = await storageApi.getHierarchyFifo({
  797. type: this.dimension,
  798. ids: this.selectionList.map((item) => item.id),
  799. builders: this.selectionList.map((item) => {
  800. return {
  801. warehouseId: this.searchForm.warehouseId,
  802. categoryId: item.categoryId,
  803. batchNo: item.batchNo,
  804. // 历史数据保持空值,由后端按外部批次号兼容匹配
  805. systemBatchNo: item.systemBatchNo || '',
  806. num: item.outboundNum,
  807. id: item.id
  808. };
  809. })
  810. });
  811. } else if (this.dimension == 1) {
  812. data = await storageApi.getHierarchyFifo({
  813. type: this.dimension,
  814. builders: this.selectionList.map((item) => {
  815. return {
  816. warehouseId: this.searchForm.warehouseId,
  817. categoryId: item.categoryId,
  818. num: item.outboundNum
  819. };
  820. })
  821. });
  822. }
  823. console.log('data-------------------', data);
  824. this.$emit('detailData', data, this.dimension);
  825. this.cancel();
  826. },
  827. cancel() {
  828. this.selectionList = [];
  829. // this.$refs.multipleTable.clearSelection();
  830. this.visible = false;
  831. },
  832. handleSelectionChange(val) {
  833. this.selectionList = val;
  834. },
  835. handleNodeClick(data) {
  836. // console.log(data);
  837. this.categoryLevelId = data.id;
  838. this.searchForm.categoryLevelId = data.id;
  839. this.doSearch();
  840. },
  841. handleCurrentChange() {
  842. this.changeDimension(this.dimension);
  843. },
  844. reset() {
  845. this.searchForm = {
  846. categoryCode: '',
  847. categoryName: '',
  848. batchNo: '',
  849. systemBatchNo: '',
  850. brandNum: '',
  851. engrave: '',
  852. barcodes: '',
  853. warehouseId: '',
  854. factoryId: '',
  855. categoryLevelId: this.categoryLevelId,
  856. pageNum: 1,
  857. size: 20
  858. };
  859. this.doSearch();
  860. },
  861. doSearch() {
  862. this.searchForm.pageNum = 1;
  863. this.$refs.table.reload();
  864. this.$refs.table.reRenderTable();
  865. },
  866. handleSizeChange() {
  867. this.searchForm.pageNum = 1;
  868. this.changeDimension(this.dimension, 'page');
  869. },
  870. // 翻页时,输入的数量会重置
  871. updateSelect(data) {
  872. if (!this.selectionList.length) {
  873. return data;
  874. }
  875. let ids = this.selectionList.map((item) => item.id);
  876. data.list.forEach((item) => {
  877. let id = ids.find((id) => item.id === id);
  878. if (id) {
  879. item.outboundNum = this.selectionList.find(
  880. (item) => item.id === id
  881. ).outboundNum;
  882. }
  883. });
  884. return data;
  885. },
  886. async datasource({ page, limit, where, order }) {
  887. const dimension = this.dimension;
  888. let data;
  889. // console.log(this.searchForm);
  890. // console.log(dimension);
  891. if (dimension == 1) {
  892. data = await storageApi.getProductList({
  893. ...where,
  894. ...order,
  895. ...this.searchForm,
  896. pageNum: page,
  897. size: limit
  898. });
  899. // console.log(data);
  900. // let result = this.updateSelect(data);
  901. // return result;
  902. data.list.forEach(item => {
  903. // 使用整数运算避免浮点数精度丢失
  904. const measure = Number(item.measureQuantity) || 0;
  905. const lock = Number(item.lockQuantity) || 0;
  906. const result = (measure * 100 - lock * 100) / 100;
  907. item.availableQuantity = Math.round(result * 100) / 100;
  908. });
  909. console.log('dimension == 1~~~', data.list);
  910. this.updateProductOutboundNums(data.list);
  911. return data;
  912. }
  913. if (dimension == 2) {
  914. data = await storageApi.getBatchList({
  915. ...where,
  916. ...order,
  917. ...this.searchForm,
  918. pageNum: page,
  919. size: limit
  920. });
  921. data.list.forEach((item) => {
  922. // 入库计量数量不会随出库变化,可用数量必须使用当前批次库存余额计算
  923. const inventoryBalance = Number(item.availableCountBase) || 0;
  924. const lock = Number(item.lockQuantity) || 0;
  925. const result = (inventoryBalance * 100 - lock * 100) / 100;
  926. item.availableQuantity = Math.round(result * 100) / 100;
  927. item.outboundNum = item.availableQuantity;
  928. });
  929. return data;
  930. }
  931. if (dimension == 3) {
  932. data = await storageApi.getPackingList({
  933. ...where,
  934. ...order,
  935. ...this.searchForm,
  936. pageNum: page,
  937. size: limit
  938. });
  939. data.list.forEach((item) => {
  940. const measure = Number(item.measureQuantity) || 0;
  941. const lock = Number(item.lockQuantity) || 0;
  942. const result = (measure * 100 - lock * 100) / 100;
  943. item.availableQuantity = Math.round(result * 100) / 100;
  944. item.outboundNum = item.packingQuantity;
  945. });
  946. this.updateProductOutboundNums(data.list);
  947. return data;
  948. }
  949. },
  950. reload(where) {
  951. this.$refs.table.reload({
  952. pageNum: 1
  953. });
  954. }
  955. }
  956. };
  957. </script>
  958. <style lang="scss" scoped>
  959. .el-dialog__wrapper {
  960. ::v-deep .el-aside {
  961. background-color: #fff !important;
  962. border: 1px solid #ccc;
  963. }
  964. }
  965. .wrapper-assets {
  966. max-height: 53vh;
  967. overflow: auto;
  968. }
  969. </style>