Просмотр исходного кода

缓存架入库移动端页面

Zhouzhendong 4 лет назад
Родитель
Сommit
f128895d1f

+ 28 - 0
app/Http/Controllers/StorageController.php

@@ -15,16 +15,21 @@ use App\Storage;
 use App\StoreItem;
 use App\TaskTransaction;
 use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Foundation\Auth\AuthenticatesUsers;
 use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Gate;
+use Illuminate\Support\Facades\Validator;
 
 class StorageController extends Controller
 {
     use AsyncResponse;
+    use AuthenticatesUsers;
 
     public function putShelf()
     {
+        $this->gate("入库管理-入库-缓存架入库");
         $asn = \request("asn");
         $ide = \request("ide");
         $barCode = \request("barCode");
@@ -107,6 +112,7 @@ class StorageController extends Controller
      */
     public function resetCacheShelf()
     {
+        $this->gate("入库管理-入库-缓存架入库");
         $boxes = request("boxes");
         //清理任务
         $data = '';
@@ -131,6 +137,7 @@ class StorageController extends Controller
      */
     public function acquireBox()
     {
+        $this->gate("入库管理-入库-半箱补货入库");
         $boxId = request("material_box_id");
         $modelId = request("material_box_model_id");
         //获取目标库位
@@ -212,6 +219,7 @@ class StorageController extends Controller
      */
     public function overflowRevision()
     {
+        $this->gate("入库管理-入库-半箱补货入库");
         $station = request("station");
         $amount = request("amount");
         //获取目标库位
@@ -261,4 +269,24 @@ sql;
         DB::commit();
         $this->success();
     }
+
+    /**
+     * 在安卓端的个体登录鉴权
+     *
+     */
+    public function androidLogin()
+    {
+        $errors=Validator::make(request()->input(),[
+            "name"      => 'required|string',
+            'password'  => 'required|string'])->errors();
+        if($errors->count()>0){return ['success'=>false,'errors'=>$errors];}
+        request()->offsetSet("remember",true);
+        if (!$this->attemptLogin(request()))return ['success'=>false,'errors'=>['name'=>['登录信息验证失败']]];
+        if (!Gate::allows("入库管理-入库-缓存架入库") && !Gate::allows("入库管理-入库-半箱补货入库"))return ['success'=>false,'errors'=>['name'=>['用户无权操作入库']]];
+        return ['success'=>true,'url'=>url("store/inStorage/android.index")];
+    }
+    public function username(): string
+    {
+        return 'name';
+    }
 }

+ 20 - 12
app/Http/Controllers/TestController.php

@@ -144,21 +144,29 @@ class TestController extends Controller
     {
         return call_user_func([$this, $method], $request);
     }
-    public function test1(){
-        $aa = [1,2,3];
-
-        $this->test1(...$aa);
+    public function test1($nums,$target)
+    {
+        $map=[];
+        foreach ($nums as $index=>$val){
+            $complement=$target-$val;
+            if(array_key_exists($complement,$map))return [$map[$complement],$index];
+            if ($val==$target)return [$index];
+            $map[$val]=$index;
+            if ($val<$target){
+                $temp = $nums;
+                unset($temp[$index]);
+                $arr = $this->test1($temp,$target-$val);
+                if ($arr) {
+                    $arr[] = $index;
+                    return $arr;
+                }
+            }
+        }
+        return null;
     }
     public function test()
     {
-        app('StorageService')->clearTask(['HAIB2-02-02','HAIB2-01-01']);
-        dd();
-        ini_set('max_execution_time', 0);
-        $orders = Order::query()->whereBetween("wms_edittime",["2021-06-01 00:00:00","2021-06-30 23:59:59"])
-            ->whereNotIn("id",OwnerFeeDetail::query()->select("outer_id")
-                ->whereBetween("worked_at",["2021-06-01 00:00:00","2021-06-30 23:59:59"])
-                ->where("outer_table_name","orders"))->get();
-        foreach ($orders->chunk(50) as $or)dispatch(new OrderCreateInstantBill($or));
+        dd($this->test1([1,2,3,4,5,6,7],28));
     }
     public function orderCreateBill()
     {

+ 30 - 0
resources/views/store/inStorage/androidIndex.blade.php

@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="h-100">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <link rel="icon" href="{{asset('icon/faviconc.ico')}}" type="image/x-icon"/>
+    <!-- CSRF Token -->
+    <meta name="csrf-token" content="{{ csrf_token() }}">
+    <title>入库首页</title>
+    <link href="{{ mix('css/app.css') }}" rel="stylesheet">
+</head>
+<body class="h-100">
+<div class="container-fluid h-100 text-center">
+    <div class="container-fluid h-25">
+        <a class="navbar-brand" href="{{ url('/control/panel/menu') }}" title="宝时 Warehouse Assistance System" style="vertical-align: text-bottom">
+            <img src="{{asset('icon/logo100b.png')}}" alt="宝时 Warehouse Assistance System" height="30" >
+        </a>
+    </div>
+    <div class="text-center h-75">
+        <div class="w-100 center h-75 row align-items-center justify-content-center">
+            <div class="w-100">
+                <a href="{{url('store/inStorage/cacheRackStorage')}}"><button class="btn btn-info w-75 text-white" style="height: 60px"><h4>整箱入库</h4></button></a>
+                <a href="{{url('store/inStorage/halfChestStorage')}}"><button class="btn btn-info w-75 mt-3 text-white" style="height: 60px"><h4>半箱入库</h4></button></a>
+            </div>
+        </div>
+    </div>
+</div>
+<script src="{{ mix('js/app.js') }}"></script>
+</body>
+</html>

+ 69 - 18
resources/views/store/inStorage/cacheRackStorage.blade.php

@@ -2,43 +2,51 @@
 @section('title')缓存架入库-入库管理@endsection
 
 @section('content')
-    <div class="container-fluid" id="container">
+    <div class="container-fluid d-none" id="container">
         <div class="row">
             <div class="card offset-md-1 col-md-5 col-sm-12">
                 <div class="card-body">
-                    <div class="form-group text-center font-weight-bold h4">
+                    <div class="form-group text-center font-weight-bold h4 mt-2" id="header_title">
                         入库信息
                     </div>
                     <div class="form-group row">
                         <label for="asn" class="col-sm-2 col-3 text-right">ASN号:</label>
-                        <input type="text" class="form-control col-8" :class="errors.asn ? 'is-invalid' : ''" id="asn" v-model="info.asn" @blur="checkAsn()" placeholder="只需填写后几位,自动补充">
+                        <div tabindex="0" @keydown="enterVal($event,'asn')" class="form-control col-8 overflow-hidden" :contenteditable="!isOnlyKeyboardEnter" :class="errors.asn ? 'is-invalid' : ''"
+                             id="asn" @blur="checkAsn()">@{{ info.asn ? info.asn : '只需填写后几位,自动补充' }}</div>
                         <span class="invalid-feedback offset-2" role="alert" v-if="errors.asn">
                             <strong>@{{ errors.asn[0] }}</strong>
                         </span>
                     </div>
                     <div class="form-group row">
                         <label for="ide" class="col-sm-2 col-3 text-right">料箱号:</label>
-                        <input type="text" class="form-control col-8" :class="errors.ide ? 'is-invalid' : ''" id="ide" v-model="info.ide" @blur="checkIde()" placeholder="只需填写后几位,自动补充">
+                        <div tabindex="0" @keydown="enterVal($event,'ide')" class="form-control col-8 overflow-hidden" :contenteditable="!isOnlyKeyboardEnter" :class="errors.ide ? 'is-invalid' : ''"
+                             id="ide" @blur="checkIde()">@{{ info.ide ? info.ide : '只需填写后几位,自动补充' }}</div>
                         <span class="invalid-feedback offset-2" role="alert" v-if="errors.ide">
                             <strong>@{{ errors.ide[0] }}</strong>
                         </span>
                     </div>
-                    <div class="input-group row">
+                    <div class="form-group row">
                         <label for="barCode" class="col-sm-2 col-3 text-right">条码:</label>
-                        <input type="text" class="form-control rounded col-sm-5 col-8 ml-sm-1 ml-2" :class="errors.barCode ? 'is-invalid' : ''" id="barCode" @blur="codeBlur()" @keydown.enter="checkInfo()" v-model="info.barCode">
-                        <div class="input-group-append mt-sm-0 mt-4">
-                            <span class="input-group-text d-none d-sm-block">@数量</span>
-                            <label for="amount" class="d-sm-none col-4 text-right">数量:</label>
-                            <span class="input-group-text p-0 border-0">
-                                <input class="form-control" type="number" :class="errors.amount ? 'is-invalid' : ''" step="1" min="1" id="amount" v-model="info.amount">
-                            </span>
-                        </div>
+                        <div tabindex="0" @keydown="enterVal($event,'barCode')" class="form-control col-8 overflow-hidden" :contenteditable="!isOnlyKeyboardEnter" :class="errors.barCode ? 'is-invalid' : ''"
+                             id="barCode">@{{ info.barCode }}</div>
                         <span class="invalid-feedback offset-2" role="alert" v-if="errors.barCode">
                             <strong>@{{ errors.barCode[0] }}</strong>
                         </span>
                     </div>
+                    <div class="form-group row">
+                        <label for="amount" class="col-sm-2 col-3 text-right">数量:</label>
+                        <div tabindex="0" @keydown="enterVal($event,'amount')" class="form-control col-8 overflow-hidden"
+                             :class="errors.amount ? 'is-invalid' : ''" id="amount" type="number" :contenteditable="!isOnlyKeyboardEnter" >@{{ info.amount }}</div>
+                        <span class="invalid-feedback offset-2" role="alert" v-if="errors.amount">
+                            <strong>@{{ errors.amount[0] }}</strong>
+                        </span>
+                    </div>
                     <div class="input-group row mt-5">
-                        <button type="submit" class="btn btn-success offset-2 col-9" @click="checkInfo()">提交</button>
+                        <button type="submit" class="btn btn-success offset-2 col-6 col-sm-8" @click="checkInfo()">提交</button>
+                        <div class="custom-control custom-checkbox mt-2 d-sm-none">
+                            <input type="checkbox" class="custom-control-input" id="customCheck" v-model="isOnlyKeyboardEnter">
+                            <label class="custom-control-label" for="customCheck">键盘</label>
+                        </div>
                     </div>
                 </div>
             </div>
@@ -99,14 +107,31 @@
                 errors:{},
                 shelfOccupy:{},
                 selectedBox:{},
+                isAndroid:false,
+                isOnlyKeyboardEnter:true,
             },
             mounted(){
+                if (navigator.userAgent.indexOf("Android")!==-1)this.isAndroid = true;
                 @foreach($storages as $storage)this.$set(this.shelfOccupy,"{{$storage->station->code}}",true);@endforeach
-                this.codeFocus();
-                this.globalClick();
+                //this.codeFocus();
+                //this.globalClick();
                 this.createBefore();
+                this.pageInit();
+                $("#container").removeClass("d-none");
             },
             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;
+                    document.getElementById("header_title").className += " col-5";
+                    element.append(document.getElementById("header_title"));
+                    document.getElementById("menu").remove();
+                    document.getElementById("demand-div").remove();
+                },
                 //选中填充料箱
                 fillingBox(ideCode){
                     this.$set(this.selectedBox,ideCode,this.selectedBox[ideCode] ? !this.selectedBox[ideCode] : true);
@@ -144,11 +169,11 @@
                 },
                 codeBlur(){
                     if (this.info.asn && this.info.ide && !this.info.amount){
-                        this.globalClick(false);
+                        //this.globalClick(false);
                         window.tempTip.inputVal('请输入数量:',(amount)=>{
                             this.$set(this.info,'amount',amount);
                             if (this.info.asn && this.info.ide && this.info.barCode && this.info.amount)this.checkInfo();
-                            this.globalClick();
+                            //this.globalClick();
                         });
                     }
                 },
@@ -206,6 +231,32 @@
                     ides.forEach((ideCode)=>{
                         this.$set(this.selectedBox,ideCode,this.selectedBox[ideCode] ? !this.selectedBox[ideCode] : true);
                     });
+                },
+                enterVal(e,type){
+                    /*if (e.keyCode === 8 && this.info[type] && this.isOnlyKeyboardEnter){this.$set(this.info,type,this.info[type].slice(0,-1));return;}
+                    if (type === 'amount'){
+                        if((e.keyCode>=48 && e.keyCode<=57) || (e.keyCode>=96 && e.keyCode<=105)){
+                            if (!this.isOnlyKeyboardEnter)return;
+                            if (this.info[type])this.$set(this.info,type,this.info[type] += e.key);
+                            else this.$set(this.info,type,e.key);
+                        }else e.preventDefault();
+                        return;
+                    }
+                    if (!this.isOnlyKeyboardEnter)return;
+                    if ((e.keyCode<48 || e.keyCode>105) || (e.keyCode>57 && e.keyCode<65) || (e.keyCode>90 && e.keyCode<96))return;
+                    if (this.info[type])this.$set(this.info,type,this.info[type] += e.key);
+                    else this.$set(this.info,type,e.key);*/
+                    if (e.keyCode === 229){e.preventDefault();return;}
+                    if (e.keyCode === 8 && this.info[type]){this.$set(this.info,type,this.info[type].slice(0,-1));return;}
+                    if (e.key.length>1)return;
+                    if (e.key.match(/[a-zA-Z0-9\-]/g)===null)return;
+                    if (type === 'amount'){
+                        if (e.key.match(/[0-9]/g)===null)return;
+                        if (this.info.maximum && Number((this.info[type] ? this.info[type] : '0')+e.key)>this.info.maximum) return;
+                    }
+                    if (this.info[type])this.$set(this.info,type,this.info[type] += e.key);
+                    else this.$set(this.info,type,e.key);
+                    this.downSign();
                 }
             },
         });

