packingBom.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891
  1. <template>
  2. <view>
  3. <view class="col userInp " style="display: flex; align-items: center;">
  4. <text class="label lable150 rx-cc">规格选择:</text>
  5. <!-- multiple -->
  6. <zxz-uni-data-select :localdata="localdataList" v-model="Usertype"
  7. @change="changeUserType"></zxz-uni-data-select>
  8. </view>
  9. <view v-for="(item, i) in DispositionList" :key="i">
  10. <view class="title_box rx-bc">
  11. <!-- 最小包装单元 -->
  12. <view class="name">{{ item.titel }}</view>
  13. <view class="btn_box rx-bc" @click="handCancelPacking">
  14. 重置打包
  15. </view>
  16. </view>
  17. <view class="material ">
  18. <view class="content_table">
  19. <view class="item">
  20. <view class="lable rx-cc">包装总数 </view>
  21. <view class="content content_num">
  22. <input class="uni-input" v-model="item.formedNumLast" type="number" :disabled="i != 0"
  23. @input="changeinput"></input>
  24. <view class="unit">{{ item.packageUnit }}</view>
  25. </view>
  26. </view>
  27. <view class="item rx-sc">
  28. <view class="rx ww55 ">
  29. <view class="lable lable150 rx-cc ">{{ item.titel }}单元</view>
  30. <view class="content content_num">
  31. <input class="uni-input" v-model="item.packageCell" disabled></input>
  32. <view style="max-width: 100rpx; font-size: 24rpx;">{{ item.packageUnit }}</view>
  33. </view>
  34. </view>
  35. <view class="rx ww45">
  36. <view class="rx-cc ww80">
  37. /<view style="max-width: 100rpx; font-size: 24rpx;">{{ item.conversionUnit }}</view>
  38. </view>
  39. <view class="content rx-sc">
  40. <!-- <zxz-uni-data-select :localdata="unitList" v-model="unit" dataValue='Key'
  41. format='{Value}' dataKey="Key" filterable :clear='false'></zxz-uni-data-select> -->
  42. <!-- <view class="penalize" @click="handleSplit">确认</view> -->
  43. </view>
  44. </view>
  45. </view>
  46. </view>
  47. <view class="content_table2" v-if='item.splitList.length'>
  48. <view class="head row rx-sc">
  49. <view class="item ww10">序号</view>
  50. <view class="item ww30">数量</view>
  51. <view class="item ww50">条码</view>
  52. <!-- <view class="item ww10 jsColor" @click="calculation()" v-if="clientEnvironmentId != 3">计算</view>
  53. <view class="item ww10" v-if="clientEnvironmentId == 3"></view> -->
  54. </view>
  55. <view class="table">
  56. <u-list @scrolltolower="scrolltolower" class="z_list" style="height: 100% !important;">
  57. <view class="tr row rx-sc" v-for="(it, idx) in item.splitList" :key='idx'>
  58. <view class="item ww10 rx-cc ">{{ it.computeSize }}</view>
  59. <view class="item ww30 content_num rx-sc">
  60. <input class="uni-input" v-model="it.quantity" type="digit"></input>
  61. <view style="width: 260rpx; font-size: 22rpx;"> {{ it.unit }}/{{
  62. item.conversionUnit }}
  63. </view>
  64. </view>
  65. <view class="item ww50">
  66. {{ it.code }}
  67. </view>
  68. </view>
  69. </u-list>
  70. </view>
  71. </view>
  72. </view>
  73. </view>
  74. <SearchPopup mode="center" v-if='show'>
  75. <template v-slot:list>
  76. <view class="search_list">
  77. <u-form labelPosition="left" :model="formData" labelWidth="180" labelAlign="left" class="baseForm">
  78. <u-form-item label="外包装数:" class="required-form" borderBottom prop="assetType">
  79. <input class="uni-input" v-model="formData.wPackNum" style="width: 280rpx;"
  80. placeholder="外包装数"></input> / {{ splitList[0].unit }}
  81. </u-form-item>
  82. </u-form>
  83. </view>
  84. </template>
  85. <template v-slot:operate>
  86. <view class="operate_box rx-bc">
  87. <u-button size="small" class="u-reset-button" @click="calculationClose()">
  88. 取消
  89. </u-button>
  90. <u-button type="success" size="small" class="u-reset-button" @click="calculationReset()">
  91. 重置
  92. </u-button>
  93. <u-button type="success" size="small" class="u-reset-button" @click="calculationSave()">
  94. 确定
  95. </u-button>
  96. </view>
  97. </template>
  98. </SearchPopup>
  99. </view>
  100. </template>
  101. <script>
  102. import {
  103. getByCode
  104. } from '@/api/pda/common.js'
  105. import {
  106. cancelPacking,
  107. packingReport,
  108. getPackingReport,
  109. packingReportRepeat,
  110. packageDisposition,
  111. getPackingReportRepeat
  112. } from '@/api/pda/workOrder.js'
  113. import SearchPopup from '../../components/searchPopup.vue'
  114. export default {
  115. components: {
  116. SearchPopup
  117. },
  118. props: {
  119. categoryId: {
  120. type: String,
  121. default: ''
  122. },
  123. objData: {
  124. type: Object,
  125. default: () => { }
  126. },
  127. taskId: {
  128. type: String,
  129. default: ''
  130. },
  131. workOrderId: {
  132. type: String,
  133. default: ''
  134. }
  135. },
  136. data() {
  137. return {
  138. formedNumLast: 0,
  139. quantity: '',
  140. unit: '',
  141. Usertype: "",// 规格
  142. unitList: [],
  143. splitList: [],
  144. localdataList: [],
  145. packUnit: null,
  146. temporaryNum: 0,
  147. temporaryCount: 0,
  148. temporaryList: [],
  149. packTwoList: [],
  150. DispositionList: [],
  151. newCategoryId: '',
  152. show: false,
  153. formData: {
  154. wPackNum: null,
  155. },
  156. clientEnvironmentId: uni.getStorageSync("userInfo") && uni.getStorageSync("userInfo").clientEnvironmentId,
  157. }
  158. },
  159. watch: {
  160. categoryId: {
  161. handler(newVal) {
  162. console.log(newVal, 'newVal');
  163. this.newCategoryId = newVal;
  164. },
  165. deep: true,
  166. immediate: true
  167. },
  168. objData: {
  169. handler(newVal) {
  170. this.formedNumLast = newVal.formedNumLast;
  171. console.log(this.formedNumLast );
  172. },
  173. deep: true,
  174. immediate: true
  175. }
  176. },
  177. created() {
  178. // this.formedNumLast = this.objData.formedNumLast;
  179. this.byCode();
  180. this.packageDispositionFn();
  181. // this.getPackingDetails()
  182. // this.getPackingDetailsTwo()
  183. },
  184. methods: {
  185. // 输入数量变化
  186. changeinput(e){
  187. console.log(e);
  188. },
  189. changeUserType(e) {
  190. this.listFn(e.arr);
  191. },
  192. groupBy(arr, key) {
  193. return arr.reduce((acc, obj) => {
  194. const groupKey = obj[key];
  195. if (!acc[groupKey]) {
  196. acc[groupKey] = [];
  197. }
  198. console.log();
  199. acc[groupKey].push(obj);
  200. return acc;
  201. }, {});
  202. },
  203. async packageDispositionFn() {
  204. let that = this;
  205. const res = await packageDisposition(this.newCategoryId);
  206. if (res.length) {
  207. res.shift();
  208. let data = JSON.parse(JSON.stringify(res));
  209. let list = this.groupBy(data, 'code');
  210. Object.entries(list).forEach(([key, value]) => {
  211. let obj = {
  212. text: value[0].name,
  213. arr: value,
  214. value: key
  215. }
  216. this.localdataList.push(obj);
  217. });
  218. this.Usertype = this.localdataList[0].value;
  219. this.listFn(this.localdataList[0].arr);
  220. }
  221. },
  222. listFn(arr) {
  223. let obj = {
  224. withinQuantity: "",
  225. withinUnit: '',
  226. outsideQuantity: '',
  227. outsideUnit: ''
  228. }
  229. let textList = ['最小包装', '内包装', '外包装'];
  230. arr.map(async (v, i) => {
  231. v.splitList = [];
  232. v.titel = textList[i];
  233. if (i === 0) {
  234. v.formedNumLast = this.formedNumLast;
  235. v.splitList = await this.handleSplit(v)||[];
  236. // this.$nextTick(c () => {
  237. // })
  238. }
  239. if (i === 1) {
  240. obj.withinQuantity = v.packageCell;
  241. obj.withinUnit = v.conversionUnit
  242. }
  243. if (i === 2) {
  244. obj.outsideQuantity = v.packageCell;
  245. obj.outsideUnit = v.conversionUnit;
  246. }
  247. })
  248. this.$set(this,'DispositionList',arr)
  249. },
  250. sunNum(v, i) {
  251. let _this = this;
  252. this.$nextTick(() => {
  253. switch (i) {
  254. case 0:
  255. console.log(_this.formedNumLast);
  256. return _this.formedNumLast;
  257. case 1:
  258. return v.splitList.length || 0
  259. case 2:
  260. return v.splitList.length || 0
  261. }
  262. })
  263. },
  264. byCode() {
  265. getByCode('packing_unit').then(res => {
  266. this.unitList = []
  267. res.forEach((obj, index) => {
  268. for (let key in obj) {
  269. if (obj.hasOwnProperty(key)) { // 确保key是对象自身的属性
  270. this.unitList.push({
  271. Key: `${key}`,
  272. Value: ` ${obj[key]}`
  273. })
  274. }
  275. }
  276. });
  277. })
  278. },
  279. getPackingDetails() {
  280. let param = {
  281. workOrderId: this.workOrderId,
  282. taskId: this.taskId,
  283. tier: 1
  284. }
  285. getPackingReport(param).then(res => {
  286. this.splitList = res.detailList
  287. this.formedNumLast = res.totalQuantity
  288. this.quantity = res.quantity
  289. this.unit = res.unit
  290. })
  291. },
  292. handCancelPacking() {
  293. uni.showModal({
  294. title: `是否清空包装?`,
  295. content: "",
  296. confirmText: "确认",
  297. success: () => {
  298. let param = {
  299. workOrderId: this.workOrderId,
  300. taskId: this.taskId,
  301. }
  302. cancelPacking(param).then(res => {
  303. this.getPackingDetails()
  304. this.getPackingDetailsTwo()
  305. })
  306. },
  307. })
  308. },
  309. // 第一次调用
  310. handleSplit(v) {
  311. if (this.splitList.length) {
  312. uni.showToast({
  313. title: '产品已分包',
  314. icon: 'none'
  315. })
  316. return false
  317. }
  318. if (!v.formedNumLast) {
  319. uni.showToast({
  320. title: '包装总数数量不能为空',
  321. icon: 'none'
  322. })
  323. return false
  324. }
  325. if (!v.packageCell) {
  326. uni.showToast({
  327. title: '内包装单元数量不能为空',
  328. icon: 'none'
  329. })
  330. return false
  331. }
  332. if (!v.packageUnit) {
  333. uni.showToast({
  334. title: '请选择包装单位',
  335. icon: 'none'
  336. })
  337. return false
  338. }
  339. let param = {
  340. totalQuantity: v.formedNumLast,
  341. quantity: v.packageCell,
  342. unit: v.packageUnit,
  343. packageUnit: v.conversionUnit,
  344. workOrderId: this.workOrderId,
  345. taskId: this.taskId,
  346. tier: 1
  347. }
  348. return new Promise((resolve, reject) => {
  349. packingReport(param).then(res => {
  350. this.splitList = res.map(m => {
  351. return {
  352. check: false,
  353. ...m
  354. }
  355. })
  356. resolve(this.splitList)
  357. // this.getPackingDetails()
  358. })
  359. })
  360. },
  361. handleCheck(idx, it) {
  362. if (it.quantity <= 0) {
  363. uni.showToast({
  364. icon: 'none',
  365. title: '数量为空不能勾选'
  366. })
  367. return false
  368. }
  369. this.$set(this.splitList[idx], 'check', it.check ? 0 : 1)
  370. this.temporaryList = []
  371. this.temporaryList = this.splitList.filter(e => {
  372. return e.check == 1
  373. })
  374. this.temporaryNum = 0
  375. this.temporaryCount = 0
  376. if (this.temporaryList.length > 0) {
  377. this.temporaryList.forEach(e => {
  378. this.temporaryNum = this.temporaryNum + 1
  379. this.temporaryCount = this.temporaryCount + Number(e.quantity)
  380. })
  381. }
  382. },
  383. handclose(it) {
  384. this.splitList.forEach(f => {
  385. if (f.computeSize == it.computeSize) {
  386. f.check = 0
  387. }
  388. })
  389. this.temporaryList = []
  390. this.temporaryList = this.splitList.filter(e => {
  391. return e.check == 1
  392. })
  393. },
  394. getPackingDetailsTwo(v) {
  395. console.log(v);
  396. let param = {
  397. totalQuantity: v.formedNumLast,
  398. quantity: v.packageCell,
  399. unit: v.conversionUnit,
  400. workOrderId: this.workOrderId,
  401. taskId: this.taskId,
  402. tier: 2,
  403. }
  404. getPackingReportRepeat(param).then(res => {
  405. resolve(res.detailList)
  406. })
  407. },
  408. handlePack(v, s) {
  409. let _arr = []
  410. _arr = s.map(m => {
  411. return {
  412. ...m,
  413. isChecked: 1
  414. }
  415. })
  416. console.log(_arr, '123');
  417. let param = {
  418. detailList: _arr,
  419. quantity: v.temporaryCount,
  420. totalQuantity: v.formedNumLast,
  421. unit: v.packageUnit,
  422. taskId: this.taskId,
  423. workOrderId: this.workOrderId,
  424. tier: 2
  425. }
  426. return new Promise((resolve, reject) => {
  427. packingReportRepeat(param).then(res => {
  428. console.log(res);
  429. // this.temporaryList = []
  430. this.getPackingDetails()
  431. // this.getPackingDetailsTwo()
  432. })
  433. })
  434. },
  435. scrolltolower() {
  436. },
  437. getData() {
  438. let _packingReportMarginList = []
  439. _packingReportMarginList = this.splitList.filter(e => {
  440. return !e.parentId
  441. })
  442. let packInfo = {
  443. packingReportList: this.packTwoList,
  444. packingReportMarginList: _packingReportMarginList,
  445. formedNumLast: this.formedNumLast
  446. }
  447. return packInfo
  448. },
  449. calculation() {
  450. this.show = true
  451. },
  452. calculationSave() {
  453. let count = this.splitList.filter(item => item.isChecked != 1).length;
  454. if (this.formData.wPackNum <= count && count != 0) {
  455. for (let i = 0; i < this.formData.wPackNum; i++) {
  456. this.splitList[i].check = 1
  457. }
  458. this.handleCheck(0, 0)
  459. this.calculationClose()
  460. } else {
  461. if (count != 0) {
  462. for (let i = 0; i < count; i++) {
  463. this.splitList[i].check = 1
  464. }
  465. this.handleCheck(0, 0)
  466. this.calculationClose()
  467. }
  468. uni.showToast({
  469. icon: 'none',
  470. title: '外包装数超出内包装条数'
  471. })
  472. }
  473. },
  474. calculationClose() {
  475. this.show = false
  476. },
  477. calculationReset() {
  478. this.formData.wPackNum = null
  479. this.splitList.forEach(f => {
  480. f.check = null
  481. })
  482. this.temporaryList = []
  483. this.show = false
  484. }
  485. },
  486. }
  487. </script>
  488. <style lang="scss" scoped>
  489. .title_box {
  490. margin-top: 20rpx;
  491. .name {
  492. font-size: 28rpx;
  493. font-style: normal;
  494. font-weight: 400;
  495. color: $theme-color;
  496. padding-left: 20rpx;
  497. position: relative;
  498. &:before {
  499. position: absolute;
  500. content: '';
  501. left: 0rpx;
  502. top: 0rpx;
  503. bottom: 0rpx;
  504. width: 4rpx;
  505. height: 28rpx;
  506. background: $theme-color;
  507. margin: auto;
  508. }
  509. }
  510. .btn_box {
  511. color: $theme-color;
  512. }
  513. }
  514. .material {
  515. margin-top: 10rpx;
  516. .content_table {
  517. width: 100%;
  518. border: 2rpx solid $border-color;
  519. .item {
  520. display: flex;
  521. border-bottom: 2rpx solid $border-color;
  522. .lable {
  523. width: 132rpx;
  524. text-align: center;
  525. background-color: #F7F9FA;
  526. font-size: 26rpx;
  527. border-right: 2rpx solid $border-color;
  528. flex-shrink: 0;
  529. }
  530. .lable220 {
  531. width: 220rpx !important;
  532. font-size: 24rpx;
  533. }
  534. .lable150 {
  535. width: 156rpx !important;
  536. font-size: 24rpx;
  537. }
  538. .ww80 {
  539. width: 80rpx;
  540. }
  541. .content {
  542. width: 518rpx;
  543. min-height: 64rpx;
  544. font-size: 28rpx;
  545. line-height: 28rpx;
  546. font-style: normal;
  547. font-weight: 400;
  548. // padding: 18rpx 8rpx;
  549. box-sizing: border-box;
  550. word-wrap: break-word;
  551. flex-grow: 1 !important;
  552. .unit {
  553. padding: 0 4rpx;
  554. font-size: 24rpx;
  555. color: #404446;
  556. }
  557. }
  558. &:last-child {
  559. border-bottom: none;
  560. }
  561. }
  562. .ww55 {
  563. width: 55%;
  564. }
  565. .ww45 {
  566. width: 45%;
  567. }
  568. }
  569. }
  570. .content_table2 {
  571. width: 100%;
  572. margin-top: 16rpx;
  573. .row {
  574. width: 100%;
  575. .item {
  576. color: #404446;
  577. font-size: 28rpx;
  578. padding-left: 12rpx;
  579. }
  580. .color157 {
  581. color: $theme-color;
  582. }
  583. .ww30 {
  584. width: 30%;
  585. }
  586. .ww50 {
  587. width: 50%;
  588. }
  589. .ww90 {
  590. width: 90%;
  591. }
  592. .ww15 {
  593. width: 15%;
  594. }
  595. .ww10 {
  596. width: 10%;
  597. }
  598. .ww30 {
  599. width: 30%;
  600. }
  601. .jsColor {
  602. color: $theme-color;
  603. font-size: 20rpx;
  604. }
  605. }
  606. .head {
  607. height: 64rpx;
  608. background: #F7F9FA;
  609. border-top: 2rpx solid #E3E5E5;
  610. border-left: 2rpx solid #E3E5E5;
  611. .item {
  612. height: 64rpx;
  613. line-height: 64rpx;
  614. border-right: 2rpx solid #E3E5E5;
  615. box-sizing: border-box;
  616. }
  617. }
  618. .tr {
  619. border-top: 2rpx solid #E3E5E5;
  620. border-left: 2rpx solid #E3E5E5;
  621. .item {
  622. font-size: 24rpx;
  623. min-height: 64rpx;
  624. display: flex;
  625. align-items: center;
  626. border-right: 2rpx solid #E3E5E5;
  627. box-sizing: border-box;
  628. white-space: normal;
  629. word-break: break-all;
  630. }
  631. &:last-child {
  632. border-bottom: 2rpx solid #E3E5E5;
  633. }
  634. }
  635. }
  636. .label {
  637. display: flex;
  638. height: 70rpx;
  639. width: 86px !important;
  640. font-size: 13px;
  641. align-items: center;
  642. justify-content: center;
  643. background-color: #F7F9FA;
  644. }
  645. .content_num {
  646. display: flex;
  647. align-items: center;
  648. padding: 0 4rpx;
  649. /deep/ .uni-input-input {
  650. border: 2rpx solid #F0F8F2;
  651. background: #F0F8F2;
  652. color: $theme-color;
  653. }
  654. }
  655. .penalize {
  656. width: 86rpx;
  657. line-height: 60rpx;
  658. background: $theme-color;
  659. font-size: 24rpx;
  660. text-align: center;
  661. color: #fff;
  662. }
  663. .check {
  664. width: 30rpx;
  665. height: 30rpx;
  666. }
  667. .z_list {
  668. max-height: 500rpx;
  669. }
  670. .search_list {
  671. min-height: 100rpx;
  672. width: 80vw;
  673. /deep/ .baseForm {
  674. padding: 0 20rpx;
  675. }
  676. }
  677. .operate_box {
  678. padding: 10rpx 32rpx;
  679. /deep/ .u-button {
  680. width: 30%;
  681. }
  682. }
  683. </style>