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

Merge branch 'yang' of ssh://47.103.131.176:10022/var/git/bswas into yang_temp

ajun 5 лет назад
Родитель
Сommit
e6ba1bd0a1
50 измененных файлов с 2769 добавлено и 278 удалено
  1. 45 0
      app/Console/Commands/SyncUserVisitMenuLogsCacheTask.php
  2. 1 0
      app/Console/Kernel.php
  3. 87 0
      app/Http/Controllers/ControlPanelController.php
  4. 10 262
      app/Http/Controllers/CustomerController.php
  5. 1 0
      app/Http/Kernel.php
  6. 24 0
      app/Http/Middleware/CheckActiveMenu.php
  7. 11 0
      app/KeyValues.php
  8. 14 0
      app/Menu.php
  9. 1 2
      app/Order.php
  10. 11 0
      app/OrderCountingRecord.php
  11. 25 0
      app/Providers/AppServiceProvider.php
  12. 264 0
      app/Services/CheckActiveMenuService.php
  13. 168 0
      app/Services/LaborReportsCountingRecordService.php
  14. 340 0
      app/Services/OrderCountingRecordService.php
  15. 4 2
      app/Services/OwnerService.php
  16. 57 0
      app/Services/RealtimePendingOrdersService.php
  17. 14 0
      app/UserVisitMenuLog.php
  18. 36 0
      database/migrations/2020_11_03_092648_create_menus.php
  19. 88 0
      database/migrations/2020_11_03_095519_seed_menus_level_1.php
  20. 481 0
      database/migrations/2020_11_03_095724_seed_menus_level_2.php
  21. 33 0
      database/migrations/2020_11_03_111159_create_user_visit_menu_logs.php
  22. 38 0
      database/migrations/2020_11_06_114606_create_order_counting_records_table.php
  23. 33 0
      database/migrations/2020_11_20_101212_create_key_values_table.php
  24. 53 0
      database/migrations/2020_11_20_101353_seed_key_values_table.php
  25. 14 1
      package-lock.json
  26. 1 0
      package.json
  27. 3 1
      resources/js/app.js
  28. 3 0
      resources/js/echarts.js
  29. 0 0
      resources/js/element-ui.js
  30. 0 0
      resources/sass/element-ui.css
  31. 508 0
      resources/views/control/panel.blade.php
  32. 1 1
      resources/views/layouts/app.blade.php
  33. 3 3
      resources/views/layouts/menu.blade.php
  34. 2 2
      resources/views/maintenance/log/index.blade.php
  35. 8 2
      routes/apiLocal.php
  36. 4 1
      routes/web.php
  37. 26 0
      tests/Services/CheckActiveMenuService/CheckActiveMenuServiceActiveMenusTest.php
  38. 24 0
      tests/Services/CheckActiveMenuService/CheckActiveMenuServiceSetTest.php
  39. 32 0
      tests/Services/CheckActiveMenuService/CheckActiveMenuSyncTest.php
  40. 39 0
      tests/Services/LaborReportsCountingRecordService/ByCacheTest.php
  41. 48 0
      tests/Services/LaborReportsCountingRecordService/GetTest.php
  42. 27 0
      tests/Services/LaborReportsCountingRecordService/UserGroupsCountTest.php
  43. 20 0
      tests/Services/OrderCountingRecordService/DateTestTest.php
  44. 30 0
      tests/Services/OrderCountingRecordService/OrderCountingRecordServiceGetTest.php
  45. 30 0
      tests/Services/OrderCountingRecordService/OrderCountingRecordServiceLogisticsCountingRecordsTest.php
  46. 31 0
      tests/Services/OrderCountingRecordService/OrderCountingRecordServiceOrderCountingRecordsTest.php
  47. 30 0
      tests/Services/OrderCountingRecordService/OrderCountingRecordServiceWarehouseCountingRecordsTest.php
  48. 22 0
      tests/Services/RealtimePendingOrdersService/RealtimePendingOrdersServiceTest.php
  49. 4 1
      webpack.mix.js
  50. 20 0
      yarn.lock

+ 45 - 0
app/Console/Commands/SyncUserVisitMenuLogsCacheTask.php

@@ -0,0 +1,45 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Services\LogService;
+use App\Services\CheckActiveMenuService;
+use App\UserVisitMenuLog;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Redis;
+
+class SyncUserVisitMenuLogsCacheTask extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'syncUserVisitMenuLogsCacheTask';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Command description';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     */
+    public function handle()
+    {
+        CheckActiveMenuService::sync();
+    }
+}

+ 1 - 0
app/Console/Kernel.php

@@ -19,6 +19,7 @@ class Kernel extends ConsoleKernel
         \App\Console\Commands\InventoryDailyLoggingOwner::class,
         \App\Console\Commands\WASSyncWMSOrderInformation::class,
         \App\Console\Commands\SyncLogCacheTask::class,
+        \App\Console\Commands\SyncUserVisitMenuLogsCacheTask::class,
         \App\Console\Commands\TestTemp::class,
     ];
 

+ 87 - 0
app/Http/Controllers/ControlPanelController.php

@@ -0,0 +1,87 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Services\CheckActiveMenuService;
+use App\Services\LaborReportsCountingRecordService;
+use App\Services\OrderCountingRecordService;
+use App\Services\RealtimePendingOrdersService;
+use Carbon\Carbon;
+use DebugBar\DataFormatter\DataFormatter;
+use Illuminate\Http\Request;
+
+class ControlPanelController extends Controller
+{
+    public function index()
+    {
+        /**
+         * @var CheckActiveMenuService $checkActiveMenuService
+         * @var RealtimePendingOrdersService $realtimePendingOrdersService
+         * @var OrderCountingRecordService $orderCountingRecords
+         * @var LaborReportsCountingRecordService $laborReportsCountingRecordService
+         */
+        $checkActiveMenuService = app(CheckActiveMenuService::class);
+        $menus = $checkActiveMenuService->activeMenus();
+        $realtimePendingOrdersService = app(RealtimePendingOrdersService::class);
+        $warehousesOrders = $realtimePendingOrdersService->warehousesOrders();
+        $orderCountingRecordService = app(OrderCountingRecordService::class);
+        //默认查询一个月的数据
+        $start = (new Carbon())->subMonth()->addDay()->toDateString();
+        $end = (new Carbon())->toDateString();
+        $orderCountingRecords = $orderCountingRecordService->orderCountingRecords($start, $end);
+        $logisticsCountingRecords = $orderCountingRecordService->logisticsCountingRecords($start, $end);
+        $warehouseCountingRecords = $orderCountingRecordService->warehouseCountingRecords($start, $end);
+
+        $laborReportsCountingRecordService = app(LaborReportsCountingRecordService::class);
+        $laborReportsCountingRecords = $laborReportsCountingRecordService->get($start, $end, '日');
+        $laborReportsUserGroupsCount = $laborReportsCountingRecordService->userGroupsCount($start, $end);
+        return view('control.panel', compact('menus', 'warehousesOrders', 'orderCountingRecords', 'logisticsCountingRecords', 'warehouseCountingRecords', 'laborReportsCountingRecords','laborReportsUserGroupsCount'));
+    }
+
+    public function orderCountingRecordsApi(Request $request)
+    {
+        $orderCountingRecordService = app(OrderCountingRecordService::class);
+        $start = $request->start;
+        $end = $request->end;
+        $unit = $request->unit;
+        $orderCountingRecords = $orderCountingRecordService->orderCountingRecords($start, $end, null, $unit, null);
+        return compact('orderCountingRecords');
+    }
+
+    public function logisticsCountingRecordsApi(Request $request)
+    {
+        $orderCountingRecordService = app(OrderCountingRecordService::class);
+        $start = $request->start;
+        $end = $request->end;
+        $logisticsCountingRecords = $orderCountingRecordService->logisticsCountingRecords($start, $end);
+        return compact('logisticsCountingRecords');
+    }
+
+    public function warehouseCountingRecordsApi(Request $request)
+    {
+        $orderCountingRecordService = app(OrderCountingRecordService::class);
+        $start = $request->start;
+        $end = $request->end;
+        $warehouseCountingRecords = $orderCountingRecordService->warehouseCountingRecords($start, $end);
+        return compact('warehouseCountingRecords');
+    }
+
+    public function laborReportsCountingRecordApi(Request $request)
+    {
+        $laborReportsCountingRecordService = app(LaborReportsCountingRecordService::class);
+        $start = $request->start;
+        $end = $request->end;
+        $unit = $request->unit;
+        $laborReportsCountingRecords = $laborReportsCountingRecordService->get($start, $end, $unit);
+        return compact('laborReportsCountingRecords');
+    }
+
+    public function laborReportsUserGroupsCountApi(Request $request)
+    {
+        $laborReportsCountingRecordService = app(LaborReportsCountingRecordService::class);
+        $start = $request->start;
+        $end = $request->end;
+        $laborReportsUserGroupsCount = $laborReportsCountingRecordService->userGroupsCount($start, $end);
+        return compact('laborReportsUserGroupsCount');
+    }
+}

+ 10 - 262
app/Http/Controllers/CustomerController.php

@@ -11,6 +11,7 @@ use Exception;
 use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
+use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Gate;
 use Illuminate\Support\Facades\Http;
@@ -141,284 +142,31 @@ class CustomerController extends Controller
             "Content-type"=>"application/octet-stream",
             "Content-Disposition"=>"attachment; filename=客户报表-".date('ymdHis').'.xlsx',
         ]);
+        $customers = $service->get(Auth::user(),['customer_id'=>true],['customer']);
+        return response()->view('customer.project.index');
     }
 
     public function projectCreate()
     {
         if(!Gate::allows('客户管理-项目-录入')){ return redirect('denied');  }
-        $customers = app('CustomerService')->getSelection();
-        $ownerGroups = app('UserOwnerGroupService')->getSelection();
-        $storagePriceModels = app('OwnerStoragePriceModelService')->getSelection(["id","counting_type","using_type","minimum_area","price","unit_id"],["unit"=>function($query){$query->select("id","name");}]);
-        $owner = null;
-        return response()->view('customer.project.create',compact("customers","ownerGroups","storagePriceModels","owner"));
+        return response()->view('customer.project.create');
     }
 
-    public function seekOwner(Request $request)
-    {
-        $params = $request->input();
-        $params["customer_id"] = true;
-        $owner = app('OwnerService')->first($params,["customer_id"=>"null"]);
-        if ($owner)return ["success"=>true,"data"=>$owner];
-        else return ["success"=>false];
-    }
-
-    public function projectStore(Request $request)
-    {
-        if(!Gate::allows('客户管理-项目-录入')){ return redirect('denied');  }
-        $this->validator($request->input())->validate();
-        $params = $request->input();
-        if ($params["id"]){
-            /** @var Owner $owner */
-            $owner = app('OwnerService')->find($params["id"]);
-            app('OwnerService')->update($owner,[
-                "customer_id"           => $params["customer_id"],
-                "tax_rate"              => $params["tax_rate"],
-                "contract_number"       => $params["contract_number"],
-                "salesman"              => $params["salesman"],
-                "linkman"               => $params["linkman"],
-                "phone_number"          => $params["phone_number"],
-                "user_owner_group_id"   => $params["owner_group_id"],
-                "waring_line_on"        => $params["waring_line_on"],
-                "description"           => $params["description"],
-            ],[
-                "ownerStoragePriceModels" => explode(',',$params["owner_storage_price_model_id"])
-            ]);
-            $msg = "成功更新“".$owner->name."”的信息!";
-        }else{
-            $owner = app('OwnerService')->create([
-                "name"                  => $params["name"],
-                "code"                  => $params["code"],
-                "customer_id"           => $params["customer_id"],
-                "tax_rate"              => $params["tax_rate"],
-                "contract_number"       => $params["contract_number"],
-                "salesman"              => $params["salesman"],
-                "linkman"               => $params["linkman"],
-                "phone_number"          => $params["phone_number"],
-                "user_owner_group_id"   => $params["owner_group_id"],
-                "waring_line_on"        => $params["waring_line_on"],
-                "description"           => $params["description"],
-            ],[
-                "ownerStoragePriceModels" => explode(',',$params["owner_storage_price_model_id"])
-            ]);
-            $msg = "成功创建“".$owner->name."”项目!";
-        }
-        return response()->redirectTo('customer/project/index')->with('successTip',$msg);
-    }
-
-    //获取货主下所有相关计费模型
-    public function getOwnerPriceModel(Request $request)
-    {
-        $owner = new Owner();
-        $owner->id = $request->id;
-        $owner->load(["ownerPriceOperations","ownerPriceExpresses","ownerPriceLogistics","ownerPriceDirectLogistics"]);
-        return ["success"=>true,"data"=>["ownerPriceOperations"=>$owner->ownerPriceOperations,
-            "ownerPriceExpresses"=>$owner->ownerPriceExpresses,
-            "ownerPriceLogistics"=>$owner->ownerPriceLogistics,
-            "ownerPriceDirectLogistics"=>$owner->ownerPriceDirectLogistics]];
-    }
-
-    public function projectEdit($id)
-    {
-        if(!Gate::allows('客户管理-项目-编辑')){ return redirect('denied');  }
-        /** @var Owner $owner */
-        $owner = app('OwnerService')->find($id);
-        $owner->owner_storage_price_model_id = $owner->getOwnerStoragePriceModelIds();
-        $customers = app('CustomerService')->getSelection();
-        $ownerGroups = app('UserOwnerGroupService')->getSelection();
-        $storagePriceModels = app('OwnerStoragePriceModelService')->getSelection(["id","counting_type","using_type","minimum_area","price","unit_id"],["unit"=>function($query){$query->select("id","name");}]);
-        return response()->view('customer.project.create',compact("customers","ownerGroups","storagePriceModels",'owner'));
-    }
-
-    public function projectArea(Request $request)
+    public function projectArea()
     {
         if(!Gate::allows('客户管理-项目-面积')){ return redirect('denied');  }
-        $areas = app('OwnerAreaReportService')->paginate($request->input(),["owner"=>function($query){$query->with(["customer","ownerStoragePriceModels"]);}]);
-        $ownerGroups = app('UserOwnerGroupService')->getSelection();
-        $customers = app('CustomerService')->getSelection();
-        $owners = app('OwnerService')->getSelection();
-        $params = $request->input();
-        return response()->view('customer.project.area',compact("areas","ownerGroups","customers","owners","params"));
+        return response()->view('customer.project.area');
     }
 
