Преглед изворни кода

Merge branch 'yang-panel-new-cache' into yang

# Conflicts:
#	app/Providers/AppServiceProvider.php
#	app/Services/NewOrderCountingRecordService.php
ANG YU пре 5 година
родитељ
комит
b5ce9ecc20
46 измењених фајлова са 1335 додато и 364 уклоњено
  1. 1 1
      app/Console/Commands/WasSyncWmsAsnInformation.php
  2. 4 1
      app/Console/Kernel.php
  3. 1 1
      app/Http/Controllers/CitiesController.php
  4. 2 2
      app/Http/Controllers/ControlPanelController.php
  5. 12 1
      app/Http/Controllers/CustomerBaseController.php
  6. 2 3
      app/Http/Controllers/OwnerController.php
  7. 24 10
      app/Http/Controllers/PriceModelController.php
  8. 37 12
      app/Http/Controllers/TestController.php
  9. 1 1
      app/Http/Controllers/api/thirdPart/jianshang/RejectedController.php
  10. 36 4
      app/Imports/ExpressImport.php
  11. 74 11
      app/Imports/OwnerPriceLogisticDetailImport.php
  12. 8 0
      app/Observers/OwnerObserver.php
  13. 4 0
      app/Providers/AppServiceProvider.php
  14. 6 6
      app/Services/CommodityService.php
  15. 45 14
      app/Services/NewOrderCountingRecordService.php
  16. 4 0
      app/Services/OrderIssueService.php
  17. 12 7
      app/Services/OrderService.php
  18. 32 1
      app/Services/OwnerService.php
  19. 3 4
      app/Services/RejectedBillService.php
  20. 6 5
      app/Services/StoreService.php
  21. 4 1
      app/StoreItems.php
  22. 3 0
      app/Waybill.php
  23. 3 0
      resources/js/queryForm/queryForm.js
  24. 27 1
      resources/sass/text.scss
  25. 13 32
      resources/views/customer/customer/_customerLog.blade.php
  26. 106 76
      resources/views/customer/customer/index.blade.php
  27. 0 55
      resources/views/customer/project/_three.blade.php
  28. 398 42
      resources/views/customer/project/create.blade.php
  29. 8 5
      resources/views/customer/project/part/_addFeature.blade.php
  30. 1 0
      resources/views/customer/project/part/_directLogistic.blade.php
  31. 57 0
      resources/views/customer/project/part/_express.blade.php
  32. 72 0
      resources/views/customer/project/part/_logistic.blade.php
  33. 91 0
      resources/views/customer/project/part/_logisticDetail.blade.php
  34. 0 0
      resources/views/customer/project/part/_one.blade.php
  35. 53 52
      resources/views/customer/project/part/_operation.blade.php
  36. 0 0
      resources/views/customer/project/part/_storage.blade.php
  37. 171 0
      resources/views/customer/project/part/_three.blade.php
  38. 0 0
      resources/views/customer/project/part/_two.blade.php
  39. 1 1
      resources/views/maintenance/owner/recycle.blade.php
  40. 1 1
      resources/views/maintenance/priceModel/logistic/index.blade.php
  41. 5 8
      resources/views/order/index/delivering.blade.php
  42. 3 3
      resources/views/order/issue/index.blade.php
  43. 1 1
      resources/views/waybill/index.blade.php
  44. 1 1
      resources/views/waybill/recycle.blade.php
  45. 0 1
      routes/apiLocal.php
  46. 2 0
      routes/web.php

+ 1 - 1
app/Console/Commands/WasSyncWmsAsnInformation.php

@@ -54,7 +54,7 @@ class WasSyncWmsAsnInformation extends Command
     {
         $this->init();
         if($this->is_enabled==false)return;
-        sleep(rand(10,25));
+        sleep(rand(1,2));
         $start_time =  Cache::remember($this->task_start_at,null,function (){
             return ValueStore::query()->firstOrCreate(['name'=>$this->task_start_at])->first()->value;
         });

+ 4 - 1
app/Console/Kernel.php

@@ -14,6 +14,7 @@ use App\Console\Commands\SyncUserVisitMenuLogsCacheTask;
 use App\Console\Commands\SyncWmsCommoditiesInformation;
 use App\Console\Commands\SyncWMSOrderTask;
 use App\Console\Commands\TestTemp;
+use App\Console\Commands\WasSyncWmsAsnInformation;
 use App\Console\Commands\WASSyncWMSOrderInformation;
 use Illuminate\Console\Scheduling\Schedule;
 use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
@@ -39,7 +40,8 @@ class Kernel extends ConsoleKernel
         SyncWMSOrderTask::class,
 //        SyncOrderPackageLogisticRouteTask::class,
         SyncWmsCommoditiesInformation::class,
-        ClearCancelledOrderTask::class
+        ClearCancelledOrderTask::class,
+        WasSyncWmsAsnInformation::class,
     ];
 
     /**
@@ -63,6 +65,7 @@ class Kernel extends ConsoleKernel
 //        $schedule->command('syncOrderPackageLogisticRouteTask')->dailyAt('00:00')();//同步快递信息到orderPackage
         $schedule->command('SyncWmsCommoditiesInformation')->everyMinute();
         $schedule->command('clear:cancelledOrder')->everyTenMinutes();
+        $schedule->command('WasSyncWmsAsnInformation')->everyMinute();
     }
 
     /**

+ 1 - 1
app/Http/Controllers/CitiesController.php

@@ -83,6 +83,6 @@ class CitiesController extends Controller
     }
 
     public function get(){
-        return City::query()->select("id","name","province_id")->get();
+        return ["success"=>true,"data"=>City::query()->select("id","name","province_id")->get()];
     }
 }

+ 2 - 2
app/Http/Controllers/ControlPanelController.php

@@ -41,7 +41,7 @@ class ControlPanelController extends Controller
         $end = (new Carbon())->toDateString();
         $ownerIds = $this->getCountingOwnerIds(null);
         $unit = '日';
-        $orderCountingRecords = $orderCountingRecordService->orderCountingRecords($start, $end, $unit, $ownerIds);
+        $orderCountingRecords = $orderCountingRecordService->orderCountingRecordsFromCache($start, $end, $unit, $ownerIds);
         $logisticsCountingRecords = $orderCountingRecordService->logisticsCountingRecords($start, $end, $ownerIds);
         $warehouseCountingRecords = $orderCountingRecordService->warehouseCountingRecords($start, $end, $ownerIds);
 
@@ -60,7 +60,7 @@ class ControlPanelController extends Controller
         $start = Carbon::parse($request->start)->gt(Carbon::now()) ? Carbon::now()->toDateString() : $request->start;
         $end = Carbon::parse($request->end)->gt(Carbon::now()) ? Carbon::now()->toDateString() : $request->end;
         $ownerIds = $this->getCountingOwnerIds(null);
-        $orderCountingRecords = $orderCountingRecordService->orderCountingRecords($start, $end, $request->unit, $ownerIds);
+        $orderCountingRecords = $orderCountingRecordService->orderCountingRecordsFromCache($start, $end, $request->unit, $ownerIds);
         return compact('orderCountingRecords');
     }
 

+ 12 - 1
app/Http/Controllers/CustomerBaseController.php

@@ -4,9 +4,11 @@ namespace App\Http\Controllers;
 
 use App\Components\SyncResponse;
 use App\Customer;
+use App\CustomerLog;
 use App\CustomerTag;
 use App\Owner;
 use App\Services\LogService;
+use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
 use Illuminate\Support\Facades\Gate;
@@ -24,7 +26,10 @@ class CustomerBaseController extends Controller
     public function index(Request $request)
     {
         $this->gate("客户-查询");
-        $customers = app('CustomerService')->paginate($request->input(),["owners.contracts.files","tags:id,name"]);
+        $customers = app('CustomerService')->paginate($request->input(),["owners.contracts.files","tags:id,name","customerLogs"=>function($query){
+            /** @var Builder $query */
+            $query->with(["status:id,name,created_at","user:id,name"])->orderByDesc('id');
+        }]);
         $owners = app("OwnerService")->getIntersectPermitting(['id','name','customer_id']);
         $tags = CustomerTag::query()->get(["id","name"]);
         return response()->view('customer.customer.index',compact("customers","owners","tags"));
@@ -158,4 +163,10 @@ class CustomerBaseController extends Controller
         $customer->load("tags");
         return ["success"=>true,"data"=>$customer->tags];
     }
+
+    public function destroyLog(Request $request)
+    {
+        CustomerLog::destroy($request->input("id"));
+        return ["success"=>true];
+    }
 }

+ 2 - 3
app/Http/Controllers/OwnerController.php

@@ -164,9 +164,8 @@ class OwnerController extends Controller
             return ['success' => 'false', 'fail_info' => "没有权限"];
         }
         $id = $request->input('id');
-        $owner = Owner::query()->whereNotNull('deleted_at')->where('id', $id)->update([
-            "deleted_at" => null,
-        ]);
+        $owner = Owner::query()->whereNotNull('deleted_at')->where('id', $id)->first();
+        $owner->update(["deleted_at" => null]);
         app('LogService')->log(__METHOD__, __FUNCTION__, json_encode($request->toArray()), Auth::user()['id']);
         return ['success' => 'true', 'owner' => $owner];
     }

+ 24 - 10
app/Http/Controllers/PriceModelController.php

@@ -2,16 +2,17 @@
 
 namespace App\Http\Controllers;
 
+use App\Components\AsyncResponse;
 use App\Imports\ExpressImport;
 use App\Imports\OwnerPriceDirectLogisticDetailImport;
 use App\Imports\OwnerPriceLogisticDetailImport;
 use App\Owner;
-use App\OwnerOutStorageRule;
 use App\OwnerPriceDirectLogistic;
 use App\OwnerPriceExpress;
 use App\OwnerPriceExpressProvince;
 use App\OwnerPriceLogistic;
 use App\OwnerPriceOperation;
+use App\OwnerPriceOperationItemOut;
 use App\Services\common\ExportService;
 use App\Services\LogService;
 use App\Services\OwnerOutStorageRuleService;
@@ -26,6 +27,7 @@ use Maatwebsite\Excel\Facades\Excel;
 
 class PriceModelController extends Controller
 {
+    use AsyncResponse;
     public function storageIndex(Request $request)
     {
         if(!Gate::allows('计费模型-仓储')){ return redirect('denied');  }
@@ -187,7 +189,7 @@ class PriceModelController extends Controller
         $row = app('OwnerOutStorageRuleService')->update(["id"=>$id],["feature"=>$feature]);
         if ($row != 1)return ["success"=>false,"data"=>"影响了“".$row."”行"];
         LogService::log(__METHOD__,"计费模型-修改出库特征",json_encode($request->input()));
-        OwnerOutStorageRule::$features = $result["map"];
+        OwnerPriceOperationItemOut::$features = $result["map"];
         $rule = app('OwnerOutStorageRuleService')->find($id)->append("featureFormat");
         return ["success"=>true,"data"=>["featureFormat"=>$rule->featureFormat,"feature"=>$feature]];
     }
@@ -208,7 +210,8 @@ class PriceModelController extends Controller
             }
         }
         if (count($stack) > 0)return ["success"=>false,"data"=>"组标记错误,起始与结束标记必须对应"];
-        return ["success"=>true,"data"=>$feature];
+        if ($request->has("isFormat"))$this->success(["feature"=>$feature,"featureFormat"=>app("FeatureService")->formatFeature($result["map"], $feature)]);
+        $this->success($feature);
     }
 
     public function operationDestroy($id)
@@ -434,11 +437,16 @@ class PriceModelController extends Controller
         ini_set('max_execution_time',2500);
         ini_set('memory_limit','1526M');
         $fileSuffix = ucwords($fileSuffix);
-        /** @var OwnerPriceExpress $model */
-        $model = app('OwnerPriceExpressService')->find($request->input("id"),["details"]);
-        Excel::import(new ExpressImport($model),$request->file('file')->path(),null,$fileSuffix);
-        if (Cache::has('express'))return Cache::pull('express');
 
+        if (!$request->has("id")){
+            Excel::import(new ExpressImport(null),$request->file('file')->path(),null,$fileSuffix);
+        }else{
+            /** @var OwnerPriceExpress $model */
+            $model = app('OwnerPriceExpressService')->find($request->input("id"),["details"]);
+            Excel::import(new ExpressImport($model),$request->file('file')->path(),null,$fileSuffix);
+        }
+
+        if (Cache::has('express'))return Cache::pull('express');
         return ["success"=>false,"data"=>"导入发生错误,数据无响应"];
     }
 
@@ -651,9 +659,15 @@ class PriceModelController extends Controller
         ini_set('max_execution_time',2500);
         ini_set('memory_limit','1526M');
         $fileSuffix = ucwords($fileSuffix);
-        /** @var OwnerPriceLogistic $model */
-        $model = app('OwnerPriceLogisticService')->find($request->input("id"),["unit","otherUnit","details"]);
-        Excel::import(new OwnerPriceLogisticDetailImport($model),$request->file('file')->path(),null,$fileSuffix);
+
+        if (!$request->has("id")){
+            Excel::import(new OwnerPriceLogisticDetailImport(null),$request->file('file')->path(),null,$fileSuffix);
+        }else{
+            /** @var OwnerPriceLogistic $model */
+            $model = app('OwnerPriceLogisticService')->find($request->input("id"),["unit","otherUnit","details"]);
+            Excel::import(new OwnerPriceLogisticDetailImport($model),$request->file('file')->path(),null,$fileSuffix);
+        }
+
         if (Cache::has('logistic'))return Cache::pull('logistic');
 
         return ["success"=>false,"data"=>"导入发生错误,数据无响应"];

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

@@ -25,6 +25,7 @@ use App\Log;
 use App\Logistic;
 use App\Menu;
 use App\OracleActAllocationDetails;
+use App\OracleBasCustomer;
 use App\OracleBasSKU;
 use App\OracleDOCASNHeader;
 use App\OracleDOCOrderHeader;
@@ -89,6 +90,7 @@ use Illuminate\Http\Request;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Hash;
 use Illuminate\Support\Facades\Http;
+use Illuminate\Support\Facades\Redis;
 use Illuminate\Support\Facades\Storage;
 use Illuminate\Support\Str;
 use Maatwebsite\Excel\Facades\Excel;
@@ -159,7 +161,7 @@ sql;
     }
     public function zzd()
     {
-        $this->disposeDetail();
+        dd(300%300);
     }
 
     public function zzd1()
@@ -282,9 +284,40 @@ sql;
 
     function t1(Request $request)
     {
-        $user=City::query()->firstx();
-        $user['created_at'] = '2020-12-23';
-        $user->save();
+        $times=12345;
+        $start_at = microtime(true);
+        for($i=0;$i<$times;$i++){
+            Cache::put(md5('k_delme'.$i), 'a');
+        }
+        echo microtime(true)-$start_at, '<br>';
+
+        $start_at = microtime(true);
+        for($i=0;$i<$times;$i++){
+            Cache::get(md5('k_delme'.$i));
+        }
+        echo microtime(true)-$start_at, '<br>';
+
+        $start_at = microtime(true);
+        for($i=0;$i<$times;$i++){
+            Cache::pull(md5('k_delme'.$i));
+        }
+        echo microtime(true)-$start_at, '<br>';
+        for($i=0;$i<$times;$i++){
+            Redis::set(md5('k_delme'.$i), 'a');
+        }
+        echo microtime(true)-$start_at, '<br>';
+
+        $start_at = microtime(true);
+        for($i=0;$i<$times;$i++){
+            Redis::get(md5('k_delme'.$i));
+        }
+        echo microtime(true)-$start_at, '<br>';
+
+        $start_at = microtime(true);
+        for($i=0;$i<$times;$i++){
+            Redis::del(md5('k_delme'.$i));
+        }
+        echo microtime(true)-$start_at, '<br>';
     }
 
     function packageT(Request $request)
