Bläddra i källkod

Merge branch 'master' into Haozi

haozi 4 år sedan
förälder
incheckning
70c47da5ee
69 ändrade filer med 2834 tillägg och 256 borttagningar
  1. 38 21
      app/Console/Commands/CreateWeightStatistic.php
  2. 34 4
      app/DischargeTask.php
  3. 4 0
      app/Filters/OrderIssueFilters.php
  4. 6 6
      app/Filters/RequirementFilters.php
  5. 122 0
      app/Filters/WorkOrderFilters.php
  6. 57 39
      app/Http/Controllers/ControlPanelController.php
  7. 28 1
      app/Http/Controllers/DischargeTaskController.php
  8. 0 2
      app/Http/Controllers/OrderIssueController.php
  9. 92 119
      app/Http/Controllers/StorageController.php
  10. 190 5
      app/Http/Controllers/TestController.php
  11. 43 2
      app/Http/Controllers/WaybillController.php
  12. 9 0
      app/Http/Controllers/WorkOrderChildTypeController.php
  13. 122 0
      app/Http/Controllers/WorkOrderController.php
  14. 9 0
      app/Http/Controllers/WorkOrderTypeController.php
  15. 86 0
      app/Imports/DischargeTaskCostEntryImport.php
  16. 4 4
      app/Jobs/CacheShelfTaskJob.php
  17. 1 1
      app/OrderPackageCountingRecord.php
  18. 6 0
      app/Providers/AppServiceProvider.php
  19. 1 0
      app/Services/CacheShelfService.php
  20. 8 8
      app/Services/DbOpenService.php
  21. 1 0
      app/Services/DischargeTaskService.php
  22. 1 1
      app/Services/MaterialBoxService.php
  23. 6 3
      app/Services/StationService.php
  24. 2 2
      app/Services/StationTaskMaterialBoxService.php
  25. 5 15
      app/Services/StorageService.php
  26. 1 1
      app/Services/WaybillService.php
  27. 13 0
      app/Services/WorkOrderChildTypeService.php
  28. 38 0
      app/Services/WorkOrderService.php
  29. 14 0
      app/Services/WorkOrderTypeService.php
  30. 9 0
      app/Waybill.php
  31. 111 0
      app/WorkOrder.php
  32. 16 0
      app/WorkOrderChildType.php
  33. 21 0
      app/WorkOrderType.php
  34. 14 0
      database/factories/WorkOrderChildTypeFactory.php
  35. 11 0
      database/factories/WorkOrderFactory.php
  36. 12 0
      database/factories/WorkOrderTypeFactory.php
  37. 38 0
      database/migrations/2021_08_03_154931_change_order_package_counting_records_table.php
  38. 42 0
      database/migrations/2021_08_04_093716_create_work_orders_table.php
  39. 32 0
      database/migrations/2021_08_04_101843_create_work_order_types_table.php
  40. 34 0
      database/migrations/2021_08_04_101906_create_work_order_child_types_table.php
  41. 32 0
      database/migrations/2021_08_10_110830_change_express_face_list_column_in_waybills_table.php
  42. 36 0
      database/migrations/2021_08_11_153350_change_dbwl_column_in_waybills_table.php
  43. 18 0
      database/seeds/WorkOrderChildTypeSeeder.php
  44. 16 0
      database/seeds/WorkOrderSeeder.php
  45. 18 0
      database/seeds/WorkOrderTypeSeeder.php
  46. BIN
      resources/images/dbwl/qrCode.jpg
  47. BIN
      resources/images/dbwl/revice.png
  48. 0 1
      resources/js/app.js
  49. BIN
      resources/js/lodop/CLodop_Setup_for_Win32NT.exe
  50. 133 0
      resources/js/lodop/LodopFuncs.js
  51. BIN
      resources/js/lodop/install_lodop32.exe
  52. BIN
      resources/js/lodop/install_lodop64.exe
  53. 37 0
      resources/js/lodop/jquery.PrintArea.js
  54. 2 0
      resources/js/lodop/jquery.js
  55. 50 0
      resources/js/lodop/myAlert.js
  56. 320 0
      resources/js/lodop/myPrintKit.js
  57. 32 7
      resources/views/control/panel.blade.php
  58. 72 0
      resources/views/order/index/delivering.blade.php
  59. 18 3
      resources/views/order/issue/index.blade.php
  60. 199 0
      resources/views/order/workOrder/create.blade.php
  61. 157 0
      resources/views/order/workOrder/index.blade.php
  62. 38 0
      resources/views/personnel/discharge/task/_constEntryImport.blade.php
  63. 51 3
      resources/views/personnel/discharge/task/index.blade.php
  64. 2 2
      resources/views/requirement/index.blade.php
  65. 23 5
      resources/views/store/inStorage/halfChestStorage.blade.php
  66. 276 1
      resources/views/transport/waybill/index.blade.php
  67. 6 0
      routes/apiLocal.php
  68. 8 0
      routes/web.php
  69. 9 0
      webpack.mix.js

+ 38 - 21
app/Console/Commands/CreateWeightStatistic.php

@@ -2,7 +2,15 @@
 
 namespace App\Console\Commands;
 
+use App\Order;
+use App\OrderBin;
 use App\OrderPackageCountingRecord;
+use App\Services\BatchService;
+use App\Services\common\BatchUpdateService;
+use App\Services\DocWaveHeaderService;
+use App\Services\LogService;
+use App\ValueStore;
+use Carbon\Carbon;
 use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Cache;
 use Illuminate\Support\Facades\DB;
@@ -17,28 +25,37 @@ class CreateWeightStatistic extends Command
     {
         $yesterday = date("Y-m-d",strtotime("-1 day"));
         $sql = <<<sql
-SELECT DATE_FORMAT(order_packages.created_at,'%Y-%m-%d') date,
+SELECT DATE_FORMAT(order_packages.created_at,'%Y-%m-%d') date,IFNULL(order_packages.measuring_machine_id, 0) measuring_machine_id,order_packages.owner_id,
 SUM(CASE WHEN order_packages.weighed_at IS NOT NULL THEN 1 ELSE 0 END) AS count,
-COUNT(1) total FROM order_packages LEFT JOIN orders ON order_packages.order_id=orders.id WHERE orders.wms_status != '订单取消'
-AND order_packages.created_at BETWEEN '{$yesterday} 00:00:00' AND '{$yesterday} 23:59:59' GROUP BY date
+COUNT(1) total FROM order_packages LEFT JOIN orders ON order_packages.order_id=orders.id
+WHERE orders.wms_status != '订单取消'
+AND order_packages.created_at BETWEEN '{$yesterday} 00:00:00' AND '{$yesterday} 23:59:59' GROUP BY date,order_packages.measuring_machine_id,order_packages.owner_id
 sql;
-        $result = DB::selectOne(DB::raw($sql));
-        if (!$result)$obj = [
-            "targeted_at"    => $yesterday,
-            "un_weigh_count" => 0,
-            "total_count"    => 0
-        ]; else $obj = [
-            "targeted_at"    => $result->date,
-            "un_weigh_count" => $result->count,
-            "total_count"    => $result->total,
-        ];
-        /** @var \stdClass $model */
-        $model = OrderPackageCountingRecord::query()->create($obj);
-        Cache::put("weight.".$yesterday,[
-            "date"=>$yesterday,
-            "total"=>$model->total_count,
-            "count"=>$model->un_weigh_count,
-            "value"=>$model->total_count ? intval(($model->un_weigh_count/$model->total_count)*100) : 0
-        ]);
+        $result = DB::select(DB::raw($sql));
+        if (!$result) {
+            $obj = [
+                "targeted_at" => $yesterday,
+                "un_weigh_count" => 0,
+                "total_count" => 0,
+                "measuring_machine_id" => 0,
+                "owner_id" => 0
+            ];
+            $model = OrderPackageCountingRecord::query()->create($obj);
+            Cache::put("weight.".$yesterday, $obj);
+        }else{
+            $objs = [];
+            foreach ($result as $v){
+                $obj = [
+                    "targeted_at"    => $v->date,
+                    "un_weigh_count" => $v->count,
+                    "total_count"    => $v->total,
+                    "measuring_machine_id"    => $v->measuring_machine_id,
+                    "owner_id"    => $v->owner_id
+                ];
+                $model = OrderPackageCountingRecord::query()->create($obj);
+                array_push($objs, $obj);
+            }
+            Cache::put("weight.".$yesterday, $objs);
+        }
     }
 }

+ 34 - 4
app/DischargeTask.php

@@ -35,17 +35,34 @@ class DischargeTask extends Model
     ];
 
     protected $fillable = [
-        'owner_id','type','numbers','status',
-        'income_amount','income_unit','income_unit_price','income_total_cost','income_remark',
-        'facilitator_id','expenditure_amount','expenditure_unit','expenditure_unit_price','expenditure_total_cost','expenditure_remark',
-        'income_at','expenditure_at','warehouse_id'
+        'owner_id',  // 货主
+        'type',      // 类型
+        'numbers',   // 任务编号
+        'status',    // 状态
+        'income_amount', // 数量
+        'income_unit',   // 单位
+        'income_unit_price', // 单价
+        'income_total_cost', // 总价
+        'income_remark',     // 备注
+        'facilitator_id',    // 卸货商
+        'expenditure_amount',  // 成本数量
+        'expenditure_unit',    // 成本单位
+        'expenditure_unit_price',  // 成本单价
+        'expenditure_total_cost',  // 成本总价
+        'expenditure_remark',      // 成本备注
+        'income_at',                // 预约时间
+        'expenditure_at',          // 卸货时间
+        'warehouse_id',              // 仓库
+        'created_at',  // 创建时间->卸货任务:预约时间->结算报表:日期
     ];
 
+    // 货主
     function owner(): BelongsTo
     {
         return $this->belongsTo(Owner::class);
     }
 
+    // 卸货商
     function facilitator(): BelongsTo
     {
         return $this->belongsTo(Facilitator::class);
@@ -56,9 +73,22 @@ class DischargeTask extends Model
         return $filters->apply($query);
     }
 
+    // 仓库
     public function warehouse(): BelongsTo
     {
         return $this->belongsTo(Warehouse::class);
     }
 
+    // 任务创建人
+    public function creator(): BelongsTo
+    {
+        return $this->belongsTo(User::class,'creator_id');
+    }
+
+    // 成本录入人
+    public function constEntry():BelongsTo
+    {
+        return $this->belongsTo(User::class,'const_entry_id');
+    }
+
 }

+ 4 - 0
app/Filters/OrderIssueFilters.php

@@ -67,6 +67,7 @@ class OrderIssueFilters
         'user_owner_group',
         'archive_at_start',
         'archive_at_end',
+        'result_explain'
     ];
     protected $array_filter;
     protected $params = [];
@@ -451,4 +452,7 @@ class OrderIssueFilters
         $this->queryBuilder->where('order_issues.archive_at','<=',$archive_at_end.' 23:59:59');
     }
 
+    public function result_explain($result_explain){
+        $this->queryBuilder->where('order_issues.result_explain','like',"%{$result_explain}%");
+    }
 }

+ 6 - 6
app/Filters/RequirementFilters.php

@@ -18,7 +18,7 @@ class RequirementFilters
     protected $queryBuilder;
     protected $filters = [
         'title',
-        'creator_id',
+        'creator',
         'worker_ids',
         'began_at_start',
         'began_at_end',
@@ -26,7 +26,7 @@ class RequirementFilters
         'finished_at_end',
         'created_at_start',
         'created_at_end',
-        'requirement_id',
+        'requirement',
         'status'
     ];
 
@@ -47,9 +47,9 @@ class RequirementFilters
         return $this->queryBuilder;
     }
 
-    public function creator_id($creator_id)
+    public function creator($creator)
     {
-        $this->queryBuilder->where('u];ser_id', $creator_id);
+        $this->queryBuilder->where('user_id', $creator);
     }
 
     private function worker_ids($worker_ids)
@@ -104,8 +104,8 @@ class RequirementFilters
         $this->queryBuilder->where('status', Requirement::$enums['status'][$status]);
     }
 
-    public function requirement_id($requirement_id)
+    public function requirement($requirement)
     {
-        $this->queryBuilder->where('id', $requirement_id);
+        $this->queryBuilder->where('id', $requirement);
     }
 }

+ 122 - 0
app/Filters/WorkOrderFilters.php

@@ -0,0 +1,122 @@
+<?php
+
+
+namespace App\Filters;
+
+use App\WorkOrder;
+use App\WorkOrderChildType;
+use Illuminate\Http\Request;
+
+class WorkOrderFilters
+{
+    protected $request;
+    protected $queryBuilder;
+    protected $filters = [
+        'ids','creator','name','remake','created_at_start','created_at_end','review_at_start','review_at_end','reviewer','word_order_types','word_order_child_types'
+    ];
+    protected $array_filter;
+    protected $params = [
+        'ids','creator','name','remake','created_at_start','created_at_end','review_at_start','review_at_end','reviewer','word_order_types','word_order_child_types'
+    ];
+
+    protected $workOrderTypeQuery;
+
+    protected $workOrderChildQuery;
+
+    public function __construct(Request $request)
+    {
+        $this->request = $request;
+        $this->params = $request->all();
+        $this->array_filter = array_filter($this->request->only($this->filters));
+    }
+
+    public function apply($builder)
+    {
+        $this->queryBuilder = $builder;
+        $this->afterApply();
+        foreach ($this->array_filter as $filter => $value) {
+            if (method_exists($this, $filter)) {
+                $this->$filter($value, $this->queryBuilder);
+            }
+        }
+        $this->beforeApply();
+        return $this->queryBuilder;
+    }
+
+    public function afterApply()
+    {
+        if(isset($this->params['data']))
+            $this->id(explode(',',$this->params['data']));
+    }
+
+    public function beforeApply()
+    {
+        if($this->workOrderChildQuery)
+            $this->queryBuilder->whereIn('work_order_type_id',$this->workOrderChildQuery);
+
+        if ($this->workOrderTypeQuery)
+            $this->queryBuilder->whereIn('work_order_child_id',$this->workOrderChildQuery);
+    }
+
+    public function id($id)
+    {
+        if(is_array($id))$this->queryBuilder->whereIn('work_orders.id',$id);
+        else $this->queryBuilder->where('work_orders.id',$id);
+    }
+
+    // 创建开始时间
+    public function created_at_start($create_at_start)
+    {
+        $this->queryBuilder->where('work_orders.created_at','>=',$create_at_start);
+    }
+    // 创建结束时间
+    public function created_at_end($created_at_end)
+    {
+        $this->queryBuilder->where('work_orders.created_at','<=',$created_at_end);
+    }
+    // 审核开始时间
+    public function review_at_start($review_at_start)
+    {
+        $this->queryBuilder->where('work_orders.review_at','>=',$review_at_start);
+    }
+    // 审核结束时间
+    public function review_at_end($review_at_end)
+    {
+        $this->queryBuilder->where('work_orders.review_at','<=',$review_at_end);
+    }
+    // 创建人
+    public function creator($id)
+    {
+        if (is_array($id))
+            $this->queryBuilder->whereIn('work_orders.creator_id',$id);
+        else
+            $this->queryBuilder->where('work_orders.creator_id',$id);
+    }
+    // 审核人
+    public function reviewer($id)
+    {
+        if (is_array($id))
+            $this->queryBuilder->whereIn('work_orders.reviewer_id',$id);
+        else
+            $this->queryBuilder->where('work_orders.reviewer_id',$id);
+    }
+
+    // 类型
+    public function word_order_types($word_order_types)
+    {
+        if(!$this->workOrderTypeQuery)
+            $this->workOrderTypeQuery = WorkOrder::query()->select('id');
+        if (is_array($word_order_types))
+            $this->workOrderTypeQuery->whereIn('id',$word_order_types);
+        else $this->workOrderTypeQuery->where('id',$word_order_types);
+    }
+    // 子类型
+    public function word_order_child_types($word_order_child_types)
+    {
+        if(!$this->workOrderTypeQuery)
+            $this->workOrderChildQuery = WorkOrderChildType::query()->select('id');
+        if (is_array($word_order_child_types))
+            $this->workOrderChildQuery->whereIn('id',$word_order_child_types);
+        else $this->workOrderChildQuery->where('id',$word_order_child_types);
+    }
+}

+ 57 - 39
app/Http/Controllers/ControlPanelController.php

@@ -7,6 +7,7 @@ use App\Filters\OrderPackageReceivedSyncRecordFilters;
 use App\OrderPackageCountingRecord;
 use App\OrderPackageReceivedSyncRecord;
 use App\Owner;
+use App\MeasuringMachine;
 use App\Services\CacheService;
 use App\Services\CheckActiveMenuService;
 use App\Services\LaborReportsCountingRecordService;
@@ -124,41 +125,49 @@ class ControlPanelController extends Controller
         //转化为Carbon
         $start = Carbon::parse(request("start"));
         $end   = Carbon::parse(request("end"));
+        $owner = request("owner_ids");
 
         //定义三个数组 空间换时间 避免结果集二次转换
         $title = []; //标题
         $data = []; //核心数据,二维数组
-        foreach (CarbonPeriod::create($start,$end) as $date){
-            /** @var $date Carbon */
-            $str = $date->format("Y-m-d");
-            $data = $this->getTargetData($str);
-            $title[] = $str;
-        }
-
         //大于31天转换为月份显示
         if ($end->diffInDays($start) > 31){
+            $time1 = strtotime($start);
+            $time2 = strtotime($end);
             $title = [];
-            $sign = []; //标记是否已被插入
-            $dataTemp = []; //临时存储
-
-            foreach ($data as $datum){
-                $month = substr($datum["date"],0,7);
-                if (!isset($sign[$month])){
-                    $dataTemp[] = ["date"=>$month,"total"=>$datum["total"],"count"=>$datum["count"],"value"=>$datum["value"]];
-                    $title[] = $month;
-                    $sign[$month] = count($dataTemp)-1;
-                }else{
-                    $dataTemp[$sign[$month]]["total"] += $datum["total"];
-                    $dataTemp[$sign[$month]]["count"] += $datum["count"];
-                    $dataTemp[$sign[$month]]["value"] = (string)($dataTemp[$sign[$month]]["total"] ? intval(($dataTemp[$sign[$month]]["count"]/$dataTemp[$sign[$month]]["total"])*100) : 0);
-                }
+            do{
+                $str = date('Y-m',$time1); // 取得递增月;
+                $data[] = $this->getTargetData($str, $owner);
+                $title[] = $str;
+            }while( ($time1 = strtotime('+1 month', $time1)) <= $time2);
+            $start = $title[0];
+        }else{
+            foreach (CarbonPeriod::create($start,$end) as $date){
+                /** @var $date Carbon */
+                $str = $date->format("Y-m-d");
+                $data[] = $this->getTargetData($str, $owner);
+                $title[] = $str;
             }
-            $data = $dataTemp;
+            $start = date('Y-m-d', strtotime($start));
         }
 
+        $machines = MeasuringMachine::query()->select(['id','name'])->get()->toArray();
+        array_unshift($machines, ['id' => 0, 'name'=>'未知']);
+        array_unshift($machines, ['id' => '未称重','name'=>'未称重']);
+
+        //data数据处理
+        $real_data = [];
+        foreach ($machines as $v){
+            $temp = [$v['name']];
+            foreach ($data as $val){
+                array_push($temp, array_column($val, $v['id'])? array_sum( array_column($val, $v['id'])) : 0);
+            }
+            array_push($real_data,$temp);
+        }
         array_unshift($title, 'product');
-        array_unshift($data, $title);
-        $this->success(["title"=>date("Y-m-d",strtotime($start)),"data"=>$data]);
+        array_unshift($real_data, $title);
+
+        $this->success(["title"=> $start,"data"=>$real_data]);
     }
 
 
@@ -209,36 +218,45 @@ class ControlPanelController extends Controller
      * @param string $date
      * @return array|null
      */