-    public function updateArea(Request $request)
-    {
-        if(!Gate::allows('客户管理-项目-面积-编辑')){ return ["success"=>false,'data'=>"无权操作!"];  }
-        if (!($request->id ?? false) || !($request->area ?? false)) return ["success"=>false,'data'=>"传递错误!"];
-        $values = $request->area ?? null;
-        if (!$values)return ["success"=>true,"data"=>$values];
-        foreach ($values as $column=>$value){
-            if ($value && (!is_numeric($value) || $value<0))return ["success"=>false,'data'=>$column."非数字或小于0!"];
-        }
-        $accounting_area = ((int)$values["area_on_tray"]*205) + ((int)$values["area_on_half_tray"]*1.8) + ((int)$values["area_on_flat"]*1.3);
-        $values["accounting_area"] = $accounting_area;
-        if (app('OwnerAreaReportService')->update(["id"=>$request->id],$values))
-            return ["success"=>true,"data"=>$values];
-        return ["success"=>false,"data"=>"未知错误!"];
-    }
-
-    public function projectAreaExport(Request $request)
-    {
-        if(!Gate::allows('客户管理-项目-面积')){ return redirect('denied');  }
-        $params = $request->input();
-        if ($request->checkAllSign)unset($params['checkAllSign']);
-        else $params = ["id"=>$request->data];
-        /** @var OwnerAreaReportService $serves */
-        $serves = app('OwnerAreaReportService');
-        $areas = $serves->get($params,["owner"=>function($query){$query->with(["customer","ownerStoragePriceModels","userOwnerGroup"]);}]);
-
-        $column = ["状态","项目组","客户","子项目","结算月","录入时间","用仓类型","货物整托","货物半托","平面区面积","结算面积"];
-        $list = [];
-        foreach ($areas as $area){
-            $list[] = [
-                $area->status,
-                $area->owner ? ($area->owner->userOwnerGroup ? $area->owner->userOwnerGroup->name : '') : '',
-                $area->owner ? ($area->owner->customer ? $area->owner->customer->name : '') : '',
-                $area->owner ? $area->owner->name : '',
-                $area->counting_month,
-                $area->updated_at,
-                $area->owner ? implode(",",array_unique(array_column(($area->owner->ownerStoragePriceModels)->toArray(),"using_type"))) : '',
-                $area->area_on_tray,
-                $area->area_on_half_tray,
-                $area->area_on_flat,
-                $area->accounting_area,
-            ];
-        }
-
-        $post = Http::post(config('go.export.url'),['type'=>'base','data'=>json_encode(["row"=>$column,"list"=>$list],JSON_UNESCAPED_UNICODE)]);
-        if ($post->status() == 500){
-            throw new Exception($post->header("Msg"));
-        }
-        return response($post,200, [
-            "Content-type"=>"application/octet-stream",
-            "Content-Disposition"=>"attachment; filename=项目面积报表-".date('ymdHis').'.xlsx',
-        ]);
-    }
-
-    public function financeInstantBill(Request $request)
+    public function financeInstantBill()
     {
         if(!Gate::allows('客户管理-财务-即时账单')){ return redirect('denied');  }
-        $params = $request->input();
-        $shops = app('ShopService')->getSelection();
-        $customers = app('CustomerService')->getSelection();
-        $owners = app('OwnerService')->getSelection();
-        $details = app('OwnerFeeDetailService')->paginate($params,["owner"=>function($query){$query->with("customer");},"shop","processMethod","logistic"]);
-        return response()->view('customer.finance.instantBill',compact("details","params","shops","customers","owners"));
+        return response()->view('customer.finance.instantBill');
     }
 
-    public function financeInstantBillExport(Request $request)
-    {
-        if(!Gate::allows('客户管理-财务-即时账单')){ return redirect('denied');  }
-        $params = $request->input();
-        if ($request->checkAllSign)unset($params['checkAllSign']);
-        else $params = ["id"=>$request->data];
-        $sql = app('OwnerFeeDetailService')->getSql($params);
-
-        $row = ["客户", "项目", "作业时间", "类型","店铺", "单号(发/收/退/提)", "收件人", "收件人电话", "商品数量",
-            "物流/快递单号", "体积", "重量", "承运商", "操作费", "物流费", "合计"];
-        $column = ["customer_name", "owner_name", "worked_at", "type","shop_name", "operation_bill", "consignee_name", "consignee_phone", "commodity_amount",
-            "logistic_bill", "volume", "weight", "logistic_name", "work_fee", "logistic_fee", "total"];
-        $rule = ["work_fee"=>"mysqlDate"];
-
-        $post = Http::post(config('go.export.url'),['type'=>'unify','sql'=>$sql, 'connection'=>'mysql',
-            'row'=>json_encode($row,JSON_UNESCAPED_UNICODE), 'column'=>json_encode($column), 'rule'=>json_encode($rule)]);
-        if ($post->status() == 500){
-            throw new Exception($post->header("Msg"));
-        }
-        return response($post,200, [
-            "Content-type"=>"application/octet-stream",
-            "Content-Disposition"=>"attachment; filename=即时账单记录-".date('ymdHis').'.xlsx',
-        ]);
-    }
-
-    public function financeBillConfirmation(Request $request)
-    {
-        if(!Gate::allows('客户管理-财务-账单确认')){ return redirect('denied');  }
-        $params = $request->input();
-        $ownerGroups = app('UserOwnerGroupService')->getSelection();
-        $customers = app('CustomerService')->getSelection();
-        $owners = app('OwnerService')->getSelection();
-        $bills = app('OwnerBillReportService')->paginate($params,["owner"=>function($query){
-            /** @var Builder $query */
-            $query->with(["customer","userOwnerGroup"]);
-        }]);
-        return response()->view('customer.finance.billConfirmation',compact("params","owners","ownerGroups","customers","bills"));
-    }
-
-    public function financeBillConfirmationExport(Request $request)
+    public function financeBillConfirmation()
     {
         if(!Gate::allows('客户管理-财务-账单确认')){ return redirect('denied');  }
-        $params = $request->input();
-        if ($request->checkAllSign)unset($params['checkAllSign']);
-        else $params = ["id"=>$request->data];
-        /** @var OwnerBillReportService $serves */
-        $serves = app('OwnerBillReportService');
-        $bills = $serves->get($params,["owner"=>function($query){
-            /** @var Builder $query */
-            $query->with(["customer","userOwnerGroup"]);
-        }]);
-
-        $column = ["项目小组","客户","子项目","结算月","录入日期","原始账单金额","确认账单金额","差额","状态"];
-        $list = [];
-        foreach ($bills as $bill){
-            $list[] = [
-                $bill->owner ? ($bill->owner->userOwnerGroup ? $bill->owner->userOwnerGroup->name : '') : '',
-                $bill->owner ? ($bill->owner->customer ? $bill->owner->customer->name : '') : '',
-                $bill->owner ? $bill->owner->name : '',
-                $bill->counting_month,
-                $bill->updated_at,
-                $bill->initial_fee,
-                $bill->confirm_fee,
-                $bill->difference,
-                $bill->confirmed == '是' ? '已确认' : '未确认',
-            ];
-        }
-
-        $post = Http::post(config('go.export.url'),['type'=>'base','data'=>json_encode(["row"=>$column,"list"=>$list],JSON_UNESCAPED_UNICODE)]);
-        if ($post->status() == 500){
-            throw new Exception($post->header("Msg"));
-        }
-        return response($post,200, [
-            "Content-type"=>"application/octet-stream",
-            "Content-Disposition"=>"attachment; filename=客户账单报表-".date('ymdHis').'.xlsx',
-        ]);
-    }
-
-    public function updateBillReport(Request $request)
-    {
-        if(!Gate::allows('客户管理-财务-账单确认-编辑')){ return ["success"=>false,'data'=>"无权操作!"];  }
-        if (!$request->confirm_fee || !is_numeric($request->confirm_fee) || $request->confirm_fee<0)return ["success"=>false,"data"=>"非法金额参数"];
-        $date = date('Y-m-d H:i:s');
-        app('OwnerBillReportService')->update(["id"=>$request->id],["confirm_fee"=>$request->confirm_fee,"difference"=>DB::raw($request->confirm_fee.'- initial_fee'),"updated_at"=>$date]);
-        return ["success"=>true,"data"=>$date];
-    }
-
-    public function billConfirm(Request $request)
-    {
-        if(!Gate::allows('客户管理-财务-账单确认-完结')){ return ["success"=>false,'data'=>"无权操作!"];  }
-        if (!($request->id ?? false))return["success"=>false,"data"=>"非法参数"];
-        app('OwnerBillReportService')->update(["id"=>$request->id],["confirmed"=>"是"]);
-        return ["success"=>true];
-    }
-
-    private function validator(array $params){
-        $id = $params['id'] ?? null;
-        $validator=Validator::make($params,[
-            'id' => ['required_without_all:code,name'],
-            'code'=>['required','max:50',$id ? "unique:owners,code,$id":'unique:owners,code'],
-            'name'=>['required','max:50'],
-            'customer_id'=>['required'],
-            'owner_group_id'=>['required'],
-            'tax_rate' => ['required','numeric'],
-        ],[
-            'required'=>':attribute 为必填项',
-            'unique'=>':attribute 已存在',
-        ],[
-            'code'=>'项目代码',
-            'name'=>'项目名称',
-            'customer_id'=>'客户',
-            'owner_group_id'=>'工作组',
-            'tax_rate' => '税率'
-        ]);
-        return $validator;
+        return response()->view('customer.finance.billConfirmation');
     }
 }

+ 1 - 0
app/Http/Kernel.php

@@ -20,6 +20,7 @@ class Kernel extends HttpKernel
         \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
         \App\Http\Middleware\TrustProxies::class,
         \App\Http\Middleware\DecodingRequest::class,
+        \App\Http\Middleware\CheckActiveMenu::class,
     ];
 
     /**

+ 24 - 0
app/Http/Middleware/CheckActiveMenu.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use App\Services\CheckActiveMenuService;
+use Closure;
+use Illuminate\Http\Request;
+
+class CheckActiveMenu
+{
+    /**
+     * Handle an incoming request.
+     *
+     * @param Request $request
+     * @param \Closure $next
+     * @return mixed
+     */
+    public function handle(Request $request, Closure $next)
+    {
+        $response = $next($request);
+        CheckActiveMenuService::set($request);
+        return $response;
+    }
+}

+ 11 - 0
app/KeyValues.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+class KeyValues extends Model
+{
+    //
+    protected $fillable = ['key', 'value',];
+}

+ 14 - 0
app/Menu.php

@@ -0,0 +1,14 @@
+<?php
+
+namespace App;
+
+use App\Traits\ModelTimeFormat;
+use Illuminate\Database\Eloquent\Model;
+
+class Menu extends Model
+{
+    use ModelTimeFormat;
+    protected $fillable=[
+        'name','level', 'parent_id', 'route','sequence',
+    ];
+}

+ 1 - 2
app/Order.php

@@ -60,8 +60,7 @@ class Order extends Model
 
     public function warehouse()
     {
-        return $this->hasOne(Warehouse::class, 'id', 'owner_id');
-
+        return $this->belongsTo(Warehouse::class);
     }
     public function orderCommodities(){
         return $this->hasMany('App\OrderCommodity','order_id','id');

+ 11 - 0
app/OrderCountingRecord.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+class OrderCountingRecord extends Model
+{
+    //
+    protected $fillable = ['owner_id','shop_id' ,'warehouse_id' ,'logistic_id' ,'date_target' ,'counting_unit' ,'amount'];
+}

+ 25 - 0
app/Providers/AppServiceProvider.php

@@ -15,11 +15,13 @@ use App\Services\DepositoryService;
 use App\Services\FeatureService;
 use App\Services\InventoryAccountMissionService;
 use App\Services\InventoryCompareService;
+use App\Services\LaborReportsCountingRecordService;
 use App\Services\LogService;
 use App\Services\OracleBasCustomerService;
 use App\Services\OracleBasSkuService;
 use App\Services\OracleDocAsnDetailService;
 use App\Services\OracleDOCOrderHeaderService;
+use App\Services\OrderCountingRecordService;
 use App\Services\OracleDocAsnHerderService;
 use App\Services\OrderIssuePerformanceService;
 use App\Services\AllInventoryService;
@@ -50,6 +52,7 @@ use App\Services\ProcessesContentService;
 use App\Services\ProcessMethodService;
 use App\Services\ProcessService;
 use App\Services\ProcessStatisticService;
+use App\Services\RealtimePendingOrdersService;
 use App\Services\RejectedBillItemService;
 use App\Services\RejectedBillService;
 use App\Services\ShopService;
@@ -58,6 +61,7 @@ use App\Services\StoreCheckingReceiveItemService;
 use App\Services\StoreCheckingReceiveService;
 use App\Services\StoreItemService;
 use App\Services\StoreService;
+use App\Services\CheckActiveMenuService;
 use App\Services\UnitService;
 use App\Services\UserOwnerGroupService;
 use App\Services\UserService;
@@ -164,6 +168,10 @@ class AppServiceProvider extends ServiceProvider
         $this->loadingOrderModuleService();
         $this->loadingBasedModuleService();
         $this->loadingRejectedModuleService();
+        $this->loadingCheckActiveMenuService();
+        $this->loadingRealtimePendingOrdersService();
+        $this->loadingOrderCountingRecordService();
+        $this->loadingLaborReportsCountingRecordService();
     }
 
     private function loadingOrderModuleService(){
@@ -198,4 +206,21 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('RejectedService',RejectedService::class);
     }
 
+    private function loadingCheckActiveMenuService()
+    {
+        app()->singleton('CheckActiveMenuService',CheckActiveMenuService::class);
+    }
+
+    private function loadingRealtimePendingOrdersService()
+    {
+        app()->singleton('RealtimePendingOrdersService',RealtimePendingOrdersService::class);
+    }
+    private function loadingOrderCountingRecordService()
+    {
+        app()->singleton('OrderCountingRecordService',OrderCountingRecordService::class);
+    }
+    private function loadingLaborReportsCountingRecordService()
+    {
+        app()->singleton('LaborReportsCountingRecordService',LaborReportsCountingRecordService::class);
+    }
 }

+ 264 - 0
app/Services/CheckActiveMenuService.php

