Pārlūkot izejas kodu

Merge branch 'zengjun' of ssh://was.baoshi56.com:10022/var/git/bswas

 Conflicts:
	app/Http/Controllers/TestController.php
LD 5 gadi atpakaļ
vecāks
revīzija
6cdbf7ed6d
39 mainītis faili ar 1564 papildinājumiem un 24 dzēšanām
  1. 95 0
      app/Http/Controllers/CacheShelfController.php
  2. 13 1
      app/Http/Controllers/OrderIssueController.php
  3. 7 7
      app/Http/Controllers/RejectedBillController.php
  4. 85 0
      app/Http/Controllers/StationCacheShelfGridController.php
  5. 1 0
      app/Http/Controllers/StationController.php
  6. 20 5
      app/Http/Controllers/TestController.php
  7. 10 2
      app/Http/Controllers/api/thirdPart/haiq/LightController.php
  8. 4 0
      app/Providers/AppServiceProvider.php
  9. 108 0
      app/Services/CacheShelfService.php
  10. 40 0
      app/Services/ForeignHaiRoboticsService.php
  11. 1 0
      app/Services/OrderIssueService.php
  12. 106 0
      app/Services/StationCacheShelfGridService.php
  13. 34 1
      app/Services/StationTaskMaterialBoxService.php
  14. 8 1
      app/Station.php
  15. 61 0
      app/StationCacheShelfGrid.php
  16. 1 1
      app/StationTask.php
  17. 15 0
      database/factories/StationCacheShelfGridFactory.php
  18. 2 1
      database/factories/StationFactory.php
  19. 69 0
      database/migrations/2021_04_13_140632_add_station_type_and_add_station.php
  20. 35 0
      database/migrations/2021_04_15_132002_create_station_cache_shelf_grids_table.php
  21. 16 0
      database/seeds/StationCacheShelfGridSeeder.php
  22. 5 4
      resources/views/rejected/importRejectedNumber.blade.php
  23. 42 0
      resources/views/station/cachingShelf/list/_fillBox.blade.php
  24. 61 0
      resources/views/station/cachingShelf/list/_table.blade.php
  25. 190 0
      resources/views/station/cachingShelf/list/index.blade.php
  26. 9 0
      resources/views/station/cachingShelf/menu.blade.php
  27. 1 1
      resources/views/station/menu.blade.php
  28. 9 0
      routes/apiLocal.php
  29. 3 0
      routes/web.php
  30. 49 0
      tests/Services/CacheShelfService/GetTasksTest.php
  31. 70 0
      tests/Services/CacheShelfService/LightOffTaskTest.php
  32. 88 0
      tests/Services/CacheShelfService/PutBinToStoreTest.php
  33. 62 0
      tests/Services/ForeignHaiRoboticsService/PutBinToStoreFromCacheShelfTest.php
  34. 38 0
      tests/Services/StationCacheShelfGrid/GetGridByCodeTest.php
  35. 39 0
      tests/Services/StationCacheShelfGrid/GetLocationTest.php
  36. 39 0
      tests/Services/StationCacheShelfGridService/CancelTaskTest.php
  37. 47 0
      tests/Services/StationCacheShelfGridService/LightOffTest.php
  38. 42 0
      tests/Services/StationCacheShelfGridService/ProcessGridTest.php
  39. 39 0
      tests/webApi/cacheShelf.http

+ 95 - 0
app/Http/Controllers/CacheShelfController.php

@@ -0,0 +1,95 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Components\AsyncResponse;
+use App\Exceptions\ErrorException;
+use App\MaterialBox;
+use App\Services\CacheShelfService;
+use App\Services\StationCacheShelfGridService;
+use App\Station;
+use App\StationCacheShelfGrid;
+use Illuminate\Contracts\Foundation\Application;
+use Illuminate\Contracts\View\Factory;
+use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Http\Request;
+use Illuminate\View\View;
+
+class CacheShelfController extends Controller
+{
+    use AsyncResponse;
+
+    /**
+     * 缓存货架
+     * @return Application|Factory|View
+     */
+    public function index()
+    {
+        $stations = Station::query()->with('stationType:name', 'parent:name')->whereHas('stationType', function ($query) {
+            /** @var Builder $query */
+            $query->where('name', '缓存架');
+        })->paginate(100);
+
+        return view('station.cachingShelf.list.index', compact('stations'));
+    }
+
+    /**
+     * 获取缓存货架上的任务列表
+     * @param Request $request
+     * @param string $id
+     * @param CacheShelfService $service
+     */
+    public function getTasksApi(Request $request,string $id,CacheShelfService $service)
+    {
+        /** @var Station $station */
+        $station = Station::query()->where('id',$id)->first();
+
+        $service->getTasks($station);
+        $this->success($station['grids']);
+    }
+
+    /**
+     * 缓存架亮灯
+     * @param Request $request
+     * @param StationCacheShelfGridService $gridService
+     */
+    public function lightOnApi(Request $request,StationCacheShelfGridService $gridService)
+    {
+        $grid_id = $request['index'];
+        /** @var Station $station */
+        $station = Station::query()->where('id',$request['id'])->first();
+
+        $grid = StationCacheShelfGrid::query()->firstOrCreate(['station_id'=>$station['id'],'grid_id'=>$grid_id]);
+        $materialBox = MaterialBox::query()->firstOrCreate(['code'=>$request['code']]);
+
+        $grid->update(['material_box_id' => $materialBox['id'],'status' => 1]);
+
+        return $gridService->lightOn($station,$request['x'],$request['y']);
+    }
+
+//    /**
+//     * 拍灯推送任务
+//     * @param Request $request
+//     * @param CacheShelfService $service
+//     */
+//    public function pushTaskApi(Request $request,CacheShelfService $service)
+//    {
+//        /**
+//         * @var Station $station
+//         * @var MaterialBox $materialBox
+//         * @var StationCacheShelfGrid $grid
+//         */
+//        $station = Station::query()->where('id',$request['id'])->first();
+//        $materialBox = MaterialBox::query()->where('code',$request['code'])->first();
+//        $grid = StationCacheShelfGrid::query()->where(['station_id'=>$station['id'],'grid_id'=>$request['index']])->first();
+//
+//        try {
+//            $bool = $service->putBinToStore($station, $materialBox, $grid);
+//            if($bool)$this->success();
+//            else $this->error('推送任务异常');
+//        } catch (ErrorException $e) {
+//            $this->error($e->getMessage());
+//        }
+//    }
+
+}

+ 13 - 1
app/Http/Controllers/OrderIssueController.php

@@ -338,11 +338,16 @@ class OrderIssueController extends Controller
         }
     }
 
-    public function updateColumnApi(Request $request)
+    public function updateColumnApi(Request $request,OrderIssueService $service): array
     {
         if (!Gate::allows('订单管理-问题件-编辑')) {
             return ['success'=>false,'fail_info' => '没有对应权限'];
         }
+        if($request['column']=='final_status'){
+            $orderIssues = OrderIssue::query()->where('id',$request['id'])->get();
+            $service->archive($orderIssues);
+            return ['success' =>true];
+        }
         try {
             OrderIssue::query()
                 ->where('id', $request->input('id'))
@@ -737,6 +742,13 @@ class OrderIssueController extends Controller
         }
     }
 