@@ -1257,14 +1290,6 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
 //        return view('test');
     }
 
-    public function testSyncCommodity()
-    {
-        dump('start' . (string)Carbon::now());
-        $syncCommodityTask=new SyncWmsCommoditiesInformation();
-        $syncCommodityTask->handle();
-        dump('end' . (string)Carbon::now());
-    }
-
     public function editOrderSyncAt()
     {
         ValueStore::query()->where('name','order_last_created_sync_at')->update(['value'=>'2020-12-22 09:00:00']);

+ 1 - 1
app/Http/Controllers/api/thirdPart/jianshang/RejectedController.php

@@ -221,7 +221,7 @@ class RejectedController extends Controller
             $response=false;
         }
         if(!$response){
-            app('LogService')->log(__METHOD__,'笕尚接口返回异常!!:',$response->body());
+            app('LogService')->log(__METHOD__,'笕尚接口返回异常!!:',"沒有返回");
             return false;
         }
         app('LogService')->log(__METHOD__,'笕尚接口返回:',$response->body());

+ 36 - 4
app/Imports/ExpressImport.php

@@ -28,10 +28,6 @@ class ExpressImport implements ToCollection,WithHeadingRow
     */
     public function collection(Collection $collection)
     {
-        if (!$this->express){
-            Cache::put("express",["success"=>false, "data"=>"不存在父级"],86400);
-            return false;
-        }
         $row = $collection->first();
         $header = [
             "省","首重价格","续重价格"
@@ -50,6 +46,10 @@ class ExpressImport implements ToCollection,WithHeadingRow
             $map[$province->name] = $province->id;
         }
 
+        if (!$this->express){
+            return $this->readonly($collection,$map);
+        }
+
         //已存在的计费
         $existDetails = [];
         foreach ($this->express->details as $detail){
@@ -105,4 +105,36 @@ class ExpressImport implements ToCollection,WithHeadingRow
         Cache::put("express",["success"=>true,"data"=>$this->express->details,"errors"=>$errors],86400);
         return true;
     }
+
+    private function readonly(Collection $collection, array $map)
+    {
+        $errors = [];
+        $data = [];
+        foreach ($collection as $index => $item){
+            if (!isset($map[$item["省"]])){
+                foreach ($map as $name=>$id){
+                    if (mb_strpos($item["省"],$name) !== false)$item["省"] = $name;
+                }
+                if (!isset($map[$item["省"]])){
+                    $errors[] = "第“".($index+2)."”行未知省份";
+                    continue;
+                }
+            }
+            if (!is_numeric($item["首重价格"]) || $item["首重价格"] <= 0){
+                $errors[] = "第“".($index+2)."”行非法首重价格";
+                continue;
+            }
+            if (!is_numeric($item["续重价格"]) || $item["续重价格"] <= 0){
+                $errors[] = "第“".($index+2)."”行非法续重价格";
+                continue;
+            }
+            $data[] = [
+                "province_id" => $map[$item["省"]],
+                "initial_weight_price" => $item["首重价格"],
+                "additional_weight_price" => $item["续重价格"],
+            ];
+        }
+        Cache::put("express",["success"=>true,"data"=>$data,"errors"=>$errors],86400);
+        return true;
+    }
 }

+ 74 - 11
app/Imports/OwnerPriceLogisticDetailImport.php

@@ -3,7 +3,6 @@
 namespace App\Imports;
 
 use App\City;
-use App\OwnerPriceLogistic;
 use App\OwnerPriceLogisticDetail;
 use App\Province;
 use App\Services\common\BatchUpdateService;
@@ -19,7 +18,7 @@ HeadingRowFormatter::default('none');
 class OwnerPriceLogisticDetailImport implements ToCollection,WithHeadingRow
 {
     protected $logistic;
-    public function __construct(OwnerPriceLogistic $logistic)
+    public function __construct($logistic)
     {
         $this->logistic = $logistic;
     }
@@ -30,10 +29,6 @@ class OwnerPriceLogisticDetailImport implements ToCollection,WithHeadingRow
     */
     public function collection(Collection $collection)
     {
-        if (!$this->logistic){
-            Cache::put("logistic",["success"=>false, "data"=>"不存在父级"],86400);
-            return false;
-        }
         $row = $collection->first();
         $header = [
             "计数单位","计数区间","省份","市","单价","送货费","起始计费","起始计数","费率"
@@ -61,6 +56,9 @@ class OwnerPriceLogisticDetailImport implements ToCollection,WithHeadingRow
             $cityMappingProvince[$city->id] = $city->province_id;
         }
 
+        if (!$this->logistic)
+            return $this->readonly($collection, $map, $cityMap, $cityMappingProvince);
+
         //对比单位
         $unit = $this->logistic->unit ? strtoupper($this->logistic->unit->name) : '';
         $otherUnit = $this->logistic->otherUnit ? strtoupper($this->logistic->otherUnit->name) : '';
@@ -99,14 +97,10 @@ class OwnerPriceLogisticDetailImport implements ToCollection,WithHeadingRow
                 if (isset($map[mb_substr($item["省份"], 0,-1)]))$item["省份"] = mb_substr($item["省份"], 0,-1);
             }
             if (!$item["计数单位"] || (strtoupper($item["计数单位"]) != $unit && strtoupper($item["计数单位"]) != $otherUnit)){
-                //$errors[] = "第“".($index+2)."”行单位不符合";
-                //continue;
                 Cache::put("logistic",["success"=>false, "data"=>"第“".($index+2)."”行单位不符合"],86400);
                 return false;
             }
             if (!$item["计数区间"] || array_search($item["计数区间"],$range[strtoupper($item["计数单位"])]) === false){
-                //$errors[] = "第“".($index+2)."”行非法首重价格";
-                //continue;
                 Cache::put("logistic",["success"=>false, "data"=>"第“".($index+2)."”行区间不符合"],86400);
                 return false;
             }
@@ -135,8 +129,8 @@ class OwnerPriceLogisticDetailImport implements ToCollection,WithHeadingRow
                 continue;
             }
             $item["省份"] = $map[$item["省份"]];
-            $item["计数单位"] = strtoupper($item["计数单位"]) == $unit ? $this->logistic->unit_id : $this->logistic->other_unit_id;
             $item["市"] = $cityMap[$item["市"]];
+            $item["计数单位"] = strtoupper($item["计数单位"]) == $unit ? $this->logistic->unit_id : $this->logistic->other_unit_id;
             $key = $item["计数单位"]."_".$item["计数区间"]."_".$item["省份"]."_".$item["市"];
             if (isset($existInsert[$key])){
                 $errors[] = "第“".($index+2)."”行与第“".$existInsert[$key]."”行重复";
@@ -183,4 +177,73 @@ class OwnerPriceLogisticDetailImport implements ToCollection,WithHeadingRow
         Cache::put("logistic",["success"=>true,"data"=>$this->logistic->details,"errors"=>$errors],86400);
         return true;
     }
+
+    public function readonly(Collection $collection, array $map, array $cityMap, array $cityMappingProvince)
+    {
+        //生成列表内的重复条目
+        $existInsert = [];
+        //符合数据
+        $data = [];
+        //错误信息
+        $errors = [];
+        foreach ($collection as $index => $item){
+            /* 数据校验 */
+            if (!$item["省份"]){
+                $errors[] = "第“".($index+2)."”行省份为空";
+                continue;
+            }else{
+                if ((!isset($map[$item["省份"]]) && !isset($map[mb_substr($item["省份"], 0,-1)]))){
+                    $errors[] = "第“".($index+2)."”行未知省份";
+                    continue;
+                }
+                if (isset($map[mb_substr($item["省份"], 0,-1)]))$item["省份"] = mb_substr($item["省份"], 0,-1);
+            }
+            if (!isset($cityMap[$item["市"]])){
+                $errors[] = "第“".($index+2)."”行未知城市";
+                continue;
+            }
+            if (!$item["单价"] || !is_numeric($item["单价"]) || $item["单价"] <= 0){
+                $errors[] = "第“".($index+2)."”行非法单价";
+                continue;
+            }
+            $numeric = ["送货费","起始计费","起始计数","费率"];
+            $sign = false;
+            foreach ($numeric as $column){
+                if ($item[$column] && (!is_numeric($item[$column]) || $item[$column] <= 0)){
+                    $errors[] = "第“".($index+2)."”行非法".$column;
+                    $sign = true;
+                    break;
+                }
+            }
+            if ($sign)continue;
+
+            /* 数据转换及存在校验 */
+            if ($cityMappingProvince[$cityMap[$item["市"]]] != $map[$item["省份"]]){
+                $errors[] = "第“".($index+2)."”行城市不属于该省份";
+                continue;
+            }
+            $item["省份"] = $map[$item["省份"]];
+            $item["市"] = $cityMap[$item["市"]];
+            $key = $item["计数单位"]."_".$item["计数区间"]."_".$item["省份"]."_".$item["市"];
+            if (isset($existInsert[$key])){
+                $errors[] = "第“".($index+2)."”行与第“".$existInsert[$key]."”行重复";
+                continue;
+            }
+
+            $data[] = [
+                "unit_id" => $item["计数单位"],
+                "range" => $item["计数区间"],
+                "province_id" => $item["省份"],
+                "city_id" => $item["市"],
+                "unit_price" => $item["单价"],
+                "delivery_fee" => $item["送货费"],
+                "initial_fee" => $item["起始计费"],
+                "initial_amount" => $item["起始计数"],
+                "rate" => $item["费率"],
+            ];
+            $existInsert[$key] = $index+2;
+        }
+        Cache::put("logistic",["success"=>true,"data"=>$data,"errors"=>$errors],86400);
+        return true;
+    }
 }

+ 8 - 0
app/Observers/OwnerObserver.php

@@ -17,4 +17,12 @@ class OwnerObserver
         if(env('APP_ENV')=='production')
             app("OwnerService")->syncPush($owner);
     }
+
+    public function updated(Owner $owner)
+    {
+        if(env('APP_ENV')=='production'){
+            app("OwnerService")->syncUpdate($owner);
+        }
+    }
+
 }

+ 4 - 0
app/Providers/AppServiceProvider.php

@@ -10,6 +10,8 @@ use App\Services\CommodityService;
 use App\Services\common\BatchUpdateService;
 use App\Services\CommodityBarcodeService;
 use App\Services\common\DataHandlerService;
+use App\Services\CustomerLogService;
+use App\Services\CustomerLogStatusService;
 use App\Services\CustomerService;
 use App\Services\DepositoryService;
 use App\Services\FeatureService;
@@ -195,6 +197,8 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('WarehouseService',WarehouseService::class);
         app()->singleton('WaybillFinancialService',WaybillFinancialService::class);
         app()->singleton('WeighExceptedService',WeighExceptedService::class);
+        app()->singleton('CustomerLogService',CustomerLogService::class);
+        app()->singleton('CustomerLogStatusService',CustomerLogStatusService::class);
         app()->singleton('OrderPackageReceivedSyncService',OrderPackageReceivedSyncService::class);
     }
 

+ 6 - 6
app/Services/CommodityService.php

@@ -401,7 +401,7 @@ Class CommodityService
         $create_key = config('sync.commodity_sync.cache_prefix.create');
         /** @var OracleBasSkuService $oracleBasSkuService */
         $oracleBasSkuService = app(OracleBasSkuService::class);
-        $last_time = $this->getAsnLastSyncAt($created_at, 'create');
+        $last_time = $this->getCommodityLastSyncAt($created_at, 'create');
         $basSkus = $oracleBasSkuService->getWmsCreatedCommodities($last_time);
         $last_time = $basSkus->first()['addtime'];
         $last_records = $basSkus->where('addtime', $last_time);
@@ -409,7 +409,7 @@ Class CommodityService
         $this->syncCreateCommodity($basSkus);
         $this->deleteCacheKey($create_set, $create_keys);
         $this->setLastRecordsByRedis($create_key, $create_set, $create_keys, $last_records);
-        $this->setAsnLastSyncAt($created_at, $last_time);
+        $this->setCommodityLastSyncAt($created_at, $last_time);
     }
 
     public function syncCommodityUpdated()
@@ -420,7 +420,7 @@ Class CommodityService
         $update_key = config('sync.commodity_sync.cache_prefix.update');
         /** @var OracleBasSkuService $oracleBasSkuService */
         $oracleBasSkuService = app(OracleBasSkuService::class);
-        $last_time = $this->getAsnLastSyncAt($updated_at, 'update');
+        $last_time = $this->getCommodityLastSyncAt($updated_at, 'update');
         $basSkus = $oracleBasSkuService->getWmsUpdatedCommodities($last_time);
         $last_time = $basSkus->first()['edittime'];
         $last_records = $basSkus->where('edittime', $last_time);
@@ -428,7 +428,7 @@ Class CommodityService
         $this->syncUpdateCommodity($basSkus);
         $this->deleteCacheKey($update_set, $update_keys);
         $this->setLastRecordsByRedis($update_key, $update_set, $update_keys, $last_records);
-        $this->setAsnLastSyncAt($updated_at, $last_time);
+        $this->setCommodityLastSyncAt($updated_at, $last_time);
     }
 
     public function syncCreateCommodity($addBasSkus)
@@ -658,7 +658,7 @@ Class CommodityService
         }
     }
 
-    public function getAsnLastSyncAt($key, $type)
+    public function getCommodityLastSyncAt($key, $type)
     {
         $last_time = ValueStore::query()->where('name', $key)->value('value');
         if ($last_time) return $last_time;
@@ -672,7 +672,7 @@ Class CommodityService
         return Carbon::now()->subSeconds(65);
     }
 
