Jelajahi Sumber

盲收神器置入

LD 5 tahun lalu
induk
melakukan
9059a42dba

+ 1 - 1
app/Exports/GoodsNeateningExcelExport.php → app/Exports/InventoryBlindReceiveExcelExport.php

@@ -6,7 +6,7 @@ use App\User;
 use Illuminate\Support\Collection;
 use Maatwebsite\Excel\Concerns\FromCollection;
 
-class GoodsNeateningExcelExport implements FromCollection
+class InventoryBlindReceiveExcelExport implements FromCollection
 {
     private $data;
     public function __construct($data)

+ 11 - 11
app/Http/Controllers/ExcelController.php

@@ -2,8 +2,8 @@
 
 namespace App\Http\Controllers;
 
-use App\Exports\GoodsNeateningExcelExport;
-use App\GoodsNeateningExcel;
+use App\Exports\InventoryBlindReceiveExcelExport;
+use App\InventoryBlindReceiveExcel;
 use Carbon\Carbon;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\DB;
@@ -59,17 +59,17 @@ class ExcelController extends Controller
             array_push($goodsesExcelArray,[$barcode,$obj['weight']??'',($obj['id']??'').' '
                 ,($obj['key'])??'',($obj['time'])??'', ($url)??'']);
         }
-        Excel::store(new GoodsNeateningExcelExport($goodsesExcelArray),'exportedJson.xlsx','public');
+        Excel::store(new InventoryBlindReceiveExcelExport($goodsesExcelArray),'exportedJson.xlsx','public');
         return ['result'=>'success'];
     }
 
     /**
      * Display the specified resource.
      *
-     * @param  \App\GoodsNeateningExcel  $goodsNeateningExcel
+     * @param  \App\InventoryBlindReceiveExcel  $goodsNeateningExcel
      * @return \Illuminate\Http\Response
      */
-    public function show(GoodsNeateningExcel $goodsNeateningExcel)
+    public function show(InventoryBlindReceiveExcel $goodsNeateningExcel)
     {
         //
     }
@@ -77,10 +77,10 @@ class ExcelController extends Controller
     /**
      * Show the form for editing the specified resource.
      *
-     * @param  \App\GoodsNeateningExcel  $goodsNeateningExcel
+     * @param  \App\InventoryBlindReceiveExcel  $goodsNeateningExcel
      * @return \Illuminate\Http\Response
      */
-    public function edit(GoodsNeateningExcel $goodsNeateningExcel)
+    public function edit(InventoryBlindReceiveExcel $goodsNeateningExcel)
     {
         //
     }
@@ -89,10 +89,10 @@ class ExcelController extends Controller
      * Update the specified resource in storage.
      *
      * @param  \Illuminate\Http\Request  $request
-     * @param  \App\GoodsNeateningExcel  $goodsNeateningExcel
+     * @param  \App\InventoryBlindReceiveExcel  $goodsNeateningExcel
      * @return \Illuminate\Http\Response
      */
-    public function update(Request $request, GoodsNeateningExcel $goodsNeateningExcel)
+    public function update(Request $request, InventoryBlindReceiveExcel $goodsNeateningExcel)
     {
         //
     }
@@ -100,10 +100,10 @@ class ExcelController extends Controller
     /**
      * Remove the specified resource from storage.
      *
-     * @param  \App\GoodsNeateningExcel  $goodsNeateningExcel
+     * @param  \App\InventoryBlindReceiveExcel  $goodsNeateningExcel
      * @return \Illuminate\Http\Response
      */
-    public function destroy(GoodsNeateningExcel $goodsNeateningExcel)
+    public function destroy(InventoryBlindReceiveExcel $goodsNeateningExcel)
     {
         //
     }

+ 98 - 0
app/Http/Controllers/InventoryBlindReceiveExcelController.php