-    private function getTargetData(string $date)
+    private function getTargetData(string $date, array $owner = [])
     {
-        $res = [];
-        if ($date == date("Y-m-d",1622908800)){
+        $res = [];$where='';$no_weight  = 0;
+        if ($owner) $where = " and order_packages.owner_id in (".implode(',',$owner).")";
+        if ($date == date("Y-m-d")){
             $sql = <<<sql
-SELECT DATE_FORMAT(order_packages.created_at,'%Y-%m-%d') date,IFNULL(mm.name,'未知') name ,
+SELECT DATE_FORMAT(order_packages.created_at,'%Y-%m-%d') date,IFNULL(order_packages.measuring_machine_id, 0) measuring_machine_id,
 SUM(CASE WHEN order_packages.weighed_at IS NOT NULL THEN 1 ELSE 0 END) AS count,
 COUNT(1) total FROM order_packages LEFT JOIN orders ON order_packages.order_id=orders.id
-LEFT JOIN measuring_machines AS mm ON mm.id = order_packages.measuring_machine_id
-WHERE orders.wms_status != '订单取消'
+WHERE orders.wms_status != '订单取消'  {$where}
 AND order_packages.created_at like '{$date}%' GROUP BY date,order_packages.measuring_machine_id
 sql;
             //todo 新写
             $info = DB::select(DB::raw($sql));
-            if (!$info) return  $res;
-            $no_weight  =  isset($info[0]->name)  && $info[0]->name == '未知' ? $info[0]->total - $info[0]->count : 0;
+            if (empty($info)) return  $res;
             foreach ($info as $v){
-                $res[] = [$v->name,$v->count];
+                $res[] = [$v->measuring_machine_id,(int)$v->count];
+                $no_weight += (int)($v->total - $v->count);
             }
             array_push($res, ['未称重',$no_weight]);
         }else{
-            $info = app(CacheService::class)->getOrExecute("weight.".$date,function ()use($date){
-                return OrderPackageCountingRecord::query()->where("targeted_at",$date)->get()->toArray();
+            $info = app(CacheService::class)->getOrExecute("weight.".$date.($owner?implode(',',$owner):''),function ()use($date,$owner){
+                return OrderPackageCountingRecord::query()
+                    ->where(function ($query)use($date, $owner){
+                        if($owner)return $query->whereIn('owner_id',$owner);
+                        if ( strlen($date) > 8 ) {
+                            return $query->where('targeted_at',$date);
+                        }else{
+                            return $query->where('targeted_at', 'like',$date.'%');
+                        }
+                    })
+                    ->get()->toArray();
             },config("cache.expirations.forever"));
-            if (array_key_exists('date',$info)) return  $res;
-            $no_weight  =  isset($info[0]->name)  && $info[0]->name == '未知' ? $info[0]->total - $info[0]->count : 0;
+            if (empty($info)) return  $res;
             foreach ($info as $v){
-                $res[] = [$v->name,$v->count];
+                $res[] = [$v['measuring_machine_id']=>(int)$v['un_weigh_count']];
+                $no_weight += (int)($v['total_count'] - $v['un_weigh_count']);
             }
-            array_push($res, ['未称重',$no_weight]);
+            array_push($res, ['未称重'=>$no_weight]);
         }
         return $res;
     }

+ 28 - 1
app/Http/Controllers/DischargeTaskController.php

@@ -7,9 +7,11 @@ use App\Facilitator;
 use App\DischargeTask;
 use App\Filters\DischargeTaskFilters;
 use App\Http\Requests\DischargeTask\DischargeTaskRequest;
+use App\Imports\DischargeTaskCostEntryImport;
 use App\Imports\DischargeTaskImport;
 use App\Owner;
 use App\Role;
+use App\Services\DischargeTaskService;
 use App\Services\OwnerService;
 use App\Services\UserService;
 use App\Warehouse;
@@ -84,6 +86,7 @@ class DischargeTaskController extends Controller
         $result = app('DischargeTaskService')->updateDischargeTask($dischargeTask, $request->all());
 
         if ($result['success']) $this->success($result['data']);
+
         else $this->error($result['message'] ?? '操作异常,请刷新页面重试');
     }
 
@@ -137,7 +140,7 @@ class DischargeTaskController extends Controller
             $dischargeTasks = DischargeTask::query()->with(['Facilitator', 'owner'])->filter($filters)->whereIn('owner_id', data_get($owners, '*.id'))->orderByDesc('id')->get();
         }
 
-        $row = ['日期', '客户名称', '作业名称', '入库单号', '数量', '单位', '单价', '收费', '状态', '备注'];
+        $row = ['日期','仓库', '客户名称', '作业名称','入库单号', '数量', '单位', '单价', '收费', '状态', '备注'];
         $json = app('DischargeTaskService')->getJson($dischargeTasks);
 
         return Export::make($row, $json, "卸货任务");
@@ -182,6 +185,30 @@ class DischargeTaskController extends Controller
         return ['success' => true];
     }
 
+    public function constEntryImportApi(Request $request): array
+    {
+        $this->gate('人事管理-卸货-成本录入');
+        $extension = $request->file()['file']->getClientOriginalExtension();
+        $flag = !in_array($extension, ['xlsx', 'xlsm', 'xltx', 'xltm', 'xls', 'xlt', 'ods', 'ots', 'slk', 'xml', 'gnumeric', 'htm', 'html', 'csv', 'tsv']);
+        if ($flag){
+            return ['success' => false, 'message' => '请检查导入文件是否符合要求'];
+        }
+
+        $extension[0] = strtoupper($extension[0]);
+
+        try {
+            Excel::import(new DischargeTaskCostEntryImport(), $request->file()['file']->path(), null, $extension);
+        } catch (\Exception $e) {
+            return ['success' => false, 'message' => ['请检查导入文件是否符合要求']];
+        }
+
+        $exception=Cache::get('exception');
+        $numbers=Cache::get('numbers');
+
+        if ($exception) return ['success' => false, 'errors' => $exception,'message' => $numbers];
+        return ['success' => true];
+    }
+
 
     public function show(DischargeTask $dischargeTask)
     {

+ 0 - 2
app/Http/Controllers/OrderIssueController.php

@@ -44,8 +44,6 @@ class OrderIssueController extends Controller
         }
         $owners = app(OwnerService::class)->getAuthorizedOwners();
         $orderIssues = OrderIssue::query()->filter($filter)->defaultWith()->paginate($request['paginate'] ?? 50);
-//        $orderIssues = OrderIssue::query()->filter($filter)->defaultWith()->toSql();
-//        dd($orderIssues);
         $orderIssueType = OrderIssueType::all();
         $qualityLabel = QualityLabel::all();
         $logistics = Logistic::all();

+ 92 - 119
app/Http/Controllers/StorageController.php

@@ -192,8 +192,12 @@ sql;
     public function acquireBox()
     {
         $this->gate("入库管理-入库-半箱补货入库");
-
-        list($track, $barCode, $lotNum, $amount) = request()->only(["track","barCode","lotNum","amount"]);
+        $param = request()->only(["track","barCode","lotNum","amount","call"]);
+        $track = $param["track"] ?? null;
+        $barCode = $param["barCode"] ?? null;
+        $lotNum = $param["lotNum"] ?? null;
+        $amount = $param["amount"] ?? null;
+        $manualCall = $param["call"] ?? false;
         if (!$track || !$barCode || !$lotNum || !$amount)$this->error("提交信息不完整");
 
         $sql = <<<SQL
@@ -206,7 +210,7 @@ WHERE FMID = ? AND FMLOTNUM = ? AND
   AND TASKPROCESS = '00' AND TASKTYPE = 'PA'
 GROUP BY FMID,FMLOTNUM,TSK_TASKLISTS.SKU,TSK_TASKLISTS.CUSTOMERID
 SQL;
-        $task = DB::connection("oracle")->selectOne(DB::raw($sql));
+        $task = DB::connection("oracle")->selectOne(DB::raw($sql),[$track,$lotNum,$barCode,$barCode,$barCode]);
         if (!$task || $task->qty<$amount)$this->error("待上架数量不足");
         $commodity = Commodity::query()->whereHas("owner",function ($query)use($task){
             $query->where("code",$task->customerid);
@@ -219,7 +223,7 @@ SQL;
             $query->where("commodity_id",$commodity->id);
         }]);
         $models = $models->whereNotNull("commodity");
-        if ($models->count()==0)$this->success(["status"=>false]);
+        if ($models->count()==0)$this->success(["status"=>false,"commodityId"=>$commodity->id]);
 
         //设定一个默认缓存架 仅用于任务占位 没有实际作用
         $defaultStation = Station::query()->where("station_type_id",5)
@@ -259,19 +263,44 @@ SQL;
                 return $task;
             };
 
-            $stations = app("StationService")->getCacheShelf(true);
+            $stations = app("StationService")->getCacheShelf(true,true);
             $collection = collect();
             $location = collect();
             $ids = [];
             //寻找半箱