@@ -0,0 +1,264 @@
+<?php
+
+
+namespace App\Services;
+
+
+use App\Menu;
+use App\UserVisitMenuLog;
+use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Http\Request;
+use Illuminate\Support\Collection;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Redis;
+
+class CheckActiveMenuService
+{
+    /**
+     *同步数据到数据库并且将L1转移到L2
+     */
+    public static function sync()
+
+    {
+        try {
+            self::syncToDB();
+            self::switchL1ToL2();
+        } catch (\Exception $e) {
+            // TODO 同步异常的处理策略
+            return;
+        }
+    }
+
+    /**
+     * 将用户菜单点击事件保存
+     * @param Request $request
+     */
+    public static function set(Request $request): void
+    {
+        // 请求方法为get
+        if ($request->method() == 'GET') {
+            $menu = Menu::query()->where('route', substr($request->getRequestUri(), 1))->first();
+            if ($menu) {
+                //redis正常保存在缓存中
+                $date = date('Y-m-d H:i:s');
+                $userVisitMenuLog = new UserVisitMenuLog([
+                    'user_id' => Auth::user()['id'],
+                    'menu_id' => $menu->id,
+                    'created_at' => $date,
+                    'updated_at' => $date,
+                ]);
+                try {
+                    //菜单点击入缓存
+                    Redis::LPUSH('UserVisitMenuLogsL1', $userVisitMenuLog);
+                } catch (\Exception $e) {
+                    // TODO 缓存异常的处理策略
+                    $userVisitMenuLog->save();
+                }
+            }
+        }
+    }
+
+    /**
+     * 获取活跃菜单
+     * @return Builder|Builder[]|\Illuminate\Database\Eloquent\Collection|Model|null
+     */
+    public static function activeMenus()
+    {
+        $user_id = self::getUserId();
+        try {
+            Redis::LLEN('UserVisitMenuLogsL1');
+            if (Redis::LLEN('UserVisitMenuLogsL1') + Redis::LLEN('UserVisitMenuLogsL2') > 0) {
+                //缓存中有数据
+                return self::getFromRedis($user_id);
+            }else{
+                return self::getFromDB($user_id);
+            }
+        } catch (\Exception $e) {
+            // TODO 缓存异常的处理策略
+            return self::getFromDB($user_id);
+        }
+    }
+
+    /**
+     * 将缓存中的数据拿出保存,转换为数组,方便数据库保存
+     * @param $userVisitMenuLogsStr
+     * @return array
+     */
+    public static function redisListToArray($userVisitMenuLogsStr): array
+    {
+        $userVisitMenuLogsArr = [];
+        foreach ($userVisitMenuLogsStr as $userVisitMenuLog) {
+            $userVisitMenuLogObj = json_decode($userVisitMenuLog);
+            $userVisitMenuLogsArr[] = [
+                'user_id' => $userVisitMenuLogObj->user_id,
+                'menu_id' => $userVisitMenuLogObj->menu_id,
+                'created_at' => $userVisitMenuLogObj->created_at,
+                'updated_at' => $userVisitMenuLogObj->updated_at,
+            ];
+        }
+        return $userVisitMenuLogsArr;
+    }
+
+    /**
+     *将L1缓存转移到L2
+     */
+    public static function switchL1ToL2(): void
+    {
+        while (Redis::LLEN('UserVisitMenuLogsL1') > 0) {
+            Redis::LPUSH('UserVisitMenuLogsL2', Redis::LPOP('UserVisitMenuLogsL1'));
+        }
+    }
+
+    /**
+     * @return int
+     */
+    public static function getUserId(): int
+    {
+        $user_id = 1;
+        if (Auth::user()) {
+            $user_id = Auth::user()->id;
+        }
+        return $user_id;
+    }
+
+    /**
+     * 从数据库获取活跃菜单
+     * @param $user_id
+     * @return Builder|Builder[]|\Illuminate\Database\Eloquent\Collection|Model|null
+     */
+    public static function getFromDB($user_id)
+    {
+        return self::getMenusAndSort(self::getMenuIdsFromDB($user_id));
+    }
+
+    /**
+     * 从缓存获取活跃菜单
+     * @param $user_id
+     * @return Builder|Builder[]|\Illuminate\Database\Eloquent\Collection|Model|null
+     */
+    public static function getFromRedis($user_id)
+    {
+        return self::getMenusAndSort(self::getMenuIdsFromRedis($user_id));
+    }
+
+    /**
+     * 获取活跃菜单并按照活跃度排序
+     * @param Collection $menuIds
+     * @return Builder|Builder[]|\Illuminate\Database\Eloquent\Collection|Model|Collection|\Tightenco\Collect\Support\Collection|null
+     */
+    public static function getMenusAndSort(Collection $menuIds)
+    {
+        return self::buildResult(self::getMenusAndSortByActive($menuIds));
+    }
+
+    /**
+     * @param $user_id
+     * @return Collection|\Tightenco\Collect\Support\Collection
+     */
+    public static function getMenuIdsFromRedis($user_id)
+    {
+        return collect(array_merge(self::redisListToArray(Redis::LRANGE('UserVisitMenuLogsL1', 0, -1)), self::redisListToArray(Redis::LRANGE('UserVisitMenuLogsL2', 0, -1))))
+            //从缓存中查找全部用户的活跃菜单数据,合并L1,L2
+            ->filter(function ($item) use ($user_id) {
+                return $user_id === $item['user_id'];
+            })
+            //根据user_id筛选
+            ->groupBy('menu_id')
+            //根据menu_id分组
+            ->sortByDesc(function ($item) {
+                return $item->count();
+            })
+            //根据分组结果的二级列表降序排列
+//            ->forPage(0, 5)
+            //取前数量最高的五条
+            ->keys();
+        //只获取对应的菜单Id
+    }
+
+    /**
+     * @param $user_id
+     * @return Builder[]|\Illuminate\Database\Eloquent\Collection|Collection
+     */
+    public static function getMenuIdsFromDB($user_id)
+    {
+        return UserVisitMenuLog::query()
+            ->selectRaw('menu_id')
+            ->where('user_id', $user_id)
+            ->groupBy('menu_id')
+            ->get()->sortByDesc(function ($item) {
+                return $item->count();
+            })
+//            ->forPage(0, 5)
+            ->map(function ($item) {
+                return $item->menu_id;
+            });
+    }
+
+    public static function syncToDB(): void
+    {
+        UserVisitMenuLog::query()->insert(self::redisListToArray(Redis::LRANGE('UserVisitMenuLogsL1', 0, -1)));
+    }
+
+    /**
+     * 将排好序的菜单集合构造为一级菜单嵌套二级菜单的形式
+     * @param $menus
+     * @return Collection|\Tightenco\Collect\Support\Collection
+     */
+    public static function buildResult($menus)
+    {
+        $result = collect([]);
+        foreach ($menus as $menu) {
+            switch ($menu->level) {
+                case 1:
+                    if (!$result->where('id', $menu->parent_id)->first()) {
+                        //结果集中尚未包含当前菜单,添加
+                        $result->add($menu);
+                    }
+                    break;
+                case 2:
+                    self::setToParent($result, $menu);
+                    //查找到对应子菜单的父菜单,并将其放入到父菜单的集合中
+                    break;
+                default:
+                    break;
+            }
+        }
+        return $result;
+    }
+
+    /**
+     * 查找到对应子菜单的父菜单,并将其放入到父菜单的集合中
+     * @param $data
+     * @param $menu
+     */
+    public static function setToParent($data, $menu): void
+    {
+        //二级菜单
+        $firstLevelMenu = $data->where('id', $menu->parent_id)->first();
+        if (!$firstLevelMenu) {
+            //当前集合中不存在该一级菜单,从数据库中获取,并将其放入集合中
+            $firstLevelMenu = Menu::query()->where('id', $menu->parent_id)->first();
+            $data->push($firstLevelMenu);
+        }
+        $secondLevelMenu = $firstLevelMenu->secondLevelMenu ?? collect();
+        $secondLevelMenu->push($menu);
+        $firstLevelMenu->secondLevelMenu = $secondLevelMenu;
+    }
+
+    /**
+     * 根据菜单Id查询菜单,并安装点击频率排序
+     * @param Collection $arr
+     * @return Builder|Builder[]|\Illuminate\Database\Eloquent\Collection|Model|null
+     */
+    public static function getMenusAndSortByActive(Collection $arr)
+    {
+        return Menu::query()
+            ->find($arr)
+            //根据菜单Id查询
+            ->sortBy(function ($item) use ($arr) {
+                return $arr->search($item->id);
+                //将查询结果按照上面拍好的顺序重新排列
+            });
+    }
+}

+ 168 - 0
app/Services/LaborReportsCountingRecordService.php

@@ -0,0 +1,168 @@
+<?php
+
+
+namespace App\Services;
+
+
+use App\LaborReport;
+use Carbon\Carbon;
+use DateTime;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Str;
+use Ramsey\Uuid\Type\Integer;
+
+class LaborReportsCountingRecordService
+{
+    public function userGroupsCount($start, $end)
+    {
+        $resultByCache = Cache::remember('userGroupsCount_' . $start . '_' . $end, 600, function () use ($start, $end) {
+            return LaborReport::query()->selectRaw('user_workgroup_id,count(user_workgroup_id) amount')
+                ->with('userWorkgroup','laborReportStatus')
+                ->whereDate('created_at', '>=', $start)
+                ->whereDate('created_at', '<', $end)
+                ->groupBy('user_workgroup_id')->get();
+        });
+
+        $resultByCache = $resultByCache->filter(function ($item) {
+            return $item->amount != 0;
+        });
+
+        $result = collect();
+        $resultByCache->each(function ($item) use (&$result) {
+            $result->push(
+                [
+                    'value' => $item->amount,
+                    'name' => $item->userWorkgroup->name,
+                    'id' => $item->userWorkgroup->id,
+                ]
+            );
+        });
+        return $result->sortBy('id');
+    }
+
+    public function get($start, $end, $unit = '日')
+    {
+        $resultByCache = $this->getByCache($start, $end, $unit);
+        if ($resultByCache['dateList'] == []) {
+            return $resultByCache['dataList'];
+        } else {
+            $this->syncDBToCache($resultByCache['dateList'], $unit);
+            return $this->getByCache($start, $end, $unit)['dataList'];
+        }
+    }
+
+    public function getByCache($start, $end, $unit)
+    {
+        $dataList = collect();
+        $dateList = collect($this->periodDateToArray($start, $end, $unit));
+        $result = [];
+        foreach ($dateList as $date) {
+            $key = 'laborReportsCountingRecords_' . $date . '_' . $unit;
+            $item = Cache::get($key);
+            if ($item) {
+                $dataList->push($item);
+                $dateList = $dateList->reject(function ($value) use ($date) {
+                    return $value == $date;
+                });
+            }
+        }
+        $result['dataList'] = $dataList;
+        $result['dateList'] = $dateList->toArray();
+        return $result;
+    }
+
+
+    /**
+     * @param $start
+     * @param $end
+     * @param string $unit
+     * @return array
+     */
+    private function periodDateToArray($start, $end, $unit = '日')
+    {
+        $dataArray = [];
+        switch ($unit) {
+            case '日';
+                foreach (Carbon::parse($start)->daysUntil($end, 1)->toArray() as $item) {
+                    $dataArray[] = $item->toDateString();
+                }
+                break;
+            case '周';
+                foreach (Carbon::parse($start)->startOfWeek(1)->weeksUntil($end, 1)->toArray() as $item) {
+                    $dataArray[] = $item->year . '-' . $item->week . '';
+                }
+                break;
+            case '月';
+                foreach (Carbon::parse($start)->monthsUntil($end, 1)->toArray() as $item) {
+                    $dataArray[] = $item->year . '-' . $item->format('m') . '';
+                }
+                break;
+            case '年';
+                foreach (Carbon::parse($start)->yearsUntil($end, 1)->toArray() as $item) {
+                    $dataArray[] = $item->year . '-' . $item->month . '';
+                }
+                break;
+            default:
+                break;
+        }
+        return $dataArray;
+    }
+
+    private function syncDBToCache($dateList, $unit)
+    {
+        switch ($unit) {
+            case '日':
+                $query = LaborReport::query()
+                    ->selectRaw("DATE_FORMAT(created_at,'%Y-%m-%d') as date_target, count(1) as counter");
+                foreach ($dateList as $startOfWeek) {
+                    $query->orWhere(function ($query) use ($startOfWeek) {
+                        $query->whereDate('created_at', $startOfWeek);
+                    });
+                }
+                $dataList = $query->groupBy('date_target')->get();
+                $dataList->each(function ($item) use ($unit) {
+                    $date = $item->date_target;
+                    $key = 'laborReportsCountingRecords_' . $date . '_' . $unit;
+                    Cache::put($key, $item);
+                });
+                break;
+            case '周':
+                $query = LaborReport::query()->selectRaw("DATE_FORMAT(created_at,'%x-%v') as date_target, count(1) as counter");
+                foreach ($dateList as $date) {
+                    $query->orWhere(function ($query) use ($date) {
+                        $year = Str::of($date)->explode('-')[0];
+                        $week = Str::of($date)->explode('-')[1];
+                        $startOfWeek = Carbon::now()->setISODate($year, $week)->startOfWeek()->toDateString();
+                        $endOfWeek = Carbon::parse($startOfWeek)->endOfWeek()->toDateString();
+                        $query->whereDate('created_at', '>=', $startOfWeek)->whereDate('created_at', '<=', $endOfWeek);
+                    });
+                }
+                $dataList = $query->groupBy('date_target')->get();
+                $dataList->each(function ($item) use ($unit) {
+                    $date = $item->date_target;
+                    $item->date_target = Carbon::now()->setISODate(Str::of($date)->explode('-')[0], Str::of($date)->explode('-')[1])->startOfWeek()->toDateString();
+                    Cache::put('laborReportsCountingRecords_' . $date . '_' . $unit, $item);
+                });
+                break;
+            case '月':
+                $query = LaborReport::query()->selectRaw("DATE_FORMAT(created_at,'%Y-%m') as date_target, count(1) as counter");
+                foreach ($dateList as $date) {
+                    $query->orWhere(function ($query) use ($date) {
+                        $year = Str::of($date)->explode('-')[0];
+                        $month = Str::of($date)->explode('-')[1];
+                        $query->whereYear('created_at', $year)->whereMonth('created_at', $month);
+                    });
+                }
+                $dataList = $query->groupBy('date_target')->get();
+                $dataList->each(function ($item) use ($unit) {
+                    $date = $item->date_target;
+                    $key = 'laborReportsCountingRecords_' . $date . '_' . $unit;
+                    Cache::put($key, $item);
+                });
+                break;
+            default:
+                break;
+        }
+    }
+}

+ 340 - 0
app/Services/OrderCountingRecordService.php

