AssetsDialog.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. <template>
  2. <el-dialog :visible.sync="visible" title="物品信息" width="80vw" :append-to-body="true">
  3. <el-form :model="searchForm" label-width="100px">
  4. <el-row>
  5. <el-col :span="6">
  6. <el-form-item label="列表维度:" prop="dimension">
  7. <template>
  8. <el-select style="width: 100%" @change="changeDimensionHandler" v-model="dimension" placeholder="请选择">
  9. <!-- <el-option label="物料维度" value="4"> </el-option> -->
  10. <el-option label="包装维度" value="3"> </el-option>
  11. <el-option label="批次维度" value="2"> </el-option>
  12. <el-option label="物品维度" value="1"> </el-option>
  13. </el-select>
  14. </template>
  15. </el-form-item>
  16. </el-col>
  17. <el-col :span="6">
  18. <el-form-item label="关键字:">
  19. <el-input type="text" placeholder="请输入关键字" v-model="searchForm.keyWord"></el-input>
  20. </el-form-item>
  21. </el-col>
  22. <el-col :span="6">
  23. <el-form-item label="物品编码:">
  24. <el-input type="text" placeholder="搜索物品编码" v-model="searchForm.categoryCode"></el-input>
  25. </el-form-item>
  26. </el-col>
  27. <el-col :span="6">
  28. <el-form-item label="物品名称:">
  29. <el-input type="text" placeholder="搜索物品名称" v-model="searchForm.categoryName"></el-input>
  30. </el-form-item>
  31. </el-col>
  32. <el-col :span="6">
  33. <el-form-item label="批次号:">
  34. <el-input type="text" placeholder="搜索批次号" v-model="searchForm.batchNo"></el-input>
  35. </el-form-item>
  36. </el-col>
  37. <el-col :span="6">
  38. <el-form-item label="刻码">
  39. <el-input type="text" placeholder="搜索物品刻码" v-model="searchForm.engrave"></el-input>
  40. </el-form-item>
  41. </el-col>
  42. <el-col :span="6">
  43. <el-form-item label="发货码">
  44. <el-input type="text" placeholder="搜索发货码" v-model="searchForm.barcodes"></el-input>
  45. </el-form-item>
  46. </el-col>
  47. <el-col :span="6">
  48. <el-form-item label="批次号">
  49. <el-input type="text" placeholder="搜索批号" v-model="searchForm.batchNo"></el-input>
  50. </el-form-item>
  51. </el-col>
  52. <el-col :span="6">
  53. <el-form-item label="牌号">
  54. <el-input type="text" placeholder="搜索牌号" v-model="searchForm.brandNum"></el-input>
  55. </el-form-item>
  56. </el-col>
  57. <el-col style="text-align: right">
  58. <el-button type="primary" @click="doSearch">搜索</el-button>
  59. <el-button icon="el-icon-refresh-left" @click="reset">重置</el-button>
  60. </el-col>
  61. </el-row>
  62. </el-form>
  63. <el-container class="assets-dialog">
  64. <el-aside width="200px" class="wrapper-assets">
  65. <AssetTree ref="treeList" :treeIds="treeIds" @handleNodeClick="handleNodeClick" />
  66. </el-aside>
  67. <el-main>
  68. <el-table ref="multipleTable" :data="tableData" tooltip-effect="dark" height="50vh" border row-key="id"
  69. style="width: 100%" :header-cell-style="{ background: '#F0F3F3', border: 'none' }"
  70. @selection-change="handleSelectionChange" :key="productLists.length">
  71. <el-table-column v-if="dimension == 1" type="selection" :reserve-selection="true" width="55" align="center"
  72. fixed="left" :selectable="(row) => {
  73. return !this.productLists.some(
  74. (it) => it.categoryId == row.categoryId
  75. );
  76. }">
  77. </el-table-column>
  78. <el-table-column v-else-if="dimension != 1" type="selection" :reserve-selection="true" width="55"
  79. align="center" fixed="left" :selectable="(row) => {
  80. return !this.productLists.some(
  81. (it) => it.id == row.id
  82. );
  83. }">
  84. </el-table-column>
  85. <el-table-column label="序号" type="index" width="50" fixed="left">
  86. </el-table-column>
  87. <el-table-column prop="categoryCode" label="物品编码" min-width="120" fixed="left"
  88. :show-overflow-tooltip="true"></el-table-column>
  89. <el-table-column prop="categoryName" width="200" label="物品名称" fixed="left"
  90. :show-overflow-tooltip="true"></el-table-column>
  91. <el-table-column v-if="dimension != 4" label="出库数量" type="index" width="100">
  92. <template slot-scope="{ row }">
  93. <el-input type="text" placeholder="请输入" v-model="row.outboundNum" @input="handleInput(row, $event)"
  94. :class="{ password: errorVerify(row) }" :disabled="dimension == '3'"></el-input>
  95. </template>
  96. </el-table-column>
  97. <el-table-column prop="brandNum" label="牌号" :show-overflow-tooltip="true"></el-table-column>
  98. <el-table-column prop="categoryModel" label="型号" :show-overflow-tooltip="true"></el-table-column>
  99. <el-table-column prop="specification" label="规格" :show-overflow-tooltip="true"></el-table-column>
  100. <template v-if="dimension == 1">
  101. <el-table-column v-for="(item, index) in newColumns" :label="item.label" :align="item.align"
  102. :prop="item.prop" :show-overflow-tooltip="item.showOverflowTooltip"></el-table-column>
  103. </template>
  104. <el-table-column v-else prop="batchNo" key="batchNo" label="批次号" min-width="80"></el-table-column>
  105. <el-table-column prop="level" label="级别"></el-table-column>
  106. <el-table-column prop="measureQuantity" label="计量数量" width="120"></el-table-column>
  107. <el-table-column prop="measureUnit" label="计量单位" width="90"></el-table-column>
  108. <el-table-column prop="weight" label="重量" min-width="120"></el-table-column>
  109. <el-table-column prop="weightUnit" label="重量单位" min-width="120"></el-table-column>
  110. <el-table-column v-if="dimension == 3" prop="packageNo" label="包装编码" min-width="120"
  111. :show-overflow-tooltip="true"></el-table-column>
  112. <el-table-column v-if="dimension == 3" prop="packingQuantity" label="包装数量" min-width="120"
  113. :show-overflow-tooltip="true"></el-table-column>
  114. <el-table-column v-if="dimension == 3" prop="packingUnit" label="单位" min-width="120"
  115. :show-overflow-tooltip="true"></el-table-column>
  116. <el-table-column v-if="dimension == 3 || dimension == 4" label="发货条码" prop="barcodes" width="80"
  117. :show-overflow-tooltip="true"></el-table-column>
  118. <el-table-column v-if="dimension == 4" prop="no" label="物料编码" min-width="120"
  119. :show-overflow-tooltip="true"></el-table-column>
  120. <el-table-column v-if="dimension == 3 || dimension == 4" prop="materielDesignation" label="物料代号"
  121. min-width="100"></el-table-column>
  122. <el-table-column v-if="dimension == 3 || dimension == 4" prop="clientCode" label="客户代号"
  123. min-width="100"></el-table-column>
  124. <el-table-column v-if="dimension == 3 || dimension == 4" prop="engrave" label="刻码"
  125. min-width="120"></el-table-column>
  126. <el-table-column v-if="dimension == 3 || dimension == 4" prop="warehouseName" label="仓库" min-width="200"
  127. :show-overflow-tooltip="true"></el-table-column>
  128. <el-table-column prop="supplierName" label="供应商" min-width="200"
  129. :show-overflow-tooltip="true"></el-table-column>
  130. <el-table-column prop="supplierCode" label="供应商代号" min-width="200"
  131. :show-overflow-tooltip="true"></el-table-column>
  132. </el-table>
  133. <div style="text-align: right; padding: 10px">
  134. <el-pagination background layout="total, sizes, prev, pager, next, jumper" :total="total"
  135. :page-sizes="[5, 10, 20, 50]" :page-size.sync="searchForm.size" :current-page.sync="searchForm.pageNum"
  136. @current-change="handleCurrentChange" @size-change="handleSizeChange">
  137. </el-pagination>
  138. </div>
  139. </el-main>
  140. </el-container>
  141. <div slot="footer">
  142. <el-button type="primary" @click="confirm">确定</el-button>
  143. <el-button @click="cancel">关闭</el-button>
  144. </div>
  145. </el-dialog>
  146. </template>
  147. <script>
  148. import storageApi from '@/api/warehouseManagement';
  149. import AssetTree from '../../stockManagement/components/assetTree.vue';
  150. import { getDetailById, quantityDelivery } from '@/api/classifyManage';
  151. import { forEach } from 'lodash';
  152. export default {
  153. components: { AssetTree },
  154. props: {
  155. treeIds: { type: Array, default: () => [] },
  156. },
  157. data() {
  158. return {
  159. newColumns: [], // 动态表头
  160. isShowTable: true,
  161. qualityResultOption: [
  162. {
  163. value: 0,
  164. label: '合格'
  165. },
  166. {
  167. value: 1,
  168. label: '不合格'
  169. }
  170. ],
  171. qualityStatusOption: [
  172. {
  173. value: 1,
  174. label: '已质检'
  175. },
  176. {
  177. value: 0,
  178. label: '未质检'
  179. }
  180. ],
  181. visible: false,
  182. tableData: [],
  183. total: 0,
  184. categoryLevelId: '',
  185. searchForm: {
  186. keyWord: '',
  187. categoryCode: '',
  188. categoryName: '',
  189. batchNo: '',
  190. brandNum: '',
  191. engrave: '',
  192. barcodes: '',
  193. batchNo: '',
  194. categoryLevelId: '',
  195. pageNum: 1,
  196. size: 20
  197. },
  198. selectionList: [],
  199. materialType: '',
  200. warehouseList: [],
  201. dimension: '1',
  202. productLists: []
  203. };
  204. },
  205. created() {
  206. this.getFieldModel();
  207. },
  208. watch: {
  209. tableData(val) {
  210. this.doLayout();
  211. },
  212. },
  213. methods: {
  214. errorVerify(row) {
  215. return (
  216. !row.outboundNu &&
  217. this.selectionList.some((item) => item.id == row.id)
  218. );
  219. },
  220. doLayout() {
  221. let that = this;
  222. this.$nextTick(() => {
  223. that.$refs.multipleTable.doLayout();
  224. });
  225. },
  226. // 获取动态表头
  227. getFieldModel() {
  228. storageApi.fieldModel({ fieldModel: 't_main_category' }).then((res) => {
  229. let newRes = res.map((m) => {
  230. return {
  231. prop: 'extField.' + m.prop,
  232. label: m.label,
  233. align: 'center',
  234. showOverflowTooltip: true
  235. };
  236. });
  237. this.newColumns = [...newRes];
  238. });
  239. },
  240. // 出库数量限制
  241. handleInput(row, value) {
  242. if (row.outboundNum <= row.measureQuantity) {
  243. // return (row.outboundNum = value.replace(/^(0+)|[^\d]+/g, ''));
  244. // 过滤掉非数字和小数点的字符
  245. const filteredValue = value.replace(/[^0-9.]/g, '');
  246. // 限制只能有一个小数点
  247. const singleDotValue = filteredValue.replace(/(\..*)\./g, '$1');
  248. let finalValue = '';
  249. const dotIndex = singleDotValue.indexOf('.');
  250. if (dotIndex !== -1) {
  251. // 截取小数点后最多两位
  252. finalValue = singleDotValue.slice(0, dotIndex + 3);
  253. } else {
  254. finalValue = singleDotValue;
  255. }
  256. return row.outboundNum = finalValue;
  257. } else {
  258. row.outboundNum = row.measureQuantity;
  259. }
  260. },
  261. // 切换维度
  262. changeDimensionHandler(e) {
  263. this.searchForm.pageNum = 1;
  264. this.selectionList = [];
  265. this.$refs.multipleTable.clearSelection();
  266. this.changeDimension(e);
  267. },
  268. async changeDimension(e) {
  269. console.log('changeDimension')
  270. this.dimension = e;
  271. if (this.dimension == 1) {
  272. // 物品维度
  273. const data = await storageApi.getProductList(this.searchForm);
  274. this.tableData = data.list;
  275. this.total = data.count;
  276. } else if (this.dimension == 2) {
  277. // 批次维度
  278. const data = await storageApi.getBatchList(this.searchForm);
  279. this.tableData = data.list;
  280. this.total = data.count;
  281. } else if (this.dimension == 4) {
  282. // 物料维度
  283. const data = await storageApi.getMaterialList(this.searchForm);
  284. this.tableData = data.list;
  285. this.total = data.count;
  286. } else {
  287. // 包装维度
  288. const data = await storageApi.getPackingList(this.searchForm);
  289. for (let i = 0; i < data.list.length; i++) {
  290. data.list[i].outboundNum = data.list[i].packingQuantity;
  291. }
  292. this.tableData = data.list;
  293. this.total = data.count;
  294. }
  295. this.updateProductOutboundNums(this.tableData)
  296. },
  297. updateProductOutboundNums(list) {
  298. console.log(this.productLists, 'this.productLists')
  299. if (this.dimension == 1) {
  300. //物品层
  301. for (let i = 0; i < list.length; i++) {
  302. const item = list[i];
  303. const matchedProduct = this.productLists.find(product => {
  304. const isMatch = product.categoryId === item.categoryId;
  305. return isMatch;
  306. });
  307. if (matchedProduct) {
  308. this.$set(item, 'outboundNum', matchedProduct.measureQuantity);
  309. } else {
  310. console.warn('No match for item.id:', item.id);
  311. }
  312. }
  313. } else {
  314. for (let i = 0; i < list.length; i++) {
  315. const item = list[i];
  316. const matchedProduct = this.productLists.find(product => {
  317. const isMatch = product.id === item.id;
  318. return isMatch;
  319. });
  320. if (matchedProduct) {
  321. this.$set(item, 'outboundNum', matchedProduct.measureQuantity);
  322. } else {
  323. console.warn('No match for item.id:', item.id);
  324. }
  325. }
  326. }
  327. },
  328. open(val) {
  329. this.productLists = val || [];
  330. this.visible = true;
  331. this.$nextTick(() => {
  332. this.$refs.treeList.getTreeData().then(async (data) => {
  333. await this.handleNodeClick(data);
  334. });
  335. });
  336. },
  337. async confirm() {
  338. if (!this.selectionList.length) {
  339. this.$message.error('请至少选择一条数据!');
  340. return;
  341. }
  342. if (this.dimension == 1) {
  343. let boolen = this.selectionList.every((item) => item.outboundNum > 0);
  344. if (!boolen) {
  345. this.$message.error('请输入出库数量!');
  346. return;
  347. }
  348. }
  349. console.log(this.selectionList);
  350. let data = null;
  351. if (this.dimension != 1) {
  352. data = await storageApi.getHierarchyList({
  353. ids: this.selectionList.map((item) => item.id).join(','),
  354. type: this.dimension
  355. });
  356. } else {
  357. data = await storageApi.getHierarchyFifo({
  358. type: this.dimension,
  359. builders: this.selectionList.map((item) => {
  360. return {
  361. categoryId: item.categoryId,
  362. num: item.outboundNum
  363. };
  364. })
  365. });
  366. }
  367. console.log('data-------------------', data);
  368. this.$emit('detailData', data, this.dimension);
  369. this.cancel();
  370. },
  371. cancel() {
  372. this.selectionList = [];
  373. this.$refs.multipleTable.clearSelection();
  374. this.visible = false;
  375. },
  376. handleSelectionChange(val) {
  377. this.selectionList = val;
  378. },
  379. handleNodeClick(data) {
  380. console.log(data);
  381. this.categoryLevelId = data.id;
  382. this.searchForm.categoryLevelId = data.id;
  383. this.doSearch();
  384. },
  385. handleCurrentChange() {
  386. this.changeDimension(this.dimension);
  387. },
  388. reset() {
  389. this.searchForm = {
  390. categoryCode: '',
  391. categoryName: '',
  392. batchNo: '',
  393. brandNum: '',
  394. engrave: '',
  395. barcodes: '',
  396. batchNo: '',
  397. categoryLevelId: this.categoryLevelId,
  398. pageNum: 1,
  399. size: 20
  400. };
  401. this.doSearch();
  402. },
  403. doSearch() {
  404. this.searchForm.pageNum = 1;
  405. this.changeDimension(this.dimension);
  406. },
  407. handleSizeChange() {
  408. this.searchForm.pageNum = 1;
  409. this.changeDimension(this.dimension, 'page');
  410. }
  411. }
  412. };
  413. </script>
  414. <style lang="scss" scoped>
  415. .el-dialog__wrapper {
  416. ::v-deep .el-aside {
  417. background-color: #fff !important;
  418. border: 1px solid #ccc;
  419. }
  420. }
  421. .wrapper-assets {
  422. max-height: 53vh;
  423. overflow: auto;
  424. }
  425. ::v-deep .password .el-input__inner {
  426. border-color: red !important;
  427. }
  428. </style>