-    public function setAsnLastSyncAt($key, $last_time)
+    public function setCommodityLastSyncAt($key, $last_time)
     {
         $asnLastSyncAt = ValueStore::query()->updateOrCreate([
             'name' => $key,

+ 45 - 14
app/Services/NewOrderCountingRecordService.php

@@ -9,10 +9,30 @@ use App\Order;
 use App\OrderCountingRecord;
 use App\Warehouse;
 use Carbon\Carbon;
+use Illuminate\Support\Arr;
+use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\Cache;
 
 class NewOrderCountingRecordService
 {
+    public function orderCountingRecordsFromCache($start, $end, $unit, $ownerIds)
+    {
+        $dataList = collect();
+        if (count($ownerIds) == 1) return $this->orderCountingRecords($start, $end, $unit, $ownerIds);//当前用户只有一个货主权限,只需执行旧方法即可
+        $queryCondition = $this->transfersToCondition($start, $end, $unit, $ownerIds);//根据条件获取查询条件
+        $md5OwnerIds = md5(join(Arr::sortRecursive($ownerIds)));//将$ownerIds排序,保证md5加密后结果一致  将当前用户拥有的ownerIds进行md5加密
+        foreach ($queryCondition['data'] as $dateStr => $ownerIds) {
+            $key = 'new_order_counting_records_' . $dateStr . '_' . $md5OwnerIds . '_' . $queryCondition['unit'];
+            $data = cache()->remember($key, $this->getTtl($dateStr, $unit), function () use ($dateStr, $unit, $ownerIds) {
+                //如果缓存不存在,则将$dateStr作为查询条件,使用之前的接口查询改日的订单量统计结果,由于接口返回collect,去其中的第一个
+                //因为查询条件仅为一天
+                return $this->orderCountingRecords($dateStr, $dateStr, $unit, $ownerIds)->first();
+            });
+            $dataList->push($data);
+        }
+        return $dataList;
+    }
+
     public function orderCountingRecords($start, $end, $unit, $ownerIds)
     {
         $orders = $this->get($start, $end, $unit, $ownerIds);
@@ -148,6 +168,12 @@ class NewOrderCountingRecordService
         return [$orderCountingRecords_fromSelfTable, $lackingCondition];
     }
 
+    /**
+     * 根据$queryCondition从多种数据源中查询数据
+     * 并将结果插入中间表或者缓存
+     * @param $queryCondition
+     * @return Collection|mixed|\Tightenco\Collect\Support\Collection
+     */
     public function getOrderCountingRecords($queryCondition)
     {
         list($orderCountingRecords_fromCache, $lackingCondition)
@@ -167,7 +193,7 @@ class NewOrderCountingRecordService
          */
         if ($lackingCondition['unit'] != '日') {//日为最低粒度,不用进入此方法
             $orderCountingRecords_combinedByLower = $this->getFromLowerUnit($lackingCondition);
-        }else{
+        } else {
             $orderCountingRecords_FromOrder = $this->dataFromOrder($lackingCondition);
         }
         $result = collect();
@@ -207,7 +233,7 @@ class NewOrderCountingRecordService
                 $orderCountingRecords_days = $this->getOrderCountingRecords($conditionClone);
                 $orderCountingRecords_combinedByLower = $this->turnGradingUpToLow($orderCountingRecords_days, $lowUnit, 'year');
                 $this->insertIntoMiddleTable($orderCountingRecords_combinedByLower, '年');
-                $this->insertIntoCache(collect($orderCountingRecords_combinedByLower),'年');
+                $this->insertIntoCache(collect($orderCountingRecords_combinedByLower), '年');
                 break;
             case '月':
                 $lowUnit = '日';
@@ -226,7 +252,7 @@ class NewOrderCountingRecordService
                 $orderCountingRecords_days = $this->getOrderCountingRecords($conditionClone);
                 $orderCountingRecords_combinedByLower = $this->turnGradingUpToLow($orderCountingRecords_days, $lowUnit, 'month');
                 $this->insertIntoMiddleTable($orderCountingRecords_combinedByLower, '月');
-                $this->insertIntoCache(collect($orderCountingRecords_combinedByLower),'月');
+                $this->insertIntoCache(collect($orderCountingRecords_combinedByLower), '月');
 
                 break;
             case '日':
@@ -309,12 +335,7 @@ class NewOrderCountingRecordService
         });
 
         foreach ($map as $key => $orders) {
-
-            $ttl = config('cache.expirations.forever');
-            if (!$this->isNotCurrentDate($orders[0]['date_target'], $unit)) {
-                $ttl = config('cache.expirations.orderCountingRecord');
-            }
-            Cache::put($key, collect($orders), $ttl);
+            Cache::put($key, collect($orders), $this->getTtl($orders[0]['date_target'], $unit));
         }
     }
 
@@ -411,17 +432,17 @@ class NewOrderCountingRecordService
                     break;
             }
             $item['amount'] = $amount;
-            return $result->push(new OrderCountingRecord( [
+            return $result->push(new OrderCountingRecord([
                 'owner_id' => $item->owner_id,
                 'shop_id' => $item->shop_id,
                 'warehouse_id' => $item->warehouse_id,
                 'logistic_id' => $item->logistic_id,
                 'date_target' => $item->date_target,
                 'counting_unit' => $item->counting_unit,
-                'amount'=>$item->amount,
-                'year'=>$item->year,
-                'month'=>$item->month,
-                'week'=>$item->week
+                'amount' => $item->amount,
+                'year' => $item->year,
+                'month' => $item->month,
+                'week' => $item->week
             ]));
         }
         return $result;
@@ -464,4 +485,14 @@ class NewOrderCountingRecordService
             }
         }
     }
+
+    private function getTtl($dateStr, $unit)
+    {
+        if ($this->isNotCurrentDate($dateStr, $unit)) {
+            $ttl = config('cache.expirations.forever');//非当前日期的缓存为永久
+        } else {
+            $ttl = config('cache.expirations.orderCountingRecord');//当前日期缓存为1800s
+        }
+        return $ttl;
+    }
 }

+ 4 - 0
app/Services/OrderIssueService.php

@@ -520,6 +520,10 @@ class OrderIssueService
     public function updateSecondLogisticNumber($id, $logisticNumber)
     {
         $orderIssue = OrderIssue::query()->where('id', $id)->first();
+        if(!$orderIssue->second_client_no){
+            $orderIssue->update(['second_logistic_number'=>$logisticNumber]);
+            return ['success' => true,'second_logistic_number' => $logisticNumber];
+        }
         $order = app(OrderService::class)->getOrderByLogisticNumber($logisticNumber);
         if (!$order) {
             $orderIssue->update(['second_logistic_number' => $logisticNumber]);

+ 12 - 7
app/Services/OrderService.php

@@ -323,6 +323,7 @@ class OrderService
         $commodities=[];
         $orderNos = "(''";
         $picktotraceids=[];
+        $count = 1;
         /*
          * 第二种扁平化方式(节省空间): 使用快慢指针,因拿到数据正常为顺序数据,自下标1开始与上一条对比orderno唯一标识,不同则更新慢指针下标,
          *  相同则为指定下标map类型数组追加一个键值对属性来记录同类数量,如N条,每次追加属性时先看属性是否存在,存在+1
@@ -330,10 +331,12 @@ class OrderService
         foreach ($orders as $index=>$order){
             $key = $order->orderno;
             if (isset($commodities[$key])){
-                if (!isset($signs[$order->orderlineno]))
+                if (!isset($signs[$order->orderlineno])){
+                    $signs[$order->orderlineno] = true;
                     array_push($commodities[$key],
                         ["sku"=>$order->sku,"alternate_sku1"=>$order->alternate_sku1,"descr_c"=>$order->descr_c,"qtyordered"=>$order->qtyordered
                             ,"lotnum"=>$order->lotnum,"checktime"=>$order->checktime,"orderdetailcodename"=>$order->orderdetailcodename]);
+                }
                 unset($orders[$index]);
                 continue;
             }
@@ -342,12 +345,14 @@ class OrderService
             $commodities[$key]=[["sku"=>$order->sku,"alternate_sku1"=>$order->alternate_sku1,
                 "descr_c"=>$order->descr_c,"qtyordered"=>$order->qtyordered,"lotnum"=>$order->lotnum,"checktime"=>$order->checktime,"orderdetailcodename"=>$order->orderdetailcodename]];
             $orderNos .= ",'".$order->orderno."'";
-        }
-        $orderNos .= ")";
-        $allocations = DB::connection("oracle")->select(DB::raw("SELECT DROPID,ORDERNO FROM ACT_ALLOCATION_DETAILS WHERE orderno IN ".$orderNos." GROUP BY (DROPID,ORDERNO)"));
-        foreach ($allocations as $allocation){
-            if (isset($picktotraceids[$allocation->orderno])) $picktotraceids[$allocation->orderno][] = $allocation->dropid;
-            else $picktotraceids[$allocation->orderno] = [$allocation->dropid];
+            if ($count % 500 == 0 || $index == count($orders)-1){
+                $orderNos .= ")";
+                $allocations = DB::connection("oracle")->select(DB::raw("SELECT DROPID,ORDERNO FROM ACT_ALLOCATION_DETAILS WHERE orderno IN ".$orderNos." GROUP BY (DROPID,ORDERNO)"));
+                foreach ($allocations as $allocation){
+                    if (isset($picktotraceids[$allocation->orderno])) $picktotraceids[$allocation->orderno][] = $allocation->dropid;
+                    else $picktotraceids[$allocation->orderno] = [$allocation->dropid];
+                }
+            }
         }
         $picktotraceids=json_encode($picktotraceids);
         $orders=array_values($orders);

+ 32 - 1
app/Services/OwnerService.php

@@ -235,7 +235,11 @@ Class OwnerService
             if($owner) return $owner;
              $basCustomer = app('OracleBasCustomerService')->first(['Customer_Type'=>'OW','CustomerID'=>$code]);
             if(!$basCustomer)return null;
-            return Owner::query()->create(['name'=>$basCustomer['descr_c'],'code'=>$basCustomer['customerid']]);
+            if($basCustomer && $basCustomer['active_flag']=='Y') return Owner::query()
+                ->create(['name'=>$basCustomer['descr_c'],'code'=>$basCustomer['customerid']]);
+            $deleted_at=Carbon::now()->toDateTimeString();
+            if($basCustomer && $basCustomer['active_flag']=='N') return Owner::query()
+                ->create(['name'=>$basCustomer['descr_c'],'code'=>$basCustomer['customerid'],'deleted_at'=>$deleted_at]);
         });
     }
     public function codeGetOwner($code)
@@ -275,4 +279,31 @@ sql
         }
         return true;
     }
+
+
+    public function syncUpdate($owner)
+    {
+        if (is_array($owner)){
+            $owner = new Owner();
+            foreach ($owner as $column=>$value){
+                $owner[$column] = $value;
+            }
+        }
+        if (is_numeric($owner)){
+            $owner = Owner::query()->find($owner);
+            if (!$owner)return false;
+        }
+        $sql = DB::raw(<<<sql
+    update BAS_CUSTOMER set ACTIVE_FLAG = ?,EDITTIME = TO_DATE(?,'yyyy-mm-dd hh24:mi:ss'),EDITWHO = ? where CUSTOMERID = ? and CUSTOMER_TYPE = ? 
+sql
+        );
+        $date = date('Y-m-d H:i:s');
+        if ($owner && $owner->deleted_at){
+            DB::connection("oracle")->update($sql,['N',$date,'WAS-'.(Auth::user() ? Auth::user()['name'] : 'SYSTEM'),$owner->code,'OW']);
+        }
+       if ($owner && $owner->deleted_at==null) {
+            DB::connection("oracle")->update($sql,['Y',$date,'WAS-'.(Auth::user() ? Auth::user()['name'] : 'SYSTEM'),$owner->code,'OW']);
+        }
+        return true;
+    }
 }

+ 3 - 4
app/Services/RejectedBillService.php

@@ -122,10 +122,9 @@ Class RejectedBillService
     {
         $updateCollect = collect();
         foreach ($asnHerders as $asnHerder) {
-            if (($asnHerder->asnType->codename_c == '退货入库'
-                    || $asnHerder->asnType->codename_c == '其他入库')
-                && ($asnHerder->asnStatus->codename_c == '已入库'
-                    ||$asnHerder->asnStatus->codename_c == 'ASN关闭')) {
+            if ($asnHerder->asnType && $asnHerder->asnStatus &&
+                ($asnHerder->asnType->codename_c == '退货入库' || $asnHerder->asnType->codename_c == '其他入库')
+                && ($asnHerder->asnStatus->codename_c == '完全收货' ||$asnHerder->asnStatus->codename_c == 'ASN关闭')) {
                 $updateCollect->add($asnHerder);
             }
         }

+ 6 - 5
app/Services/StoreService.php

@@ -51,7 +51,7 @@ Class StoreService
         $oracleDocAsnHerderService = app(OracleDocAsnHerderService::class);
         $last_time = $this->getAsnLastSyncAt($created_at, 'create');
         $asnHerders = $oracleDocAsnHerderService->getWmsAsnOnStartDateCreate($last_time);
-        if (!$asnHerders) return;
+        if (count($asnHerders)<1) return;
         $last_time = $asnHerders->first()['addtime'];
         $last_records = $asnHerders->where('addtime', $last_time);
         $this->createStore($asnHerders);
@@ -71,7 +71,7 @@ Class StoreService
         $oracleDocAsnHerderService = app(OracleDocAsnHerderService::class);
         $last_time = $this->getAsnLastSyncAt($updated_at, 'update');
         $asnHerders = $oracleDocAsnHerderService->getWmsAsnOnStartDateEdit($last_time);
-        if (!$asnHerders) return;
+        if (count($asnHerders)<1) return;
         $last_time = $asnHerders->first()['edittime'];
         $last_records = $asnHerders->where('edittime', $last_time);
         $this->createStore($asnHerders);
@@ -196,9 +196,10 @@ Class StoreService
             if ($store->asn_code != $asnHerder->asnno ||
                 $store->warehouse_id != $warehouse_id ||
                 $store->owner_id != $owner_id ||
-                $store->stored_method != $asnHerder->asnType->codename_c ||
-                $store->status != $asnHerder->asnStatus->codename_c ||
-                $store->remark != $asnHerder->notes) {
+                $store->stored_method != ($asnHerder->asnType->codename_c ??'')||
+                $store->status != ($asnHerder->asnStatus->codename_c ?? '')||
+                $store->remark != $asnHerder->notes ||
+                $store->updated_at != $asnHerder->edittime) {
                 $updateParams[] = [
                     'id' => $store->id,
                     'asn_code' => $asnHerder->asnno,

+ 4 - 1
app/StoreItems.php

@@ -14,7 +14,7 @@ class StoreItems extends Model
     use ModelTimeFormat;
     protected $fillable=[
         'store_id','asn_line_code','name',
-        'sku','barcode','depository_id','amount','quality','status',
+        'sku','barcode','depository_id','amount','quality','status','commodity_id'
     ];
     protected $appends=[
         'store_asn_code',
@@ -27,6 +27,9 @@ class StoreItems extends Model
     public function store(){
         return $this->belongsTo('App\Store','store_id','id');
     }
+    public function commodity(){
+        return $this->hasOne('App\Commodity','id','commodity_id');
+    }
 
 
     public function getStoreASNCodeAttribute()

+ 3 - 0
app/Waybill.php

@@ -66,6 +66,9 @@ class Waybill extends Model
     public function uploadFile(){
         return $this->hasOne('App\UploadFile','table_id','id')->where('table_name','waybills');
     }
+//    public function getOrderingRemarkAttribute($val){
+//        return
+//    }
 
 
     static public function setWeightByOrderCode($orderCode,$weight){

+ 3 - 0
resources/js/queryForm/queryForm.js

@@ -32,6 +32,7 @@ const query = function getQueryForm(data) {
             let form = $("<form method='" + _this.method +"'></form>");
             for (const key in _data) {
                 let map = _data[key];
+                if(map['required'] == true && (map.value === '' || map.value===null || map.value === undefined))return;
                 if (["string", "number"].includes(fetchJsType(map.value)) && map.value !== '') {
                     // if(map.value){
                     //     let string = new String(map.value);
@@ -1146,6 +1147,7 @@ const query = function getQueryForm(data) {
                         data:condition.data,
                         killings:condition.killings,
                         rules:condition.rules,
+                        required:condition.required,
                     }
                     if (condition.type === 'search_select') {
                         data.mold = 'select';
@@ -1171,6 +1173,7 @@ const query = function getQueryForm(data) {
                             mold: ['input', 'dateTime'].includes(types[index]) ? 'input' : types[index],
                             killings:condition.killings,
                             rules:condition.rules,
+                            required:condition.required,
                         }
                         if(condition.killings&&Array.isArray(condition.killings)){
                             data.killings=condition.killings[index];

+ 27 - 1
resources/sass/text.scss

@@ -65,7 +65,33 @@
     overflow: hidden;
     white-space: nowrap;
     text-overflow: ellipsis;
-    pointer-events: none
+    pointer-events: none;
+}
+.text-overflow-replace-100{
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    pointer-events: none;
+    max-width: 100px;
+}
+.text-overflow-replace-200{
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    pointer-events: none;
+    max-width: 200px;
+}
+//文本溢出换行展示
+.text-overflow-warp{
+    white-space: normal;
+}
+.text-overflow-warp-100{
+    max-width: 100px;
+    white-space: normal;
+}
+.text-overflow-warp-200{
+    max-width: 200px;
+    white-space: normal;
 }
 //输入框font标签图
 .form-font{

+ 13 - 32
resources/views/customer/customer/_customerLog.blade.php

@@ -1,43 +1,24 @@
 <div class="modal fade" tabindex="-1" role="dialog" id="modal">
-    <div class="modal-dialog modal-xl modal-dialog-centered modal-dialog-scrollable">
+    <div class="modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable">
         <div class="modal-content">
             <div class="modal-header">
-                <button type="button" class="btn btn-outline-info pull-left" @click="addLog()">新增</button>
+                <h4 class="modal-title text-primary">新增日志信息</h4>
                 <button type="button" class="close" data-dismiss="modal">&times;</button>
             </div>
             <div class="modal-body">
-                <table class="table table-sm table-hover table-striped" v-if="index !== ''">
-                    <tr>
-                        <th>状态</th>
-                        <th>操作者</th>
-                        <th>说明</th>
-                        <th>操作时间</th>
-                    </tr>
-                    <tr v-for="(log,i) in customerLogs[customers[index]['id']]">
-                        <td>
-                            <select id="logStatusName" v-if="!log.id" class="form-control form-control-sm" :id="'logStatus-'+log.id">
-                                <option v-for="logStatus in logStatuses" :value="logStatus.id">@{{ logStatus.name }}</option>
-                            </select>
-                            <label v-else for="logStatusName">
-                                @{{ log.status.name }}
-                            </label>
-                        </td>
-                        <td>@{{ log.user.name }}</td>
-                        <td style="max-width: 100px" class="cursor-pointer" @mouseenter="textClass($event,true)" @mouseleave="textClass($event,false)">
-                            <div class="text-overflow-replace" v-if="currentLogIndex !== i" @click="edit(i,log.user)">
-                                @{{ log.description }}
-                            </div>
-                            <div v-if="currentLogIndex === i && i===0">
-                                <textarea class="form-control form-control-sm" v-text="log.description" :id="'description-'+log.id"></textarea>
-                            </div>
-                        </td>
-                        <td>@{{ log.created_at }}</td>
-                    </tr>
-                </table>
+                <div class="row">
+                    <label for="status" class="col-3">客户状态</label>
+                    <select id="status" class="form-control form-control-sm col-5">
+                        <option v-for="status in logStatuses" :value="status.id">@{{ status.name }}</option>
+                    </select>
+                </div>
+                <div class="row mt-2">
+                    <label for="description" class="col-3">说明</label>
+                    <textarea id="description" class="form-control form-control-sm col-7"></textarea>
+                </div>
             </div>
             <div class="modal-footer">
-                <button type="button" class="btn btn-success" v-if="currentLogIndex !== ''" @click="editLog()">保存</button>
-                <button type="button" class="btn btn-danger" v-if="currentLogIndex !== ''" @click="closeEditLog()">取消</button>
+                <button type="button" class="btn btn-success" @click="addLog()">提交</button>
                 <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
             </div>
         </div>

+ 106 - 76
resources/views/customer/customer/index.blade.php

@@ -25,7 +25,18 @@
                     <th>联系人</th>
                     <th>联系电话</th>
                     <th>公司备注</th>
-                    <th>日志</th>
+                    <th class="text-center" style="min-width: 700px">
+                        <div class="row">
+                            <label class="col-12">日志</label>
+                        </div>
+                        <div class="row text-secondary">
+                            <label class="col-2">状态</label>
+                            <label class="col-2">操作者</label>
+                            <label class="col-4">说明</label>
+                            <label class="col-3">操作时间</label>
+                            <label class="col-1"></label>
+                        </div>
+                    </th>
                     <th>合同</th>
                     <th>创建时间</th>
                     <th>标签</th>
@@ -40,7 +51,35 @@
                     <td>@{{ customer.contact_man }}</td>
                     <td>@{{ customer.phone }}</td>
                     <td>@{{ customer.remark }}</td>
-                    <td><span class="cursor-pointer" @click="showCustomerLog(customer.id,i)">查看</span></td>
+                    <td>
+                        <div class="row text-center mb-0" v-if="customer.customer_logs.length > 0">
+                            <div class="col-2">@{{ customer.customer_logs[0].status ? customer.customer_logs[0].status.name : '' }}</div>
+                            <div class="col-2">@{{ customer.customer_logs[0].user ? customer.customer_logs[0].user.name : '' }}</div>
+                            <label v-if="editCustomer == customer.id">
+                                <textarea @blur="editLog(i,$event)" class="form-control form-control-sm">@{{ customer.customer_logs[0].description }}</textarea>
+                            </label>
+                            <div v-if="editCustomer != customer.id" @click="edit(i,customer.customer_logs[0].user)" @mouseenter="textClass($event,true)" @mouseleave="textClass($event,false)" class="col-4">
+                                <div class="text-overflow-replace cursor-pointer">@{{ customer.customer_logs[0].description }}</div>
+                            </div>
+                            <div class="col-3">@{{ customer.customer_logs[0].created_at }}</div>
+                            @can("客户-编辑")<div class="col-1 font-weight-bold text-danger h4 cursor-pointer" @click="delLog(i,0)">&times;</div>@endcan
+                        </div>
+                        <div class="w-100 up" :id="'log-'+customer.id">
+                            <div class="text-center mb-0 row" v-for="(log,j) in customer.customer_logs" v-if="j!==0">
+                                <div class="col-2">@{{ log.status ? log.status.name : '' }}</div>
+                                <div class="col-2">@{{ log.user ? log.user.name : '' }}</div>
+                                <div @mouseenter="textClass($event,true)" @mouseleave="textClass($event,false)" class="col-4"><div class="text-overflow-replace cursor-pointer">@{{ log.description }}</div></div>
+                                <div class="col-3">@{{ log.created_at }}</div>
+                                @can("客户-编辑")<div class="col-1 font-weight-bold text-danger h4 cursor-pointer" @click="delLog(i,j)">&times;</div>@endcan
+                            </div>
+                        </div>
+                        <div class="row" @click="showLog(i)">
+                            <label class="text-center mt-0 p-0 cursor-pointer offset-5">
+                                <span class="fa" :class="customer.isShowLog ? 'fa-angle-double-down' : 'fa-angle-double-right'"></span>
+                                &nbsp;<span v-if="customer.isShowLog">收起</span><span v-if="!customer.isShowLog">展开</span>&nbsp;@{{ customer.customer_logs.length }} 条日志
+                            </label>
+                        </div>
+                    </td>
                     <td v-if="customer.contractQuantity>0" class="cursor-pointer" @click="showContract(customer.id)"><span class="fa" :class="contractIds['_'+customer.id] === true ? 'fa-angle-double-down' : 'fa-angle-double-right'"></span>@{{ customer.contractQuantity }}份合同</td>
                     <td v-else>#</td>
                     <td>@{{ customer.created_at }}</td>
@@ -60,6 +99,7 @@
                     </td>
                     <td>
                         @can("客户-编辑")
+                            <button class="btn btn-sm btn-outline-info" @click="showCustomerLog(i)">新建日志</button>
                             <button class="btn btn-sm btn-outline-success" @click="addContract(i)">新建合同</button>
                             <button v-if="!tagIndexes[i]" class="btn btn-sm btn-info text-white" @click="setTag(i)">设定标签</button>
                             <button class="btn btn-sm btn-outline-primary" @click="relatedOwner(i)">关联项目</button>
@@ -82,8 +122,7 @@
                 customers :  {!!  $customers->toJson() !!}['data'],
                 customerLogs : [],
                 index:'',
-                currentLogIndex:"",
-                logStatuses:[],
+                logStatuses:null,
                 contractIds:[],
                 customerOwners:[],
                 files:[],
@@ -100,10 +139,14 @@
                     {name:"{{$tag->id}}",value:"{{$tag->name}}"},
                     @endforeach
                 ],
+                editCustomer:"",
+                addCustomerLogIndex:"",
             },
             mounted(){
                 this._formatOwner();
+                $(".up").slideUp();
                 $('#container').removeClass('d-none');
+                console.log(this.customers[0].customer_logs);
                 this.rendering();
                 let data=[
                     [
@@ -120,6 +163,46 @@
                 }).init();
             },
             methods:{
+                textClass(event,isOver){
+                    event = event.target.children[0];
+                    if (isOver) event.className = "text-overflow-warp";
+                    else event.className = "cursor-pointer text-overflow-replace";
+                },
+                editLog(customer_index,event){
+                    let description = event.target.value;
+                    if (description ===this.customers[customer_index].customer_logs[0].description){
+                        this.editCustomer = "";
+                        return;
+                    }
+                    let url="{{url('customer/customer/editLog')}}";
+                    let params = {id:this.customers[customer_index].customer_logs[0].id,description:description};
+                    window.tempTip.confirm("确定要提交该条日志的修改信息吗?",()=>{
+                        window.tempTip.postBasicRequest(url,params,(res)=> {
+                            this.customers[customer_index].customer_logs[0].description = description;
+                            this.$forceUpdate();
+                            return "修改说明成功!";
+                        });
+                    });
+                },
+                showLog(index){
+                    if(this.customers[index].isShowLog){
+                        this.customers[index].isShowLog = false;
+                        $("#log-"+this.customers[index].id).slideUp();
+                    } else{
+                        this.customers[index].isShowLog = true;
+                        $("#log-"+this.customers[index].id).slideDown();
+                    }
+                    this.$forceUpdate();
+                },
+                delLog(customer_index,log_index){
+                    let id = this.customers[customer_index].customer_logs[log_index].id;
+                    window.tempTip.confirm("确定要删除该条日志吗?",()=>{
+                        window.tempTip.postBasicRequest("{{url('customer/customer/destroyLog')}}",{id:id},res=>{
+                            this.$delete(this.customers[customer_index].customer_logs,log_index);
+                            return "已成功删除该条日志记录";
+                        });
+                    })
+                },
                 addTag(index){
                     let val = $("#sel-"+index).selectpicker('val');
                     let url = "{{url('customer/customer/addTag')}}";
@@ -144,14 +227,7 @@
                         });
                     }
                     this.$forceUpdate();
-                    /*if (this.tags.length<1){
-                        window.tempTip.postBasicRequest("{{--{{url('customer/customer/customerTag/get')}}--}}",{},(res)=>{
-                            this.tags = res;
-                        });
-                    }*/
-                    //setTimeout(()=>{
-                        $(".selectpicker").selectpicker('refresh').selectpicker('val',defaults);
-                    //},500);
+                    $(".selectpicker").selectpicker('refresh').selectpicker('val',defaults);
                 },
                 _formatOwner(){
                     let ownerIds=[];
@@ -227,77 +303,31 @@
                         })
                     })
                 },