-            foreach ($models as $model){
-                list($invs,$map) = app("StorageService")->getMaxAvailableHalfBoxLocation($model->commodity, request("lotNum"));
-                if (!$invs)continue;
+            $sql = <<<SQL
+SELECT LOCATIONID,QTY FROM INV_LOT_LOC_ID WHERE LOTNUM = '{$lotNum}'
+AND LOCATIONID LIKE 'IDE%' AND SKU = '{$commodity->sku}' AND TRACEID = '*' AND QTY > 0 AND QTY > 0 ORDER BY QTY
+SQL;
+            $invs = DB::connection("oracle")->select(DB::raw($sql));
+            if ($invs){
+                $map = [];
+                $codes = [];
                 foreach ($invs as $inv){
+                    $map[$inv->locationid] = $inv->qty;
+                    $codes[] = $inv->locationid;
+                }
+                $modelMap = [];
+                $orderBy = "CASE material_box_model_id ";
+                foreach ($models as $key=>$model){
+                    $orderBy .= 'WHEN '.$model->id." THEN ".$key;
+                    $modelMap[$model->id] = $model->commodity->maximum;
+                }
+                $orderBy.= " END";
+                $boxes = MaterialBox::query()->whereIn("code",$codes)->orderByRaw($orderBy)->lockForUpdate()->get();
+                //筛选下海柔可用箱
+                list($codes,$notCodes) = app("MaterialBoxService")->checkHaiQ(array_column($boxes->toArray(),"code"));
+                if (!$codes)$boxes = new \Illuminate\Database\Eloquent\Collection();
+                $boxes = $boxes->filter(function ($box)use($codes,$notCodes){
+                    if (!isset($codes[$box->code]) || isset($notCodes[$box->code]))return false;
+                    return true;
+                });
+                foreach ($boxes as $box){
+                    if ($modelMap[$box->material_box_model_id]<=$map[$box->code])continue;
+                    $num = $modelMap[$box->material_box_model_id]-$map[$box->code];
                     $station = $stations->last();
-                    $boxId = $map[$inv->locationid];
-                    $number = $amount >= $inv->qty ? $amount-$inv->qty : $amount;
-                    $task = $exe($station, $boxId, $number);
+                    $number = $amount >= $num ? $amount-$num : $amount;
+                    $task = $exe($station, $box->id, $number);
                     if ($station){
                         $stations->offsetUnset($stations->count()-1);
                         $collection->push($task);
@@ -281,8 +310,8 @@ SQL;
                     $amount -= $number;
                     if ($amount==0)break;
                 }
-                if ($amount==0)break;
             }
+
             if ($amount){
                 //寻找空箱
                 $blacklist = [];//空箱逐一寻找需要列队黑名单
@@ -308,7 +337,8 @@ SQL;
             if ($location->count()){
                 /** @var ForeignHaiRoboticsService $service */
                 $service = app("ForeignHaiRoboticsService");
-                $result = $service->fetchGroup_multiLocation($location,$collection,'','立架出至缓存架');
+                if ($manualCall)$result = $this->mergeIntoCache($location,$collection);
+                else $result = $service->fetchGroup_multiLocation($location,$collection,'','立架出至缓存架');
                 if (!$result){
                     DB::rollBack();
                     $this->error("机器人呼叫失败,海柔任务错误");
@@ -335,105 +365,35 @@ SQL;
     }
 
     /**
-     * 取得料箱 废弃
+     * 并入缓存 等待呼叫
+     *
+     * @param Collection $location
+     * @param Collection $collection
+     *
+     * @return bool
      */
-    public function acquireBoxTemp()
+    public function mergeIntoCache(Collection $location,Collection $collection):bool
     {
-        $this->gate("入库管理-入库-半箱补货入库");
-        $boxId = request("material_box_id");
-        $modelId = request("material_box_model_id");
-        if (!$modelId)$this->error("商品未设定库存上限");
-        //获取目标库位
-        $station = app("StationService")->getMirrorMappingLocation(request("station"));
-        if (!$station)$this->error("未知库位");
-        $isAvailable = app("StationService")->isAvailable($station);
-        if (!$isAvailable)$this->error("库存被占用或存在任务未处理");
-        $amount = app("StorageService")->checkPutAmount(request("track"),request("barCode"),request("lotNum"));
-        if ($amount<request("amount"))$this->error("待上架数量不足,最大可上数量为{$amount}");
-
-        //发起取箱任务
-        $exe = function ($boxId)use($station,$amount){
-            DB::beginTransaction();
-            try{
-                $collection = new Collection();
-                $task = StationTask::query()->create([
-                    'status' => "待处理",
-                    'station_id' => $station->id,
-                ]);
-                $collection->add(StationTaskMaterialBox::query()->create([
-                    'station_id' => $station->id,
-                    'material_box_id'=>$boxId,
-                    'status'=>"待处理",
-                    'type' => '取',
-                    'station_task_id' => $task->id,
-                ]));
-                if (!app("ForeignHaiRoboticsService")->fetchGroup($station->code,$collection,'','立架出至缓存架'))$this->error("呼叫机器人失败");
-                //生成临时任务事务
-                TaskTransaction::query()->create([
-                    //"doc_code" => request("asn"),
-                    "bar_code" => request("barCode"),
-                    "fm_station_id" => $station->id,
-                    "material_box_id" => $boxId,
-                    "commodity_id" => request("commodity_id"),
-                    "amount" => request("amount"),
-                    "type" => "入库",
-                    "user_id" => Auth::id(),
-                    "mark" => 1,
-                    "lot_num" => request("lotNum"),
-                    "track_num" => request("track"),
-                ]);
-                //亮灯
-                app("CacheShelfService")->lightUp($station->code,'3','0');
-                app("StationService")->locationOccupy($station->code);//占用库位
-                Cache::forever("CACHE_SHELF_OCCUPANCY_{$station->id}",true);
-                DB::commit();
-                return true;
-            }catch (\Exception $e){
-                DB::rollBack();
-                return false;
-            }
-        };
-        //检查获取的料箱仍然可用
-        if ($boxId && app("MaterialBoxService")->checkUsableBox($boxId))$this->success(["status"=>$exe($boxId),"amount"=>$amount-request("amount")]);
-
-        $commodity = Commodity::query()->find(request("commodity_id"));
-        if (!$commodity)$this->error("商品在WAS丢失");
-        $models = app("MaterialBoxModelService")->getModelSortedByOwner($commodity->owner_id);
-        $models->load(["commodity"=>function($query)use($commodity){
-            $query->where("commodity_id",$commodity->id);
-        }]);
-        //获取料箱
-        if ($boxId){
-            $blacklist = [$boxId];
-            $boxId = null;
-            //料箱存在且不可用
-            /** @var \Illuminate\Database\Eloquent\Collection $models */
-            foreach ($models as $model){
-                if (!$model->commodity)continue;
-                //料箱不可用寻找新料箱
-                $result = app("StorageService")->getMaxAvailableHalfBoxLocation($model->commodity, request("lotNum"), $blacklist);
-                while ($result){
-                    $materialBox = MaterialBox::query()->where("code",$result->locationid)->first();
-                    //料箱可用并且数量符合本次半箱数量 跳出
-                    if ($materialBox && app("MaterialBoxService")->checkUsableBox($materialBox->id)
-                        && $result->qty>=request("amount"))$this->success(["status"=>$exe($materialBox->id),"amount"=>$amount-request("amount")]);
-                    else if ($materialBox)$blacklist[] = $materialBox->id;
-                    //否则黑名单此料箱继续查找 直至料箱为空
-                    $result = app("StorageService")->getMaxAvailableHalfBoxLocation($model->commodity, request("lotNum"), $blacklist);
-                }
-            }
+        $key = "CACHE_SHELF_CALL_".Auth::id();
+        if (Cache::has($key)){
+            list($locationAdd,$collectionAdd) = Cache::get($key);
+            $location = $locationAdd->merge($location);
+            $collection = $collectionAdd->merge($collection);
         }
-        //料箱不存在且该商品有过入库记录 拿取空箱
-        if (!$modelId){
-            $box = null;
-            foreach ($models as $model){
-                if (!$model->commodity)continue;
-                $box = app("MaterialBoxService")->getAnEmptyBox($model);
-                if($box)break;
-            }
-        }else $box = app("MaterialBoxService")->getAnEmptyBox(MaterialBoxModel::query()->find($modelId));
-        if (!$box)$this->error("无可用料箱");
-        $this->success(["status"=>$exe($box->id),"amount"=>$amount-request("amount")]);
+        return Cache::forever($key,[$location,$collection]);
+    }
+
+    public function callRobot()
+    {
+        /** @var ForeignHaiRoboticsService $service */
+        $service = app("ForeignHaiRoboticsService");
+        $key = "CACHE_SHELF_CALL_".Auth::id();
+        list($location,$collection) = Cache::get($key);
+        if ($location->count()==0||$collection->count()==0)$this->error("没有可执行任务");
+        $res = $service->fetchGroup_multiLocation($location,$collection,'','立架出至缓存架');
+        if (!$res)$this->error("呼叫失败,海柔拒绝任务");
+        Cache::forget($key);
+        $this->success();
     }
 
     /**
@@ -448,16 +408,28 @@ SQL;
         $box = MaterialBox::query()->where("code",$ide)->first();
         if (!$box)$this->error("未知料箱");
 
-        $task = TaskTransaction::query()->where("material_box_id",$box->id)->where("amount",">",$amount)
-            ->where("type","入库")->where("mark",1)->where("status",0)->first();
-        if (!$task)$this->error("无任务存在");
-        $task->update(["amount" => DB::raw("amount - {$amount}")]);
-        $storage = MaterialBoxCommodity::query()->where("material_box_id",$task->material_box_id)
-            ->where("commodity_id",$task->commodity_id)->first();
-        $maximum = (($storage->amount ?? 0)+$task->amount)-$amount;
-        CommodityMaterialBoxModel::query()->where("material_box_model_id",$task->materialBox->material_box_model_id)
-            ->where("commodity_id",$task->commodity_id)->update(["maximum"=>$maximum]);
-        $this->success("校正成功");
+        DB::beginTransaction();
+        try {
+            $task = TaskTransaction::query()->where("material_box_id",$box->id)->where("amount",">=",$amount)
+                ->where("type","入库")->where("mark",1)->where("status",0)->lockForUpdate()->first();
+            if (!$task)$this->error("无任务存在");
+            if ($task->amount == $amount){
+                $station = Station::query()->find($task->fm_station_id);
+                app("CacheShelfService")->lightUp($station->code);
+                $task->delete();
+            }
+            else $task->update(["amount" => DB::raw("amount - {$amount}")]);
+            $storage = MaterialBoxCommodity::query()->where("material_box_id",$task->material_box_id)
+                ->where("commodity_id",$task->commodity_id)->first();
+            $maximum = (($storage->amount ?? 0)+$task->amount)-$amount;
+            CommodityMaterialBoxModel::query()->where("material_box_model_id",$task->materialBox->material_box_model_id)
+                ->where("commodity_id",$task->commodity_id)->update(["maximum"=>$maximum]);
+            DB::commit();
+            $this->success("校正成功");
+        }catch (\Exception $e){
+            DB::rollBack();
+            $this->error("校正失败");
+        }
     }
 
     public function syncStorage()
@@ -588,6 +560,7 @@ sql;
      */
     public function settingModelMaximum()
     {
+        if (!request("commodityId"))$this->error("未获取商品");
         $insert = function ($commodityId){
             $in = [];
             $ids = [];

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

@@ -2,10 +2,13 @@
 
 namespace App\Http\Controllers;
 
+use App\Commodity;
+use App\CommodityMaterialBoxModel;
 use App\Components\AsyncResponse;
 use App\Components\ErrorPush;
 use App\ErrorTemp;
 use App\Feature;
+use App\Jobs\CacheShelfTaskJob;
 use App\Jobs\OrderCreateWaybill;
 use App\MaterialBox;
 use App\MaterialBoxModel;
@@ -13,18 +16,23 @@ use App\Order;
 use App\Owner;
 use App\OwnerFeeDetail;
 use App\OwnerPriceOperation;
+use App\OrderPackageCountingRecord;
 use App\RejectedBill;
 use App\Services\ForeignHaiRoboticsService;
+use App\Services\StationService;
+use App\Services\StorageService;
 use App\Station;
 use App\StationTask;
 use App\StationTaskMaterialBox;
 use App\TaskTransaction;
 use App\Unit;
 use App\Waybill;
+use Carbon\Carbon;
+use Carbon\CarbonPeriod;
 use Illuminate\Database\Eloquent\Collection;
 use Illuminate\Http\Request;
-use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Cookie;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Http;
@@ -58,12 +66,189 @@ class TestController extends Controller
         $response = Http::post(config('api.haiq.storage.light'), $params);
         return json_decode($response->body());
     }
-    private $key = "CACHE_SHELF_AVAILABLE";
+
     public function test()
     {
-        $w = Waybill::query()->first();
-        $w->loadCount(["waybillAuditLogs"]);
-        dd($w);
+        app("CacheShelfService")->_stationCacheLightOff("HAIB1-01-01");
+        app("CacheShelfService")->_stationCacheLightOff("HAIB1-01-02");
+        app("CacheShelfService")->_stationCacheLightOff("HAIB1-02-02");
+        dd(1);
+        $stationTaskMaterialBox = StationTaskMaterialBox::query()->find(70370);
+        DB::beginTransaction();
+        try{
+            $stationTaskMaterialBox->loadMissing("station");
+            //如果为半箱位置 清理原有任务
+            if (!$stationTaskMaterialBox->station)return;
+            if (app("StationService")->isHalfBoxLocation($stationTaskMaterialBox->station)){
+                app("StationService")->locationOccupy($stationTaskMaterialBox->station->code,$stationTaskMaterialBox->material_box_id);
+                //清除海柔库位信息
+                app("StorageService")->clearTask([$stationTaskMaterialBox->station->code]);
+                $stationId = $stationTaskMaterialBox->station_id;
+                $tasks = TaskTransaction::query()->with("materialBox")->where(function ($query)use($stationId){
+                    $query->where("fm_station_id",$stationId)->orWhere("to_station_id",$stationId);
+                })->where("status",0)->get();
+                if ($tasks->count()!=0){
+                    $options = [];
+                    switch ($tasks[0]->mark){
+                        case 1:
+                            $options["title"] = '上架任务';
+                            break;
+                        case 2:
+                            $options["title"] = '出库任务';
+                            break;
+                        default:
+                            $options["title"] = '未知类型';
+                    }
+                    switch ($tasks->count()){
+                        case 1:
+                            $task = $tasks[0];
+                            $options["detail01"] = $task->materialBox->code ?? '';
+                            $options["detail02"] = $task->doc_code ?: '跟踪:‘'.$task->track_num."’ 批次:‘".$task->lot_num."’";
+                            $options["detail03"] = $task->bar_code;
+                            $options["qty01"] = $task->amount;
+                            $options["uomDesc01"] = '件';
+                            $options["qty02"] = $task->bin_number;
+                            $options["uomDesc02"] = '号';
+                            break;
+                        default:
+                            $count = count(array_unique(array_column($tasks->toArray(),"commodity_id")));
+                            if ($count==1){
+                                $options["detail01"] = $tasks[0]->bar_code;
+                                $options["detail02"] = "";
+                                $options["detail03"] = "";
+                                $amount = 0;
+                                foreach ($tasks as $task){
+                                    if (mb_strlen($options["detail02"])>20){
+                                        $options["detail03"] .= $task->bin_number."号-".$task->amount."件,";
+                                    }else $options["detail02"] .= $task->bin_number."号-".$task->amount."件,";
+                                    $amount += $task->amount;
+                                }
+                                $options["detail02"] = rtrim($options["detail02"],",");
+                                $options["detail03"] = rtrim($options["detail03"],",");
+                                $options["qty02"] = $amount;
+                                $options["uomDesc02"] = '件';
+                            }else{
+                                $task = $tasks[0];
+                                $options["detail01"] = $task->materialBox->code ?? '';
+                                $options["detail02"] = "货品过多请自行核对";
+                                $options["detail03"] = "波次:".$task->doc_code ?
+                                    (Order::query()->with("batch")->where("code",$task->doc_code)->first()->batch->code ?? '无') : '无';
+                            }
+                            break;
+                    }
+                    app("CacheShelfService")->lightUp($stationTaskMaterialBox->station->code,'2','0',$options);
+                    Cache::forget("CACHE_SHELF_OCCUPANCY_{$stationTaskMaterialBox->station->id}");//关闭无限亮灯
+                }
+            }else app("StationService")->locationFreed($stationTaskMaterialBox->station->code); //释放库位占用
+            DB::commit();
+            dd("OK");
+        }catch (\Exception $e){
+            DB::rollBack();
+            dd($e->getTrace());
+        }
+
+
+    }
+
+    //快递称重 生成历史数据
+    public function addRecord(Request $request)
+    {
+        ini_set('max_execution_time',-1);
+        OrderPackageCountingRecord::query()->truncate();
+        $start =  Carbon::parse(request("month"))->startOfMonth();
+        $end = Carbon::parse(request('month'))->endOfMonth();
+
+        foreach (CarbonPeriod::create($start,$end) as $date){
+            /** @var $date Carbon */
+            $yesterday = $date->format("Y-m-d");
+            $sql = <<<sql
+SELECT DATE_FORMAT(order_packages.created_at,'%Y-%m-%d') date,IFNULL(order_packages.measuring_machine_id,0) measuring_machine_id,order_packages.owner_id,
+SUM(CASE WHEN order_packages.weighed_at IS NOT NULL THEN 1 ELSE 0 END) AS count,
+COUNT(1) total FROM order_packages LEFT JOIN orders ON order_packages.order_id=orders.id
+WHERE orders.wms_status != '订单取消'
+AND order_packages.created_at BETWEEN '{$yesterday} 00:00:00' AND '{$yesterday} 23:59:59' GROUP BY date,order_packages.measuring_machine_id,order_packages.owner_id
+sql;
+            $result = DB::select(DB::raw($sql));
+            if (!$result) {
+                $obj = [
+                    "targeted_at" => $yesterday,
+                    "un_weigh_count" => 0,
+                    "total_count" => 0,
+                    "measuring_machine_id" => 0,
+                    "owner_id" => 0
+                ];
+                $model = OrderPackageCountingRecord::query()->create($obj);
+                Cache::put("weight.".$yesterday, $obj);
+            }else{
+                $objs = [];
+                foreach ($result as $v){
+                    $obj = [
+                        "targeted_at"    => $v->date,
+                        "un_weigh_count" => $v->count,
+                        "total_count"    => $v->total,
+                        "measuring_machine_id"    => $v->measuring_machine_id,
+                        "owner_id"    => $v->owner_id
+                    ];
+                    $model = OrderPackageCountingRecord::query()->create($obj);
+                    array_push($objs, $obj);
+                }
+                Cache::put("weight.".$yesterday, $objs);
+            }
+        }
     }
 
+    public function redis()
+    {
+        $start = 1606752000;$end = 1627747200;
+        $len = ($end - $start) / 86400;
+        for ($i=0; $i <= $len ; $i ++){
+            $date = date("Y-m-d", $start + $i * 86400);
+            Cache::pull('weight.'.$date);
+        }
+    }
+
+    public function delRedis(Request $request)
+    {
+        $date = $request->get('date','');
+        if (empty($date)) return false;
+        Cache::pull('weight.'.$date);
+    }
+
+    public function addDateRecords(Request $request)
+    {
+        $yesterday = $request->get('date','');
+        $sql = <<<sql
+SELECT DATE_FORMAT(order_packages.created_at,'%Y-%m-%d') date,IFNULL(order_packages.measuring_machine_id,0) measuring_machine_id,order_packages.owner_id,
+SUM(CASE WHEN order_packages.weighed_at IS NOT NULL THEN 1 ELSE 0 END) AS count,
+COUNT(1) total FROM order_packages LEFT JOIN orders ON order_packages.order_id=orders.id
+WHERE orders.wms_status != '订单取消'
+AND order_packages.created_at BETWEEN '{$yesterday} 00:00:00' AND '{$yesterday} 23:59:59' GROUP BY date,order_packages.measuring_machine_id,order_packages.owner_id
+sql;
+        $result = DB::select(DB::raw($sql));
+        if (!$result) {
+            $obj = [
+                "targeted_at" => $yesterday,
+                "un_weigh_count" => 0,
+                "total_count" => 0,
+                "measuring_machine_id" => 0,
+                "owner_id" => 0
+            ];
+            $model = OrderPackageCountingRecord::query()->create($obj);
+            Cache::put("weight.".$yesterday, $obj);
+        }else{
+            $objs = [];
+            foreach ($result as $v){
+                $obj = [
+                    "targeted_at"    => $v->date,
+                    "un_weigh_count" => $v->count,
+                    "total_count"    => $v->total,
+                    "measuring_machine_id"    => $v->measuring_machine_id,
+                    "owner_id"    => $v->owner_id
+                ];
+                $model = OrderPackageCountingRecord::query()->create($obj);
+                array_push($objs, $obj);
+            }
+            Cache::put("weight.".$yesterday, $objs);
+        }
+    }
 }

+ 43 - 2
app/Http/Controllers/WaybillController.php

@@ -170,8 +170,8 @@ class WaybillController extends Controller
             if ($waybill->type=='德邦物流' && !$oldBill){
                 $bill = app('DbOpenService')->getDbOrderNo($waybill);
                 if (!$bill){DB::rollBack();return "获取德邦单号失败,德邦服务异常";}
-                $waybill->update(["carrier_bill"=>$bill]);
-                $msg =  "【申请德邦物流单号:".$bill."】";
+                $waybill->update(["carrier_bill"=>$bill['mailNo'],'waybill_number'=>$bill['mailNo'],'station_no' => $bill['stationNo'], 'arrived_org_simple_name' =>$bill['arrivedOrgSimpleName'], 'much_higher_delivery'=>$bill['muchHigherDelivery']]);
+                $msg =  "【申请德邦物流单号:".$bill['mailNo']."】";
                 if (!app("WaybillService")->notifyFlux($waybill))$msg .= ",通知FLUX失败";
                 $stage = '发起德邦调度';
             }
@@ -1120,4 +1120,45 @@ class WaybillController extends Controller
         }
         $this->success(count($ids)==$waybills->count() ? '运单拆单完毕' : '部分运单不符合拆单条件');
     }
+
+    /**
+     * 快递面单打印 :暂时支持 德邦
+     */
+    public function expressFaceList(Request $request)
+    {
+        $this->gate("运输管理-编辑");
+        $ids = $request->input("ids");
+        try {
+            /** @var Collection $waybills */
+            $waybills = Waybill::query()->where('type','德邦物流')
+                ->whereIn("id",$ids)
+                ->whereHas("waybillAuditLogs",function ($query){
+                    $query->where("audit_stage","发起德邦调度");
+                })
+                ->get();
+            if ($waybills->count()==0)$this->error("运单不存在或运单类型不正确");
+            foreach ($waybills as $waybill){
+                $waybill->loadMissing([
+                    "order.shop","destinationCity","owner","order.warehouse.province","order.warehouse.city","order.warehouse.county","deliveryType"
+                ]);
+            }
+        }catch (\Exception $e){
+            $this->error($e->getMessage());
+        }
+        if (count($ids)==$waybills->count())$this->success($waybills );
+        $this->error('非德邦快递不可打印');
+    }
+
+    public function changeExpressTag(Request $request)
+    {
+        $this->gate("运输管理-编辑");
+        $id = $request->input("id");
+        try {
+            $row = Waybill::where('waybill_number',$id)->update(['express_face_list'=>1, 'updated_at'=>date('Y-m-d H:i:s')]);
+            if ($row) $this->success('打印成功');
+        }catch (\Exception $e){
+            $this->error($e->getMessage());
+        }
+        $this->error('打印失败');
+    }
 }

+ 9 - 0
app/Http/Controllers/WorkOrderChildTypeController.php

@@ -0,0 +1,9 @@
+<?php
+
+namespace App\Http\Controllers;
+
+
+class WorkOrderChildTypeController extends Controller
+{
+
+}

+ 122 - 0
app/Http/Controllers/WorkOrderController.php

@@ -0,0 +1,122 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Filters\WorkOrderFilters;
+use App\Order;
+use App\Services\OrderService;
+use App\Services\WorkOrderService;
+use App\WorkOrder;
+use App\WorkOrderChildType;
+use App\WorkOrderType;
+use Carbon\Carbon;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Gate;
+
+class WorkOrderController extends Controller
+{
+    public function index(Request $request, WorkOrderFilters $filters)
+    {
+        if(!Gate::allows('订单管理-工单处理-查询'))return redirect('/');
+
+        $workOrders = WorkOrder::query()->filter($filters)->with('type', 'childType', 'creator', 'order.packages','reviewer')->orderByDesc('created_at','grad','status')->paginate($request['paginate'] ?? 50);
+        return view('order.workOrder.index', compact('workOrders'));
+    }
+
+    public function create()
+    {
+        if(!Gate::allows('订单管理-工单处理-创建'))return redirect('/');
+        $workOrderTypes = WorkOrderType::query()->with('childTypes')->get();
+        $grads = WorkOrder::$enums['grad'];
+        array_shift($grads);
+        return view('order.workOrder.create', compact('workOrderTypes', 'grads'));
+    }
+
+
+    public function store(Request $request, WorkOrderService $service)
+    {
+        if(!Gate::allows('订单管理-工单处理-创建'))return redirect('/');
+        $result = $service->createWordOrder($request->all());
+        $workOrderTypes = WorkOrderType::query()->with('childTypes')->get();
+        $grads = WorkOrder::$enums['grad'];
+        array_shift($grads);
+        return view('order.workOrder.create', compact('workOrderTypes', 'result', 'grads'));
+    }
+
+    // 创建
+    public function storeApi(Request $request): array
+    {
+        if(!Gate::allows('订单管理-订单-生成工单'))return ['success' => false,'message' => '没有对应的创建权限'];
+        $order_nos = $request['order_nos'];
+
+        app(OrderService::class)->syncOrderInfoByWmsOrderNos($order_nos);
+
+        $orders = Order::query()->whereIn('code', $order_nos)->get();
+
+        $work_orders = WorkOrder::query()->with('order')->where('outer_table_name', 'orders')->whereIn('outer_table_id', $orders->map(function($item){
+            return $item['id'];
+        }))->get();
+        $exists_nos = $work_orders->map(function ($item) {
+            return $item->order->code;
+        });
+        if (count($exists_nos) > 0)
+            return ['success' => false, 'message' => join(',',$exists_nos->toArray()) . '  已有对应的工单'];
+
+        $inner_params = [];
+
+        $creator_id = Auth::user()['id'];
+
+        $work_order_type = WorkOrderType::query()->firstOrCreate(['name'=> '订单']);
+
+        $work_order_child_type= WorkOrderChildType::query()->firstOrCreate(['name' => '拦截','work_order_type_id' => $work_order_type['id'],'table_name' => 'orders']);
+        $datetime = Carbon::now();
+        foreach ($orders as $order) {
+            $inner_params[] = [
+                'work_order_type_id' => $work_order_type['id'],
+                'work_order_child_type_id' => $work_order_child_type['id'],
+                'outer_table_name' => $work_order_child_type['table_name'],
+                'outer_table_id' => $order['id'],
+                'remark' => "拦截订单:{$order['code']}",
+                'creator_id' => $creator_id,
+                'grad' => $request['grad'] ?? 1,
+                'status' => 1,
+                'updated_at' => $datetime,
+                'created_at' => $datetime,
+            ];
+        }
+        WorkOrder::query()->insert($inner_params);
+        return ['success' => true];
+    }
+
+    // 审核
+    public function reviewApi(Request $request, WorkOrderService $service): array
+    {
+        if(!Gate::allows('订单管理-工单处理-审核'))return ['success' => false,'message' => '没有对应的编辑权限'];
+        $workOrder = WorkOrder::query()->find($request['id']);
+        return $service->reviewWordOrder($workOrder);
+    }
+
+    public function show(WorkOrder $workOrder)
+    {
+        //
+    }
+
+
+    public function edit(WorkOrder $workOrder)
+    {
+        //
+    }
+
+
+    public function update(Request $request, WorkOrder $workOrder)
+    {
+        //
+    }
+
+
+    public function destroy(WorkOrder $workOrder)
+    {
+        //
+    }
+}

+ 9 - 0
app/Http/Controllers/WorkOrderTypeController.php

@@ -0,0 +1,9 @@
+<?php
+
+namespace App\Http\Controllers;
+
+
+class WorkOrderTypeController extends Controller
+{
+
+}

+ 86 - 0
app/Imports/DischargeTaskCostEntryImport.php

@@ -0,0 +1,86 @@
+<?php
+
+namespace App\Imports;
+
+use App\DischargeTask;
+use App\Facilitator;
+use App\Owner;
+use App\Warehouse;
+use Illuminate\Support\Collection;
+use Illuminate\Support\Facades\Cache;
+use Maatwebsite\Excel\Concerns\ToCollection;
+use Maatwebsite\Excel\Concerns\WithHeadingRow;
+use Maatwebsite\Excel\Imports\HeadingRowFormatter;
+
+HeadingRowFormatter::default('none');
+class DischargeTaskCostEntryImport implements ToCollection,WithHeadingRow
+{
+    /**
+    * @param Collection $collection
+    */
+    public function collection(Collection $collection)
+    {
+        $exception = [];
+        $numbers = [];
+        foreach ($collection as $row => $item) {
+            $index = $row + 1;  // 行数
+            $message = '';      // 信息
+
+            $type = array_search(trim($item['作业名称']), DischargeTask::types);
+            $created_at = $item['日期'] ?? '';            // 导入的日期为创建时间
+            $number = $item['入库单号'] ?? '';
+            $owner_name = $item['客户名称'] ?? '';
+            $owner = Owner::query()->where('name',$owner_name)->first();
+            $ware_house = Warehouse::query()->where('name',$item['仓库'])->first();
+            $facilitator = Facilitator::query()->where('name', $item['服务商'] ?? '')->first();
+
+            if ($created_at == '') $message .= '日期为空,';
+            if ($number == '')$message .= '入库单号为空,';
+            if ($owner_name =='' || $owner == null) $message .= '货主未找到,';
+            if ($ware_house == null)  $message .= '仓库未找到,';
+            $expenditure_unit_price = $item['成本单价'];
+
+            $expenditure_amount = $item['成本数量'];
+            $dischargeTask = DischargeTask::query()->where([
+                'owner_id' => $owner['id'],
+                'numbers' => $number,
+                'created_at' => $created_at,
+                'type' => $type,
+                'warehouse_id' =>$ware_house['id']
+            ])->first();
+
+
+            if (isset($item['成本单位'])){
+                $expenditure_unit = array_search(trim($item['成本单位']), DischargeTask::units);
+                if (trim($expenditure_unit) == 'm3'){
+                    $expenditure_unit= array_search('m³', DischargeTask::types);
+                }
+            }else{
+                $expenditure_unit = $dischargeTask['income_unit'];
+            }
+
+            if ($expenditure_unit_price == 0 || $expenditure_unit_price == null)  $message .= '成本单价为空,';
+            if ($expenditure_unit != 0 &&  ($expenditure_unit == '' || $expenditure_unit == null ) )  $message .= '成本单位为空,';
+            if ($expenditure_amount == '' || $expenditure_unit_price == null) $message .= '成本数量为空,';
+            if ($facilitator == null) $message .= '未指定服务商,';
+            if (strlen($message) != 0) {
+                $exception[] = "第{$index}行成本编辑异常:" . $message;
+                continue;
+            }
+            $params = [
+                'expenditure_unit_price' => $expenditure_unit_price,
+                'expenditure_unit' => $expenditure_unit,
+                'expenditure_amount'=>$expenditure_amount,
+                'facilitator_id' => $facilitator['id'],
+                'status' => array_search('接单',DischargeTask::status),
+                'expenditure_at' => $dischargeTask->expenditure_at,
+            ];
+            $params['expenditure_total_cost'] = $expenditure_unit_price * $expenditure_amount;
+
+            $dischargeTask->update($params);
+            $numbers[] = $number;
+        }
+        Cache::put('exception', $exception, 86400);
+        Cache::put('numbers', $numbers, 86400);
+    }
+}

+ 4 - 4
app/Jobs/CacheShelfTaskJob.php

@@ -108,7 +108,7 @@ class CacheShelfTaskJob implements ShouldQueue
                 }else $updateTransaction[] = ["id"=>$obj->id,"to_station_id"=>$stationId,"status"=>0,"updated_at"=>$time];
             },function ($service,$toLocation,$task,$prefix){
                 return $service->fetchGroup_multiLocation($toLocation,$task,$prefix,'立架出至缓存架',20);
-            })){DB::commit();return true;}
+            },"to_station_id")){DB::commit();return true;}
             DB::rollBack();
         }catch (\Exception $e){
             DB::rollBack();
@@ -137,7 +137,7 @@ class CacheShelfTaskJob implements ShouldQueue
                 $updateTransaction[] = ["id"=>$obj->id,"fm_station_id"=>$stationId,"status"=>0,"updated_at"=>$time];
             },function ($service,$toLocation,$task,$prefix){
                 return $service->fetchGroup_multiLocation($toLocation,$task,'','立架出至缓存架');
-            })){DB::commit();return true;}
+            },"fm_station_id")){DB::commit();return true;}
             DB::rollBack();
         }catch (\Exception $e){
             DB::rollBack();
@@ -147,7 +147,7 @@ class CacheShelfTaskJob implements ShouldQueue
     }
 
     private function dispatchTask(\Illuminate\Database\Eloquent\Collection $tasks, array $available, $service,
-                                  \Closure $update, \Closure $execute):bool
+                                  \Closure $update, \Closure $execute, string $stationName):bool
     {
         if (!$tasks->count())return false;
         if ($tasks->count()>count($available))$tasks = $tasks->slice(0,count($available));//事务过多切割部分处理
@@ -156,7 +156,7 @@ class CacheShelfTaskJob implements ShouldQueue
         $availableTemp = array_keys($available);
         $map = app("StationService")->getStationMapping($availableTemp);//获取库位映射信息
         $updateTask = [["id","station_id","updated_at"]];
-        $updateTransaction = [["id","to_station_id","status","updated_at"]];
+        $updateTransaction = [["id",$stationName,"status","updated_at"]];
         $time = date("Y-m-d H:i:s");
         foreach ($tasks as $index=>$obj){
             $loc = $availableTemp[$index];

+ 1 - 1
app/OrderPackageCountingRecord.php

@@ -11,7 +11,7 @@ class OrderPackageCountingRecord extends Model
     use ModelLogChanging;
 
     protected $fillable=[
-        "targeted_at","un_weigh_count","total_count"
+        "targeted_at","un_weigh_count","total_count","measuring_machine_id","owner_id"
     ];
     public $timestamps=false;
 

+ 6 - 0
app/Providers/AppServiceProvider.php

@@ -164,6 +164,9 @@ use App\Services\MaterialBoxModelService;
 use App\Services\HandInStorageService;
 use App\Services\RequirementService;
 use App\Services\RequirementUserService;
+use App\Services\WorkOrderService;
+use App\Services\WorkOrderTypeService;
+use App\Services\WorkOrderChildTypeService;
 
 class AppServiceProvider extends ServiceProvider
 {
@@ -380,6 +383,9 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('WaybillFinancialService', WaybillFinancialService::class);
         app()->singleton('WeighExceptedService', WeighExceptedService::class);
         app()->singleton('WaybillService', WaybillService::class);
+        app()->singleton('WorkOrderChildTypeService',WorkOrderChildTypeService::class);
+        app()->singleton('WorkOrderService',WorkOrderService::class);
+        app()->singleton('WorkOrderTypeService',WorkOrderTypeService::class);
     }
 
     private function registerObserver()

+ 1 - 0
app/Services/CacheShelfService.php

@@ -66,6 +66,7 @@ class   CacheShelfService
                 $this->lightUp($station->code);
                 return ['success' => true];
             }
+            app("StationService")->locationFreed($station->code);
         }
         try {
             $bool = $this->putBinToStore($station);                         // 推送任务

+ 8 - 8
app/Services/DbOpenService.php

@@ -20,7 +20,7 @@ class DbOpenService
      * @return string|null
      * @throws \Throwable
      */
-    public function getDbOrderNo($waybill):?string
+    public function getDbOrderNo($waybill):?array
     {
         $waybill->loadCount(["waybillAuditLogs"=>function($query){
             $query->where("audit_stage","发起德邦调度");
@@ -35,7 +35,7 @@ class DbOpenService
         try {
             $response = httpPost(config('api_logistic.DB.prod.uri')['create_order'], $body, $header);
             if (!$response["result"])return null;
-            return $response['mailNo'] ?? '';
+            return $response ?? '';
             //OracleDOCOrderHeader::query()->where('orderno', $order_no)->update(['edittime' => Carbon::now(), 'soreference5' => $mail_no]);
         }catch (\Exception $e){
             $this->push(__METHOD__."->".__LINE__,"德邦接口请求失败",$e->getMessage() . ' | '.json_encode($response ?? ''));
@@ -78,7 +78,7 @@ class DbOpenService
         $waybill->loadMissing([
             "order.shop","owner","order.warehouse.province","order.warehouse.city","order.warehouse.county","deliveryType"
         ]);
-        $date = date('Y-m-d H:i:s');
+        $date = date('Y-m-d H:i:s', $waybill->deliver_at ? strtotime($waybill->deliver_at) : now());
         $data =  [
             'logisticID'    =>      config('api_logistic.DB.prod.sign').date("YmdHis").mt_rand(1000, 9999).$waybill->order->id,
             'custOrderNo'   =>      $waybill->order->client_code ?? '',
@@ -88,11 +88,11 @@ class DbOpenService
             'transportType' =>      $waybill->transport_type,
             'customerCode'  =>      config('api_logistic.DB.prod.customer_Code'),
             'sender'        =>      [
-                'companyName'       => $waybill->order->shop->name ?? '',
+                'companyName'       => '宝时物流',
                 'businessNetworkNo' => '',
-                'name'              => $waybill->owner->name ?? '',
-                'mobile'            => $waybill->owner->phone_number ?? '',
-                'phone'             => $waybill->owner->phone_number ?? '',
+                'name'              => '宝时物流',
+                'mobile'            => '',
+                'phone'             => '021-6316561',
                 'province'          => $waybill->order->warehouse->province->name ?? '',
                 'city'              => $waybill->order->warehouse->city->name ?? '',
                 'country'           => $waybill->order->warehouse->county->name ?? '',
@@ -131,7 +131,7 @@ class DbOpenService
             ],
             'smsNotify'     => config('api_logistic.DB.prod.smsNotify'),
             'sendStartTime' => $date,
-            'sendEndTime'   => $waybill->deliver_at ?? date("Y-m-d H:i:s", strtotime('+1 day')),
+            'sendEndTime'   => date('Y-m-d ', $waybill->deliver_at ? strtotime($waybill->deliver_at) : now()).'23:59:59',
             'originalWaybillNumber' => $waybill->wms_bill_number ?? '',
             'remark'        => $waybill->dispatch_remark ?? '',
             'isOut'         => 'N',

+ 1 - 0
app/Services/DischargeTaskService.php

@@ -104,6 +104,7 @@ class DischargeTaskService
 
             $json[] = [
                 $date->toDateTimeString(),
+                $dischargeTask->warehouse->name ?? '',
                 $dischargeTask->owner->name ?? '',
                 DischargeTask::types[$dischargeTask['type']] ?? '',
                 $dischargeTask->numbers ?? '',

+ 1 - 1
app/Services/MaterialBoxService.php

@@ -65,7 +65,7 @@ sql;
         return null;
     }
 
-    private function checkHaiQ(array $boxCodes)
+    public function checkHaiQ(array $boxCodes)
     {
         $haiBoxes = DB::connection("mysql_haiRobotics")->table("ks_bin")
             ->where("status",1)->whereIn("ks_bin_code",$boxCodes)->get();

+ 6 - 3
app/Services/StationService.php

@@ -135,10 +135,11 @@ class StationService
      * 获取缓存架
      *
      * @param bool $onlyAvailable
+     * @param bool $desc
      *
      * @return Collection
      */
-    public function getCacheShelf(bool $onlyAvailable = false):Collection
+    public function getCacheShelf(bool $onlyAvailable = false, bool $desc = false):Collection
     {
         $stations = Station::query()->where("station_type_id",5)
             ->whereNotNull("parent_id");
@@ -146,6 +147,7 @@ class StationService
             ->whereNotIn("id",Station::query()->select("id")->whereHas("task",function ($query){
                 $query->whereNotIn("status",["完成","取消"]);
             }))->lockForUpdate();
+        if ($desc)$stations->orderByDesc("code");
         return $stations->get();
     }
 
@@ -191,13 +193,14 @@ class StationService
     /**
      * 库位释放
      *
-     * @param string $location
+     * @param ?string $location
      * @param int|null $boxId
      *
      * @return int
      */
-    public function locationFreed(string $location, ?int $boxId=null):int
+    public function locationFreed(?string $location, ?int $boxId=null):int
     {
+        if (!$location)return 0;
         $update = ["status"=>0];
         if ($boxId)$update["material_box_id"]=$boxId;
         return Station::query()->where("code",$location)->update($update);

+ 2 - 2
app/Services/StationTaskMaterialBoxService.php

@@ -179,7 +179,6 @@ class StationTaskMaterialBoxService
                     $stationTaskMaterialBox->materialBox->update();
                     $stationTaskMaterialBox->loadMissing("station");    //提前加载站,后续都需要站信息来处理
                     $this->storageService->putCacheShelf($stationTaskMaterialBox);
-                    $this->storageService->releaseOccupation($stationTaskMaterialBox); //释放库位占用
                     break;
                 default:;
             }
@@ -206,11 +205,12 @@ class StationTaskMaterialBoxService
     /**
      * 取出料箱通知
      *
-     * @param $stationTaskMaterialBox
+     * @param StationTaskMaterialBox|\stdClass $stationTaskMaterialBox
      * @throws \Exception
      */
     function markHasTaken($stationTaskMaterialBox)
     {
+        $stationTaskMaterialBox->loadMissing("station");
         $this->instant($this->cacheShelfService,'CacheShelfService');
         //维护缓存架可用度
         $map = Cache::get("CACHE_SHELF_MAPPING",function (){return [];});

+ 5 - 15
app/Services/StorageService.php

@@ -37,8 +37,9 @@ class StorageService
         try{
             $stationTaskMaterialBox->loadMissing("station");
             //如果为半箱位置 清理原有任务
-            if ($stationTaskMaterialBox->station && app("StationService")->isHalfBoxLocation($stationTaskMaterialBox->station)){
-                app("StationService")->locationFreed($stationTaskMaterialBox->station->code,$stationTaskMaterialBox->material_box_id);
+            if (!$stationTaskMaterialBox->station)return;
+            if (app("StationService")->isHalfBoxLocation($stationTaskMaterialBox->station)){
+                app("StationService")->locationOccupy($stationTaskMaterialBox->station->code,$stationTaskMaterialBox->material_box_id);
                 //清除海柔库位信息
                 $this->clearTask([$stationTaskMaterialBox->station->code]);
                 $stationId = $stationTaskMaterialBox->station_id;
@@ -97,7 +98,7 @@ class StorageService
                     app("CacheShelfService")->lightUp($stationTaskMaterialBox->station->code,'2','0',$options);
                     Cache::forget("CACHE_SHELF_OCCUPANCY_{$stationTaskMaterialBox->station->id}");//关闭无限亮灯
                 }
-            }
+            }else app("StationService")->locationFreed($stationTaskMaterialBox->station->code); //释放库位占用
             DB::commit();
         }catch (\Exception $e){
             DB::rollBack();
@@ -105,17 +106,6 @@ class StorageService
         }
     }
 
-    /**
-     * 释放库位占用
-     *
-     * @param StationTaskMaterialBox|\stdClass $stationTaskMaterialBox
-     */
-    public function releaseOccupation($stationTaskMaterialBox)
-    {
-        if (!app("StationService")->isHalfBoxLocation($stationTaskMaterialBox->station))return;
-        app("StationService")->locationFreed($stationTaskMaterialBox->station->code);
-    }
-
     /**
      * 检查临时事务标记处理一些特殊情况
      *
@@ -307,8 +297,8 @@ AND TSK_TASKLISTS.SKU = BAS_SKU.SKU
 WHERE FMID = ? AND FMLOTNUM = ? AND (ALTERNATE_SKU1 = ? OR ALTERNATE_SKU2 = ? OR ALTERNATE_SKU3 = ?)
 AND TASKPROCESS = '00' AND TASKTYPE = 'PA'
 SQL;
+        $tasks = DB::connection("oracle")->select(DB::raw($sql),[$trace,$lotNum,$barCode,$barCode,$barCode]);
 
-        $tasks = DB::connection("oracle")->select(DB::raw($sql),[$trace,$lotNum,$barCode,$barCode,$barCode,$amount]);
         if (!$tasks)return [];
         $nums = [];
         $sum = 0;

+ 1 - 1
app/Services/WaybillService.php

@@ -219,7 +219,7 @@ class WaybillService
     {
         //替换换行符
         if ($param["dispatch_remark"] ?? false)$param["dispatch_remark"] = str_replace(["\n","\r"], ' ', $param["dispatch_remark"]);
-        if (!$param["destination"]) $param["destination"] = $waybill->destination;
+        if (!($param["destination"] ?? false)) $param["destination"] = $waybill->destination;
         $waybill->fill($param);
         $waybill->update();
         return $waybill;

+ 13 - 0
app/Services/WorkOrderChildTypeService.php

@@ -0,0 +1,13 @@
+<?php 
+
+namespace App\Services;
+
+use App\Traits\ServiceAppAop;
+use App\WorkOrderChildType;
+
+class WorkOrderChildTypeService
+{
+    use ServiceAppAop;
+    protected $modelClass=WorkOrderChildType::class;
+
+}

+ 38 - 0
app/Services/WorkOrderService.php

@@ -0,0 +1,38 @@
+<?php
+
+namespace App\Services;
+
+use App\Traits\ServiceAppAop;
+use App\WorkOrder;
+use Illuminate\Support\Carbon;
+use Illuminate\Support\Facades\Auth;
+
+class WorkOrderService
+{
+    use ServiceAppAop;
+    protected $modelClass=WorkOrder::class;
+
+    // 创建工单
+    public function createWordOrder($params): array
+    {
+        $params['status'] = 1;
+        $params['creator_id'] = Auth::user()['id'];
+        $params['grad']  ?? $params['grad'] = 1;
+        $workOrder = WorkOrder::query()->create($params);
+        return ['success' => false,'data' => $workOrder];
+    }
+
+    // 审核工单
+    public function reviewWordOrder($wordOrder): array
+    {
+        $wordOrder->update([
+            'reviewer_id' =>Auth::user()['id'],
+            'review_at' => Carbon::now(),
+            'status' => 2,
+        ]);
+        $wordOrder = WorkOrder::query()->with('type', 'childType', 'creator', 'order.packages','reviewer')->find($wordOrder['id']);
+        return ['success' => true,'data' => $wordOrder];
+    }
+
+
+}

+ 14 - 0
app/Services/WorkOrderTypeService.php

@@ -0,0 +1,14 @@
+<?php
+
+namespace App\Services;
+
+use App\Traits\ServiceAppAop;
+use App\WorkOrderType;
+
+class WorkOrderTypeService
+{
+    use ServiceAppAop;
+    protected $modelClass=WorkOrderType::class;
+
+
+}

+ 9 - 0
app/Waybill.php

@@ -65,6 +65,15 @@ class Waybill extends Model
         'total_weight',
         'deliveryType_id',
         "merge_owner",//合并货主ID集
+        'order_type',
+        'transport_type',
+        'pay_type',
+        'back_sign_bill',
+        'package_service',
+        'express_face_list',
+        'arrived_org_simple_name',
+        'much_higher_delivery',
+        'station_no'
     ];
 
     public function district()

+ 111 - 0
app/WorkOrder.php

@@ -0,0 +1,111 @@
+<?php
+
+namespace App;
+
+use App\Traits\ModelTimeFormat;
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Illuminate\Database\Eloquent\SoftDeletes;
+
+class WorkOrder extends Model
+{
+    use ModelLogChanging;
+    use ModelTimeFormat;
+    use SoftDeletes;
+
+    // 工单 信息
+    protected $fillable = ['status', 'creator_id', 'reviewer_id', 'work_order_type_id', 'work_order_child_type_id', 'grad', 'remark', 'outer_table_name', 'outer_table_id', 'review_at'];
+
+    static public $enums = [
+        'status' => [
+            '' => 0,
+            '待审核' => 1,
+            '已处理' => 2,
+        ],
+        'grad' => [
+            '' => 0,
+            '一般' => 1,
+            '重要' => 2,
+            '紧急' => 3,
+            '重要且紧急' => 4,
+        ],
+    ];
+
+    function __construct(array $attributes = [])
+    {
+        foreach (self::$enums as &$enum) {
+            $enum = $enum + array_flip($enum);
+        }
+        parent::__construct($attributes);
+    }
+
+    public function getStatusAttribute($value)
+    {
+        if (!$value) return '';
+        return self::$enums['status'][$value];
+    }
+
+    public function setStatusAttribute($value)
+    {
+        if (!$value) return 0;
+        if (is_numeric($value)) {
+            $this->attributes['status'] = $value;
+        } else {
+            $this->attributes['status'] = self::$enums['status'][$value];
+        }
+    }
+
+    public function getGradAttribute($value)
+    {
+        if (!$value) return '';
+        return self::$enums['grad'][$value];
+    }
+
+    public function setGradAttribute($value)
+    {
+        if (!$value) return 0;
+        if (is_numeric($value)) {
+            $this->attributes['grad'] = $value;
+        } else {
+            $this->attributes['grad'] = self::$enums['grad'][$value];
+        }
+    }
+
+    // 创建人
+    public function creator(): BelongsTo
+    {
+        return $this->belongsTo(User::class, 'creator_id');
+    }
+
+    // 审核人
+    public function reviewer(): BelongsTo
+    {
+        return $this->belongsTo(User::class, 'reviewer_id');
+    }
+
+    // 关联订单
+    public function order(): BelongsTo
+    {
+        return $this->belongsTo(Order::class, 'outer_table_id');
+    }
+
+    // 类型
+    public function type(): BelongsTo
+    {
+        return $this->belongsTo(WorkOrderType::class, 'work_order_type_id', 'id');
+    }
+
+    // 子类型
+    public function childType(): BelongsTo
+    {
+        return $this->belongsTo(WorkOrderChildType::class, 'work_order_child_type_id', 'id');
+    }
+
+    public function scopeFilter($query, $filters)
+    {
+        return $filters->apply($query);
+    }
+
+}

+ 16 - 0
app/WorkOrderChildType.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+
+class WorkOrderChildType extends Model
+{
+    use ModelLogChanging;
+
+    // 工单类型 子 类型
+    protected $fillable = ['work_order_type_id','name','table_name'];
+
+}

+ 21 - 0
app/WorkOrderType.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+use Illuminate\Database\Eloquent\Relations\HasMany;
+
+class WorkOrderType extends Model
+{
+    use ModelLogChanging;
+
+    // 工单 类型
+    protected $fillable = ['name'];
+
+    public function childTypes(): HasMany
+    {
+        return $this->hasMany(WorkOrderChildType::class);
+    }
+}

+ 14 - 0
database/factories/WorkOrderChildTypeFactory.php

@@ -0,0 +1,14 @@
+<?php
+
+/** @var \Illuminate\Database\Eloquent\Factory $factory */
+
+use App\WorkOrderChildType;
+use Faker\Generator as Faker;
+
+$factory->define(WorkOrderChildType::class, function (Faker $faker) {
+    return [
+        'work_order_type_id' =>rand(1,10),
+        'name' => $faker->name(),
+        'table_name' => $faker->name(),
+    ];
+});

+ 11 - 0
database/factories/WorkOrderFactory.php

@@ -0,0 +1,11 @@
+<?php
+
+/** @var \Illuminate\Database\Eloquent\Factory $factory */
+
+use App\WorkOrder;
+use Faker\Generator as Faker;
+
+$factory->define(WorkOrder::class, function (Faker $faker) {
+    return [
+    ];
+});

+ 12 - 0
database/factories/WorkOrderTypeFactory.php

@@ -0,0 +1,12 @@
+<?php
+
+/** @var \Illuminate\Database\Eloquent\Factory $factory */
+
+use App\WorkOrderType;
+use Faker\Generator as Faker;
+
+$factory->define(WorkOrderType::class, function (Faker $faker) {
+    return [
+        'name' => $faker->name
+    ];
+});

+ 38 - 0
database/migrations/2021_08_03_154931_change_order_package_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 ChangeOrderPackageCountingRecordsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('order_package_counting_records', function (Blueprint $table) {
+            $table->dropColumn('name');
+            $table->bigInteger('measuring_machine_id')->nullable()->comment('外联 设备号');
+            $table->bigInteger('owner_id')->nullable()->comment('外联 货主ID');
+            $table->dropPrimary('targeted_at');
+            $table->index('targeted_at','index_date');
+            $table->unique(['targeted_at','measuring_machine_id','owner_id'],'index_data_id');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('order_package_counting_records', function (Blueprint $table) {
+            $table->dropColumn('measuring_machine_id');
+            $table->dropColumn('owner_id');
+        });
+    }
+}

+ 42 - 0
database/migrations/2021_08_04_093716_create_work_orders_table.php

@@ -0,0 +1,42 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateWorkOrdersTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('work_orders', function (Blueprint $table) {
+            $table->id();
+            $table->integer('creator_id')->comment('创建人');
+            $table->integer('reviewer_id')->nullable()->comment('审核人');
+            $table->integer('work_order_type_id')->comment('类型');
+            $table->integer('work_order_child_type_id')->comment('子类型');
+            $table->string('outer_table_name')->comment('关联表名');
+            $table->integer('outer_table_id')->comment('关联表id');
+            $table->tinyInteger('grad')->comment('工单等级');
+            $table->tinyInteger('status')->comment('工单状态');
+            $table->string('remark')->comment('描述信息');
+            $table->dateTime('review_at')->default(null)->nullable()->comment('审核时间');
+            $table->softDeletes();
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('work_orders');
+    }
+}

+ 32 - 0
database/migrations/2021_08_04_101843_create_work_order_types_table.php

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateWorkOrderTypesTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('work_order_types', function (Blueprint $table) {
+            $table->id();
+            $table->string('name')->comment('工单类型');
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('work_order_types');
+    }
+}

+ 34 - 0
database/migrations/2021_08_04_101906_create_work_order_child_types_table.php

@@ -0,0 +1,34 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateWorkOrderChildTypesTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('work_order_child_types', function (Blueprint $table) {
+            $table->id();
+            $table->tinyInteger('work_order_type_id')->comment('工单类型');
+            $table->string('name')->comment('子类型名称');
+            $table->string('table_name')->comment('关联表');
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('work_order_child_types');
+    }
+}

+ 32 - 0
database/migrations/2021_08_10_110830_change_express_face_list_column_in_waybills_table.php

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class ChangeExpressFaceListColumnInWaybillsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('waybills', function (Blueprint $table) {
+            $table->tinyInteger('express_face_list')->default(0)->comment('快递面单 是否打印: 1:是 0:否');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('waybills', function (Blueprint $table) {
+            $table->dropColumn('express_face_list');
+        });
+    }
+}

+ 36 - 0
database/migrations/2021_08_11_153350_change_dbwl_column_in_waybills_table.php

@@ -0,0 +1,36 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class ChangeDbwlColumnInWaybillsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('waybills', function (Blueprint $table) {
+            $table->string('station_no')->nullable()->comment('提货网点编码');
+            $table->string('much_higher_delivery')->nullable()->comment('超远派送金额');
+            $table->string('arrived_org_simple_name')->nullable()->comment('目的站部门简称');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('waybills', function (Blueprint $table) {
+            $table->dropColumn('station_no');
+            $table->dropColumn('much_higher_delivery');
+            $table->dropColumn('arrived_org_simple_name');
+        });
+    }
+}

+ 18 - 0
database/seeds/WorkOrderChildTypeSeeder.php

@@ -0,0 +1,18 @@
+<?php
+
+use App\WorkOrderChildType;
+use Illuminate\Database\Seeder;
+
+class WorkOrderChildTypeSeeder extends Seeder
+{
+    /**
+     * Run the database seeds.
+     *
+     * @return void
+     */
+    public function run()
+    {
+        $params = factory(WorkOrderChildType::class)->times(30)->make()->toArray();
+        WorkOrderChildType::query()->insert($params);
+    }
+}

+ 16 - 0
database/seeds/WorkOrderSeeder.php

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

+ 18 - 0
database/seeds/WorkOrderTypeSeeder.php

@@ -0,0 +1,18 @@
+<?php
+
+use App\WorkOrderType;
+use Illuminate\Database\Seeder;
+
+class WorkOrderTypeSeeder extends Seeder
+{
+    /**
+     * Run the database seeds.
+     *
+     * @return void
+     */
+    public function run()
+    {
+        $params = factory(WorkOrderType::class)->times(10)->make()->toArray();
+        WorkOrderType::query()->insert($params);
+    }
+}

BIN
resources/images/dbwl/qrCode.jpg


BIN
resources/images/dbwl/revice.png


+ 0 - 1
resources/js/app.js

@@ -12,4 +12,3 @@ window.datetimeRelating=require('./utilities/datetimeRelating');
 window.Vue.use(window.ElementUI);
 require('bootstrap-select');
 window.Vue.use(require('http-vue-loader'));
-

BIN
resources/js/lodop/CLodop_Setup_for_Win32NT.exe


+ 133 - 0
resources/js/lodop/LodopFuncs.js

@@ -0,0 +1,133 @@
+var CreatedOKLodop7766=null;
+
+//====判断是否需要安装CLodop云打印服务器:====
+function needCLodop(){
+    try{
+	var ua=navigator.userAgent;
+	if (ua.match(/Windows\sPhone/i) !=null) return true;
+	if (ua.match(/iPhone|iPod/i) != null) return true;
+	if (ua.match(/Android/i) != null) return true;
+	if (ua.match(/Edge\D?\d+/i) != null) return true;
+	if (ua.match(/QQBrowser/i) != null) return false;
+	var verTrident=ua.match(/Trident\D?\d+/i);
+	var verIE=ua.match(/MSIE\D?\d+/i);
+	var verOPR=ua.match(/OPR\D?\d+/i);
+	var verFF=ua.match(/Firefox\D?\d+/i);
+	var x64=ua.match(/x64/i);
+	if ((verTrident==null)&&(verIE==null)&&(x64!==null))
+		return true; else
+	if ( verFF !== null) {
+		verFF = verFF[0].match(/\d+/);
+		if ( verFF[0] >= 42 ) return true;
+	} else
+	if ( verOPR !== null) {
+		verOPR = verOPR[0].match(/\d+/);
+		if ( verOPR[0] >= 32 ) return true;
+	} else
+	if ((verTrident==null)&&(verIE==null)) {
+		var verChrome=ua.match(/Chrome\D?\d+/i);
+		if ( verChrome !== null ) {
+			verChrome = verChrome[0].match(/\d+/);
+			if (verChrome[0]>=42) return true;
+		};
+	};
+        return false;
+    } catch(err) {return true;};
+};
+
+//====页面引用CLodop云打印必须的JS文件:====
+if (needCLodop()) {
+	var head = document.head || document.getElementsByTagName("head")[0] || document.documentElement;
+	var oscript = document.createElement("script");
+	var ishttps = 'https:' == document.location.protocol ? true: false;
+    ishttps = false;
+	if(ishttps){
+		oscript.src ="https://localhost:8443/CLodopfuncs.js?priority=1";
+		head.insertBefore( oscript,head.firstChild );
+		//本机云打印的后补端口8444:
+		oscript = document.createElement("script");
+		oscript.src ="https://localhost:8444/CLodopfuncs.js?priority=2";
+		head.insertBefore( oscript,head.firstChild );
+	}else{
+		oscript.src ="http://localhost:8000/CLodopfuncs.js?priority=1";
+		head.insertBefore( oscript,head.firstChild );
+		//本机云打印的后补端口8001:
+		oscript = document.createElement("script");
+		oscript.src ="http://localhost:8001/CLodopfuncs.js?priority=2";
+		head.insertBefore( oscript,head.firstChild );
+	}
+
+
+};
+
+//====获取LODOP对象的主过程:====
+function getLodop(oOBJECT,oEMBED){
+    var strHtmInstall="<br><font color='#FF00FF'>打印控件未安装!点击这里<a href='../../js/lodop/install_lodop32.exe' target='_self'>执行安装</a>,安装后请刷新页面或重新进入。</font>";
+    var strHtmUpdate="<br><font color='#FF00FF'>打印控件需要升级!点击这里<a href='../../js/lodop/install_lodop32.exe' target='_self'>执行升级</a>,升级后请重新进入。</font>";
+    var strHtm64_Install="<br><font color='#FF00FF'>打印控件未安装!点击这里<a href='../../js/lodop/install_lodop64.exe' target='_self'>执行安装</a>,安装后请刷新页面或重新进入。</font>";
+    var strHtm64_Update="<br><font color='#FF00FF'>打印控件需要升级!点击这里<a href='../../js/lodop/install_lodop64.exe' target='_self'>执行升级</a>,升级后请重新进入。</font>";
+    var strHtmFireFox="<br><br><font color='#FF00FF'>(注意:如曾安装过Lodop旧版附件npActiveXPLugin,请在【工具】->【附加组件】->【扩展】中先卸它)</font>";
+    var strHtmChrome="<br><br><font color='#FF00FF'>(如果此前正常,仅因浏览器升级或重安装而出问题,需重新执行以上安装)</font>";
+    var strCLodopInstall="<br><font color='#FF00FF'>CLodop云打印服务(本地)未安装启动!点击这里<a href='../../js/lodop/CLodop_Setup_for_Win32NT.exe' target='_self'>执行安装</a>,安装后请刷新页面。</font>";
+    var strCLodopUpdate="<br><font color='#FF00FF'>CLodop云打印服务需升级!点击这里<a href='../../js/lodop/CLodop_Setup_for_Win32NT.exe' target='_self'>执行升级</a>,升级后请刷新页面。</font>";
+    var LODOP;
+    try{
+        var isIE = (navigator.userAgent.indexOf('MSIE')>=0) || (navigator.userAgent.indexOf('Trident')>=0);
+        if (needCLodop()) {
+            try{ LODOP=getCLodop();} catch(err) {};
+	    if (!LODOP && document.readyState!=="complete") {/*alert("C-Lodop没准备好,请稍后再试!");*/ return;};
+            if (!LODOP) {
+		 if (isIE) document.write(strCLodopInstall); else
+		  $("#lodopTips").append(strCLodopInstall);
+                 return;
+            } else {
+
+	         if (CLODOP.CVERSION<"2.0.6.8") {
+			if (isIE) document.write(strCLodopUpdate); else
+			 $("#lodopTips").append(strCLodopUpdate);
+		 };
+		 if (oEMBED && oEMBED.parentNode) oEMBED.parentNode.removeChild(oEMBED);
+		 if (oOBJECT && oOBJECT.parentNode) oOBJECT.parentNode.removeChild(oOBJECT);
+	    };
+        } else {
+            var is64IE  = isIE && (navigator.userAgent.indexOf('x64')>=0);
+            //=====如果页面有Lodop就直接使用,没有则新建:==========
+            if (oOBJECT!=undefined || oEMBED!=undefined) {
+                if (isIE) LODOP=oOBJECT; else  LODOP=oEMBED;
+            } else if (CreatedOKLodop7766==null){
+                LODOP=document.createElement("object");
+                LODOP.setAttribute("width",0);
+                LODOP.setAttribute("height",0);
+                LODOP.setAttribute("style","position:absolute;left:0px;top:-100px;width:0px;height:0px;");
+                if (isIE) LODOP.setAttribute("classid","clsid:2105C259-1E0C-4534-8141-A753534CB4CA");
+                else LODOP.setAttribute("type","application/x-print-lodop");
+                document.documentElement.appendChild(LODOP);
+                CreatedOKLodop7766=LODOP;
+             } else LODOP=CreatedOKLodop7766;
+            //=====Lodop插件未安装时提示下载地址:==========
+            if ((LODOP==null)||(typeof(LODOP.VERSION)=="undefined")) {
+                 if (navigator.userAgent.indexOf('Chrome')>=0)
+                      $("#lodopTips").append(strHtmChrome);
+                 if (navigator.userAgent.indexOf('Firefox')>=0)
+                      $("#lodopTips").append(strHtmFireFox);
+                 if (is64IE) document.write(strHtm64_Install); else
+                 if (isIE)   document.write(strHtmInstall);    else
+                      $("#lodopTips").append(strHtmInstall);
+                 return LODOP;
+            };
+        };
+        if (LODOP.VERSION<"6.2.0.8") {
+            if (needCLodop())
+             $("#lodopTips").append(strCLodopUpdate); else
+            if (is64IE)  $("#lodopTips").append(strHtm64_Update); else
+            if (isIE)  $("#lodopTips").append(strHtmUpdate); else
+             $("#lodopTips").append(strHtmUpdate);
+            return LODOP;
+        };
+        //===如下空白位置适合调用统一功能(如注册语句、语言选择等):===
+        LODOP.SET_LICENSES("","8547576574263FCEE0D67DA8BFE4BECC","C94CEE276DB2187AE6B65D56B3FC2848","");
+        //===========================================================
+        return LODOP;
+    } catch(err) {alert("getLodop出错:"+err);};
+};
+

BIN
resources/js/lodop/install_lodop32.exe


BIN
resources/js/lodop/install_lodop64.exe


+ 37 - 0
resources/js/lodop/jquery.PrintArea.js

@@ -0,0 +1,37 @@
+// JavaScript Document
+(function($) {
+var printAreaCount = 0;
+$.fn.printArea = function()
+{
+var ele = $(this);
+var idPrefix = "printArea_";
+removePrintArea( idPrefix + printAreaCount );
+printAreaCount++;
+var iframeId = idPrefix + printAreaCount;
+var iframeStyle = 'position:absolute;width:0px;height:0px;left:-500px;top:-500px;';
+iframe = document.createElement('IFRAME');
+$(iframe).attr({ style : iframeStyle,
+id    : iframeId
+});
+document.body.appendChild(iframe);
+var doc = iframe.contentWindow.document;
+$(document).find("link")
+.filter(function(){
+return $(this).attr("rel").toLowerCase() == "stylesheet";
+})
+.each(function(){
+doc.write('<link type="text/css" rel="stylesheet" href="' +
+$(this).attr("href") + '" >');
+});
+doc.write('<div class="' + $(ele).attr("class") + '">' + $(ele).html() + '</div>');
+doc.close();
+var frameWindow = iframe.contentWindow;
+frameWindow.close();
+frameWindow.focus();
+frameWindow.print();
+}
+var removePrintArea = function(id)
+{
+$( "iframe#" + id ).remove();
+};
+})(jQuery);

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 2 - 0
resources/js/lodop/jquery.js


+ 50 - 0
resources/js/lodop/myAlert.js

@@ -0,0 +1,50 @@
+(function() {
+	$.extend({
+		myAlert: function(options) {//参数格式{title:'Title',message:'message',callback:function(){alert('callback')}}or"需要提示的话"
+			var option={title:"提示",message:"程序员太傻,忘记输入提示内容啦……",callback:function(){}}
+			if(typeof(options)=="string"){
+				option.message=options
+			}else{
+				option=$.extend(option,options);
+			}
+			var top=$(window).height()*0.3;
+			$('body').append('<div class="myModa"><div class="myAlertBox"  style="margin-top:'+top+'px"><h6>'+option.title+'</h6><p>'+option.message+'</p><div class="btn sure">确定</div></div></div>');
+			$('.btn.sure').click(function(){
+				$('.myModa').remove();
+				option.callback();
+			})
+		},
+		myConfirm: function(options) {//参数格式{title:'Title',message:'message',callback:function(){alert('callback')}}or"需要提示的话"$.myConfrim()
+			var option={title:"提示",message:"程序员太傻,忘记输入提示内容啦……",callback:function(){}}
+			if(typeof(options)=="string"){
+				option.message=options
+			}else{
+				option=$.extend(option,options);
+			}
+			var top=$(window).height()*0.3;
+			$('body').append('<div class="myModa"><div class="myAlertBox" style="margin-top:'+top+'px"><h6>'+option.title+'</h6><p>'+option.message+'</p><div class="col2"><div class="col" style="margin-right: 20px;"><div class="btn exit">取消</div></div><div class="col"><div class="btn sure">确定</div></div></div></div></div>');
+			$('.btn.exit').click(function(){
+				$('.myModa').remove();
+			})
+			$('.btn.sure').click(function(){
+				$('.myModa').remove();
+				option.callback();
+			})
+		},
+		myToast:function(message){
+			var top=$(window).height()*0.3;
+			$('body').append('<div class="myToast">'+message+'</div>');
+			console.log($('.myToast').outerWidth())
+			var top=($(window).height()-$('.myToast').height())/2;
+			var left=($('body').width()-$('.myToast').width())/2;
+			$('.myToast').css({'top':top+'px','left':left+'px'});
+			setTimeout(function(){
+				$('.myToast').fadeOut(300);
+				setTimeout(function(){
+					$('.myToast').remove();
+				},300)
+			},1000)
+		}
+	});
+})(jQuery)
+

+ 320 - 0
resources/js/lodop/myPrintKit.js

@@ -0,0 +1,320 @@
+function PrintTable(billList){
+    for (var i = 0; i < billList.length; i++) {
+        var printOrders = billList[i];
+        //如果原发货人,电话不为空,显示原发货人信息,否则现在发货人信息
+        if (printOrders.shipperCompanyName != null
+            && printOrders.shipperCompanyName != ''
+            && printOrders.shipperCompanyPhone != null
+            && printOrders.shipperCompanyPhone != '') {
+            printOrders.shipperTel = printOrders.shipperCompanyPhone;
+            printOrders.shipperName = printOrders.shipperCompanyName;
+            printOrders.saddress = printOrders.shipperCompanyAddress;
+            printOrders.shipperPhone = '';
+        }
+    }
+    var len = $(".waybillNum").length;
+    var wayNum = "";
+    for (var i = 0; i < len; i++) {
+        wayNum += $(".waybillNum")[i].innerText + ",";
+    }
+    wayNum = wayNum.substring(0, wayNum.length - 1);
+    //newPrintWayBill(billList, wayNum); //打印
+    lodopPrintTable(billList, wayNum); //打印
+}
+//当前打印模板
+var htmlTemplateObj = null;
+
+function lodopPrintTable(billList, wayNum){
+    //获取打印模板
+    htmlTemplateObj = $("#printContext");
+    // console.log("shipperName"+htmlTemplateObj.find("span.shipperName").text())
+    var LODOP = null;
+    try{
+        LODOP=getLodop();
+        if ((LODOP!=null)&&(typeof(LODOP.VERSION)!="undefined")){
+            $("#lodopTips").hide();
+        }
+        else{
+            $("#lodopTips").show();
+            return;
+        }
+    }catch(err){
+        $("#lodopTips").show();
+        return;
+    }
+    //打印
+    print(billList, wayNum);
+
+}
+//打印模板
+function templateDataProcess(data, index){
+    Date.prototype.Format = function (fmt) { //author: meizz
+        var o = {
+            "M+": this.getMonth() + 1, //月份
+            "d+": this.getDate(), //日
+            "H+": this.getHours(), //小时
+            "m+": this.getMinutes(), //分
+            "s+": this.getSeconds(), //秒
+            "q+": Math.floor((this.getMonth() + 3) / 3), //季度
+            "S": this.getMilliseconds() //毫秒
+        };
+        if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
+        for (var k in o)
+            if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
+        return fmt;
+    }
+
+    var printHtml = null;
+    if(data==undefined || data == null || data== ""){
+        return printHtml;
+    }
+
+    htmlTemplateObj.find("span.conPhone").text(data.conPhone);
+    htmlTemplateObj.find("span.conTel").text(data.conTel);
+    htmlTemplateObj.find("span.shipperTel").text(data.shipperTel);
+    htmlTemplateObj.find("span.shipperName").text(data.shipperName);
+    htmlTemplateObj.find("span.shipperPhone").text(data.shipperPhone);
+    htmlTemplateObj.find("span.conName").text(data.conName);
+
+    if(data.caddress.length>42){
+        $('#conMsg').attr('style','border-right:0mm;font-size:8pt;width:90mm;font-family:黑体;font-weight:bold;text-align:left; ');
+        $('#conMsg2').attr('style','font-family:黑体;text-align:left; font-size:8px;font-weight:bold; ');
+
+    }else{
+        $('#conMsg').attr('style','border-right:0mm;font-size:10pt;width:90mm;font-family:黑体;font-weight:bold;text-align:left; ');
+        $('#conMsg2').attr('style','font-family:黑体;text-align:left; font-size:10px;font-weight:bold; ');
+    }
+    htmlTemplateObj.find("span.caddress").text(data.caddress);
+    htmlTemplateObj.find("span.saddress").text(data.saddress);
+    htmlTemplateObj.find("span.cargoName").text(data.cargoName);
+    htmlTemplateObj.find("span.cargoWeight").text(data.cargoWeight);
+    htmlTemplateObj.find("span.refundPayment").text(data.refundPayment);
+
+    if (data.refundPayment > 0) {
+        $("#refundPaymentId").text("代收货款");
+        $('#refundPaymentId').attr('style','border-top:0mm;background:#000000;line-height:72px;font-weight:bold; text-align:center; color:#FFFFFF; font-size:20px;');
+    } else {
+        $("#refundPaymentId").text("");
+        $('#refundPaymentId').attr('style','border-top:0mm;background:#000000;line-height:72px; text-align:center; color:#FFFFFF;');
+    }
+
+    if (data.payType.length > 2) {
+
+        $('#payTypeId').attr('style','border-top:0mm;background:#000000;line-height:72px;font-weight:bold; text-align:center; color:#FFFFFF; font-size:10px;');
+
+    } else {
+
+        $('#payTypeId').attr('style','border-top:0mm;background:#000000;line-height:72px;font-weight:bold; text-align:center; color:#FFFFFF; font-size:20px;');
+
+    }
+    $("#payTypeId").text(data.payType);
+
+    if ("" == data.transType) {
+
+        $('#transTypeId').attr('style','border-top:0mm;background:#FFFFFF;line-height:72px;font-weight:bold; text-align:center; color:#000000; font-size:13px;');
+        htmlTemplateObj.find("span.transType").text("无法匹配");
+
+    } else {
+
+        if (data.transType.length > 4) {
+
+            $('#transTypeId').attr('style','border-top:0mm;background:#FFFFFF;line-height:72px;font-weight:bold; text-align:center; color:#000000; font-size:8px;');
+
+        } else {
+
+            $('#transTypeId').attr('style','border-top:0mm;background:#FFFFFF;line-height:72px;font-weight:bold; text-align:center; color:#000000; font-size:13px;');
+
+        }
+
+        htmlTemplateObj.find("span.transType").text(data.transType);
+    }
+
+    htmlTemplateObj.find("span.destination").text(data.destination);
+    htmlTemplateObj.find("span.billWeight").text(data.billWeight);
+    htmlTemplateObj.find("span.transportCharge").text(data.transportCharge);
+    htmlTemplateObj.find("span.totalCharge").text(data.totalCharge);
+    htmlTemplateObj.find("span.insuranceMoney").text(data.insuranceMoney);
+    htmlTemplateObj.find("span.signSheet").text(data.signSheet);
+    htmlTemplateObj.find("span.outerField1").text(data.outerField1);
+    htmlTemplateObj.find("span.lastOutLoadOrgName").text(data.lastOutLoadOrgName);
+    htmlTemplateObj.find("span.departCityName").text(data.departCityName);
+    htmlTemplateObj.find("span.departCityName").text(data.departCityName);
+    htmlTemplateObj.find("span.secondLoadOrgName").text(data.secondLoadOrgName);
+    htmlTemplateObj.find("span.stationNumber").text(data.stationNumber);
+    htmlTemplateObj.find("span.custOrderLine").text(data.custOrderLine);
+    htmlTemplateObj.find("span.transNote").text(data.transNote);
+    htmlTemplateObj.find("span.originalNumber").text(data.orderNumber);
+
+    if ("" == data.markerPen) {
+
+        $('#markerPen').attr('style','text-align: center; line-height: 13mm; vertical-align: middle;font-size: 35px; font-weight: bold; margin: 0px; padding: 0px;');
+        $("#refundPaymentId").text("无大头笔信息");
+    } else {
+
+        if (data.markerPen.length > 10) {
+
+            $('#markerPen').attr('style','text-align: center; line-height: 13mm; vertical-align: middle;font-size: 18px; font-weight: bold; margin: 0px; padding: 0px;');
+            $("#markerPen").text(data.markerPen);
+        } else {
+
+            $('#markerPen').attr('style','text-align: center; line-height: 13mm; vertical-align: middle;font-size: 35px; font-weight: bold; margin: 0px; padding: 0px;');
+            $("#markerPen").text(data.markerPen);
+        }
+    }
+//	htmlTemplateObj.find("span.markerPen").text(data.markerPen);
+
+
+
+    htmlTemplateObj.find("span.orderNumber").text(data.orderNumber);
+    htmlTemplateObj.find("span.printTime").text(new Date().Format("yyyyMMdd HH:mm:ss"));
+    htmlTemplateObj.find("span.billTime").text(data.billTime.substring(0,10));
+    var cargoCount = data.cargoCount;
+    if(data.cargoCount>1){
+        cargoCount += "-" + (index+1);
+    }
+    htmlTemplateObj.find("span.cargoCount").text(cargoCount);
+
+    //代收账号
+    var account = data.reciveLoanAccount;
+    if (account != null && account != '') {
+        account = account.substring(0, 3) + "*"
+            + account.substring(account.length - 4, account.length);
+    } else {
+        account = "";
+    }
+    htmlTemplateObj.find("span.reciveLoanAccount").text(account);
+
+    if (data.conTel != '' && data.conTel != null) {
+        if (data.conPhone != '' && data.conPhone != null) {
+            htmlTemplateObj.find("span.conTel").text(data.conTel + "/");
+        }
+    }
+    if (data.shipperTel != '' && data.shipperTel != null) {
+        if (data.shipperPhone != ''
+            && data.shipperPhone != null) {
+            htmlTemplateObj.find("span.shipperTel").text(data.shipperTel + "/");
+        }
+    }
+//	return htmlTemplateObj.html();
+}
+/**
+ * 打印
+ * @param list
+ */
+function print(billList, wayNum){
+    for(var i=0; i<billList.length; i++){
+
+        var data = billList[i];
+        data.cargoCount = 1;
+        for(var j=0; j<data.cargoCount; j++){
+
+            var serialNo = data.printSerialNos;
+            if(data.cargoCount>1){
+                serialNo = data.printSerialNos.split(",")[j];
+            }
+            //条码
+            var barcode = data.waybillNumber + serialNo + data.stationNumber;
+
+            var isHideWareHouse  = data.isHideWareHouse;
+
+            //模板数据处理
+            templateDataProcess(data, j);
+            // console.log("XXXX: "+ htmlTemplateObj.find("span.shipperName").text())
+            //打印电子运单1
+            printEWaybill(data, serialNo, barcode, wayNum);
+
+            //打印仓库分拣单
+//			if("N"==isHideWareHouse){
+//				printWareHouseWaybill(data, serialNo, barcode);
+//			}
+
+        }
+    }
+    if(billList.length>0){
+        //$.myAlert("本次共打印"+billList.length+"张,已成功添加到打印列表!");
+
+    }else {
+        //$.myAlert('请先勾选需要打印的面单');
+    }
+}
+/**
+ * 打印电子运单
+ * @param data
+ * @param serialNo
+ */
+function printEWaybill(data, serialNo, barcode, wayNum){
+    //打印内容
+    var printHtml = htmlTemplateObj.find("div#expressPrintArea").html();
+
+    LODOP.PRINT_INIT("二级模板");
+    LODOP.SET_PRINT_PAGESIZE(0,"110mm","180mm","CreateCustomPage");
+
+    // LODOP.ADD_PRINT_TEXT(130,30,150,130,$(".markerPenCode").text());
+    // LODOP.ADD_PRINT_TEXT(130,30,150,130,"河南郑州");
+    LODOP.SET_SHOW_MODE("BKIMG_WIDTH","100mm");
+    LODOP.SET_SHOW_MODE("BKIMG_HEIGHT","180mm");
+
+
+    LODOP.ADD_PRINT_TABLE("2mm","0.6mm","95mm","177mm",printHtml);
+    LODOP.ADD_PRINT_BARCODE("79mm","10mm","84mm","15mm","128C", data.waybillNumber);
+    LODOP.ADD_PRINT_BARCODE("117mm","45mm","50mm","8mm","128C", data.waybillNumber);
+
+    //打印
+    // LODOP.PREVIEW();
+    LODOP.PRINT();
+//	LODOP.PRINT_DESIGN();
+
+    //记录打印日志
+    try {
+        //printLogses(data);
+        window.tempTip.postBasicRequest("changeExpressTag",{id:data.waybillNumber},res=>{
+
+        });
+    } catch (e) {
+    }
+}
+function printTest(items ='') {
+    var printList = [];
+    items.forEach((item, index)=>{
+        var printOrder = {};
+        printOrder.waybillNumber = item.waybill_number??'';
+        printOrder.shipperCompanyPhone = '021-6316561';
+        printOrder.shipperCompanyAddress = item.order.warehouse.province.name +'-'+item.order.warehouse.city.name+'-'+item.order.warehouse.county.name+'-'+item.order.warehouse.address
+        printOrder.shipperTel = '021-6316561';
+        printOrder.saddress = item.order.warehouse.province.name +'-'+item.order.warehouse.city.name+'-'+item.order.warehouse.county.name+'-'+item.order.warehouse.address;
+        printOrder.shipperPhone = '021-6316561';
+        printOrder.conPhone = item.order.consignee_phone;
+        printOrder.conTel = item.order.consignee_phone;
+        printOrder.shipperName = '宝时物流';
+        printOrder.conName = item.order.consignee_name;
+        printOrder.caddress = item.order.province+'-'+item.order.city+'-'+item.order.district+'-'+item.order.address;
+        printOrder.cargoName = item.cargo_name;
+        printOrder.cargoWeight = item.total_weight;
+        printOrder.refundPayment = item.is_to_pay ? item.collect_fee : 0;  //代收款
+        printOrder.payType = '月结';
+        printOrder.transType = item.transport_type == "JZQY_LONG" ? '精确汽运' : '精准卡航';
+        printOrder.destination = item.destination_city.name;
+        printOrder.billWeight = item.total_weight;
+        printOrder.transportCharge = item.fee;
+        printOrder.totalCharge = item.charge;
+        printOrder.insuranceMoney = 0; //保价
+        printOrder.signSheet = item.back_sign_bill ? (item.back_sign_bill == 1 ? '签收单原件返回' : '电子签收单' ) : '无需返单';
+        printOrder.outerField1 = ''; //受理部门
+        printOrder.lastOutLoadOrgName = item.arrived_org_simple_name??'';  //最终外场
+        printOrder.departCityName = '上海市'; //原寄地
+        printOrder.secondLoadOrgName = '';  //第二外场
+        printOrder.stationNumber = item.station_no??''; //提货网点id
+        printOrder.custOrderLine = item.wms_bill_number;
+        printOrder.transNote = item.ordering_remark;
+        printOrder.markerPen = item.origination;
+        printOrder.orderNumber = item.source_bill;
+        printOrder.billTime = item.order.created_at;
+        printOrder.cargoCount = item.total_number;
+        printOrder.reciveLoanAccount = ''; //代收账号
+        printOrder.printSerialNos = ''; //流水号
+        printOrder.isHideWareHouse = '';
+        printOrder.originalNumber = '';
+        printList.push(printOrder);
+    })
+    PrintTable(printList);
+}

+ 32 - 7
resources/views/control/panel.blade.php

@@ -967,7 +967,26 @@
                     let params = {start:this.searchOption.weightDate[0],end:this.searchOption.weightDate[1],owner_ids:this.selectWeightOwners};
                     window.tempTip.postBasicRequest(url,params,res=>{
                         this.cardPool.weight.hideLoading();
-                        this.cardPool.weight.setOption(this._setWeightData(res.title,res.data));
+                        let myechart = this.cardPool.weight, option = this._setWeightData(res.title,res.data);
+                        myechart.on('updateAxisPointer', function (event) {
+                            var xAxisInfo = event.axesInfo[0];
+                            if (xAxisInfo) {
+                                var dimension = xAxisInfo.value + 1;
+                                myechart.setOption({
+                                    series: {
+                                        id: 'pie',
+                                        label: {
+                                            formatter: '{b}: {@[' + dimension + ']} ({d}%)'
+                                        },
+                                        encode: {
+                                            value: dimension,
+                                            tooltip: dimension
+                                        }
+                                    }
+                                });
+                            }
+                        });
+                        myechart.setOption(option);
                     });
                 },
                 loadOrderPackageReceivedSyncRecordInfo(){
@@ -1022,11 +1041,16 @@
                     this.loadExceptionTypeInfo();
                 },
                 _setWeightData(title, data){
-                    let temp = [];
-                    for (let i=1;i<data.length; i++){
+                    let temp = [],len = data.length -1;
+                    for (let i=0; i < len; i++){
                         temp.push({type: 'line', smooth: true, seriesLayoutBy: 'row', emphasis: {focus: 'series'}});
                     }
-                    temp.push({type: 'pie', id: 'pie', radius: '30%', center: ['50%', '25%'], emphasis: {focus: 'data'},
+                    temp.push({
+                        type: 'pie',
+                        id: 'pie',
+                        radius: '30%',
+                        center: ['50%', '32%'],
+                        emphasis: {focus: 'data'},
                         label: {
                             formatter: '{b}: {@'+title+'} ({d}%)'
                         },
@@ -1035,8 +1059,9 @@
                             value: title,
                             tooltip: title
                         }
-                    })
-                    return {
+                    });
+                    console.log(temp)
+                   return {
                         legend: {},
                         tooltip: {
                             trigger: 'axis',
@@ -1047,7 +1072,7 @@
                         },
                         xAxis: {type: 'category'},
                         yAxis: {gridIndex: 0},
-                        grid: {top: '55%'},
+                        grid: {top: '60%'},
                         series: temp
                     };
                 },

+ 72 - 0
resources/views/order/index/delivering.blade.php

@@ -34,7 +34,11 @@
                         <button class="btn btn-sm btn-outline-dark ml-1"@click="isRejectedBillExist()"
                             style="opacity: 0.7">生成退货单</button>
                     @endcan
+
                     <button class="btn btn-sm ml-1 btn-primary" @click="copyLogisticNumber()">复制快递单号</button>
+                    @can('订单管理-订单-生成工单')
+                    <button class="btn btn-sm ml-1 btn-outline-secondary" @click="showInterceptModel()">订单拦截</button>
+                    @endcan
                 </div>
                 <div class="modal fade " style="top: 20%" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
                     <div class="modal-dialog">
@@ -219,6 +223,39 @@
                         </div>
                     </div>
                 </div>
+
+                <div class="modal fade " id="intercept-modal" tabindex="-1" role="dialog" aria-labelledby="checkModalLabel" aria-hidden="true">
+                    <div class="modal-dialog modal-dialog-centered">
+                        <div class="modal-content">
+                            <div class="modal-header">
+                                <h5 class="modal-title" id="checkModalLabel">拦截工单生成提示</h5>
+                                <button type="button" class="close" data-dismiss="modal" aria-label="Close"  >
+                                    <span aria-hidden="true">&times;</span>
+                                </button>
+                            </div>
+                            <div class="modal-body">
+                                <div class="form-group">
+                                    <label for="grad" class="">任务紧急程度</label>
+                                    <div class="pl-1">
+                                        <div v-for="(item,i) in grads">
+                                            <input type="radio" :id="'grad'+i" name="grad" :value="item.value" v-model="grad">
+                                            <label :for="'grad'+i">@{{ item.name }}</label>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="modal-footer">
+                                <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭
+                                </button>
+                                <button type="button" class="btn btn-outline-primary" @click="interceptOrder">
+                                    提交
+                                </button>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
+
                 <textarea  id="clipboardDiv" style="opacity:0"></textarea>
             </div>
         </div>
@@ -272,6 +309,13 @@
                     merchantInfo:'',
                 },
                 upList:{},
+                grad:1,
+                grads:[
+                    {name:'一般',value:'1'},
+                    {name:'重要',value:'2'},
+                    {name:'紧急',value:'3'},
+                    {name:'重要且紧急',value:'4'},
+                ]
             },
             mounted:function () {
                 this.initData();
@@ -880,6 +924,34 @@
                         });
                     }else {char+=order.soreference5}
                     return char;
+                },
+                showInterceptModel(){
+                    this.grad = 1;
+                    if(checkData.length === 0){
+                        tempTip.show('选中订单在进行操作');
+                        return;
+                    }
+                    $('#intercept-modal').modal('show');
+                },
+                interceptOrder(){    // 订单拦截
+                    let url = '{{url('apiLocal/workOrder/store')}}';
+                    let data = {
+                        work_order_type:'订单',
+                        work_order_child_type:'拦截',
+                        order_nos:checkData,
+                        grad:this.grad,
+                    }
+                    window.tempTip.setIndex(1999);
+                    window.axios.post(url,data).then(res=>{
+                        if (res.data.success){
+                            window.tempTip.showSuccess('生成订单拦截成功');
+                            $('#intercept-modal').modal('hide');
+                        }else{
+                            window.tempTip.show(res.data.message);
+                        }
+                    }).catch(err=>{
+                        window.tempTip.show(err);
+                    });
                 }
             },
         });

