delivery.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. <template>
  2. <view class="deliver-page">
  3. <u-navbar
  4. height="40px"
  5. title="货物出库"
  6. bgColor="#0256FF"
  7. :titleStyle="{ color: '#fff' }"
  8. leftIconColor="#fff"
  9. autoBack
  10. placeholder
  11. >
  12. </u-navbar>
  13. <view class="container_main">
  14. <view class="info-box" :class="isUnfold ? '' : 'min-height'">
  15. <view class="info-line">
  16. <view class="info-line-label">
  17. <text>发出仓库</text>
  18. </view>
  19. <view class="info-line-value">
  20. {{ depotInfo ? depotInfo.depotName : "" }}
  21. </view>
  22. </view>
  23. <view class="info-line">
  24. <view class="info-line-label">
  25. <text>客户</text>
  26. </view>
  27. <view class="info-line-value">
  28. {{ orderInfo.supplierName || "-" }}
  29. </view>
  30. </view>
  31. <view class="info-line">
  32. <view class="info-line-label">
  33. <text>出库类型</text>
  34. </view>
  35. <view class="info-line-value">
  36. {{ orderInfo.subType || "-" }}
  37. </view>
  38. </view>
  39. <view class="info-line" v-if="orderInfo.submitTime">
  40. <view class="info-line-label">
  41. <text>出库日期</text>
  42. </view>
  43. <view class="info-line-value">
  44. {{ orderInfo.submitTime || "-" }}
  45. </view>
  46. </view>
  47. <view class="info-line">
  48. <view class="info-line-label">
  49. <text>配送地址</text>
  50. </view>
  51. <view class="info-line-value">
  52. {{ orderInfo.receiverAddress || "-" }}
  53. </view>
  54. </view>
  55. <view class="info-line">
  56. <view class="info-line-label">
  57. <text>上传凭证</text>
  58. </view>
  59. <view class="info-line-value ss-p-y-24">
  60. <upload-image
  61. v-model="voucherPicture"
  62. width="196rpx"
  63. height="196rpx"
  64. ></upload-image>
  65. </view>
  66. </view>
  67. <view class="info-line">
  68. <view class="info-line-label">
  69. <text>备注信息</text>
  70. </view>
  71. <view class="info-line-value">
  72. <u-input
  73. v-model="orderInfo.mark"
  74. placeholder="请输入备注信息"
  75. border="none"
  76. ></u-input>
  77. </view>
  78. </view>
  79. </view>
  80. <view class="btn-box">
  81. <view class="btn-cont" @click="isUnfold = !isUnfold">
  82. <text>{{ isUnfold ? "收起" : "展开" }}</text>
  83. <u-icon :name="isUnfold ? 'arrow-up' : 'arrow-down'"></u-icon>
  84. </view>
  85. </view>
  86. <view class="scan-box">
  87. <view class="scan-box-l" @click="scanCode">
  88. <u-image
  89. width="120rpx"
  90. height="120rpx"
  91. src="@/static/image/zidong-saoma-img.png"
  92. ></u-image>
  93. <view class="tips-text">扫描快速识别货物</view>
  94. <view class="tips-text2">
  95. <u-icon name="checkmark-circle-fill" color="#0256FF"></u-icon>
  96. <text>连续扫描</text>
  97. </view>
  98. </view>
  99. <!-- <view class="scan-box-r" @click="manualClick">
  100. <u-image width="120rpx" height="120rpx" src="@/static/image/shoudong-saoma-img.png"></u-image>
  101. <view class="tips-text">手动选择</view>
  102. </view> -->
  103. </view>
  104. <!-- 货物清单 -->
  105. <view class="cargo-list">
  106. <view class="cargo-list-title">
  107. <view>出库货物清单</view>
  108. <view class="cargo-list-title-tips">(轻触货物查看详情)</view>
  109. </view>
  110. <block v-for="(item, i) in goodsList" :key="i">
  111. <good-item
  112. :item="item"
  113. @toDetail="toDetail"
  114. :show-print="true"
  115. @print="(e) => handlePrint(e.id, '2', status)"
  116. >
  117. <view class="num-box" @click.stop="">
  118. <view class="num-box-text">已确认出库数量</view>
  119. <u-number-box
  120. v-model="item.materialNumber"
  121. :min="0"
  122. :inputWidth="56"
  123. :max="item.inventory"
  124. >
  125. </u-number-box>
  126. </view>
  127. </good-item>
  128. </block>
  129. </view>
  130. </view>
  131. <view class="footer-box">
  132. <view class="footer-box-l">
  133. <view>货物种类:{{ speciesNum }}种</view>
  134. <view>货物总数:{{ orderGoodsNum }}件</view>
  135. </view>
  136. <button class="submitBtn" @tap="submitClick">提交</button>
  137. </view>
  138. <error-pop
  139. v-model="errorShow"
  140. @close="errorShow = false"
  141. @confirm="confirm"
  142. :content="popText.errorText"
  143. ></error-pop>
  144. <success-pop
  145. v-model="successShow"
  146. @close="successShow = false"
  147. @backClick="backClick"
  148. :content="popText.successText"
  149. ></success-pop>
  150. <!-- 扫码之后弹窗 -->
  151. <scaned-pop
  152. v-if="scanedShow"
  153. v-model="scanedShow"
  154. :scanNum="scanNum"
  155. :max="scanMaxNum"
  156. @close="scanedShow = false"
  157. @confirm="scanConfirm"
  158. ></scaned-pop>
  159. <goods-pop v-model="goodsShow" @close="goodsShow = false"></goods-pop>
  160. <!-- 打印条码弹框 -->
  161. <print-pop
  162. :show.sync="blePrintPop.show"
  163. :info="blePrintPop.data"
  164. @confirm="startPrint"
  165. ></print-pop>
  166. <!-- 选择蓝牙设备弹框 -->
  167. <ble-pop
  168. :show.sync="bleSelectPop.show"
  169. :list="discoveredDevices"
  170. @close="closeBleSelectPop"
  171. @refresh="refreshBleDevice"
  172. @selectItem="handleSelectBle"
  173. ></ble-pop>
  174. <ble-tip-pop
  175. v-model="bleErrorTipPop.show"
  176. :is-center="true"
  177. @confirm="bleErrorTipConfirm"
  178. :content="bleErrorTipPop.content"
  179. :extraText="bleErrorTipPop.extraText"
  180. >
  181. </ble-tip-pop>
  182. </view>
  183. </template>
  184. <script>
  185. import goodItem from "@/components/good-item/good-item.vue";
  186. import errorPop from "@/components/error-pop/error-pop.vue";
  187. import successPop from "@/components/success-pop/success-pop.vue";
  188. import scanedPop from "@/components/scaned-pop/scaned-pop.vue";
  189. import goodsPop from "@/components/goods-pop/goods-pop.vue";
  190. import {
  191. orderDetail,
  192. orderInfo,
  193. orderSubmit,
  194. getSkuByUpc,
  195. } from "@/common/request/apis/purchase";
  196. import { mapGetters } from "vuex";
  197. import blePrintMixin from "@/common/mixins/blePrintMixin.js";
  198. export default {
  199. mixins: [blePrintMixin],
  200. components: {
  201. goodItem,
  202. errorPop,
  203. successPop,
  204. scanedPop,
  205. goodsPop,
  206. },
  207. data() {
  208. return {
  209. popText: {
  210. errorText: "实际出库数量与应出库数量有差异,是否确认提交?",
  211. successText: "您的拣货出库任务已提交,审核后方可生效!",
  212. },
  213. goodsShow: false,
  214. scanedShow: false,
  215. errorShow: false,
  216. successShow: false,
  217. value: 0,
  218. isUnfold: true, //是否展开
  219. info: {
  220. mark: "",
  221. url: "",
  222. },
  223. goodsList: [],
  224. orderInfo: {},
  225. id: "",
  226. calendarShow: false,
  227. value1: "",
  228. maxDate: Number(new Date()),
  229. chooseGoodsInfo: {},
  230. voucherPicture: "",
  231. scanIndex: -1,
  232. scanNum: 1,
  233. scanMaxNum: 0,
  234. status: null,
  235. };
  236. },
  237. onLoad(e) {
  238. this.id = e.id;
  239. this.getOrderDetail(e.id);
  240. this.getOrderInfo(e.id);
  241. },
  242. computed: {
  243. ...mapGetters(["depotInfo"]),
  244. speciesNum() {
  245. let num = 0;
  246. if (this.goodsList.length == 0 || !this.goodsList) {
  247. num = 0;
  248. } else {
  249. num = this.goodsList.length;
  250. }
  251. return num;
  252. },
  253. // 订单返回的数量
  254. orderGoodsNum() {
  255. let num = 0;
  256. if (this.goodsList.length == 0 || !this.goodsList) {
  257. num = 0;
  258. } else {
  259. this.goodsList.forEach((item) => {
  260. num += item.operNumber;
  261. });
  262. }
  263. return num;
  264. },
  265. },
  266. onShow() {
  267. uni.$on("scanFinish", async (data) => {
  268. try {
  269. const params = {
  270. upc: data,
  271. };
  272. console.log("params===", params);
  273. const res = await getSkuByUpc(params);
  274. console.log("getSkuByUpc====", res);
  275. if (res.code === 200) {
  276. const sku = res.data;
  277. if (this.goodsList.length == 0)
  278. return uni.$u.toast("该货物不属于该任务");
  279. let index = this.goodsList.findIndex((item) => item.sku == sku);
  280. if (index == -1) return uni.$u.toast("该货物不属于该任务");
  281. this.scanIndex = index;
  282. this.scanNum = this.goodsList[index].materialNumber;
  283. this.scanMaxNum = this.goodsList[index].inventory;
  284. this.scanedShow = true;
  285. } else {
  286. uni.$u.toast(res.msg);
  287. }
  288. } catch (error) {}
  289. });
  290. },
  291. onHide() {
  292. uni.$off("scanFinish");
  293. },
  294. onUnload() {
  295. uni.$off("scanFinish");
  296. },
  297. methods: {
  298. scanCode() {
  299. this.$scan.scanCode();
  300. },
  301. calendarConfirm(val) {
  302. this.goodsList.forEach((item) => {
  303. if (item.id == this.chooseGoodsInfo.id) {
  304. item.productionDate = this.$u.timeFormat(val.value, "yyyy-mm-dd");
  305. }
  306. });
  307. this.calendarShow = false;
  308. },
  309. calendarClick(item) {
  310. console.log(item.productionDate, "item.productionDate");
  311. this.chooseGoodsInfo = item;
  312. if (item.productionDate) {
  313. this.value1 = Number(new Date(item.productionDate));
  314. } else {
  315. this.value1 = Number(new Date());
  316. }
  317. this.calendarShow = true;
  318. },
  319. getOrderInfo(id) {
  320. orderInfo(id).then((res) => {
  321. if (res.code == 200) {
  322. this.orderInfo = res.data;
  323. this.status = res.data.status;
  324. console.log("this.orderInfo====", this.orderInfo);
  325. }
  326. });
  327. },
  328. getOrderDetail(id) {
  329. orderDetail(id).then((res) => {
  330. if (res.code == 200) {
  331. res.data.rows.forEach((item) => {
  332. if (item.imgName && item.imgName.length > 0) {
  333. item.imgNameArr = item.imgName.split(",");
  334. } else {
  335. item.imgNameArr = [];
  336. }
  337. item.materialNumber = 0;
  338. });
  339. this.goodsList = res.data.rows;
  340. console.log("goodsList==========", this.goodsList);
  341. }
  342. });
  343. },
  344. submitClick() {
  345. let num = 0;
  346. console.log("this.goodsList=====", this.goodsList);
  347. this.goodsList.forEach((item) => {
  348. if (item.materialNumber * 1 != item.operNumber) {
  349. num++;
  350. }
  351. });
  352. console.log("num=====", num);
  353. if (num > 0) {
  354. return (this.errorShow = true);
  355. }
  356. console.log("111111=====", 1111);
  357. this.toOrderSubmit();
  358. },
  359. toOrderSubmit() {
  360. console.log("this.goodsList=====", this.goodsList);
  361. let materials = this.goodsList.map((item) => {
  362. return {
  363. barCode: item.sku,
  364. materialNumber: item.materialNumber,
  365. productionDate: item.productionDate
  366. ? this.$u.timeFormat(item.productionDate, "yyyy-mm-dd")
  367. : "",
  368. };
  369. });
  370. let params = {
  371. id: this.id,
  372. materials: materials,
  373. voucherPicture: this.voucherPicture || "",
  374. remark: this.orderInfo.mark || "",
  375. number: this.orderInfo.number,
  376. };
  377. console.log("orderSubmit========params====", params);
  378. orderSubmit(params).then((res) => {
  379. console.log("orderSubmit============res=====", res);
  380. if (res.code == 200) {
  381. if (this.errorShow) {
  382. this.errorShow = false;
  383. }
  384. this.successShow = true;
  385. } else {
  386. uni.showToast({
  387. icon: "error",
  388. mask: true,
  389. title: res.msg || "服务错误",
  390. });
  391. }
  392. });
  393. },
  394. confirm() {
  395. this.toOrderSubmit();
  396. this.errorShow = false;
  397. },
  398. backClick() {
  399. uni.setStorageSync("orderRefresh", true);
  400. uni.navigateBack();
  401. },
  402. // 扫码确认
  403. scanConfirm(val) {
  404. this.goodsList[this.scanIndex].materialNumber = Number(val);
  405. this.scanedShow = false;
  406. },
  407. manualClick() {
  408. this.goodsShow = true;
  409. },
  410. toDetail(val) {
  411. uni.navigateTo({
  412. url: `/pages/goods/detail?id=${val.id}&name=${val.materialName}`,
  413. });
  414. },
  415. },
  416. };
  417. </script>
  418. <style lang="scss" scoped>
  419. .deliver-page {
  420. min-height: 100vh;
  421. background-color: #f0f6fb;
  422. padding-bottom: 130rpx;
  423. .container_main {
  424. padding: 24rpx;
  425. .info-box {
  426. background-color: #fff;
  427. border-radius: 16rpx 16rpx 0 0;
  428. padding: 24rpx 24rpx 0 24rpx;
  429. .info-line {
  430. border-bottom: 1px solid #f4f4f4;
  431. padding: 24rpx 0;
  432. color: #333;
  433. font-family: "PingFang SC";
  434. font-size: 28rpx;
  435. line-height: 1.5;
  436. font-weight: 400;
  437. display: flex;
  438. align-items: center;
  439. &-label {
  440. flex: 0 0 162rpx;
  441. width: 162rpx;
  442. }
  443. &-value {
  444. word-break: break-all;
  445. }
  446. .must-box {
  447. color: #ff3b1d;
  448. }
  449. }
  450. }
  451. .min-height {
  452. height: 300rpx;
  453. overflow: hidden;
  454. }
  455. .btn-box {
  456. height: 112rpx;
  457. display: flex;
  458. align-items: center;
  459. justify-content: center;
  460. background-color: #fff;
  461. border-radius: 0 0 16rpx 16rpx;
  462. .btn-cont {
  463. display: flex;
  464. align-items: center;
  465. justify-content: center;
  466. width: 154rpx;
  467. height: 56rpx;
  468. border-radius: 120rpx;
  469. border: 1px solid #d9d9d9;
  470. color: #666;
  471. font-family: "PingFang SC";
  472. font-size: 28rpx;
  473. font-weight: 400;
  474. }
  475. }
  476. .scan-box {
  477. margin-top: 24rpx;
  478. padding: 24rpx 0;
  479. border-radius: 16rpx;
  480. background: #fff;
  481. display: flex;
  482. .tips-text {
  483. color: #333;
  484. font-size: 28rpx;
  485. font-weight: 400;
  486. line-height: 48rpx;
  487. }
  488. .tips-text2 {
  489. color: #0256ff;
  490. font-size: 24rpx;
  491. font-weight: 400;
  492. display: flex;
  493. align-items: center;
  494. .radio-box {
  495. width: 32rpx;
  496. height: 32rpx;
  497. border-radius: 50%;
  498. border: 1px solid #d9d9d9;
  499. margin-right: 16rpx;
  500. }
  501. }
  502. .scan-box-l {
  503. width: 100%;
  504. display: flex;
  505. flex-direction: column;
  506. align-items: center;
  507. position: relative;
  508. &::after {
  509. content: "";
  510. display: block;
  511. width: 1px;
  512. height: 138rpx;
  513. background-color: #f4f4f4;
  514. position: absolute;
  515. top: 50%;
  516. right: 0;
  517. transform: translateY(-50%);
  518. }
  519. }
  520. .scan-box-r {
  521. width: 50%;
  522. display: flex;
  523. flex-direction: column;
  524. align-items: center;
  525. }
  526. }
  527. .cargo-list {
  528. padding: 24rpx 0;
  529. background-color: #fff;
  530. margin-top: 24rpx;
  531. border-radius: 16rpx;
  532. .cargo-list-title {
  533. font-family: "PingFang SC";
  534. font-size: 32rpx;
  535. font-style: normal;
  536. font-weight: bold;
  537. display: flex;
  538. align-items: center;
  539. position: relative;
  540. padding-left: 50rpx;
  541. &::after {
  542. content: "";
  543. display: block;
  544. width: 6rpx;
  545. height: 30rpx;
  546. border-radius: 100px;
  547. background: #0256ff;
  548. position: absolute;
  549. top: 50%;
  550. left: 24rpx;
  551. transform: translateY(-50%);
  552. }
  553. .cargo-list-title-tips {
  554. color: #0256ff;
  555. font-size: 24rpx;
  556. font-weight: 400;
  557. }
  558. }
  559. .num-box {
  560. display: flex;
  561. align-items: center;
  562. justify-content: space-between;
  563. padding: 0 48rpx 0 26rpx;
  564. .num-box-text {
  565. color: #666;
  566. font-family: "PingFang SC";
  567. font-size: 28rpx;
  568. font-weight: 400;
  569. }
  570. .input {
  571. width: 112rpx;
  572. text-align: center;
  573. border-bottom: 1px solid #0256ff;
  574. margin: 0 8rpx;
  575. }
  576. .minus {
  577. width: 40rpx;
  578. height: 40rpx;
  579. border-radius: 8rpx;
  580. border: 1px solid #0256ff;
  581. display: flex;
  582. align-items: center;
  583. justify-content: center;
  584. }
  585. .plus {
  586. width: 40rpx;
  587. height: 40rpx;
  588. border-radius: 8rpx;
  589. background-color: #0256ff;
  590. display: flex;
  591. align-items: center;
  592. justify-content: center;
  593. }
  594. }
  595. }
  596. }
  597. .footer-box {
  598. background-color: #fff;
  599. height: 126rpx;
  600. position: fixed;
  601. bottom: 0;
  602. left: 0;
  603. right: 0;
  604. display: flex;
  605. align-items: center;
  606. justify-content: space-between;
  607. padding: 0 40rpx 0 60rpx;
  608. .footer-box-l {
  609. color: #666;
  610. font-family: "PingFang SC";
  611. font-size: 28rpx;
  612. font-weight: 400;
  613. }
  614. .submitBtn {
  615. width: 362rpx;
  616. height: 76rpx;
  617. border-radius: 16rpx;
  618. background: #0256ff;
  619. color: #fff;
  620. font-size: 28rpx;
  621. font-weight: 500;
  622. margin: 0;
  623. }
  624. }
  625. }
  626. </style>