delivery.vue 17 KB

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