+ 18 - 3
resources/views/order/issue/index.blade.php

@@ -1153,7 +1153,6 @@
                             }
                         }]
                     },
-                    // {date_relevance:{date:['orderdate_start','orderdate_end'],relevance:'addtime',killing:'date',default:[31,92,183,366]}}]},
                     {
                         name: 'finance_confirm',
                         type: 'select',
@@ -1161,6 +1160,22 @@
                         placeholder: '财务确认是/否',
                         data: [{name: '是', value: '是'}, {name: '否', value: '否'}]
                     },
+                    {
+                        name: ['result_explain', 'addtime'],
+                        type: 'input_select',
+                        tip: ['情况说明:前或后加 百分号为单个模糊搜索,否则为多条件精确搜索', '查询范围越短,搜索速度越快'],
+                        placeholder: ['处理结果', ''],
+                        data: log_content_range,
+                        rules: [{
+                            son: {
+                                addtime: {
+                                    default: '31',
+                                    required_without_all_if: ['created_at_start', 'created_at_end']
+                                }
+                            }
+                        }]
+
+                    }
                 ], [
                     {name: 'settlement_at_start', type: 'dateTime', tip: '完结起始日期'},
                     {name: 'settlement_at_end', type: 'dateTime', tip: '完结结束日期'},
@@ -1914,7 +1929,7 @@
                         tempTip.show('没有勾选内容')
                         return;
                     }