@@ -0,0 +1,98 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Exports\InventoryBlindReceiveExcelExport;
+use App\InventoryBlindReceiveExcel;
+use Carbon\Carbon;
+use Illuminate\Http\Request;
+use Maatwebsite\Excel\Facades\Excel;
+
+class InventoryBlindReceiveExcelController extends Controller
+{
+    public function index()
+    {
+        $excels=InventoryBlindReceiveExcel::orderBy('id','desc')->get();
+        return view('inventory.blindReceive.excel.index',['excels'=>$excels]);
+    }
+    public function create()
+    {
+
+    }
+    public function store(Request $request)
+    {
+        //
+    }
+    public function apiStore(Request $request)
+    {
+        $request=json_decode($request->getContent(),true);
+        $goodses=$request['goodses']??'';
+        $excelFileName=$request['filename']??'';
+        if(!$goodses||!is_array($goodses)||count($goodses)==0){
+            return ['result'=>'failure','fail_info'=>'没有数据提交!'];
+        }
+        $goodsesExcelArray=[['隔口','数量','条码','生产日期','失效日期','批次号']];
+        foreach ($goodses as $goods){
+            array_push($goodsesExcelArray,[$goods['bin'],$goods['amount'],$goods['barcode'].' '
+                ,$goods['produce_date'],$goods['valid_date'],$goods['batch_number']]);
+        }
+        $fileName=Carbon::now()->toDateTimeLocalString().microtime(true).'.xlsx';
+        $fileName = str_replace( ':', '_',$fileName);
+        $goodsNeateningExcel = new InventoryBlindReceiveExcel(['file' => $fileName, 'goods_amount' => count($goodses), 'name'=>$excelFileName]);
+        $goodsNeateningExcel->save();
+        Excel::store(new InventoryBlindReceiveExcelExport($goodsesExcelArray),$fileName,'public');
+        $this->removeExpiredExcel();
+        return ['result'=>'success'];
+    }
+    private function removeExpiredExcel(){
+        $excels=InventoryBlindReceiveExcel::where('created_at','<',Carbon::now()->subDays(100)->toDateTimeString())->get();
+        $excels->each(function(InventoryBlindReceiveExcel $excel){
+            $excel->delete();
+        });
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  \App\InventoryBlindReceiveExcel  $goodsNeateningExcel
+     * @return \Illuminate\Http\Response
+     */
+    public function show(InventoryBlindReceiveExcel $goodsNeateningExcel)
+    {
+        //
+    }
+
+    /**
+     * Show the form for editing the specified resource.
+     *
+     * @param  \App\InventoryBlindReceiveExcel  $goodsNeateningExcel
+     * @return \Illuminate\Http\Response
+     */
+    public function edit(InventoryBlindReceiveExcel $goodsNeateningExcel)
+    {
+        //
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \App\InventoryBlindReceiveExcel  $goodsNeateningExcel
+     * @return \Illuminate\Http\Response
+     */
+    public function update(Request $request, InventoryBlindReceiveExcel $goodsNeateningExcel)
+    {
+        //
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  \App\InventoryBlindReceiveExcel  $goodsNeateningExcel
+     * @return \Illuminate\Http\Response
+     */
+    public function destroy(InventoryBlindReceiveExcel $goodsNeateningExcel)
+    {
+        //
+    }
+}

+ 19 - 0
app/InventoryBlindReceiveExcel.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Facades\Storage;
+
+class InventoryBlindReceiveExcel extends Model
+{
+    //
+    protected $fillable = [
+        'file','goods_amount','name'
+    ];
+    public function delete()
+    {
+        Storage::disk('public')->delete($this['file']);
+        return parent::delete();
+    }
+}

+ 35 - 0
database/migrations/2020_09_11_155001_create_inventory_blind_receive_excels_table.php

@@ -0,0 +1,35 @@
+<?php
+
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class CreateInventoryBlindReceiveExcelsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('inventory_blind_receive_excels', function (Blueprint $table) {
+            $table->bigIncrements('id');
+            $table->string('name')->nullable();
+            $table->string('file');
+            $table->integer('goods_amount');
+            $table->timestamps();
+            $table->timestamp('created_at')->nullable()->index()->change();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('inventory_blind_receive_excels');
+    }
+}

File diff ditekan karena terlalu besar
+ 0 - 61994
public/js/app.js


TEMPAT SAMPAH
public/sound/ding.mp3


TEMPAT SAMPAH
public/sound/warning_otherBarcode.mp3


+ 1 - 1
resources/js/utilities/tempTip.js

@@ -96,7 +96,7 @@ const tempTip={
         $('body').append(tiper);
     },
     inputVal:function(tipText,resultFunc){
-        let bg=$("<div style='opacity:0.4;position:fixed;top:0;width:100%;height:100%;z-index:"+this.index+";background-color:#000;'></div>" );
+        let bg=$("<div style='opacity:0.4;position:fixed;top:0;width:100%;height:100%;z-index:"+(this.index-1)+";background-color:#000;'></div>" );
         let tiper=$("<div class='row' style='color:#000;opacity:0.9;position:fixed;top:40%;transform:translateY(-50%);width:100%;z-index:"+this.index+"'>" +
             "<div class='col-8 offset-2'><div class='card'><div class='card-body'><div class='card-title h5'>" +
             tipText +

TEMPAT SAMPAH
resources/sound/ding.mp3


TEMPAT SAMPAH
resources/sound/warning_otherBarcode.mp3


+ 32 - 0
resources/views/inventory/blindReceive/excel/index.blade.php

@@ -0,0 +1,32 @@
+@extends('layouts.app')
+
+@section('content')
+    <div id="nav2">
+        @component('inventory.blindReceive.menu')@endcomponent
+    </div>
+    <div class="container">
+        <div class="row mt-2">
+            <div class="col-12">
+                <p><span class="h4">Excel文件列表</span><span class="text-muted">(仅保留三个月以内的文件)</span></p>
+                <table class="table table-striped">
+                    <tr>
+                        <th>序号</th>
+                        <th>名称</th>
+                        <th>时间</th>
+                        <th>条目数</th>
+                        <th>文件下载</th>
+                    </tr>
+                    @foreach($excels as $i=>$excel)
+                        <tr>
+                            <td>{{$i+1}}</td>
+                            <td>{{$excel['name']}}</td>
+                            <td>{{$excel['created_at']}}</td>
+                            <td>{{$excel['goods_amount']}}</td>
+                            <td><a href="{{asset('storage/'.$excel['file'])}}"><span class="fa fa-download"></span><span class="fa fa-download"></span><span class="fa fa-download"></span></a></td>
+                        </tr>
+                    @endforeach
+                </table>
+            </div>
+        </div>
+    </div>
+@endsection

+ 471 - 0
resources/views/inventory/blindReceive/index.blade.php

@@ -0,0 +1,471 @@
+@extends('layouts.app')
+
+@section('content')
+    <div class="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 mt-2">
+            <div class="col-12" id="scanColumn">
+                <div class="card" :class="borderByMode">
+                    <div class="card-body">
+                        <div class="row">
+                            <div class="col-12">
+                                <p class="text-muted" style="font-size: 0.5em" v-if="inputMode=='regular'">常规:可输入效期,相同条码记录不会合并</p>
+                                <p class="text-muted" style="font-size: 0.5em" v-if="inputMode=='increasing'">逐一扫描:处理单一重复商品,每扫一次对应隔口总数量自动递增,扫到不同条码会提示</p>
+                                <p class="text-muted" style="font-size: 0.5em" v-if="inputMode=='multiIncreasing'">边扫边分:处理多种商品,自动将扫到的不同条码数量递增到各自隔口号</p>
+                                <ul class="nav nav-tabs mb-4 mt-n3">
+                                    <li class="nav-item"><a href="#" class="nav-link" :class="inputMode=='regular'?'active':''"
+                                                            @click="inputMode='regular';changeToManualInputAmount();cleanInputs();inputting.fromIncreasing=false">常规</a></li>
+                                    <li class="nav-item"><a href="#" class="nav-link" :class="inputMode=='increasing'?'active':''"
+                                                            @click="inputMode='increasing';changeToScanInputAmount();cleanInputs();inputting.fromIncreasing=true;">逐一扫描</a></li>
+                                    <li class="nav-item"><a href="#" class="nav-link" :class="inputMode=='multiIncreasing'?'active':''"
+                                                            @click="inputMode='multiIncreasing';changeToScanInputAmount();cleanInputs();inputting.fromIncreasing=true">边扫边分</a></li>
+                                </ul>
+                            </div>
+                            <div class="col-6">
+                                <div v-if="inputMode=='regular'">
+                                    <div class="btn btn-sm btn-outline-primary"
+                                         v-if="!isManualInputtingBarcode" @click="changeToManualInputBarcode">手动输入</div>
+                                    <div class="btn btn-sm btn-outline-danger"
+                                         @click="changeToScanInputBarcode" v-if="isManualInputtingBarcode">扫描输入</div>
+                                </div>
+                                <input type="text" id="barcode" class="form-control" :disabled="status.barcodeDisable" placeholder="扫入条码" @focusin="focusOutDocument" @focusout="focusDocument" v-model="inputting.barcode">
+                                <div v-if="inputMode=='regular'">
+                                    <div class="card-title">
+                                        生产日期:
+                                    </div>
+                                    <input type="date" class="form-control mb-2" v-model="inputting.produce_date" @focusin="focusOutDocument" @focusout="focusDocument" @keyup="oninputEnter">
+                                </div>
+                                <div v-if="inputMode=='regular'">
+                                    <div class="card-title">
+                                        失效日期:
+                                    </div>
+                                    <input type="date" class="form-control mb-2" v-model="inputting.valid_date" @focusin="focusOutDocument" @focusout="focusDocument" @keyup="oninputEnter">
+                                </div>
+                            </div>
+                            <div class="col-6">
+                                <div class="card-title" id="amountLabel">
+                                    手动输入数量:
+                                </div>
+                                <div class="input-group mt-n2 mb-2">
+                                    <input type="number" id="amount" class="form-control" placeholder="" :disabled="status.amountDisable"
+                                           v-model="inputting.amount" @focusin="focusOutDocument" @focusout="focusDocument" @keyup="oninputEnter"
+                                           style='height: 40px;font-size: 1.6em;color:blue;font-weight: bolder;padding: 3px;text-align: center'>
+                                </div>
+                                <div class="card-title">
+                                    格口号:
+                                </div>
+                                <input type="number" id="bin" class="form-control mt-n2 mb-2"
+                                       v-model="inputting.bin"
+                                       :disabled="status.binDisable" @focusin="focusOutDocument" @focusout="focusDocument" @keyup="oninputEnter"
+                                       style='height: 80px;font-size: 5em;color:red;font-weight: bolder;padding: 3px;text-align: center'>
+                                <div v-if="inputMode=='regular'">
+                                    <div class="card-title">
+                                        批次号:
+                                    </div>
+                                    <input type="text" class="form-control mb-2" v-model="inputting.batch_number" @focusin="focusOutDocument" @focusout="focusDocument" @keyup="oninputEnter">
+                                </div>
+                            </div>
+                            <div class="col-12" v-if="commitButtonVisible && inputMode=='regular'" >
+                                <button class="btn btn-success btn form-control" @click="commitGoods">确定</button>
+                            </div>
+                        </div>
+                        <p class="card-text text-muted mt-3 mb-n3 text-center">
+                            已完成:
+                        </p>
+                        <hr>
+                        <table class="table table-sm  table-striped" v-if="goodses.length>0">
+                            <tr>
+                                <th>隔口号</th>
+                                <th>数量</th>
+                                <th>条码</th>
+                                <th>生产日期</th>
+                                <th>失效日期</th>
+                                <th>批次号</th>
+                                <th>操作</th>
+                            </tr>
+                            <tr v-for="goods in goodses">
+                                <td>@{{ goods.bin }}</td>
+                                <td>@{{ goods.amount }}</td>
+                                <td>@{{ goods.barcode }}</td>
+                                <td>@{{ goods.produce_date }}</td>
+                                <td>@{{ goods.valid_date }}</td>
+                                <td>@{{ goods.batch_number }}</td>
+                                <td><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">结束并生成Excel</span>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+@endsection
+
+@section('lastScript')
+    <script>
+        new Vue({
+            el: '#app',
+            data:{
+                focusing:'document',
+                commitButtonVisible:false,
+                isManualInputtingBarcode:false,
+                isManualInputtingAmount:true,
+                lastScannedBarcode:'',
+                inputMode:'regular',//regular,increasing,multiIncreasing
+                inputting:{
+                    barcode:'',amount:'',bin:'',produce_date:'',valid_date:'',batch_number:'',fromIncreasing:false
+                },
+                status:{
+                    scanEndInputted:false,binDisable:false,barcodeDisable:true,amountDisable:false,
+                },
+                goodses:[],//{barcode,amount,bin,produce_date,valid_date,batch_number}
+            },
+            mounted() {
+                this.scanListening();
+            },
+            methods: {
+                changeToManualInputAmount:function(){
+                    this.status.amountDisable=false;
+                    this.isManualInputtingAmount=true;
+                    $('#amountLabel').text('输入数量:');
+                    // $('#amount').attr('placeholder','数字');
+                },
+                changeToScanInputAmount:function(){
+                    this.status.amountDisable=true;
+                    this.isManualInputtingAmount=false;
+                    $('#amountLabel').text('自动扫入数量:');
+                    // $('#amount').attr('placeholder','自动');
+                },
+                changeToManualInputBarcode:function(){
+                    this.status.barcodeDisable=false;
+                    this.isManualInputtingBarcode=true;
+                    $('#barcode').attr('placeholder','手工输入条码');
+                },
+                changeToScanInputBarcode:function(){
+                    let data = this;
+                    this.isManualInputtingBarcode=false;
+                    this.inputting.barcode='';
+
+                    let $barcode = $('#barcode');
+                    this.status.barcodeDisable=false;
+                    setTimeout(function () {
+                        $barcode.focus();
+                        data.status.barcodeDisable=true;
+                    },20);
+                    $barcode.attr('placeholder','扫入条码');
+                },
+                oninputEnter:function(e){
+                    if (e.key === 'Enter') {
+                        this.focusDocument();
+                    }
+                },
+                focusDocument: function () {
+                    this.focusing = 'document';
+                    this.showCommitButton();
+                },
+                focusOutDocument: function () {
+                    this.focusing = '';
+                    this.autoFillBin();
+                },
+                scanListening: function () {
+                    let data = this;
+                    $(document).on('keypress', function (e) {
+                        if(data.focusing!=='document'){return}
+                        if(data.isManualInputtingBarcode){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;
+                            data.showCommitButton();
+                            data.autoFillBin();
+                            switch(data.inputMode){
+                                case 'increasing': data.commitGoodsOnIncreasingMode();break;
+                                case 'multiIncreasing': data.commitGoodsOnMultiIncreasingMode();break;
+                            }
+                        }
+                    });
+                },
+                commitGoodsOnIncreasingMode: function () {
+                    let data = this;
+                    function doIt(){
+                        let repeatedBarcode=data.repeatedIncreasingBarcodeFromSaved();
+                        function increase(){
+                            data.inputting.bin=repeatedBarcode.bin;
+                            repeatedBarcode.amount++;
+                            data.inputting.amount=repeatedBarcode.amount;
+                            window.tempTip.setDuration(500);
+                            window.tempTip.showSuccess(repeatedBarcode.amount);
+                            data.focusDocument();
+                            data.audioDing();
+                        }
+                        if(!repeatedBarcode){
+                            data.focusOutDocument();
+                            data.alertVibrate();
+                            window.tempTip.setInputType('number');
+                            window.tempTip.inputVal('该商品第一件递增请输入隔口号:',function(bin){
+                                if(bin===''){
+                                    window.tempTip.setDuration(1500);
+                                    window.tempTip.show('未输入隔口号,请重新扫描');
+                                    data.alertVibrate();
+                                    data.focusDocument();return}
+                                data.inputting.bin=bin;
+                                data.inputting.amount=1;
+                                data.goodses.unshift(JSON.parse(JSON.stringify(data.inputting)));
+                                data.status.binDisable=true;
+                                window.tempTip.setDuration(500);
+                                window.tempTip.showSuccess('保存成功');
+                                data.focusDocument();
+                                data.audioDing();
+                            })
+                        }else{
+                            increase();
+                        }
+                    }
+                    if(data.lastScannedBarcode!==data.inputting.barcode && data.lastScannedBarcode){
+                        data.audioWarning_otherBarcode();
+                        data.focusOutDocument();
+                        window.tempTip.confirm('扫到其它条码,是否切换至新条码并记录?',doIt,function () {
+                            data.inputting.barcode=data.lastScannedBarcode;
+                            // data.cleanInputs();
+                            data.focusDocument();
+                        })
+                    }else{
+                        doIt()
+                    }
+                },
+                commitGoodsOnMultiIncreasingMode: function () {
+                    let data = this;
+                    let repeatedBarcode=this.repeatedIncreasingBarcodeFromSaved();
+                    function increase(){
+                        data.inputting.bin=repeatedBarcode.bin;
+                        repeatedBarcode.amount++;
+                        data.inputting.amount=repeatedBarcode.amount;
+                        window.tempTip.setDuration(500);
+                        window.tempTip.showSuccess(repeatedBarcode.amount);
+                        data.focusDocument();
+                        data.audioDing();
+                    }
+                    if(!repeatedBarcode){
+                        data.focusOutDocument();
+                        data.alertVibrate();
+                        window.tempTip.setInputType('number');
+                        window.tempTip.inputVal('该商品第一件递增请输入隔口号:',function(bin){
+                            if(bin===''){
+                                window.tempTip.setDuration(1500);
+                                window.tempTip.show('未输入隔口号,请重新扫描');
+                                data.alertVibrate();
+                                data.focusDocument();return}
+                            data.inputting.bin=bin;
+                            data.inputting.amount=1;
+                            data.goodses.unshift(JSON.parse(JSON.stringify(data.inputting)));
+                            data.status.binDisable=true;
+                            window.tempTip.setDuration(500);
+                            window.tempTip.showSuccess('保存成功');
+                            data.focusDocument();
+                            data.audioDing();
+                        })
+                    }else{
+                        increase();
+                    }
+                },
+                audioWarning_otherBarcode: function () {
+                    let audio = document.getElementById('soundWarning');
+                    audio.currentTime = 0;//重新播放
+                    if(audio.paused){
+                        audio.play();// 播放
+                    }
+                    this.alertVibrate();
+
+                },
+                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);
+                },
+                autoFillBin: function () {
+                    let data = this;
+                    let isNotRepeatingBarcode=this.goodses.every(function(goods){
+                        if(goods.barcode===data.inputting.barcode){
+                            data.inputting.bin=goods.bin;
+                            data.status.binDisable=true;
+                            return false;
+                        }
+                        return true;
+                    });
+                    if(isNotRepeatingBarcode){
+                        data.status.binDisable=false;
+                    }
+                },
+                repeatedIncreasingBarcodeFromSaved: function () {
+                    let data = this;
+                    let repeatedGoods=null;
+                    data.goodses.every(function(goods){
+                        if(goods.barcode===data.inputting.barcode && goods.fromIncreasing){
+                            repeatedGoods=goods;
+                            return false;
+                        }
+                        return true;
+                    });
+                    return repeatedGoods;
+                },
+                commitGoods: function () {
+                    let data = this;
+                    window.tempTip.setDuration(3500);
+                    if(!data.inputting.barcode){window.tempTip.show('请扫入条码');return;}
+                    else if(!data.inputting.amount){window.tempTip.show('请输入数量');return;}
+                    else if(!data.inputting.bin){window.tempTip.show('请输入隔口号');return;}
+                    data.recordOrPlusGoods();
+                    window.tempTip.setDuration(1500);
+                    window.tempTip.showSuccess('成功提交:' + data.inputting.barcode);
+                    data.cleanInputs();
+                    data.audioDing();
+                },
+                cleanInputs: function () {
+                    this.changeToScanInputBarcode();
+                    this.inputting.barcode='';
+                    this.inputting.amount='';
+                    this.inputting.bin='';
+                    this.inputting.produce_date='';
+                    this.inputting.valid_date='';
+                    this.inputting.batch_number='';
+                    this.commitButtonVisible=false;
+                    this.status.binDisable=false;
+                    this.lastScannedBarcode='';
+                },
+                recordOrPlusGoods: function () {
+                    let data = this;
+                    if(this.inputMode==='regular'){
+                        data.goodses.unshift(JSON.parse(JSON.stringify(data.inputting)));
+                        return;
+                    }
+                    let isNotRepeating=data.goodses.every(function(goods){
+                        if(goods.barcode===data.inputting.barcode){
+                            goods.amount=parseInt(goods.amount)+parseInt(data.inputting.amount);
+                            return false;
+                        }
+                        return true;
+                    });
+                    if(isNotRepeating){
+                        data.goodses.unshift(JSON.parse(JSON.stringify(data.inputting)));
+                    }
+                },
+                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;
+                    })
+                },
+                showCommitButton: function () {
+                    let data = this;
+                    if(data.inputting.barcode && data.inputting.amount && data.inputting.bin){
+                        data.commitButtonVisible=true;
+                    }
+                },
+                submitExcelData: function () {
+                    let data = this;
+                    data.focusOutDocument();
+                    if(data.goodses.length===0){
+                        window.tempTip.show('请先录入数据再提交EXCEL');return;
+                    }
+                    window.tempTip.confirm('请检查表格,确定全部完成。提交后数据将全部清空,不能后退',
+                        function () {
+                            window.tempTip.setInputType('input');
+                            window.tempTip.setIndex(999999);
+                            window.tempTip.inputVal('请输入文件名:',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("inventory/blindReceive/excels/apiStore")}}';
+                                axios.post(url,{'goodses':data.goodses,'filename':val})
+                                    .then(function(response){
+                                        if(response.data.result==='success'){
+                                            data.goodses=[];
+                                            data.cleanInputs();
+                                            window.tempTip.cancelWaitingTip();
+                                            window.tempTip.setDuration(1500);
+                                            window.tempTip.showSuccess('成功生成EXCEL,可在列表页查看');
+                                            data.focusDocument();
+                                        }else{
+                                            window.tempTip.setDuration(1500);
+                                            window.tempTip.show('生成EXCEL失败:'+response.data.fail_info);
+                                            console.log(response);
+                                            data.focusDocument();
+                                            data.alertVibrate()
+                                        }
+                                        clearInterval(expireHandler);
+                                    })
+                                    .catch(function (err) {
+                                        window.tempTip.setDuration(3500);
+                                        window.tempTip.show('网络或系统错误,请将以下信息提交给开发者:'+err);
+                                        clearInterval(expireHandler);
+                                        data.alertVibrate();
+                                    });
+                            });
+                        },function () {
+                            data.focusDocument();
+                        })
+                }
+            },
+            computed: {
+                borderByMode: function () {
+                    return {
+                        // 'border-info':this.inputMode==='regular',
+                        'border-success':this.inputMode==='increasing',
+                        'border-danger':this.inputMode==='multiIncreasing'
+                    }
+                }
+            }
+        });
+    </script>
+@endsection