+ 47 - 10
resources/views/store/inStorage/halfChestStorage.blade.php

@@ -6,42 +6,52 @@
         <div class="row">
             <div class="card offset-md-3 col-md-6 col-sm-12">
                 <div class="card-body">
-                    <div class="form-group text-center">
+                    <div class="form-group text-center mt-2" id="header_title">
                         <span class="font-weight-bold h4">入库信息</span>
                         <a class="small" href="#" @click="openModal()">溢出减量</a>
                     </div>
                     <div class="form-group row">
                         <label for="asn" class="col-sm-2 col-3 text-right">ASN号:</label>
-                        <input type="text" class="form-control col-8" @change="downSign()" :class="errors.asn ? 'is-invalid' : ''" id="asn" v-model="info.asn" @blur="checkAsn()" placeholder="只需填写后几位,自动补充">
+                        <div tabindex="0" @keydown="enterVal($event,'asn')" class="form-control col-8 overflow-hidden"
+                             :contenteditable="!isOnlyKeyboardEnter" :class="errors.asn ? 'is-invalid' : ''"
+                             id="asn" @blur="checkAsn()">@{{ info.asn ? info.asn : '只需填写后几位,自动补充' }}</div>
                         <span class="invalid-feedback offset-2" role="alert" v-if="errors.asn">
                             <strong>@{{ errors.asn[0] }}</strong>
                         </span>
                     </div>
                     <div class="form-group row">
                         <label for="station" class="col-sm-2 col-3 text-right">库位:</label>