-                    if (flag == '是') {
+                    if (flag === '是') {
                         if (!confirm('是否进行财务确认')) return;
                     } else {
                         if (!confirm('是否取消财务确认')) return;
@@ -1928,7 +1943,7 @@
                             tempTip.cancelWaitingTip();
                             if (response.data.success) {
                                 tempTip.setDuration(2000);
-                                if (flag == '是') {
+                                if (flag === '是') {
                                     tempTip.showSuccess('确认成功');
                                 } else {
                                     tempTip.showSuccess('取消成功');

+ 199 - 0
resources/views/order/workOrder/create.blade.php

@@ -0,0 +1,199 @@
+@extends("layouts.app")
+@section('title','工单创建')
+
+@section("content")
+    <div class="container-fluid d-none card" id="list">
+        @if(isset($reslut))
+            <div @if($reslut['success']) class="alert-success" @else class="alert-warning" @endif>
+                {{ $reslut['message'] }}
+            </div>
+        @endif
+
+        <div class="card-body bg-light">
+            <div class="col-8 offset-2 row bg-white">
+                <span class="btn col-4 left" @click="changeStep(1)">
+                    <!-- 三种:选中,未选,编辑后-->
+                    <span class="fa-stack fa-lg">
+                        <template v-if="step === 1">
+                            <i class="fa fa-circle-thin fa-stack-2x" style="color: #269dec"></i>
+                            <span class="fa" style="color:#269dec">1</span>
+                        </template>
+                        <template v-if="step > 1">
+                            <i class="fa fa-check-circle-o fa-stack-2x" style="color: #269dec"></i>
+                        </template>
+                    </span>
+                    选择工单类型
+                </span>
+                <!--  fa-check-circle-o 选中-->
+                <span class="btn col-4 left" @click="changeStep(2)">
+                    <span class="fa-stack fa-lg">
+                        <template v-if="step === 2">
+                            <i class="fa fa-circle-thin fa-stack-2x" style="color: #269dec"></i>
+                            <span style="color:#269dec">2</span>
+                        </template>
+                        <template v-if="step < 2">
+                             <i class="fa fa-circle-thin fa-stack-2x" style="color: #888"></i>
+                             <span style="color:#888">2</span>
+                        </template>
+                        <template v-if="step > 2">
+                            <i class="fa fa-check-circle-o fa-stack-2x" style="color: #269dec"></i>
+                        </template>
+                    </span>
+                    选择工单子类型
+                </span>
+                <span class="btn col-4 left" @click="changeStep(3)">
+                       <span class="fa-stack fa-lg">
+                            <template v-if="step === 3">
+                                <i class="fa fa-circle-thin fa-stack-2x" style="color: #269dec"></i>
+                                <span style="color:#269dec">3</span>
+                            </template>
+                            <template v-if="step < 3">
+                                <i class="fa fa-circle-thin fa-stack-2x" style="color: #888"></i>
+                                <span style="color: #888">3</span>
+                            </template>
+                        </span>
+                    创建工单
+                </span>
+            </div>
+            <hr class="">
+            <div class="card-body bg-light">
+
+                <div class="col-8 offset-2 row bg-white card" v-if="step === 1">
+                    <div class="card-body">
+                        <div v-for="(item) in workOrderTypes" class="col-4  d-inline-block ">
+                            <div class="p-3 m-2 bg-light text-break" @click="selectWorkOrderType(item)">
+                                <strong> @{{ item.name }}</strong>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
+                <div class="col-8 offset-2 row bg-white card" v-if="step === 2">
+                    <div class="card-body">
+                        <div v-for="(item) in workOrderChildTypes" class="col-4 d-inline-block">
+                            <div class="p-3 m-2 bg-light text-break" @click="selectWorkOrderChildType(item)">
+                                <strong> @{{ item.name }}</strong>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-8 offset-2 row bg-white card" v-if="step === 3">
+                    <form action="{{url("order/workOrder/store")}}" method="post" id="store_form">
+                        @csrf
+                        @method('POST')
+                        <input type="text" class="d-none" name="work_order_type_id" :value="workOrder.work_order_type_id">
+                        <input type="text" class="d-none" name="work_order_child_type_id"
+                               :value="workOrder.work_order_child_type_id">
+                        <div class="card-body">
+                            <div class="form-group">
+                                <label for="grad" class="">任务紧急程度</label>
+                                <div class="pl-1">
+                                    <div v-for="(item,i) in grads">
+                                        <input type="radio" :id="'grad'+i" name="grad" :value="item.value" v-model="workOrder.grad">
+                                        <label :for="'grad'+i">@{{ item.name }}</label>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <label for="remark">详细内容</label>
+                                <textarea class="form-control" name="remark" id="remark" v-model="workOrder.remark">
+                            </textarea>
+                            </div>
+                            <div class="form-group">
+                                <button class="btn btn-md btn-outline-primary" type="button" @click="checkSubmit">提交</button>
+                            </div>
+
+                        </div>
+                    </form>
+                </div>
+            </div>
+        </div>
+    </div>
+
+@endsection()
+
+@section("lastScript")
+    <script>
+        let list = new Vue({
+            el: "#list",
+            data: {
+                step: 1,
+                workOrderTypes: [
+                        @foreach($workOrderTypes as $workOrderType)
+                    {
+                        id: '{{$workOrderType->id}}',
+                        name: '{{$workOrderType->name}}',
+                        child_types: [
+                                @foreach($workOrderType->childTypes  as $type)
+                            {
+                                id: '{{$type->id}}', name: '{{$type->name}}',
+                            },
+                            @endforeach
+                        ],
+                    },
+                    @endforeach],
+                workOrderChildTypes: [],
+                grads: [
+                        @foreach($grads as $key=>$item)
+                    {
+                        name: '{{$key}}', value: '{{$item}}'
+                    },
+                    @endforeach
+                ],
+                workOrder: {
+                    work_order_type_id: null,
+                    work_order_child_type_id: null,
+                    grad: 1,
+                    remark:null,
+                },
+            },
+            watch: {
+                step: function (newValue, OldValue) {
+                    if (newValue === 1) {
+                        this.workOrder.work_order_child_type_id = null;
+                        this.workOrder.grad = 1;
+                    } else if (newValue === 2) {
+                        this.workOrder.grad = 1;
+                    }
+                },
+            },
+            created() {
+                $("#list").removeClass("d-none");
+            },
+            methods: {
+                changeStep(step) {
+                    if (step < this.step) {
+                        this.step = step;
+                        return;
+                    }
+                    if (step === 2) {
+                        if (this.workOrder.work_order_type_id === null) return;
+                        else this.step = step;
+                    } else if (step === 3) {
+                        if (this.workOrder.work_order_child_type_id === null) return;
+                        else this.step = step;
+                    }
+                },
+                selectWorkOrderType(item) {
+                    this.workOrder.work_order_type_id = item.id;
+                    this.workOrderChildTypes = item['child_types'];
+                    this.changeStep(2);
+                },
+                selectWorkOrderChildType(item) {
+                    this.workOrder.work_order_child_type_id = item.id;
+                    this.changeStep(3);
+                },
+                checkSubmit(){
+                    if (this.workOrder.grad === null){
+                        return false;
+                    }
+                    if (this.workOrder.remark === null){
+                        window.tempTip.show("详细内容未必填项!");
+                        return false;
+                    }
+                    document.getElementById('store_form').submit();
+                },
+            }
+        });
+    </script>
+@endsection

+ 157 - 0
resources/views/order/workOrder/index.blade.php

@@ -0,0 +1,157 @@
+@extends("layouts.app")
+@section('title','处理工单')
+@section("content")
+    <div class="container-fluid d-none" id="list">
+        <div id="form_div" style="min-width: 2250px;"></div>
+        <table class="table table-striped table-md">
+            <thead>
+            <tr class="text-center">
+                <th>序号</th>
+                <th>工单编号</th>
+                <th>工单等级</th>
+                <th>相关类型</th>
+                <th>状态</th>
+                <th>创建人</th>
+                <th>提交时间</th>
+                <th>问题描述</th>
+                <th>物流跟踪信息</th>
+                <th>审核人</th>
+                <th>审核时间</th>
+                <th>操作</th>
+            </tr>
+            </thead>
+            <tbody class="text-center">
+            <template v-for="(item,i) in workOrders">
+                <tr @click="selectTr===i+1?selectTr=0:selectTr=i+1" :class="selectTr===i+1?'focusing' : ''">
+                    <td>@{{i+1}}</td>
+                    <td>@{{item.id}}</td>
+                    <td>
+                        <template v-if="item.status === '已处理'">
+                            @{{ item.grad }}
+                        </template>
+                        <template v-else>
+                            <span class="badge badge-light" style="opacity: 0.7"  v-if="item.grad === '一般'">@{{ item.grad }}</span>
+                            <span class="badge badge-primary" style="opacity: 0.7" v-if="item.grad === '重要'">@{{ item.grad }}</span>
+                            <span class="badge badge-warning" style="opacity: 0.7" v-if="item.grad === '紧急'">@{{ item.grad }}</span>
+                            <span class="badge badge-danger" style="opacity: 0.7" v-if="item.grad === '重要且紧急'">@{{ item.grad }}</span>
+                        </template>
+                    </td>
+                    <td>@{{item.type ? item.type.name : '' }} - @{{ item.child_type ? item.child_type.name : '' }}</td>
+                    <td>
+                        @{{ item.status }}
+                    </td>
+                    <td>@{{ item.creator.name }}</td>
+                    <td>@{{ item.created_at }}</td>
+                    <td>@{{ item.remark }}</td>
+                    <td>
+                        <template v-if="item.review_at">
+                            <div v-if="item.order && item.order.packages">
+                                <template v-for="package in item.order.packages">
+                                    <template v-if="package.transfer_status && package.transfer_status.length > 0">
+                                        <div v-if="selectOrderPackage === package.id">
+                                            <template v-for="transfer in package.transfer_status">
+                                                <p>@{{ transfer['accept_time']+':'+transfer['accept_address'] }}</p>
+                                            </template>
+                                        </div>
+                                        <div v-else>
+                                            @{{ package.transfer_status[0]['accept_time']+':'+package.transfer_status[0]['accept_address'] }}
+                                        </div>
+                                        <button class="btn btn-sm btn-outline-primary" v-if="selectOrderPackage !== package.id" @click="selectOrderPackage = package.id">展开</button>
+                                        <button class="btn btn-sm btn-outline-primary" v-else @click="selectOrderPackage = null">收起</button>
+                                    </template>
+                                </template>
+                            </div>
+                        </template>
+                    </td>
+                    <td>@{{ item.reviewer ? item.reviewer.name : ''}}</td>
+                    <td>@{{ item.review_at }}</td>
+                    <td>
+                        @can('订单管理-工单处理-审核')
+                            <button class="btn btn-sm btn-outline-primary" v-if="item.status !== '已处理'"
+                                    @click="reviewWorkOrder(item,i)">审核
+                            </button>
+                        @endcan()
+                    </td>
+                </tr>
+            </template>
+            </tbody>
+            {{ $workOrders->withQueryString()->links() }}
+        </table>
+    </div>
+@endsection()
+
+@section("lastScript")
+    <script type="text/javascript" src="{{mix('js/queryForm/queryForm.js')}}"></script>
+    <script>
+        let list = new Vue({
+            el: "#list",
+            data: {
+                workOrders: {!! $workOrders->toJson() !!}['data'],
+                selectTr: null,
+                form:null,
+                selectOrderPackage:null,
+            },
+            mounted() {
+                let data = [[
+                    {name: 'created_at_start', type: 'time', tip:['工单创建开始日期','时间']},
+                    {name: 'created_at_end', type: 'time', tip:['工单创建结束日期','时间']},
+                    {name: 'review_at_start', type: 'time', tip:['工单审核开始日期','时间']},
+                    {name: 'review_at_end', type: 'time', tip:['工单审核结束日期','时间']},
+                ]];
+                this.form = new query({
+                    el: '#form_div',
+                    condition: data,
+                    appendDom: "btn",
+                    paginations: [50, 100, 200, 500, 1000, 20],
+                })
+                this.form.init();
+                $("#list").removeClass("d-none");
+            },
+            created() {
+                let self = this;
+                $.each(this.workOrders, function (index, workOrder) {
+                    if (!workOrder.order) return ;
+                    if (!workOrder.order.packages) return ;
+                    self.sortOrder(workOrder);
+                });
+            },
+            methods: {
+                sortOrder(workOrder){
+                    let self = this;
+                    if (!workOrder.order) return ;
+                    if (!workOrder.order.packages) return ;
+                    $.each(workOrder.order.packages,function(i,item){
+                        self.sortTransfer(item);
+                    })
+                },
+                sortTransfer(item){
+                    if (!("transfer_status"  in item))return ;
+                    if (item.transfer_status == null ||  !(item.transfer_status instanceof Array)) return ;
+                    item.transfer_status.sort(function (item1, item2) {
+                        let date1 = new Date(item1['accept_time']);
+                        let date2 = new Date(item2['accept_time']);
+                        if (date1 - date2 > 0) return -1;
+                        if (date1 - date2 < 0) return 1;
+                        return 0;
+                    });
+                },
+                // todo 审核工单
+                reviewWorkOrder(item, i) {
+                    let url = '{{url('apiLocal/workOrder/review')}}';
+                    let data = {id: item.id};
+                    window.axios.post(url, data).then(res => {
+                        if (res.data.success) {
+                            this.$set(this.workOrders, i, res.data.data);
+                            this.sortOrder(res.data.data);
+                            window.tempTip.showSuccess("审核完成");
+                        } else {
+                            window.tempTip.show(res.data.message ?  res.data.message : '审核异常');
+                        }
+                    }).catch(err => {
+                        window.tempTip.show(err)
+                    })
+                },
+            },
+        });
+    </script>
+@endsection

+ 38 - 0
resources/views/personnel/discharge/task/_constEntryImport.blade.php

@@ -0,0 +1,38 @@
+<div class="modal fade" id="importConstEntryModal">
+    <div class="modal-dialog modal-dialog-centered modal-lg">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">
+                    批量成本导入
+                </h5>
+                <button type="button" class="close" data-dismiss="modal">
+                    <span>&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <form>
+                    <div class="form-group">
+                        <label for="importConstEntryFile">导入文件</label>
+                        <input type="file" ref="constEntryfile" name="file"  id="importConstEntryFile"  class="form-control-file">
+                    </div>
+                    <div class="form-group">
+                        <small>文件类型:xlsx ,xlsm ,xls</small>
+                    </div>
+                    <div class="form-group">
+                        <small>字段:*货主,*仓库,*预约日期,*作业名称,*仓库,*入库单,*成本单价,*成本数量,*成本单价,*服务商</small>
+                    </div>
+                    <div class="form-group" v-if="constEntryError.length > 0">
+                        <p class="text-danger">导入异常明细</p>
+                        <ul class="list-group" v-if="constEntryError">
+                            <li class="list-group-item" v-for="error in constEntryError">@{{ error }}</li>
+                        </ul>
+                    </div>
+                </form>
+            </div>
+            <div class="modal-footer">
+                <button class="btn btn-success" @click="cancelConstEntryImport">关闭</button>
+                <button class="btn btn-success" @click="constEntryImport">导入</button>
+            </div>
+        </div>
+    </div>
+</div>

+ 51 - 3
resources/views/personnel/discharge/task/index.blade.php

@@ -30,6 +30,13 @@
                   >批量导入</button>
             </span>
             @endcan
+            @can('人事管理-卸货-成本录入')
+                <span class="ml-1">
+                  <button type="button" class="btn btn-outline-primary btn-sm form-control-sm tooltipTarget"
+                          @click="constEntryImportModel"
+                  >批量成本录入</button>
+            </span>
+            @endcan
         </div>
         @include('personnel.discharge.task._import')
         @include('personnel.discharge.task._table')
@@ -39,6 +46,9 @@
         @can('人事管理-卸货-编辑')
         @include('personnel.discharge.task._executeTask')
         @endcan
+        @can('人事管理-卸货-成本录入')
+            @include('personnel.discharge.task._constEntryImport')
+        @endcan
     </div>
 @endsection
 
@@ -60,6 +70,7 @@
                 executingTack: {},
                 taskError:{},
                 uploadErrors:[],
+                constEntryError:[],
                 taskTypes: [
                     {name: 0, value: "装车"},
                     {name: 1, value: "卸车"},
@@ -181,7 +192,10 @@
                     this.executingTack = JSON.parse(JSON.stringify(task));
                     this.selectIndex = index;
                     if (isDisplay) {
-                        this.executingTack.expenditure_at = moment().format('YYYY-MM-DDTHH:mm');
+                        this.executingTack.expenditure_at = moment(this.executingTack.income_at).format('YYYY-MM-DDTHH:mm');
+                        this.executingTack.expenditure_amount = this.executingTack.income_amount;
+                        this.executingTack.expenditure_unit = this.executingTack.income_unit;
+                        this.executingTack.expenditure_unit_price = this.executingTack.income_unit_price;
                         this.isUpdate = true;
                         this.$forceUpdate();
                         $("#executingTaskModal").modal('show');
@@ -200,7 +214,6 @@
                 },
                 // 创建任务
                 createTask(index) {
-                    console.log(this.addTask);
                     if (this.isUpdate) {
                         this.updateCurrentTask(index);
                         return
@@ -387,6 +400,32 @@
                         window.tempTip.show(err);
                     });
                 },
+                // 成本批量录入
+                constEntryImport(){
+                    window.tempTip.setIndex(1999);
+                    let formData = new FormData();
+                    let file = document.querySelector('#importConstEntryFile').files[0];
+                    if(file==null){
+                        window.tempTip.show('请选择上传文件');
+                    }
+                    formData.append('file',file);
+                    let url = '{{url('apiLocal/personnel/discharge/task/constEntryImport')}}';
+                    window.axios.post(url,formData,{
+                        'Content-Type': 'multipart/form-data'
+                    }).then(res=>{
+                        if(res.data.success){
+                            window.tempTip.showSuccess(res.data.message ? res.data.message : '导入成功!刷新页面显示');
+                            return ;
+                        }else if(res.data.errors){
+                            window.tempTip.show('导入卸货成本失败!,详情请看列表')
+                            this.constEntryError = res.data.errors;
+                            return ;
+                        }
+                        window.tempTip.show('导入失败!'+(res.data.message ? res.data.message : ''));
+                    }).catch(err=>{
+                        window.tempTip.show(err);
+                    });
+                },
                 importModal(){
                     document.querySelector('#importFile').file = [];
                     $('#importModal').modal('show');
@@ -395,7 +434,16 @@
                     this.uploadErrors = [];
                     $('#importModal').modal('hide');
                     document.querySelector('#importFile').value = null;
-                }
+                },
+                constEntryImportModel(){
+                    document.querySelector('#importConstEntryFile').file = [];
+                    $('#importConstEntryModal').modal('show');
+                },
+                cancelConstEntryImport(){
+                    this.constEntryError = [];
+                    $('#importConstEntryModal').modal('hide');
+                    document.querySelector('#importConstEntryFile').value = null;
+                },
 
 
             }

+ 2 - 2
resources/views/requirement/index.blade.php

@@ -97,7 +97,7 @@
                 let data = [
                     [
                         {
-                            name: 'requirement_id',
+                            name: 'requirement',
                             type: 'input',
                             tip: '输入任务号',
                             placeholder: '任务号',
@@ -116,7 +116,7 @@
                             ]
                         },
                         {
-                            name: 'creator_id',
+                            name: 'creator',
                             type: 'select',
                             tip: ['输入关键词快速定位下拉列表,回车确定', '选择要显示的状态'],
                             placeholder: '发布人',

+ 23 - 5
resources/views/store/inStorage/halfChestStorage.blade.php

@@ -33,8 +33,13 @@
                             <strong>@{{ errors.amount[0] }}</strong>
                         </span>
                     </div>
+                    <div class="form-group row">
+                        <label for="call" class="col-sm-2 col-3 text-right">手动呼叫:</label>
+                        <input type="checkbox" style="top: 5px" class="switch" id="call" v-model="info.call">
+                    </div>
                     <div class="input-group row mt-5">
-                        <button type="submit" id="submit" class="btn btn-success offset-2 col-8" @click="checkInfo()">提交</button>
+                        <button type="submit" id="submit" class="btn btn-success offset-3 col-6" @click="checkInfo()">提交</button>
+                        <button type="button" class="btn btn-sm btn-info col-2 text-white offset-1" @click="callRobot()">手动呼叫</button>
                     </div>
                 </div>
             </div>
@@ -142,7 +147,7 @@
                 },
                 //提交溢出减量
                 overflowRevision(){
-                    if (!this.ov.station || !this.ov.amount){
+                    if (!this.ov.ide || !this.ov.amount){
                         window.tempTip.show("信息不完整");
                         return;
                     }
@@ -171,11 +176,14 @@
                 _exeTask(){
                     window.tempTip.postBasicRequest("{{url('store/inStorage/acquireBox')}}",this.info,res=>{
                         if (!res.status){
+                            this.info.commodityId = res.commodityId;
                             this.showMaximumModal();
                             return;
                         }
-                        this.info = {track:this.info.track};
+                        this.info = {track:this.info.track,call:this.info.call};
                         this.errors = {};
+                        let element = document.getElementById("barCode");
+                        if (element)element.focus();
                         return res.amount==0 ? "调取料箱成功!" : "空箱不足,剩余”"+res.amount+"“未上架";
                     });
                 },
@@ -192,7 +200,7 @@
                                 case 1:
                                     this.info.lotNum = res.lots;
                                     this.info.maximum = res.lotMap[res.lots];
-                                    break;
+                                    return "最大可上数量为"+this.info.maximum;
                                 default:
                                     this.lots = res.lots;
                                     $("#lotModal").modal("show");
@@ -271,7 +279,9 @@
                         return;
                     }
                     window.tempTip.postBasicRequest("{{url('store/inStorage/setMaximum')}}",
-                        {models:models,commodityId:this.info.commodity_id},()=>{
+                        {models:models,commodityId:this.info.commodityId},()=>{
+                            $("#maximumModal").modal("hide");
+                            this._exeTask();
                     },true);
                 },
                 selectedLot(index){
@@ -279,6 +289,14 @@
                     this.info.maximum = this.lotMap[this.lots[index].lotnum];
                     $("#lotModal").modal("hide");
                 },
+                callRobot(){
+                    window.tempTip.postBasicRequest("{{url('store/inStorage/callRobot')}}",{},()=>{
+                        this.info = {call:this.info.call};
+                        let element = document.getElementById("track");
+                        if (element)element.focus();
+                        return '呼叫成功';
+                    });
+                }
             },
         });
     </script>

+ 276 - 1
resources/views/transport/waybill/index.blade.php

@@ -46,12 +46,20 @@
                         title="合并多条运单至一条,已填写信息将被累加处理" @click="waybillMerge()">运单合并</button>
             <button class="btn btn-sm btn-outline-info tooltipTarget"
                     title="将已合并运单拆分返回原状态" @click="waybillSplit()">拆单返回</button>
+                @if($uriType=='' || $uriType=='德邦物流')
+                    <button class="btn btn-sm btn-outline-info tooltipTarget"
+                        title="打印快递面单" @click="expressFaceList()">打印快递面单</button>
+                @endif
             @endcan
             <div>
                 @if(Session::has('successTip'))
                     <div class="alert alert-success h1">{{Session::get('successTip')}}</div>
                 @endif
             </div>
+            {{--    德邦面单--}}
+            <div id="lodopTips"></div>
+            {{--    德邦面单--}}
+
             <table class="table table-striped table-bordered table-hover text-nowrap waybill-table td-min-width-80" style="background: #fff;" id="table">
                 <tr v-for="(waybill,i) in waybills" :class="[waybill.status=='待重审'?'td-red':''||waybill.status=='已完结'?'td-green':'',selectTr==waybill.id ? 'tr-select' : '']"
                     :id="'waybill'+waybill.id" @click="selectedColor(waybill.id)" @mouseover="hidetop($event)" @mouseleave="showtop($event)">
@@ -91,6 +99,12 @@
                         </td>
                     @endcan
                     <td :class="[waybill.status=='已审核'?'text-success':'']"><span>@{{waybill.status}}</span></td>
+                    <td class="td-warm">
+                        <span v-if="waybill.express_face_list == 1" style="color: red">
+                           是
+                        </span>
+                        <span v-else>否</span>
+                    </td>
                     <td class="td-warm text-muted toptd position-static">
                         <div v-if="waybill.remark" class="bg-light-yellow  text-danger top position-absolute"  data-toggle="tooltip" style="opacity: 0.1;z-index: 1">置顶备注:@{{  waybill.remark }}</div>
                         @{{ i+1 }}</td>
@@ -241,8 +255,239 @@
         </div>
     </div>
 
-@endsection
+    <div id="printContext" class="ordercontent"
+         style="margin-top: 15px; width: 630px; height: 665px; float: left; overflow-y: auto; text-align: center; display:none">
+        <div id="expressPrintArea">
+            <style>
+                .wayBill li {
+                    float: left;
+                    width: 85px;
+                }
+
+                .wayBill li a:hover {
+                    color: blue;
+                }
+
+                .wayBill li a {
+                    color: blue;
+                }
+                #expressPrintArea {
+                    width: 100mm;
+                    height: 180mm;
+                    margin-left: 100px;
+                    /*  float: left; */
+                    /* background: url('../images/order/lttBackground.jpg') no-repeat; */
+                    background-size: 104mm 175mm;
+                    padding: 4mm 0.5mm 0.5mm 2.3mm;
+                }
+                #expressPrintArea td {
+                    border: 0.15mm solid #cecece;
+                    padding-left: 1mm;
+                    font-size: 12px;
+                    font-family: 宋体;
+                    vertical-align: middle;
+                    text-align: left;
+                }
+                #expressPrintArea tr {
+                    width: 100%;
+                    border-left:0mm;
+                    border-right:0mm;
+                    border: 0.2mm solid #000000;
+                }
+                .singlePlane{
+                    font-size: 7pt;
+                    width:60mm;
+                    font-family:黑体;
+                    text-align:left;
+                    valign:top;
+                }
+                .sign{
+                    font-size:8pt;
+                    width:60mm;
+                    font-family:黑体;
+                    text-align:right;
+                    line-height: 5mm;
+                    padding-top: 2mm;
+                }
+                .singlePlane2{
+                    font-size:7pt;
+                    width:99mm;
+                    font-family:黑体;
+                    text-align:left;
+                    valign:top;
+                    padding-left: 1mm;
+                    padding-right: 1mm;
+                }
+                .houseCode td{
+                    font-size:17px;width:20mm;font-family:黑体; font-weight:bold; text-align:center;
+                }
+                .originalNumber {
+                    font-size: 15px;
+                    font-weight: bold;
+                }
+
+                #cargoName {
+                    font-size:  16px;
+                    font-weight: bold;
+                }
+                #transNote {
+                    font-weight: bold;
+                }
+                #transNote {
+                    font-size:  10px;
+                }
+
+                .top-amount td span, .top-amount td strong, .outerField1, .signSheet {
+                    font-size: 10px !important;
+                    font-family: "黑体";
+                }
+
+            </style>
+            <%-- <div style="width: 20mm;height: 20mm;/* background-color: #fff; */text-align: center;line-height: 20mm;position: absolute; left:50mm; top:60mm;">
+                <span class="markerPenCode" style=" display: inline-block; color: #666;font-size: 40mm;font-weight: bold;transform:rotate(-30deg);opacity: 0.5;">A5</span>
+            </div> --%>
+            <span class="markerPenCode" style="
+        /*display: none;*/
+"></span>
+            <table border="2" style="width: 99mm;border-collapse:collapse;">
+                <%--==================================上联=============================================--%>
+                <tr class="tr1" style="height: 0mm; border: none;">
+                    <td width="10mm"></td>
+                    <td width="10mm"></td>
+                    <td width="10mm"></td>
+                    <td width="10mm"></td>
+                    <td width="10mm"></td>
+                    <td width="10mm"></td>
+                    <td width="10mm"></td>
+                    <td width="10mm"></td>
+                    <td width="10mm"></td>
+                    <td width="5mm"></td>
+                </tr>
+                <%--德邦--%>
+                <tr style="height: 14mm;">
+                    <td colspan="3"></td>
+                    <td valign="middle" colspan="3" style="border-top:0mm;background:white;color:black;line-height:72px;font-weight:bold; text-align:center; font-size:20px;" id="refundPaymentId"></td>
+                    <td valign="middle" colspan="2" style="border-top:0mm;background:black;color:white;line-height:72px;font-weight:bold; text-align:center; font-size:20px;" id="payTypeId"></td>
+                    <td valign="middle" colspan="2" style="border-top:0mm;background:white;color:black;line-height:72px;font-weight:bold; text-align:left; font-size:13px;" id = "transTypeId">
+                        <span class=transType></span></td>
+                </tr>
+                <%--金额--%>
+                <tr style="height: 11mm;" class="top-amount">
+                    <td colspan="4" style="width: 30mm; vertical-align: middle; border-right: 0px;">
+                        <span style="padding-bottom: 1.5mm;"><strong>代收金额:</strong></span><span
+                            class="refundPayment">20000</span><br/>
+                    </td>
+                    <td colspan="6" style="width: 50mm; vertical-align: middle; border-left: 0px;">
+                        <span style="padding-bottom: 1.5mm;"><strong>保价金额:</strong></span><span
+                            class="insuranceMoney">22</span><br/>
+                        <span style="padding-bottom: 1.5mm;"><strong>签单返回:</strong></span><span
+                            class="signSheet"></span><br/>
+                        <span style="padding-bottom: 1.5mm;"><strong>始发网点:</strong></span><span
+                            class="outerField1" style="font-size: 8px;"></span><br/>
+                    </td>
+                </tr>
+                <%--大头笔--%>
+                <tr style="height: 14mm;" >
+                    <td colspan="10" style="text-align: center; line-height: 13mm; vertical-align: middle;font-size: 35px; font-weight: bold; margin: 0px; padding: 0px;" id="markerPen">
+                        无大头笔信息
+                    </td>
+                </tr>
 