@@ -0,0 +1,340 @@
+<?php
+
+
+namespace App\Services;
+
+
+use App\Logistic;
+use App\Order;
+use App\OrderCountingRecord;
+use App\Warehouse;
+use Carbon\Carbon;
+use DateTime;
+use Illuminate\Database\Eloquent\Collection;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Cache;
+use App\User;
+use Illuminate\Support\Str;
+
+
+class OrderCountingRecordService
+{
+    /** @var $ownerService OwnerService */
+    private $ownerService = null;
+
+    function __construct()
+    {
+        $this->ownerService = app(OwnerService::class);
+    }
+
+    /**
+     * @param $start
+     * @param $end
+     * @param null $ownerIds
+     * @param string $unit
+     * @param $user
+     * @return mixed
+     */
+    public function get($start, $end, $ownerIds = null, $unit = '日', $user)
+    {
+        $resultByCache = $this->getByCache($start, $end, $ownerIds, $unit, $user);
+        if (!($resultByCache['unExistingOrders'])) return $resultByCache['resultOrders'];
+        $resultByOrderCountingRecords = $this->getByDatabase($resultByCache['unExistingOrders'], $unit);
+        $this->createByDatabase($resultByOrderCountingRecords['unExistingOrders'], $unit);
+        $this->getByDatabase($resultByCache['unExistingOrders'], $unit);
+        $resultByCache = $this->getByCache($start, $end, $ownerIds, $unit, $user);
+        return $resultByCache['resultOrders'];
+    }
+
+    public function orderCountingRecords($start, $end, $ownerIds = null, $unit = '日', $user = null)
+    {
+        $key = 'orderCountingRecords_' . $start . '_' . $end . '_' . $unit . '_' . Auth::user()->id;
+        return Cache::remember($key, 600, function () use ($start, $end, $unit, $ownerIds, $user) {
+            $orders = $this->get($start, $end, null, $unit, null);
+            $dataList = collect();
+            $orders->groupBy('date_target')->each(function ($items) use (&$dataList, $unit) {
+                $counter = $items->reduce(function ($sum, $item) {
+                    return $sum + $item->amount;
+                }, 0);
+                $date_target = $items[0]->date_target;
+                if ($unit == '周') {
+                    $date_target = (new DateTime())->setISODate(Str::of($date_target)->explode('-')[0], Str::of($date_target)->explode('-')[1])->format('yy-m-d');
+                }
+                $dataList->push([
+                    'counter' => $counter,
+                    'date_target' => $date_target,
+                ]);
+            });
+            return $dataList->sortBy("date_target");
+        });
+    }
+
+    /**
+     * @param $start
+     * @param $end
+     * @param null $ownerIds
+     * @param null $user
+     * @return \Illuminate\Support\Collection|\Tightenco\Collect\Support\Collection
+     */
+    public function logisticsCountingRecords($start, $end, $ownerIds = null, $user = null)
+    {
+        $key = 'logisticsCountingRecords_' . $start . '_' . $end . '_' . Auth::user()->id;
+        return Cache::remember($key, 600, function () use ($start, $end, $ownerIds, $user) {
+            $dataList = collect();
+            $resultOrders = $this->get($start, $end, $ownerIds, '日', $user);
+            $resultOrders->groupBy('logistic_id')->each(function ($item) use (&$dataList) {
+                $counter = $item->reduce(function ($sum, $item) {
+                    return $sum + $item->amount;
+                }, 0);
+                $dataList->push([
+                    'value' => $counter,
+                    'logistic_id' => $item[0]->logistic_id,
+                ]);
+            });
+            $map = [];
+            $logistics = Logistic::query()->whereIn('id', data_get($dataList, '*.logistic_id'))->get();
+            $logistics->each(function ($logistic) use (&$map) {
+                $map[$logistic->id] = $logistic;
+            });
+            return $dataList->map(function (&$item) use ($map) {
+                $logistic = $map[$item['logistic_id']] ?? '';
+                $item['name'] = $logistic->name ?? '';
+                return $item;
+            });
+        });
+    }
+
+    public function warehouseCountingRecords($start, $end, $ownerIds = null, $user = null)
+    {
+        $key = 'warehouseCountingRecords_' . $start . '_' . $end . '_' . Auth::user()->id;
+        return Cache::remember($key, 600, function () use ($start, $end, $ownerIds, $user) {
+            $dataList = collect();
+            $resultOrders = $this->get($start, $end, $ownerIds, '日', $user);
+            $resultOrders->groupBy('warehouse_id')->each(function ($item) use (&$dataList) {
+                $counter = $item->reduce(function ($sum, $item) {
+                    return $sum + $item->amount;
+                }, 0);
+                $dataList->push([
+                    'value' => $counter,
+                    'warehouse_id' => $item[0]->warehouse_id,
+                ]);
+            });
+            $map = [];
+            $logistics = Warehouse::query()->whereIn('id', data_get($dataList, '*.warehouse_id'))->get();
+            $logistics->each(function ($warehouse) use (&$map) {
+                $map[$warehouse->id] = $warehouse;
+            });
+            return $dataList->map(function (&$item) use ($map) {
+                $warehouse = $map[$item['warehouse_id']] ?? '';
+                $item['code'] = $warehouse->name ?? '';
+                switch ($item['code']) {
+                    case 'WH01':
+                        $item['name'] = '松江一仓';
+                        break;
+                    case 'WH02':
+                        $item['name'] = '松江二仓';
+                        break;
+                    case 'WH03':
+                        $item['name'] = '嘉定一仓';
+                        break;
+                    default:
+                        $item['name'] = '仓库为空';
+                        break;
+                }
+                return $item;
+            });
+        });
+    }
+
+    /**
+     * @param $start
+     * @param $end
+     * @param null $ownerIds
+     * @param string $unit
+     * @param $user
+     * @return array
+     */
+    public function getByCache($start, $end, $ownerIds = null, $unit = '日', $user)
+    {// Order[] results, Array [$date=>[$ownerIds]]
+        $countingOwnerIds = $this->getCountingOwnerIds($ownerIds, $user);
+        $resultOrders = collect();
+        $unExistingOrders = [];
+        $carbonInterfaces = $this->periodDateToArray($start, $end, $unit);
+        foreach ($carbonInterfaces as $dateStr) {
+            foreach ($countingOwnerIds as $ownerId) {
+                $key = "order_counting_records_{$dateStr}_{$ownerId}_{$unit}";
+                $orders = Cache::get($key);
+                if ($orders) {
+                    $orders->each(function ($item) use (&$resultOrders) {
+                        $resultOrders->push($item);
+                    });
+                    continue;
+                }
+                $unExistingOrders[$dateStr][] = $ownerId;
+            }
+        }
+        return ['resultOrders' => $resultOrders, 'unExistingOrders' => $unExistingOrders];
+    }
+
+    public function getByDatabase($targetOwnerIdsUnderDates, $unit = '日')
+    {// Order[] results, Array [$date=>[$ownerIds]]
+        $orderSqlBuilder = OrderCountingRecord::query();
+        foreach ($targetOwnerIdsUnderDates as $date => $owners) {
+            $orderSqlBuilder->orWhere(function ($query) use ($owners, $date, $unit) {
+                $query->whereIn('owner_id', $owners)->where('date_target', $date)->where('counting_unit', $unit);
+            });
+        }
+        $resultOrders = $orderSqlBuilder->get();
+        $resultOrders->groupBy(['date_target', 'owner_id'])->each(function ($item, $dateStr) use ($unit) {
+            $item->each(function ($item, $owner_id) use ($dateStr, $unit) {
+                $key = "order_counting_records_{$dateStr}_{$owner_id}_{$unit}";
+                $ttl = 3600 * 24;
+                if ($dateStr==Carbon::now()->toDateString()) {
+                    $ttl = 60;
+                }
+                Cache::put($key, $item, $ttl);
+            });
+        });
+        $map = [];
+        $resultOrders->each(function ($item) use (&$map) {
+            $key = 'owner_id=' . $item->owner_id . ' date_target' . $item->date_target;
+            $map[$key] = true;
+        });
+        foreach ($targetOwnerIdsUnderDates as $dateStr => $ownerIds) {
+            foreach ($ownerIds as $key => $ownerId) {
+                $key1 = 'owner_id=' . $ownerId . ' date_target' . $dateStr;
+                if (isset($map[$key1])) {
+                    unset($targetOwnerIdsUnderDates[$dateStr][$key]);
+                }
+            }
+        }
+        return ['resultOrders' => $resultOrders, 'unExistingOrders' => $targetOwnerIdsUnderDates];
+    }
+
+    public function createByDatabase($targetOwnerIdsUnderDates, $unit = '日')
+    {// Order[] results]
+        switch ($unit) {
+            case '日':
+                $resultOrders = $this->getCreateByDatabaseUnitDay($targetOwnerIdsUnderDates);
+                break;
+            case'周':
+                $resultOrders = $this->getCreateByDatabaseUnitWeek($targetOwnerIdsUnderDates);
+                break;
+            case'月':
+                $resultOrders = $this->getCreateByDatabaseUnitMonth($targetOwnerIdsUnderDates);
+                break;
+            default:
+                $resultOrders = collect();
+                break;
+        }
+        $result = collect();
+        $resultOrders->each(function ($order) use (&$result, $unit) {
+            $orderCountingRecord = new OrderCountingRecord([
+                'owner_id' => $order->owner_id,
+                'shop_id' => $order->shop_id,
+                'warehouse_id' => $order->warehouse_id,
+                'logistic_id' => $order->logistic_id,
+                'date_target' => $order->date_target,
+                'counting_unit' => $unit,
+                'amount' => $order->amounts,
+            ]);
+            $result->push($orderCountingRecord);
+        });
+        OrderCountingRecord::query()->insert($result->toArray());
+        return ['resultOrders' => $result];
+    }
+
+
+    public function periodDateToArray($start, $end, $unit = '日')
+    {
+        $dataArray = [];
+        switch ($unit) {
+            case '日';
+                foreach (Carbon::parse($start)->daysUntil($end, 1)->toArray() as $item) {
+                    $dataArray[] = $item->toDateString();
+                }
+                break;
+            case '周';
+                foreach (Carbon::parse($start)->weeksUntil($end, 1)->toArray() as $item) {
+                    $dataArray[] = $item->year . '-' . $item->week . '';
+                }
+                break;
+            case '月';
+                foreach (Carbon::parse($start)->monthsUntil($end, 1)->toArray() as $item) {
+                    $dataArray[] = $item->year . '-' . $item->format('m') . '';
+                }
+                break;
+            case '年';
+                foreach (Carbon::parse($start)->yearsUntil($end, 1)->toArray() as $item) {
+                    $dataArray[] = $item->year . '-' . $item->month . '';
+                }
+                break;
+            default:
+                break;
+        }
+        return $dataArray;
+    }
+
+    /**
+     * @param $ownerIds
+     * @return array
+     */
+    public function getCountingOwnerIds($ownerIds = null, $user): array
+    {
+        if ($user == null) {
+            $user = auth()->user();
+        }
+        /** @var UserService $userService */
+        $userService = app('UserService');
+        $permittingOwnerIds = $userService->getPermittingOwnerIds($user);
+        if (!$ownerIds) {
+            return $permittingOwnerIds;
+        }
+        return Cache::remember(
+            'PermittingOwnerIds' . '_' . auth()->user()->id . '_' . implode('_', $ownerIds),
+            600, function () use ($ownerIds, $permittingOwnerIds) {
+            /** @var User $user */
+            return array_intersect($ownerIds, $permittingOwnerIds);
+        });
+    }
+
+    /**
+     * @param $targetOwnerIdsUnderDates
+     * @return \Illuminate\Database\Eloquent\Builder[]|Collection
+     */
+    private function getCreateByDatabaseUnitDay($targetOwnerIdsUnderDates)
+    {
+        $orderSqlBuilder = Order::query()->selectRaw("owner_id,warehouse_id,shop_id,logistic_id,count(1) as amounts ,DATE_FORMAT(created_at,'%Y-%m-%d') as date_target");
+        foreach ($targetOwnerIdsUnderDates as $dateStr => $ownerIds) {
+            $orderSqlBuilder->orWhere(function ($query) use ($ownerIds, $dateStr) {
+                $query->whereIn('owner_id', $ownerIds)->whereDate('created_at', $dateStr)->where('wms_status', '订单完成');
+            });
+        }
+        return $orderSqlBuilder->groupBy(['owner_id', 'warehouse_id', 'shop_id', 'logistic_id', 'date_target'])->get();
+    }
+
+    private function getCreateByDatabaseUnitWeek($targetOwnerIdsUnderDates)
+    {
+        $orderSqlBuilder = Order::query()->selectRaw("owner_id,warehouse_id,shop_id,logistic_id,count(1) as amounts ,DATE_FORMAT(created_at,'%x-%v') as date_target");
+        foreach ($targetOwnerIdsUnderDates as $dateStr => $ownerIds) {
+            $orderSqlBuilder->orWhere(function ($query) use ($ownerIds, $dateStr) {
+                $dateStr = (new DateTime())->setISODate(Str::of($dateStr)->explode('-')[0], Str::of($dateStr)->explode('-')[1])->format('yy-m-d');
+                $query->whereIn('owner_id', $ownerIds)->whereDate('created_at', '>=', $dateStr)->whereDate('created_at', '<', Carbon::parse($dateStr)->addWeek()->toDateString())->where('wms_status', '订单完成');;
+            });
+        }
+        return $orderSqlBuilder->groupBy(['owner_id', 'warehouse_id', 'shop_id', 'logistic_id', 'date_target'])->get();
+    }
+
+    private function getCreateByDatabaseUnitMonth($targetOwnerIdsUnderDates)
+    {
+        $orderSqlBuilder = Order::query()->selectRaw("owner_id,warehouse_id,shop_id,logistic_id,count(1) as amounts ,DATE_FORMAT(created_at,'%Y-%m') as date_target");
+        foreach ($targetOwnerIdsUnderDates as $dateStr => $ownerIds) {
+            $orderSqlBuilder->orWhere(function ($query) use ($ownerIds, $dateStr) {
+                $year = Str::of($dateStr)->explode('-')[0];
+                $month = Str::of($dateStr)->explode('-')[1];
+                $query->whereIn('owner_id', $ownerIds)->whereMonth('created_at', $month)->whereYear('created_at', $year)->where('wms_status', '订单完成');;
+            });
+        }
+        return $orderSqlBuilder->groupBy(['owner_id', 'warehouse_id', 'shop_id', 'logistic_id', 'date_target'])->get();
+    }
+}

+ 4 - 2
app/Services/OwnerService.php

@@ -166,10 +166,12 @@ Class OwnerService
         return Owner::query()->whereIn('id',app('UserService')->getPermittingOwnerIds($user)??[])->get();
     }
 