-                showCustomerLog(id,index){
-                    this.index = index;
-                    if (this.customerLogs[id]){
-                        $("#modal").modal('show');
-                        return;
-                    }
-                    let url="{{url('customer/customer/getLog')}}";
-                    let params = {customer_id:id};
-                    window.tempTip.postBasicRequest(url,params,(res)=> {
-                        this.customerLogs[id] = res;
-                        this.$forceUpdate();
-                        $("#modal").modal('show');
-                    });
-                },
-                textClass(event,isOver){
-                    event = event.target.children[0];
-                    if (isOver){event.classList.remove("text-overflow-replace");}
-                    else {event.classList.add("text-overflow-replace");}
+                showCustomerLog(index){
+                    if (!this.logStatuses)window.tempTip.postBasicRequest("{{url('customer/customer/getLogStatus')}}",{},(res)=>{
+                        this.logStatuses = res;
+                    },true);
+                    this.addCustomerLogIndex = index;
+                    $("#modal").modal('show');
                 },
                 edit(index,user){
+                    if (!user)return;
                     let id = "{{\Illuminate\Support\Facades\Auth::id()}}";
                     if (id != user.id) return;
-                    if (index === 0)this.currentLogIndex=index;
-                    else this.currentLogIndex='';
-                },
-                closeEditLog(){
-                    this.currentLogIndex = '';
-                    if (this.customerLogs[this.customers[this.index]['id']][0].id === ''){
-                        this.$delete(this.customerLogs[this.customers[this.index]['id']],0);
-                    }
-                },
-                editLog(){
-                    let log = this.customerLogs[this.customers[this.index]['id']][this.currentLogIndex];
-                    if (log.id === ''){
-                        let description = $("#description-"+log.id)[0].value;
-                        let logStatus = $("#logStatus-"+log.id)[0].value;
-                        let url="{{url('customer/customer/storeLog')}}";
-                        let params = {customer_id:this.customers[this.index]['id'],description:description,customer_log_status_id:logStatus};
-                        window.tempTip.postBasicRequest(url,params,(res)=>{
-                            this.customerLogs[this.customers[this.index]['id']][0] = res;
-                            this.currentLogIndex = '';
-                            this.$forceUpdate();
-                            return "成功创建客户日志";
-                        },true);
-                        return;
-                    }
-                    let url="{{url('customer/customer/editLog')}}";
-                    let description = $("#description-"+log.id)[0].value;
-                    let params = {id:log.id,description:description};
-                    window.tempTip.postBasicRequest(url,params,(res)=> {
-                        this.customerLogs[this.customers[this.index]['id']][this.currentLogIndex].description = description;
-                        this.currentLogIndex = '';
-                        this.$forceUpdate();
-                        return "修改说明成功!";
-                    },true);
+                    this.editCustomer = this.customers[index].id;
                 },
                 addLog(){
-                    if (this.logStatuses.length < 1)window.tempTip.postBasicRequest("{{url('customer/customer/getLogStatus')}}",{},(res)=>{
-                        this.logStatuses = res;
+                    let description = $("#description")[0].value;
+                    let logStatus = $("#status")[0].value;
+                    let url="{{url('customer/customer/storeLog')}}";
+                    let params = {customer_id:this.customers[this.addCustomerLogIndex].id,description:description,customer_log_status_id:logStatus};
+                    window.tempTip.postBasicRequest(url,params,(res)=>{
+                        this.customers[this.addCustomerLogIndex].customer_logs.unshift(res);
+                        console.log(this.customers[this.addCustomerLogIndex].customer_logs);
+                        this.$forceUpdate();
+                        $("#modal").modal('hide');
+                        return "成功创建客户日志";
                     },true);
-                    let logs = this.customerLogs[this.customers[this.index]['id']];
-                    if (logs.length > 0 && logs[0].id === "")return;
-                    logs.unshift({
-                        id:"",
-                        status:{name:""},
-                        user:{name:"{{\Illuminate\Support\Facades\Auth::user()->name}}"},
-                        description:"",
-                        created_at:"",
-                    });
-                    this.currentLogIndex = 0;
-                    this.$forceUpdate();
                 },
                 showContract(id){
                     if (this.contractIds['_'+id] &&  this.contractIds['_'+id]===true){

+ 0 - 55
resources/views/customer/project/_three.blade.php

@@ -1,55 +0,0 @@
-<div class="row">
-    <div class="col-6">
-        <div class="card">
-            <div class="card-header bg-light-info">
-                <span class="pull-left font-weight-bold cursor-pointer" @click="show('storage')"><span class="fa fa-cubes"></span>&nbsp;仓储</span>
-            </div>
-            <div class="card-body" id="storage">
-                <table class="table table-sm">
-                    <tr>
-                        <th>计费类型</th>
-                        <th>用仓类型</th>
-                        <th>起租面积</th>
-                        <th>单价</th>
-                        <th>单位</th>
-                        <th>减免类型</th>
-                        <th>减免值</th>
-                    </tr>
-                    <tr v-for="item in selectedModel.storage">
-                        <td>@{{ item.counting_type }}</td>
-                        <td>@{{ item.using_type }}</td>
-                        <td>@{{ item.minimum_area }}</td>
-                        <td>@{{ item.price }}</td>
-                        <td>@{{ item.discount_type }}</td>
-                        <td>@{{ item.discount_value }}</td>
-                        <td>@{{ poolMapping.units[item.unit_id] }}</td>
-                    </tr>
-                </table>
-            </div>
-        </div>
-    </div>
-    <div class="col-6">
-        <div class="card">
-            <div class="card-header bg-light-info">
-                <button type="button" class="btn mr-1" :class="type == 'storage' ? 'btn-primary text-white' : 'btn-outline-primary'" @click="switchType('storage')">仓储</button>
-                <button type="button" class="btn mr-1" :class="type == 'operation' ? 'btn-primary text-white' : 'btn-outline-primary'" @click="switchType('operation')">作业</button>
-                <button type="button" class="btn mr-1" :class="type == 'express' ? 'btn-primary text-white' : 'btn-outline-primary'" @click="switchType('express')">快递</button>
-                <button type="button" class="btn mr-1" :class="type == 'logistic' ? 'btn-primary text-white' : 'btn-outline-primary'" @click="switchType('logistic')">物流</button>
-                <button type="button" class="btn mr-1" :class="type == 'directLogistic' ? 'btn-primary text-white' : 'btn-outline-primary'" @click="switchType('directLogistic')">直发</button>
-            </div>
-            <div class="card-body">
-                <div v-if="type == 'storage'">
-                    @include("customer.project._storage")
-                </div>
-                <div v-show="type == 'operation'">
-                    @include("customer.project._operation")
-                    @include("customer.project._addFeature")
-                </div>
-                <div class="row mt-3" v-if="base=='three'">
-                    <div class="col-3"></div>
-                    <button type="button" class="btn btn-success ml-1 col-6" @click="saveModel()">保存</button>
-                </div>
-            </div>
-        </div>
-    </div>
-</div>

+ 398 - 42
resources/views/customer/project/create.blade.php

@@ -56,13 +56,13 @@
             <form method="POST" action="{{url('customer/project/store')}}" class="mt-5">
                 @csrf
                 <div v-if="base == 'one'">
-                    @include("customer.project._one")
+                    @include("customer.project.part._one")
                 </div>
                 <div v-if="base == 'two'">
-                    @include("customer.project._two")
+                    @include("customer.project.part._two")
                 </div>
                 <div v-if="base == 'three'">
-                    @include("customer.project._three")
+                    @include("customer.project.part._three")
                 </div>
                 <div class="row mt-3">
                     <div class="pull-right offset-7">
@@ -82,7 +82,7 @@
         new Vue({
             el:"#container",
             data:{
-                base:"one",
+                base:"three",
                 owner : {
                     id:"{{old('id') ?? ($owner->id ?? '') }}",
                     name : "{{old('name') ?? ($owner->name ?? '')}}",
@@ -140,6 +140,10 @@
                     storage : false,
                 },
                 type:"storage",//当前编辑类型 仓储,作业,物流...
+
+                currentInputting:{
+                    edittingOperation:null,
+                },
                 model:{ //编辑元素绑定值
                     storage:{
                         counting_type : "",
@@ -161,6 +165,17 @@
                             {strategy:"特征"},
                         ],
                     },
+                    express:{
+                        name:"",
+                        initial_weight:"",
+                        additional_weight:"",
+                        items:[],
+                    },
+                    logistic:{
+                        items:[],
+                        other_ranges:[],
+                        ranges:[],
+                    },
                 },
                 pool:{//基础数据选择池,以方便异步懒加载而非即时加载 例:units,owners等
                     counting_type:[
@@ -172,17 +187,25 @@
                     discount_type:[
                         "无减免","按单减免","固定减免"
                     ],
+                    feature_type:['商品名称','订单类型','承运商','店铺类型'],
+                    logic : ['包含','不包含','等于'],
                 },
                 poolMapping:{//基础数据选择池的映射对象 供展示使用
 
                 },
                 selectedModel:{//已选定的计费模型
                     storage:[],
+                    operation:[],
+                    express:{},
+                    logistic:{},
                 },
                 thisOperationItemIndex:-1,//当前选中的作业费子项下标,用以唤起特征模态框
-                oldFeature:"",//上一个特征,如果与当前特征一致则无需再次转换特征
+                operationItems:{},//控制作业费子项的渐入展开
+                importError:[],//导入时的错误数据原因
+                isShowError:false,//是否展开导入错误信息
             },
             mounted(){
+                $('[data-toggle="tooltip"]').tooltip();
                 if (this.errors.length===0 && this.owner.id){
                     this.display = true;
                 }
@@ -210,6 +233,13 @@
                         case "operation":
                             this._loadOperation();
                             break;
+                        case "express":
+                            this._loadExpress();
+                            break;
+                        case "logistic":
+                            this._loadLogistic();
+                            $("#parent").append($("#logistic-card"));
+                            break;
                     }
                     this.type = type;
                 },
@@ -251,12 +281,6 @@
                         this.errors["owner_group_id"] = ["必须选择项目小组"];
                         this.$forceUpdate();
                     }
-/*                    this._requestRequest({
-                        customer_id:this.owner.customer_id,
-                        owner_group_id:this.owner.owner_group_id,
-                        tax_rate:this.owner.tax_rate,
-                        waring_line_on:this.owner.waring_line_on,
-                    },"three")*/
                 },
                 //上一步
                 back(){
@@ -290,6 +314,16 @@
                 _loadOperation(){
                     if (!this.pool.units)this._getUnits();
                 },
+                //加载快递
+                _loadExpress(){
+                    if (!this.pool.provinces)this._getProvinces();
+                },
+                //加载物流
+                _loadLogistic(){
+                    if (!this.pool.units) this._getUnits();
+                    if (!this.pool.provinces)this._getProvinces();
+                    if (!this.pool.cities)this._getCities();
+                },
                 //获取单位
                 _getUnits(){
                     let url = "{{url('maintenance/unit/getUnits')}}";
@@ -303,12 +337,44 @@
                         this.$forceUpdate();
                     });
                 },
+                //获取省份
+                _getProvinces(){
+                    let url = "{{url('maintenance/province/get')}}";
+                    window.tempTip.postBasicRequest(url,{},res=>{
+                        this.pool.provinces = res;
+                        let mapping = [];
+                        res.forEach(province=>{
+                            mapping[province.id] = province.name;
+                        });
+                        this.poolMapping.provinces = mapping;
+                        this.$forceUpdate();
+                    });
+                },
+                //获取城市
+                _getCities(){
+                    let url = "{{url('maintenance/city/get')}}";
+                    window.tempTip.postBasicRequest(url,{},res=>{
+                        this.pool.cities = res;
+                        let mapping = [];
+                        res.forEach(city=>{
+                            mapping[city.id] = city.name;
+                        });
+                        this.poolMapping.cities = mapping;
+                        this.$forceUpdate();
+                    });
+                },
                 //保存模型
                 saveModel(){
                     switch (this.type) {
                         case "storage":
                             this._verifyStorage();
                             break;
+                        case "operation":
+                            this._verifyOperation();
+                            break;
+                        case "express":
+                            this._verifyExpress();
+                            break;
                     }
                 },
                 _verifyStorage(){
@@ -344,6 +410,89 @@
                     };
                     this.errors = [];
                 },
+                _verifyOperation() {
+                    if (this.selectedModel.operation.length>0){
+                        this.selectedModel.operation.forEach(operation=>{
+                            if (operation.operation_type === this.model.operation.operation_type && operation.strategy === this.model.operation.strategy){
+                                this.errors["operation_type"] = ["已存在同类型的"+operation.operation_type+"作业计费模型"];
+                                this.$forceUpdate();
+                                return;
+                            }
+                        });
+                    }
+                    if (!this.model.operation.name){
+                        this.errors["name"] = ["名称不得为空"];
+                        this.$forceUpdate();
+                        return;
+                    }
+                    if ((this.model.operation.operation_type === '出库' && this._verifyOperationItem(0)) || this._verifyOperationItem(1))return;
+                    if (this.model.operation.items.length>2){
+                        for (let i=2;i<this.model.operation.items.length;i++){
+                            if (this._verifyOperationItem(i))return;
+                        }
+                    }
+                    if (this.model.operation.operation_type === '入库')this.$delete(this.model.operation.items,0);//入库时干掉起步子项
+                    this.selectedModel.operation.push(this.model.operation);
+                    setTimeout(()=>{
+                        this._renderingOperationItem(this.selectedModel.operation.length-1);
+                    },100);
+                    this.model.operation = {
+                        operation_type:"入库",
+                        strategy:"默认",
+                        name:"",
+                        feature:"",
+                        items : [
+                            {strategy:"起步"},
+                            {strategy:"默认"},
+                            {strategy:"特征"},
+                        ],
+                    };
+                    this.errors = [];
+                },
+                _verifyOperationItem(itemIndex){//验证作业费子项信息完整
+                    let obj = this.model.operation.items[itemIndex];
+                    let sign = false;
+                    if (!obj.amount){
+                        this.errors['items.'+itemIndex+'.amount'] = ["数量不得为空"];
+                        sign = true;
+                    }
+                    if (!obj.unit_id){
+                        this.errors['items.'+itemIndex+'.unit_id'] = ["必须选择单位"];
+                        sign = true;
+                    }
+                    if (!obj.unit_price){
+                        this.errors['items.'+itemIndex+'.unit_price'] = ["单价不得为空"];
+                    }
+                    if (sign)this.$forceUpdate();
+                    return sign;
+                },
+                _verifyExpress(){
+                    let error = {};
+                    if (!this.model.express.name)error.name = ["名称不得为空"];
+                    if (!this.model.express.initial_weight)error.initial_weight = ["首重不得为空"];
+                    if (!this.model.express.additional_weight)error.additional_weight = ["续重不得为空"];
+                    if (this.model.express.items.length>0){
+                        this.model.express.items.forEach((item,index)=>{
+                            if (!item.province_id)error["item."+index+".province_id"] = ["不存在"];
+                            if (!item.initial_weight_price)error["item."+index+".initial_weight_price"] = ["不存在"];
+                            if (!item.additional_weight_price)error["item."+index+".additional_weight_price"] = ["不存在"];
+                        });
+                    }
+                    if (JSON.stringify(error) !== "{}"){
+                        this.errors = error;
+                        this.$forceUpdate();
+                        return;
+                    }
+                    this.selectedModel.express = this.model.express;
+                    this.model.express = {
+                        name:"",
+                        initial_weight:"",
+                        additional_weight:"",
+                        items:[],
+                    };
+                    this.errors = [];
+                    this.importError = [];
+                },
                 //增加作业费特征子项
                 addOperationItem(){
                     this.model.operation.items.push({
@@ -355,45 +504,252 @@
                     this.$delete(this.model.operation.items,index);
                 },
                 //显示特征选择modal
-                showAddFeatureModal(index,feature){
-                    if (!feature){
-                        this.model.operation.items[index].features = [{
-                            "strategyGroupStartSign": false,
-                            "calculation" : "",
-                            "type" : "",
-                            "id" : "",
-                            "logic" : "",
-                            "describe" : "",
-                            "strategyGroupEndSign" : false,
-                        }];
-                        this.thisOperationItemIndex = index;
-                        $("#addFeatureModal").modal("show");
-                        return;
-                    }
-                    if (this.oldFeature === feature) {
-                        this.thisOperationItemIndex = index;
-                        $("#addFeatureModal").modal("show");
-                        return;
+                showAddFeatureModal(index){
+                    if (index === -1){
+                        if (!this.model.operation.feature){
+                            this.model.operation.features = this._createFeature();
+                            this.thisOperationItemIndex = index;
+                            this.$forceUpdate();
+                            $("#addFeatureModal").modal("show");
+                            return;
+                        }
+                        if (this.model.operation.features) {
+                            this.thisOperationItemIndex = index;
+                            $("#addFeatureModal").modal("show");
+                            return;
+                        }
+                    }else{
+                        if (!this.model.operation.items[index].feature){
+                            this.model.operation.items[index].features = this._createFeature();
+                            this.thisOperationItemIndex = index;
+                            $("#addFeatureModal").modal("show");
+                            return;
+                        }
+                        if (this.model.operation.items[index].features) {
+                            this.thisOperationItemIndex = index;
+                            $("#addFeatureModal").modal("show");
+                            return;
+                        }
                     }
                     let url = "{{url('maintenance/priceModel/operation/getFeatures')}}";
+                    let feature = index===-1 ? this.model.operation.feature : this.model.operation.items[index].feature;
                     window.tempTip.postBasicRequest(url,{feature:feature},res=>{
-                        this.features = res.data.data;
-                        this.oldFeature = feature;
-                        if (!this.features || this.features.length === 0){
-                            this.features = [{
-                                "strategyGroupStartSign": false,
-                                "calculation" : "",
-                                "type" : "",
-                                "id" : "",  //特征ID
-                                "logic" : "",  //特征逻辑
-                                "describe" : "",  //特征信息
-                                "strategyGroupEndSign" : false,
-                            }];
+                        if (!res.data.data || res.data.data.length === 0){
+                            res.data.data = this._createFeature();
                         }
+                        if (index === -1) this.model.operation.features = res.data.data;
+                        else this.model.operation.items[index].features = res.data.data;
                         this.thisOperationItemIndex = index;
                         $("#addFeatureModal").modal("show");
                     });
                 },
+                //增加特征
+                addFeature(){
+                    let obj = {
+                        "strategyGroupStartSign": false,
+                        "calculation" : "",
+                        "type" : "",
+                        "id" : "",
+                        "logic" : "",
+                        "describe" : "",
+                        "strategyGroupEndSign" : false,
+                    };
+                    if (this.thisOperationItemIndex === -1)this.model.operation.features.push(obj);
+                    else this.model.operation.items[this.thisOperationItemIndex].features.push(obj);
+                    this.$forceUpdate();
+                },
+                _createFeature(){
+                    return [{
+                        "strategyGroupStartSign": false,
+                        "calculation" : "",
+                        "type" : "",
+                        "id" : "",
+                        "logic" : "",
+                        "describe" : "",
+                        "strategyGroupEndSign" : false,
+                    }];
+                },
+                //删除特征
+                delFeature(index) {
+                    if (this.thisOperationItemIndex === -1)this.$delete(this.model.operation.features,index);
+                    else this.$delete(this.model.operation.items[this.thisOperationItemIndex].features,index);
+                    this.$forceUpdate();
+                },
+                //提交特征更新现有
+                submitFeature(){
+                    let url = "{{url('maintenance/priceModel/operation/getFeature')}}";
+                    let features = this.thisOperationItemIndex === -1 ? this.model.operation.features : this.model.operation.items[this.thisOperationItemIndex].features;
+                    window.tempTip.postBasicRequest(url,{features:features,isFormat:true},res=>{
+                        if (this.thisOperationItemIndex === -1){
+                            this.model.operation.feature = res.feature;
+                            this.model.operation.featureFormat = res.featureFormat;
+                        } else {
+                            this.model.operation.items[this.thisOperationItemIndex].feature = res.feature;
+                            this.model.operation.items[this.thisOperationItemIndex].featureFormat = res.featureFormat;
+                            this.$forceUpdate();
+                        }
+                        $("#addFeatureModal").modal("hide");
+                        return "已更新特征";
+                    },true);
+                },
+                //渲染作业费子项
+                _renderingOperationItem(index){
+                    let domId = "operation-"+index;
+                    let trId = "operation-tr-"+index;
+                    let itemId = "operation-item-"+index;
+                    let html = "<tr class='d-none' id='"+trId+"'><td></td><td colspan='5'>"+
+                        "<div id='"+itemId+"'><table class='table table-sm'>"+
+                        "<th>子策略</th><th>数量</th><th>单位</th><th>单价</th><th>特征</th></th>";
+                    this.selectedModel.operation[index].items.forEach(item=> {
+                        html = this._createOperationItemList(html,item.strategy,item.amount,this.poolMapping.units[item.unit_id],item.unit_price,item.featureFormat ? item.featureFormat : '');
+                    });
+                    html += "</table></div></td></tr>";
+                    $("#"+domId).after(html);
+                    $("#"+itemId).slideUp();
+                },
+                _createOperationItemList(html,strategy,amount,unit,unit_price,feature){
+                    html += "<tr><td>"+strategy+"</td><td>"+amount+"</td><td>"+unit+"</td><td>"+unit_price+"</td><td><div class='text-overflow-warp-100'>"+feature+"</div></td></tr>";
+                    return html;
+                },
+                //移入移出时更改长文本显示效果
+                textClass(event,isOver){
+                    event = event.target.children[0];
+                    if (isOver) event.className = "text-overflow-warp-100";
+                    else event.className = "cursor-pointer text-overflow-replace-100";
+                },
+                //展开子策略
+                showOperationItem(index){
+                    let trId = "operation-tr-"+index;
+                    let itemId = "operation-item-"+index;
+                    if (this.operationItems['_'+index] &&  this.operationItems['_'+index]===true){
+                        this.operationItems['_'+index] = false;
+                        $("#"+itemId).slideUp(undefined,function () {
+                            $("#"+trId).addClass("d-none");
+                        });
+                    }else {
+                        $("#"+trId).removeClass("d-none");
+                        this.operationItems['_'+index] = true;
+                        $("#"+itemId).slideDown();
+                    }
+                    this.$forceUpdate();
+                },
+                //新增快递子项
+                addExpressItem(){
+                    this.model.express.items.unshift({
+                        province_id : "",
+                        initial_weight_price:"",
+                        additional_weight_price:"",
+                    });
+                },
+                //删除快递子项
+                delExpressItem(index){
+                    this.$delete(this.model.express.items,index);
+                },
+                //选择文件
+                selectFile(id){
+                    this.importError = [];
+                    $("#"+id).click();
+                },
+                //导入快递子项
+                importExpress(e){
+                    let file=e.target.files[0];
+                    if (!file){
+                        tempTip.setDuration(3000);
+                        tempTip.show("未选择文件");
+                        return;
+                    }
+                    let formData = new FormData();
+                    formData.append("file",file);
+                    axios.post('{{url('maintenance/priceModel/express/import')}}',formData,{
+                        'Content-Type':'multipart/form-data'
+                    }).then(res=>{
+                            if (res.data.success) {
+                                res.data.data.forEach(data=>{
+                                    let unique = this.model.express.items.every(item=>{
+                                        if (data.province_id === item.province_id)return false;
+                                        return true;
+                                    });
+                                    if (unique)this.model.express.items.push(data);
+                                });
+                                this.importError = res.data.errors;
+                                tempTip.setDuration(3000);
+                                tempTip.showSuccess("导入成功!");
+                                return;
+                            }
+                            tempTip.setDuration(3000);
+                            tempTip.show(res.data.data);
+                        }).catch(err=> {
+                        tempTip.setDuration(3000);
+                        tempTip.show("网络错误:"+err);
+                    })
+                },
+                //物流详情列表modal
+                showDetailModal() {
+                    $("#logisticModal").modal("show");
+                },
+                //新增物流详情
+                addLogisticDetail(){
+                    this.model.logistic.items.unshift({
+
+                    });
+                },
+                //导入物流详情
+                importLogistic(e){
+                    tempTip.setIndex(1099);
+                    let file=e.target.files[0];
+                    if (!file){
+                        tempTip.setDuration(3000);
+                        tempTip.show("未选择文件");
+                        return;
+                    }
+                    let formData = new FormData();
+                    formData.append("file",file);
+                    axios.post('{{url('maintenance/priceModel/logistic/import')}}',formData,{
+                        'Content-Type':'multipart/form-data'
+                    }).then(res=>{
+                        if (res.data.success) {
+                            res.data.data.forEach(data=>{
+                                //过滤非已选择单位的数据
+                                let id = "";
+                                if (data.unit_id === this.poolMapping.units[this.model.logistic.unit_id]) id = this.model.logistic.unit_id;
+                                if (data.unit_id === this.poolMapping.units[this.model.logistic.other_unit_id]) id = this.model.logistic.other_unit_id;
+                                if (id){
+                                    //过滤重复数据
+                                    let unique = this.model.logistic.items.every(item=>{
+                                        if (id === item.unit_id && data.range === item.range
+                                        && data.province_id === item.province_id && data.city_id === item.city_id)return false;
+                                        return true;
+                                    });
+                                    if (unique){
+                                        data.unit_id = id;
+                                        this.model.logistic.items.push(data);
+                                    }
+                                }
+                            });
+                            this.importError = res.data.errors;
+                            tempTip.setDuration(3000);
+                            tempTip.showSuccess("导入成功!");
+                            return;
+                        }
+                        tempTip.setDuration(3000);
+                        tempTip.show(res.data.data);
+                    }).catch(err=> {
+                        tempTip.setDuration(3000);
+                        tempTip.show("网络错误:"+err);
+                    })
+                },
+                //删除物流子项
+                delLogisticItem(index){
+                    this.$delete(this.model.logistic.items,index);
+                },
+                //改变物流区间时改变可选择项
+                changeRange(type){
+                    if (type === 'ranges'){
+                        this.model.logistic.ranges = this.model.logistic.unit_range.split(",");
+                    }else{
+                        this.model.logistic.other_ranges = this.model.logistic.other_unit_range.split(",");
+                    }
+                }
             },
         });
     </script>

+ 8 - 5
resources/views/customer/project/_addFeature.blade.php → resources/views/customer/project/part/_addFeature.blade.php

@@ -11,9 +11,11 @@
                         <label class="col-4">特征内容</label>
                         <label class="col-1"></label>
                     </div>
-                    <div class="row" v-for="(feature,i) in features">
+                    <div class="row" v-for="(feature,i) in (thisOperationItemIndex===-1 ? model.operation.features : (model.operation.items[thisOperationItemIndex] ? model.operation.items[thisOperationItemIndex].features : []))">
                         <div class="col-1">
-                            <span class="fa fa-minus-square pull-right mt-1" v-if="features.length > 1" style="cursor: pointer" @click="delFeature(i)"></span>
+                            <span class="fa fa-minus-square pull-right mt-1"
+                                  v-if="(thisOperationItemIndex===-1 ? model.operation.features : (model.operation.items[thisOperationItemIndex] ? model.operation.items[thisOperationItemIndex].features : [])).length > 1"
+                                  style="cursor: pointer" @click="delFeature(i)"></span>
                         </div>
                         <label class="col-2">
                             <select class="form-control form-control-sm" v-if="i != 0" v-model="feature.calculation">
@@ -23,19 +25,20 @@
                         </label>
                         <label class="col-2">
                             <select class="form-control form-control-sm" v-model="feature.type">
-                                <option v-for="t in type" :value="t" v-if="(thisIndex == '-1' && t != '商品名称') || (thisIndex != '-1' && t=='商品名称')">@{{ t }}</option>
+                                <option v-for="t in pool.feature_type" :value="t">@{{ t }}</option>
                             </select>
                         </label>
                         <label class="col-2">
                             <select class="form-control form-control-sm" v-model="feature.logic">
-                                <option v-for="l in logic" :value="l" v-if="thisIndex == '-1' || l != '不包含'">@{{ l }}</option>
+                                <option v-for="l in pool.logic" :value="l">@{{ l }}</option>
                             </select>
                         </label>
                         <label class="col-4">
                             <input class="form-control form-control-sm" v-model="feature.describe">
                         </label>
                         <div class="col-1">
-                            <span v-if="i == (features.length-1)" class="fa fa-plus-square pull-right mt-1" style="cursor: pointer" @click="addFeature()"></span>
+                            <span v-if="i == ((thisOperationItemIndex===-1 ? model.operation.features : (model.operation.items[thisOperationItemIndex] ? model.operation.items[thisOperationItemIndex].features : [])).length-1)"
+                                  class="fa fa-plus-square pull-right mt-1" style="cursor: pointer" @click="addFeature()"></span>
                         </div>
                     </div>
                 </div>

+ 1 - 0
resources/views/customer/project/part/_directLogistic.blade.php

@@ -0,0 +1 @@
+2

+ 57 - 0
resources/views/customer/project/part/_express.blade.php

@@ -0,0 +1,57 @@
+<div class="row">
+    <label class="col-3"><b class="text-danger">* </b>价格名称</label>
+    <label class="col-7"><input type="text" class="form-control"
+           v-model="model.express.name" :class="errors.name ? 'is-invalid' : ''"></label>
+</div>
+<div class="row mt-3">
+    <label class="col-3"><b class="text-danger">* </b>首重值(KG)</label>
+    <label class="col-7"><input type="number" min="0" step="0.01" class="form-control"
+           v-model="model.express.initial_weight" :class="errors.initial_weight ? 'is-invalid' : ''"></label>
+</div>
+<div class="row mt-3">
+    <label class="col-3"><b class="text-danger">* </b>续重值(KG)</label>
+    <label class="col-7"><input type="number" min="0" step="0.01" class="form-control"
+           v-model="model.express.additional_weight" :class="errors.additional_weight ? 'is-invalid' : ''"></label>
+</div>
+<div class="row mt-3">
+    <label class="col-3">详情</label>
+    <div class="col-9">
+        <div class="w-100 form-inline">
+            <input id="expressFile" type="file" class="d-none" accept=".csv, .xlsx, .xls" @change="importExpress($event)"/>
+            <button type="button" class="btn btn-sm btn-outline-info w-25" @click="addExpressItem()">新增</button>
+            <button type="button" class="btn btn-sm btn-outline-primary w-25 ml-2" @click="selectFile('expressFile')">导入</button>
+            <h5><span class="ml-0 fa fa-question-circle-o cursor-pointer" data-toggle="tooltip" data-placement="top" title="导入与保存时自动过滤重复数据"></span></h5>
+        </div>
+        <div class="w-100 text-center mb-1 mt-1" v-if="importError.length > 0">
+            <button type="button" class="btn btn-sm btn-danger mb-1" @click="isShowError = true" v-if="!isShowError">@{{ importError.length }}条错误,点击展开</button>
+            <button type="button" class="btn btn-sm btn-dark mb-1" @click="isShowError = false" v-else>收起错误展示</button>
+            <div v-if="isShowError" class="container-fluid text-danger font-weight-bolder">
+                <div class="row text-left">
+                    <div class="col-6" v-for="error in importError">@{{ error }}</div>
+                </div>
+            </div>
+        </div>
+        <div class="row font-weight-bold" v-if="model.express.items.length>0">
+            <label class="col-3">省</label>
+            <label class="col-3">首重价格</label>
+            <label class="col-3">续重价格</label>
+            <label class="col-3"></label>
+        </div>
+        <div class="row" v-for="(item,i) in model.express.items">
+            <label class="col-3">
+                <select class="form-control form-control-sm" v-model="item.province_id" :class="errors['item.'+i+'.province_id'] ? 'is-invalid' : ''">
+                    <option v-for="province in pool.provinces" :value="province.id">@{{ province.name }}</option>
+                </select>
+            </label>
+            <label class="col-3">
+                <input type="number" step="0.01" class="form-control form-control-sm" v-model="item.initial_weight_price" :class="errors['item.'+i+'.initial_weight_price'] ? 'is-invalid' : ''">
+            </label>
+            <label class="col-3">
+                <input type="number" step="0.01" class="form-control form-control-sm" v-model="item.additional_weight_price" :class="errors['item.'+i+'.additional_weight_price'] ? 'is-invalid' : ''">
+            </label>
+            <label class="col-3 cursor-pointer h3 font-weight-bold text-danger" @click="delExpressItem(i)">
+                &times;
+            </label>
+        </div>
+    </div>
+</div>

+ 72 - 0
resources/views/customer/project/part/_logistic.blade.php

@@ -0,0 +1,72 @@
+<div class="row">
+    <label for="logistic_name" class="col-2"><b class="text-danger">* </b>价格名称</label>
+    <input id="logistic_name" type="text" class="col-6 form-control"
+           :class="errors.name ? 'is-invalid' : ''" v-model="model.logistic.name">
+    <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors.name">
+        <strong>@{{ errors.name[0] }}</strong>
+    </span>
+</div>
+<div class="row mt-3">
+    <label for="logistic_pick_up_price" class="col-2">提货费</label>
+    <input id="logistic_pick_up_price" type="number" min="0" step="0.01" class="col-3 form-control"
+           :class="errors.pick_up_price ? 'is-invalid' : ''" v-model="model.logistic.pick_up_price">
+    <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors.pick_up_price">
+        <strong>@{{ errors.pick_up_price[0] }}</strong>
+    </span>
+</div>
+<div class="row mt-3">
+    <label for="logistic_fuel_price" class="col-2">燃油附加费</label>
+    <input id="logistic_fuel_price" type="number" min="0" step="0.01" class="col-3 form-control"
+           :class="errors.fuel_price ? 'is-invalid' : ''" v-model="model.logistic.fuel_price">
+    <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors.fuel_price">
+        <strong>@{{ errors.fuel_price[0] }}</strong>
+    </span>
+</div>
+<div class="row mt-3">
+    <label for="logistic_service_price" class="col-2">信息服务费</label>
+    <input id="logistic_service_price" type="number" min="0" step="0.01" class="col-3 form-control"
+           :class="errors.service_price ? 'is-invalid' : ''" v-model="model.logistic.service_price">
+    <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors.service_price">
+        <strong>@{{ errors.service_price[0] }}</strong>
+    </span>
+</div>
+<div class="row mt-3">
+    <label for="logistic_unit_id" class="col-2"><b class="text-danger">* </b>单位一</label>
+    <select id="logistic_unit_id" class="col-2 form-control"
+            v-model="model.logistic.unit_id" :class="errors.unit_id ? 'is-invalid' : ''">
+        <option v-for="unit in pool.units" :value="unit.id">@{{ unit.name }}</option>
+    </select>
+    <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors.unit_id">
+        <strong>@{{ errors.unit_id[0] }}</strong>
+    </span>
+    <label for="logistic_unit_range" class="col-2 text-right"><b class="text-danger">*</b>区间值</label>
+    <input id="logistic_unit_range" type="text" placeholder="文字描述区间逗号(,)间隔,示例:0-5,10-30,30-"
+           v-model="model.logistic.unit_range" class="col-3 form-control" :class="errors.unit_range ? 'is-invalid' : ''" @change="changeRange('ranges')">
+    <span class="invalid-feedback mt-0 offset-6" role="alert" v-if="errors.unit_range">
+        <strong>@{{ errors.unit_range[0] }}</strong>
+    </span>
+</div>
+<div class="row mt-3">
+    <label for="logistic_other_unit_id" class="col-2"><b class="text-danger">* </b>单位二</label>
+    <select id="logistic_other_unit_id" class="col-2 form-control"
+            v-model="model.logistic.other_unit_id" :class="errors.other_unit_id ? 'is-invalid' : ''">
+        <option v-for="unit in pool.units" :value="unit.id">@{{ unit.name }}</option>
+    </select>
+    <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors.other_unit_id">
+        <strong>@{{ errors.other_unit_id[0] }}</strong>
+    </span>
+    <label for="logistic_other_unit_range" class="col-2 text-right"><b class="text-danger">*</b>区间值</label>
+    <input id="logistic_other_unit_range" type="text" placeholder="文字描述区间逗号(,)间隔,示例:0-5,10-30,30-"
+           v-model="model.logistic.other_unit_range" class="col-3 form-control" :class="errors.other_unit_range ? 'is-invalid' : ''" @change="changeRange('other_ranges')">
+    <span class="invalid-feedback mt-0 offset-6" role="alert" v-if="errors.other_unit_range">
+        <strong>@{{ errors.other_unit_range[0] }}</strong>
+    </span>
+</div>
+<div class="row mt-3">
+    <label class="col-2">详情</label>
+    <div class="col-10">
+        <div class="row">
+            <button type="button" class="btn btn-sm btn-outline-info col-4" @click="showDetailModal()">详情列表</button>
+        </div>
+    </div>
+</div>

+ 91 - 0
resources/views/customer/project/part/_logisticDetail.blade.php

@@ -0,0 +1,91 @@
+<div class="modal fade" tabindex="-1" role="dialog" id="logisticModal">
+    <div class="modal-dialog modal-xl modal-dialog-centered modal-dialog-scrollable">
+        <div class="modal-content">
+            <div class="modal-header">
+                <div class="row w-100">
+                    <button type="button" class="btn btn-sm btn-outline-dark col-1" @click="addLogisticDetail()">新增</button>
+                    <input id="logisticFile" type="file" style="display:none" accept=".csv, .xlsx, .xls" @change="importLogistic($event)"/>
+                    <button type="button" class="btn btn-sm btn-outline-info col-1" @click="selectFile('logisticFile')">导入</button>
+                    <h5><span class="ml-0 fa fa-question-circle-o cursor-pointer" data-toggle="tooltip" data-placement="top" title="导入与保存时自动过滤重复数据和与当前选择单位不一致数据"></span></h5>
+                    <div class="font-weight-bolder offset-3">物流收费标准</div>
+                </div>
+            </div>
+            <div class="modal-body">
+                <div class="w-100 text-center mb-1" v-if="importError.length > 0">
+                    <button type="button" class="btn btn-sm btn-danger mb-1" @click="isShowError = true" v-if="!isShowError">@{{ importError.length }}条错误,点击展开</button>
+                    <button type="button" class="btn btn-sm btn-dark mb-1" @click="isShowError = false" v-else>收起错误展示</button>
+                    <div v-if="isShowError" class="container-fluid text-danger font-weight-bolder">
+                        <div class="row text-left">
+                            <div class="col-6" v-for="err in importError">@{{ err }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="w-100 text-primary text-center mt-0" v-else>
+                    <div class="small"><b class="text-dark font-weight-bold">导入表头示例:</b>计数单位,计数区间,省份,市,单价,送货费,起始计费,起始计数,费率</div>
+                </div>
+                <table class="table table-sm table-bordered">
+                    <tr class="text-success">
+                        <th>计价单位</th>
+                        <th>计价区间</th>
+                        <th style="min-width: 100px">省份</th>
+                        <th style="min-width: 100px">市</th>
+                        <th>单价</th>
+                        <th>送货费</th>
+                        <th>起始计费</th>
+                        <th>起始计数</th>
+                        <th>费率(%)</th>
+                        <th>操作</th>
+                    </tr>
+                    <tr v-for="(detail,i) in model.logistic.items">
+                        <td>
+                            <label>
+                                <select class="form-control form-control-sm col-6" style="min-width: 80px" v-model="detail.unit_id">
+                                    <option v-for="unit in pool.units" :value="unit.id" v-if="unit.id == model.logistic.unit_id || unit.id == model.logistic.other_unit_id">@{{ unit.name }}</option>
+                                </select>
+                            </label>
+                        </td>
+                        <td>
+                            <label>
+                                <select class="form-control form-control-sm col-6" style="min-width: 80px" v-model="detail.range">
+                                    <option v-for="range in (detail.unit_id == model.logistic.unit_id ? model.logistic.ranges : model.logistic.other_ranges)" :value="range">@{{ range }}</option>
+                                </select>
+                            </label>
+                        </td>
+                        <td>
+                            <label>
+                                <select class="form-control form-control-sm" v-model="detail.province_id">
+                                    <option v-for="province in pool.provinces" :value="province.id">@{{ province.name }}</option>
+                                </select>
+                            </label>
+                        </td>
+                        <td>
+                            <label>
+                                <select class="form-control form-control-sm" v-model="detail.city_id">
+                                    <option v-for="city in pool.cities" v-if="detail.province_id === city.province_id" :value="city.id">@{{ city.name }}</option>
+                                </select>
+                            </label>
+                        </td>
+                        <td>
+                            <label><input type="number" min="0" step="0.001" class="form-control form-control-sm" v-model="detail.unit_price" :data="detail.unit_price"></label>
+                        </td>
+                        <td>
+                            <label><input type="number" min="0" step="0.001" class="form-control form-control-sm" v-model="detail.delivery_fee" :data="detail.delivery_fee"></label>
+                        </td>
+                        <td>
+                            <label><input type="number" min="0" step="0.001" class="form-control form-control-sm" v-model="detail.initial_fee" :data="detail.initial_fee"></label>
+                        </td>
+                        <td>
+                            <label><input type="number" min="0" class="form-control form-control-sm" v-model="detail.initial_amount" :data="detail.initial_amount"></label>
+                        </td>
+                        <td>
+                            <label><input type="number" min="0" step="0.001" class="form-control form-control-sm" v-model="detail.rate" :data="detail.rate"></label>
+                        </td>
+                        <td>
+                            <button type="button" class="btn btn-sm btn-outline-danger" @click="delLogisticItem(i)">删</button>
+                        </td>
+                    </tr>
+                </table>
+            </div>
+        </div>
+    </div>
+</div>

+ 0 - 0
resources/views/customer/project/_one.blade.php → resources/views/customer/project/part/_one.blade.php


+ 53 - 52
resources/views/customer/project/_operation.blade.php → resources/views/customer/project/part/_operation.blade.php

@@ -37,33 +37,33 @@
             <div class="row">
                 <label class="col-3">子策略:</label>
                 <label class="col-5"><select disabled v-model="model.operation.items[0].strategy" class="form-control">
-                        <option>起步</option>
-                    </select></label>
+                    <option>起步</option>
+                </select></label>
             </div>
             <div class="row mt-2">
                 <label class="col-3">起步数</label>
-                <label class="col-5"><input id="amount" type="number" :class="errors['items.0.amount'] ? 'is-invalid' : ''"
+                <label class="col-5 mb-0"><input id="amount" type="number" :class="errors['items.0.amount'] ? 'is-invalid' : ''"
                        v-model="model.operation.items[0].amount" class="form-control" step="1"></label>
-                <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors['items.0.amount']">
-                    <strong>@{{ errors['items.0.amount'][0] }}</strong>
-                </span>
+            </div>
+            <div class="row mt-0" v-if="errors['items.0.amount']">
+                <div class="offset-3"><small class="text-danger font-weight-bold ml-3">@{{ errors['items.0.amount'][0] }}</small></div>
             </div>
             <div class="row mt-2">
                 <label class="col-3">单位</label>
-                <label class="col-5"><select v-model="model.operation.items[0].unit_id" class="form-control" :class="errors['items.0.unit_id'] ? 'is-invalid' : ''">
+                <label class="col-5 mb-0"><select v-model="model.operation.items[0].unit_id" class="form-control" :class="errors['items.0.unit_id'] ? 'is-invalid' : ''">
                         <option v-for="unit in pool.units" :value="unit.id">@{{ unit.name }}</option>
                 </select></label>
-                <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors['items.0.unit_id']">
-                    <strong>@{{ errors['items.0.unit_id'][0] }}</strong>
-                </span>
+            </div>
+            <div class="row mt-0" v-if="errors['items.0.unit_id']">
+                <div class="offset-3"><small class="text-danger font-weight-bold ml-3">@{{ errors['items.0.unit_id'][0] }}</small></div>
             </div>
             <div class="row mt-2">
                 <label class="col-3">单价</label>
-                <label class="col-5"><input type="number" min="0" step="0.001" class="form-control" v-model="model.operation.items[0].unit_price"
+                <label class="col-5 mb-0"><input type="number" min="0" step="0.001" class="form-control" v-model="model.operation.items[0].unit_price"
                            :class="errors['items.0.unit_price'] ? 'is-invalid' : ''"></label>
-                <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors['items.0.unit_price']">
-                    <strong>@{{ errors['items.0.unit_price'][0] }}</strong>
-                </span>
+            </div>
+            <div class="row mt-0" v-if="errors['items.0.unit_price']">
+                <div class="offset-3"><small class="text-danger font-weight-bold ml-3">@{{ errors['items.0.unit_price'][0] }}</small></div>
             </div>
         </div>
     </div>
@@ -75,36 +75,37 @@
         </div>
         <div class="card-body">
             <div class="row">
+                <label class="col-3">子策略:</label>
+                <label class="col-5"><select disabled v-model="model.operation.items[1].strategy" class=" form-control">
+                    <option>默认</option>
+                </select></label>
+            </div>
+            <div class="row mt-2">
                 <label class="col-3">数量</label>
-                <label class="col-5"><input id="amount" type="number" :class="errors['items.1.amount'] ? 'is-invalid' : ''"
-                                            v-model="model.operation.items[1].amount" class="form-control" step="1">
+                <label class="col-5 mb-0"><input id="amount" type="number" :class="errors['items.1.amount'] ? 'is-invalid' : ''"
+                       v-model="model.operation.items[1].amount" class="form-control" step="1">
                 </label>
-                <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors['items.1.amount']">
-                    <strong>@{{ errors['items.1.amount'][0] }}</strong>
-                </span>
+                <div class="col-4"></div>
+            </div>
+            <div class="row mt-0" v-if="errors['items.1.amount']">
+                <div class="offset-3"><small class="text-danger font-weight-bold ml-3">@{{ errors['items.1.amount'][0] }}</small></div>
             </div>
             <div class="row mt-2">
                 <label class="col-3">单位</label>
-                <label class="col-5"><select v-model="model.operation.items[1].unit_id" class="form-control" :class="errors['items.1.unit_id'] ? 'is-invalid' : ''">
-                        <option v-for="unit in pool.units" :value="unit.id">@{{ unit.name }}</option>
-                    </select></label>
-                <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors['items.1.unit_id']">
-                     <strong>@{{ errors['items.1.unit_id'][0] }}</strong>
-                </span>
+                <label class="col-5 mb-0"><select v-model="model.operation.items[1].unit_id" class="form-control" :class="errors['items.1.unit_id'] ? 'is-invalid' : ''">
+                    <option v-for="unit in pool.units" :value="unit.id">@{{ unit.name }}</option>
+                </select></label>
+            </div>
+            <div class="row mt-0" v-if="errors['items.1.unit_id']">
+                <div class="offset-3"><small class="text-danger font-weight-bold ml-3">@{{ errors['items.1.unit_id'][0] }}</small></div>
             </div>
             <div class="row mt-2">
                 <label class="col-3">单价</label>
-                <label class="col-5"><input type="number" min="0" step="0.001" class="form-control" v-model="model.operation.items[1].unit_price"
+                <label class="col-5 mb-0"><input type="number" min="0" step="0.001" class="form-control" v-model="model.operation.items[1].unit_price"
                            :class="errors['items.1.unit_price'] ? 'is-invalid' : ''"></label>
-                <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors['items.1.unit_price']">
-                    <strong>@{{ errors['items.1.unit_price'][0] }}</strong>
-                </span>
             </div>
-            <div class="row mt-2">
-                <label class="col-3">子策略:</label>
-                <label class="col-5"><select disabled v-model="model.operation.items[1].strategy" class=" form-control">
-                    <option>默认</option>
-                </select></label>
+            <div class="row mt-0" v-if="errors['items.1.unit_price']">
+                <div class="offset-3"><small class="text-danger font-weight-bold ml-3">@{{ errors['items.1.unit_price'][0] }}</small></div>
             </div>
         </div>
     </div>
@@ -117,40 +118,40 @@
         </div>
         <div class="card-body">
             <div class="row">
+                <label class="col-3">子策略</label>
+                <label class="col-5"><select disabled v-model="item.strategy" class="form-control">
+                    <option>特征</option>
+                </select></label>
+            </div>
+            <div class="row mt-2">
                 <label class="col-3">数量</label>
-                <label class="col-5"><input type="number" step="1" :class="errors['items.'+i+'.amount'] ? 'is-invalid' : ''" v-model="item.amount" class="form-control"></label>
-                <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors['items.'+i+'.amount']">
-                    <strong>@{{ errors['items.'+i+'.amount'][0] }}</strong>
-                </span>
+                <label class="col-5 mb-0"><input type="number" step="1" :class="errors['items.'+i+'.amount'] ? 'is-invalid' : ''" v-model="item.amount" class="form-control"></label>
+            </div>
+            <div class="row mt-0" v-if="errors['items.'+i+'.amount']">
+                <div class="offset-3"><small class="text-danger font-weight-bold ml-3">@{{ errors['items.'+i+'.amount'][0] }}</small></div>
             </div>
             <div class="row mt-2">
                 <label class="col-3">单位</label>
-                <label class="col-5"><select v-model="item.unit_id" class="form-control" :class="errors['items.'+i+'.unit_id'] ? 'is-invalid' : ''">
+                <label class="col-5 mb-0"><select v-model="item.unit_id" class="form-control" :class="errors['items.'+i+'.unit_id'] ? 'is-invalid' : ''">
                     <option v-for="unit in pool.units" :value="unit.id">@{{ unit.name }}</option>
                 </select></label>
-                <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors['items.'+i+'.unit_id']">
-                    <strong>@{{ errors['items.'+i+'.unit_id'][0] }}</strong>
-                </span>
+            </div>
+            <div class="row mt-0" v-if="errors['items.'+i+'.unit_id']">
+                <div class="offset-3"><small class="text-danger font-weight-bold ml-3">@{{ errors['items.'+i+'.unit_id'][0] }}</small></div>
             </div>
             <div class="row mt-2">
                 <label class="col-3">单价</label>
-                <label class="col-5"><input type="number" min="0" step="0.001" class="form-control" v-model="item.unit_price"
+                <label class="col-5 mb-0"><input type="number" min="0" step="0.001" class="form-control" v-model="item.unit_price"
                        :class="errors['items.'+i+'.unit_price'] ? 'is-invalid' : ''"></label>
-                <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors['items.'+i+'.unit_price']">
-                    <strong>@{{ errors['items.'+i+'.unit_price'][0] }}</strong>
-                </span>
             </div>
-            <div class="row mt-2">
-                <label class="col-3">子策略</label>
-                <label class="col-5"><select disabled v-model="item.strategy" class="form-control">
-                    <option>特征</option>
-                </select></label>
+            <div class="row mt-0" v-if="errors['items.'+i+'.unit_price']">
+                <div class="offset-3"><small class="text-danger font-weight-bold ml-3">@{{ errors['items.'+i+'.unit_price'][0] }}</small></div>
             </div>
             <div class="row mt-2">
                 <label class="col-3">特征:</label>
                 <label class="col-5">
                     <label v-if="item.feature">@{{ item.feature }}</label><br>
-                    <button type="button" class="btn btn-dark ml-2" @click="showAddFeatureModal(i,item.feature)">调整特征</button>
+                    <button type="button" class="btn btn-dark ml-2" @click="showAddFeatureModal(i)">调整特征</button>
                 </label>
             </div>
         </div>

+ 0 - 0
resources/views/customer/project/_storage.blade.php → resources/views/customer/project/part/_storage.blade.php


+ 171 - 0
resources/views/customer/project/part/_three.blade.php

@@ -0,0 +1,171 @@
+<div class="row">
+    <div class="col-6" id="parent">
+        <div class="card">
+            <div class="card-header bg-light-info">
+                <span class="pull-left font-weight-bold cursor-pointer" @click="show('storage')"><span class="fa fa-cubes"></span>&nbsp;仓储</span>
+            </div>
+            <div class="card-body" id="storage">
+                <table class="table table-sm">
+                    <tr>
+                        <th>计费类型</th>
+                        <th>用仓类型</th>
+                        <th>起租面积</th>
+                        <th>单价</th>
+                        <th>单位</th>
+                        <th>减免类型</th>
+                        <th>减免值</th>
+                    </tr>
+                    <tr v-for="item in selectedModel.storage">
+                        <td>@{{ item.counting_type }}</td>
+                        <td>@{{ item.using_type }}</td>
+                        <td>@{{ item.minimum_area }}</td>
+                        <td>@{{ item.price }}</td>
+                        <td>@{{ item.discount_type }}</td>
+                        <td>@{{ item.discount_value }}</td>
+                        <td>@{{ poolMapping.units[item.unit_id] }}</td>
+                    </tr>
+                </table>
+            </div>
+        </div>
+        <div class="card">
+            <div class="card-header bg-light-info">
+                <span class="pull-left font-weight-bold cursor-pointer" @click="show('operation')"><span class="fa fa-suitcase"></span>&nbsp;作业</span>
+            </div>
+            <div class="card-body" id="operation">
+                <table class="table table-sm">
+                    <tr>
+                        <th>操作类型</th>
+                        <th>计费策略</th>
+                        <th>名称</th>
+                        <th>子策略</th>
+                        <th>特征</th>
+                        <th>备注</th>
+                    </tr>
+                    <tr v-for="(operation,i) in selectedModel.operation" :id="'operation-'+i">
+                        <td>@{{ operation.operation_type }}</td>
+                        <td>@{{ operation.strategy }}</td>
+                        <td>@{{ operation.name }}</td>
+                        <td class="cursor-pointer" @click="showOperationItem(i)"><span class="fa" :class="operationItems['_'+i] === true ? 'fa-angle-double-down' : 'fa-angle-double-right'"></span>@{{ operation.items.length }}条策略</td>
+                        <td @mouseenter="textClass($event,true)" @mouseleave="textClass($event,false)"><div class="cursor-pointer text-overflow-replace-100">@{{ operation.featureFormat }}</div></td>
+                        <td @mouseenter="textClass($event,true)" @mouseleave="textClass($event,false)"><div class="cursor-pointer text-overflow-replace-100">@{{ operation.remark }}</div></td>
+                    </tr>
+                </table>
+            </div>
+        </div>
+        <div class="card">
+            <div class="card-header bg-light-info">
+                <span class="pull-left font-weight-bold cursor-pointer" @click="show('express')"><span class="fa fa-cube"></span>&nbsp;快递</span>
+            </div>
+            <div class="card-body" id="express">
+                <div class="row">
+                    <label class="col-4">名称:<b>@{{ selectedModel.express.name }}</b></label>
+                    <label class="col-4">首重值(KG):<b>@{{ selectedModel.express.initial_weight }}</b></label>
+                    <label class="col-4">续重值(KG):<b>@{{ selectedModel.express.additional_weight }}</b></label>
+                </div>
+                <div class="row">
+                    <label class="text-primary col-2">详情</label>
+                    <table class="table table-sm col-10">
+                        <tr>
+                            <th>省份</th>
+                            <th>首重价格</th>
+                            <th>续重价格</th>
+                        </tr>
+                        <tr v-for="(item,i) in selectedModel.express.items">
+                            <td>@{{ poolMapping.provinces[item.province_id] }}</td>
+                            <td>@{{ item.initial_weight_price }}</td>
+                            <td>@{{ item.additional_weight_price }}</td>
+                        </tr>
+                    </table>
+                </div>
+            </div>
+        </div>
+        <div class="card" id="logistic-card">
+            <div class="card-header bg-light-info">
+                <span class="pull-left font-weight-bold cursor-pointer" @click="show('logistic')"><span class="fa fa-truck"></span>&nbsp;物流</span>
+            </div>
+            <div class="card-body" id="logistic">
+                <div class="row">
+                    <label class="col-4">名称:<b>@{{ selectedModel.express.name }}</b></label>
+                    <label class="col-4">首重值(KG):<b>@{{ selectedModel.express.initial_weight }}</b></label>
+                    <label class="col-4">续重值(KG):<b>@{{ selectedModel.express.additional_weight }}</b></label>
+                </div>
+                <div class="row">
+                    <label class="text-primary col-2">详情</label>
+                    <table class="table table-sm col-10">
+                        <tr>
+                            <th>省份</th>
+                            <th>首重价格</th>
+                            <th>续重价格</th>
+                        </tr>
+                        <tr v-for="(item,i) in selectedModel.express.items">
+                            <td>@{{ poolMapping.provinces[item.province_id] }}</td>
+                            <td>@{{ item.initial_weight_price }}</td>
+                            <td>@{{ item.additional_weight_price }}</td>
+                        </tr>
+                    </table>
+                </div>
+            </div>
+        </div>
+        <div class="card" id="directLogistic-card">
+            <div class="card-header bg-light-info">
+                <span class="pull-left font-weight-bold cursor-pointer" @click="show('directLogistic')"><span class="fa fa-rocket"></span>&nbsp;直发</span>
+            </div>
+            <div class="card-body" id="directLogistic">
+                <div class="row">
+                    <label class="col-4">名称:<b>@{{ selectedModel.express.name }}</b></label>
+                    <label class="col-4">首重值(KG):<b>@{{ selectedModel.express.initial_weight }}</b></label>
+                    <label class="col-4">续重值(KG):<b>@{{ selectedModel.express.additional_weight }}</b></label>
+                </div>
+                <div class="row">
+                    <label class="text-primary col-2">详情</label>
+                    <table class="table table-sm col-10">
+                        <tr>
+                            <th>省份</th>
+                            <th>首重价格</th>
+                            <th>续重价格</th>
+                        </tr>
+                        <tr v-for="(item,i) in selectedModel.express.items">
+                            <td>@{{ poolMapping.provinces[item.province_id] }}</td>
+                            <td>@{{ item.initial_weight_price }}</td>
+                            <td>@{{ item.additional_weight_price }}</td>
+                        </tr>
+                    </table>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="col-6">
+        <div class="card">
+            <div class="card-header bg-light-info">
+                <button type="button" class="btn mr-1" :class="type == 'storage' ? 'btn-primary text-white' : 'btn-outline-primary'" @click="switchType('storage')">仓储</button>
+                <button type="button" class="btn mr-1" :class="type == 'operation' ? 'btn-primary text-white' : 'btn-outline-primary'" @click="switchType('operation')">作业</button>
+                <button type="button" class="btn mr-1" :class="type == 'express' ? 'btn-primary text-white' : 'btn-outline-primary'" @click="switchType('express')">快递</button>
+                <button type="button" class="btn mr-1" :class="type == 'logistic' ? 'btn-primary text-white' : 'btn-outline-primary'" @click="switchType('logistic')">物流</button>
+                <button type="button" class="btn mr-1" :class="type == 'directLogistic' ? 'btn-primary text-white' : 'btn-outline-primary'" @click="switchType('directLogistic')">直发</button>
+            </div>
+            <div class="card-body">
+                <div v-if="type == 'storage'">
+                    @include("customer.project.part._storage")
+                </div>
+                <div v-show="type == 'operation'">
+                    @include("customer.project.part._operation")
+                    @include("customer.project.part._addFeature")
+                </div>
+                <div v-show="type == 'express'">
+                    @include("customer.project.part._express")
+                </div>
+                <div v-show="type == 'logistic'">
+                    @include("customer.project.part._logistic")
+                    @include("customer.project.part._logisticDetail")
+                </div>
+                <div v-show="type == 'directLogistic'">
+                    @include("customer.project.part._directLogistic")
+                </div>
+                <div class="row mt-3" v-if="base=='three'">
+                    <div class="col-3"></div>
+                    <button type="button" class="btn btn-success ml-1 col-6" @click="saveModel()">保存</button>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>

+ 0 - 0
resources/views/customer/project/_two.blade.php → resources/views/customer/project/part/_two.blade.php


+ 1 - 1
resources/views/maintenance/owner/recycle.blade.php

@@ -52,7 +52,7 @@
                 restoreSelected:function(owner){
                     let _this=this;
                     confirm('确定要恢复停用货主“' + owner.name + '”吗?');
-                    let ajaxUrl='{{url("apiLocal/owner/restoreSelected")}}';
+                    let ajaxUrl='{{url("maintenance/owners/restoreSelected")}}';
                     axios.post(ajaxUrl,{id:owner.id}).then(function(response){
                         if(response.data.success){
                             tempTip.setDuration(1000);

+ 1 - 1
resources/views/maintenance/priceModel/logistic/index.blade.php

@@ -122,7 +122,7 @@
                         window.axios.post('{{url('maintenance/city/get')}}')
                             .then(res=>{
                                 let cities = [];
-                                res.data.forEach(function (city) {
+                                res.data.data.forEach(function (city) {
                                     if (city.province_id){
                                         if (cities[city.province_id]){
                                             cities[city.province_id].push(city)

+ 5 - 8
resources/views/order/index/delivering.blade.php

@@ -858,25 +858,22 @@
                 copyLogisticNumber(){
                     let text="";
                     this.checkData.forEach((code,i)=>{
-                        if (this.picktotraceidMap[code] && this.picktotraceidMap[code].length>1){console.log(1);
+                        if(this.picktotraceidMap[code] && this.picktotraceidMap[code].length>1){
                             this.picktotraceidMap[code].forEach((number,j)=>{
-                                text += number;
-                                if (i!==this.checkData.length-1 && j!==this.picktotraceidMap[code].length-1){
-                                    text += ",";
-                                }
+                                text += number+"\r\n";
                             });
-                        }else{
+                        }else {
                             this.orders.some(order=>{
                                 if (order.orderno == code){
                                     if (order.soreference5) {
-                                        text += order.soreference5;
-                                        if(i!==this.checkData.length-1)text += "\r\n";
+                                        text += order.soreference5+"\r\n";
                                     }
                                     return true;
                                 }
                             });
                         }
                     });
+                    text.substring(0,text.lastIndexOf("\r\n",text));
                     if (!text)text = " ";
                     this.copyText(text)
                 },

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

@@ -257,8 +257,8 @@
                             <span v-if='orderIssue.order.logistic'>@{{ orderIssue.order.logistic.name }}</span>
                         </td>
                         <td class=" hide-content p-0 td-yellow child-layer-2" valign="middle" align="center">
-                            <span :id="'logisticNumbers'+orderIssue.id" :class="orderIssue.order.logisticNumbers.length > 1 ?'collapse ':''">
-                                <span v-for="logisticNumber in orderIssue.order.logisticNumbers" >@{{ logisticNumber }}&nbsp;&nbsp;</span>
+                            <span  :class="orderIssue.order.logisticNumbers.length > 1 ?'collapse ':''" :id="'logisticNumbers'+orderIssue.id" >
+                                <span class="m-0 p-0 d-inline-block" v-for="logisticNumber in orderIssue.order.logisticNumbers" >@{{ logisticNumber }}&nbsp;&nbsp;</span>
                             </span>
                             <button v-if="orderIssue.order.logisticNumbers.length > 1" type="button" class="btn btn-sm btn-outline-primary align-middle mt-1"
                                     :id="'logisticNumbersBtn'+orderIssue.id" data-toggle="collapse" :data-target="'#logisticNumbers'+orderIssue.id"
@@ -749,7 +749,7 @@
                         placeholder: ['货主', '定位或多选货主'],
                         data: _this.owners
                     },
-                    {name: 'client_code', type: 'input', tip: '原始订单号:前或后加百分号为单个模糊搜索,否则为多条件精确搜索', placeholder: '原始订单号'},
+                    {name: 'client_code', type: 'input', tip: '原始订单号:前或后加百分号为单个模糊搜索,否则为多条件精确搜索', placeholder: '原始订单号',required:true},
                     {name: 'logistic_number', type: 'input', tip: ['输入原始运单号:前或后加百分号为单个模糊搜索,否则为多条件精确搜索'], placeholder: '运单号'},
                     {
                         name: 'logistic_id',

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

@@ -277,7 +277,7 @@
                         recipient:'{{$waybill->recipient}}',
                         recipient_mobile:'{{$waybill->recipient_mobile}}',
                         charge:'{{$waybill->charge}}',
-                        ordering_remark:'{{$waybill->ordering_remark}}',
+                        ordering_remark:'{{preg_replace("/[\n\s]/",' ',($waybill->ordering_remark??""))}}',
                         carrier:'{{$waybill->logistic ? $waybill->logistic->name : ''}}',
                         carrier_bill:'{{$waybill->carrier_bill}}',
                         origination_city:'{{$waybill->origination_city ? $waybill->origination_city->name : ''}}',

+ 1 - 1
resources/views/waybill/recycle.blade.php

@@ -146,7 +146,7 @@
                         recipient:'{{$waybill->recipient}}',
                         recipient_mobile:'{{$waybill->recipient_mobile}}',
                         charge:'{{$waybill->charge}}',
-                        ordering_remark:'{{$waybill->ordering_remark}}',
+                        ordering_remark:'{{preg_replace("/[\n\s]/",' ',($waybill->ordering_remark??""))}}',
                         carrier:'{{$waybill->carrier ? $waybill->carrier->name : ''}}',
                         carrier_bill:'{{$waybill->carrier_bill}}',
                         origination_city:'{{$waybill->origination_city ? $waybill->origination_city->name : ''}}',

+ 0 - 1
routes/apiLocal.php

@@ -7,7 +7,6 @@ use Illuminate\Support\Facades\Route;
 地址前缀:/apiLocal/
 */
 Route::post('rejected/recoverSelected', 'RejectedController@apiRecoverSelected');
-Route::post('owner/restoreSelected', 'OwnerController@restoreSelected');
 Route::post('rejectedBillItem/store', 'RejectedBillItemController@apiStore');
 Route::post('rejectedBillItem/update', 'RejectedBillItemController@apiUpdate');
 Route::post('rejectedBillItem/apiGet', 'RejectedBillItemController@apiGet');

+ 2 - 0
routes/web.php

@@ -47,6 +47,7 @@ Route::group(['prefix'=>'maintenance'],function(){
     /** 货主 */
     Route::group(['prefix'=>'owners'],function(){
         Route::get('recycle','OwnerController@recycle');
+        Route::post('restoreSelected', 'OwnerController@restoreSelected');
     });
     Route::group(['prefix'=>'owner'],function (){
         Route::post("get","OwnerController@get");
@@ -624,6 +625,7 @@ Route::group(['prefix'=>'customer'],function(){
         Route::post('storeLog', 'CustomerLogController@store');
         Route::post('relatedOwner', 'CustomerBaseController@relatedOwner');
         Route::post('addTag', 'CustomerBaseController@addTag');
+        Route::post('destroyLog', 'CustomerBaseController@destroyLog');
         Route::group(['prefix' => 'customerLogStatus'], function () {
             Route::post('save', 'CustomerLogStatusController@save');
             Route::post('destroy', 'CustomerLogStatusController@destroy');