+
+    /**
+     * 批量归档
+     * @param Request $request
+     * @param OrderIssueService $service
+     * @return array|bool[]
+     */
     public function archiveOrderIssueApi(Request $request,OrderIssueService $service): array
     {
         if (!Gate::allows('订单管理-问题件-编辑')) return ['success'=>false,'error'=>'没有对应权限'];

+ 7 - 7
app/Http/Controllers/RejectedBillController.php

@@ -310,7 +310,7 @@ class RejectedBillController extends Controller
          */
         $service = app('RejectedBillService');
         $rejectedBillItemService = app('RejectedBillItemService');
-        $params = [['logistic_number_return','logistic_number','fee_collected']];
+        $params = [['logistic_number_return','order_number','fee_collected']];
         $logistic_numbers = [];             // 原单单号
         $logistic_number_map = [];
         $logistic_number_return = [];       // 退回单号
@@ -341,8 +341,8 @@ class RejectedBillController extends Controller
         $rejectedBill_collect = collect();
 
         // 对已用的进行修改
-        $update_fee_params = [['id','logistic_number','fee_collected']];                //对原有的进行修改 有到付费用
-        $update_params = [['id','logistic_number']];                                    // 无到付费用
+        $update_fee_params = [['id','order_number','fee_collected']];                //对原有的进行修改 有到付费用
+        $update_params = [['id','order_number']];                                    // 无到付费用
         $exist_picktotraceid = [];                                                      // 已有退回单号
         $rejectedBills = RejectedBill::query()->whereIn('logistic_number_return',$logistic_number_return)->get();
         $rejectedBills->each(function($rejectedBill)use(&$update_fee_params,&$update_params,$logistic_number_return_map,&$exist_picktotraceid,&$rejectedBill_collect){
@@ -351,9 +351,9 @@ class RejectedBillController extends Controller
             $params = $logistic_number_return_map[$logistic_number_return];
             $rejectedBill->logistic_number ? $exist_picktotraceid[$rejectedBill->logistic_number] = $rejectedBill->logistic_number : null;    // 记录已有原单单号
             if(isset($params[2])){
-                $update_fee_params[] = ['id'=>$rejectedBill->id,'logistic_number'=>$params[1],'fee_collected'=>$params[2]];
+                $update_fee_params[] = ['id'=>$rejectedBill->id,'order_number'=>$params[1],'fee_collected'=>$params[2]];
             }else if(isset($params[1])){
-                $update_params[] = ['id'=>$rejectedBill->id,'logistic_number'=>$params[1]];
+                $update_params[] = ['id'=>$rejectedBill->id,'order_number'=>$params[1]];
             }
         });
         // 对不存在的进行创建
@@ -380,9 +380,9 @@ class RejectedBillController extends Controller
                     'logistic_number_return' => $logistic_number_map[$key][0] ?? '',
                     'id_logistic_return' =>$logistic->id ?? '',
                     'fee_collected' => $logistic_number_map[$key][2] ?? '',
-                    'order_number' =>$order_header->soreference1,
+//                    'order_number' =>$order_header->soreference1,
                     'mobile_sender' => empty($order_header->c_tel2)?$order_header->c_tel1:$order_header->c_tel2,
-                    'logistic_number' => $logistic_number_map[$key][1] ?? '',
+                    'order_number' => $logistic_number_map[$key][1] ?? '',
                     'remark' => $order_header->notes,
                     'is_loaded' =>0,
                     "id_operator" => Auth::id(),

+ 85 - 0
app/Http/Controllers/StationCacheShelfGridController.php

@@ -0,0 +1,85 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\StationCacheShelfGrid;
+use Illuminate\Http\Request;
+
+class StationCacheShelfGridController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function index()
+    {
+        //
+    }
+
+    /**
+     * Show the form for creating a new resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function create()
+    {
+        //
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\Response
+     */
+    public function store(Request $request)
+    {
+        //
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  \App\StationCacheShelfGrid  $stationCacheShelfGrid
+     * @return \Illuminate\Http\Response
+     */
+    public function show(StationCacheShelfGrid $stationCacheShelfGrid)
+    {
+        //
+    }
+
+    /**
+     * Show the form for editing the specified resource.
+     *
+     * @param  \App\StationCacheShelfGrid  $stationCacheShelfGrid
+     * @return \Illuminate\Http\Response
+     */
+    public function edit(StationCacheShelfGrid $stationCacheShelfGrid)
+    {
+        //
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \App\StationCacheShelfGrid  $stationCacheShelfGrid
+     * @return \Illuminate\Http\Response
+     */
+    public function update(Request $request, StationCacheShelfGrid $stationCacheShelfGrid)
+    {
+        //
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  \App\StationCacheShelfGrid  $stationCacheShelfGrid
+     * @return \Illuminate\Http\Response
+     */
+    public function destroy(StationCacheShelfGrid $stationCacheShelfGrid)
+    {
+        //
+    }
+}

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

@@ -107,4 +107,5 @@ class StationController extends Controller
     {
         //
     }
+
 }

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

@@ -109,9 +109,11 @@ use App\Services\ShopService;
 use App\Services\StoreService;
 use App\Services\SupplierService;
 use App\Services\WarehouseService;
+use App\Station;
 use App\StationRuleBatch;
 use App\StationTask;
 use App\StationTaskMaterialBox;
+use App\StationType;
 use App\Store;
 use App\StationTaskBatch;
 use App\StoreCheckingReceiveItem;
@@ -1365,12 +1367,25 @@ where purch.islower=1 and deliver.id>'.$id);
         }
     }
 
-    public function testOrderTracking()
+    public function firstAndCreated()
     {
-        $orderNos =  ['SO210416004929'];
-        $service = app(OrderTrackingService::class);
-        $orderHeadService= app(OracleDOCOrderHeaderService::class);
-        $orderHeaders = $orderHeadService->getQuery()->whereIn('DOC_Order_Header.OrderNo',$orderNos)->get();
+        $arr = ['name' => '缓存货架3'];
+        $created = ['name'=>'缓存货架3','station_type_id' => (function(){
+            $type =StationType::query()->where('name','缓存架')->first();
+            return $type['id'];
+        })()];
+        $station = Station::query()->firstOrCreate($arr,$created);
+        dd($station);
+    }
+
+
+    public function syncOrderTracking()
+    {
+        $orderNos = ['OSSO21040013','OSSO21040012'];
+        $service = new OrderTrackingService();
+        $orderHeaderService = new OracleDOCOrderHeaderService();
+        $orderHeaders = $orderHeaderService->getQuery()->whereIn('DOC_Order_Header.SoReference1',$orderNos)->get();
+        $service->createByWmsOrderHeader($orderHeaders);
         $service->updateByWmsOrderHeaders($orderHeaders);
     }
     public function addHaiBox(Request $request)

+ 10 - 2
app/Http/Controllers/api/thirdPart/haiq/LightController.php

@@ -6,6 +6,7 @@ namespace App\Http\Controllers\api\thirdPart\haiq;
 
 
 
+use App\Services\CacheShelfService;
 use App\Services\ForeignHaiRoboticsService;
 use Illuminate\Http\Request;
 
@@ -19,7 +20,7 @@ class LightController
         $this->service=app('ForeignHaiRoboticsService');
     }
 
