AssetsDialog.vue 31 KB

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