| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876 |
- <template>
- <div class="container">
- <van-nav-bar title="宝时快上" left-arrow fixed placeholder @click-left="goBack" z-index="100"
- @click-right="refresh()">
- <template #left>
- <van-icon name="arrow-left" size="25" />
- <div style="color: #fff">返回</div>
- </template>
- <template #right>
- <div style="color: #fff">刷新<van-icon name="replay" /></div>
- </template>
- </van-nav-bar>
- <div class="take-delivery">
- <div class="take-info">
- <div class="take-info-no">
- <div class="info-no-tips">
- <div>货主: <span style="color: #333;font-weight: bold;" v-if="barcodeActiveList.length>0">{{ ownerMap[barcodeActiveList[0].owner] || barcodeActiveList[0].owner }}</span>
- <span v-else>--</span>
- </div>
- <div>待上架数:<span style="color: #0077ff;font-weight: bold;">{{ totalQuantity || 0 }}</span></div>
- </div>
- </div>
- <div class="take-info-number">
- <div class="info-number-left">
- <div class="number-left-box">
- <div>开始时间</div>
- <div class="left-box-title">{{ currentTime }}</div>
- </div>
- <div class="number-left-box">
- <div>已用时</div>
- <div class="left-box-title">{{ formattedTime }}</div>
- </div>
- </div>
- <div class="info-number-right">
- <div>容器号</div>
- <div style="display: flex;justify-content:center;align-items: center;">
- <div style="flex: 1;font-size: 14px;font-weight: bold;color: #0077ff;line-height: 34px">
- {{ containerNo || '--' }}
- </div>
- <div style="width:50px">
- <van-button type="primary" size="mini" plain @click="switchTask">切换容器</van-button>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div class="take-barcode">
- <div class="barcode-input">
- <van-search
- ref="searchRef"
- v-model="searchBarcode"
- placeholder="请扫描商品条码"
- @search="_handlerScan(searchBarcode)"
- label="商品条码:"
- left-icon=""
- :class="[scanType===2?'search-input-barcode':'','van-hairline--bottom']"
- @focus="scanType=2"
- autocomplete="off"
- @input="onAsnCancel"
- @clear="reset"
- >
- </van-search>
- </div>
- <div class="barcode-input">
- <van-search
- ref="locationRef"
- v-model="searchLocation"
- placeholder="请扫描库位编号"
- @search="_handlerScan(searchLocation)"
- label="库位编号:"
- left-icon=""
- :class="[scanType===3?'search-input-barcode':'','van-hairline--bottom']"
- @focus="scanType=3"
- autocomplete="off"
- >
- <template #right-icon>
- <van-button
- v-if="forcePublishEnabled && barcodeActiveList.length > 0"
- type="primary"
- size="mini"
- plain
- :loading="changeLocationLoading"
- @click.stop="onChangeLocation"
- >
- 换一换
- </van-button>
- </template>
- </van-search>
- </div>
- <div class="barcode-input">
- <van-search
- ref="numberRef"
- v-model="searchCount"
- placeholder="请输入上架数量"
- type="number"
- label="上架数量:"
- left-icon=""
- autocomplete="off"
- show-action
- :min="1"
- :max="barcodeQuantity(barcodeActiveList)"
- @search="onConfirm"
- :class="[scanType===4?'search-input-barcode':'','van-hairline--bottom','search-input-number']"
- @focus="scanType=4"
- >
- <template #action>
- <div style="display: flex; align-items: center;margin-left: 20px">
- <div style="font-size: 12px">预计:</div>
- <div style="font-size: 18px;font-weight: bold;color: #ee0a25">{{ barcodeQuantity(barcodeActiveList) }}
- </div>
- </div>
- </template>
- </van-search>
- </div>
- </div>
- <div class="take-lot" v-if="barcodeActiveList.length>0">
- <van-cell-group>
- <div class="take-lot-title">批次信息</div>
- <template v-for="(value, key) in lotAttributes" :key="key">
- <van-cell v-if="barcodeActiveList[0][key]">
- <template #title>
- <van-icon name="warning-o" color="#ed6a0c" />
- <span class="custom-title">{{ value.title }}</span>
- </template>
- <template #value>
- <div>{{ barcodeActiveList[0][key] }}</div>
- </template>
- </van-cell>
- </template>
- </van-cell-group>
- </div>
- <div class="take-button">
- <div class="btn" type="primary" size="large" round style="height: 36px" @click="onConfirm">上架</div>
- </div>
- <div>
- <location-list :locationList="locationList" :legacy="!forcePublishEnabled" />
- </div>
- </div>
- </div>
- <!-- 条码输入组件 -->
- <input-barcode :back="back" @setBarcode="setBarcode" ref="inputBarcodeRef" />
- <!-- 单据选择-->
- <van-action-sheet v-model:show="lotBarcodeTrueFalseBy" cancel-text="取消" description="请选择具体单据"
- close-on-click-action>
- <van-cell-group>
- <van-cell v-for="item in lotBarcodeList" @click="onDetailActive(item)">
- <template #title>
- {{ item[0].barcode }}({{ item[0].lotNumber }}-{{ barcodeQuantity(item) }}件)
- </template>
- <template #label>
- 生产日期:{{ item[0].lotAtt01 || '--' }}-失效日期:{{ item[0].lotAtt02 || '--' }}
- </template>
- </van-cell>
- </van-cell-group>
- </van-action-sheet>
- <!-- 推荐库位列表-->
- <van-action-sheet v-model:show="locationTrueFalseBy" cancel-text="取消" description="推荐库位列表"
- close-on-click-action>
- <div style="max-height: 60vh;overflow: auto;">
- <location-list :locationList="locationList" :legacy="!forcePublishEnabled" />
- </div>
- </van-action-sheet>
- <!-- 组合商品上架数量-->
- <barcode-combine ref="barcodeCombineRef" @setCombine="setPutawayCombine" @cancel="onCombineCancel" :matched-sku="combineMatchedSku" />
- </template>
- <script setup>
- import { onMounted, onUnmounted, ref, computed } from 'vue'
- import { androidFocus, getHeader, goBack, scanError, scanSuccess } from '@/utils/android'
- import InputBarcode from '@/views/outbound/picking/components/InputBarcode.vue'
- import LocationList from '@/views/inbound/putaway/components/LocationList.vue'
- import BarcodeCombine from '@/views/inbound/putaway/components/BarcodeCombine.vue'
- import { openListener,closeListener,scanInit } from '@/utils/keydownListener.js'
- import { useRouter } from 'vue-router'
- import { closeLoading, showLoading } from '@/utils/loading'
- import { useStore } from '@/store/modules/user'
- import { showNotify, showToast } from 'vant'
- import { getCurrentTime } from '@/utils/date'
- import { getWaitPutawayListNew, setPutawayNew } from '@/api/putaway/index'
- import { getListCombineSku } from '@/api/picking'
- import { barcodeToUpperCase } from '@/utils/dataType.js'
- import { getRecommendedLocation, getRecommendedLocationNew } from '@/api/haikang/index'
- import { findSysParamByKey } from '@/api/basic/index'
- import { getOwnerList } from '@/hooks/basic/index'
- const router = useRouter()
- const store = useStore()
- try {
- getHeader()
- androidFocus()
- } catch (error) {
- router.push('/login')
- }
- /** 查询参数配置-精准推荐是否开启 */
- const forcePublishEnabled = ref(true)
- async function loadForcePublishParam() {
- try {
- const res = await findSysParamByKey({ paramKey: 'FORCE_PUBLISH_ENABLED' })
- console.log(res)
- if (res?.data && res.data=='true') {
- forcePublishEnabled.value = true
- }else{
- forcePublishEnabled.value = false
- }
- } catch (e) {
- console.error(e)
- }
- }
- // 页面初始化
- onMounted(async () => {
- openListener()
- scanInit(_handlerScan)
- await loadForcePublishParam()
- loadData()
- })
- const warehouse = store.warehouse
- //容器号
- const containerNo = ref('')
- //数据列表
- const dataList = ref([])
- //
- const dataMap = ref({})
- //库位列表
- const locationTrueFalseBy = ref(false)
- const locationList = ref([])
- //商品条码
- const searchBarcode = ref('')
- //库位
- const searchLocation = ref('')
- //收货数量
- const searchCount = ref('')
- //收货详情
- const taskInfo = ref({})
- //开始时间
- const currentTime = ref('--')
- const scanType = ref(2)
- const putweayType=ref('def')
- const lotAttributes = {
- lotAtt01: { title: '生产日期' },
- lotAtt02: { title: '失效日期' },
- lotAtt03: { title: '入库日期' },
- lotAtt04: { title: '生产批号' },
- lotAtt05: { title: '属性仓' },
- lotAtt08: { title: '质量状态' },
- }
- // 获取货主
- const { ownerMap, getOwnerData } = getOwnerList()
- getOwnerData()
- //待上架数
- const totalQuantity = computed(() => {
- return dataList.value.reduce((sum, item) => sum + Number(item.quantity), 0)
- })
- //待上架数
- const barcodeQuantity = (list) => {
- return list.reduce((sum, item) => sum + Number(item.quantity), 0)
- }
- const back = ref(true)
- const inputBarcodeType = ref('task')
- //输入框组件
- const inputBarcodeRef = ref(null)
- const oldSearchBarcode = ref('')
- /**
- * 计算时分秒
- */
- // 时器的总秒数
- let totalSeconds = ref(0)
- //时分秒
- const formattedTime = ref('00:00:00')
- let windowTimer = null // 计时器的引用
- const updateFormattedTime = () => {
- let hours = Math.floor(totalSeconds.value / 3600)
- let minutes = Math.floor((totalSeconds.value % 3600) / 60)
- let seconds = totalSeconds.value % 60
- formattedTime.value = `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`
- }
- // 启动计时器
- const startTimer = () => {
- if (!windowTimer) {
- windowTimer = setInterval(() => {
- totalSeconds.value++
- updateFormattedTime()
- }, 1000)
- }
- }
- // 停止计时器
- const stopTimer = () => {
- if (windowTimer) {
- clearInterval(windowTimer)
- windowTimer = null
- }
- }
- // 设置容器号
- const setBarcode = (code, type) => {
- showLoading()
- if (!type) { //切换任务时初始化计时器
- stopTimer()
- formattedTime.value = '00:00:00'
- totalSeconds.value = 0
- }
- const params = { warehouseId:warehouse, containerId: code }
- getWaitPutawayListNew(params).then(res => {
- reset()
- scanType.value=2
- back.value = true
- if (!type) {//切换任务成功重启计时器
- currentTime.value = getCurrentTime()
- startTimer()
- }
- if (res.data.asnToShelfList.length > 0 || res.data.noAsnToShelfList.length>0 ) {
- const asnToShelfList = res.data.asnToShelfList.map(item => {
- return {
- ...item,
- totalQuantity: 0,
- type:'asn'
- }
- })
- // 先映射数据
- const noAsnToShelfListTemp = res.data.noAsnToShelfList.map(item => {
- return {
- ...item,
- lotNumber: item.lotNum,
- lotAtt01: item.productDate,
- lotAtt02: item.expireDate,
- lotAtt04: item.productNum,
- lotAtt08: item.quality,
- quantity: item.remainShelfQty,
- taskLineNo: item.id,
- owner:item.customer,
- type:'noAsn'
- }
- })
- // 按照 lotNumber 和 businessNo 分组并累加 quantity
- const groupedMap = {}
- noAsnToShelfListTemp.forEach(item => {
- const key = `${item.lotNumber}_${item.businessNo || ''}`
- if (!groupedMap[key]) {
- groupedMap[key] = {
- items: [],
- totalQuantity: 0
- }
- }
- groupedMap[key].items.push(item)
- groupedMap[key].totalQuantity += Number(item.quantity) || 0
- })
- // 更新每项的 totalQuantity 为累加后的值
- const noAsnToShelfList = noAsnToShelfListTemp.map(item => {
- const key = `${item.lotNumber}_${item.businessNo || ''}`
- return {
- ...item,
- totalQuantity: groupedMap[key].totalQuantity
- }
- })
- dataList.value = [...asnToShelfList,...noAsnToShelfList]
- dataMap.value = groupedData(dataList.value)
- containerNo.value = code
- scanSuccess()
- } else {
- reset()
- dataMap.value = {}
- dataList.value = []
- inputBarcodeRef.value?.show('', '请扫描容器号', '暂无待上架信息')
- scanError()
- }
- }).catch(err => {
- reset()
- dataMap.value = {}
- dataList.value = []
- inputBarcodeRef.value?.show('', '请扫描容器号', err.message)
- scanError()
- }).finally(() => {
- closeLoading()
- })
- }
- //根据条码批次分组数据
- const groupedData = (data) => {
- return data.reduce((acc, item) => {
- const key = `{${item.barcode}、${item.barcodeAs}、${item.sku}}-${item.lotNumber}`
- if (acc[key]) {
- acc[key].push(item)
- } else {
- acc[key] = [item]
- }
- return acc
- }, {})
- }
- //匹配待上架列表数据
- const matchingBarcodeItem = (data, barcode) => {
- const matchingItems = []
- for (const key in data) {
- const barcodeList = key.match(/\{(.*?)\}/)[1].split('、')
- if (data.hasOwnProperty(key)) {
- if (barcodeList.some(item => barcodeToUpperCase(item) === barcodeToUpperCase(barcode))) {
- matchingItems.push(data[key])
- }
- }
- }
- return matchingItems.length > 0 ? matchingItems : []
- }
- // setBarcode()
- //切换任务
- const switchTask = () => {
- inputBarcodeType.value = 'switchTask'
- back.value = false
- if (forcePublishEnabled.value) excludedLocations.value = {}
- inputBarcodeRef.value?.show('', `请扫描容器号`, '')
- }
- //批次数据
- const lotBarcodeList = ref([])
- const lotBarcodeTrueFalseBy = ref(false)
- const barcodeActiveList = ref([])
- // 组合商品
- const barcodeCombineRef = ref(null)
- const putawayCombineData = ref(null)
- const combineMatchedSku = ref([])
- // 已推荐过的库位,按 lotNum 批次维度存储,用于换一换时排除
- const excludedLocations = ref({})
- // 换一换按钮 loading
- const changeLocationLoading = ref(false)
- const reset = () => {
- searchCount.value = ''
- searchBarcode.value = ''
- searchLocation.value = ''
- oldSearchBarcode.value = ''
- locationList.value = []
- barcodeActiveList.value = []
- putawayCombineData.value = null
- combineMatchedSku.value = []
- }
- // 组合商品上架数量弹框
- const _showPutawayCombineDialog = (batchItem) => {
- if (!putawayCombineData.value || !batchItem?.length) return
- const total = batchItem.reduce((sum, i) => sum + Number(i.quantity || 0), 0)
- combineMatchedSku.value = [{
- matchedJson: putawayCombineData.value,
- expectedQuantity: total,
- receivedQuantity: 0,
- }]
- barcodeCombineRef.value?.show()
- }
- // 组合商品确认上架数量
- const setPutawayCombine = ({ dataList }) => {
- if (dataList?.[0]?.quantity != null) {
- searchCount.value = String(dataList[0].quantity)
- }
- showNotify({ type: 'success', duration: 2000, message: `已填入上架数量:${searchCount.value},请扫描库位并确认上架` })
- }
- // 组合商品取消
- const onCombineCancel = () => {
- const qtyPerSet = putawayCombineData.value?.quantity ?? 1
- const total = barcodeQuantity(barcodeActiveList.value)
- searchCount.value = String(total < qtyPerSet ? 1 : qtyPerSet)
- }
- // 选择单据
- const onDetailActive = (item) => {
- barcodeActiveList.value = item
- lotBarcodeTrueFalseBy.value = false
- if (putawayCombineData.value) {
- _showPutawayCombineDialog(item)
- _getRecommendedLocation(item[0])
- scanType.value = 3
- return
- }
- searchCount.value = 1
- scanType.value = 3
- _getRecommendedLocation(item[0])
- scanSuccess()
- }
- const onAsnCancel = () => {
- if (searchBarcode.value === '' || (oldSearchBarcode.value.length != searchBarcode.value.length && oldSearchBarcode.value != '')) {
- barcodeActiveList.value = []
- searchCount.value = ''
- locationList.value = []
- }
- }
- // 商品条码不匹配时,查询组合条码
- const _handlePutawayCombineProduct = (code) => {
- showLoading()
- getListCombineSku({ combineSku: barcodeToUpperCase(code), workEnvironment: 'inbound' })
- .then((res) => {
- const _err = (msg) => {
- closeLoading()
- scanError()
- showNotify({ type: 'danger', duration: 3000, message: msg })
- reset()
- }
- if (!res.data?.length) return _err(`${code}-商品条码不匹配,请重新扫描`)
- if (res.data.length > 1) return _err('不支持多商品组合商品')
- const combineBarcode = res.data[0].barcode
- lotBarcodeList.value = matchingBarcodeItem(dataMap.value, combineBarcode)
- if (lotBarcodeList.value.length === 0) return _err('组合商品与待上架数据不匹配,请检查组合商品配置!')
- putawayCombineData.value = res.data[0]
- closeLoading()
- scanSuccess()
- if (lotBarcodeList.value.length === 1) {
- barcodeActiveList.value = lotBarcodeList.value[0]
- _showPutawayCombineDialog(lotBarcodeList.value[0])
- _getRecommendedLocation(barcodeActiveList.value[0])
- scanType.value = 3
- } else {
- locationList.value = []
- barcodeActiveList.value = []
- searchCount.value = ''
- searchLocation.value = ''
- lotBarcodeTrueFalseBy.value = true
- }
- })
- .catch(() => {
- closeLoading()
- scanError()
- showNotify({ type: 'danger', duration: 3000, message: `${code}-商品条码不匹配,请重新扫描` })
- reset()
- })
- }
- // 扫描条码监听
- const _handlerScan = (code) => {
- if (scanType.value == 2) {
- searchBarcode.value = code
- oldSearchBarcode.value = code
- lotBarcodeList.value = matchingBarcodeItem(dataMap.value, code)
- if (lotBarcodeList.value.length > 0) {
- putawayCombineData.value = null
- combineMatchedSku.value = []
- if (lotBarcodeList.value.length == 1) {
- barcodeActiveList.value = lotBarcodeList.value[0]
- _getRecommendedLocation(barcodeActiveList.value[0])
- scanType.value = 3
- scanSuccess()
- } else if (lotBarcodeList.value.length > 1) {
- locationList.value = []
- barcodeActiveList.value = []
- searchCount.value = ''
- searchLocation.value = ''
- lotBarcodeTrueFalseBy.value = true
- }
- } else {
- _handlePutawayCombineProduct(code)
- }
- } else if (scanType.value == 3) {
- const scannedLocation = barcodeToUpperCase(code)
- if (forcePublishEnabled.value) {
- const { lotAtt02 } = barcodeActiveList.value[0]
- if (locationList.value.length > 0 && !lotAtt02) {
- const recommendedLocations = locationList.value.map(item => barcodeToUpperCase(item.locationId || ''))
- if (!recommendedLocations.includes(scannedLocation)) {
- showNotify({ type: 'warning', duration: 3000, message: `扫描库位${scannedLocation}与推荐库位不一致,请确认` })
- searchLocation.value=''
- scanError()
- return
- }
- }
- }
- searchLocation.value = scannedLocation
- scanType.value = 4
- if (!searchCount.value) searchCount.value = 1
- scanSuccess()
- }
- }
- // 获取推荐库位(false:master GET 多行列表;true:精准推荐 POST)
- const _getRecommendedLocation = async (item, options = {}) => {
- const { fromChangeLocation = false } = options
- const { lotNumber, owner } = item
- if (!forcePublishEnabled.value) {
- try {
- const res = await getRecommendedLocation({ warehouse, lotNum: lotNumber, owner })
- locationList.value = res.data || []
- } catch (err) {
- console.error(err)
- }
- return
- }
- const { sku, quantity, lotAtt08 } = item
- const listByLot = fromChangeLocation ? (excludedLocations.value[lotNumber] || []) : []
- const uniqueLocationIds = listByLot.length > 0
- ? [...new Set(listByLot.map(loc => loc.locationId))]
- : undefined
- try {
- const params = { warehouse, lotNum: lotNumber, owner, sku, qty: quantity, lotAtt08 }
- if (fromChangeLocation && uniqueLocationIds) params.excludedLocations = uniqueLocationIds
- if (containerNo.value?.includes('TH-')) params.scene = 'RETURN_SHELVE'
- const res = await getRecommendedLocationNew(params)
- if (res.data) {
- const loc = res.data.location ?? res.data
- if (fromChangeLocation) {
- // 按批次维度存储已推荐库位,用于后续换一换排除
- const lotExcluded = excludedLocations.value[lotNumber] || []
- excludedLocations.value = {
- ...excludedLocations.value,
- [lotNumber]: [...lotExcluded, loc]
- }
- }
- locationList.value = [res.data]
- searchCount.value = 1
- }
- } catch (err) {
- console.error(err)
- }
- }
- // 换一换:请求新的推荐库位,排除当前批次已推荐过的
- const onChangeLocation = async () => {
- if (!forcePublishEnabled.value) return
- if (barcodeActiveList.value.length > 0) {
- changeLocationLoading.value = true
- try {
- const item = barcodeActiveList.value[0]
- const lotNumber = item.lotNumber
- const currentLoc = locationList.value?.[0]?.location ?? locationList.value?.[0]
- if (currentLoc) {
- const lotExcluded = excludedLocations.value[lotNumber] || []
- excludedLocations.value = {
- ...excludedLocations.value,
- [lotNumber]: [...lotExcluded, currentLoc]
- }
- }
- await _getRecommendedLocation(item, { fromChangeLocation: true })
- } finally {
- changeLocationLoading.value = false
- }
- }
- }
- const numberRef = ref(null)
- const locationRef = ref(null)
- // 完成收货校验
- const isCheck = () => {
- if (searchLocation.value == '') {
- locationRef.value?.focus()
- scanError()
- showToast({ duration: 3000, message: '请先扫描库位编号' })
- return false
- }
- if (forcePublishEnabled.value) {
- if(barcodeActiveList.value.length ==0) {
- showToast({ duration: 3000, message: '数据异常请重新扫描' })
- scanError()
- return
- }
- const { lotAtt02 } = barcodeActiveList.value[0]
- if (locationList.value.length > 0 && !lotAtt02) {
- const recommendedLocations = locationList.value.map(item => barcodeToUpperCase(item.locationId || ''))
- if (!recommendedLocations.includes(barcodeToUpperCase(searchLocation.value))) {
- locationRef.value?.focus()
- scanError()
- showToast({ duration: 3000, message: '库位与推荐库位不一致,无法上架' })
- return false
- }
- }
- }
- if (searchCount.value == '') {
- numberRef.value?.focus()
- scanError()
- showToast({ duration: 3000, message: '请先输入上架数量' })
- return false
- }
- const maxQuantity = barcodeQuantity(barcodeActiveList.value)
- if (Number(searchCount.value) > maxQuantity) {
- numberRef.value?.focus()
- scanError()
- showToast({ duration: 3000, message: `上架数量最大为:${maxQuantity}` })
- return false
- }
- return true
- }
- // 上架
- const onConfirm = () => {
- if (isCheck()) {
- const quantity = searchCount.value
- const asnDoShelfList = []
- const noAsnDoShelfList=[]
- const list = structuredClone(barcodeActiveList.value) // 深拷贝,保证原始数据不被修改
- // 按照 totalQuantity 从小到大排序,优先扣除最小的
- list.sort((a, b) => {
- const totalQuantityA = Number(a.totalQuantity || a.quantity || 0)
- const totalQuantityB = Number(b.totalQuantity || b.quantity || 0)
- return totalQuantityA - totalQuantityB
- })
- let remainingQuantity = quantity
- for (let i = 0; i < list.length && remainingQuantity > 0; i++) {
- const { taskNo, taskLineNo, warehouse, quantity } = list[i]
- const takeQuantity = Math.min(quantity, remainingQuantity)
- if(list[i].type=='asn'){
- asnDoShelfList.push({
- taskNo,
- taskLineNo,
- warehouse,
- container: '*',
- targetCode: searchLocation.value,
- quantity: takeQuantity, // 当前项扣除的数量
- })
- }else {
- noAsnDoShelfList.push({
- id:taskLineNo,
- location:searchLocation.value,
- qty:takeQuantity
- })
- }
- remainingQuantity -= takeQuantity
- }
- showLoading()
- setPutawayNew({asnDoShelfList,noAsnDoShelfList}).then(res => {
- if (totalQuantity.value - Number(searchCount.value) == 0) {
- containerNo.value = ''
- dataMap.value = {}
- dataList.value = []
- showNotify({ type: 'success', message: '当前任务已上架完成,请扫描下一个容器号', duration: 3000 })
- inputBarcodeRef.value?.show('', '请扫描容器号', '')
- stopTimer()
- } else {
- showNotify({ type: 'success', message: '上架成功,请继续扫描商品进行上架', duration: 3000 })
- setBarcode(containerNo.value, 'success')
- scanType.value = 2
- }
- reset()
- scanSuccess()
- }).catch(err => {
- scanError()
- }).finally(() => {
- closeLoading()
- })
- }
- }
- const refresh=()=>{
- reset()
- scanType.value=2
- loadData()
- }
- // 数据刷新
- const loadData = () => {
- if (!containerNo.value) {
- inputBarcodeRef.value?.show('', '请扫描容器号', '')
- return
- } else {
- setBarcode(containerNo.value, 'container')
- // currentTime.value=getCurrentTime()
- // startTimer()
- }
- }
- onUnmounted(() => {
- closeListener()
- stopTimer()
- })
- window.onRefresh = loadData
- </script>
- <style scoped lang="sass">
- .take-delivery
- .take-info
- padding: 6px 10px
- background: linear-gradient(to left, #c8e2fb, #ffffff)
- display: flex
- flex-direction: column
- text-align: left
- .take-info-no
- flex: 1
- .info-no-title
- font-size: 19px
- font-width: 500
- display: flex
- justify-content: space-between
- align-items: center
- .info-no-tips
- font-size: 14px
- color: #666666
- display: flex
- justify-content: space-between
- padding: 6px 0
- .take-info-number
- flex: 1
- border-top: 1.5px solid #efefef
- display: flex
- justify-content: space-between
- gap: 10px
- color: #666
- font-size: 14px
- padding-top: 10px
- .info-number-left
- flex: 1
- display: flex
- justify-content: space-evenly
- align-items: center
- .number-left-box
- flex: 1
- display: flex
- flex-direction: column
- align-items: center
- .left-box-title
- font-size: 14px
- font-weight: bold
- color: #000
- line-height: 34px
- .info-number-right
- width: 45%
- text-align: center
- .van-search
- padding: 0
- .take-barcode
- margin-top: 10px
- text-align: left
- background: #FFFFFF
- .barcode-input
- ::v-deep(.van-search)
- padding: 0
- height: 50px
- display: flex
- align-items: center
- ::v-deep(.van-search__field)
- border-bottom: 2px solid #ffffff
- display: flex
- align-items: center
- height: 50px
- ::v-deep(.van-search__content)
- background: #fff
- display: flex
- align-items: center
- height: 50px
- ::v-deep(.van-field__control)
- font-size: 16px
- font-weight: bold
- ::v-deep(.van-search__label)
- font-size: 16px
- font-weight: bold
- .search-input-barcode
- ::v-deep(.van-search__field)
- border-bottom: 2px solid #0077ff
- z-index: 2
- .search-input-number
- ::v-deep(.van-field__control)
- font-size: 16px
- font-weight: bold
- color: #ee0a25
- .take-lot
- text-align: left
- margin-top: 5px
- ::v-deep(.van-cell)
- padding: 5px 8px
- .take-lot-title
- font-size: 15px
- font-weight: bold
- padding: 0 5px
- border-left: 3px solid #1989fa
- color: #333
- margin-bottom: 3px
- .take-button
- padding: 10px 20px
- .btn
- background: #1989fa
- color: #fff
- font-size: 16px
- line-height: 35px
- border-radius: 8px
- </style>
|