AssetsDialog.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  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. placeholder="请选择"
  18. >
  19. <!-- <el-option label="物料维度" value="4"> </el-option> -->
  20. <el-option label="包装维度" value="3"> </el-option>
  21. <el-option label="批次维度" value="2"> </el-option>
  22. <el-option label="物品维度" value="1"> </el-option>
  23. </el-select>
  24. </template>
  25. </el-form-item>
  26. </el-col>
  27. <el-col :span="6">
  28. <el-form-item label="关键字:">
  29. <el-input
  30. type="text"
  31. placeholder="请输入关键字"
  32. v-model="searchForm.keyWord"
  33. ></el-input>
  34. </el-form-item>
  35. </el-col>
  36. <el-col :span="6">
  37. <el-form-item label="物品编码:">
  38. <el-input
  39. type="text"
  40. placeholder="搜索物品编码"
  41. v-model="searchForm.categoryCode"
  42. ></el-input>
  43. </el-form-item>
  44. </el-col>
  45. <el-col :span="6">
  46. <el-form-item label="物品名称:">
  47. <el-input
  48. type="text"
  49. placeholder="搜索物品名称"
  50. v-model="searchForm.categoryName"
  51. ></el-input>
  52. </el-form-item>
  53. </el-col>
  54. <el-col :span="6">
  55. <el-form-item label="批次号:">
  56. <el-input
  57. type="text"
  58. placeholder="搜索批次号"
  59. v-model="searchForm.batchNo"
  60. ></el-input>
  61. </el-form-item>
  62. </el-col>
  63. <el-col :span="6">
  64. <el-form-item label="刻码">
  65. <el-input
  66. type="text"
  67. placeholder="搜索物品刻码"
  68. v-model="searchForm.engrave"
  69. ></el-input>
  70. </el-form-item>
  71. </el-col>
  72. <el-col :span="6">
  73. <el-form-item label="发货码">
  74. <el-input
  75. type="text"
  76. placeholder="搜索发货码"
  77. v-model="searchForm.barcodes"
  78. ></el-input>
  79. </el-form-item>
  80. </el-col>
  81. <el-col :span="6">
  82. <el-form-item label="所属工厂" prop="factoryId">
  83. <el-select
  84. filterable
  85. placeholder="请选择"
  86. v-model="searchForm.factoryId"
  87. clearable
  88. class="w100"
  89. @change="getWarehouseListHandle"
  90. >
  91. <el-option
  92. v-for="item in factoryList"
  93. :key="item.id"
  94. :label="item.name"
  95. :value="item.id"
  96. ></el-option>
  97. </el-select>
  98. </el-form-item>
  99. </el-col>
  100. <el-col :span="6">
  101. <el-form-item label="仓库">
  102. <el-select
  103. clearable
  104. style="width: 100%"
  105. v-model="searchForm.warehouseId"
  106. placeholder="请选择"
  107. >
  108. <el-option
  109. v-for="item in warehouseList"
  110. :label="item.name"
  111. :value="item.id"
  112. :key="item.id"
  113. >
  114. </el-option>
  115. </el-select>
  116. </el-form-item>
  117. </el-col>
  118. <el-col :span="6">
  119. <el-form-item label="牌号">
  120. <el-input
  121. type="text"
  122. placeholder="搜索牌号"
  123. v-model="searchForm.brandNum"
  124. ></el-input>
  125. </el-form-item>
  126. </el-col>
  127. <el-col :span="6">
  128. <el-form-item label="颜色">
  129. <el-input
  130. type="text"
  131. placeholder="搜索颜色"
  132. v-model="searchForm.colorKey"
  133. ></el-input>
  134. </el-form-item>
  135. </el-col>
  136. <el-col style="text-align: right">
  137. <el-button type="primary" @click="doSearch">搜索</el-button>
  138. <el-button icon="el-icon-refresh-left" @click="reset">重置</el-button>
  139. </el-col>
  140. </el-row>
  141. </el-form>
  142. <el-container class="assets-dialog">
  143. <el-aside width="200px" class="wrapper-assets">
  144. <AssetTree
  145. ref="treeList"
  146. :treeIds="treeIds"
  147. @handleNodeClick="handleNodeClick"
  148. />
  149. </el-aside>
  150. <el-main>
  151. <el-table
  152. ref="multipleTable"
  153. :data="tableData"
  154. tooltip-effect="dark"
  155. height="50vh"
  156. border
  157. row-key="id"
  158. style="width: 100%"
  159. :header-cell-style="{ background: '#F0F3F3', border: 'none' }"
  160. @selection-change="handleSelectionChange"
  161. :key="productLists.length"
  162. >
  163. <el-table-column
  164. v-if="dimension == 1"
  165. type="selection"
  166. :reserve-selection="true"
  167. width="55"
  168. align="center"
  169. fixed="left"
  170. :selectable="
  171. (row) => {
  172. return !this.productLists.some(
  173. (it) => it.categoryId == row.categoryId
  174. ) && row.measureQuantity != 0;
  175. }
  176. "
  177. >
  178. </el-table-column>
  179. <el-table-column
  180. v-else-if="dimension != 1"
  181. type="selection"
  182. :reserve-selection="true"
  183. width="55"
  184. align="center"
  185. fixed="left"
  186. :selectable="
  187. (row) => {
  188. return !this.productLists.some((it) => it.id == row.id) && row.measureQuantity != 0;
  189. }
  190. "
  191. >
  192. </el-table-column>
  193. <el-table-column label="序号" type="index" width="50" fixed="left">
  194. </el-table-column>
  195. <el-table-column
  196. prop="categoryCode"
  197. label="物品编码"
  198. min-width="120"
  199. fixed="left"
  200. :show-overflow-tooltip="true"
  201. ></el-table-column>
  202. <el-table-column
  203. prop="categoryName"
  204. width="200"
  205. label="物品名称"
  206. fixed="left"
  207. :show-overflow-tooltip="true"
  208. ></el-table-column>
  209. <el-table-column
  210. v-if="dimension != 4"
  211. label="出库数量"
  212. type="index"
  213. width="100"
  214. >
  215. <template slot-scope="{ row }">
  216. <el-input
  217. type="text"
  218. placeholder="请输入"
  219. v-model="row.outboundNum"
  220. @input="handleInput(row, $event)"
  221. :class="{ password: errorVerify(row) }"
  222. :disabled="dimension == '3'"
  223. ></el-input>
  224. </template>
  225. </el-table-column>
  226. <el-table-column
  227. prop="brandNum"
  228. label="牌号"
  229. :show-overflow-tooltip="true"
  230. ></el-table-column>
  231. <el-table-column
  232. prop="categoryModel"
  233. label="型号"
  234. :show-overflow-tooltip="true"
  235. ></el-table-column>
  236. <el-table-column
  237. prop="specification"
  238. label="规格"
  239. :show-overflow-tooltip="true"
  240. ></el-table-column>
  241. <el-table-column
  242. prop="colorKey"
  243. label="颜色"
  244. :show-overflow-tooltip="true"
  245. ></el-table-column>
  246. <template v-if="dimension == 1">
  247. <el-table-column
  248. v-for="(item, index) in newColumns"
  249. :label="item.label"
  250. :align="item.align"
  251. :prop="item.prop"
  252. :show-overflow-tooltip="item.showOverflowTooltip"
  253. ></el-table-column>
  254. </template>
  255. <el-table-column
  256. v-else
  257. prop="batchNo"
  258. key="batchNo"
  259. label="批次号"
  260. min-width="80"
  261. ></el-table-column>
  262. <el-table-column prop="level" label="级别"></el-table-column>
  263. <el-table-column
  264. prop="measureQuantity"
  265. label="计量数量"
  266. width="120"
  267. ></el-table-column>
  268. <el-table-column
  269. prop="measureUnit"
  270. label="计量单位"
  271. width="90"
  272. ></el-table-column>
  273. <el-table-column
  274. prop="weight"
  275. label="重量"
  276. min-width="120"
  277. ></el-table-column>
  278. <el-table-column
  279. prop="weightUnit"
  280. label="重量单位"
  281. min-width="120"
  282. ></el-table-column>
  283. <el-table-column
  284. v-if="dimension == 3"
  285. prop="packageNo"
  286. label="包装编码"
  287. min-width="120"
  288. :show-overflow-tooltip="true"
  289. ></el-table-column>
  290. <el-table-column
  291. v-if="dimension == 3"
  292. prop="packingQuantity"
  293. label="包装数量"
  294. min-width="120"
  295. :show-overflow-tooltip="true"
  296. ></el-table-column>
  297. <el-table-column
  298. v-if="dimension == 3"
  299. prop="packingUnit"
  300. label="单位"
  301. min-width="120"
  302. :show-overflow-tooltip="true"
  303. ></el-table-column>
  304. <el-table-column
  305. v-if="dimension == 3 || dimension == 4"
  306. label="发货条码"
  307. prop="barcodes"
  308. width="80"
  309. :show-overflow-tooltip="true"
  310. ></el-table-column>
  311. <el-table-column
  312. v-if="dimension == 4"
  313. prop="no"
  314. label="物料编码"
  315. min-width="120"
  316. :show-overflow-tooltip="true"
  317. ></el-table-column>
  318. <el-table-column
  319. v-if="dimension == 3 || dimension == 4"
  320. prop="materielDesignation"
  321. label="物料代号"
  322. min-width="100"
  323. ></el-table-column>
  324. <el-table-column
  325. v-if="dimension == 3 || dimension == 4"
  326. prop="clientCode"
  327. label="客户代号"
  328. min-width="100"
  329. ></el-table-column>
  330. <el-table-column
  331. v-if="dimension == 3 || dimension == 4"
  332. prop="engrave"
  333. label="刻码"
  334. min-width="120"
  335. ></el-table-column>
  336. <el-table-column
  337. v-if="dimension == 3 || dimension == 4"
  338. prop="warehouseName"
  339. label="仓库"
  340. min-width="200"
  341. :show-overflow-tooltip="true"
  342. ></el-table-column>
  343. <el-table-column
  344. prop="supplierName"
  345. label="供应商"
  346. min-width="200"
  347. :show-overflow-tooltip="true"
  348. ></el-table-column>
  349. <el-table-column
  350. prop="supplierCode"
  351. label="供应商代号"
  352. min-width="200"
  353. :show-overflow-tooltip="true"
  354. ></el-table-column>
  355. </el-table>
  356. <div style="text-align: right; padding: 10px">
  357. <el-pagination
  358. background
  359. layout="total, sizes, prev, pager, next, jumper"
  360. :total="total"
  361. :page-sizes="[5, 10, 20, 50]"
  362. :page-size.sync="searchForm.size"
  363. :current-page.sync="searchForm.pageNum"
  364. @current-change="handleCurrentChange"
  365. @size-change="handleSizeChange"
  366. >
  367. </el-pagination>
  368. </div>
  369. </el-main>
  370. </el-container>
  371. <div slot="footer">
  372. <el-button type="primary" @click="confirm">确定</el-button>
  373. <el-button @click="cancel">关闭</el-button>
  374. </div>
  375. </el-dialog>
  376. </template>
  377. <script>
  378. import storageApi from '@/api/warehouseManagement';
  379. import { getWarehouseList } from '@/api/bpm/components/wms';
  380. import warehouseDefinition from '@/api/warehouseManagement/warehouseDefinition';
  381. import AssetTree from '../../stockManagement/components/assetTree.vue';
  382. import { getDetailById, quantityDelivery } from '@/api/classifyManage';
  383. import { forEach } from 'lodash';
  384. export default {
  385. components: { AssetTree },
  386. props: {
  387. treeIds: { type: Array, default: () => [] }
  388. },
  389. data() {
  390. return {
  391. newColumns: [], // 动态表头
  392. isShowTable: true,
  393. qualityResultOption: [
  394. {
  395. value: 0,
  396. label: '合格'
  397. },
  398. {
  399. value: 1,
  400. label: '不合格'
  401. }
  402. ],
  403. qualityStatusOption: [
  404. {
  405. value: 1,
  406. label: '已质检'
  407. },
  408. {
  409. value: 0,
  410. label: '未质检'
  411. }
  412. ],
  413. visible: false,
  414. tableData: [],
  415. total: 0,
  416. categoryLevelId: '',
  417. searchForm: {
  418. keyWord: '',
  419. categoryCode: '',
  420. categoryName: '',
  421. batchNo: '',
  422. brandNum: '',
  423. engrave: '',
  424. barcodes: '',
  425. batchNo: '',
  426. categoryLevelId: '',
  427. pageNum: 1,
  428. size: 20,
  429. factoryId: '',
  430. warehouseId: ''
  431. },
  432. selectionList: [],
  433. materialType: '',
  434. dimension: '1',
  435. productLists: [],
  436. warehouseList: [],
  437. allWarehouseList: [],
  438. factoryList: []
  439. };
  440. },
  441. created() {
  442. this.getFieldModel();
  443. this.getFactoryList();
  444. this.getWarehouse()
  445. },
  446. watch: {
  447. tableData(val) {
  448. this.doLayout();
  449. }
  450. },
  451. methods: {
  452. //获取工厂列表
  453. async getFactoryList() {
  454. const res = await warehouseDefinition.getFactoryarea({
  455. pageNum: 1,
  456. size: 9999,
  457. type: 1
  458. });
  459. this.factoryList = res.list;
  460. },
  461. async getWarehouse() {
  462. const { data } = await getWarehouseList();
  463. this.allWarehouseList = data;
  464. },
  465. getWarehouseListHandle(val) {
  466. this.searchForm.warehouseId = '';
  467. this.warehouseList = this.allWarehouseList.filter(
  468. (item) => item.factoryId === val
  469. );
  470. },
  471. errorVerify(row) {
  472. return (
  473. !row.outboundNu &&
  474. this.selectionList.some((item) => item.id == row.id)
  475. );
  476. },
  477. doLayout() {
  478. let that = this;
  479. this.$nextTick(() => {
  480. that.$refs.multipleTable.doLayout();
  481. });
  482. },
  483. // 获取动态表头
  484. getFieldModel() {
  485. storageApi.fieldModel({ fieldModel: 't_main_category' }).then((res) => {
  486. let newRes = res.map((m) => {
  487. return {
  488. prop: 'extField.' + m.prop,
  489. label: m.label,
  490. align: 'center',
  491. showOverflowTooltip: true
  492. };
  493. });
  494. this.newColumns = [...newRes];
  495. });
  496. },
  497. // 出库数量限制
  498. handleInput(row, value) {
  499. if (row.outboundNum <= row.measureQuantity) {
  500. // return (row.outboundNum = value.replace(/^(0+)|[^\d]+/g, ''));
  501. // 过滤掉非数字和小数点的字符
  502. const filteredValue = value.replace(/[^0-9.]/g, '');
  503. // 限制只能有一个小数点
  504. const singleDotValue = filteredValue.replace(/(\..*)\./g, '$1');
  505. let finalValue = '';
  506. const dotIndex = singleDotValue.indexOf('.');
  507. if (dotIndex !== -1) {
  508. // 截取小数点后最多两位
  509. finalValue = singleDotValue.slice(0, dotIndex + 3);
  510. } else {
  511. finalValue = singleDotValue;
  512. }
  513. return (row.outboundNum = finalValue);
  514. } else {
  515. row.outboundNum = row.measureQuantity;
  516. }
  517. },
  518. // 切换维度
  519. changeDimensionHandler(e) {
  520. this.searchForm.pageNum = 1;
  521. this.selectionList = [];
  522. this.$refs.multipleTable.clearSelection();
  523. this.changeDimension(e);
  524. },
  525. async changeDimension(e) {
  526. console.log('changeDimension');
  527. this.dimension = e;
  528. if (this.dimension == 1) {
  529. // 物品维度
  530. const data = await storageApi.getProductList(this.searchForm);
  531. this.tableData = data.list;
  532. this.total = data.count;
  533. } else if (this.dimension == 2) {
  534. // 批次维度
  535. const data = await storageApi.getBatchList(this.searchForm);
  536. for (let i = 0; i < data.list.length; i++) {
  537. data.list[i].outboundNum = data.list[i].measureQuantity;
  538. }
  539. this.tableData = data.list;
  540. this.total = data.count;
  541. } else if (this.dimension == 4) {
  542. // 物料维度
  543. const data = await storageApi.getMaterialList(this.searchForm);
  544. this.tableData = data.list;
  545. this.total = data.count;
  546. } else {
  547. // 包装维度
  548. const data = await storageApi.getPackingList(this.searchForm);
  549. for (let i = 0; i < data.list.length; i++) {
  550. data.list[i].outboundNum = data.list[i].packingQuantity;
  551. }
  552. this.tableData = data.list;
  553. this.total = data.count;
  554. }
  555. this.updateProductOutboundNums(this.tableData);
  556. },
  557. updateProductOutboundNums(list) {
  558. console.log(this.productLists, 'this.productLists');
  559. if (this.dimension == 1) {
  560. //物品层
  561. for (let i = 0; i < list.length; i++) {
  562. const item = list[i];
  563. const matchedProduct = this.productLists.find((product) => {
  564. const isMatch = product.categoryId === item.categoryId;
  565. return isMatch;
  566. });
  567. if (matchedProduct) {
  568. this.$set(item, 'outboundNum', matchedProduct.measureQuantity);
  569. }
  570. const isSelection = this.selectionList.find(
  571. (product) => product.categoryId === item.categoryId
  572. );
  573. if (isSelection) {
  574. this.$set(item, 'outboundNum', isSelection.outboundNum);
  575. }
  576. }
  577. } else {
  578. for (let i = 0; i < list.length; i++) {
  579. const item = list[i];
  580. const matchedProduct = this.productLists.find((product) => {
  581. const isMatch = product.id === item.id;
  582. return isMatch;
  583. });
  584. if (matchedProduct) {
  585. this.$set(item, 'outboundNum', matchedProduct.measureQuantity);
  586. }
  587. const isSelection = this.selectionList.find(
  588. (product) => product.id === item.id
  589. );
  590. if (isSelection) {
  591. this.$set(item, 'outboundNum', isSelection.outboundNum);
  592. }
  593. }
  594. }
  595. },
  596. open(val) {
  597. this.productLists = val || [];
  598. this.visible = true;
  599. this.$nextTick(() => {
  600. this.$refs.treeList.getTreeData().then(async (data) => {
  601. await this.handleNodeClick(data);
  602. });
  603. });
  604. },
  605. async confirm() {
  606. if (!this.selectionList.length) {
  607. this.$message.error('请至少选择一条数据!');
  608. return;
  609. }
  610. if (this.dimension == 1) {
  611. let boolen = this.selectionList.every((item) => item.outboundNum > 0);
  612. if (!boolen) {
  613. this.$message.error('请输入出库数量!');
  614. return;
  615. }
  616. }
  617. console.log(this.selectionList);
  618. let data = null;
  619. if (this.dimension == 3) {
  620. data = await storageApi.getHierarchyList({
  621. ids: this.selectionList.map((item) => item.id).join(','),
  622. type: this.dimension
  623. });
  624. } else if (this.dimension == 2) {
  625. data = await storageApi.getHierarchyFifo({
  626. type: this.dimension,
  627. ids: this.selectionList.map((item) => item.id),
  628. builders: this.selectionList.map((item) => {
  629. return {
  630. categoryId: item.categoryId,
  631. num: item.outboundNum,
  632. id: item.id
  633. };
  634. })
  635. });
  636. } else if (this.dimension == 1) {
  637. data = await storageApi.getHierarchyFifo({
  638. type: this.dimension,
  639. builders: this.selectionList.map((item) => {
  640. return {
  641. categoryId: item.categoryId,
  642. num: item.outboundNum
  643. };
  644. })
  645. });
  646. }
  647. console.log('data-------------------', data);
  648. this.$emit('detailData', data, this.dimension);
  649. this.cancel();
  650. },
  651. cancel() {
  652. this.selectionList = [];
  653. this.$refs.multipleTable.clearSelection();
  654. this.visible = false;
  655. },
  656. handleSelectionChange(val) {
  657. this.selectionList = val;
  658. },
  659. handleNodeClick(data) {
  660. console.log(data);
  661. this.categoryLevelId = data.id;
  662. this.searchForm.categoryLevelId = data.id;
  663. this.doSearch();
  664. },
  665. handleCurrentChange() {
  666. this.changeDimension(this.dimension);
  667. },
  668. reset() {
  669. this.searchForm = {
  670. categoryCode: '',
  671. categoryName: '',
  672. batchNo: '',
  673. brandNum: '',
  674. engrave: '',
  675. barcodes: '',
  676. batchNo: '',
  677. categoryLevelId: this.categoryLevelId,
  678. pageNum: 1,
  679. size: 20
  680. };
  681. this.doSearch();
  682. },
  683. doSearch() {
  684. this.searchForm.pageNum = 1;
  685. this.changeDimension(this.dimension);
  686. },
  687. handleSizeChange() {
  688. this.searchForm.pageNum = 1;
  689. this.changeDimension(this.dimension, 'page');
  690. }
  691. }
  692. };
  693. </script>
  694. <style lang="scss" scoped>
  695. .el-dialog__wrapper {
  696. ::v-deep .el-aside {
  697. background-color: #fff !important;
  698. border: 1px solid #ccc;
  699. }
  700. }
  701. .wrapper-assets {
  702. max-height: 53vh;
  703. overflow: auto;
  704. }
  705. ::v-deep .password .el-input__inner {
  706. border-color: red !important;
  707. }
  708. </style>