index.blade.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. @extends('layouts.app')
  2. @section('title')点收一体@endsection
  3. @section('content')
  4. <div class="d-none" id="container">
  5. <audio src="{{asset('sound/warning_otherBarcode.mp3')}}" controls="controls" preload id="soundWarning" hidden>
  6. </audio>
  7. <audio src="{{asset('sound/ding.mp3')}}" controls="controls" preload id="soundDing" hidden>
  8. </audio>
  9. <div class="row">
  10. <div class="col-4" id="countGoods">
  11. <div class="col-12 text-center bg-white mt-2">
  12. <h4 class="font-weight-bold text-dark">清点模式</h4>
  13. </div>
  14. <div class="card-body">
  15. <div class="row pl-5">
  16. <div class="col-6">
  17. <label class="text-left font-weight-bold text-muted">条码</label>
  18. <input type="text" id="barcode" class="form-control" :disabled="status.barcodeDisable" placeholder="扫入条码"
  19. @focusin="focusOutDocument" @focusout="focusDocument" v-model="inputting.barcode">
  20. </div>
  21. <div v-if="inputMode==='sweepModel'" class="col-6">
  22. <label class="text-left font-weight-bold text-muted">已扫数量</label>
  23. <input type="number" id="amount" class="form-control mt-0" placeholder="" :disabled="status.amountDisable"
  24. v-model="inputting.amount" style='height: 40px;font-size: 1.6em;color:blue;font-weight: bolder;padding: 3px;text-align: center'>
  25. </div>
  26. </div>
  27. <p class="card-text text-muted mt-3 mb-n3 text-center">已完成:</p>
  28. <hr>
  29. <table class="table table-sm table-striped table-bordered" v-if="goodses.length>0">
  30. <tr>
  31. <th class="text-center">条码</th>
  32. <th class="text-center">数量</th>
  33. <th class="text-center">箱规</th>
  34. <th class="text-center">操作</th>
  35. </tr>
  36. <tr v-for="(goods,i) in goodses" :id="'tr_'+i">
  37. <td class="text-center">@{{ goods.barcode }}</td>
  38. <td class="text-center">@{{ goods.amount }}</td>
  39. <td class="text-center">
  40. <span v-if="goods.cast_number">第@{{ goods.cast_number }}箱</span>
  41. </td>
  42. <td class="text-center">
  43. <span v-if="goods.countGoodStatus">
  44. <button class="btn btn-outline-info btn-sm" @click="countGoods(i,goods.barcode)">完成清点</button>
  45. </span>
  46. <button class="btn btn-outline-danger btn-sm" @click="removeGoods($event,goods.barcode)">删</button>
  47. </td>
  48. </tr>
  49. </table>
  50. <hr>
  51. <span class="btn btn-outline-dark btn form-control" style="cursor: pointer" @click="submitExcelData">一键收货</span>
  52. </div>
  53. </div>
  54. <div class="col-8" id="receive">
  55. <div class="col-12 text-center bg-white mt-2">
  56. <h4 class="font-weight-bold text-dark">收货模式</h4>
  57. </div>
  58. <div class="card-body">
  59. <div class="col-8 offset-2 row">
  60. <label for="asnno" class="font-weight-bold text-muted ">输入ASN</label>
  61. <input type="text" id="asnno" class="form-control" @focusin="focusOutDocument"
  62. @change="getReceiveTaskByAsnNoAndBarcodes()" placeholder="ASN单号" v-model="asnno">
  63. </div>
  64. <table class="table table-sm table-striped" v-if="regroupGoods.length>0">
  65. <hr>
  66. <tr>
  67. <th class="text-center">货主</th>
  68. <th class="text-center">条码</th>
  69. <th class="text-center">清点数量</th>
  70. <th class="text-center">ASN数量</th>
  71. <th class="text-center">差值</th>
  72. <th class="text-center">容器号</th>
  73. <th class="text-center">生产日期</th> <!--lotatt01-->
  74. <th class="text-center">失效日期</th> <!--lotatt02-->
  75. <th class="text-center">批号</th> <!--lotatt04-->
  76. <th class="text-center">属性仓</th> <!--lotatt05-->
  77. <th class="text-center">质量状态</th> <!--lotatt08-->
  78. <th class="text-center">入库日期</th> <!--lotatt03-->
  79. <th class="text-center">操作</th>
  80. </tr>
  81. <tr v-for="(goods,i) in regroupGoods">
  82. <td class="text-center">@{{ goods.customerid }}</td>
  83. <td class="text-center">@{{ goods.barcode }}</td>
  84. <td class="text-center">@{{ goods.amount }}</td>
  85. <td class="text-center">@{{ goods.asn_amount }}</td>
  86. <td class="text-center">@{{ goods.diff_val }}</td>
  87. <td class="text-center">
  88. <span v-if="goods.receiveStatus">
  89. <input type="text" class="form-control form-control-sm" id="trackNumber" v-model="goods.trackNumber">
  90. </span>
  91. </td>
  92. <td class="text-center">
  93. <span v-if="basSku.lot_id">
  94. <input type="date" class="form-control form-control-sm input-sm"
  95. :disabled="goods.basSku.lot_id.lotkey01==='Y' ? '' : 'true'" id="lotatt01" v-model="goods.lotatt01">
  96. </span>
  97. </td>
  98. <td class="text-center">
  99. <span v-if="basSku.lot_id">
  100. <input type="date" class="form-control form-control-sm input-sm"
  101. :disabled="goods.basSku.lot_id.lotkey02==='Y' ? '' : 'true'" id="lotatt02" v-model="goods.lotatt02">
  102. </span>
  103. </td>
  104. <td class="text-center">
  105. <span v-if="basSku.lot_id">
  106. <input type="text" class="form-control form-control-sm input-sm"
  107. :disabled="goods.basSku.lot_id.lotkey04==='Y' ? '' : 'true'" id="lotatt04" v-model="goods.lotatt04">
  108. </span>
  109. </td>
  110. <td class="text-center">
  111. <span v-if="basSku.lot_id">
  112. <select class="form-control form-control-sm" :disabled="goods.basSku.lot_id.lotkey05==='Y' ? '' : 'true'"
  113. id="lotatt05" v-model="goods.lotatt05">
  114. <option v-for="(attributeLocation,i) in attributeLocations"
  115. :value="attributeLocation.code">@{{ attributeLocation.codename_c }}</option>
  116. </select>
  117. </span>
  118. </td>
  119. <td class="text-center">
  120. <span v-if="basSku.lot_id">
  121. <select class="form-control form-control-sm"
  122. :disabled="goods.basSku.lot_id.lotkey08==='Y' ? '' : 'true'" id="lotatt08" v-model="goods.lotatt08">
  123. <option v-for="(quality,i) in qualityStatus" :value="quality.code">@{{ quality.codename_c }}</option>
  124. </select>
  125. </span>
  126. </td>
  127. <td class="text-center">
  128. <span v-if="basSku.lot_id">
  129. <input type="date" class="form-control form-control-sm input-sm"
  130. :disabled="goods.basSku.lot_id.lotkey03==='Y' ? '' : 'true'" id="lotatt03" v-model="goods.lotatt03">
  131. </span>
  132. </td>
  133. <td class="text-center">
  134. <span v-if="goods.receiveStatus">
  135. <button class="btn btn-outline-info btn-sm" @click="receiveGoods(i,goods.barcode)">收货</button>
  136. </span>
  137. </td>
  138. </tr>
  139. </table>
  140. </div>
  141. </div>
  142. </div>
  143. </div>
  144. @endsection
  145. @section('lastScript')
  146. <script>
  147. new Vue({
  148. el: '#app',
  149. data:{
  150. qualityStatus:{!! $qualityStatus !!},
  151. attributeLocations:{!! $attributeLocations !!},
  152. focusing:'document',
  153. lastScannedBarcode:'',
  154. inputMode:'sweepModel',
  155. inputting:{
  156. barcode:'',amount:'',fromIncreasing:true,cast_number:'',countGoodStatus:true
  157. },
  158. status:{
  159. scanEndInputted:false,barcodeDisable:true,amountDisable:true,
  160. },
  161. asnno:'',
  162. basSku:{},
  163. goodses:[],
  164. regroupGoods:[],
  165. },
  166. mounted() {
  167. if (navigator.userAgent.indexOf("Android")!==-1)this.isAndroid = true;
  168. this.pageInit();
  169. $("#container").removeClass("d-none");
  170. this.scanListening();
  171. },
  172. methods: {
  173. //页面初始化
  174. pageInit(){
  175. if (!this.isAndroid)return;
  176. let element = document.getElementById("navbarSupportedContent").parentElement;
  177. element.className = "row";
  178. element.children[0].className += " col-5";
  179. element.innerHTML = element.children[0].outerHTML;
  180. let e1 = document.getElementById("menu");
  181. let e2 = document.getElementById("demand-div");
  182. if (e1)e1.remove();
  183. if (e2)e2.remove();
  184. },
  185. focusDocument: function () {
  186. this.focusing = 'document';
  187. },
  188. focusOutDocument: function () {
  189. this.focusing = '';
  190. },
  191. scanListening: function () {
  192. let data = this;
  193. $(document).on('keypress', function (e) {
  194. if(data.focusing!=='document'){return}
  195. if (e.keyCode !== 13) {
  196. if(data.status.scanEndInputted){
  197. data.lastScannedBarcode=data.inputting.barcode;
  198. data.inputting.barcode='';
  199. data.status.scanEndInputted=false;
  200. }
  201. data.inputting.barcode += String.fromCharCode(e.keyCode);
  202. } else {
  203. if(data.inputting.barcode.length<=1){
  204. window.tempTip.setDuration(4500);
  205. window.tempTip.show('未扫入条码,请检查扫码枪设置,尝试调至“直接键盘输出”模式');
  206. return;
  207. }
  208. data.status.scanEndInputted = true;
  209. switch(data.inputMode){
  210. case 'sweepModel': data.commitGoodsOnSweepModel();break;
  211. }
  212. }
  213. });
  214. },
  215. commitGoodsOnSweepModel(){
  216. let repeatedBarcode=this.repeatedIncreasingBarcodeFromSaved();
  217. if(!repeatedBarcode){
  218. this.focusOutDocument();
  219. this.alertVibrate();
  220. this.inputting.amount=1;
  221. this.goodses.unshift(JSON.parse(JSON.stringify(this.inputting)));
  222. window.tempTip.setDuration(500);
  223. window.tempTip.showSuccess('保存成功');
  224. this.focusDocument();
  225. this.audioDing();
  226. }else{
  227. repeatedBarcode.amount++;
  228. this.inputting.amount=repeatedBarcode.amount;
  229. window.tempTip.setDuration(500);
  230. window.tempTip.showSuccess(repeatedBarcode.amount);
  231. this.focusDocument();
  232. this.audioDing();
  233. }
  234. },
  235. audioDing: function () {
  236. let audio = document.getElementById('soundDing');
  237. audio.currentTime = 0;//重新播放
  238. audio.play();// 播放
  239. function startVibrate(duration) {
  240. if (navigator.vibrate) {
  241. navigator.vibrate(duration);
  242. } else if (navigator.webkitVibrate) {
  243. navigator.webkitVibrate(duration);
  244. }
  245. }
  246. startVibrate(500);
  247. },
  248. alertVibrate: function () {
  249. function startVibrate(duration) {
  250. if (navigator.vibrate) {
  251. navigator.vibrate(duration);
  252. } else if (navigator.webkitVibrate) {
  253. navigator.webkitVibrate(duration);
  254. }
  255. }
  256. let vibrateInterval = setInterval(function() {
  257. startVibrate(150);
  258. }, 50);
  259. setTimeout(function() {
  260. clearInterval(vibrateInterval)
  261. }, 2000);
  262. },
  263. repeatedIncreasingBarcodeFromSaved: function () {
  264. let data = this;
  265. let repeatedGoods=null;
  266. data.goodses.every(function(goods){
  267. if(goods.barcode===data.inputting.barcode && goods.fromIncreasing && goods.countGoodStatus){
  268. repeatedGoods=goods;
  269. return false;
  270. }
  271. return true;
  272. });
  273. return repeatedGoods;
  274. },
  275. cleanInputs: function () {
  276. this.inputting.barcode='';
  277. this.inputting.amount='';
  278. this.inputting.cast_number='';
  279. this.lastScannedBarcode='';
  280. },
  281. countGoods: function (i,barcode) {
  282. if(!confirm('确定要结束清点'+barcode+'的记录吗'))return;
  283. let data = this;
  284. let cast_number=0;
  285. data.goodses.forEach(function (goods) {
  286. if (goods.barcode===barcode)cast_number++
  287. });
  288. data.goodses.every(function(goods,i){
  289. if(goods.barcode===barcode &&goods.countGoodStatus){
  290. goods.countGoodStatus=false;
  291. goods.cast_number=cast_number;
  292. return false;
  293. }
  294. return true;
  295. })
  296. $('#tr_'+i).attr("class",'alert alert-dark');
  297. },
  298. removeGoods: function ($e,barcode) {
  299. if(!confirm('确定要删除条码为'+barcode+'的记录吗'))return;
  300. let data = this;
  301. data.goodses.every(function(goods,i){
  302. if(goods.barcode===barcode){
  303. data.goodses.splice(i,1)
  304. return false;
  305. }
  306. return true;
  307. })
  308. },
  309. regroupArr(arr){
  310. let a =JSON.parse(JSON.stringify(arr));
  311. return a.reduce((total, cur, index) => {
  312. let hasValue = total.findIndex(current => {
  313. return current.barcode === cur.barcode
  314. })
  315. hasValue === -1 && total.push(cur)
  316. hasValue !== -1 && (total[hasValue].amount = total[hasValue].amount + cur.amount)
  317. return total
  318. }, []);
  319. },
  320. assignRegroupGoods(){
  321. let data=this;
  322. data.regroupGoods=data.regroupArr(data.goodses);
  323. data.regroupGoods.forEach(function (obj){
  324. delete obj.fromIncreasing;
  325. delete obj.cast_number;
  326. delete obj.countGoodStatus;
  327. obj.customerid='';
  328. obj.asn_amount='';
  329. obj.diff_val='';
  330. obj.receiveStatus=false;
  331. obj.basSku='';
  332. obj.lotatt01='';obj.lotatt02='';
  333. obj.lotatt03='';obj.lotatt04='';
  334. obj.lotatt05='';obj.lotatt08='';
  335. })
  336. },
  337. receiveGoods(){
  338. let data=this;
  339. if(data.asnno===''||data.asnno===null||data.asnno===undefined) window.tempTip.show('请先输入ASN单号!');
  340. if (data.asnno && data.asnno.indexOf('ASN')===-1)window.tempTip.show('无效ASN号!');
  341. },
  342. getReceiveTaskByAsnNoAndBarcodes(){
  343. let data=this;
  344. if(data.asnno===''||data.asnno===null||data.asnno===undefined) window.tempTip.show('请先输入ASN单号!');
  345. if (data.asnno && data.asnno.indexOf('ASN')===-1)window.tempTip.show('无效ASN号!');
  346. let url='{{url("store/countGoodsAndReceive/getReceiveTaskByAsnNoAndBarcodes")}}';
  347. window.axios.post(url,{asnno:data.asnno,goods:data.regroupGoods})
  348. .then(res=>{
  349. if (res.data.success){
  350. data.regroupGoods=res.data.data;
  351. this.$forceUpdate()
  352. console.log(data.regroupGoods)
  353. }else {
  354. }
  355. }).catch(err=>{
  356. window.tempTip.setDuration(2000);
  357. window.tempTip.show("网络错误:"+err);
  358. })
  359. },
  360. submitExcelData: function () {
  361. let data = this;
  362. data.assignRegroupGoods();
  363. data.focusOutDocument();
  364. if(data.goodses.length===0){
  365. window.tempTip.show('请先录入数据再提交收货');return;
  366. }
  367. window.tempTip.confirm('请检查表格,确定全部完成。',
  368. function () {
  369. window.tempTip.setInputType('input');
  370. window.tempTip.setIndex(999999);
  371. window.tempTip.inputVal('收货前将上传excel文件,请输入文件名:',function(val){
  372. if(val===''){
  373. window.tempTip.setDuration(2500);
  374. window.tempTip.show('失败!文件名不能为空,请重新点击生成');
  375. return;
  376. }
  377. window.tempTip.setDuration(15500);
  378. window.tempTip.waitingTip('提交Excel中...');
  379. let expireHandler = setTimeout(function () {
  380. window.tempTip.cancelWaitingTip();
  381. window.tempTip.setDuration(1500);
  382. window.tempTip.show('响应超时! 请检查网络,确保可以连接后再重试。');
  383. },9000);
  384. let url='{{url("store/countGoodsAndReceive/createExcel")}}';
  385. axios.post(url,{'goodses':data.goodses,'filename':val})
  386. .then(function(response){
  387. if(response.data.result==='success'){
  388. data.assignRegroupGoods();//统计清点信息,并生成收货所需数据
  389. data.goodses=[];
  390. data.cleanInputs();
  391. window.tempTip.cancelWaitingTip();
  392. window.tempTip.setDuration(1500);
  393. window.tempTip.showSuccess('成功生成EXCEL,可在列表页查看');
  394. data.focusDocument();
  395. }else{
  396. window.tempTip.setDuration(1500);
  397. window.tempTip.show('生成EXCEL失败:'+response.data.fail_info);
  398. console.log(response);
  399. data.focusDocument();
  400. data.alertVibrate()
  401. }
  402. clearInterval(expireHandler);
  403. })
  404. .catch(function (err) {
  405. window.tempTip.setDuration(3500);
  406. window.tempTip.show('网络或系统错误,请将以下信息提交给开发者:'+err);
  407. clearInterval(expireHandler);
  408. data.alertVibrate();
  409. });
  410. });
  411. },function () {
  412. data.focusDocument();
  413. })
  414. }
  415. },
  416. });
  417. </script>
  418. @endsection