+ 58 - 0
resources/views/inventory/blindReceive/layout.blade.php

@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+
+    <!-- CSRF Token -->
+    <meta name="csrf-token" content="{{ csrf_token() }}">
+
+    <title>盲收神器</title>
+
+    <!-- Styles -->
+    <link rel="shortcut icon" href="{{asset('icon/WcsIcon_blindPack.ico')}}" />
+    <link rel="bookmark" href="{{asset('icon/WcsIcon_blindPack.ico')}}" />
+    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
+</head>
+<body>
+<div id="app">
+    <nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm" id="nav1">
+        <div class="container">
+            <span class="navbar-brand">
+                盲收神器
+            </span>
+        </div>
+    </nav>
+    @yield('content')
+</div>
+</body>
+<!-- Scripts -->
+@yield('script_before')
+{{-- 必须在app.js前边--}}
+<script src="{{ asset('js/app.js') }}"></script>
+<script>
+    let isActive=function (name,atSlashLevel) {
+        let uriWithNoParam=location.href.split('?')[0];
+        let uriParts=uriWithNoParam.split('//')[1].split('/');
+        if(!name){
+            return uriParts.length===atSlashLevel;
+        }
+        if(atSlashLevel>uriParts.length||!atSlashLevel)return false;
+        return uriParts[atSlashLevel]===name;
+    };
+    new Vue({
+        el:'#nav1',
+        methods:{
+            isActive:isActive,
+        }
+    });
+    if($('#nav2').length>0)
+        new Vue({
+            el:'#nav2',
+            methods:{
+                isActive:isActive,
+            }
+        });
+</script>
+@yield('script_after')
+</html>