-                        <input type="text" class="form-control col-8" :class="errors.station ? 'is-invalid' : ''" id="station" v-model="info.station" @blur="checkMaximum()"
-                               placeholder="扫描货架条码">
+                        <div tabindex="0" @keydown="enterVal($event,'station')" class="form-control col-8 overflow-hidden"
+                             :contenteditable="!isOnlyKeyboardEnter" :class="errors.station ? 'is-invalid' : ''"
+                             id="station" @blur="checkMaximum()">@{{ info.station ? info.station : '扫描货架条码' }}</div>
                         <span class="invalid-feedback offset-2" role="alert" v-if="errors.station">
                             <strong>@{{ errors.station[0] }}</strong>
                         </span>
                     </div>
                     <div class="form-group row">
                         <label for="barCode" class="col-sm-2 col-3 text-right">条码:</label>
-                        <input type="text" class="form-control col-8" @change="downSign()" :class="errors.barCode ? 'is-invalid' : ''" id="barCode" v-model="info.barCode" @blur="checkMaximum()" placeholder="扫描商品条码">
+                        <div tabindex="0" @keydown="enterVal($event,'barCode')" class="form-control col-8 overflow-hidden"
+                             :contenteditable="!isOnlyKeyboardEnter" :class="errors.barCode ? 'is-invalid' : ''"
+                             id="barCode" @blur="checkMaximum()">@{{ info.barCode ? info.barCode : '扫描商品条码' }}</div>
                         <span class="invalid-feedback offset-2" role="alert" v-if="errors.barCode">
                             <strong>@{{ errors.barCode[0] }}</strong>
                         </span>
                     </div>
                     <div class="form-group row">
                         <label for="amount" class="col-sm-2 col-3 text-right">数量:</label>