-    public function get(array $params, array $withs = null, bool $authority = true, bool $notShowSoftDelete = false)
+    public function get(array $params, array $withs = null, bool $authority = true, bool $notShowSoftDelete = false,$user)
     {
         /** @var User $user */
-        $user = Auth::user();
+        if ($user==null) {
+            $user = Auth::user();
+        }
         $query = Owner::query();
         if ($withs)$query->with($withs);
         if ($authority){

+ 57 - 0
app/Services/RealtimePendingOrdersService.php

@@ -0,0 +1,57 @@
+<?php
+
+
+namespace App\Services;
+
+
+use App\Order;
+use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Database\Eloquent\Collection;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\DB;
+
+class RealtimePendingOrdersService
+{
+    /**
+     * 获取实时待处理订单
+     * @param null $start
+     * @param null $end
+     * @return Builder[]|Collection|mixed
+     */
+    public function warehousesOrders($start = null, $end = null)
+    {
+        try {
+            return Cache::remember('RealTimePendingOrders' . Auth::id(), 60, function () use ($start, $end) {
+                return $this->getOrderStatistics($start, $end);
+            });
+        } catch (\Exception $e) {
+            return $this->getOrderStatistics($start, $end);
+        }
+    }
+
+    /**
+     * @param $start
+     * @param $end
+     * @return Builder[]|Collection
+     */
+    public function getOrderStatistics($start, $end)
+    {
+        $start = $start ?? date('Y-m-d 00:00:00');
+        $end = $end ?? date('Y-m-d 23:59:59');
+        $ownerIds = app('OwnerService')->getSelectionId();
+        $builders = Order::query()->selectRaw("warehouses.name," .
+            "count(case wms_status when '创建订单' then 1 end) as createOrder, " .
+            "count(case wms_status when '分配完成' then 1 end) as assignedComplete, " .
+            "count(case wms_status when '部分分配' then 1 end) as partialAllocation, " .
+            "count(case wms_status when '部分装箱' then 1 end) as partPacking, " .
+            "count(case wms_status when '播种完成' then 1 end) as sowComplete, " .
+            "count(1) as total"
+        )->whereBetween('orders.created_at', [$start, $end,])
+            ->whereIn('wms_status', ['创建订单', '分配完成', '部分分配', '部分装箱', '播种完成'])
+            ->leftJoin('warehouses', 'orders.warehouse_id', 'warehouses.id')
+            ->groupBy('warehouse_id');
+        if ($ownerIds) $builders->whereIn('owner_id', $ownerIds);
+        return $builders->get();
+    }
+}

+ 14 - 0
app/UserVisitMenuLog.php

@@ -0,0 +1,14 @@
+<?php
+
+namespace App;
+
+use App\Traits\ModelTimeFormat;
+use Illuminate\Database\Eloquent\Model;
+
+class UserVisitMenuLog extends Model
+{
+    use ModelTimeFormat;
+    protected $fillable=[
+        'user_id','menu_id','created_at','updated_at',
+    ];
+}

+ 36 - 0
database/migrations/2020_11_03_092648_create_menus.php

@@ -0,0 +1,36 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateMenus extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('menus', function (Blueprint $table) {
+            $table->id();
+            $table->string('name')->comment('名称');
+            $table->integer('level')->comment('等级');
+            $table->integer('parent_id')->nullable();
+            $table->string('route')->comment('路由地址');
+            $table->integer('sequence')->comment('顺序');
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('menus');
+    }
+}

+ 88 - 0
database/migrations/2020_11_03_095519_seed_menus_level_1.php

@@ -0,0 +1,88 @@
+<?php
+
+use App\Menu;
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class SeedMenusLevel1 extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        \App\Menu::create([
+            'name'=>'退货管理',
+            'level'=>1,
+            'route'=>'rejected/index/general',
+            'sequence'=>1,
+        ]);
+        \App\Menu::create([
+            'name'=>'入库管理',
+            'level'=>1,
+            'route'=>'store/checkingReceive/mission',
+            'sequence'=>2,
+        ]);
+        \App\Menu::create([
+            'name'=>'订单管理',
+            'level'=>1,
+            'route'=>'order/index/delivering',
+            'sequence'=>3,
+        ]);
+        \App\Menu::create([
+            'name'=>'运输管理',
+            'level'=>1,
+            'route'=>'waybill/index',
+            'sequence'=>4,
+        ]);
+        \App\Menu::create([
+            'name'=>'称重管理',
+            'level'=>1,
+            'route'=>'package',
+            'sequence'=>5,
+        ]);
+        \App\Menu::create([
+            'name'=>'库存管理',
+            'level'=>1,
+            'route'=>'inventory/statement/allInventory',
+            'sequence'=>6,
+        ]);
+        \App\Menu::create([
+            'name'=>'二次加工管理',
+            'level'=>1,
+            'route'=>'process',
+            'sequence'=>7,
+        ]);
+        \App\Menu::create([
+            'name'=>'客户管理',
+            'level'=>1,
+            'route'=>'customer/project/report',
+            'sequence'=>8,
+        ]);
+        \App\Menu::create([
+            'name'=>'人事管理',
+            'level'=>1,
+            'route'=>'personnel/laborReport',
+            'sequence'=>9,
+        ]);
+        \App\Menu::create([
+            'name'=>'基础设置',
+            'level'=>1,
+            'route'=>'maintenance',
+            'sequence'=>10,
+        ]);
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Menu::query()->where('level',1)->delete();
+    }
+}

+ 481 - 0
database/migrations/2020_11_03_095724_seed_menus_level_2.php

@@ -0,0 +1,481 @@
+<?php
+
+use App\Menu;
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class SeedMenusLevel2 extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Menu::create([
+            'name'=>'查询',
+            'level'=>2,
+            'parent_id'=>1,
+            'route'=>'rejected/index/general',
+            'sequence'=>1,
+        ]);
+        Menu::create([
+            'name'=>'录入',
+            'level'=>2,
+            'parent_id'=>1,
+            'route'=>'rejected/create',
+            'sequence'=>2,
+        ]);
+        Menu::create([
+            'name'=>'相关设置',
+            'level'=>2,
+            'parent_id'=>1,
+            'route'=>'rejected/relating',
+            'sequence'=>3,
+        ]);
+        Menu::create([
+            'name'=>'回收站',
+            'level'=>2,
+            'parent_id'=>1,
+            'route'=>'rejected/recycle',
+            'sequence'=>4,
+        ]);
+
+        Menu::create([
+            'name'=>'盘收一体',
+            'level'=>2,
+            'parent_id'=>2,
+            'route'=>'store/checkingReceive/mission',
+            'sequence'=>1,
+        ]);
+        Menu::create([
+            'name'=>'快速入库',
+            'level'=>2,
+            'parent_id'=>2,
+            'route'=>'store/fast/create',
+            'sequence'=>2,
+        ]);
+        Menu::create([
+            'name'=>'盲收',
+            'level'=>2,
+            'parent_id'=>2,
+            'route'=>'store/blindReceive/excels',
+            'sequence'=>3,
+        ]);
+
+        Menu::create([
+            'name'=>'订单',
+            'level'=>2,
+            'parent_id'=>3,
+            'route'=>'order/index/delivering',
+            'sequence'=>1,
+        ]);
+        Menu::create([
+            'name'=>'波次',
+            'level'=>2,
+            'parent_id'=>3,
+            'route'=>'order/wave/index/',
+            'sequence'=>2,
+        ]);
+        Menu::create([
+            'name'=>'问题件',
+            'level'=>2,
+            'parent_id'=>3,
+            'route'=>'order/issue/index?addtime=15',
+            'sequence'=>3,
+        ]);
+        Menu::create([
+            'name'=>'跟踪',
+            'level'=>2,
+            'parent_id'=>3,
+            'route'=>'order/tracking/index',
+            'sequence'=>4,
+        ]);
+
+        //运输
+        Menu::create([
+            'name'=>'查询',
+            'level'=>2,
+            'parent_id'=>4,
+            'route'=>'waybill/index',
+            'sequence'=>1,
+        ]);
+        Menu::create([
+            'name'=>'录入',
+            'level'=>2,
+            'parent_id'=>4,
+            'route'=>'waybill/create?type=ZX',
+            'sequence'=>2,
+        ]);
+        Menu::create([
+            'name'=>'发运',
+            'level'=>2,
+            'parent_id'=>4,
+            'route'=>'waybill/delivering',
+            'sequence'=>3,
+        ]);
+        Menu::create([
+            'name'=>'相关设置',
+            'level'=>2,
+            'parent_id'=>4,
+            'route'=>'waybill/relating',
+            'sequence' => 4,
+        ]);
+        Menu::create([
+            'name'=>'财务报表',
+            'level'=>2,
+            'parent_id'=>4,
+            'route'=>'waybill/waybillFinancialSnapshot',
+            'sequence'=>5,
+        ]);
+        Menu::create([
+            'name'=>'异常报表',
+            'level'=>2,
+            'parent_id'=>4,
+            'route'=>'waybill/waybillFinancialExcepted',
+            'sequence'=>6,
+        ]);
+        Menu::create([
+            'name'=>'回收站',
+            'level'=>2,
+            'parent_id'=>4,
+            'route'=>'waybill/recycle',
+            'sequence'=>7,
+        ]);
+        //称重
+        Menu::create([
+            'name'=>'记录',
+            'level'=>2,
+            'parent_id'=>5,
+            'route'=>'package/',
+            'sequence'=>1,
+        ]);
+        Menu::create([
+            'name'=>'设备',
+            'level'=>2,
+            'parent_id'=>5,
+            'route'=>'package/measureMonitor',
+            'sequence'=>2,
+        ]);
+        Menu::create([
+            'name'=>'统计',
+            'level'=>2,
+            'parent_id'=>5,
+            'route'=>'package/statistics',
+            'sequence'=>3,
+        ]);
+        Menu::create([
+            'name'=>'手动录入',
+            'level'=>2,
+            'parent_id'=>5,
+            'route'=>'package/create',
+            'sequence'=>4,
+        ]);
+        Menu::create([
+            'name'=>'异常记录',
+            'level'=>2,
+            'parent_id'=>5,
+            'route'=>'package/weightExcepted/indexCreate',
+            'sequence'=>5,
+        ]);
+        Menu::create([
+            'name'=>'相关设置',
+            'level'=>2,
+            'parent_id'=>5,
+            'route'=>'package/relating',
+            'sequence'=>6,
+        ]);
+        //库存管理
+        Menu::create([
+            'name'=>'库存',
+            'level'=>2,
+            'parent_id'=>6,
+            'route'=>'inventory/statement/changeInventory?range=1',
+            'sequence'=>1,
+        ]);
+        Menu::create([
+            'name'=>'盘点',
+            'level'=>2,
+            'parent_id'=>6,
+            'route'=>'inventory/stockInventory/mission',
+            'sequence'=>2,
+        ]);
+        //二次加工
+        Menu::create([
+            'name'=>'查询',
+            'level'=>2,
+            'parent_id'=>7,
+            'route'=>'process/',
+            'sequence'=>1,
+        ]);
+        Menu::create([
+            'name'=>'录入',
+            'level'=>2,
+            'parent_id'=>7,
+            'route'=>'process/create',
+            'sequence'=>2,
+        ]);
+        Menu::create([
+            'name'=>'统计',
+            'level'=>2,
+            'parent_id'=>7,
+            'route'=>'process/statistic',
+            'sequence'=>3,
+        ]);
+        Menu::create([
+            'name'=>'回收站',
+            'level'=>2,
+            'parent_id'=>7,
+            'route'=>'process/recycle',
+            'sequence'=>4,
+        ]);
+        Menu::create([
+            'name'=>'相关设置',
+            'level'=>2,
+            'parent_id'=>7,
+            'route'=>'process/relating',
+            'sequence'=>5,
+        ]);
+        //客户管理
+        Menu::create([
+            'name'=>'项目',
+            'level'=>2,
+            'parent_id'=>8,
+            'route'=>'customer/project/report',
+            'sequence'=>1,
+        ]);
+        Menu::create([
+            'name'=>'财务',
+            'level'=>2,
+            'parent_id'=>8,
+            'route'=>'customer/finance/instantBill',
+            'sequence'=>2,
+        ]);
+        Menu::create([
+            'name'=>'相关设置',
+            'level'=>2,
+            'parent_id'=>8,
+            'route'=>'customer/relating',
+            'sequence'=>3,
+        ]);
+        //人事管理
+        Menu::create([
+            'name'=>'临时工报表',
+            'level'=>2,
+            'parent_id'=>9,
+            'route'=>'personnel/laborReport',
+            'sequence'=>1,
+        ]);
+        Menu::create([
+            'name'=>'打卡相关',
+            'level'=>2,
+            'parent_id'=>9,
+            'route'=>'personnel/checking-in/createReplenishClock',
+            'sequence'=>2,
+        ]);
+        Menu::create([
+            'name'=>'相关设置',
+            'level'=>2,
+            'parent_id'=>9,
+            'route'=>'personnel/relating',
+            'sequence'=>3,
+        ]);
+
+
+        //基础设置
+        Menu::create([
+            'name'=>'用户',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/user',
+            'sequence'=>1,
+        ]);
+        Menu::create([
+            'name'=>'角色',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/role',
+            'sequence'=>2,
+        ]);
+        Menu::create([
+            'name'=>'权限',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/authority',
+            'sequence'=>3,
+        ]);
+        Menu::create([
+            'name'=>'工作组',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/userWorkgroup',
+            'sequence'=>4,
+        ]);
+        Menu::create([
+            'name'=>'项目组',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/userOwnerGroup',
+            'sequence'=>5,
+        ]);
+        Menu::create([
+            'name'=>'仓库',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/warehouse',
+            'sequence'=>6,
+        ]);
+        Menu::create([
+            'name'=>'客户',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/customer',
+            'sequence'=>7,
+        ]);
+        Menu::create([
+            'name'=>'货主',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/owner',
+            'sequence'=>8,
+        ]);
+        Menu::create([
+            'name'=>'品质标签',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/qualityLabel',
+            'sequence'=>9,
+        ]);
+        Menu::create([
+            'name'=>'作业类型',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/processMethod',
+            'sequence'=>10,
+        ]);
+        Menu::create([
+            'name'=>'商品信息',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/commodity',
+            'sequence'=>11,
+        ]);
+        Menu::create([
+            'name'=>'计量单位',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/unit',
+            'sequence'=>12,
+        ]);
+        Menu::create([
+            'name'=>'省份',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/province',
+            'sequence'=>13,
+        ]);
+        Menu::create([
+            'name'=>'城市',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/city',
+            'sequence'=>14,
+        ]);
+        Menu::create([
+            'name'=>'物流公司',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/logistic',
+            'sequence'=>15,
+        ]);
+        Menu::create([
+            'name'=>'承运商',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/carrier',
+            'sequence'=>16,
+        ]);
+        Menu::create([
+            'name'=>'车型',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/carType',
+            'sequence'=>17,
+        ]);
+        Menu::create([
+            'name'=>'作业类型',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/jobType',
+            'sequence'=>18,
+        ]);
+        Menu::create([
+            'name'=>'特征',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/feature',
+            'sequence'=>19,
+        ]);
+        Menu::create([
+            'name'=>'计费模型',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/priceModel/waybillPriceModel',
+            'sequence'=>20,
+        ]);
+        Menu::create([
+            'name'=>'纸箱',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/paperBox/index/model',
+            'sequence'=>21,
+        ]);
+        Menu::create([
+            'name'=>'测量设备',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/measuringMachine',
+            'sequence'=>22,
+        ]);
+        Menu::create([
+            'name'=>'教程',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/tutorial',
+            'sequence'=>23,
+        ]);
+        Menu::create([
+            'name'=>'临时工',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/userLabor',
+            'sequence'=>24,
+        ]);
+        Menu::create([
+            'name'=>'劳务所',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/laborCompany',
+            'sequence'=>25,
+        ]);
+        Menu::create([
+            'name'=>'日志',
+            'level'=>2,
+            'parent_id'=>10,
+            'route'=>'maintenance/log',
+            'sequence'=>26,
+        ]);
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Menu::query()->where('level',2)->delete();
+    }
+}