-    public function lightOn(Request $request){
+    public function lightOn($post){
     }
     public function lightOff(Request $request){
     }
@@ -28,7 +29,14 @@ class LightController
      * @param Request $request {"areaCode":"1004","locCode":"HAIB2-02-03","displayInfo":null,"PTLAction":0,"PTLSettings":null}
      * @return array
      */
-    public function update(Request $request){
+    public function update(Request $request){// 拍灯以后的消息发至此处
+
+        if($request['PTLAction'] == 0){  // 拍灯 推送任务
+            /** @var CacheShelfService $cacheShelfService */
+            $cacheShelfService = app(CacheShelfService::class);
+            $result =   $cacheShelfService->lightOffTask($request['locCode'],$request['PTLAction']);
+            return ['location'=>$result['success'] ? 200 :0,'errMsg'=>$result['errMsg'] ?? null,'data'=>$request->all()];
+        }
         $success = $request->input('success');
         $location = $success?200:0;
         app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->all()));

+ 4 - 0
app/Providers/AppServiceProvider.php

@@ -6,6 +6,7 @@ use App\Http\Controllers\Controller;
 use App\Services\AuthorityService;
 use App\Services\BatchService;
 use App\Services\CacheService;
+use App\Services\CacheShelfService;
 use App\Services\CommodityService;
 use App\Services\common\BatchUpdateService;
 use App\Services\CommodityBarcodeService;
@@ -101,6 +102,7 @@ use App\Services\RegionService;
 use App\Services\UserWorkgroupService;
 use App\Services\DischargeTaskService;
 use App\Services\DeliveryAppointmentService;
+use App\Services\StationCacheShelfGridService;
 use Illuminate\Queue\Events\JobFailed;
 use Illuminate\Support\Facades\Queue;
 use Illuminate\Support\Facades\Schema;
@@ -157,6 +159,7 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('BatchService',BatchService::class);
         app()->singleton('BatchUpdateService', BatchUpdateService::class);
         app()->singleton('CacheService',CacheService::class);
+        app()->singleton('CacheShelfService',CacheShelfService::class);
         app()->singleton('CheckActiveMenuService',CheckActiveMenuService::class);
         app()->singleton('CommodityBarcodeService',CommodityBarcodeService::class);
         app()->singleton('CommodityService', CommodityService::class);
@@ -230,6 +233,7 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('RejectedBillService',RejectedBillService::class);
         app()->singleton('RejectedService',RejectedService::class);
         app()->singleton('ShopService',ShopService::class);
+        app()->singleton('StationCacheShelfGridService',StationCacheShelfGridService::class);
         app()->singleton('StationRuleBatchService',StationRuleBatchService::class);
         app()->singleton('StationService',StationService::class);
         app()->singleton('StationTaskBatchService',StationTaskBatchService::class);

+ 108 - 0
app/Services/CacheShelfService.php

@@ -0,0 +1,108 @@
+<?php
+
+namespace App\Services;
+
+use App\Exceptions\ErrorException;
+use App\MaterialBox;
+use App\Station;
+use App\StationCacheShelfGrid;
+use App\StationTaskMaterialBox;
+use App\Traits\ServiceAppAop;
+use Illuminate\Support\Facades\Http;
+
+class CacheShelfService
+{
+    use ServiceAppAop;
+
+    protected $modelClass = Station::class;
+    /** @var StationTaskMaterialBoxService $stationTaskMaterialBoxService */
+    private $stationTaskMaterialBoxService;
+    /** @var StationCacheShelfGridService $stationCacheShelfGridService */
+    private $stationCacheShelfGridService;
+    /** @var ForeignHaiRoboticsService $foreignHaiRoboticsService */
+    private $foreignHaiRoboticsService;
+
+    /**
+     * 获取现有的缓存架任务
+     * @param Station $station
+     */
+    public function getTasks(Station $station)
+    {
+        $grids = StationCacheShelfGrid::query()->with('materialBox')->where('station_id', $station['id'])->where('status', 1)->orderBy('grid_id')->get();
+        $station->setRelation('grids', $grids);
+    }
+
+    public function lightOffTask($locCode, $PTLAction): array
+    {
+        $this->instant($this->stationCacheShelfGridService, 'StationCacheShelfGridService');
+        list($stationCode, $gridId, $row, $col) = StationCacheShelfGrid::getGridByCode($locCode);
+        $station = Station::query()->where('code', $stationCode)->first();
+        $grid = StationCacheShelfGrid::query()->where('station_id', $station['id'])->where('grid_id', $gridId)->first();
+        $materialBox = MaterialBox::query()->where('id', $grid['material_box_id'])->first();
+        try {
+            $bool = $this->putBinToStore($station, $materialBox, $grid);                    // 推送任务
+            if($bool)$this->stationCacheShelfGridService->lightOff($locCode, $PTLAction);    // 灭灯广播
+            return ['success' => $bool];
+        } catch (ErrorException $e) {
+            LogService::log(__FUNCTION__,'缓存架推送任务失败',json_encode($e->getMessage()));
+            return ['success' => false,'errMsg' => $e->getMessage()];
+        }
+    }
+
+    /**
+     * 推任务
+     * @param  $station
+     * @param  $materialBox
+     * @param  $grid
+     * @return bool
+     * @throws ErrorException
+     */
+    public function putBinToStore($station, $materialBox, $grid): bool
+    {
+        $this->instant($this->stationTaskMaterialBoxService, 'StationTaskMaterialBoxService');
+        $this->instant($this->stationCacheShelfGridService, 'StationCacheShelfGridService');
+        $this->instant($this->foreignHaiRoboticsService, 'ForeignHaiRoboticsService');
+
+        /** @var StationTaskMaterialBox $stationTaskMaterialBox */
+        $stationTaskMaterialBox = $this->stationTaskMaterialBoxService->createByStationMaterialBox($station, $materialBox);
+        $this->stationCacheShelfGridService->processGrid($grid, $station, $materialBox);
+
+        $station->setRelation('grids', $grid);
+        $stationTaskMaterialBox->setRelation('station', $station);
+        $stationTaskMaterialBox->setRelation('materialBox', $materialBox);
+
+        return $this->foreignHaiRoboticsService->putBinToStore_fromCacheShelf($stationTaskMaterialBox);
+    }
+
+//    /**
+//     * 入库任务完成
+//     * @param $params
+//     */
+//    public function putBinToStoreFinish($params)
+//    {
+//        $this->instant($this->stationTaskMaterialBoxService,'StationTaskMaterialBoxService');
+//
+//        $locCode = $params['locCode'];
+//
+//        list($stationCode, $gridId) = StationCacheShelfGrid::getGridByCode($locCode);
+//        $station = Station::query()->where('code', $stationCode)->first();
+//
+//        $stationCacheShelfGrid = StationCacheShelfGrid::query()->with('materialBox')->where('station_id', $station)->where('grid_id', $gridId)->first();
+//        $stationCacheShelfGrid->update(['status' => '0', 'material_box_id' => null]);
+//
+//        $StationTaskMaterialBox = StationTaskMaterialBox::query()->where('station_id', $station['id'])->where('material_box_id', $stationCacheShelfGrid['$stationCacheShelfGrid'])->first();
+//        $this->stationTaskMaterialBoxService->set($StationTaskMaterialBox, ['status' => '已完成']);
+//    }
+
+//    /**
+//     * 取消格口任务
+//     * @param Station $station
+//     * @param array $girds
+//     */
+//    public function cancelTask(Station $station, array $girds = [])
+//    {
+//        $gridQuery = StationCacheShelfGrid::query()->where('station_id', $station['id']);
+//        if (count($girds) > 0) $gridQuery->whereIn('grid_id', $girds);
+//        $this->stationCacheShelfGridService->cancelTask($gridQuery->get());
+//    }
+}

+ 40 - 0
app/Services/ForeignHaiRoboticsService.php

@@ -6,6 +6,7 @@ namespace App\Services;
 
 use App\Exceptions\ErrorException;
 use App\MaterialBox;
+use App\StationCacheShelfGrid;
 use App\StationTaskMaterialBox;
 use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\Http;
@@ -225,6 +226,45 @@ class ForeignHaiRoboticsService
             $this->stationTaskMaterialBoxService->set($stationTaskMaterialBox,[
                 'id' => $stationTaskMaterialBox['id'],
                 'status' => $stationTaskMaterialBox['status']='处理中',
+                'station_id' => 4,
+            ]);
+        }
+        return $controlSuccess;
+    }
+
+    /** 缓存架入立架 料箱 任务
+     * @param StationTaskMaterialBox|null $stationTaskMaterialBox
+     * @return bool
+     * @throws ErrorException
+     */
+    public function putBinToStore_fromCacheShelf(?StationTaskMaterialBox $stationTaskMaterialBox): bool
+    {
+        LogService::log('海柔请求','putBinToStore_fromCacheShelf1', '');
+        LogService::log('海柔请求','putBinToStore_fromCacheShelf2', json_encode($stationTaskMaterialBox));
+
+        $this->instant($this->stationService,'StationService');
+
+        // 缓存架格口
+        $formLocation = StationCacheShelfGrid::getLocation($stationTaskMaterialBox['station'],$stationTaskMaterialBox['station']['grids']->first());
+
+        /** 创建料箱 从缓存架 到 立架任务 */
+        $dataToPost=$this->makeJson_move(
+            collect([$stationTaskMaterialBox]),
+            '缓存架入立架',
+            $formLocation,              //TODO:通过计算StationCacheShelfGrid 的 Grid_id 获取格口的编号
+            ''
+        );
+
+        LogService::log('海柔请求','putBinToStore_fromCacheShelf3', json_encode($dataToPost));
+
+        /** 控制海柔机器人执行任务 */
+        $controlSuccess = $this->controlHaiRobot($dataToPost);
+        if($controlSuccess){
+            $this->instant($this->stationTaskMaterialBoxService,'StationTaskMaterialBoxService');
+            $this->stationTaskMaterialBoxService->set($stationTaskMaterialBox,[
+                'id' => $stationTaskMaterialBox['id'],
+                'status' => $stationTaskMaterialBox['status']='处理中',
+                'station_id' => $stationTaskMaterialBox['station']['id']?? '',
             ]);
         }
         return $controlSuccess;

+ 1 - 0
app/Services/OrderIssueService.php

@@ -382,6 +382,7 @@ class OrderIssueService
     }
 
     /**
+     * 归档
      * @param $orderIssues
      */
     public function archive($orderIssues)

+ 106 - 0
app/Services/StationCacheShelfGridService.php

@@ -0,0 +1,106 @@
+<?php
+
+namespace App\Services;
+
+use App\Events\BroadcastToStation;
+use App\Station;
+use App\Traits\ServiceAppAop;
+use App\StationCacheShelfGrid;
+use Illuminate\Support\Facades\Http;
+
+class StationCacheShelfGridService
+{
+    use ServiceAppAop;
+
+    protected $modelClass = StationCacheShelfGrid::class;
+
+    /**
+     * processGrid 格口上放入料箱
+     * lightOff 解析HaiQ格口灭灯请求  完成格口上的任务 进行灭灯完成后的广播
+     * cancelTask 完成格口上的任务
+     * lightOn 发送给HaiQ的格口亮灯
+     */
+
+    /**
+     * 修改格口的状态
+     * @param $stationCacheShelfGrid
+     * @param $station
+     * @param $materialBox
+     */
+    public function processGrid($stationCacheShelfGrid, $station, $materialBox)
+    {
+        $stationCacheShelfGrid->update(['station_id' => $station['id'], 'material_box_id' => $materialBox['id'], 'status' => 1]);
+    }
+
+    /**
+     * 清空任务
+     * @param $grids
+     * @return bool
+     */
+    public function cancelTask($grids): bool
+    {
+
+        return StationCacheShelfGrid::query()->whereIn('id',data_get($grids,'*.id'))->update(['material_box_id' => null, 'status' => 0]);
+    }
+
+    /**
+     * 格口灭灯完成后的广播
+     * @param $locCode
+     * @param $PTLAction
+     */
+    public function lightOff($locCode, $PTLAction)
+    {
+        if ($PTLAction == 0) {
+            list($stationCode, $gridId, $x, $y) = StationCacheShelfGrid::getGridByCode($locCode);
+            $station = Station::query()->where('code', $stationCode)->first();
+            $gird = StationCacheShelfGrid::query()->where('station_id',$station['id'])->where('grid_id',$gridId)->get();
+            $this->cancelTask($gird);
+            $json = json_encode([
+                'code' => $stationCode,
+                'x' => $x,
+                'y' => $y,
+                'id' => $station['id'] ?? '',
+                'grid_id' => $gridId,
+            ]);
+            broadcast(new BroadcastToStation($station['id'] ?? '', $json));
+            StationCacheShelfGrid::query()->where('station_id',$station['id'])->where('grid_id', $gridId)->update(['material_box_id' => null, 'status' => 0]);
+        }
+    }
+
+    /**
+     * 通知HaiQ亮灯
+     * @param Station $station
+     * @param $pointX
+     * @param $pointY
+     * @return string
+     */
+    public function lightOn(Station $station, $pointX, $pointY)
+    {
+        $locCode = 'HAI' . $station['code'] . '-0' . $pointX . '-0' . $pointY;
+        $params = [
+            "areaCode" => "1004",
+            "PTLAction" => 1, //1是开,0是关
+            "PTLSettings" => [
+                "color" => 1,
+                "frequency" => 1
+            ],
+            "displayInfo" => [
+                "detail01" => "detail01",
+                "detail02" => "detail02",
+                "detail03" => "detail03",
+                "qrCode" => "qrCode",
+                "qty00" => "11",
+                "qty01" => 1,
+                "qty02" => 2,
+                "title" => "title",
+                "uomDesc01" => "uo",
+                "uomDesc02" => "uo"
+            ],
+            "locCode" => $locCode//灯条口,B1\B2=设备编号,中间号码代表从右往左数的列,右边号码时从下往上数
+        ];
+//        LogService::log(__METHOD__,'海柔亮灯请求',json_encode($params));
+        $response = Http::post(config('api.haiq.storage.light'), $params);
+//        LogService::log(__METHOD__,'海柔亮灯请求返回',json_encode($params));
+        return $response->body();
+    }
+}