-                        <input type="number" class="form-control col-8" :class="errors.amount ? 'is-invalid' : ''" id="amount" @blur="checkMaximum()" v-model="info.amount"
-                               :placeholder="info.maximum!==undefined ? '最大可上:'+info.maximum : ''" :max="info.maximum" step="1">
+                        <div tabindex="0" @keydown="enterVal($event,'amount')" class="form-control col-8 overflow-hidden"
+                             :contenteditable="!isOnlyKeyboardEnter" :class="errors.amount ? 'is-invalid' : ''"
+                             id="amount" @blur="checkMaximum()">@{{ info.amount ? info.amount : (info.maximum!==undefined ? '最大可上:'+info.maximum : '') }}</div>
                         <span class="invalid-feedback offset-2" role="alert" v-if="errors.amount">
                             <strong>@{{ errors.amount[0] }}</strong>
                         </span>
                     </div>
                     <div class="input-group row mt-5">
-                        <button type="submit" class="btn btn-success offset-2 col-9" @click="checkInfo()">提交</button>
+                        <button type="submit" class="btn btn-success offset-2 col-6 col-sm-8" @click="checkInfo()">提交</button>
+                        <div class="custom-control custom-checkbox mt-2 d-sm-none">
+                            <input type="checkbox" class="custom-control-input" id="customCheck" v-model="isOnlyKeyboardEnter">
+                            <label class="custom-control-label" for="customCheck">键盘</label>
+                        </div>
                     </div>
                 </div>
             </div>