+                <%--收件人--%>
+                <tr style="height: 14mm;">
+                    <td colspan="1" style="border-right:0mm;font-size:10px;width:10mm;font-family:黑体;text-align:center;"><img
+                            src="{{URL::asset('./images/dbwl/revice.png')}}"/></td>
+                    <td colspan="9"
+                        style="border-right:0mm;font-size:10pt;width:90mm;font-family:黑体;font-weight:bold;text-align:left; " id="conMsg">
+                        <span class="conName">张小二</span>&nbsp;&nbsp;
+                        <span class="conPhone">(优先取手机号取不到取固话)</span>&nbsp;&nbsp;&nbsp;<span class="conTel"></span><br/>
+                        <span class="caddress">上海市青浦区徐泾镇明珠路10181号</span>
+                    </td>
+                </tr>
+                <%--寄件人--%>
+                <tr style="height: 11mm;">
+                    <td colspan="1" style="border-right:0mm;font-size:25px;width:10mm;font-family:黑体;font-weight:bold;text-align:center;">
+                        寄
+                    </td>
+                    <td colspan="9"
+                        style="border-right:0mm;font-size:8pt;width:90mm;font-family:黑体;text-align:left;">
+                        <span class="shipperName">张小二</span>&nbsp;&nbsp;&nbsp;
+                        <span class="shipperPhone">400-617-9999</span><br/>
+                        <span class="saddress">寄件人地址</span>
+                    </td>
+                </tr>
+                <%--运单号条码--%>
+                <tr style="height: 23mm;">
+                    <td colspan="10"></td>
+                </tr>
+                <%--打印时间验视--%>
+                <tr style="height: 18mm; text-align: left;">
+                    <td colspan="2" valign="bottom" colspan="2" style="text-align:left;font-size:12px;font-family:黑体;width:20mm;border-right:0mm;">
+                    <span class="printTime">
+                    </span><br/>
+                        打印时间
+                    </td>
+                    <td colspan="6">
+                        <div class = "singlePlane">
+                            快件送达收件人地址,经收件人或收件人(寄件人)允许的代收人签字,视为送达。您的签字代表您已经签收次包裹,并已确定商品信息无损,包装完好、没有划痕、破损等表面质量问题。
+                            <br/>
+                        </div>
+                        <div class="sign">
+                            签收栏
+                        </div>
+                    </td>
+                    <td valign="bottom" colspan="2" style="text-align:center;font-size:12px;width:20mm;font-family:黑体;border-right:0mm;">
+                        已验视
+                    </td>
+                </tr>
+                <%--==================================下联=============================================--%>
+                <%--德邦图标--%>
+                <tr style="height: 12mm;" >
+                    <td colspan="4" align="center"></td>
+                    <td colspan="6" align="center">
+                    </td>
+                </tr>
+                <%--收件人--%>
+                <tr style="height: 10mm;">
+                    <td  colspan="1"style="border-right:0mm;font-family:黑体;font-size:11pt;text-align:center;"> <img src="{{URL::asset('./images/dbwl/revice.png')}}" /></td>
+                    <td  colspan="7"style="font-family:黑体;text-align:left; font-size:10px;font-weight:bold;" id="conMsg2">
+                        <span class="conName">张小二</span>&nbsp;&nbsp;
+                        <span class="conPhone">(优先取手机号取不到取固话)</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+                        <span class="conTel"></span><br/><span class="caddress">上海市青浦区徐泾镇明珠路1018号</span></td>
+                    <%--<td  rowspan="2" valign="bottom">  <!-- <img src="../images/order/deppon_qrcode.jpg" /> --> </td>--%>
+                    <td valign="bottom" rowspan="2" style="width:180mm;border-right:0mm;">
+                        <img src="{{URL::asset('./images/dbwl/qrCode.jpg')}}" style="width: 18mm; height: 18mm" />
+                    </td>
+                </tr>
+                <%--寄件人--%>
+                <tr style="height: 10mm;">
+                    <td  colspan="1"style="font-weight:bold;border-right:0mm;font-family:黑体;font-size:14pt;width:10mm;text-align:center;">寄</td>
+                    <td  colspan="7"style="font-family:黑体;text-align:left; font-size:7pt;width:70mm">
+                        <span class="shipperName">张小二</span>&nbsp;&nbsp;&nbsp;
+                        <span class="shipperPhone">400-617-9999</span><br/>
+                        <span class="saddress">酒仙网电子商务股份有限公司</span>
+                </tr>
+                <tr style="text-align: left;">
+                    <td colspan="10">
+                        <div class="singlePlane2" style="height: 5mm; max-height: 5mm;">
+                            客户订单号:<span class="originalNumber"></span>
+                        </div>
+                        <div class="singlePlane2" style="height: 10mm; max-height: 10mm;">
+                            货物品名:<span id="cargoName" class="cargoName"></span>
+                        </div>
+                        <div class="singlePlane2" style="height: 11mm; max-height: 11mm;">
+                            备注:<span class="transNote" id="transNote"></span>
+                        </div>
+                        <div class="singlePlane2" style="height: 2mm; max-height: 2mm;">
+                            <!--                        <%&#45;&#45;用户订单号:<span class="orderNumber"></span>&#45;&#45;%>-->
+                            用户订单号:<span class="orderNumber"></span>
+                        </div>
+                    </td>
+                </tr>
+            </table>
+        </div>
+    </div>
+@endsection
 
 @section('lastScript')
     <style type="text/css">