+ 33 - 0
database/migrations/2020_11_03_111159_create_user_visit_menu_logs.php

@@ -0,0 +1,33 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateUserVisitMenuLogs extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('user_visit_menu_logs', function (Blueprint $table) {
+            $table->id();
+            $table->integer('user_id')->index();
+            $table->integer('menu_id')->index();
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('user_visit_menu_logs');
+    }
+}

+ 38 - 0
database/migrations/2020_11_06_114606_create_order_counting_records_table.php

@@ -0,0 +1,38 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateOrderCountingRecordsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('order_counting_records', function (Blueprint $table) {
+            $table->id();
+            $table->integer('owner_id')->index()->comment('外键货主');
+            $table->integer('shop_id')->nullable()->index()->comment('外键商铺');
+            $table->integer('warehouse_id')->nullable()->index()->comment('外键仓库');
+            $table->integer('logistic_id')->nullable()->index()->comment('外键快递');
+            $table->string('date_target')->index()->comment('该时间为时间, 根据单位扔掉部分信息');
+            $table->enum('counting_unit',['日','周','月','年'])->index()->comment('时间粒度');
+            $table->integer('amount')->comment('该货主下某天订单总数量');
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('order_counting_records');
+    }
+}

+ 33 - 0
database/migrations/2020_11_20_101212_create_key_values_table.php

@@ -0,0 +1,33 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateKeyValuesTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('key_values', function (Blueprint $table) {
+            $table->id();
+            $table->string('key');
+            $table->timestamp('value', 0)->nullable()->index();
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('key_values');
+    }
+}

+ 53 - 0
database/migrations/2020_11_20_101353_seed_key_values_table.php

@@ -0,0 +1,53 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class SeedKeyValuesTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        \App\KeyValues::create([
+            'key' => 'order_last_created_sync_at',
+            'value' => null,
+        ]);
+        \App\KeyValues::create([
+            'key' => 'order_last_updated_sync_at',
+            'value' => null,
+        ]);
+
+        \App\KeyValues::create([
+            'key' => 'commodity_last_created_sync_at',
+            'value' => null,
+        ]);
+        \App\KeyValues::create([
+            'key' => 'commodity_last_updated_sync_at',
+            'value' => null,
+        ]);
+
+        \App\KeyValues::create([
+            'key' => 'asn_last_created_sync_at',
+            'value' => null,
+        ]);
+        \App\KeyValues::create([
+            'key' => 'asn_last_updated_sync_at',
+            'value' => null,
+        ]);
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        //
+    }
+}

+ 14 - 1
package-lock.json

@@ -3425,6 +3425,14 @@
                 "safer-buffer": "^2.1.0"
             }
         },
+        "echarts": {
+            "version": "4.9.0",
+            "resolved": "https://registry.npm.taobao.org/echarts/download/echarts-4.9.0.tgz?cache=0&sync_timestamp=1603712828556&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fecharts%2Fdownload%2Fecharts-4.9.0.tgz",
+            "integrity": "sha1-qbm6oD8Doqcx5jQMVb77V6nhNH0=",
+            "requires": {
+                "zrender": "4.3.2"
+            }
+        },
         "ee-first": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -6192,7 +6200,7 @@
         },
         "minimist": {
             "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+            "resolved": "https://registry.npm.taobao.org/minimist/download/minimist-1.2.0.tgz",
             "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
             "dev": true
         },
@@ -10775,6 +10783,11 @@
             "version": "0.1.2",
             "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
             "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk="
+        },
+        "zrender": {
+            "version": "4.3.2",
+            "resolved": "https://registry.npm.taobao.org/zrender/download/zrender-4.3.2.tgz?cache=0&sync_timestamp=1603693382261&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fzrender%2Fdownload%2Fzrender-4.3.2.tgz",
+            "integrity": "sha1-7HQy+UFcgsc1hLa3uMR+GwFiCcY="
         }
     }
 }

+ 1 - 0
package.json