@@ -88,13 +98,27 @@
                 errors:{},
                 ov:{},//溢出减量数值
                 checkSign:false,
+                isAndroid:true,
+                isOnlyKeyboardEnter:true,
             },
             mounted(){
-                this.codeFocus();
-                this.globalClick();
+                //this.codeFocus();
+                //this.globalClick();
                 this.createBefore();
+                this.pageInit();
+                $("#container").removeClass("d-none");
             },
             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;
+                    document.getElementById("menu").remove();
+                    document.getElementById("demand-div").remove();
+                },
                 //提交溢出减量
                 overflowRevision(){
                     if (!this.ov.station || !this.ov.amount){
@@ -175,6 +199,19 @@
                         return "该库位最大可上数为"+res.maximum;
                     });
                 },
+                enterVal(e,type){
+                    if (e.keyCode === 229){e.preventDefault();return;}
+                    if (e.keyCode === 8 && this.info[type]){this.$set(this.info,type,this.info[type].slice(0,-1));return;}
+                    if (e.key.length>1)return;
+                    if (e.key.match(/[a-zA-Z0-9\-]/g)===null)return;
+                    if (type === 'amount'){
+                        if (e.key.match(/[0-9]/g)===null)return;
+                        if (this.info.maximum && Number((this.info[type] ? this.info[type] : '0')+e.key)>this.info.maximum) return;
+                    }
+                    if (this.info[type])this.$set(this.info,type,this.info[type] += e.key);
+                    else this.$set(this.info,type,e.key);
+                    this.downSign();
+                }
             },
         });
     </script>

