index.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. <template>
  2. <div class="container">
  3. <van-nav-bar title="宝时快上" left-arrow fixed placeholder @click-left="goBack" z-index="100"
  4. @click-right="refresh()">
  5. <template #left>
  6. <van-icon name="arrow-left" size="25" />
  7. <div style="color: #fff">返回</div>
  8. </template>
  9. <template #right>
  10. <div style="color: #fff">刷新<van-icon name="replay" /></div>
  11. </template>
  12. </van-nav-bar>
  13. <div class="take-delivery">
  14. <div class="take-info">
  15. <div class="take-info-no">
  16. <div class="info-no-tips">
  17. <div>货主: <span style="color: #333;font-weight: bold;" v-if="barcodeActiveList.length>0">{{ ownerMap[barcodeActiveList[0].owner] || barcodeActiveList[0].owner }}</span>
  18. <span v-else>--</span>
  19. </div>
  20. <div>待上架数:<span style="color: #0077ff;font-weight: bold;">{{ totalQuantity || 0 }}</span></div>
  21. </div>
  22. </div>
  23. <div class="take-info-number">
  24. <div class="info-number-left">
  25. <div class="number-left-box">
  26. <div>开始时间</div>
  27. <div class="left-box-title">{{ currentTime }}</div>
  28. </div>
  29. <div class="number-left-box">
  30. <div>已用时</div>
  31. <div class="left-box-title">{{ formattedTime }}</div>
  32. </div>
  33. </div>
  34. <div class="info-number-right">
  35. <div>容器号</div>
  36. <div style="display: flex;justify-content:center;align-items: center;">
  37. <div style="flex: 1;font-size: 14px;font-weight: bold;color: #0077ff;line-height: 34px">
  38. {{ containerNo || '--' }}
  39. </div>
  40. <div style="width:50px">
  41. <van-button type="primary" size="mini" plain @click="switchTask">切换容器</van-button>
  42. </div>
  43. </div>
  44. </div>
  45. </div>
  46. </div>
  47. <div class="take-barcode">
  48. <div class="barcode-input">
  49. <van-search
  50. ref="searchRef"
  51. v-model="searchBarcode"
  52. placeholder="请扫描商品条码"
  53. @search="_handlerScan(searchBarcode)"
  54. label="商品条码:"
  55. left-icon=""
  56. :class="[scanType===2?'search-input-barcode':'','van-hairline--bottom']"
  57. @focus="scanType=2"
  58. autocomplete="off"
  59. @input="onAsnCancel"
  60. @clear="reset"
  61. >
  62. </van-search>
  63. </div>
  64. <div class="barcode-input">
  65. <van-search
  66. ref="locationRef"
  67. v-model="searchLocation"
  68. placeholder="请扫描库位编号"
  69. @search="_handlerScan(searchLocation)"
  70. label="库位编号:"
  71. left-icon=""
  72. :class="[scanType===3?'search-input-barcode':'','van-hairline--bottom']"
  73. @focus="scanType=3"
  74. autocomplete="off"
  75. >
  76. </van-search>
  77. </div>
  78. <div class="barcode-input">
  79. <van-search
  80. ref="numberRef"
  81. v-model="searchCount"
  82. placeholder="请输入上架数量"
  83. type="number"
  84. label="上架数量:"
  85. left-icon=""
  86. autocomplete="off"
  87. show-action
  88. :min="1"
  89. :max="barcodeQuantity(barcodeActiveList)"
  90. @search="onConfirm"
  91. :class="[scanType===4?'search-input-barcode':'','van-hairline--bottom','search-input-number']"
  92. @focus="scanType=4"
  93. >
  94. <template #action>
  95. <div style="display: flex; align-items: center;margin-left: 20px">
  96. <div style="font-size: 12px">预计:</div>
  97. <div style="font-size: 18px;font-weight: bold;color: #ee0a25">{{ barcodeQuantity(barcodeActiveList) }}
  98. </div>
  99. </div>
  100. </template>
  101. </van-search>
  102. </div>
  103. </div>
  104. <div class="take-lot" v-if="barcodeActiveList.length>0">
  105. <van-cell-group>
  106. <div class="take-lot-title">批次信息</div>
  107. <template v-for="(value, key) in lotAttributes" :key="key">
  108. <van-cell v-if="barcodeActiveList[0][key]">
  109. <template #title>
  110. <van-icon name="warning-o" color="#ed6a0c" />
  111. <span class="custom-title">{{ value.title }}</span>
  112. </template>
  113. <template #value>
  114. <div>{{ barcodeActiveList[0][key] }}</div>
  115. </template>
  116. </van-cell>
  117. </template>
  118. </van-cell-group>
  119. </div>
  120. <div class="take-button">
  121. <div class="btn" type="primary" size="large" round style="height: 36px" @click="onConfirm">上架</div>
  122. </div>
  123. <div>
  124. <location-list :locationList="locationList" />
  125. </div>
  126. </div>
  127. </div>
  128. <!-- 条码输入组件 -->
  129. <input-barcode :back="back" @setBarcode="setBarcode" ref="inputBarcodeRef" />
  130. <!-- 单据选择-->
  131. <van-action-sheet v-model:show="lotBarcodeTrueFalseBy" cancel-text="取消" description="请选择具体单据"
  132. close-on-click-action>
  133. <van-cell-group>
  134. <van-cell v-for="item in lotBarcodeList" @click="onDetailActive(item)">
  135. <template #title>
  136. {{ item[0].barcode }}({{ item[0].lotNumber }}-{{ barcodeQuantity(item) }}件)
  137. </template>
  138. <template #label>
  139. 生产日期:{{ item[0].lotAtt01 || '--' }}-失效日期:{{ item[0].lotAtt02 || '--' }}
  140. </template>
  141. </van-cell>
  142. </van-cell-group>
  143. </van-action-sheet>
  144. <!-- 推荐库位列表-->
  145. <van-action-sheet v-model:show="locationTrueFalseBy" cancel-text="取消" description="推荐库位列表"
  146. close-on-click-action>
  147. <div style="max-height: 60vh;overflow: auto;">
  148. <location-list :locationList="locationList" />
  149. </div>
  150. </van-action-sheet>
  151. <!-- 组合商品上架数量-->
  152. <barcode-combine ref="barcodeCombineRef" @setCombine="setPutawayCombine" @cancel="onCombineCancel" :matched-sku="combineMatchedSku" />
  153. </template>
  154. <script setup>
  155. import { onMounted, onUnmounted, ref, computed } from 'vue'
  156. import { androidFocus, getHeader, goBack, scanError, scanSuccess } from '@/utils/android'
  157. import InputBarcode from '@/views/outbound/picking/components/InputBarcode.vue'
  158. import LocationList from '@/views/inbound/putaway/components/LocationList.vue'
  159. import BarcodeCombine from '@/views/inbound/putaway/components/BarcodeCombine.vue'
  160. import { openListener,closeListener,scanInit } from '@/utils/keydownListener.js'
  161. import { useRouter } from 'vue-router'
  162. import { closeLoading, showLoading } from '@/utils/loading'
  163. import { useStore } from '@/store/modules/user'
  164. import { showNotify, showToast } from 'vant'
  165. import { getCurrentTime } from '@/utils/date'
  166. import { getWaitPutawayListNew, setPutawayNew } from '@/api/putaway/index'
  167. import { getListCombineSku } from '@/api/picking'
  168. import { barcodeToUpperCase } from '@/utils/dataType.js'
  169. import { getRecommendedLocation } from '@/api/haikang/index'
  170. import { getOwnerList } from '@/hooks/basic/index'
  171. const router = useRouter()
  172. const store = useStore()
  173. try {
  174. getHeader()
  175. androidFocus()
  176. } catch (error) {
  177. router.push('/login')
  178. }
  179. // 页面初始化
  180. onMounted(() => {
  181. openListener()
  182. scanInit(_handlerScan)
  183. loadData()
  184. })
  185. const warehouse = store.warehouse
  186. //容器号
  187. const containerNo = ref('')
  188. //数据列表
  189. const dataList = ref([])
  190. //
  191. const dataMap = ref({})
  192. //库位列表
  193. const locationTrueFalseBy = ref(false)
  194. const locationList = ref([])
  195. //商品条码
  196. const searchBarcode = ref('')
  197. //库位
  198. const searchLocation = ref('')
  199. //收货数量
  200. const searchCount = ref('')
  201. //收货详情
  202. const taskInfo = ref({})
  203. //开始时间
  204. const currentTime = ref('--')
  205. const scanType = ref(2)
  206. const putweayType=ref('def')
  207. const lotAttributes = {
  208. lotAtt01: { title: '生产日期' },
  209. lotAtt02: { title: '失效日期' },
  210. lotAtt03: { title: '入库日期' },
  211. lotAtt04: { title: '生产批号' },
  212. lotAtt05: { title: '属性仓' },
  213. lotAtt08: { title: '质量状态' },
  214. }
  215. // 获取货主
  216. const { ownerMap, getOwnerData } = getOwnerList()
  217. getOwnerData()
  218. //待上架数
  219. const totalQuantity = computed(() => {
  220. return dataList.value.reduce((sum, item) => sum + Number(item.quantity), 0)
  221. })
  222. //待上架数
  223. const barcodeQuantity = (list) => {
  224. return list.reduce((sum, item) => sum + Number(item.quantity), 0)
  225. }
  226. const back = ref(true)
  227. const inputBarcodeType = ref('task')
  228. //输入框组件
  229. const inputBarcodeRef = ref(null)
  230. const oldSearchBarcode = ref('')
  231. /**
  232. * 计算时分秒
  233. */
  234. // 时器的总秒数
  235. let totalSeconds = ref(0)
  236. //时分秒
  237. const formattedTime = ref('00:00:00')
  238. let windowTimer = null // 计时器的引用
  239. const updateFormattedTime = () => {
  240. let hours = Math.floor(totalSeconds.value / 3600)
  241. let minutes = Math.floor((totalSeconds.value % 3600) / 60)
  242. let seconds = totalSeconds.value % 60
  243. formattedTime.value = `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`
  244. }
  245. // 启动计时器
  246. const startTimer = () => {
  247. if (!windowTimer) {
  248. windowTimer = setInterval(() => {
  249. totalSeconds.value++
  250. updateFormattedTime()
  251. }, 1000)
  252. }
  253. }
  254. // 停止计时器
  255. const stopTimer = () => {
  256. if (windowTimer) {
  257. clearInterval(windowTimer)
  258. windowTimer = null
  259. }
  260. }
  261. // 设置容器号
  262. const setBarcode = (code, type) => {
  263. showLoading()
  264. if (!type) { //切换任务时初始化计时器
  265. stopTimer()
  266. formattedTime.value = '00:00:00'
  267. totalSeconds.value = 0
  268. }
  269. const params = { warehouseId:warehouse, containerId: code }
  270. getWaitPutawayListNew(params).then(res => {
  271. reset()
  272. scanType.value=2
  273. back.value = true
  274. if (!type) {//切换任务成功重启计时器
  275. currentTime.value = getCurrentTime()
  276. startTimer()
  277. }
  278. if (res.data.asnToShelfList.length > 0 || res.data.noAsnToShelfList.length>0 ) {
  279. const asnToShelfList = res.data.asnToShelfList.map(item => {
  280. return {
  281. ...item,
  282. totalQuantity: 0,
  283. type:'asn'
  284. }
  285. })
  286. // 先映射数据
  287. const noAsnToShelfListTemp = res.data.noAsnToShelfList.map(item => {
  288. return {
  289. ...item,
  290. lotNumber: item.lotNum,
  291. lotAtt01: item.productDate,
  292. lotAtt02: item.expireDate,
  293. lotAtt04: item.productNum,
  294. lotAtt08: item.quality,
  295. quantity: item.remainShelfQty,
  296. taskLineNo: item.id,
  297. owner:item.customer,
  298. type:'noAsn'
  299. }
  300. })
  301. // 按照 lotNumber 和 businessNo 分组并累加 quantity
  302. const groupedMap = {}
  303. noAsnToShelfListTemp.forEach(item => {
  304. const key = `${item.lotNumber}_${item.businessNo || ''}`
  305. if (!groupedMap[key]) {
  306. groupedMap[key] = {
  307. items: [],
  308. totalQuantity: 0
  309. }
  310. }
  311. groupedMap[key].items.push(item)
  312. groupedMap[key].totalQuantity += Number(item.quantity) || 0
  313. })
  314. // 更新每项的 totalQuantity 为累加后的值
  315. const noAsnToShelfList = noAsnToShelfListTemp.map(item => {
  316. const key = `${item.lotNumber}_${item.businessNo || ''}`
  317. return {
  318. ...item,
  319. totalQuantity: groupedMap[key].totalQuantity
  320. }
  321. })
  322. dataList.value = [...asnToShelfList,...noAsnToShelfList]
  323. dataMap.value = groupedData(dataList.value)
  324. containerNo.value = code
  325. scanSuccess()
  326. } else {
  327. reset()
  328. dataMap.value = {}
  329. dataList.value = []
  330. inputBarcodeRef.value?.show('', '请扫描容器号', '暂无待上架信息')
  331. scanError()
  332. }
  333. }).catch(err => {
  334. reset()
  335. dataMap.value = {}
  336. dataList.value = []
  337. inputBarcodeRef.value?.show('', '请扫描容器号', err.message)
  338. scanError()
  339. }).finally(() => {
  340. closeLoading()
  341. })
  342. }
  343. //根据条码批次分组数据
  344. const groupedData = (data) => {
  345. return data.reduce((acc, item) => {
  346. const key = `{${item.barcode}、${item.barcodeAs}、${item.sku}}-${item.lotNumber}`
  347. if (acc[key]) {
  348. acc[key].push(item)
  349. } else {
  350. acc[key] = [item]
  351. }
  352. return acc
  353. }, {})
  354. }
  355. //匹配待上架列表数据
  356. const matchingBarcodeItem = (data, barcode) => {
  357. const matchingItems = []
  358. for (const key in data) {
  359. const barcodeList = key.match(/\{(.*?)\}/)[1].split('、')
  360. if (data.hasOwnProperty(key)) {
  361. if (barcodeList.some(item => barcodeToUpperCase(item) === barcodeToUpperCase(barcode))) {
  362. matchingItems.push(data[key])
  363. }
  364. }
  365. }
  366. return matchingItems.length > 0 ? matchingItems : []
  367. }
  368. // setBarcode()
  369. //切换任务
  370. const switchTask = () => {
  371. inputBarcodeType.value = 'switchTask'
  372. back.value = false
  373. inputBarcodeRef.value?.show('', `请扫描容器号`, '')
  374. }
  375. //批次数据
  376. const lotBarcodeList = ref([])
  377. const lotBarcodeTrueFalseBy = ref(false)
  378. const barcodeActiveList = ref([])
  379. // 组合商品
  380. const barcodeCombineRef = ref(null)
  381. const putawayCombineData = ref(null)
  382. const combineMatchedSku = ref([])
  383. const reset = () => {
  384. searchCount.value = ''
  385. searchBarcode.value = ''
  386. searchLocation.value = ''
  387. oldSearchBarcode.value = ''
  388. locationList.value = []
  389. barcodeActiveList.value = []
  390. putawayCombineData.value = null
  391. combineMatchedSku.value = []
  392. }
  393. // 组合商品上架数量弹框
  394. const _showPutawayCombineDialog = (batchItem) => {
  395. if (!putawayCombineData.value || !batchItem?.length) return
  396. const total = batchItem.reduce((sum, i) => sum + Number(i.quantity || 0), 0)
  397. combineMatchedSku.value = [{
  398. matchedJson: putawayCombineData.value,
  399. expectedQuantity: total,
  400. receivedQuantity: 0,
  401. }]
  402. barcodeCombineRef.value?.show()
  403. }
  404. // 组合商品确认上架数量
  405. const setPutawayCombine = ({ dataList }) => {
  406. if (dataList?.[0]?.quantity != null) {
  407. searchCount.value = String(dataList[0].quantity)
  408. }
  409. showNotify({ type: 'success', duration: 2000, message: `已填入上架数量:${searchCount.value},请扫描库位并确认上架` })
  410. }
  411. // 组合商品取消
  412. const onCombineCancel = () => {
  413. const qtyPerSet = putawayCombineData.value?.quantity ?? 1
  414. searchCount.value = String(qtyPerSet)
  415. }
  416. // 选择单据
  417. const onDetailActive = (item) => {
  418. barcodeActiveList.value = item
  419. lotBarcodeTrueFalseBy.value = false
  420. if (putawayCombineData.value) {
  421. _showPutawayCombineDialog(item)
  422. _getRecommendedLocation(item[0].lotNumber, item[0].owner)
  423. scanType.value = 3
  424. return
  425. }
  426. searchCount.value = 1
  427. scanType.value = 3
  428. _getRecommendedLocation(item[0].lotNumber, item[0].owner)
  429. scanSuccess()
  430. }
  431. const onAsnCancel = () => {
  432. if (searchBarcode.value === '' || (oldSearchBarcode.value.length != searchBarcode.value.length && oldSearchBarcode.value != '')) {
  433. barcodeActiveList.value = []
  434. searchCount.value = ''
  435. locationList.value = []
  436. }
  437. }
  438. // 商品条码不匹配时,查询组合条码
  439. const _handlePutawayCombineProduct = (code) => {
  440. showLoading()
  441. getListCombineSku({ combineSku: barcodeToUpperCase(code), workEnvironment: 'inbound' })
  442. .then((res) => {
  443. const _err = (msg) => {
  444. closeLoading()
  445. scanError()
  446. showNotify({ type: 'danger', duration: 3000, message: msg })
  447. reset()
  448. }
  449. if (!res.data?.length) return _err(`${code}-商品条码不匹配,请重新扫描`)
  450. if (res.data.length > 1) return _err('不支持多商品组合商品')
  451. const combineBarcode = res.data[0].barcode
  452. lotBarcodeList.value = matchingBarcodeItem(dataMap.value, combineBarcode)
  453. if (lotBarcodeList.value.length === 0) return _err('组合商品与待上架数据不匹配,请检查组合商品配置!')
  454. putawayCombineData.value = res.data[0]
  455. closeLoading()
  456. scanSuccess()
  457. if (lotBarcodeList.value.length === 1) {
  458. barcodeActiveList.value = lotBarcodeList.value[0]
  459. _showPutawayCombineDialog(lotBarcodeList.value[0])
  460. _getRecommendedLocation(barcodeActiveList.value[0].lotNumber, barcodeActiveList.value[0].owner)
  461. scanType.value = 3
  462. } else {
  463. locationList.value = []
  464. barcodeActiveList.value = []
  465. searchCount.value = ''
  466. searchLocation.value = ''
  467. lotBarcodeTrueFalseBy.value = true
  468. }
  469. })
  470. .catch(() => {
  471. closeLoading()
  472. scanError()
  473. showNotify({ type: 'danger', duration: 3000, message: `${code}-商品条码不匹配,请重新扫描` })
  474. reset()
  475. })
  476. }
  477. // 扫描条码监听
  478. const _handlerScan = (code) => {
  479. if (scanType.value == 2) {
  480. searchBarcode.value = code
  481. oldSearchBarcode.value = code
  482. lotBarcodeList.value = matchingBarcodeItem(dataMap.value, code)
  483. if (lotBarcodeList.value.length > 0) {
  484. putawayCombineData.value = null
  485. combineMatchedSku.value = []
  486. if (lotBarcodeList.value.length == 1) {
  487. barcodeActiveList.value = lotBarcodeList.value[0]
  488. _getRecommendedLocation(barcodeActiveList.value[0].lotNumber, barcodeActiveList.value[0].owner)
  489. scanType.value = 3
  490. scanSuccess()
  491. } else if (lotBarcodeList.value.length > 1) {
  492. locationList.value = []
  493. barcodeActiveList.value = []
  494. searchCount.value = ''
  495. searchLocation.value = ''
  496. lotBarcodeTrueFalseBy.value = true
  497. }
  498. } else {
  499. _handlePutawayCombineProduct(code)
  500. }
  501. } else if (scanType.value == 3) {
  502. searchLocation.value = barcodeToUpperCase(code)
  503. scanType.value = 4
  504. if (!searchCount.value) searchCount.value = 1
  505. scanSuccess()
  506. }
  507. }
  508. // 获取库存数据
  509. const _getRecommendedLocation = async (lotNum, owner) => {
  510. try {
  511. const params = { warehouse, lotNum, owner }
  512. const res = await getRecommendedLocation(params)
  513. locationList.value = res.data
  514. } catch (err) {
  515. console.error(err)
  516. }
  517. }
  518. const numberRef = ref(null)
  519. const locationRef = ref(null)
  520. // 完成收货校验
  521. const isCheck = () => {
  522. if (searchLocation.value == '') {
  523. locationRef.value?.focus()
  524. scanError()
  525. showToast({ duration: 3000, message: '请先扫描库位编号' })
  526. return false
  527. }
  528. if (searchCount.value == '') {
  529. numberRef.value?.focus()
  530. scanError()
  531. showToast({ duration: 3000, message: '请先输入上架数量' })
  532. return false
  533. }
  534. const maxQuantity = barcodeQuantity(barcodeActiveList.value)
  535. if (Number(searchCount.value) > maxQuantity) {
  536. numberRef.value?.focus()
  537. scanError()
  538. showToast({ duration: 3000, message: `上架数量最大为:${maxQuantity}` })
  539. return false
  540. }
  541. return true
  542. }
  543. // 上架
  544. const onConfirm = () => {
  545. if (isCheck()) {
  546. const quantity = searchCount.value
  547. const asnDoShelfList = []
  548. const noAsnDoShelfList=[]
  549. const list = structuredClone(barcodeActiveList.value) // 深拷贝,保证原始数据不被修改
  550. // 按照 totalQuantity 从小到大排序,优先扣除最小的
  551. list.sort((a, b) => {
  552. const totalQuantityA = Number(a.totalQuantity || a.quantity || 0)
  553. const totalQuantityB = Number(b.totalQuantity || b.quantity || 0)
  554. return totalQuantityA - totalQuantityB
  555. })
  556. let remainingQuantity = quantity
  557. for (let i = 0; i < list.length && remainingQuantity > 0; i++) {
  558. const { taskNo, taskLineNo, warehouse, quantity } = list[i]
  559. const takeQuantity = Math.min(quantity, remainingQuantity)
  560. if(list[i].type=='asn'){
  561. asnDoShelfList.push({
  562. taskNo,
  563. taskLineNo,
  564. warehouse,
  565. container: '*',
  566. targetCode: searchLocation.value,
  567. quantity: takeQuantity, // 当前项扣除的数量
  568. })
  569. }else {
  570. noAsnDoShelfList.push({
  571. id:taskLineNo,
  572. location:searchLocation.value,
  573. qty:takeQuantity
  574. })
  575. }
  576. remainingQuantity -= takeQuantity
  577. }
  578. showLoading()
  579. setPutawayNew({asnDoShelfList,noAsnDoShelfList}).then(res => {
  580. if (totalQuantity.value - Number(searchCount.value) == 0) {
  581. containerNo.value = ''
  582. dataMap.value = {}
  583. dataList.value = []
  584. showNotify({ type: 'success', message: '当前任务已上架完成,请扫描下一个容器号', duration: 3000 })
  585. inputBarcodeRef.value?.show('', '请扫描容器号', '')
  586. stopTimer()
  587. } else {
  588. showNotify({ type: 'success', message: '上架成功,请继续扫描商品进行上架', duration: 3000 })
  589. setBarcode(containerNo.value, 'success')
  590. scanType.value = 2
  591. }
  592. reset()
  593. scanSuccess()
  594. }).catch(err => {
  595. scanError()
  596. }).finally(() => {
  597. closeLoading()
  598. })
  599. }
  600. }
  601. const refresh=()=>{
  602. reset()
  603. scanType.value=2
  604. loadData()
  605. }
  606. // 数据刷新
  607. const loadData = () => {
  608. if (!containerNo.value) {
  609. inputBarcodeRef.value?.show('', '请扫描容器号', '')
  610. return
  611. } else {
  612. setBarcode(containerNo.value, 'container')
  613. // currentTime.value=getCurrentTime()
  614. // startTimer()
  615. }
  616. }
  617. onUnmounted(() => {
  618. closeListener()
  619. stopTimer()
  620. })
  621. window.onRefresh = loadData
  622. </script>
  623. <style scoped lang="sass">
  624. .take-delivery
  625. .take-info
  626. padding: 6px 10px
  627. background: linear-gradient(to left, #c8e2fb, #ffffff)
  628. display: flex
  629. flex-direction: column
  630. text-align: left
  631. .take-info-no
  632. flex: 1
  633. .info-no-title
  634. font-size: 19px
  635. font-width: 500
  636. display: flex
  637. justify-content: space-between
  638. align-items: center
  639. .info-no-tips
  640. font-size: 14px
  641. color: #666666
  642. display: flex
  643. justify-content: space-between
  644. padding: 6px 0
  645. .take-info-number
  646. flex: 1
  647. border-top: 1.5px solid #efefef
  648. display: flex
  649. justify-content: space-between
  650. gap: 10px
  651. color: #666
  652. font-size: 14px
  653. padding-top: 10px
  654. .info-number-left
  655. flex: 1
  656. display: flex
  657. justify-content: space-evenly
  658. align-items: center
  659. .number-left-box
  660. flex: 1
  661. display: flex
  662. flex-direction: column
  663. align-items: center
  664. .left-box-title
  665. font-size: 14px
  666. font-weight: bold
  667. color: #000
  668. line-height: 34px
  669. .info-number-right
  670. width: 45%
  671. text-align: center
  672. .van-search
  673. padding: 0
  674. .take-barcode
  675. margin-top: 10px
  676. text-align: left
  677. background: #FFFFFF
  678. .barcode-input
  679. ::v-deep(.van-search)
  680. padding: 0
  681. height: 50px
  682. display: flex
  683. align-items: center
  684. ::v-deep(.van-search__field)
  685. border-bottom: 2px solid #ffffff
  686. display: flex
  687. align-items: center
  688. height: 50px
  689. ::v-deep(.van-search__content)
  690. background: #fff
  691. display: flex
  692. align-items: center
  693. height: 50px
  694. ::v-deep(.van-field__control)
  695. font-size: 16px
  696. font-weight: bold
  697. ::v-deep(.van-search__label)
  698. font-size: 16px
  699. font-weight: bold
  700. .search-input-barcode
  701. ::v-deep(.van-search__field)
  702. border-bottom: 2px solid #0077ff
  703. z-index: 2
  704. .search-input-number
  705. ::v-deep(.van-field__control)
  706. font-size: 16px
  707. font-weight: bold
  708. color: #ee0a25
  709. .take-lot
  710. text-align: left
  711. margin-top: 5px
  712. ::v-deep(.van-cell)
  713. padding: 5px 8px
  714. .take-lot-title
  715. font-size: 15px
  716. font-weight: bold
  717. padding: 0 5px
  718. border-left: 3px solid #1989fa
  719. color: #333
  720. margin-bottom: 3px
  721. .take-button
  722. padding: 10px 20px
  723. .btn
  724. background: #1989fa
  725. color: #fff
  726. font-size: 16px
  727. line-height: 35px
  728. border-radius: 8px
  729. </style>