show.blade.php 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. @extends('layouts.app')
  2. @section('title')盘收一体-任务@endsection
  3. @section('content')
  4. <div id="container" class="d-none container-fluid">
  5. <span>
  6. @component('store.menu')@endcomponent
  7. @component('store.checkingReceive.menu')
  8. @can('入库管理-盘收一体-盘收')
  9. <li class="nav-item">
  10. <a class="nav-link" href="{{URL::current()}}" :class="{active:isActive('mission',3)}">盘收</a>
  11. </li>@endcan
  12. @endcomponent
  13. </span>
  14. <div class="row m-2 card">
  15. <audio src="{{asset('sound/warning_otherBarcode.mp3')}}" controls="controls" preload id="soundWarning" hidden>
  16. </audio>
  17. <audio src="{{asset('sound/ding.mp3')}}" controls="controls" preload id="soundDing" hidden>
  18. </audio>
  19. <div class="card-body col-12">
  20. <div class="col-12">
  21. <p class="text-muted small" v-if="inputMode=='regular'">常规:可输入效期,相同条码记录不会合并</p>
  22. <p class="text-muted small" v-if="inputMode=='increasing'">逐一扫描:处理单一重复商品,每扫一次对应隔口总数量自动递增,扫到不同条码会提示</p>
  23. <p class="text-muted small" v-if="inputMode=='multiIncreasing'">边扫边分:处理多种商品,自动将扫到的不同条码数量递增到各自隔口号</p>
  24. <ul class="nav nav-tabs mb-4 mt-n3">
  25. <li class="nav-item"><a style="cursor: pointer" class="nav-link text-primary" :class="inputMode=='regular'?'active':''"
  26. @click="switchMenu('regular')">常规</a></li>
  27. <li class="nav-item"><a style="cursor: pointer" class="nav-link text-primary" :class="inputMode=='increasing'?'active':''"
  28. @click="switchMenu('increasing')">逐一扫描</a></li>
  29. <li class="nav-item"><a style="cursor: pointer" class="nav-link text-primary" :class="inputMode=='multiIncreasing'?'active':''"
  30. @click="switchMenu('multiIncreasing')">边扫边分</a></li>
  31. </ul>
  32. </div>
  33. <div class="col-12 row">
  34. <div class="col-6">
  35. <div v-if="inputMode=='regular'">
  36. <div class="btn btn-sm btn-outline-primary" v-if="status.barcodeDisable" @click="status.barcodeDisable=false">手动输入</div>
  37. <div class="btn btn-sm btn-outline-danger" v-if="!status.barcodeDisable" @click="status.barcodeDisable=true">扫描输入</div>
  38. </div>
  39. <input type="text" id="barcode" class="form-control"
  40. :placeholder="status.barcodeDisable ? '扫入条码' : '输入条码'" :disabled="status.barcodeDisable" v-model="inputting.barcode" :class="inputMode=='regular' ? '' : 'mt-4'" {{-- @focusin="focusOutDocument" @focusout="focusDocument" --}}>
  41. <div v-if="inputMode=='regular'">
  42. <div class="card-title">生产日期:</div>
  43. <input type="date" class="form-control mb-2"
  44. {{--v-model="inputting.produce_date" @focusin="focusOutDocument" @focusout="focusDocument" @keyup="oninputEnter"--}}>
  45. <div class="card-title">失效日期:</div>
  46. <input type="date" class="form-control mb-2"
  47. {{--v-model="inputting.valid_date" @focusin="focusOutDocument" @focusout="focusDocument" @keyup="oninputEnter"--}}>
  48. </div>
  49. </div>
  50. <div class="col-6">
  51. <div class="card-title" id="amountLabel">手动输入数量:</div>
  52. <div class="input-group mt-n2 mb-2">
  53. <input type="number" id="amount" style='height: 40px;font-size: 1.6em;color:blue;font-weight: bolder;padding: 3px;text-align: center' class="form-control" placeholder=""
  54. :disabled="status.amountDisable" v-model="inputting.amount"{{-- @focusin="focusOutDocument" @focusout="focusDocument" @keyup="oninputEnter"--}}>
  55. </div>
  56. <div class="card-title">格口号:</div>
  57. <input type="number" id="bin" class="form-control mt-n2 mb-2" style='height: 80px;font-size: 5em;color:red;font-weight: bolder;padding: 3px;text-align: center'
  58. v-model="inputting.bin"{{-- :disabled="status.binDisable" @focusin="focusOutDocument" @focusout="focusDocument" @keyup="oninputEnter"--}}>
  59. <div v-if="inputMode=='regular'">
  60. <div class="card-title">批次号:</div>
  61. <input type="text" class="form-control mb-2"
  62. v-model="inputting.batch_number"{{-- @focusin="focusOutDocument" @focusout="focusDocument" @keyup="oninputEnter"--}}>
  63. </div>
  64. </div>
  65. <div class="col-12" v-if="status.commitButtonVisible && inputMode=='regular'" >
  66. <button class="btn btn-success btn form-control" @click="commitGoods">确定</button>
  67. </div>
  68. </div>
  69. <p class="card-text text-muted mt-3 mb-n3 text-center">已完成:</p>
  70. <hr>
  71. <table class="table table-sm table-striped" {{--v-if="goodses.length>0"--}}>
  72. <tr>
  73. <th>隔口号</th>
  74. <th>数量</th>
  75. <th>条码</th>
  76. <th>生产日期</th>
  77. <th>失效日期</th>
  78. <th>批次号</th>
  79. <th>操作</th>
  80. </tr>
  81. {{--<tr v-for="goods in goodses">
  82. <td>@{{ goods.bin }}</td>
  83. <td>@{{ goods.amount }}</td>
  84. <td>@{{ goods.barcode }}</td>
  85. <td>@{{ goods.produce_date }}</td>
  86. <td>@{{ goods.valid_date }}</td>
  87. <td>@{{ goods.batch_number }}</td>
  88. <td><button class="btn btn-outline-danger btn-sm" @click="removeGoods($event,goods.barcode)">删</button></td>
  89. </tr>--}}
  90. </table>
  91. <hr>
  92. <span class="btn btn-outline-success btn form-control" style="cursor: pointer">确定生成该批盘收</span>
  93. </div>
  94. </div>
  95. <div class="ml-2 mt-2">
  96. <button class="btn btn-sm btn-outline-dark">导出</button>
  97. <button class="btn btn-sm btn-outline-danger">重新清点</button>
  98. <button class="btn btn-sm btn-outline-success">匹配ASN单据</button>
  99. </div>
  100. <div class="row text-primary ml-1 mr-2 mt-1 mb-1 w-100" style="background-color: #c3e3b5">
  101. <span class="ml-1">任务ID: <b class="text-dark">@{{ storeCheckingReceive.id }}</b></span>
  102. <span class="ml-3">货主: <b class="text-dark">@{{ storeCheckingReceive.owner_name }}</b></span>
  103. <span class="ml-3">创建时间: <b class="text-dark">@{{ storeCheckingReceive.created_at }}</b></span>
  104. <span class="ml-3">ASN号: <b class="text-dark">@{{ storeCheckingReceive.asn }}</b></span>
  105. </div>
  106. <table class="table table-sm text-nowrap table-bordered d-none" id="headerRoll"></table>
  107. <table class="table table-striped table-sm text-nowrap table-hover mt-1" id="headerParent">
  108. <tr id="header"></tr>
  109. <tr v-for="(storeCheckingReceiveItem,i) in storeCheckingReceiveItems">
  110. <td>@{{ i+1 }}</td>
  111. <td>@{{ storeCheckingReceiveItem.id }}</td>
  112. <td>@{{ storeCheckingReceiveItem.bin_number }}</td>
  113. <td>@{{ storeCheckingReceiveItem.commodity_name }}</td>
  114. <td>
  115. <span v-for="commodity_barcode in storeCheckingReceiveItem.commodity_barcodes">
  116. <small>@{{ commodity_barcode.code }}</small><br>
  117. </span>
  118. </td>
  119. <td>@{{ storeCheckingReceiveItem.imported_amount }}</td>
  120. <td>@{{ storeCheckingReceiveItem.counted_amount }}</td>
  121. <td>@{{ storeCheckingReceiveItem.asn_amount }}</td>
  122. <td>@{{ storeCheckingReceiveItem.imported_diff_amount }}</td>
  123. <td>@{{ storeCheckingReceiveItem.asn_diff_amount }}</td>
  124. <td>@{{ storeCheckingReceiveItem.produced_at }}</td>
  125. <td>@{{ storeCheckingReceiveItem.invalid_at }}</td>
  126. <td>@{{ storeCheckingReceiveItem.batch_code }}</td>
  127. <td>@{{ storeCheckingReceiveItem.unique_code }}</td>
  128. </tr>
  129. </table>
  130. </div>
  131. @stop
  132. @section('lastScript')
  133. <script type="text/javascript" src="{{asset('js/queryForm/header200826b.js')}}"></script>
  134. <script>
  135. new Vue({
  136. el:"#container",
  137. data:{
  138. storeCheckingReceive:{id:'{{$storeCheckingReceive->id}}',owner_name:'{{$storeCheckingReceive->owner ? $storeCheckingReceive->owner->name : ''}}',
  139. created_at:'{{$storeCheckingReceive->created_at}}',asn:'{{$storeCheckingReceive->asn}}'},
  140. storeCheckingReceiveItems:[
  141. @foreach($storeCheckingReceive->storeCheckingReceiveItems as $storeCheckingReceiveItem)
  142. {id:'{{$storeCheckingReceiveItem->id}}',bin_number:'{{$storeCheckingReceiveItem->bin_number}}',
  143. commodity_name:"{{$storeCheckingReceiveItem->commodity ? $storeCheckingReceiveItem->commodity->name : ''}}",
  144. commodity_barcodes:{!! $storeCheckingReceiveItem->commodity ? ($storeCheckingReceiveItem->commodity->barcodes ? $storeCheckingReceiveItem->commodity->barcodes : []) : [] !!},
  145. imported_amount:'{{$storeCheckingReceiveItem->imported_amount}}',counted_amount:'{{$storeCheckingReceiveItem->counted_amount}}',
  146. asn_amount:'{{$storeCheckingReceiveItem->asn_amount}}',imported_diff_amount:'{{$storeCheckingReceiveItem->imported_diff_amount}}',
  147. asn_diff_amount:'{{$storeCheckingReceiveItem->asn_diff_amount}}',produced_at:'{{$storeCheckingReceiveItem->produced_at}}',
  148. invalid_at:'{{$storeCheckingReceiveItem->invalid_at}}',batch_code:'{{$storeCheckingReceiveItem->batch_code}}',
  149. unique_code:'{{$storeCheckingReceiveItem->unique_code}}'}
  150. @endforeach
  151. ],
  152. inputMode : 'regular',
  153. status:{
  154. barcodeDisable : true,
  155. commitButtonVisible:false,
  156. scanEndInputted:false,
  157. amountDisable : false,
  158. },
  159. focusing : 'document',
  160. inputting:{
  161. barcode : '',
  162. amount : '',
  163. bin : '',
  164. batch_number : '',
  165. },
  166. goodses : [],
  167. },
  168. mounted(){
  169. $('#container').removeClass('d-none');
  170. $(".tooltipTarget").tooltip({'trigger':'hover'});
  171. let column = [
  172. {name:'index',value: '序号', neglect: true},
  173. {name:'id',value: 'ID', neglect: true},
  174. {name:'bin_number',value: '格口号'},
  175. {name:'commodity_name',value: '商品名'},
  176. {name:'commodity_barcode',value: '商品条码'},
  177. {name:'imported_amount',value: '导入数量', neglect: true},
  178. {name:'counted_amount',value: '实盘数量', neglect: true},
  179. {name:'asn_amount',value: 'ASN数量', neglect: true},
  180. {name:'imported_diff_amount',value: '导入差异数', neglect: true},
  181. {name:'asn_diff_amount',value: 'ASN差异数', neglect: true},
  182. {name:'produced_at',value: '生产日期'},
  183. {name:'invalid_at',value: '有效期'},
  184. {name:'batch_code',value: '批次号'},
  185. {name:'unique_code',value: '唯一码'},
  186. ];
  187. let header = new Header({
  188. el: "#header",
  189. column: column,
  190. data: this.storeCheckingReceiveItems,
  191. restorationColumn: 'id',
  192. });
  193. header.init();
  194. this.scanListening();
  195. },
  196. methods:{
  197. switchMenu(menuName){
  198. this.inputMode = menuName;
  199. this.inputting.barcode='';
  200. if (menuName === 'regular') {
  201. this.status.amountDisable = false;
  202. $('#amountLabel').text('输入数量:');
  203. }else {
  204. this.status.amountDisable = true;
  205. $('#amountLabel').text('自动扫入数量:');
  206. }
  207. },
  208. scanListening: function () {
  209. let _this = this;
  210. $(document).on('keypress', function (e) {
  211. if(_this.focusing!=='document'){return}
  212. if(!_this.status.barcodeDisable){return}
  213. if (e.keyCode !== 13) {
  214. if(_this.status.scanEndInputted){
  215. _this.inputting.barcode='';
  216. _this.status.scanEndInputted=false;
  217. }
  218. _this.inputting.barcode += String.fromCharCode(e.keyCode);
  219. } else {
  220. if(_this.inputting.barcode.length<=1){
  221. window.tempTip.setDuration(4500);
  222. window.tempTip.show('未扫入条码,请检查扫码枪设置,尝试调至“直接键盘输出”模式');
  223. return;
  224. }
  225. _this.status.scanEndInputted = true;
  226. _this.showCommitButton();
  227. _this.autoFillBin();
  228. switch(_this.inputMode){
  229. case 'increasing': _this.commitGoodsOnIncreasingMode();break;
  230. case 'multiIncreasing': _this.commitGoodsOnMultiIncreasingMode();break;
  231. }
  232. }
  233. });
  234. },
  235. showCommitButton: function () {
  236. if(this.inputting.barcode && this.inputting.amount && this.inputting.bin){
  237. if (this.status.commitButtonVisible){
  238. this.commitGoods();
  239. this.status.commitButtonVisible=false;
  240. }else this.status.commitButtonVisible=true;
  241. }
  242. },
  243. commitGoods: function () {
  244. window.tempTip.setDuration(3500);
  245. if(!this.inputting.barcode){window.tempTip.show('请扫入条码');return;}
  246. else if(!this.inputting.amount){window.tempTip.show('请输入数量');return;}
  247. else if(!this.inputting.bin){window.tempTip.show('请输入隔口号');return;}
  248. this.recordOrPlusGoods();
  249. window.tempTip.setDuration(1500);
  250. window.tempTip.showSuccess('成功提交:' + data.inputting.barcode);
  251. this.cleanInputs();
  252. this.audioDing();
  253. },
  254. cleanInputs: function () {
  255. this.changeToScanInputBarcode();
  256. this.inputting.barcode='';
  257. this.inputting.amount='';
  258. this.inputting.bin='';
  259. this.inputting.produce_date='';
  260. this.inputting.valid_date='';
  261. this.inputting.batch_number='';
  262. this.status.commitButtonVisible=false;
  263. this.status.binDisable=false;
  264. },
  265. autoFillBin: function () {
  266. let data = this;
  267. let isNotRepeatingBarcode=this.goodses.every(function(goods){
  268. if(goods.barcode===data.inputting.barcode){
  269. data.inputting.bin=goods.bin;
  270. data.status.binDisable=true;
  271. return false;
  272. }
  273. return true;
  274. });
  275. if(isNotRepeatingBarcode){
  276. data.status.binDisable=false;
  277. }
  278. },
  279. commitGoodsOnIncreasingMode: function () {
  280. let data = this;
  281. function doIt() {
  282. let repeatedBarcode = data.repeatedIncreasingBarcodeFromSaved();
  283. function increase() {
  284. data.inputting.bin = repeatedBarcode.bin;
  285. repeatedBarcode.amount++;
  286. data.inputting.amount = repeatedBarcode.amount;
  287. window.tempTip.setDuration(500);
  288. window.tempTip.showSuccess(repeatedBarcode.amount);
  289. data.focusDocument();
  290. data.audioDing();
  291. }
  292. if (!repeatedBarcode) {
  293. data.focusOutDocument();
  294. data.alertVibrate();
  295. window.tempTip.setInputType('number');
  296. window.tempTip.inputVal('该商品第一件递增请输入隔口号:', function (bin) {
  297. if (bin === '') {
  298. window.tempTip.setDuration(1500);
  299. window.tempTip.show('未输入隔口号,请重新扫描');
  300. data.alertVibrate();
  301. data.focusDocument();
  302. return
  303. }
  304. data.inputting.bin = bin;
  305. data.inputting.amount = 1;
  306. data.goodses.unshift(JSON.parse(JSON.stringify(data.inputting)));
  307. data.status.binDisable = true;
  308. window.tempTip.setDuration(500);
  309. window.tempTip.showSuccess('保存成功');
  310. data.focusDocument();
  311. data.audioDing();
  312. })
  313. } else {
  314. increase();
  315. }
  316. }
  317. if (data.lastScannedBarcode !== data.inputting.barcode && data.lastScannedBarcode) {
  318. data.audioWarning_otherBarcode();
  319. data.focusOutDocument();
  320. window.tempTip.confirm('扫到其它条码,是否切换至新条码并记录?', doIt, function () {
  321. data.inputting.barcode = data.lastScannedBarcode;
  322. data.focusDocument();
  323. })
  324. } else {
  325. doIt()
  326. }
  327. },
  328. commitGoodsOnMultiIncreasingMode: function () {
  329. let data = this;
  330. let repeatedBarcode=this.repeatedIncreasingBarcodeFromSaved();
  331. function increase(){
  332. data.inputting.bin=repeatedBarcode.bin;
  333. repeatedBarcode.amount++;
  334. data.inputting.amount=repeatedBarcode.amount;
  335. window.tempTip.setDuration(500);
  336. window.tempTip.showSuccess(repeatedBarcode.amount);
  337. data.focusDocument();
  338. data.audioDing();
  339. }
  340. if(!repeatedBarcode){
  341. data.focusOutDocument();
  342. data.alertVibrate();
  343. window.tempTip.setInputType('number');
  344. window.tempTip.inputVal('该商品第一件递增请输入隔口号:',function(bin){
  345. if(bin===''){
  346. window.tempTip.setDuration(1500);
  347. window.tempTip.show('未输入隔口号,请重新扫描');
  348. data.alertVibrate();
  349. data.focusDocument();return}
  350. data.inputting.bin=bin;
  351. data.inputting.amount=1;
  352. data.goodses.unshift(JSON.parse(JSON.stringify(data.inputting)));
  353. data.status.binDisable=true;
  354. window.tempTip.setDuration(500);
  355. window.tempTip.showSuccess('保存成功');
  356. data.focusDocument();
  357. data.audioDing();
  358. })
  359. }else{
  360. increase();
  361. }
  362. },
  363. oninputEnter:function(e){
  364. if (e.key === 'Enter') {
  365. this.focusDocument();
  366. }
  367. },
  368. focusDocument: function () {
  369. this.focusing = 'document';
  370. this.showCommitButton();
  371. },
  372. focusOutDocument: function () {
  373. this.focusing = '';
  374. this.autoFillBin();
  375. },
  376. audioWarning_otherBarcode: function () {
  377. let audio = document.getElementById('soundWarning');
  378. audio.currentTime = 0;//重新播放
  379. if(audio.paused){
  380. audio.play();// 播放
  381. }
  382. this.alertVibrate();
  383. },
  384. audioDing: function () {
  385. let audio = document.getElementById('soundDing');
  386. audio.currentTime = 0;//重新播放
  387. audio.play();// 播放
  388. //手机震动
  389. function startVibrate(duration) {
  390. if (navigator.vibrate) {
  391. navigator.vibrate(duration);
  392. } else if (navigator.webkitVibrate) {
  393. navigator.webkitVibrate(duration);
  394. }
  395. }
  396. startVibrate(500);
  397. },
  398. recordOrPlusGoods: function () {
  399. if(this.inputMode==='regular'){
  400. this.addGoods();
  401. return;
  402. }
  403. let isNotRepeating=this.goodses.every(goods => {
  404. if(goods.barcode===this.inputting.barcode){
  405. goods.amount=parseInt(goods.amount)+parseInt(this.inputting.amount);
  406. return false;
  407. }
  408. return true;
  409. });
  410. if(isNotRepeating)this.addGoods();
  411. },
  412. addGoods(){
  413. this.goodses.unshift(JSON.parse(JSON.stringify(this.inputting)));
  414. }
  415. },
  416. });
  417. </script>
  418. @stop