@@ -26,6 +26,7 @@
   },
   "dependencies": {
     "bootstrap-select": "^1.13.18",
+    "echarts": "^4.9.0",
     "jquery.cookie": "^1.4.1",
     "js-cookie": "^2.2.1",
     "laravel-echo": "^1.8.0",

+ 3 - 1
resources/js/app.js

@@ -1,12 +1,14 @@
 
 require('./bootstrap');
 require('./mounted');
+require('./element-ui');
 
 window.Vue = require('vue');
 window.tempTip=require('./utilities/tempTip');
+window.ElementUI=require('./utilities/tempTip');
 window.getGetVal=require('./utilities/getGetVal');
 window.scanner=require('./utilities/scanner');
 window.datetimeRelating=require('./utilities/datetimeRelating');
-
+window.Vue.use(window.ElementUI)
 require('bootstrap-select');
 

+ 3 - 0
resources/js/echarts.js

@@ -0,0 +1,3 @@
+window.echarts = require('echarts');
+import echarts from 'echarts'
+Vue.prototype.$echarts = echarts

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
resources/js/element-ui.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
resources/sass/element-ui.css


+ 508 - 0
resources/views/control/panel.blade.php

@@ -0,0 +1,508 @@
+@extends('layouts.app')
+@section('title')控制台@endsection
+@section('head')
+    <link href="{{ mix('css/element-ui.css') }}" rel="stylesheet">
+@endsection
+@section('content')
+    <div class="container-fluid" id="list">
+        <div class="card">
+            <h5 class="card-header">最近使用功能</h5>
+            <div class="card-body row">
+                <ul class="list-group" v-for="(menu,index) in menus">
+                    <div class="container-fluid btn-group justify-content-center">
+                        <a class="btn-primary btn-lg" v-if="index<=3" :href="'/'+menu.route">@{{ menu.name }}</a>
+                    </div>
+                    <div v-if="menu.secondLevelMenu && menu.secondLevelMenu.length>0&&index<=3">
+                        <div class="container-fluid btn-group m-1">
+                            <a class="bth btn-sm btn-info m-1" v-for="(secondMenu,index) in menu.secondLevelMenu"
+                               :href="'/'+secondMenu.route" v-if="index < 2"> @{{ secondMenu.name }}</a>
+                        </div>
+                    </div>
+                </ul>
+            </div>
+        </div>
+        <div class="row my-3">
+            <div class="col-2">
+                <div class="card">
+                    <div class="card-header text-dark h5">
+                        <p>实时待处理订(总):@{{ totalOrders.total }}</p>
+                    </div>
+                    <div class="card-body">
+                        <p>创建订单:@{{ totalOrders.createOrder }}</p>
+                        <p>分配完成:@{{ totalOrders.assignedComplete }}</p>
+                        <p>部分分配:@{{ totalOrders.partialAllocation }}</p>
+                        <p>部分装箱:@{{ totalOrders.partPacking }}</p>
+                        <p>播种完成:@{{ totalOrders.sowComplete }}</p>
+                    </div>
+                </div>
+            </div>
+            <div class="col-2" v-for="(warehousesOrder,index) in warehousesOrders">
+                <div class="card">
+                    <div class="card-header text-success h5">
+                        <p>@{{ getWareHouse(warehousesOrder.name) }}:@{{ warehousesOrder.total }}</p>
+                    </div>
+                    <div class="card-body">
+                        <p>创建订单:@{{ warehousesOrder.createOrder }}</p>
+                        <p>分配完成:@{{ warehousesOrder.assignedComplete }}</p>
+                        <p>部分分配:@{{ warehousesOrder.partialAllocation }}</p>
+                        <p>部分装箱:@{{ warehousesOrder.partPacking }}</p>
+                        <p>播种完成:@{{ warehousesOrder.sowComplete }}</p>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="row my-3">
+            <div class="col-5">
+                <div class="card">
+                    <div class="card-header">
+                            <span class="demonstration" ></span>
+                            <el-date-picker @blur="orderCountingRecordApi('')"
+                                v-model="orderCountingRecordsDate"
+                                type="daterange"
+                                align="right"
+                                unlink-panels
+                                range-separator="-"
+                                start-placeholder="开始日期"
+                                end-placeholder="结束日期"
+                                value-format="yyyy-MM-dd"
+                                :picker-options="pickerOptions">
+                            </el-date-picker>
+                            <el-button type="primary" value="日" @click="orderCountingRecordApi('日')" v-model="orderCountingRecordsUnit">日</el-button>
+                            <el-button type="primary" value="周" @click="orderCountingRecordApi('周')" v-model="orderCountingRecordsUnit">周</el-button>
+                            <el-button type="primary" value="月" @click="orderCountingRecordApi('月')" v-model="orderCountingRecordsUnit">月</el-button>
+                    </div>
+                    <div class="card-body row">
+                        <div id="orderCountingRecords" class="col" style="width:600px;height:600px;"></div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-7">
+                <div class="row">
+                    <div class="col-6">
+                        <div class="card">
+                            <div class="card-header">
+                                <div class="col-5 row">
+                                    <div class="block">
+                                        <span class="demonstration"></span>
+                                        <el-date-picker @blur="logisticsCountingRecordsApi()"
+                                            v-model="logisticsCountingRecordsData"
+                                            type="daterange"
+                                            align="right"
+                                            unlink-panels
+                                            range-separator="-"
+                                            start-placeholder="开始日期"
+                                            end-placeholder="结束日期"
+                                            value-format="yyyy-MM-dd"
+                                            :picker-options="pickerOptions">
+                                        </el-date-picker>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="card-body row">
+                                <div id="logisticsCountingRecords" class="col"
+                                     style="width: 600px;height:600px;"></div>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="col-6">
+                        <div class="card">
+                            <div class="card-header">
+                                <div class="col-5 row">
+                                    <div class="block">
+                                        <span class="demonstration"></span>
+                                        <el-date-picker @blur="warehouseCountingRecordsApi()"
+                                            v-model="warehouseCountingRecordsData"
+                                            type="daterange"
+                                            align="right"
+                                            unlink-panels
+                                            range-separator="-"
+                                            start-placeholder="开始日期"
+                                            end-placeholder="结束日期"
+                                            value-format="yyyy-MM-dd"
+                                            :picker-options="pickerOptions">
+                                        </el-date-picker>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="card-body row">
+                                <div id="warehouseCountingRecords" class="col"
+                                     style="width: 600px;height:600px;"></div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            @can('人事管理-临时工报表-可见全部组')
+            <div class="col-5">
+                <div class="card">
+                    <div class="card-header">
+                        <span class="demonstration" ></span>
+                        <el-date-picker @blur="laborReportsCountingRecordApi('')"
+                                        v-model="laborReportsCountingRecordsDate"
+                                        type="daterange"
+                                        align="right"
+                                        unlink-panels
+                                        range-separator="-"
+                                        start-placeholder="开始日期"
+                                        end-placeholder="结束日期"
+                                        value-format="yyyy-MM-dd"
+                                        :picker-options="pickerOptions">
+                        </el-date-picker>
+                        <el-button type="primary" value="日" @click="laborReportsCountingRecordApi('日')" v-model="laborReportsCountingRecordUnit">日</el-button>
+                        <el-button type="primary" value="周" @click="laborReportsCountingRecordApi('周')" v-model="laborReportsCountingRecordUnit">周</el-button>
+                        <el-button type="primary" value="月" @click="laborReportsCountingRecordApi('月')" v-model="laborReportsCountingRecordUnit">月</el-button>
+                    </div>
+                    <div class="card-body row">
+                        <div id="laborReportsCountingRecords" class="col" style="width:600px;height:600px;"></div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-7">
+
+                <div class="card">
+                    <div class="card-header">
+                        <span class="demonstration" ></span>
+                        <el-date-picker @blur="laborReportsUserGroupsCountApi('')"
+                                        v-model="laborReportsUserGroupsCountDate"
+                                        type="daterange"
+                                        align="right"
+                                        unlink-panels
+                                        range-separator="-"
+                                        start-placeholder="开始日期"
+                                        end-placeholder="结束日期"
+                                        value-format="yyyy-MM-dd"
+                                        :picker-options="pickerOptions">
+                        </el-date-picker>
+                    </div>
+                    <div class="card-body row">
+                        <div id="laborReportsUserGroupsCount" class="col" style="width:600px;height:600px;"></div>
+                    </div>
+                </div>
+            </div>
+            @endcan
+        </div>
+    </div>
+@endsection
+@section('lastScript')
+    <script src="{{ mix('js/echarts.js') }}"></script>
+    <!-- 引入样式 -->
+    <!-- 引入组件库 -->
+    <script src="{{ mix('js/element-ui.js') }}"></script>
+    <script>
+        let vue = new Vue({
+            el: "#list",
+            data: {
+                myChart: null,
+                menus:{!! $menus !!},
+                warehousesOrders:{!! $warehousesOrders !!},
+                orderCountingRecords:{!! $orderCountingRecords !!},
+                logisticsCountingRecords:{!! $logisticsCountingRecords !!},
+                warehouseCountingRecords:{!! $warehouseCountingRecords !!},
+                laborReportsCountingRecords:{!! $laborReportsCountingRecords !!},
+                laborReportsUserGroupsCount:{!! $laborReportsUserGroupsCount !!},
+                warehouses: {},
+                totalOrders: {
+                    total: null,
+                    createOrder: null,
+                    assignedComplete: null,
+                    partialAllocation: null,
+                    partPacking: null,
+                    sowComplete: null,
+                },
+                orderCountingRecordsDateTarget: [],
+                orderCountingRecordsData: [],
+                laborReportsCountingRecordsDateTarget: [],
+                laborReportsCountingRecordsData: [],
+                pickerOptions: {
+                    shortcuts: [{
+                        text: '最近一周',
+                        onClick(picker) {
+                            const end = new Date();
+                            const start = new Date();
+                            start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
+                            picker.$emit('pick', [start, end]);
+                        }
+                    }, {
+                        text: '最近一个月',
+                        onClick(picker) {
+                            const end = new Date();
+                            const start = new Date();
+                            start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
+                            picker.$emit('pick', [start, end]);
+                        }
+                    }, {
+                        text: '最近三个月',
+                        onClick(picker) {
+                            const end = new Date();
+                            const start = new Date();
+                            start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
+                            picker.$emit('pick', [start, end]);
+                        }
+                    }]
+                },
+                orderCountingRecordsDate: [moment(new Date(new Date().getTime() - 3600 * 1000 * 24 * 30)).format('yyyy-MM-DD'),
+                    moment(new Date()).format('yyyy-MM-DD')],
+                logisticsCountingRecordsData: [moment(new Date(new Date().getTime() - 3600 * 1000 * 24 * 30)).format('yyyy-MM-DD'),
+                    moment(new Date()).format('yyyy-MM-DD')],
+                warehouseCountingRecordsData: [moment(new Date(new Date().getTime() - 3600 * 1000 * 24 * 30)).format('yyyy-MM-DD'),
+                    moment(new Date()).format('yyyy-MM-DD')],
+                laborReportsCountingRecordsDate: [moment(new Date(new Date().getTime() - 3600 * 1000 * 24 * 30)).format('yyyy-MM-DD'),
+                    moment(new Date()).format('yyyy-MM-DD')],
+                laborReportsUserGroupsCountDate: [moment(new Date(new Date().getTime() - 3600 * 1000 * 24 * 30)).format('yyyy-MM-DD'),
+                    moment(new Date()).format('yyyy-MM-DD')],
+                orderCountingRecordsUnit: '日',
+                laborReportsCountingRecordUnit: '日'
+            },
+            mounted: function () {
+                let _this = this;
+                this.warehouses = {
+                    "WH01": '松江一仓',
+                    "WH02": '松江二仓',
+                    "WH03": '嘉定一仓',
+                }
+                this.warehousesOrders.forEach(function (item) {
+                    _this.totalOrders.total += parseInt(item.total);
+                    _this.totalOrders.createOrder += item.createOrder;
+                    _this.totalOrders.assignedComplete += item.assignedComplete;
+                    _this.totalOrders.partialAllocation += item.partialAllocation;
+                    _this.totalOrders.partPacking += item.partPacking;
+                    _this.totalOrders.sowComplete += item.sowComplete;
+                });
+                this.initOrderCountingRecords();
+                this.orderCountingRecordsChart = echarts.init(document.getElementById('orderCountingRecords'));
+                this.initOrderCountingRecordsChart();
+
+                this.logisticsCountingRecordsChart = echarts.init(document.getElementById('logisticsCountingRecords'));
+                this.initLogisticsCountingRecordsChart();
+
+                this.warehouseCountingRecordsChart = echarts.init(document.getElementById('warehouseCountingRecords'));
+                this.initWarehouseCountingRecordsChart();
+
+                this.initLaborReportsCountingRecords();
+                this.laborReportsCountingRecordsChart = echarts.init(document.getElementById('laborReportsCountingRecords'));
+                this.initLaborReportsCountingRecordsChart();
+
+                this.laborReportsUserGroupsCountChart = echarts.init(document.getElementById('laborReportsUserGroupsCount'));
+                this.initLaborReportsUserGroupsCountChart();
+
+            },
+            methods: {
+                getWareHouse: function (code) {
+                    return this.warehouses[code];
+                },
+                initOrderCountingRecords() {
+                    let _this = this;
+                    this.orderCountingRecords.forEach(function (item) {
+                        _this.orderCountingRecordsDateTarget.push(item.date_target);
+                        _this.orderCountingRecordsData.push(item.counter);
+                    });
+                },
+                initOrderCountingRecordsChart() {
+                    this.orderCountingRecordsChart.setOption({
+                        title: {text: '订单量趋势'},
+                        tooltip: {},
+                        legend: {data: ['订单数']},
+                        xAxis: {
+                            type: 'category',
+                            data: this.orderCountingRecordsDateTarget
+                        },
+                        yAxis: {type: 'value'},
+                        series: [{
+                            data: this.orderCountingRecordsData,
+                            type: 'line',
+                            smooth: true
+                        }]
+                    });
+                },
+                initLaborReportsCountingRecordsChart() {
+                    this.laborReportsCountingRecordsChart.setOption({
+                        title: {text: '临时用工趋势'},
+                        tooltip: {},
+                        legend: {data: ['临时用工数']},
+                        xAxis: {
+                            type: 'category',
+                            data: this.laborReportsCountingRecordsDateTarget
+                        },
+                        yAxis: {type: 'value'},
+                        series: [{
+                            data: this.laborReportsCountingRecordsData,
+                            type: 'line',
+                            smooth: true
+                        }]
+                    });
+                },
+                initLogisticsCountingRecordsChart() {
+                    this.logisticsCountingRecordsChart.setOption({
+                        title: {
+                            text: '快递分布',
+                            left: 'left'
+                        },
+                        tooltip: {
+                            trigger: 'item',
+                            formatter: '{a} <br/>{b} : {c} ({d}%)'
+                        },
+                        series: [
+                            {
+                                name: '访问来源',
+                                type: 'pie',
+                                radius: '55%',
+                                center: ['50%', '60%'],
+                                data: this.logisticsCountingRecords,
+                                emphasis: {
+                                    itemStyle: {
+                                        shadowBlur: 10,
+                                        shadowOffsetX: 0,
+                                        shadowColor: 'rgba(0, 0, 0, 0.5)'
+                                    }
+                                }
+                            }
+                        ]
+                    });
+                },
+                initWarehouseCountingRecordsChart() {
+                    this.warehouseCountingRecordsChart.setOption({
+                        title: {
+                            text: '仓库分布',
+                            left: 'left'
+                        },
+                        tooltip: {
+                            trigger: 'item',
+                            formatter: '{a} <br/>{b} : {c} ({d}%)'
+                        },
+                        series: [
+                            {
+                                name: '访问来源',
+                                type: 'pie',
+                                radius: '55%',
+                                center: ['50%', '60%'],
+                                data: this.warehouseCountingRecords,
+                                emphasis: {
+                                    itemStyle: {
+                                        shadowBlur: 10,
+                                        shadowOffsetX: 0,
+                                        shadowColor: 'rgba(0, 0, 0, 0.5)'
+                                    }
+                                }
+                            }
+                        ]
+                    });
+                },
+                initLaborReportsUserGroupsCountChart() {
+                    this.laborReportsUserGroupsCountChart.setOption({
+                        title: {
+                            text: '小组临时工分布',
+                            left: 'left'
+                        },
+                        tooltip: {
+                            trigger: 'item',
+                            formatter: '{a} <br/>{b} : {c} ({d}%)'
+                        },
+                        series: [
+                            {
+                                name: '访问来源',
+                                type: 'pie',
+                                radius: '55%',
+                                center: ['50%', '60%'],
+                                data: this.laborReportsUserGroupsCount,
+                                emphasis: {
+                                    itemStyle: {
+                                        shadowBlur: 10,
+                                        shadowOffsetX: 0,
+                                        shadowColor: 'rgba(0, 0, 0, 0.5)'
+                                    }
+                                }
+                            }
+                        ]
+                    });
+                },
+                initLaborReportsCountingRecords() {
+                    let _this = this;
+                    this.laborReportsCountingRecords.forEach(function (item) {
+                        _this.laborReportsCountingRecordsDateTarget.push(item.date_target);
+                        _this.laborReportsCountingRecordsData.push(item.counter);
+                    });
+                },
+
+                orderCountingRecordApi(orderCountingRecordsUnit) {
+                    if (orderCountingRecordsUnit === '') {
+                        orderCountingRecordsUnit = this.orderCountingRecordsUnit;
+                    }
+                    this.orderCountingRecordsUnit = orderCountingRecordsUnit;
+                    let formData = new FormData();
+                    formData.append('start', this.orderCountingRecordsDate[0]);
+                    formData.append('end', this.orderCountingRecordsDate[1]);
+                    formData.append('unit', orderCountingRecordsUnit);
+                    let _this = this;
+                    axios.post('{{url('apiLocal/control/panel/menu/orderCountingRecordApi')}}', formData).then(function (res) {
+                        if (res.status === 200) {
+                            _this.orderCountingRecords = res.data.orderCountingRecords;
+                            _this.orderCountingRecordsDateTarget = [];
+                            _this.orderCountingRecordsData = [];
+                            _this.initOrderCountingRecords();
+                            _this.initOrderCountingRecordsChart();
+                        }
+                    });
+                },
+                logisticsCountingRecordsApi() {
+                    let formData = new FormData();
+                    formData.append('start', this.logisticsCountingRecordsData[0]);
+                    formData.append('end', this.logisticsCountingRecordsData[1]);
+                    let _this = this;
+                    axios.post('{{url('apiLocal/control/panel/menu/logisticsCountingRecordsApi')}}', formData).then(function (res) {
+                        if (res.status === 200) {
+                            _this.logisticsCountingRecords = res.data.logisticsCountingRecords;
+                            _this.initLogisticsCountingRecordsChart();
+                        }
+                    });
+                },
+
+                warehouseCountingRecordsApi() {
+                    let formData = new FormData();
+                    formData.append('start', this.warehouseCountingRecordsData[0]);
+                    formData.append('end', this.warehouseCountingRecordsData[1]);
+                    let _this = this;
+                    axios.post('{{url('apiLocal/control/panel/menu/warehouseCountingRecordsApi')}}', formData).then(function (res) {
+                        if (res.status === 200) {
+                            _this.warehouseCountingRecords = res.data.warehouseCountingRecords;
+                            _this.initWarehouseCountingRecordsChart();
+                        }
+                    });
+                },
+
+                laborReportsCountingRecordApi(laborReportsCountingRecordUnit) {
+                    if (laborReportsCountingRecordUnit === '') {
+                        laborReportsCountingRecordUnit = this.laborReportsCountingRecordUnit;
+                    }
+                    this.laborReportsCountingRecordUnit = laborReportsCountingRecordUnit;
+                    let formData = new FormData();
+                    formData.append('start', this.laborReportsCountingRecordsDate[0]);
+                    formData.append('end', this.laborReportsCountingRecordsDate[1]);
+                    formData.append('unit', laborReportsCountingRecordUnit);
+                    let _this = this;
+                    axios.post('{{url('apiLocal/control/panel/menu/laborReportsCountingRecordApi')}}', formData).then(function (res) {
+                        if (res.status === 200) {
+                            _this.laborReportsCountingRecords = res.data.laborReportsCountingRecords;
+                            _this.laborReportsCountingRecordsDateTarget = [];
+                            _this.laborReportsCountingRecordsData = [];
+                            _this.initLaborReportsCountingRecords();
+                            _this.initLaborReportsCountingRecordsChart();
+                        }
+                    });
+                },
+                laborReportsUserGroupsCountApi() {
+                    let formData = new FormData();
+                    formData.append('start', this.laborReportsUserGroupsCountDate[0]);
+                    formData.append('end', this.laborReportsUserGroupsCountDate[1]);
+                    let _this = this;
+                    axios.post('{{url('apiLocal/control/panel/menu/laborReportsUserGroupsCountApi')}}', formData).then(function (res) {
+                        if (res.status === 200) {
+                            _this.laborReportsUserGroupsCount = res.data.laborReportsUserGroupsCount;
+                            _this.initLaborReportsUserGroupsCountChart();
+                        }
+                    });
+                },
+            }
+        });
+    </script>
+@endsection
+

+ 1 - 1
resources/views/layouts/app.blade.php

@@ -16,7 +16,7 @@
 <div id="app">
     <nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm">
         <div class="container-fluid">
-            <a class="navbar-brand" href="{{ url('/') }}" title="宝时 Warehouse Assistance System" style="vertical-align: text-bottom">
+            <a class="navbar-brand" href="{{ url('/control/panel/menu') }}" title="宝时 Warehouse Assistance System" style="vertical-align: text-bottom">
                 <img src="{{asset('icon/logo100b.png')}}" alt="宝时 Warehouse Assistance System" height="30" >
             </a>
             <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">

+ 3 - 3
resources/views/layouts/menu.blade.php

@@ -23,7 +23,7 @@
                     <span class="fa fa-truck" style="color: #4c2584"></span>
                     运输管理</a></li> @endcan
         @can('称重管理')
-            <li class="nav-item"><a href="{{url("package/")}}" class="nav-link"
+            <li class="nav-item"><a href="{{url("package")}}" class="nav-link"
                                     :class="{active:isActive('package',1)}">
                     <span class="fa fa-balance-scale" style="color: #1b7234"></span>
                     称重管理</a></li> @endcan
@@ -33,7 +33,7 @@
                     <span class="fa fa-list-alt" style="color: #32721b"></span>
                     库存管理</a></li> @endcan
         @can('二次加工管理')
-            <li class="nav-item"><a href="{{url("process/")}}" class="nav-link"
+            <li class="nav-item"><a href="{{url("process")}}" class="nav-link"
                                     :class="{active:isActive('process',1)}">
                     <span class="fa fa-hand-scissors-o" style="color: #726e1b"></span>
                     二次加工管理</a></li> @endcan
@@ -48,7 +48,7 @@
                     <span class="fa fa-header" style="color: #72441b"></span>
                     人事管理</a></li> @endcan
         @can('基础设置')
-            <li class="nav-item"><a href="{{url("maintenance/")}}" class="nav-link"
+            <li class="nav-item"><a href="{{url("maintenance")}}" class="nav-link"
                                     :class="{active:isActive('maintenance',1)}">
                     <span class="fa fa-server"></span>
                     基础设置</a></li> @endcan

+ 2 - 2
resources/views/maintenance/log/index.blade.php

@@ -41,7 +41,7 @@
                     </tr>
                 </table>
                     @if($logs)
-                    带参分页查询
+                    <!--带参分页查询-->
                     {{$logs->withQueryString()->links()}}
                     @endif
             </div>
@@ -95,7 +95,7 @@
             methods: {
                 logsClick: function (log) {
                     console.log(log);
-                    window.location.href = '{{url('maintenance/log/')}}' + '/' + log.id;
+                    window.open("{{url('maintenance/log')}}"+'/'+log.id,'_blank');
                 }
             }
         });

+ 8 - 2
routes/apiLocal.php

@@ -90,5 +90,11 @@ Route::group(['prefix'=>'maintenance'],function (){
     });
 });
 
-
-
+/** 控制台 */
+Route::group(['prefix'=>'control'],function () {
+    Route::post('panel/menu/orderCountingRecordApi','ControlPanelController@orderCountingRecordsApi') ;
+    Route::post('panel/menu/logisticsCountingRecordsApi','ControlPanelController@logisticsCountingRecordsApi');
+    Route::post('panel/menu/warehouseCountingRecordsApi','ControlPanelController@warehouseCountingRecordsApi');
+    Route::post('panel/menu/laborReportsCountingRecordApi','ControlPanelController@laborReportsCountingRecordApi');
+    Route::post('panel/menu/laborReportsUserGroupsCountApi','ControlPanelController@laborReportsUserGroupsCountApi');
+});

+ 4 - 1
routes/web.php

@@ -587,4 +587,7 @@ Route::group(['prefix'=>'customer'],function(){
     });
     Route::get('relating',function (){return view('customer.relating');});
 });
-
+/** 控制台 */
+Route::group(['prefix'=>'control'],function () {
+   Route::get('panel/menu','ControlPanelController@index') ;
+});

+ 26 - 0
tests/Services/CheckActiveMenuService/CheckActiveMenuServiceActiveMenusTest.php