@@ -293,6 +538,12 @@
     <script type="text/javascript" src="{{mix('js/queryForm/export.js')}}"></script>
     <script type="text/javascript" src="{{mix('js/queryForm/queryForm.js')}}"></script>
     <script type="text/javascript" src="{{mix('js/queryForm/header.js')}}"></script>{{--新版2--}}
+{{--    德邦物流--}}
+{{--    <script type="text/javascript" src="{{URL::asset('js/lodop/jquery.js')}}"></script>--}}
+    <script type="text/javascript" src="{{mix('js/lodop/myAlert.js')}}"></script>
+    <script type="text/javascript" src="{{mix('js/lodop/myPrintKit.js')}}"></script>
+    <script type="text/javascript" src="{{mix('js/lodop/jquery.PrintArea.js')}}"></script>
+    <script type="text/javascript" src="{{mix('js/lodop/LodopFuncs.js')}}"></script>
     <script>
         let vue = new Vue({
             el:'#list',
@@ -352,6 +603,7 @@
                         district:'{{$waybill->order_district ?? ($waybill->district->name ?? '')}}',
                         order_status:'{{$waybill->order->wms_status ?? ''}}',
                         is_to_pay:'{{ $waybill->is_to_pay }}',
+                        express_face_list:'{{ $waybill->express_face_list }}',
                     },
                     @endforeach
                 ],
@@ -393,6 +645,7 @@
                 selectTr:'',
                 dailyBilling:{screenDate:'', billing:''},
                 error:{screenDate:'', billing:''},
+                expresss:[{name:1,value:'是'},{name:0,value:'否'}]
             },
             mounted:function(){
                 $(".tooltipTarget").tooltip({'trigger':'hover'});
@@ -427,6 +680,7 @@
                         {name:'logistic',type:'select_multiple_select',tip:['输入关键词快速定位下拉列表,回车确定','选择要显示的承运商'],
                             placeholder:['承运商','定位或多选承运商'],data:this.logistics},
                         {name:'carType_id',type:'select',placeholder: '车型',data:this.carTypes},
+                        {name:'express_face_list',type:'select',placeholder: '快递面单是否打印',data:this.expresss},
                     ]
                 ];
                 let param=[];
@@ -483,6 +737,26 @@
                         });
                     })
                 },
+                //快递面单打印
+                expressFaceList(){
+                    if (checkData.length<1){
+                        window.tempTip.setDuration(2000);
+                        window.tempTip.show("未选择任何记录");
+                        return;
+                    }
+                    window.tempTip.postBasicRequest("{{url('transport/waybill/expressFaceList')}}",{ids:checkData},res=>{
+                        let msg = '';
+                        res.forEach((item,index)=>{
+                            if (item.express_face_list == 1 )msg += item.waybill_number + " "
+                        })
+                        if(msg)msg += '已打印过,确定重复打印? '
+                        window.tempTip.confirm(msg ?? "确定要打印快递面单吗?",()=>{
+                            window.tempTip.setDuration(4000);
+                            window.tempTip.waitingTip("打印中,请稍等...");
+                            printTest(res)
+                        })
+                    });
+                },
                 rendingFloatBtn(){
                     let parent = $('.pick-btn :visible');
                     if (parent.length<1)return;
@@ -567,6 +841,7 @@
                         {name:'operation',value: '操作', neglect: true, class:"td-operation"},@endcan
                         {name:'onTop',value: '置顶', neglect: true, class:"td-operation"},
                         {name:'status',value: '状态', class:"td-operation"},
+                        {name:'express_face_list',value: '快递面单是否打印', class:"td-operation"},
                         {name:'index',value: '序号', neglect: true, class:"td-warm"},
                         {name:'created_at', neglect: true,value: '创建时间', class:"td-warm"},
                         {name:'operating',value: '操作记录', class:"td-warm"},

+ 6 - 0
routes/apiLocal.php

@@ -53,6 +53,7 @@ Route::group(['prefix' => 'personnel'], function () {
             Route::put('updateFacilitator', 'DischargeTaskController@updateTaskFacilitatorApi')->name('discharge.updateTaskFacilitatorApi');
             Route::put('updateColumn', 'DischargeTaskController@updateApi')->name('facilitator.updateColumnApi');
             Route::post('import', 'DischargeTaskController@importApi')->name('discharge.importApi');
+            Route::post('constEntryImport', 'DischargeTaskController@constEntryImportApi')->name('discharge.constEntryImportApi');
         });
     });
 });
@@ -226,3 +227,8 @@ Route::group(['prefix' => 'package'], function () {
 Route::group(['prefix' => 'print'],function (){
     Route::post('template/store','PrintTemplateController@storeAi');
 });
+
+Route::prefix('workOrder')->group(function(){
+    Route::post('store','WorkOrderController@storeApi');
+    Route::post('review','WorkOrderController@reviewApi');
+});

+ 8 - 0
routes/web.php

@@ -380,6 +380,8 @@ Route::group(['middleware'=>'auth'],function ($route){
             Route::post('waybillSplit','WaybillController@waybillSplit');
             Route::resource('waybillFinancialSnapshot','WaybillFinancialSnapshotsController');
             Route::resource('waybillFinancialExcepted','WaybillFinancialExceptedController');
+            Route::post('expressFaceList','WaybillController@expressFaceList');
+            Route::post('changeExpressTag','WaybillController@changeExpressTag');
         });
         Route::resource('waybill','WaybillController');
     });
@@ -489,6 +491,7 @@ Route::group(['middleware'=>'auth'],function ($route){
             Route::post('settingCommodityMaximum','StorageController@settingCommodityMaximum');
             Route::post('checkTask','StorageController@checkTask');
             Route::post('changeAsnRule','StorageController@changeAsnRule');
+            Route::post('callRobot','StorageController@callRobot');
         });
         Route::group(['prefix'=>'handInStorage'],function() {
             Route::get('receive',function (){return view('store.handInStorage.receive');});//收货页面
@@ -778,6 +781,10 @@ Route::group(['middleware'=>'auth'],function ($route){
         Route::post('resetInterfaceReturnMark','OrderController@resetInterfaceReturnMark');
         Route::post('createRejectedBill','OrderController@createRejectedBill');
         Route::post('isRejectedBillExist','OrderController@isRejectedBillExist');
+        /** 工单 */
+        Route::prefix('workOrder')->group(function(){
+            Route::get('index','WorkOrderController@index');
+        });
     });
     /** 结算 */
     $route->group(['prefix'=>'finance'],function(){
@@ -1011,3 +1018,4 @@ Route::group(['middleware'=>'auth'],function ($route){
     });
 
 });
+

+ 9 - 0
webpack.mix.js

@@ -35,4 +35,13 @@ mix.js('resources/js/elementUi.js','public/js/element-ui.js')
 mix.copy("resources/sass/animation.css",'public/css/animation.css');
 mix.js("resources/js/marked.js", "public/js/marked.js");
 
+//德邦快递
+mix.js('resources/js/lodop/jquery.PrintArea.js','public/js/lodop/jquery.PrintArea.js')
+mix.copy('resources/js/lodop/LodopFuncs.js','public/js/lodop/LodopFuncs.js')
+mix.js('resources/js/lodop/myAlert.js','public/js/lodop/myAlert.js')
+mix.copy('resources/js/lodop/myPrintKit.js','public/js/lodop/myPrintKit.js')
+mix.copy('resources/js/lodop/install_lodop32.exe','public/js/lodop/install_lodop32.exe')
+mix.copy('resources/js/lodop/install_lodop64.exe','public/js/lodop/install_lodop64.exe')
+mix.copy('resources/js/lodop/CLodop_Setup_for_Win32NT.exe','public/js/lodop/CLodop_Setup_for_Win32NT.exe')
+
 mix.version();

Vissa filer visades inte eftersom för många filer har ändrats