+ 13 - 0
resources/views/inventory/blindReceive/menu.blade.php

@@ -0,0 +1,13 @@
+
+<div class="container-fluid mt-3" id="nav2">
+    <div class="card">
+        <ul class="nav nav-pills">
+            <li class="nav-item">
+                <a class="nav-link" href="{{url('inventory/blindReceive/excels')}}" :class="{active:isActive('excels',2)}">Excel下载</a>
+            </li>
+            <li class="nav-item">
+                <a class="nav-link" target="_blank" href="{{url('inventory/blindReceive')}}" :class="{active:isActive('',2)}">手持入口</a>
+            </li>
+        </ul>
+    </div>
+</div>

+ 1 - 1
resources/views/inventory/stockInventory/inventoryMission.blade.php

@@ -222,7 +222,7 @@
                     <td>@{{ inventoryMission.re_checked_amount }}</td>
                     <td>@{{ inventoryMission.difference_amount }}</td>
                     <td>@{{ inventoryMission.occupied_amount }}</td>
-                    <td v-if="!listMode">
+                    <td>
                         <span class="btn  btn-sm btn-outline-danger" @click="删除盘点记录(inventoryMission.id,inventory.id,inventoryMission.commodity.name)">删除</span>
                     </td>
                 </tr>

+ 5 - 0
routes/web.php

@@ -411,3 +411,8 @@ Route::group(['prefix'=>'order'],function(){
     Route::post('deAllocationAll','OrderController@deAllocationAll');
     Route::post('resetLogisticsGetMark','OrderController@resetLogisticsGetMark');
 });
+
+Route::get('inventory/blindReceive', function () { return view('inventory.blindReceive.index');});
+Route::get('inventory/blindReceive/excels', 'InventoryBlindReceiveExcelController@index');
+Route::post('inventory/blindReceive/excels/apiStore', 'InventoryBlindReceiveExcelController@apiStore');
+

+ 1 - 0
webpack.mix.js

@@ -23,3 +23,4 @@ mix.copy('resources/js/queryForm/queryForm.js','public/js/queryForm/queryForm200
 mix.copy('resources/js/queryForm/export.js','public/js/queryForm/export200818a.js');
 mix.js('resources/js/queryForm/header.js','public/js/queryForm/header200826b.js');
 
+mix.copy('resources/sound/','public/sound');

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini