Przeglądaj źródła

Merge branch 'zzd'

zhouzhendong 4 lat temu
rodzic
commit
65134bd5f0

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

@@ -183,7 +183,6 @@ sql;
         $result = app("ForeignHaiRoboticsService")->paddingCacheShelf(Station::query()->whereIn("code",$boxes)->get());
         if ($result===null)$this->error("任务下发错误,检查日志");
         if ($result===false)$this->error("已无可用料箱,部分库位填充失败");
-        app("StationService")->locationOccupyMulti($boxes);
         $this->success(["data"=>$data,"boxes"=>$boxes]);
     }
 

+ 34 - 26
app/Jobs/CacheShelfTaskJob.php

@@ -46,11 +46,15 @@ class CacheShelfTaskJob implements ShouldQueue
         switch ($this->key){
             case "CACHE_SHELF_AVAILABLE"://缓存架释放呼叫
                 //等待一定时间来合并同类请求至此
-                $available = Cache::get($this->key,function (){return [];});
-                if ($this->count!==count($available))return;
+                $available = Cache::get($this->key,0);
+                if ($this->count!==$available)return;
+                Cache::forget($this->key); //无论是否开始分发 都清除本次缓存架的计数器
+                //获取可用缓存架
+                $stations = app("StationService")->getCacheShelf(true);
+                if ($stations->count()==0)break;
                 //检查事务 尝试分发任务 改变下方序列来控制分发顺序 逐级分发 一次成功就终止
-                if ($this->dispatchOutTask($available,$service))break; //首先尝试向出库事务分发 分发成功跳出
-                if ($this->dispatchInTask($available,$service))break;  //尝试向入库事务分发
+                if ($this->dispatchOutTask($stations,$service))break; //首先尝试向出库事务分发 分发成功跳出
+                if ($this->dispatchInTask($stations,$service))break;  //尝试向入库事务分发
                 break;
             default://入库呼叫
                 if (!Cache::has($this->key))return;
@@ -61,10 +65,10 @@ class CacheShelfTaskJob implements ShouldQueue
                 $controlSuccess = $service->controlHaiRobot($dataToPost,$task,'缓存架入立架');
                 $tIds = [];
                 $task->each(function ($t)use(&$tIds){$tIds[] = $t->id;});
-                StationTaskMaterialBox::query()->where("id",$tIds)
+                StationTaskMaterialBox::query()->whereIn("id",$tIds)
                     ->where("status","待处理")->update(['status' => $controlSuccess ? '处理中' : '异常']);
                 Cache::forget($this->key);
-                if ($controlSuccess)$this->materialBoxMappingCacheShelf($task,$location);
+                //if ($controlSuccess)$this->materialBoxMappingCacheShelf($task,$location);
         }
     }
 
@@ -88,11 +92,11 @@ class CacheShelfTaskJob implements ShouldQueue
     /**
      * 分发出库任务
      *
-     * @param array $available
+     * @param $stations
      * @param $service
      * @return bool
      */
-    private function dispatchOutTask(array $available, $service):bool
+    private function dispatchOutTask(&$stations,$service):bool
     {
         DB::beginTransaction();
         try {
@@ -101,14 +105,14 @@ class CacheShelfTaskJob implements ShouldQueue
                     $query->where("status","待处理");
                 })->where("status",3)->lockForUpdate()
                 ->where("mark",2)->groupBy("task_id")->get(); //检索等待的队列事务来获取对应任务
-            if ($this->dispatchTask($tasks,$available,$service,function ($obj,$stationId,$time,&$updateTransaction){
+            if ($this->dispatchTask($tasks,$stations,$service,function ($obj,$stationId,$time,&$updateTransaction){
                 if ($obj->ids!=$obj->id){
                     $ids = explode(",",$obj->ids);
                     foreach ($ids as $id)$updateTransaction[] = ["id"=>$id,"to_station_id"=>$stationId,"status"=>0,"updated_at"=>$time];
                 }else $updateTransaction[] = ["id"=>$obj->id,"to_station_id"=>$stationId,"status"=>0,"updated_at"=>$time];
             },function ($service,$toLocation,$task,$prefix){
                 return $service->fetchGroup_multiLocation($toLocation,$task,$prefix,'立架出至缓存架',20);
-            },"to_station_id")){DB::commit();return true;}
+            },"to_station_id")){DB::commit();return $stations->count()==0;} //缓存架用完 跳出,否则接着分发
             DB::rollBack();
         }catch (\Exception $e){
             DB::rollBack();
@@ -120,11 +124,11 @@ class CacheShelfTaskJob implements ShouldQueue
     /**
      * 分发入库任务
      *
-     * @param array $available
+     * @param $stations
      * @param $service
      * @return bool
      */
-    private function dispatchInTask(array $available, $service):bool
+    private function dispatchInTask(&$stations,$service):bool
     {
         DB::beginTransaction();
         try {
@@ -133,11 +137,14 @@ class CacheShelfTaskJob implements ShouldQueue
                     $query->where("status","待处理");
                 })->where("status",3)->lockForUpdate()
                 ->where("mark",1)->get(); //检索等待的队列事务来获取对应任务
-            if ($this->dispatchTask($tasks,$available,$service,function ($obj,$stationId,$time,&$updateTransaction){
+            if (!$tasks->count())return false;
+            if ($this->dispatchTask($tasks,$stations,$service,function ($obj,$stationId,$time,&$updateTransaction){
                 $updateTransaction[] = ["id"=>$obj->id,"fm_station_id"=>$stationId,"status"=>0,"updated_at"=>$time];
             },function ($service,$toLocation,$task,$prefix){
                 return $service->fetchGroup_multiLocation($toLocation,$task,'','立架出至缓存架');
-            },"fm_station_id")){DB::commit();return true;}
+            },"fm_station_id")){
+                DB::commit();return $stations->count()==0; //缓存架用完 跳出,否则接着分发
+            }
             DB::rollBack();
         }catch (\Exception $e){
             DB::rollBack();
@@ -146,31 +153,32 @@ class CacheShelfTaskJob implements ShouldQueue
         return false;
     }
 
-    private function dispatchTask(\Illuminate\Database\Eloquent\Collection $tasks, array $available, $service,
+    private function dispatchTask(\Illuminate\Database\Eloquent\Collection $tasks,&$stations, $service,
                                   \Closure $update, \Closure $execute, string $stationName):bool
     {
-        if (!$tasks->count())return false;
-        if ($tasks->count()>count($available))$tasks = $tasks->slice(0,count($available));//事务过多切割部分处理
+        $locations = $stations;
+        if ($tasks->count()>$locations->count())$tasks = $tasks->slice(0,$locations->count());//事务过多切割部分处理
+        if ($tasks->count()<$locations->count()){
+            $stations = $stations->slice($tasks->count());
+            $stations = $stations->values($stations);
+        }
         $toLocation = collect();
         $task = collect();
-        $availableTemp = array_keys($available);
-        $map = app("StationService")->getStationMapping($availableTemp);//获取库位映射信息
         $updateTask = [["id","station_id","updated_at"]];
         $updateTransaction = [["id",$stationName,"status","updated_at"]];
         $time = date("Y-m-d H:i:s");
+        $map = [];
         foreach ($tasks as $index=>$obj){
-            $loc = $availableTemp[$index];
-            $toLocation->push($loc);
-            $obj->task->station_id = $map[$loc];
+            $toLocation->push($stations[$index]->code);
+            $map[$stations[$index]->code] = $stations[$index]->id;
+            $obj->task->station_id = $stations[$index]->id;
             $task->push($obj->task);
-            unset($available[$loc]);
-            $updateTask[] = ["id"=>$obj->task->id,"station_id"=>$map[$loc],"updated_at"=>$time];
-            $update($obj,$map[$loc],$time,$updateTransaction);
+            $updateTask[] = ["id"=>$obj->task->id,"station_id"=>$stations[$index]->id,"updated_at"=>$time];
+            $update($obj,$stations[$index]->id,$time,$updateTransaction);
         }
         app("BatchUpdateService")->batchUpdate("station_task_material_boxes",$updateTask);
         app("BatchUpdateService")->batchUpdate("task_transactions",$updateTransaction);
         if ($execute($service,$toLocation,$task,$tasks[0]->station_task_batch_id)){
-            Cache::forever($this->key,$available);
             foreach ($toLocation as $value){
                 app("CacheShelfService")->lightUp($value,'3','0',["title"=>"机器人取箱中,禁止操作"]);
                 Cache::forever("CACHE_SHELF_OCCUPANCY_{$map[$value]}",true);

+ 14 - 0
app/Services/CacheShelfService.php

@@ -4,6 +4,7 @@ namespace App\Services;
 
 use App\Events\BroadcastToStation;
 use App\Exceptions\ErrorException;
+use App\Jobs\CacheShelfTaskJob;
 use App\Station;
 use App\StationTaskMaterialBox;
 use App\Traits\ServiceAppAop;
@@ -202,4 +203,17 @@ class   CacheShelfService
 
         return ['success' => true];
     }
+
+    /**
+     * 料箱被取走
+     *
+     * @param Station|\stdClass $station
+     */
+    public function boxHasBeenTaken($station)
+    {
+        app("StationService")->locationFreed($station); //释放库位,解除绑定料箱
+        $available=Cache::get("CACHE_SHELF_AVAILABLE",0)+1;//获取可用缓存架数量 plus当前
+        Cache::forever("CACHE_SHELF_AVAILABLE",$available);
+        CacheShelfTaskJob::dispatch("CACHE_SHELF_AVAILABLE",$available)->delay(now()->addSeconds(config("haiRou.cacheShelf.outBinAwait")));
+    }
 }

+ 9 - 4
app/Services/ForeignHaiRoboticsService.php

@@ -351,10 +351,6 @@ class ForeignHaiRoboticsService
         $binCode
     ):bool{
         $this->instant($this->stationTaskMaterialBoxService,'StationTaskMaterialBoxService');
-        if ($status==1){ //海柔失败
-            $this->push(__METHOD__."->".__LINE__,"海柔任务异常",json_encode(request()->input()));
-            return false;
-        }
         //获取下达任务
         /** @var StationTaskMaterialBox|\stdClass $stationTaskMaterialBox */
         $stationTaskMaterialBox = $stationTaskMaterialBox_id ? StationTaskMaterialBox::query()->with("materialBox:id,code")
@@ -363,6 +359,11 @@ class ForeignHaiRoboticsService
             $this->push(__METHOD__."->".__LINE__,"海柔任务不存在",json_encode(request()->input()));
             return false;
         }
+        if ($status==1){ //海柔失败
+            $this->push(__METHOD__."->".__LINE__,"海柔任务异常",json_encode(request()->input()));
+            $stationTaskMaterialBox->update(['status'=>"异常"]);
+            return false;
+        }
         if ($stationTaskMaterialBox->materialBox->code != $binCode){
             $this->push(__METHOD__."->".__LINE__,"海柔任务料箱号不匹配",json_encode(request()->input()));
             return false;
@@ -496,6 +497,10 @@ class ForeignHaiRoboticsService
         }
         if ($stationCollection->count()>0){
             if (!$this->fetchGroup_multiLocation($stationCollection,$collection,'','立架出至缓存架')) return null;
+            app("StationService")->locationOccupyMulti($stationCollection->toArray());
+            $stationCollection->each(function ($code){
+                app("CacheShelfService")->lightUp($code,'3','0',["title"=>"机器人取箱中,禁止操作"]);
+            });
         }
         return $stations->count()==$stationCollection->count();
     }

+ 1 - 2
app/Services/StationService.php

@@ -199,8 +199,7 @@ class StationService
     public function locationFreed(?string $location, ?int $boxId=null):int
     {
         if (!$location)return 0;
-        $update = ["status"=>0];
-        if ($boxId)$update["material_box_id"]=$boxId;
+        $update = ["status"=>0,"material_box_id"=>$boxId];
         return Station::query()->where("code",$location)->update($update);
     }
 

+ 2 - 2
app/Services/StationTaskBatchService.php

@@ -136,7 +136,7 @@ class StationTaskBatchService
      * @return Collection|\Tightenco\Collect\Support\Collection|null 返回执行失败的记录
      * @throws ErrorException
      */
-    function runMany(?Collection $stationTaskBatches, $locationType = 'OUTBIN-U-SHAPE-LINE'):?Collection
+    function runMany(?Collection $stationTaskBatches,string $locationType = 'OUTBIN-U-SHAPE-LINE'):?Collection
     {
         LogService::log(__METHOD__,'runMany','波次任务分配6.1:'.json_encode($stationTaskBatches));
         $stationTaskBatches_failed = null;
@@ -171,7 +171,7 @@ class StationTaskBatchService
      * @return bool
      * @throws ErrorException
      */
-    function run(StationTaskBatch $stationTaskBatch, $locationType): bool
+    function run(StationTaskBatch $stationTaskBatch,string $locationType): bool
     {
         $this->instant($this->foreignHaiRoboticsService,'ForeignHaiRoboticsService');
         $this->instant($this->stationService,'StationService');

+ 13 - 4
app/Services/StationTaskMaterialBoxService.php

@@ -5,10 +5,12 @@ namespace App\Services;
 
 
 use App\Batch;
+use App\Components\ErrorPush;
 use App\Exceptions\ErrorException;
 use App\Jobs\CacheShelfTaskJob;
 use App\MaterialBox;
 use App\OrderCommodity;
+use App\Station;
 use App\StationTask;
 use App\StationTaskMaterialBox;
 use Carbon\Carbon;
@@ -20,7 +22,7 @@ use Illuminate\Support\Facades\DB;
 
 class StationTaskMaterialBoxService
 {
-    use ServiceAppAop;
+    use ServiceAppAop,ErrorPush;
     protected $modelClass=StationTaskMaterialBox::class;
     /** @var StationService $stationService */
     private $stationService;
@@ -209,9 +211,16 @@ class StationTaskMaterialBoxService
      */
     function markHasTaken($stationTaskMaterialBox)
     {
-        $stationTaskMaterialBox->loadMissing("station");
         $this->instant($this->cacheShelfService,'CacheShelfService');
-        //维护缓存架可用度
+        //$stationTaskMaterialBox->loadMissing("station");
+        $this->push("1","取出料箱通知","任务信息:".$stationTaskMaterialBox->toJson());
+
+        //判断取出料箱是否是在缓存架
+        $station = Station::query()->where("material_box_id",$stationTaskMaterialBox->material_box_id)
+            ->first();
+        if ($station && app("StationService")->isHalfBoxLocation($station))
+            app("CacheShelfService")->boxHasBeenTaken($station);
+        /*//维护缓存架可用度
         $map = Cache::get("CACHE_SHELF_MAPPING",function (){return [];});
         if (isset($map[$stationTaskMaterialBox->material_box_id])){
             $available=Cache::get("CACHE_SHELF_AVAILABLE",function (){return [];});
@@ -220,7 +229,7 @@ class StationTaskMaterialBoxService
             CacheShelfTaskJob::dispatch("CACHE_SHELF_AVAILABLE",count($available))->delay(now()->addSeconds(config("haiRou.cacheShelf.outBinAwait")));
             unset($map[$stationTaskMaterialBox->material_box_id]);
             Cache::forever("CACHE_SHELF_MAPPING",$map);
-        }
+        }*/
     }
 
     function processNextQueued(?StationTaskMaterialBox $stationTaskMaterialBox_lastProcessed){

+ 6 - 4
app/Services/StorageService.php

@@ -36,10 +36,8 @@ class StorageService
         DB::beginTransaction();
         try{
             $stationTaskMaterialBox->loadMissing("station");
-            //如果为半箱位置 清理原有任务
             if (!$stationTaskMaterialBox->station)return;
             if (app("StationService")->isHalfBoxLocation($stationTaskMaterialBox->station)){
-                app("StationService")->locationOccupy($stationTaskMaterialBox->station->code,$stationTaskMaterialBox->material_box_id);
                 //清除海柔库位信息
                 $this->clearTask([$stationTaskMaterialBox->station->code]);
                 $stationId = $stationTaskMaterialBox->station_id;
@@ -95,9 +93,13 @@ class StorageService
                             }
                             break;
                     }
-                    app("CacheShelfService")->lightUp($stationTaskMaterialBox->station->code,'2','0',$options);
                     Cache::forget("CACHE_SHELF_OCCUPANCY_{$stationTaskMaterialBox->station->id}");//关闭无限亮灯
-                }else app("StationService")->locationFreed($stationTaskMaterialBox->station->code); //释放库位占用
+                    app("StationService")->locationOccupy($stationTaskMaterialBox->station->code,$stationTaskMaterialBox->material_box_id);//料箱绑定缓存架
+                    app("CacheShelfService")->lightUp($stationTaskMaterialBox->station->code,'2','0',$options);
+                }else{
+                    app("StationService")->locationFreed($stationTaskMaterialBox->station->code); //释放库位占用
+                    app("CacheShelfService")->_stationCacheLightOff($stationTaskMaterialBox->station->code);//灭灯
+                }
             }
             DB::commit();
         }catch (\Exception $e){

+ 1 - 6
app/Station.php

@@ -23,8 +23,8 @@ class Station extends Model
      * CACHE_SHELF_OCCUPANCY_{ID}   //bool:缓存架占用标记,开启此标记后连续排灯无效
      * CACHE_SHELF_MAPPING          //array(map):缓存架映射标记,用来映射入库任务的真实库位 CacheShelfTaskJob:materialBoxMappingCacheShelf详细描述此流程
      * CACHE_SHELF_AVAILABLE        //array(map):缓存架可用标记,映射缓存架是否可以被下达出库任务
+     * CACHE_SHELF_AVAILABLE        //array(map):缓存架可用计数器,来标识这个已取出箱子的缓存架数量,这个标识用来判定缓存架一定时间内是否仍然被操作,如果缓存架停止操作则开启处理
      * */
-
     public function task()
     {
         return $this->hasOne(StationTaskMaterialBox::class,"station_id","id");
@@ -67,9 +67,4 @@ class Station extends Model
             ->where('status','=','待处理');
     }
 
-    public function storage(): HasOne
-    {
-        return $this->hasOne(Storage::class);
-    }
-
 }

+ 23 - 1
resources/sass/animation.css

@@ -27,4 +27,26 @@
 {
     from {top:0;}
     to {top:-50px;}
-}
+}
+
+.translationRtoL{
+    animation:moveRtoL 500ms 1;
+    -moz-animation:moveRtoL 500ms 1; /* Firefox */
+    -webkit-animation:moveRtoL 500ms 1; /* Safari and Chrome */
+    -o-animation:moveRtoL 500ms 1;/* Opera */
+}
+@keyframes moveRtoL { from {left:0;} to {left:-50px;} }
+@-moz-keyframes moveRtoL { from {left:0;} to {left:-50px;} }
+@-webkit-keyframes moveRtoL { from {left:0;} to {left:-50px;} }
+@-o-keyframes moveRtoL { from {left:0;} to {left:-50px;} }
+
+.translationLtoR{
+    animation:moveLtoR 500ms 1;
+    -moz-animation:moveLtoR 500ms 1; /* Firefox */
+    -webkit-animation:moveLtoR 500ms 1; /* Safari and Chrome */
+    -o-animation:moveLtoR 500ms 1;/* Opera */
+}
+@keyframes moveLtoR { from {right:0;} to {right:-50px;} }
+@-moz-keyframes moveLtoR { from {right:0;} to {right:-50px;} }
+@-webkit-keyframes moveLtoR { from {right:0;} to {right:-50px;} }
+@-o-keyframes moveLtoR { from {right:0;} to {right:-50px;} }

+ 116 - 83
resources/views/transport/waybill/delivering.blade.php

@@ -1,101 +1,102 @@
 @extends('layouts.app')
 @section('title')发运-运输管理@endsection
-
+@section("head")<link href="{{ mix('css/animation.css') }}" rel="stylesheet">@endsection
 @section('content')
     <div id="list" class="d-none container-fluid mt-2">
         <div class="card" v-for="(waybills,date) in groups">
-            <div class="card-header p-0 text-center" @click="selectedHeader(date)">
-                @{{ date }}
-                <i class="fa mr-2 pull-right" :class="header[date] ? 'fa-angle-down' : 'fa-angle-right'"></i>
+            <div class="card-header p-0 row" >
+                <div class="text-center" :class="slideStatus[date] ? 'col-8' : 'col-12'" @click="selectedHeader(date)" @touchstart="startSlide()" @touchend="endSlide(date)">
+                    @{{ date }}<i class="fa mr-2 pull-right" :class="header[date] ? 'fa-angle-down' : 'fa-angle-right'"></i>
+                </div>
+                <div class="col-4 bg-white" :class="slideStatus[date] ? '' : 'd-none'">
+                    专线费预留区域
+                </div>
             </div>
             <div class="card-body p-0" v-if="header[date]">
                 <div class="w-100 h-100 d-inline-block text-center" v-if="loadAnimation[date]">
                     <i class="fa fa-spinner fa-pulse"></i>
                 </div>
-                <div v-else>
-                    <table class="table table-striped table-sm table-bordered table-hover p-0 d-block d-sm-none" style="background: rgb(255, 255, 255);">
-                        <tbody>
-                        <tr v-for="waybill in waybills">
-                            <td style="filter:grayscale(30%); " :id="'waybill-'+waybill.id">
-                                <div :style="waybill.status!='已完结'?'background-color:#f6eee8':''" class="mt-3">
-                                    <div style="transform:scale(0.9)" class="pl-0">
-                                        <span class="mr-3 text-nowrap"><span style="color:#783000">日期:</span><span style="color:#af7651">@{{ waybill.deliver_at }}</span></span>
-                                        <span class="mr-3 text-nowrap"><span style="color:#783000">承运商:</span><span style="color:#af7651">@{{ waybill.carrier_name }}</span></span>
-                                        <span class="mr-3 text-nowrap"><span style="color:#783000">宝时运单号:</span><span style="color:#af7651">@{{ waybill.waybill_number }}</span><br></span>
-                                        <span class="mr-3 text-nowrap"><span style="color:#783000">目的地:</span><span style="color:#af7651">@{{ waybill.address }}</span><br></span>
-                                        <span class="mr-3 text-nowrap"><span style="color:#783000">收货人:</span><span style="color:#af7651">@{{ waybill.recipient }}</span></span>
-                                        <span class="mr-3 text-nowrap"><span style="color:#783000">提货仓:</span><span style="color:#af7651">@{{ waybill.origination }}</span></span>
-                                        <span class="mr-3 text-nowrap"><span style="color:#783000">预估重量:</span><span style="color:#af7651" v-if="waybill.warehouse_weight_other">@{{ waybill.warehouse_weight_other }} @{{ waybill.warehouse_weight_unit_other_name }}</span></span>
-                                        <span class="mr-3 text-nowrap"><span style="color:#783000">预估体积:</span><span style="color:#af7651" v-if="waybill.warehouse_weight">@{{ waybill.warehouse_weight }} @{{ waybill.warehouse_weight_unit_name }}</span></span>
-                                    </div>
-                                </div>
-                                <div style="background-color:#e8eef6"  class="mb-3">
-                                    <div style="transform:scale(0.9)" class="pl-0 form-inline">
-                                <span class="mr-3 text-nowrap form-inline"><span style="color:#02346a">专线运单号:</span>
-                                    <input :id="'carrier_bill'+waybill.id" :class="errors['_'+waybill.id]&&errors['_'+waybill.id].carrier_bill?'is-invalid tooltipTargetError':''"
-                                           :title="errors['_'+waybill.id]&&errors['_'+waybill.id].carrier_bill?errors['_'+waybill.id].carrier_bill[0]:''" v-if="waybill.isBtn || updatePool[waybill.id]" type="text" :value="waybill.carrier_bill"
-                                           class="form-control form-control-sm " @click="enlarge($event)"  style="width: 50px">
-                                    <span v-else  class="text-muted">@{{ waybill.carrier_bill }}</span>
-                                </span>
-                                        <span class="mr-3 text-nowrap form-inline"><span style="color:#02346a">查&nbsp;件&nbsp;电&nbsp;&nbsp;话:</span>
-                                    <input :id="'inquire_tel'+waybill.id" :class="errors['_'+waybill.id]&&errors['_'+waybill.id].inquire_tel?'is-invalid tooltipTargetError':''"
-                                           :title="errors['_'+waybill.id]&&errors['_'+waybill.id].inquire_tel?errors['_'+waybill.id].inquire_tel[0]:''" v-if="waybill.isBtn || updatePool[waybill.id]" type="text" :value="waybill.inquire_tel"
-                                           class="form-control form-control-sm" @click="enlarge($event)"  style="width:50px">
-                                    <span v-else  class="text-muted">@{{ waybill.inquire_tel }}</span>
-                                </span>
-                                        <span class="mr-3 text-nowrap form-inline"><span style="color:#02346a">数量:</span>
-                                    <span class="input-group input-group-sm" v-if="waybill.isBtn || updatePool[waybill.id]">
-                                        <input :id="'amount'+waybill.id" :class="errors['_'+waybill.id]&&errors['_'+waybill.id].amount?'is-invalid tooltipTargetError':''"
-                                               :title="errors['_'+waybill.id]&&errors['_'+waybill.id].amount?errors['_'+waybill.id].amount[0]:''" type="text" :value="waybill.amount"
-                                               class="form-control"
-                                               @click="enlarge($event)" style="width:50px">
-                                        <span class="input-group-append">
-                                          <span class="input-group-text">件</span>
-                                        </span>
-                                    </span>
-                                    <span v-else class="text-muted"><span v-if="waybill.amount">@{{ waybill.amount }} @{{ waybill.amount_unit_name }}</span></span>
-                                </span>
-                                        <span class="mr-3 text-nowrap form-inline"><span style="color:#02346a">重量:</span>
-                                    <span class="input-group input-group-sm" v-if="waybill.isBtn || updatePool[waybill.id]">
-                                        <input :id="'carrier_weight_other'+waybill.id" :class="errors['_'+waybill.id]&&errors['_'+waybill.id].carrier_weight_other?'is-invalid tooltipTargetError':''"
-                                               :title="errors['_'+waybill.id]&&errors['_'+waybill.id].carrier_weight_other?errors['_'+waybill.id].carrier_weight_other[0]:''" type="text" :value="waybill.carrier_weight_other"
-                                               class="form-control" @click="enlarge($event)" style="width:50px">
-                                        <span class="input-group-append">
-                                          <span class="input-group-text">KG</span>
-                                        </span>
-                                    </span>
-                                    <span v-else class="text-muted">@{{ waybill.carrier_weight_other }}</span>
-                                </span>
-                                        <span class="mr-3 text-nowrap form-inline"><span style="color:#02346a">体积:</span>
-                                    <span class="input-group input-group-sm" v-if="waybill.isBtn || updatePool[waybill.id]">
-                                        <input :id="'carrier_weight'+waybill.id" :class="errors['_'+waybill.id]&&errors['_'+waybill.id].carrier_weight?'is-invalid tooltipTargetError':''"
-                                               :title="errors['_'+waybill.id]&&errors['_'+waybill.id].carrier_weight?errors['_'+waybill.id].carrier_weight[0]:''" type="text" :value="waybill.carrier_weight"
-                                               class="form-control" @click="enlarge($event)" style="width:50px">
-                                        <span class="input-group-append">
-                                          <span class="input-group-text">M³</span>
-                                        </span>
+                <div v-else v-for="waybill in waybills" class="w-100 border border-1" style="filter:grayscale(30%); " :id="'waybill-'+waybill.id">
+                    <div :style="waybill.status!=='已完结'?'background-color:#f6eee8':''" class="mt-3">
+                        <div style="transform:scale(0.9);color:#783000" class="pl-0">
+                            <span class="mr-3 text-nowrap">日期:@{{ waybill.deliver_at }}</span>
+                            <span class="mr-3 text-nowrap">承运商:@{{ waybill.carrier_name }}</span>
+                            <span class="mr-3 text-nowrap">宝时运单号:@{{ waybill.waybill_number }}<br></span>
+                            <span class="mr-3 text-nowrap">目的地:@{{ waybill.address }}<br></span>
+                            <span class="mr-3 text-nowrap">收货人:@{{ waybill.recipient }}</span>
+                            <span class="mr-3 text-nowrap">提货仓:@{{ waybill.origination }}</span>
+                            <span class="mr-3 text-nowrap">预估重量:<span v-if="waybill.warehouse_weight_other">@{{ waybill.warehouse_weight_other }} @{{ waybill.warehouse_weight_unit_other_name }}</span></span>
+                            <span class="mr-3 text-nowrap">预估体积:<span v-if="waybill.warehouse_weight">@{{ waybill.warehouse_weight }} @{{ waybill.warehouse_weight_unit_name }}</span></span>
+                        </div>
+                    </div>
+                    <div style="background-color:#e8eef6"  class="mb-3">
+                        <div style="transform:scale(0.9);color:#02346a" class="pl-0 form-inline">
+                            <div class="mr-3 text-nowrap form-inline">
+                                <label :for="'carrier_bill'+waybill.id">专线运单号:</label>
+                                <input :id="'carrier_bill'+waybill.id" :class="errors['_'+waybill.id]&&errors['_'+waybill.id].carrier_bill?'is-invalid tooltipTargetError':''"
+                                       v-if="waybill.isBtn || updatePool[waybill.id]" type="text" :value="waybill.carrier_bill"
+                                        class="form-control form-control-sm " @click="enlarge($event)"  style="width: 50px">
+                                <span v-else  class="text-muted">@{{ waybill.carrier_bill }}</span>
+                            </div>
+                            <div class="mr-3 text-nowrap form-inline">
+                                <label :for="'inquire_tel'+waybill.id">查&nbsp;件&nbsp;电&nbsp;&nbsp;话:</label>
+                                <input :id="'inquire_tel'+waybill.id" :class="errors['_'+waybill.id]&&errors['_'+waybill.id].inquire_tel?'is-invalid tooltipTargetError':''"
+                                       v-if="waybill.isBtn || updatePool[waybill.id]" :value="waybill.inquire_tel"  @click="enlarge($event)"
+                                       class="form-control form-control-sm" type="text" style="width:50px">
+                                <span v-else  class="text-muted">@{{ waybill.inquire_tel }}</span>
+                            </div>
+                            <div class="mr-3 text-nowrap form-inline">
+                                <label :for="'amount'+waybill.id">数量:</label>
+                                <div class="input-group input-group-sm" v-if="waybill.isBtn || updatePool[waybill.id]">
+                                    <input :id="'amount'+waybill.id" :class="errors['_'+waybill.id]&&errors['_'+waybill.id].amount?'is-invalid tooltipTargetError':''"
+                                     :value="waybill.amount" @click="enlarge($event)"
+                                   class="form-control" type="text" style="width:50px">
+                                    <span class="input-group-append">
+                                        <span class="input-group-text">件</span>
                                     </span>
-                                    <span v-else class="text-muted">@{{ waybill.carrier_weight }}</span>
+                                </div>
+                                <span v-else class="text-muted"><span v-if="waybill.amount">@{{ waybill.amount }} @{{ waybill.amount_unit_name }}</span></span>
+                            </div>
+                            <div class="mr-3 text-nowrap form-inline">
+                                <label :for="'carrier_weight_other'+waybill.id">重量:</label>
+                                <div class="input-group input-group-sm" v-if="waybill.isBtn || updatePool[waybill.id]">
+                                <input :id="'carrier_weight_other'+waybill.id" :class="errors['_'+waybill.id]&&errors['_'+waybill.id].carrier_weight_other?'is-invalid tooltipTargetError':''"
+                                   :value="waybill.carrier_weight_other" @click="enlarge($event)"
+                                    type="text" class="form-control" style="width:50px">
+                                <span class="input-group-append">
+                                  <span class="input-group-text">KG</span>
                                 </span>
-                                        <span class="mr-3 text-nowrap form-inline" v-if="!waybill.isBtn"><span style="color:#02346a">附加费:</span>
-                                    <span class="input-group input-group-sm">
-                                        <input :id="'subjoin_fee'+waybill.id" :value="waybill.subjoin_fee" type="number" step="0.01"
-                                               class="form-control" style="width:150px">
-                                        <span class="input-group-append">
-                                          <span class="input-group-text">元</span>
-                                        </span>
+                                </div>
+                                <span v-else class="text-muted">@{{ waybill.carrier_weight_other }}</span>
+                            </div>
+                            <div class="mr-3 text-nowrap form-inline">
+                                <label :for="'carrier_weight'+waybill.id">体积:</label>
+                                <div class="input-group input-group-sm" v-if="waybill.isBtn || updatePool[waybill.id]">
+                                    <input :id="'carrier_weight'+waybill.id" :class="errors['_'+waybill.id]&&errors['_'+waybill.id].carrier_weight?'is-invalid tooltipTargetError':''"
+                                           :value="waybill.carrier_weight" @click="enlarge($event)"
+                                           type="text" class="form-control" style="width:50px">
+                                    <span class="input-group-append">
+                                      <span class="input-group-text">M³</span>
                                     </span>