@@ -0,0 +1,26 @@
+<?php
+
+namespace Tests\Services\CheckActiveMenuService;
+
+use App\Services\CheckActiveMenuService;
+use App\UserVisitMenuLog;
+use Illuminate\Support\Facades\Redis;
+use Tests\TestCase;
+
+class CheckActiveMenuServiceActiveMenusTest extends TestCase
+{
+    /** @var CheckActiveMenuService $checkActiveMenuService */
+    public $checkActiveMenuService;
+
+    public function setUp(): void
+    {
+        parent::setUp();
+        $this->checkActiveMenuService = app('CheckActiveMenuService');
+    }
+
+    public function testActiveMenus()
+    {
+        dd($this->checkActiveMenuService->activeMenus());
+    }
+
+}

+ 24 - 0
tests/Services/CheckActiveMenuService/CheckActiveMenuServiceSetTest.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace Tests\Services\CheckActiveMenuService;
+
+use App\Services\CheckActiveMenuService;
+use PHPUnit\Framework\TestCase;
+
+class CheckActiveMenuServiceSetTest extends TestCase
+{
+
+    /** @var CheckActiveMenuService $checkActiveMenuService */
+    public $checkActiveMenuService;
+
+    public function setUp(): void
+    {
+        parent::setUp();
+        $this->checkActiveMenuService = app('CheckActiveMenuService');
+    }
+
+    public function testSet()
+    {
+//        $this->checkActiveMenuService::set();
+    }
+}

+ 32 - 0
tests/Services/CheckActiveMenuService/CheckActiveMenuSyncTest.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace Tests\Services\CheckActiveMenuService;
+
+use App\Services\CacheService;
+use App\Services\CheckActiveMenuService;
+use App\UserVisitMenuLog;
+use Illuminate\Support\Facades\Redis;
+use Tests\TestCase;
+
+class CheckActiveMenuSyncTest extends TestCase
+{
+    /** @var CheckActiveMenuService $checkActiveMenuService */
+    public $checkActiveMenuService;
+
+    public function setUp(): void
+    {
+        parent::setUp();
+        $this->checkActiveMenuService = app('CheckActiveMenuService');
+    }
+
+    public function testHandle()
+    {
+        $l1Len = Redis::LLEN('UserVisitMenuLogsL1');
+        $l2Len = Redis::LLEN('UserVisitMenuLogsL2');
+        $DBLen = UserVisitMenuLog::query()->count();
+        $this->checkActiveMenuService->sync();
+        $this->assertTrue(Redis::LLEN('UserVisitMenuLogsL1') === 0);
+        $this->assertTrue(Redis::LLEN('UserVisitMenuLogsL2') === $l2Len + $l1Len);
+        $this->assertTrue(UserVisitMenuLog::query()->count() === $DBLen + $l1Len);
+    }
+}

+ 39 - 0
tests/Services/LaborReportsCountingRecordService/ByCacheTest.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace LaborReportsCountingRecordService;
+
+use App\Services\LaborReportsCountingRecordService;
+use Illuminate\Support\Facades\Cache;
+use Tests\TestCase;
+
+class ByCacheTest extends TestCase
+{
+    /** @var LaborReportsCountingRecordService $laborReportsCountingRecordService */
+    public $laborReportsCountingRecordService;
+
+    public function setUp(): void
+    {
+        parent::setUp();
+        $this->laborReportsCountingRecordService = new LaborReportsCountingRecordService();
+    }
+
+    public function testSet()
+    {
+        $dateList = [
+            '2025-10-01',
+            '2025-10-02',
+            '2025-10-03',
+            '2025-10-04',
+            '2025-10-05',
+        ];
+        $unit = '日';
+        foreach ($dateList as $date) {
+            $key = 'laborReportsCountingRecords_' . $date . '_' . $unit;
+            Cache::put($key, '111111111111');
+        }
+        $result = $this->laborReportsCountingRecordService->getByCache($dateList, $unit);
+
+        self::assertTrue($result['dataList']->isnotEmpty());
+        self::assertTrue($result['dateList']==[]);
+    }
+}

+ 48 - 0
tests/Services/LaborReportsCountingRecordService/GetTest.php

@@ -0,0 +1,48 @@
+<?php
+
+namespace LaborReportsCountingRecordService;
+
+use App\Services\CacheService;
+use App\Services\LaborReportsCountingRecordService;
+use App\Services\OrderCountingRecordService;
+use Illuminate\Support\Facades\Cache;
+use Tests\TestCase;
+
+class GetTest extends TestCase
+{
+    /** @var LaborReportsCountingRecordService $laborReportsCountingRecordService */
+    public $laborReportsCountingRecordService;
+
+    public function setUp(): void
+    {
+        parent::setUp();
+        $this->laborReportsCountingRecordService = new LaborReportsCountingRecordService();
+    }
+
+    public function testGet日()
+    {
+        $start = '2020-11-08';
+        $end = '2020-12-19';
+        $unit = '日';
+        $result =  $this->laborReportsCountingRecordService->get($start, $end, $unit);
+        self::assertTrue($result->isNotEmpty());
+    }
+
+    public function testGet周()
+    {
+        $start = '2020-11-08';
+        $end = '2020-12-19';
+        $unit = '周';
+        $result =  $this->laborReportsCountingRecordService->get($start, $end, $unit);
+        self::assertTrue($result->isNotEmpty());
+    }
+
+    public function testGet月()
+    {
+        $start = '2020-08-01';
+        $end = '2020-11-1';
+        $unit = '月';
+        $result =  $this->laborReportsCountingRecordService->get($start, $end, $unit);
+        self::assertTrue($result->isNotEmpty());
+    }
+}

+ 27 - 0
tests/Services/LaborReportsCountingRecordService/UserGroupsCountTest.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace LaborReportsCountingRecordService;
+
+use App\Services\CacheService;
+use App\Services\LaborReportsCountingRecordService;
+use App\Services\OrderCountingRecordService;
+use Illuminate\Support\Facades\Cache;
+use Tests\TestCase;
+
+class UserGroupsCountTest extends TestCase
+{
+    /** @var LaborReportsCountingRecordService $laborReportsCountingRecordService */
+    public $laborReportsCountingRecordService;
+
+    public function setUp(): void
+    {
+        parent::setUp();
+        $this->laborReportsCountingRecordService = new LaborReportsCountingRecordService();
+    }
+
+    public function testUserGroupsCount()
+    {
+        $result =  $this->laborReportsCountingRecordService->userGroupsCount('2020-10-17','2020-11-16');
+        self::assertTrue($result->isNotEmpty());
+    }
+}

+ 20 - 0
tests/Services/OrderCountingRecordService/DateTestTest.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace OrderCountingRecordService;
+
+
+use Carbon\Carbon;
+use DateInterval;
+use DatePeriod;
+use DateTime;
+use Tests\TestCase;
+
+class DateTestTest extends TestCase
+{
+    public function test01()
+    {
+        dd(Carbon::parse('2020-08-15')->monthsUntil('2020-11-13', 1)->toArray());
+
+
+    }
+}

+ 30 - 0
tests/Services/OrderCountingRecordService/OrderCountingRecordServiceGetTest.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace Tests\Services\OrderCountingRecordService;
+
+use App\Services\CacheService;
+use App\Services\OrderCountingRecordService;
+use Tests\TestCase;
+
+class OrderCountingRecordServiceGetTest extends TestCase
+{
+    /** @var OrderCountingRecordService $orderCountingRecordService */
+    public $orderCountingRecordService;
+
+    public function setUp(): void
+    {
+        parent::setUp();
+        app()->singleton('CacheService', CacheService::class);
+        $this->orderCountingRecordService = app(OrderCountingRecordService::class);
+    }
+
+
+    public function testGet()
+    {
+        $start = '2020-11-05';
+        $end = '2020-11-06';
+        dd($this->orderCountingRecordService->get($start, $end, null));
+
+
+    }
+}

+ 30 - 0
tests/Services/OrderCountingRecordService/OrderCountingRecordServiceLogisticsCountingRecordsTest.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace Tests\Services\OrderCountingRecordService;
+
+use App\Services\CacheService;
+use App\Services\OrderCountingRecordService;
+use App\User;
+use Tests\TestCase;
+
+class OrderCountingRecordServiceLogisticsCountingRecordsTest extends TestCase
+{
+    /** @var OrderCountingRecordService $orderCountingRecordService */
+    public $orderCountingRecordService;
+
+    public function setUp(): void
+    {
+        parent::setUp();
+        $this->orderCountingRecordService = app(OrderCountingRecordService::class);
+    }
+
+    public function testLogisticsCountingRecords()
+    {
+        $user =  User::query()->find(1)->first();
+
+        $dataList =  $this->orderCountingRecordService->logisticsCountingRecords('2020-10-01', '2020-11-09',null,$user);
+        self::assertTrue($dataList->isNotEmpty());
+        dd($dataList);
+
+    }
+}

+ 31 - 0
tests/Services/OrderCountingRecordService/OrderCountingRecordServiceOrderCountingRecordsTest.php

@@ -0,0 +1,31 @@
+<?php
+
+namespace Tests\Services\OrderCountingRecordService;
+
+use App\Services\CacheService;
+use App\Services\OrderCountingRecordService;
+use Tests\TestCase;
+
+class OrderCountingRecordServiceOrderCountingRecordsTest extends TestCase
+{
+    /** @var OrderCountingRecordService $orderCountingRecordService */
+    public $orderCountingRecordService;
+
+    public function setUp(): void
+    {
+        parent::setUp();
+        app()->singleton('CacheService', CacheService::class);
+        $this->orderCountingRecordService = app(OrderCountingRecordService::class);
+    }
+
+
+    public function testGet()
+    {
+
+        $start = '2020-11-03';
+        $end = '2020-11-09';
+        dd($this->orderCountingRecordService->orderCountingRecords($start, $end, null));
+
+
+    }
+}

+ 30 - 0
tests/Services/OrderCountingRecordService/OrderCountingRecordServiceWarehouseCountingRecordsTest.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace Tests\Services\OrderCountingRecordService;
+
+use App\Services\CacheService;
+use App\Services\OrderCountingRecordService;
+use App\User;
+use Tests\TestCase;
+
+class OrderCountingRecordServiceWarehouseCountingRecordsTest extends TestCase
+{
+    /** @var OrderCountingRecordService $orderCountingRecordService */
+    public $orderCountingRecordService;
+
+    public function setUp(): void
+    {
+        parent::setUp();
+        $this->orderCountingRecordService = app(OrderCountingRecordService::class);
+    }
+
+    public function testLogisticsCountingRecords()
+    {
+        $user =  User::query()->find(1)->first();
+
+        $dataList =  $this->orderCountingRecordService->warehouseCountingRecords('2020-10-01', '2020-11-09',null,$user);
+        self::assertTrue($dataList->isNotEmpty());
+        dd($dataList);
+
+    }
+}

+ 22 - 0
tests/Services/RealtimePendingOrdersService/RealtimePendingOrdersServiceTest.php

@@ -0,0 +1,22 @@
+<?php
+
+namespace Tests\Services\RealtimePendingOrdersService;
+
+use App\Services\RealtimePendingOrdersService;
+use Tests\TestCase;
+class RealtimePendingOrdersServiceTest extends TestCase
+{
+    /** @var RealtimePendingOrdersService $realtimePendingOrdersService */
+    public $realtimePendingOrdersService;
+
+    public function setUp(): void
+    {
+        parent::setUp();
+        $this->realtimePendingOrdersService = app('RealtimePendingOrdersService');
+    }
+
+    public function testOrders()
+    {
+        dd($this->realtimePendingOrdersService->warehousesOrders()->toArray());
+    }
+}

+ 4 - 1
webpack.mix.js

@@ -18,13 +18,16 @@ mix.copy('resources/icon','public/icon');
 mix.copy('resources/images','public/images');
 mix.copy('resources/icon/faviconc.ico','public/faviconc.ico');
 mix.js('resources/js/trix.js','public/js/trix.js');
-mix.copy('resources/sass/trix.css','public/css/trix.css');
+mix.js('resources/js/echarts.js','public/js/echarts.js');
+mix.copy('resources/sass/trix.css','public/css/initLaborReportsCountingRecords');
 mix.copy('resources/js/queryForm/queryForm.js','public/js/queryForm/queryForm.js');
 mix.copy('resources/js/queryForm/export.js','public/js/queryForm/export.js');
 mix.js('resources/js/queryForm/header.js','public/js/queryForm/header.js');
 
 mix.copy('resources/sound/','public/sound');
 
+mix.js('resources/js/element-ui.js','public/js/element-ui.js');
+mix.copy('resources/sass/element-ui.css','public/css/element-ui.css');
 
 if (mix.inProduction()) {
     mix.version();

+ 20 - 0
yarn.lock

@@ -1473,6 +1473,11 @@ boolbase@^1.0.0, boolbase@~1.0.0:
   resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
   integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
 
+bootstrap-select@^1.13.18:
+  version "1.13.18"
+  resolved "https://registry.npm.taobao.org/bootstrap-select/download/bootstrap-select-1.13.18.tgz#4557119d58dc1159189977161c803962220e4dda"
+  integrity sha1-RVcRnVjcEVkYmXcWHIA5YiIOTdo=
+
 bootstrap@^4.5.0:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.5.0.tgz#97d9dbcb5a8972f8722c9962483543b907d9b9ec"
@@ -4198,6 +4203,11 @@ isstream@~0.1.2:
   resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
   integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
 
+jquery.cookie@^1.4.1:
+  version "1.4.1"
+  resolved "https://registry.npm.taobao.org/jquery.cookie/download/jquery.cookie-1.4.1.tgz#d63dce209eab691fe63316db08ca9e47e0f9385b"
+  integrity sha1-1j3OIJ6raR/mMxbbCMqeR+D5OFs=
+
 jquery@^3.5.1:
   version "3.5.1"
   resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.5.1.tgz#d7b4d08e1bfdb86ad2f1a3d039ea17304717abb5"
@@ -4554,6 +4564,11 @@ lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
   integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
 
+lodash@^4.17.20:
+  version "4.17.20"
+  resolved "https://registry.npm.taobao.org/lodash/download/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
+  integrity sha1-tEqbYpe8tpjxxRo1RaKzs2jVnFI=
+
 loglevel@^1.6.8:
   version "1.6.8"
   resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.8.tgz#8a25fb75d092230ecd4457270d80b54e28011171"
@@ -4807,6 +4822,11 @@ mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1:
   dependencies:
     minimist "^1.2.5"
 
+moment@^2.28.0:
+  version "2.29.1"
+  resolved "https://registry.npm.taobao.org/moment/download/moment-2.29.1.tgz?cache=0&sync_timestamp=1601983320283&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmoment%2Fdownload%2Fmoment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
+  integrity sha1-sr52n6MZQL6e7qZGnAdeNQBvo9M=
+
 move-concurrently@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"

Некоторые файлы не были показаны из-за большого количества измененных файлов