+ 34 - 1
app/Services/StationTaskMaterialBoxService.php

@@ -5,10 +5,12 @@ namespace App\Services;
 
 
 use App\Batch;
+use App\Events\BroadcastToStation;
 use App\Exceptions\ErrorException;
 use App\Exceptions\Exception;
 use App\MaterialBox;
 use App\OrderCommodity;
+use App\StationCacheShelfGrid;
 use App\StationTask;
 use App\StationTaskBatch;
 use App\StationTaskMaterialBox;
@@ -35,6 +37,8 @@ class StationTaskMaterialBoxService
     private $orderCommodityService;
     /** @var MaterialBoxService $materialBoxService */
     private $materialBoxService;
+    /** @var StationCacheShelfGridService $stationCacheShelfGridService */
+    private $stationCacheShelfGridService;
     public function __construct(){
         $this->stationService=null;
         $this->stationTypeService=null;
@@ -44,6 +48,15 @@ class StationTaskMaterialBoxService
         $this->stationTaskCommodityService=null;
     }
 
+    function createByStationMaterialBox($station,$materialBox)
+    {
+        return StationTaskMaterialBox::query()->create([
+            'station_id' => $station['id'],
+            'material_box_id' => $materialBox['id'],
+            'status' => '待处理'
+        ]);
+    }
+
     function createByBatches(Collection $batches,Collection $stationTasks_toAttach): Collection
     {
         $this->instant($this->stationTaskService,'StationTaskService');
@@ -140,9 +153,28 @@ class StationTaskMaterialBoxService
         }
     }
 
-    function markHasTaken($stationTaskMaterialBox){
+    function markHasTaken($stationTaskMaterialBox)
+    {
         //TODO: 标记 料箱位置(需要其字段存在)$stationTaskMaterialBox['materialBox']['position']
+
+        $this->instant($this->stationCacheShelfGridService,'StationCacheShelfGridService');
+
+        // 料箱从缓存架上拿走
+        if($stationTaskMaterialBox['station']['stationType']['name']=='缓存架'){
+            $stationTaskMaterialBox['status'] = '完成';
+
+            $json = json_encode([
+                'station_id'=>$stationTaskMaterialBox['station_id'],
+                'code' => $stationTaskMaterialBox['materialBox']['code'],
+                'status' => '完成'
+            ]);
+            $grids = StationCacheShelfGrid::query()->where(['station_id'=>$stationTaskMaterialBox['station_id'],'material_box_id'=>$stationTaskMaterialBox['material_box_id']])->get();
+            $this->stationCacheShelfGridService->cancelTask($grids);
+            broadcast(new BroadcastToStation($stationTaskMaterialBox['station_id'], $json));
+            $this->markProcessed($stationTaskMaterialBox);
+        }
     }
+
     function processNextQueued(StationTaskMaterialBox $stationTaskMaterialBox_lastProcessed){
         $station_id=$stationTaskMaterialBox_lastProcessed['station_id'];
         $stationTaskMaterialBox_next=StationTaskMaterialBox::query()
@@ -155,6 +187,7 @@ class StationTaskMaterialBoxService
         }
         return $stationTaskMaterialBox_next;
     }