+ 91 - 0
resources/views/store/inStorage/login.blade.php

@@ -0,0 +1,91 @@
+@extends('layouts.app')
+
+@section('content')
+    <div class="container-fluid" id="list">
+        <div class="row justify-content-center">
+            <div class="col-md-12">
+                <div class="card">
+                    <div class="card-header">登录</div>
+                    <div class="card-body">
+                        <div class="row">
+                            <div class="col-md-6 text-md-right">
+                                <img src="{{asset('images/login/bg1.jpg')}}" alt="" class="img-fluid">
+                            </div>
+                            <div class="col-md-6"><form method="POST" action="{{ route('login') .'?rand='.microtime(true)}}">
+                                    @csrf
+                                    <label for="name" class="col-form-label text-md-right">用户名</label>
+                                    <div class="form-group row">
+                                        <div class="col-md-8">
+                                            <input id="name" type="text" class="form-control" :class="[errors.name?'is-invalid':'']"
+                                                   oninput="setTimeout(function(){vue.errors.name=''},10)"
+                                                   name="name" v-model="inputting.name" required autocomplete="name" autofocus>
+                                            <span class="invalid-feedback" v-if="errors.name">
+                                                <strong v-for="msg in errors.name">@{{ msg }}</strong>
+                                            </span>
+                                        </div>
+                                    </div>
+                                    <label for="password" class="col-form-label text-md-right">密码</label>
+                                    <div class="form-group row">
+                                        <div class="col-md-8">
+                                            <input id="password" type="password" class="form-control " :class="[errors.password?'is-invalid':'']"
+                                                   @keypress="passwordInput($event)"
+                                                   v-model="inputting.password" name="password" required autocomplete="current-password">
+
+                                            <span class="invalid-feedback" v-if="errors.password">
+                                                <strong v-for="msg in errors.password">@{{ msg }}</strong>
+                                            </span>
+                                        </div>
+                                    </div>
+                                    <div class="form-group row mb-0">
+                                        <div class="col-md-8">
+                                            <button type="button" class="btn btn-primary form-control" onclick="loginSubmit()">
+                                                登录
+                                            </button>
+                                        </div>
+                                    </div>
+                                </form>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+@endsection
+
+@section('lastScript')
+    <script>
+        let vue=new Vue({
+                el:"#list",
+                mounted:function(){
+                    $('.invalid-feedback').addClass('d-block');
+                },
+                data:{
+                    inputting:{name:'',password:''},
+                    errors: {name:'',password:''},
+                },
+                methods:{
+                    passwordInput:function(e){
+                        setTimeout(function(){vue.errors.password=''},10);
+                        if(e.key==='Enter')loginSubmit()
+                    },
+                }
+            }
+        )
+        function loginSubmit() {
+            tempTip.setDuration(99999);
+            tempTip.waitingTip('提交中');
+            axios.post('{{url('store/inStorage/android.login')}}',vue.inputting).then(function (response) {
+                tempTip.setDuration(2000);
+                tempTip.cancelWaitingTip();
+                if(response.data.success!==true){
+                    if(response.data.errors){vue.errors=response.data.errors;return;}
+                    if(response.data.message){tempTip.show(response.data.message);return;}
+                }else window.location.href = response.data.url;
+            }).catch(function(r){
+                tempTip.setDuration(4000);
+                tempTip.waitingTip('网络错误:'+r);
+            })
+        }
+    </script>
+@endsection

+ 2 - 0
routes/web.php

@@ -453,6 +453,8 @@ Route::group(['prefix'=>'store'],function(){
         Route::post('overflowRevision','StorageController@overflowRevision');
         Route::post('acquireBox','StorageController@acquireBox');
         Route::post('syncStorage','StorageController@syncStorage');
+        Route::get('android.index',function (){if (!Auth::user())return view("store.inStorage.login");return view('store.inStorage.androidIndex');});
+        Route::post('android.login','StorageController@androidLogin');
     });
     Route::group(['prefix'=>'fast'],function() {
         Route::resource('storeItem','StoreItemController');