| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504 |
- @extends('layouts.app')
- @section('title')点收一体@endsection
- @section('content')
- <div class="d-none" id="container">
- <audio src="{{asset('sound/warning_otherBarcode.mp3')}}" controls="controls" preload id="soundWarning" hidden>
- </audio>
- <audio src="{{asset('sound/ding.mp3')}}" controls="controls" preload id="soundDing" hidden>
- </audio>
- <div class="row">
- <div class="col-4 p-0 m-0" id="countGoods">
- <div class="col-12 text-center bg-white mt-2">
- <h4 class="font-weight-bold text-dark">清点模式</h4>
- </div>
- <div class="card-body">
- <div class="row pl-5">
- <div class="col-6">
- <label class="text-left font-weight-bold text-muted">条码</label>
- <input type="text" id="barcode" class="form-control" :disabled="status.barcodeDisable" placeholder="扫入条码"
- @focusin="focusOutDocument" @focusout="focusDocument" v-model="inputting.barcode">
- </div>
- <div v-if="inputMode==='sweepModel'" class="col-6">
- <label class="text-left font-weight-bold text-muted">已扫数量</label>
- <input type="number" id="amount" class="form-control mt-0" placeholder="" :disabled="status.amountDisable"
- v-model="inputting.amount" style='height: 40px;font-size: 1.6em;color:blue;font-weight: bolder;padding: 3px;text-align: center'>
- </div>
- </div>
- <p class="card-text text-muted mt-3 mb-n3 text-center">已完成:</p>
- <hr>
- <table class="table table-sm table-striped table-bordered" v-if="goodses.length>0">
- <tr>
- <th class="text-center">条码</th>
- <th class="text-center">数量</th>
- <th class="text-center">箱规</th>
- <th class="text-center">操作</th>
- </tr>
- <tr v-for="(goods,i) in goodses" :id="'tr_'+i">
- <td class="text-center">@{{ goods.barcode }}</td>
- <td class="text-center">@{{ goods.amount }}</td>
- <td class="text-center">
- <span v-if="goods.cast_number">第@{{ goods.cast_number }}箱</span>
- </td>
- <td class="text-center">
- <span v-if="goods.countGoodStatus">
- <button class="btn btn-outline-info btn-sm" @click="countGoods(i,goods.barcode)">完成清点</button>
- </span>
- <button class="btn btn-outline-danger btn-sm" @click="removeGoods($event,goods.barcode)">删</button>
- </td>
- </tr>
- </table>
- <hr>
- <span class="btn btn-outline-dark btn form-control" style="cursor: pointer" @click="submitExcelData">结束清点</span>
- </div>
- </div>
- <div class="col-8 p-0 m-0" id="receive">
- <div class="col-12 text-center bg-white mt-2">
- <h4 class="font-weight-bold text-dark">收货模式</h4>
- </div>
- <div class="card-body m-0">
- <div class="col-8 offset-2 row">
- <label for="asnno" class="font-weight-bold text-muted ">输入ASN</label>
- <input type="text" id="asnno" class="form-control" @focusin="focusOutDocument" autocomplete="off"
- @change="getReceiveTaskByAsnNoAndBarcodes()" disabled="true" placeholder="ASN单号" v-model="asnno">
- </div>
- <table class="table table-sm table-striped" v-if="regroupGoods.length>0">
- <hr>
- <tr>
- <th class="text-center">货主</th>
- <th class="text-center">条码</th>
- <th class="text-center">清点数量</th>
- <th class="text-center">ASN数量</th>
- <th class="text-center">差值</th>
- <th class="text-center">容器号</th>
- <th class="text-center">生产日期</th> <!--lotatt01-->
- <th class="text-center">失效日期</th> <!--lotatt02-->
- <th class="text-center">批号</th> <!--lotatt04-->
- <th class="text-center">属性仓</th> <!--lotatt05-->
- <th class="text-center">质量状态</th> <!--lotatt08-->
- <th class="text-center">入库日期</th> <!--lotatt03-->
- <th class="text-center">操作</th>
- </tr>
- <tr v-for="(goods,i) in regroupGoods">
- <td class="text-center">@{{ goods.customerid }}</td>
- <td class="text-center">@{{ goods.sku }}</td>
- <td class="text-center">@{{ goods.amount }}</td>
- <td class="text-center">@{{ goods.asn_amount }}</td>
- <td class="text-center">@{{ goods.diff_val }}</td>
- <td class="text-center">
- <span v-if="goods.receiveStatus">
- <input type="text" autocomplete="off" class="form-control form-control-sm" :class="errors.trackNumber ? 'is-invalid' : ''"
- id="trackNumber" v-model="goods.trackNumber">
- <span class="invalid-feedback offset-3" role="alert" v-if="errors.trackNumber">
- <strong>@{{ errors.trackNumber[0] }}</strong>
- </span>
- </span>
- </td>
- <td class="text-center">
- <span v-if="goods.basSku.lot_id">
- <input type="date" autocomplete="off" class="form-control form-control-sm input-sm" :class="errors.lotatt01 ? 'is-invalid' : ''"
- :disabled="goods.basSku.lot_id.lotkey01==='N'" id="lotatt01" v-model="goods.lotatt01">
- <span class="invalid-feedback offset-3" role="alert" v-if="errors.lotatt01">
- <strong>@{{ errors.lotatt01[0] }}</strong>
- </span>
- </span>
- </td>
- <td class="text-center">
- <span v-if="goods.basSku.lot_id">
- <input type="date" autocomplete="off" class="form-control form-control-sm input-sm" :class="errors.lotatt02 ? 'is-invalid' : ''"
- :disabled="goods.basSku.lot_id.lotkey02==='N'" id="lotatt02" v-model="goods.lotatt02">
- <span class="invalid-feedback offset-3" role="alert" v-if="errors.lotatt02">
- <strong>@{{ errors.lotatt02[0] }}</strong>
- </span>
- </span>
- </td>
- <td class="text-center">
- <span v-if="goods.basSku.lot_id">
- <input type="text" autocomplete="off" class="form-control form-control-sm input-sm" :class="errors.lotatt04 ? 'is-invalid' : ''"
- :disabled="goods.basSku.lot_id.lotkey04==='N'" id="lotatt04" v-model="goods.lotatt04">
- <span class="invalid-feedback offset-3" role="alert" v-if="errors.lotatt04">
- <strong>@{{ errors.lotatt04[0] }}</strong>
- </span>
- </span>
- </td>
- <td class="text-center">
- <span v-if="goods.basSku.lot_id">
- <select class="form-control form-control-sm" :disabled="goods.basSku.lot_id.lotkey05==='N'"
- id="lotatt05" v-model="goods.lotatt05" :class="errors.lotatt05 ? 'is-invalid' : ''">
- <option v-for="(attributeLocation,i) in attributeLocations"
- :value="attributeLocation.code">@{{ attributeLocation.codename_c }}</option>
- </select>
- <span class="invalid-feedback offset-3" role="alert" v-if="errors.lotatt05">
- <strong>@{{ errors.lotatt05[0] }}</strong>
- </span>
- </span>
- </td>
- <td class="text-center">
- <span v-if="goods.basSku.lot_id">
- <select class="form-control form-control-sm" :class="errors.lotatt08 ? 'is-invalid' : ''"
- :disabled="goods.basSku.lot_id.lotkey08==='N'" id="lotatt08" v-model="goods.lotatt08">
- <option v-for="(quality,i) in qualityStatus" :value="quality.code">@{{ quality.codename_c }}</option>
- </select>
- <span class="invalid-feedback offset-3" role="alert" v-if="errors.lotatt08">
- <strong>@{{ errors.lotatt08[0] }}</strong>
- </span>
- </span>
- </td>
- <td class="text-center">
- <span v-if="goods.basSku.lot_id">
- <input type="date" autocomplete="off" class="form-control form-control-sm input-sm" :class="errors.lotatt03 ? 'is-invalid' : ''"
- :disabled="goods.basSku.lot_id.lotkey03==='N'" id="lotatt03" v-model="goods.lotatt03">
- <span class="invalid-feedback offset-3" role="alert" v-if="errors.lotatt03">
- <strong>@{{ errors.lotatt03[0] }}</strong>
- </span>
- </span>
- </td>
- <td class="text-center">
- <span v-if="goods.receiveStatus&&goods.diff_val>=0">
- <button class="btn btn-outline-info btn-sm" @click="receiveGoods(goods)">收</button>
- </span>
- </td>
- </tr>
- </table>
- <span class="btn btn-outline-dark btn form-control mt-5" v-if="status.finishReceiveButton"
- style="cursor: pointer" @click="finishReceive()">结束收货</span>
- </div>
- </div>
- </div>
- </div>
- @endsection
- @section('lastScript')
- <script>
- new Vue({
- el: '#app',
- data:{
- qualityStatus:{!! $qualityStatus !!},
- attributeLocations:{!! $attributeLocations !!},
- focusing:'document',
- lastScannedBarcode:'',
- inputMode:'sweepModel',
- inputting:{
- barcode:'',amount:'',fromIncreasing:true,cast_number:'',countGoodStatus:true
- },
- status:{
- scanEndInputted:false,barcodeDisable:true,amountDisable:true,finishReceiveButton:false,
- },
- asnno:'',
- basSku:{
- lot_id:'',
- },
- goodses:[],
- initGoods:[],
- regroupGoods:[],
- errors:{},
- },
- mounted() {
- if (navigator.userAgent.indexOf("Android")!==-1)this.isAndroid = true;
- this.pageInit();
- $("#container").removeClass("d-none");
- this.scanListening();
- },
- methods: {
- //页面初始化
- pageInit(){
- if (!this.isAndroid)return;
- let element = document.getElementById("navbarSupportedContent").parentElement;
- element.className = "row";
- element.children[0].className += " col-5";
- element.innerHTML = element.children[0].outerHTML;
- let e1 = document.getElementById("menu");
- let e2 = document.getElementById("demand-div");
- if (e1)e1.remove();
- if (e2)e2.remove();
- },
- focusDocument: function () {
- this.focusing = 'document';
- },
- focusOutDocument: function () {
- this.focusing = '';
- },
- scanListening: function () {
- let data = this;
- $(document).on('keypress', function (e) {
- if(data.focusing!=='document'){return}
- if (e.keyCode !== 13) {
- if(data.status.scanEndInputted){
- data.lastScannedBarcode=data.inputting.barcode;
- data.inputting.barcode='';
- data.status.scanEndInputted=false;
- }
- data.inputting.barcode += String.fromCharCode(e.keyCode);
- } else {
- if(data.inputting.barcode.length<=1){
- window.tempTip.setDuration(4500);
- window.tempTip.show('未扫入条码,请检查扫码枪设置,尝试调至“直接键盘输出”模式');
- return;
- }
- data.status.scanEndInputted = true;
- switch(data.inputMode){
- case 'sweepModel': data.commitGoodsOnSweepModel();break;
- }
- }
- });
- },
- commitGoodsOnSweepModel(){
- let repeatedBarcode=this.repeatedIncreasingBarcodeFromSaved();
- if(!repeatedBarcode){
- this.focusOutDocument();
- this.alertVibrate();
- this.inputting.amount=1;
- this.goodses.unshift(JSON.parse(JSON.stringify(this.inputting)));
- window.tempTip.setDuration(500);
- window.tempTip.showSuccess('保存成功');
- this.focusDocument();
- this.audioDing();
- }else{
- repeatedBarcode.amount++;
- this.inputting.amount=repeatedBarcode.amount;
- window.tempTip.setDuration(500);
- window.tempTip.showSuccess(repeatedBarcode.amount);
- this.focusDocument();
- this.audioDing();
- }
- },
- audioDing: function () {
- let audio = document.getElementById('soundDing');
- audio.currentTime = 0;//重新播放
- audio.play();// 播放
- function startVibrate(duration) {
- if (navigator.vibrate) {
- navigator.vibrate(duration);
- } else if (navigator.webkitVibrate) {
- navigator.webkitVibrate(duration);
- }
- }
- startVibrate(500);
- },
- alertVibrate: function () {
- function startVibrate(duration) {
- if (navigator.vibrate) {
- navigator.vibrate(duration);
- } else if (navigator.webkitVibrate) {
- navigator.webkitVibrate(duration);
- }
- }
- let vibrateInterval = setInterval(function() {
- startVibrate(150);
- }, 50);
- setTimeout(function() {
- clearInterval(vibrateInterval)
- }, 2000);
- },
- repeatedIncreasingBarcodeFromSaved: function () {
- let data = this;
- let repeatedGoods=null;
- data.goodses.every(function(goods){
- if(goods.barcode===data.inputting.barcode && goods.fromIncreasing && goods.countGoodStatus){
- repeatedGoods=goods;
- return false;
- }
- return true;
- });
- return repeatedGoods;
- },
- cleanInputs: function () {
- this.inputting.barcode='';
- this.inputting.amount='';
- this.inputting.cast_number='';
- this.lastScannedBarcode='';
- },
- countGoods: function (i,barcode) {
- if(!confirm('确定要结束清点'+barcode+'的记录吗'))return;
- let data = this;
- let cast_number=0;
- data.goodses.forEach(function (goods) {
- if (goods.barcode===barcode)cast_number++
- });
- data.goodses.every(function(goods,i){
- if(goods.barcode===barcode &&goods.countGoodStatus){
- goods.countGoodStatus=false;
- goods.cast_number=cast_number;
- return false;
- }
- return true;
- })
- $('#tr_'+i).attr("class",'alert alert-dark');
- },
- removeGoods: function ($e,barcode) {
- if(!confirm('确定要删除条码为'+barcode+'的记录吗'))return;
- let data = this;
- data.goodses.every(function(goods,i){
- if(goods.barcode===barcode){
- data.goodses.splice(i,1)
- return false;
- }
- return true;
- })
- },
- regroupArr(arr){
- let a =JSON.parse(JSON.stringify(arr));
- return a.reduce((total, cur, index) => {
- let hasValue = total.findIndex(current => {
- return current.barcode === cur.barcode
- })
- hasValue === -1 && total.push(cur)
- hasValue !== -1 && (total[hasValue].amount = total[hasValue].amount + cur.amount)
- return total
- }, []);
- },
- assignRegroupGoods(){
- let data=this;
- data.initGoods=data.regroupArr(data.goodses);
- data.initGoods.forEach(function (obj){
- delete obj.fromIncreasing;
- delete obj.cast_number;
- delete obj.countGoodStatus;
- obj.asnno='';obj.customerid='';
- obj.location='';obj.asn_amount='';
- obj.diff_val='';obj.receiveStatus=false;
- obj.basSku=data.basSku;obj.asnlineno='';
- obj.lotatt01='';obj.lotatt02='';
- obj.lotatt03='';obj.lotatt04='';
- obj.lotatt05='';obj.lotatt08='';
- })
- data.initGoods=JSON.parse(JSON.stringify(data.initGoods).replace(/barcode/g,"sku"));
- data.regroupGoods=data.initGoods;
- },
- receiveGoods(goods){
- let data=this;
- this.errors={};
- this.checkGood(goods);
- if (JSON.stringify(this.errors)!=='{}')return;
- goods.asnno=data.asnno;
- tempTip.setDuration(99999);
- tempTip.waitingTip('提交中');
- let url='{{url("store/countGoodsAndReceive/fluxReceive")}}';
- axios.post(url,{good:goods})
- .then(function(res){
- if(res.data.success){
- data.regroupGoods.forEach(function (good,i){
- if (goods.sku==good.sku){
- data.regroupGoods.splice(i,1)
- }
- })
- tempTip.setDuration(2000);
- tempTip.cancelWaitingTip();
- tempTip.showSuccess(res.data.data);
- }else{
- tempTip.setDuration(3000);
- tempTip.cancelWaitingTip();
- tempTip.show(res.data.data);
- data.alertVibrate()
- }
- })
- .catch(function (err) {
- tempTip.setDuration(2000);
- tempTip.cancelWaitingTip();
- tempTip.show("网络错误:"+err);
- data.alertVibrate()
- });
- },
- checkGood(good){
- let error = {};
- if (!good.trackNumber)error.trackNumber = ["容器号必填"];
- if (good.basSku.lot_id && good.basSku.lot_id.lotkey01==='Y' && !good.lotatt01) error.lotatt01=["生产日期为选"];
- if (good.basSku.lot_id && good.basSku.lot_id.lotkey02==='Y' && !good.lotatt02) error.lotatt02=["失效日期为选"];
- if (good.basSku.lot_id && good.basSku.lot_id.lotkey03==='Y' && !good.lotatt03) error.lotatt03=["入库日期为选"];
- if (good.basSku.lot_id && good.basSku.lot_id.lotkey04==='Y' && !good.lotatt04) error.lotatt04=["批号未填"];
- if (good.basSku.lot_id && good.basSku.lot_id.lotkey05==='Y' && !good.lotatt05) error.lotatt05=["属性仓未选"];
- if (good.basSku.lot_id && good.basSku.lot_id.lotkey08==='Y' && !good.lotatt08) error.lotatt08=["质量状态未选"];
- if (JSON.stringify(error)!=='{}'){this.errors = error;}
- },
- getReceiveTaskByAsnNoAndBarcodes(){
- let data=this;
- data.regroupGoods=data.initGoods;//验证asn下商品时 初始商品数据
- if(data.asnno===''||data.asnno===null||data.asnno===undefined) window.tempTip.show('请先输入ASN单号!');
- if (data.asnno && data.asnno.indexOf('ASN')===-1)window.tempTip.show('无效ASN号!');
- let url='{{url("store/countGoodsAndReceive/getReceiveTaskByAsnNoAndBarcodes")}}';
- window.axios.post(url,{asnno:data.asnno,goods:data.initGoods})
- .then(res=>{
- if (res.data.success){
- data.regroupGoods=res.data.data;
- this.$forceUpdate()
- }else {
- tempTip.setDuration(3000);
- tempTip.show(res.data.data);
- }
- }).catch(err=>{
- window.tempTip.setDuration(2000);
- window.tempTip.show("网络错误:"+err);
- })
- },
- removeDisable(){
- let asnNo=$('#asnno');
- asnNo.removeAttr('disabled');
- this.status.finishReceiveButton=true;
- asnNo.focus();
- },
- submitExcelData: function () {
- let data = this;
- data.focusOutDocument();
- if(data.goodses.length===0){
- window.tempTip.show('请先录入数据再提交收货');return;
- }
- window.tempTip.confirm('请检查表格,确定全部完成。',
- function () {
- window.tempTip.setInputType('input');
- window.tempTip.setIndex(999999);
- window.tempTip.inputVal('收货前将上传excel文件,请输入文件名:',function(val){
- if(val===''){
- window.tempTip.setDuration(2500);
- window.tempTip.show('失败!文件名不能为空,请重新点击生成');
- return;
- }
- window.tempTip.setDuration(15500);
- window.tempTip.waitingTip('提交Excel中...');
- let expireHandler = setTimeout(function () {
- window.tempTip.cancelWaitingTip();
- window.tempTip.setDuration(1500);
- window.tempTip.show('响应超时! 请检查网络,确保可以连接后再重试。');
- },9000);
- let url='{{url("store/countGoodsAndReceive/createExcel")}}';
- axios.post(url,{'goodses':data.goodses,'filename':val})
- .then(function(response){
- if(response.data.result==='success'){
- data.removeDisable();//收货解锁asnno input标签
- data.assignRegroupGoods();//结束清点,重组收货所需数据
- data.goodses=[];
- data.cleanInputs();
- window.tempTip.cancelWaitingTip();
- window.tempTip.setDuration(1500);
- window.tempTip.showSuccess('成功生成EXCEL,可在列表页查看');
- }else{
- window.tempTip.setDuration(1500);
- window.tempTip.show('生成EXCEL失败');
- data.focusDocument();
- data.alertVibrate()
- }
- clearInterval(expireHandler);
- })
- .catch(function (err) {
- window.tempTip.setDuration(3500);
- window.tempTip.show('网络或系统错误,请将以下信息提交给开发者:'+err);
- clearInterval(expireHandler);
- data.alertVibrate();
- });
- });
- },function () {
- data.focusDocument();
- })
- },
- finishReceive(){
- if(!confirm('确定要结束收货吗?'))return;
- setTimeout(function (){window.location.reload()},10)
- }
- },
- });
- </script>
- @endsection
|