+
     function markProcessed(StationTaskMaterialBox $stationTaskMaterialBox){
         $stationTaskMaterialBox['status'] = '完成';
         $stationTaskMaterialBox['station_id'] = 4;

+ 8 - 1
app/Station.php

@@ -2,13 +2,15 @@
 
 namespace App;
 
+use App\Traits\ModelTimeFormat;
 use Illuminate\Database\Eloquent\Model;
-
+use Illuminate\Database\Eloquent\Relations\HasMany;
 use App\Traits\ModelLogChanging;
 
 class Station extends Model
 {
     use ModelLogChanging;
+    use ModelTimeFormat;
 
     protected $fillable=['name', 'code', 'station_type_id','sequence','parent_id'];
 
@@ -28,4 +30,9 @@ class Station extends Model
     public function stationTypeBinMonitor(){
         return $this->hasOne(StationTypeBinMonitor::class);
     }
+
+    public function grids(): HasMany
+    {
+        return $this->hasMany(StationCacheShelfGrid::class);
+    }
 }

+ 61 - 0
app/StationCacheShelfGrid.php

@@ -0,0 +1,61 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use App\Traits\ModelLogChanging;
+
+class StationCacheShelfGrid extends Model
+{
+    use ModelLogChanging;
+
+    protected $fillable = ['station_id', 'material_box_id', 'grid_id', 'status'];
+
+    public static $status = [
+        '0' => '无',
+        '1' => '待处理',
+    ];
+
+    public function station(): BelongsTo
+    {
+        return $this->belongsTo(Station::class);
+    }
+
+    public function materialBox(): BelongsTo
+    {
+        return $this->belongsTo(MaterialBox::class);
+    }
+
+    /**
+     * 根据格口计算位置
+     * @param Station $station
+     * @param StationCacheShelfGrid $grid
+     * @return string
+     */
+    public static function getLocation(Station $station, StationCacheShelfGrid $grid): string
+    {
+        $code = $station['code'];
+        $grid_id = $grid['grid_id'];
+        $row = 2 - round($grid_id / 3) + 1;
+        $col = 2 - ($grid_id % 3) + 1;
+        return 'HAI' . $code . '-0' . $col . '-0' . $row;
+    }
+
+    /**
+     * 根据位置计算 grid_id 和 station code
+     * @param $code
+     * @return array|false[]
+     */
+    public static function getGridByCode($code): array
+    {
+        $arr = [];
+        preg_match('/^HAI([\w\.\ ]+)-0([0-9]+)-0([0-9]+)/',$code,$arr);
+        if(count($arr)==0)return [false,false,null,null];
+        $stationCode =$arr[1] ?? false;
+        $col = $arr[2] ?? 0;  // 列
+        $row = $arr[3] ?? 0;  // 行
+        $gridId = ($row-1)*3 + (3-$col);
+        return [$stationCode,$gridId,$row,$col];
+    }
+}

+ 1 - 1
app/StationTask.php

@@ -10,7 +10,7 @@ class StationTask extends Model
 {
     use ModelLogChanging;
 
-    protected $fillable = ['status'];
+    protected $fillable = ['status','station_id'];
 
     public function tasks()
     {

+ 15 - 0
database/factories/StationCacheShelfGridFactory.php

@@ -0,0 +1,15 @@
+<?php
+
+/** @var \Illuminate\Database\Eloquent\Factory $factory */
+
+use App\StationCacheShelfGrid;
+use Faker\Generator as Faker;
+
+$factory->define(StationCacheShelfGrid::class, function (Faker $faker) {
+    return [
+        'station_id' => $faker->numberBetween(0,1),
+        'material_box_id' => $faker->numberBetween(0,100),
+        'grid_id' => 1,
+        'status' => 0
+    ];
+});

+ 2 - 1
database/factories/StationFactory.php

@@ -7,6 +7,7 @@ use Faker\Generator as Faker;
 
 $factory->define(Station::class, function (Faker $faker) {
     return [
-        //
+        'name' => $faker->name,
+        'code' => $faker->name,
     ];
 });

+ 69 - 0
database/migrations/2021_04_13_140632_add_station_type_and_add_station.php

@@ -0,0 +1,69 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use App\Station;
+use App\StationType;
+use App\Authority;
+
+class AddStationTypeAndAddStation extends Migration
+{
+
+    public $stationTypeNames = ['缓存架'];
+
+    public $stationNames = ['缓存架01', '缓存架02'];
+
+    public $authorityName = ['站管理-缓存架'];
+
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        foreach ($this->stationTypeNames as $name) {
+            if (StationType::query()->where('name', $name)->exists()) continue;
+            StationType::query()->create(['name' => $name]);
+        }
+
+        $stationType = StationType::query()->where('name', '缓存架')->first();
+        foreach ($this->stationNames as $stationName) {
+            if (Station::query()->where('name', $stationName)->exists()) continue;
+            Station::query()->create([
+                'name' => $stationName,
+                'code' => $stationName,
+                'station_type_id' => $stationType['id'],
+            ]);
+        }
+
+        foreach ($this->authorityName as $name) {
+            if(Authority::query()->where('name',$name)->exists())continue;
+            Authority::query()->create(['name'=>$name,
+                'alias_name'=>$name]);
+        }
+
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        foreach ($this->stationNames as $stationName) {
+            if (!Station::query()->where('name', $stationName)->exists()) continue;
+            Station::query()->where('name', $stationName)->delete();
+        }
+
+        foreach ($this->stationTypeNames as $name) {
+            if (!Station::query()->where('name', $name)->exists()) continue;
+            Station::query()->where('name', $name)->delete();
+        }
+
+        foreach ($this->authorityName as $name) {
+            if(!Authority::query()->where('name',$name)->exists())continue;
+            Authority::query()->where('name',$name)->delete();
+        }
+    }
+}

+ 35 - 0
database/migrations/2021_04_15_132002_create_station_cache_shelf_grids_table.php

@@ -0,0 +1,35 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateStationCacheShelfGridsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('station_cache_shelf_grids', function (Blueprint $table) {
+            $table->id();
+            $table->bigInteger('station_id')->comment('站');
+            $table->bigInteger('material_box_id')->nullable()->comment('料箱');
+            $table->tinyInteger('grid_id')->comment('编号');
+            $table->tinyInteger('status')->comment('状态');
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('station_cache_shelf_grids');
+    }
+}

+ 16 - 0
database/seeds/StationCacheShelfGridSeeder.php

@@ -0,0 +1,16 @@
+<?php
+
+use Illuminate\Database\Seeder;
+
+class StationCacheShelfGridSeeder extends Seeder
+{
+    /**
+     * Run the database seeds.
+     *
+     * @return void
+     */
+    public function run()
+    {
+        //
+    }
+}

+ 5 - 4
resources/views/rejected/importRejectedNumber.blade.php

@@ -2,7 +2,8 @@
 @section('title')退回件-导入@endsection
 @section('content')
     <div id="nav2">
-        @component('order.issue.menu')@endcomponent
+        @component('rejected.menu')@endcomponent
+        @component('rejected.search.menu')@endcomponent
     </div>
     <div class="container-fluid" id="issue_import_div">
         <div class="card col-md-8 offset-md-2">
@@ -11,7 +12,7 @@
                     <div class="form-group row text-center">
                         <div class="col-12 text-danger">
                             退回单号修改<br/>
-                            【退回单号,原单单号】 必填项;【到付金额】 非必填项<br/>
+                            【退回单号,单号】 必填项;【到付金额】 非必填项<br/>
                             <span class="text-muted" style="opacity:0.7">
                                 如果在导入后出现部分数据导入失败,修改对应错误的数据继续导入即可,
                             </span>
@@ -63,8 +64,8 @@
         let listVue = new Vue({
             el:'#issue_import_div',
             data:{
-                rows:['退回单号','原单单号','到付金额'],
-                requiredRows:['退回单号','原单单号','到付金额'],
+                rows:['退回单号','单号','到付金额'],
+                requiredRows:['退回单号','单号','到付金额'],
                 popoverContent:'',
                 pasteDataText: '',
             },

+ 42 - 0
resources/views/station/cachingShelf/list/_fillBox.blade.php

@@ -0,0 +1,42 @@
+<div class="modal face" id="box">
+    <div class="modal-dialog ":class="boxClass">
+        <div class="modal-content">
+            <div class="modal-header">
+                <div class="modal-title">入料箱</div>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label for="material-box">扫描条码</label>
+                    <div class="form-inline">
+                        <input type="text" id="material-box" class="form-control col" @keydown.enter="pushMaterialBox()" v-model="materialBoxCode">
+                    </div>
+                </div>
+                <hr>
+                <div class="container">
+                    <template v-if="currentStation.data ">
+                        <div class="row mt-1 mb-1" v-for="(rows,rowI) in currentStation.data">
+                            <template v-if="rows.length !== 0">
+                                <div class="col" v-for="(item,colI) in rows" :y="item.row" :x="item.col">
+                                    <textarea class="form-control font-weight-bold"
+                                              style="font-size: 35px"
+                                              @keyup.enter="pushBoxToStation(item.row,item.col,$event)"
+                                              :value="item.code"
+                                              :placeholder="item.index"
+                                              :class="item.code? 'border-success ':''"
+                                        ></textarea>
+                                </div>
+                            </template>
+                        </div>
+                    </template>
+                </div>
+                <div class="modal-footer">
+                    <button class="btn btn-primary" data-dismiss="modal">关闭</button>
+                    <button class="btn btn-primary" @click="clearCurrentStation">清空</button>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>

+ 61 - 0
resources/views/station/cachingShelf/list/_table.blade.php

@@ -0,0 +1,61 @@
+<table class="table table-striped table-md table-hover" id="table">
+    <thead>
+        <tr>
+            <th>
+                设备id
+            </th>
+            <th>
+                入料箱
+            </th>
+            <th>
+                名称
+            </th>
+            <th>
+                父级设备
+            </th>
+            <th>
+                硬件id
+            </th>
+            <th>
+                备注
+            </th>
+            <th>
+                录入时间
+            </th>
+        </tr>
+        <template v-if="stations.length > 0">
+            <tr v-for="(station,i) in stations" @click="selectTr===i+1?selectTr=0:selectTr=i+1" :class="selectTr===i+1?'focusing' : ''">
+                <td>
+                    @{{ station.id }}
+                </td>
+                <td>
+                    <button class="btn btn-primary" @click="showFeedBox(station)">入料箱</button>
+                </td>
+                <td>
+                    @{{ station.name }}
+                </td>
+                <td>
+                    @{{ station.parent ? station.parent.name  : ''}}
+                </td>
+                <td>
+                    @{{ station.parent ? station.parent.id  : ''}}
+                </td>
+                <td>
+                    @{{ station.sequence ? station.sequence : ''}}
+                </td>
+                <td>
+                    @{{ station.created_at }}
+                </td>
+            </tr>
+        </template>
+        <template v-else>
+            <tr>
+                <td colspan="2">
+                    <div class="alert alert-info">
+                        查询数据为空
+                    </div>
+                </td>
+            </tr>
+        </template>
+    </thead>
+</table>

+ 190 - 0
resources/views/station/cachingShelf/list/index.blade.php

@@ -0,0 +1,190 @@
+@extends('layouts.app')
+
+@section('title','列表')
+
+@section('content')
+    <div id="nav2">
+        @component('station.menu')@endcomponent
+        @component('station.cachingShelf.menu')@endcomponent
+    </div>
+    <div class="container-fluid d-none" id="list">
+        @include('station.cachingShelf.list._table')
+        @include('station.cachingShelf.list._fillBox')
+    </div>
+@endsection
+
+@section('lastScript')
+    <script>
+        new Vue({
+            el: '#list',
+            data: {
+                stations: {!! $stations->toJson() !!}['data'],
+                selectTr: null,
+                currentEcho:null,
+                materialBoxCode: null,      // 料箱编码
+                currentStation: {           // 当前Station
+                    id: null,               // Station->id
+                    data: [[], [], []],     // 格口
+                },
+                boxClass: 'modal-sm',
+                broadcastName: null,
+                channelName: ".App\\Events\\BroadcastToStation",
+
+            },
+            mounted() {
+                this.initCacheShelfBox();
+                this.initModalBox();
+                $('#list').removeClass('d-none');
+            },
+            methods: {
+                /** 1初始化缓存架格口 */
+                initCacheShelfBox() {
+                    this.currentStation.data.forEach(function (item, index, self) {
+                        let boxRow = new Array(3);
+                        for (let i = 0; i < boxRow.length; i++) {
+                            let row =  2 - index + 1;
+                            let col =  2 - i + 1;
+                            let myIndex = index * 3 + i + 1;
+                            boxRow[i] = {x: index, y: i, row: row, col: col, code: null, index: myIndex};
+                        }
+                        self[index] = boxRow;
+                    });
+                },
+                /** 2初始化modal大小 */
+                initModalBox() {
+                    if (window.screen.width >= 520) this.boxClass = 'modal-sm';
+                    if (window.screen.width >= 720) this.boxClass = 'modal-md';
+                    if (window.screen.width >= 960) this.boxClass = 'modal-lg';
+                    if (window.screen.width >= 1200) this.boxClass = 'modal-xl';
+                },
+                /** 展示modal */
+                showFeedBox(station) {
+                    this.currentStation.id = station['id'];
+                    this.broadcastName = "{{config('database.redis.options.prefix')}}" + 'station-' + station['id'];
+                    this.initCacheGrid();
+                    $('#box').modal('show');
+                },
+                /** 清空格口号 */
+                clearCurrentStation() {
+                    this.currentStation.data.forEach(function (item, index, items) {
+                        items[index].forEach(function (item, index, self) {
+                            self[index]['code'] = null;
+                        })
+                    });
+                    this.$forceUpdate();
+                },
+                /** 初始化格口 */
+                initCacheGrid() {
+                    let url = '{{url('apiLocal/station/cacheShelf/getTasks')}}'+'/'+this.currentStation.id;
+                    window.tempTip.setIndex(1099);
+                    window.tempTip.setDuration(3000);
+                    window.axios.get(url).then(res => {
+                        if (res.data.data) {
+                            if (res.data.data.length === 0) return;
+                            for (let i = 0; i < res.data.data.length; i++) {
+                                if(res.data.data.length === i)break;
+                                let grid = res.data.data[i];
+                                let gridIndex = grid['grid_id'];
+                                let row = Math.round(gridIndex / 3);
+                                let col = gridIndex % 3 -1;
+                                let code = grid['material_box'] ? grid['material_box']['code'] : null;
+                                if(grid['status'] === 1) this.$set(this.currentStation.data[row][col], 'code', code);
+                            }
+                            this.$forceUpdate();
+                            return;
+                        }
+                        window.tempTip.show('获取缓存货架信息失败');
+                    }).catch(err => {
+                        window.tempTip.show('获取缓存货架信息异常:' + err);
+                    });
+                },
+                /** 扫码 1、料箱扫码 */
+                pushMaterialBox($e) {
+                    let code = this.materialBoxCode;
+                    if (code === null) {
+                        $('#material-box').focus();
+                    }
+                    // 自动排号
+                    this.pushBoxToStation(null,null,$e);
+                },
+                /** 扫码 2、填写九宫格 */
+                pushBoxToStation(x = null, y = null, $e = null) {
+                    let index = null;
+                    // 自动排号和自动发送
+                    // 选排
+                    if (x !== null && y !== null) {
+                        let code = $($e.target).val();
+                        index = this.currentStation.data[x][y]['index'];
+                        this.fillBox(code,index,x,y);
+                        return;
+                    }
+                    // 自动排号
+                    let arr = [];
+                    this.currentStation.data.forEach(function (items) {
+                        items.forEach(function (item) {
+                            if (item['code'] === null) {
+                                arr.push(item);
+                            }
+                        });
+                    })
+                    x = arr[0]['x'];
+                    y = arr[0]['y'];
+                    index = arr[0]['index'];
+                    this.fillBox(this.materialBoxCode,index,x,y);
+                },
+                /** 扫码 4:填充页面 */
+                fillBox(code,index,x,y){
+                    this.$set(this.currentStation.data[x][y], 'code', this.materialBoxCode);
+                    this.lightOn(this.currentStation.id,code,index,x,y);
+                    this.$forceUpdate();
+                },
+                /** 扫码 3、亮灯 */
+                lightOn(id,code,index,x,y) {
+                    let url = '{{url('apiLocal/station/cacheShelf/lightOn')}}';
+                    let data = {id:id, code:code, index:index, x:x, y:y};
+                    window.tempTip.setDuration(2000);
+                    window.tempTip.setIndex(1999);
+                    window.axios.post(url,data).then(res=>{
+                        if(res.data.success){
+                            window.tempTip.showSuccess(res.data.data);
+                            this.materialBoxCode = null;
+                            return ;
+                        }
+                        window.tempTip.show('亮灯异常:'+res.data.data);
+                    }).catch(err=>{
+                        window.tempTip.show(err);
+                    });
+                },
+                /** 校验是否存在 */
+                checkMaterialBoxCodeExist(code) {
+                    let bool = false;
+                    for (let x = 0; x < this.currentStation.data.length; x++) {
+                        if (!isArray(this.currentStation.data[x])) {
+                            continue;
+                        }
+                        if (this.currentStation.data[x].length > 0) {
+                            for (let y = 0; y < this.currentStation.data[y].length; y++) {
+                                if (this.currentStation.data[x][y]['code'] === code) return true;
+                            }
+                        }
+                    }
+                    return bool;
+                },
+                removeMaterialBox(x,y){
+                    this.$set(this.currentStation.data[x][y],'code',null);
+                },
+                /** 监听 【灭灯】 */
+                _listenBroadcast() {
+                    initEcho();
+                    if(this.currentEcho)this.currentEcho.disconnect();
+                    this.currentEcho = window.Echo.channel(this.broadcastName).listen(this.channelName, (msg) => {
+                        let json = JSON.parse(msg.json);
+                        if (!json || json.length === 0) return;
+                        this.removeMaterialBox(json['x'],json['y']);
+                    });
+                },
+            }
+        })
+    </script>
+@endsection
+

+ 9 - 0
resources/views/station/cachingShelf/menu.blade.php

@@ -0,0 +1,9 @@
+<div class="container-fluid nav3">
+    <div class="card">
+        <ul class="nav nav-pills">
+            <li class="nav-item">
+                <a target="station/cachingShelf/index" class="nav-link" href="{{url('station/cachingShelf/index')}}" :class="{active:isActive('cachingShelf',2)}">列表</a>
+            </li>
+        </ul>
+    </div>
+</div>

+ 1 - 1
resources/views/station/menu.blade.php

@@ -8,7 +8,7 @@
                 </li> @endcan
             @can('站管理-缓存架')
                 <li class="nav-item">
-                    <a target="station/cachingShelf/index" class="nav-link" href="{{url('station/monitor/index')}}" :class="{active:isActive('monitor',2)}">缓存架</a>
+                    <a target="station/cachingShelf/index" class="nav-link" href="{{url('station/cachingShelf/index')}}" :class="{active:isActive('cachingShelf',2)}">缓存架</a>
                 </li> @endcan
         </ul>
     </div>

+ 9 - 0
routes/apiLocal.php

@@ -181,3 +181,12 @@ Route::group(['prefix'=>'demand'],function(){
 });
 
 Route::get('/authority/get','AuthorityController@getAuthoritiesApi')->name('authority.getAuthoritiesApi');
+
+/** 缓存架 */
+Route::group(['prefix' => 'station'],function(){
+    Route::group(['prefix'=>'cacheShelf'],function(){
+        Route::post('pushTask','CacheShelfController@pushTaskApi')->name('station.cacheShelf.pushTaskApi');
+        Route::post('lightOn','CacheShelfController@lightOnApi')->name('station.cacheShelf.lightOnApi');
+        Route::get('getTasks/{id}','CacheShelfController@getTasksApi')->name('station.cacheShelf.getTasksApi');
+    });
+});

+ 3 - 0
routes/web.php

@@ -804,6 +804,9 @@ Route::group(['prefix'=>'station'],function(){
         Route::get('/index','StationController@monitorIndex');
         Route::get('/{station}','StationController@monitorShow');
     });
+    Route::group(['prefix'=>'cachingShelf'],function(){
+        Route::get('/index','CacheShelfController@index');
+    });
 });
 /** 控制台 */
 Route::group(['prefix'=>'control'],function () {

+ 49 - 0
tests/Services/CacheShelfService/GetTasksTest.php

@@ -0,0 +1,49 @@
+<?php
+
+
+namespace Tests\Services\CacheShelfService;
+
+use App\Services\CacheShelfService;
+use App\Station;
+use App\StationCacheShelfGrid;
+use Tests\TestCase;
+
+class GetTasksTest extends TestCase
+{
+    /** @var CacheShelfService $service */
+    protected $service;
+
+    protected $data = [];
+
+    protected function setup(): void
+    {
+        parent::setup();
+
+        $this->service = app(CacheShelfService::class);
+        $this->data['station'] = factory(Station::class)->create();
+        $collect = collect();
+        for ($i = 1; $i <= 8; $i++) {
+            $collect->push(StationCacheShelfGrid::query()->create([
+                'station_id' => $this->data['station']['id'] ?? '',
+                'grid_id' => $i,
+                'status' => 1,
+            ]));
+        }
+        $this->data['grids'] = $collect;
+    }
+
+    public function testGetTasks()
+    {
+        $grids = $this->service->getTasks($this->data['station']);
+        $this->assertEquals(count($grids), count($this->data['grids']));
+    }
+
+    protected function tearDown(): void
+    {
+        Station::query()->where('id', $this->data['station']['id'])->delete();
+        StationCacheShelfGrid::query()->where('station_id', $this->data['station']['id'])->delete();
+        parent::tearDown(); // TODO: Change the autogenerated stub
+    }
+
+
+}

+ 70 - 0
tests/Services/CacheShelfService/LightOffTaskTest.php

@@ -0,0 +1,70 @@
+<?php
+
+
+namespace Tests\Services\CacheShelfService;
+
+use App\MaterialBox;
+use App\Services\CacheShelfService;
+use App\Services\ForeignHaiRoboticsService;
+use App\Services\StationCacheShelfGridService;
+use App\Station;
+use App\StationCacheShelfGrid;
+use App\StationTaskMaterialBox;
+use App\Traits\TestMockSubServices;
+use Tests\TestCase;
+
+
+class LightOffTaskTest extends TestCase
+{
+    use TestMockSubServices;
+
+    /** @var CacheShelfService $service */
+    protected $service;
+    /** @var ForeignHaiRoboticsService $foreignHaiRoboticsService  */
+    protected $foreignHaiRoboticsService;
+
+    protected $data = [];
+
+    protected function setup(): void
+    {
+        parent::setup();
+        $this->service = $this->subMock([
+            'class' => CacheShelfService::class,
+            'subService' => [
+                'serviceName' => 'foreignHaiRoboticsService',
+                'class' => ForeignHaiRoboticsService::class,
+                'methods'=>[
+                    'controlHaiRobot' =>true
+                ]
+            ]
+        ]);
+        $row = 2;
+        $col = 1;
+        $gridIndex = ($row-1)*3 + (3-$col);
+        $this->data['station'] = factory(Station::class)->create();
+        $this->data['materialBox'] = factory(MaterialBox::class)->create();
+        $this->data['stationCacheShelfGrid'] = factory(StationCacheShelfGrid::class)
+            ->create(['station_id' => $this->data['station']['id'],'grid_id'=>$gridIndex,'material_box_id'=>$this->data['materialBox']['id']]);
+        $this->data['locCode'] = 'HAI'.$this->data['station']['code'].'-0'.$col.'-0'.$row;
+        $this->data['PTLAction'] = 0;
+    }
+
+    public function testLightOffTask()
+    {
+        $this->service->lightOffTask($this->data['locCode'],$this->data['PTLAction']);
+        $grid = StationCacheShelfGrid::query()->where('id',$this->data['stationCacheShelfGrid']['id'])->first();
+        $task = StationTaskMaterialBox::query()->where('station_id',$this->data['station']['id'])->where('material_box_id',$this->data['materialBox']['id'])->first();
+        $this->assertNotEmpty($task);
+        $this->assertEquals($task['status'],'处理中');
+        $this->assertEquals($grid['material_id'],null);
+    }
+
+    protected function tearDown(): void
+    {
+        Station::query()->where('id',$this->data['station']['id'])->delete();
+        StationCacheShelfGrid::query()->where('id',$this->data['stationCacheShelfGrid']['id'])->delete();
+        MaterialBox::query()->where('id',$this->data['materialBox']['id'])->delete();
+        StationTaskMaterialBox::query()->where('station_id',$this->data['station']['id'])->where('material_box_id',$this->data['materialBox'])->delete();
+        parent::tearDown(); // TODO: Change the autogenerated stub
+    }
+}

+ 88 - 0
tests/Services/CacheShelfService/PutBinToStoreTest.php

@@ -0,0 +1,88 @@
+<?php
+
+
+namespace Tests\Services\CacheShelfService;
+use App\MaterialBox;
+use App\Services\CacheShelfService;
+use App\Services\ForeignHaiRoboticsService;
+use App\Services\StationCacheShelfGridService;
+use App\Services\StationTaskMaterialBoxService;
+use App\Station;
+use App\StationCacheShelfGrid;
+use App\StationTaskMaterialBox;
+use App\Traits\TestMockSubServices;
+use Tests\TestCase;
+
+
+class PutBinToStoreTest extends TestCase
+{
+    use TestMockSubServices;
+    /** @var CacheShelfService $cacheShelfService */
+    protected $cacheShelfService;
+    protected $data =[];
+    protected function setup(): void
+    {
+        parent::setup(); // todo: change the autogenerated stub
+        $this->data['station'] = factory(Station::class)->create(['name' => 'test', 'code'=> 'test']);
+        $this->data['materialBox'] = factory(MaterialBox::class)->create();
+        $this->data['stationTaskMaterialBox'] = factory(StationTaskMaterialBox::class)->create([
+            'station_id' => $this->data['station']['id'],
+            'material_box_id' => $this->data['materialBox']['id'],
+            'status' => 1
+        ]);
+        $this->data['stationCacheShelfGrid'] = factory(StationCacheShelfGrid::class)->create([
+            'station_id'=>$this->data['station']['id'],
+            'material_box_id'=>$this->data['materialBox']['id'],
+            'status' => 1
+        ]);
+
+
+
+        $this->cacheShelfService = $this->subMock([
+            'class' => CacheShelfService::class,
+            'subService' => [
+//                [
+//                    'serviceName' => 'stationTaskMaterialBoxService',
+//                    'class' => StationTaskMaterialBoxService::class,
+//                    'methods' => [
+//                        'createByStationMaterialBox' => $this->data['stationTaskMaterialBox']
+//                    ]
+//                ],
+                [
+                    'serviceName' => 'stationCacheShelfGridService',
+                    'class' => StationCacheShelfGridService::class,
+                    'methods' => [
+                        'processGrid' => null
+                    ]
+                ],
+                [
+                    'serviceName' => 'foreignHaiRoboticsService',
+                    'class' => ForeignHaiRoboticsService::class,
+                    'methods' => [
+//                        'putBinToStore_fromCacheShelf' => true,
+                        'controlHaiRobot' => true
+                    ]
+                ]
+            ]
+        ]);
+    }
+
+    public function testPutBinToStore()
+    {
+        $bool = $this->cacheShelfService->putBinToStore($this->data['station'],$this->data['materialBox'],$this->data['stationCacheShelfGrid']);
+        $boxTask = StationTaskMaterialBox::query()->where('station_id',$this->data['station']['id'])->where('material_box_id',$this->data['materialBox']['id'])->first();
+        $this->assertTrue($bool);
+        $this->assertNotEmpty($boxTask);
+        $this->assertEquals($boxTask['status'],'待处理');
+    }
+
+    protected function tearDown(): void
+    {
+        Station::query()->where('id',$this->data['station']['id'])->delete();
+        MaterialBox::query()->where('id',$this->data['materialBox']['id'])->delete();
+        StationCacheShelfGrid::query()->where('id',$this->data['stationCacheShelfGrid']['id'])->delete();
+        StationTaskMaterialBox::query()->where('id',$this->data['stationTaskMaterialBox']['id'])->delete();
+        parent::tearDown();
+    }
+
+}

+ 62 - 0
tests/Services/ForeignHaiRoboticsService/PutBinToStoreFromCacheShelfTest.php

@@ -0,0 +1,62 @@
+<?php
+
+
+namespace Tests\Services\ForeignHaiRoboticsService;
+
+use App\Exceptions\ErrorException;
+use App\MaterialBox;
+use App\Services\ForeignHaiRoboticsService;
+use App\Services\StationService;
+use App\Station;
+use App\StationCacheShelfGrid;
+use App\StationTaskMaterialBox;
+use App\Traits\TestMockSubServices;
+use Tests\TestCase;
+
+class PutBinToStoreFromCacheShelfTest extends TestCase
+{
+    use TestMockSubServices;
+
+    /** @var ForeignHaiRoboticsService $service */
+    protected $service;
+    protected $data = [];
+
+    protected function setUp(): void
+    {
+        parent::setUp();
+        $this->service = $this->subMock([
+            'class' => ForeignHaiRoboticsService::class,
+            'subService' => [
+                'serviceName' => 'StationService',
+                'class' => StationService::class,
+                'methods' => [
+                    'controlHaiRobot' => true
+                ],
+            ]
+        ]);
+        $this->data['station'] = factory(Station::class)->create();
+        $this->data['materialBox'] = factory(MaterialBox::class)->create();
+        $this->data['grids'] = factory(StationCacheShelfGrid::class)->create();
+        $this->data['stationTaskMaterialBox'] = factory(StationTaskMaterialBox::class)
+            ->create(['station_id'=>$this->data['station']['id']]);
+        $this->data['station']->setRelation('grids',collect([$this->data['grids']]));
+        $this->data['stationTaskMaterialBox']->setRelation('station', $this->data['station']);
+        $this->data['stationTaskMaterialBox']->setRelation('materialBox', $this->data['materialBox']);
+    }
+
+    public function testSuccess1()
+    {
+        $success = $this->service->putBinToStore_fromCacheShelf($this->data['stationTaskMaterialBox']);
+        $this->assertEquals($success,true);
+    }
+
+
+    protected function tearDown(): void
+    {
+        Station::query()->where('id',$this->data['station']['id'])->delete();
+        StationCacheShelfGrid::query()->where('id',$this->data['grids']['id'])->delete();
+        MaterialBox::query()->where('id',$this->data['materialBox']['id'])->delete();
+        StationTaskMaterialBox::query()->where('id',$this->data['stationTaskMaterialBox']['id'])->delete();
+        parent::tearDown();
+    }
+}

+ 38 - 0
tests/Services/StationCacheShelfGrid/GetGridByCodeTest.php

@@ -0,0 +1,38 @@
+<?php
+
+
+namespace Tests\Services\StationCacheShelfGrid;
+
+use App\Services\StationCacheShelfGridService;
+use App\StationCacheShelfGrid;
+use Tests\TestCase;
+
+class GetGridByCodeTest extends TestCase
+{
+    protected $data = [];
+
+    protected function setup(): void
+    {
+        parent::setUp();
+        $this->data['stationCode'] = 'station001';
+        $this->data['grid'] = 6;
+        $this->data['x'] = 2;
+        $this->data['y'] = 3;
+        $this->data['code'] = 'HAI'.$this->data['stationCode'].'-0'.$this->data['y'].'-0'.$this->data['x'];
+
+    }
+
+    function testGetGridByCodeTest()
+    {
+        list($stationCode, $gridId, $x, $y) = StationCacheShelfGrid::getGridByCode($this->data['code']);
+        $this->assertEquals($stationCode,$this->data['stationCode']);
+        $this->assertEquals($gridId,$this->data['grid']);
+        $this->assertEquals($x,$this->data['x']);
+        $this->assertEquals($y,$this->data['y']);
+    }
+
+    protected function tearDown(): void
+    {
+        parent::tearDown();
+    }
+}

+ 39 - 0
tests/Services/StationCacheShelfGrid/GetLocationTest.php

@@ -0,0 +1,39 @@
+<?php
+
+
+namespace Tests\Services\StationCacheShelfGrid;
+
+use App\Station;
+use App\StationCacheShelfGrid;
+use Tests\TestCase;
+
+class GetLocationTest extends TestCase
+{
+
+    protected $data = [];
+
+    protected function setUp(): void
+    {
+        parent::setUp();
+        $row = 3;
+        $col = 2;
+        $this->data['grid_id'] = ($row-1)*3+$col;
+        $this->data['station'] = factory(Station::class)->create();
+        $this->data['grid'] = factory(StationCacheShelfGrid::class)->create(['station_id'=>$this->data['station']['id'],'grid_id'=>$this->data['grid_id']]);
+        $this->data['code'] = 'HAI'.$this->data['station']['code'].'-0'. (2 - $col + 1).'-0'.(2-$row+1);
+    }
+
+    function testGetLocation()
+    {
+        $location = StationCacheShelfGrid::getLocation($this->data['station'],$this->data['grid']);
+        $this->assertEquals($this->data['grid_id'],$this->data['grid']['grid_id']);
+        $this->assertEquals($this->data['code'],$location);
+    }
+
+    protected function tearDown(): void
+    {
+        Station::query()->where('id',$this->data['station']['id'])->delete();
+        StationCacheShelfGrid::query()->where('id',$this->data['grid']['id'])->delete();
+        parent::tearDown();
+    }
+}

+ 39 - 0
tests/Services/StationCacheShelfGridService/CancelTaskTest.php

@@ -0,0 +1,39 @@
+<?php
+
+
+namespace Tests\Services\StationCacheShelfGridService;
+
+use App\Services\StationCacheShelfGridService;
+use App\StationCacheShelfGrid;
+use App\Traits\TestMockSubServices;
+use Tests\TestCase;
+
+class CancelTaskTest extends TestCase
+{
+    use TestMockSubServices;
+    /** @var StationCacheShelfGridService $stationCacheShelfGridService */
+    protected $stationCacheShelfGridService;
+    protected $data =[];
+
+    protected function setup(): void
+    {
+        parent::setUp();
+        $this->stationCacheShelfGridService = app(StationCacheShelfGridService::class);
+        $this->data['grids'] = factory(StationCacheShelfGrid::class)->times(3)->create();
+
+    }
+
+    public function testCancelTask()
+    {
+        $this->stationCacheShelfGridService->cancelTask($this->data['grids']);
+        $grids = StationCacheShelfGrid::query()->whereIn('id',data_get($this->data['grids'],'*.id'))->whereNull('material_box_id')->where('status',0)->count();
+        $this->assertEquals($grids, count($this->data['grids']));
+    }
+
+    protected function tearDown(): void
+    {
+        StationCacheShelfGrid::query()->where('id',data_get($this->data['grids'],'*.id'))->delete();
+        parent::tearDown();
+    }
+
+}

+ 47 - 0
tests/Services/StationCacheShelfGridService/LightOffTest.php

@@ -0,0 +1,47 @@
+<?php
+
+
+namespace Tests\Services\StationCacheShelfGridService;
+use App\Services\StationCacheShelfGridService;
+use App\Station;
+use App\StationCacheShelfGrid;
+use Tests\TestCase;
+
+class LightOffTest extends TestCase
+{
+    /** @var StationCacheShelfGridService $stationCacheShelfGridService */
+    protected $stationCacheShelfGridService;
+    protected $data = [];
+
+    protected function setup(): void
+    {
+        parent::setUp();
+        $this->stationCacheShelfGridService = app(StationCacheShelfGridService::class);
+        $row = 2;
+        $col = 1;
+        $gridIndex = ($row-1)*3 + (3-$col);
+        $this->data['station'] = factory(Station::class)->create();
+        $this->data['stationCacheShelfGrid'] = factory(StationCacheShelfGrid::class)->create(['station_id' => $this->data['station']['id'],'grid_id'=>$gridIndex]);
+        $this->data['locCode'] = 'HAI'.$this->data['station']['code'].'-0'.$col.'-0'.$row;
+        $this->data['PTLAction'] = 0;
+    }
+
+    public function testLightOff()
+    {
+        $this->stationCacheShelfGridService->lightOff($this->data['locCode'],$this->data['PTLAction']);
+        $grid = StationCacheShelfGrid::query()->where('id',$this->data['stationCacheShelfGrid']['id'])->first();
+        $this->assertEquals($grid['id'],$this->data['stationCacheShelfGrid']['id']);
+        $this->assertEquals($grid['station']['id'],$this->data['stationCacheShelfGrid']['station_id']);
+        $this->assertEquals($grid['material_box_id'],null);
+        $this->assertEquals($grid['status'],0);
+
+    }
+
+    protected function tearDown(): void
+    {
+        Station::query()->where('id',$this->data['station']['id'])->delete();
+        StationCacheShelfGrid::query()->where('id',$this->data['stationCacheShelfGrid']['id'])->delete();
+        parent::tearDown(); // TODO: Change the autogenerated stub
+    }
+
+}

+ 42 - 0
tests/Services/StationCacheShelfGridService/ProcessGridTest.php

@@ -0,0 +1,42 @@
+<?php
+
+
+namespace Tests\Services\StationCacheShelfGridService;
+use App\MaterialBox;
+use App\Services\StationCacheShelfGridService;
+use App\Station;
+use App\StationCacheShelfGrid;
+use Tests\TestCase;
+
+
+class ProcessGridTest extends TestCase
+{
+    /** @var StationCacheShelfGridService $stationCacheShelfGridService */
+    protected $stationCacheShelfGridService;
+    protected $data = [];
+
+    protected function setup(): void
+    {
+        parent::setUp();
+        $this->stationCacheShelfGridService = app(StationCacheShelfGridService::class);
+        $this->data['station'] = factory(Station::class)->create();
+        $this->data['materialBox'] = factory(MaterialBox::class)->create();
+        $this->data['stationCacheShelfGrid'] = factory(StationCacheShelfGrid::class)->create();
+    }
+
+    public function test()
+    {
+        $this->stationCacheShelfGridService->processGrid($this->data['stationCacheShelfGrid'],$this->data['station'],$this->data['materialBox']);
+        $grid = StationCacheShelfGrid::query()->where('id',$this->data['stationCacheShelfGrid']['id'])->first();
+        $this->assertEquals($grid['id'],$this->data['stationCacheShelfGrid']['id']);
+        $this->assertEquals($grid['station_id'],$this->data['station']['id']);
+        $this->assertEquals($grid['material_box_id'],$this->data['materialBox']['id']);
+    }
+    protected function tearDown(): void
+    {
+        Station::query()->where('id',$this->data['station']['id'])->delete();
+        MaterialBox::query()->where('id',$this->data['materialBox']['id'])->delete();
+        StationCacheShelfGrid::query()->where('id',$this->data['stationCacheShelfGrid']['id'])->delete();
+        parent::tearDown();
+    }
+}

+ 39 - 0
tests/webApi/cacheShelf.http

@@ -0,0 +1,39 @@
+###
+# 亮灯
+POST http://bswas/api/station/cacheShelf/lightOn
+Content-Type: application/json
+
+{
+    "id": "",
+    "code": "",
+    "index": "",
+    "x": "x",
+    "y": "y"
+}
+
+###
+
+###
+# 拍灯任务
+POST http://bswas/api/station/cacheShelf/pushTask
+Content-Type: application/json
+
+{
+    "id": "",
+    "code": "",
+    "index": ""
+}
+
+###
+
+###
+#获取任务
+GET http://bswas/api/station/cacheShelf/getTasks
+Content-Type: application/json
+
+{
+    "id": ""
+}
+
+###
+