-                                </span>
-                                <span class="mr-3 text-nowrap">
-                                    <button class="btn btn-sm btn-outline-success" @click="submit(date,waybill.isBtn,waybill.id)">提交</button>
-                                    <button v-if="!waybill.isBtn && !updatePool[waybill.id]" class="btn btn-sm btn-outline-info" @click="$set(updatePool,waybill.id,true);">修改</button>
-                                </span>
                                 </div>
+                                <span v-else class="text-muted">@{{ waybill.carrier_weight }}</span>
+                            </div>
+                            <div class="mr-3 text-nowrap form-inline" v-if="!waybill.isBtn">
+                                <label :for="'subjoin_fee'+waybill.id">附加费:</label>
+                                <div class="input-group input-group-sm">
+                                    <input :id="'subjoin_fee'+waybill.id" :value="waybill.subjoin_fee" type="number" step="0.01"
+                                           class="form-control" style="width:150px">
+                                    <span class="input-group-append">
+                                      <span class="input-group-text">元</span>
+                                    </span>
                                 </div>
-                            </td>
-                        </tr>
-                        </tbody>
-                    </table>
+                            </div>
+                            <span class="mr-3 text-nowrap">
+                                <button class="btn btn-sm btn-outline-success" @click="submit(date,waybill.isBtn,waybill.id)">提交</button>
+                                <button v-if="!waybill.isBtn && !updatePool[waybill.id]" class="btn btn-sm btn-outline-info" @click="$set(updatePool,waybill.id,true);">修改</button>
+                            </span>
+                        </div>
+                    </div>
                 </div>
             </div>
         </div>
@@ -129,6 +130,8 @@
             searchText:"{{$searchText}}",
             lastHeight:"",
             updatePool:{},
+            coordinate:{},
+            slideStatus:{},
         },
         mounted:function(){
             $(".tooltipTarget").tooltip({'trigger':'hover'});
@@ -137,6 +140,36 @@
             $("#list").removeClass('d-none');
         },
         methods:{
+            startSlide(){
+                event.preventDefault();
+                this.coordinate.x = event.touches[0].pageX;
+                this.coordinate.y = event.touches[0].pageY;
+            },
+            endSlide(date){
+                event.preventDefault();
+                let x = event.changedTouches[0].pageX - this.coordinate.x;
+                let y = event.changedTouches[0].pageY - this.coordinate.y;
+                if (Math.abs(x) > Math.abs(y)) {
+                    if (x>0)this.lToR(date,event.target);
+                    else this.rToL(date,event.target);
+                }
+            },
+            rToL(date,element){
+                if (this.slideStatus[date])return;
+                element.classList.add('translationRtoL');
+                setTimeout(()=>{
+                    element.classList.remove('translationRtoL');
+                    this.$set(this.slideStatus,date,true);
+                },400);
+            },
+            lToR(date,element){
+                if (!this.slideStatus[date])return;
+                element.classList.add('translationLtoR');
+                setTimeout(()=>{
+                    element.classList.remove('translationLtoR');
+                    this.$set(this.slideStatus,date,false);
+                },400);
+            },
             selectedHeader(date){
                 if (this.header[date]===undefined)this.loadData(date);
                 if (this.header[date])this.$set(this.header,date,!this.header[date])