Procházet zdrojové kódy

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

 Conflicts:
	app/Services/OwnerPriceLogisticService.php
	app/Services/OwnerPriceOperationItemService.php
	app/Services/OwnerStoragePriceModelService.php
LD před 5 roky
rodič
revize
8197cb496d
55 změnil soubory, kde provedl 1877 přidání a 622 odebrání
  1. 1 1
      app/Batch.php
  2. 5 3
      app/Components/AsyncResponse.php
  3. 1 1
      app/Console/Commands/CreateOwnerAreaReport.php
  4. 1 1
      app/Console/Commands/CreateOwnerReport.php
  5. 1 1
      app/Console/Commands/InventoryDailyLoggingOwner.php
  6. 0 1
      app/Exports/Export.php
  7. 1 1
      app/Http/Controllers/CommodityController.php
  8. 38 51
      app/Http/Controllers/CustomerController.php
  9. 34 6
      app/Http/Controllers/OwnerController.php
  10. 547 79
      app/Http/Controllers/PriceModelController.php
  11. 1 1
      app/Http/Controllers/ProcessController.php
  12. 3 4
      app/Http/Controllers/TestController.php
  13. 1 1
      app/Http/Controllers/api/thirdPart/flux/ProcessController.php
  14. 1 1
      app/Http/Controllers/api/thirdPart/weixin/WxController.php
  15. 1 1
      app/MeasuringMachine.php
  16. 6 1
      app/Owner.php
  17. 3 8
      app/OwnerPriceOperation.php
  18. 2 2
      app/OwnerPriceOperationItem.php
  19. 0 25
      app/OwnerPriceOperationItemIn.php
  20. 5 0
      app/OwnerStoragePriceModel.php
  21. 12 13
      app/Providers/AppServiceProvider.php
  22. 1 1
      app/RejectedBill.php
  23. 3 3
      app/Services/CheckActiveMenuService.php
  24. 0 2
      app/Services/CommodityService.php
  25. 1 1
      app/Services/OrderCommodityService.php
  26. 1 1
      app/Services/OrderService.php
  27. 18 5
      app/Services/OwnerPriceExpressService.php
  28. 7 3
      app/Services/OwnerPriceLogisticService.php
  29. 20 10
      app/Services/OwnerPriceOperationItemService.php
  30. 40 42
      app/Services/OwnerPriceOperationService.php
  31. 2 2
      app/Services/OwnerService.php
  32. 2 0
      app/Services/OwnerStoragePriceModelService.php
  33. 5 1
      app/Services/PackageService.php
  34. 1 1
      app/Services/StoreService.php
  35. 5 0
      app/Services/WarehouseService.php
  36. 38 0
      database/migrations/2021_01_07_145912_add_warehouse_id_column_owners_table.php
  37. 43 0
      database/migrations/2021_01_08_093237_delete_table_item_in_change_table_out.php
  38. 5 0
      resources/sass/text.scss
  39. 1 1
      resources/views/customer/customer/index.blade.php
  40. 663 158
      resources/views/customer/project/create.blade.php
  41. 3 3
      resources/views/customer/project/part/_directLogistic.blade.php
  42. 4 4
      resources/views/customer/project/part/_express.blade.php
  43. 70 0
      resources/views/customer/project/part/_introducePriceModel.blade.php
  44. 9 9
      resources/views/customer/project/part/_logisticDetail.blade.php
  45. 2 2
      resources/views/customer/project/part/_one.blade.php
  46. 21 19
      resources/views/customer/project/part/_operation.blade.php
  47. 7 0
      resources/views/customer/project/part/_storage.blade.php
  48. 117 53
      resources/views/customer/project/part/_three.blade.php
  49. 9 0
      resources/views/customer/project/part/_two.blade.php
  50. 9 9
      resources/views/maintenance/priceModel/operation/_addItemModal.blade.php
  51. 35 36
      resources/views/maintenance/priceModel/operation/create.blade.php
  52. 29 50
      resources/views/maintenance/priceModel/operation/index.blade.php
  53. 8 0
      resources/views/maintenance/priceModel/storage/create.blade.php
  54. 3 0
      resources/views/maintenance/priceModel/storage/index.blade.php
  55. 31 4
      routes/web.php

+ 1 - 1
app/Batch.php

@@ -35,7 +35,7 @@ class Batch extends Model
         $this->orders()->each(function(Order $order){
             $order->delete();
         });
-        return parent::delete(); // TODO: Change the autogenerated stub
+        return parent::delete();
     }
     public function owner()
     {

+ 5 - 3
app/Components/AsyncResponse.php

@@ -9,7 +9,7 @@ trait AsyncResponse{
     protected function gate(string $authorityName)
     {
         if(!Gate::allows($authorityName)){
-            echo ["success"=>false,"data"=>"无权操作"];
+            echo json_encode(["success"=>false,"data"=>"无权操作"]);
             exit();
         }
     }
@@ -20,9 +20,11 @@ trait AsyncResponse{
         exit();
     }
 
-    public function success($message)
+    public function success($message = null)
     {
-        echo json_encode(["success"=>true,"data"=>$message]);
+        $result = ["success"=>true];
+        if ($message)$result["data"] = $message;
+        echo json_encode($result);
         exit();
     }
 }

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

@@ -35,7 +35,7 @@ class CreateOwnerAreaReport extends Command
     }
 
     /**
-     * TODO 25号生成盘点面积记录,记录留空由人工填写
+     * 25号生成盘点面积记录,记录留空由人工填写
      *
      * @return void
      */

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

@@ -37,7 +37,7 @@ class CreateOwnerReport extends Command
     }
 
     /**
-     * TODO 1号生成或修改上月报表  此处假设每月生成报表数 不足1000,超过此数可能在SQL执行上溢出
+     * 1号生成或修改上月报表  此处假设每月生成报表数 不足1000,超过此数可能在SQL执行上溢出
      *
      * @return void
      */

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

@@ -38,7 +38,7 @@ class InventoryDailyLoggingOwner extends Command
     /**
      * Execute the console command.
      *
-     *  TODO : 增量添加,每天都会重复去录入之前数据,没有限制去重条件. 因业务需要去查看每天同批货的变动
+     *  增量添加,每天都会重复去录入之前数据,没有限制去重条件. 因业务需要去查看每天同批货的变动
      *
      * @param CommodityService $commodityService
      * @return void

+ 0 - 1
app/Exports/Export.php

@@ -56,7 +56,6 @@ class Export extends StringValueBinder implements FromCollection,
     }
     public function registerEvents(): array
     {
-        // TODO: Implement registerEvents() method.
         if ($this->mergeCell && $this->columnName){
             return [
                 AfterSheet::class => function(AfterSheet $event){

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

@@ -336,7 +336,7 @@ class CommodityController extends Controller
         }
 
         if (count($barcodes) > 0){
-            // TODO ownerBarcodeSeekCommodityGet可指定第三个参数为true 默认无差别覆盖 如若指定该布尔值true代表仅覆盖SKU空值项
+            // ownerBarcodeSeekCommodityGet可指定第三个参数为true 默认无差别覆盖 如若指定该布尔值true代表仅覆盖SKU空值项
             $commodities = $commodityService->ownerBarcodeSeekCommodityGet(['id'=>$owner_id], $barcodes);
             $updateCommodities = [];
             $updateCommodities[] = [

+ 38 - 51
app/Http/Controllers/CustomerController.php

@@ -151,50 +151,32 @@ class CustomerController extends Controller
         if(!Gate::allows('客户管理-项目-录入')){ return redirect('denied');  }
         $customers = app('CustomerService')->getSelection();
         $ownerGroups = app('UserOwnerGroupService')->getSelection();
-        $storagePriceModels = app('OwnerStoragePriceModelService')->getSelection(["id","counting_type","using_type","minimum_area","price","unit_id"],["unit"=>function($query){$query->select("id","name");}]);
+        $warehouses = app('WarehouseService')->getSelection();
         $owner = null;
-        return response()->view('customer.project.create',compact("customers","ownerGroups","storagePriceModels","owner"));
+        return response()->view('customer.project.create',compact("customers","ownerGroups","owner","warehouses"));
     }
 
-    public function projectStore(Request $request)
+    public function projectUpdate()
     {
-        if(!Gate::allows('客户管理-项目-录入')){ return redirect('denied');  }
-        $this->validator($request->input())->validate();
-        $params = $request->input();
-        if ($params["id"]){
-            /** @var Owner $owner */
-            $owner = app('OwnerService')->find($params["id"]);
-            app('OwnerService')->update($owner,[
-                "customer_id"           => $params["customer_id"],
-                "tax_rate"              => $params["tax_rate"],
-                "linkman"               => $params["linkman"],
-                "phone_number"          => $params["phone_number"],
-                "user_owner_group_id"   => $params["owner_group_id"],
-                "waring_line_on"        => $params["waring_line_on"],
-                "description"           => $params["description"],
-            ],[
-                "ownerStoragePriceModels" => explode(',',$params["owner_storage_price_model_id"])
-            ]);
-            $msg = "成功更新“".$owner->name."”的信息!";
-            LogService::log(__METHOD__,"客户管理-修改货主",json_encode($params,JSON_UNESCAPED_UNICODE));
-        }else{
-            $owner = app('OwnerService')->create([
-                "name"                  => $params["name"],
-                "code"                  => $params["code"],
-                "customer_id"           => $params["customer_id"],
-                "tax_rate"              => $params["tax_rate"],
-                "linkman"               => $params["linkman"],
-                "phone_number"          => $params["phone_number"],
-                "user_owner_group_id"   => $params["owner_group_id"],
-                "waring_line_on"        => $params["waring_line_on"],
-                "description"           => $params["description"],
-            ],[
-                "ownerStoragePriceModels" => explode(',',$params["owner_storage_price_model_id"])
-            ]);
-            $msg = "成功创建“".$owner->name."”项目!";
-            LogService::log(__METHOD__,"客户管理-增加货主",json_encode($params,JSON_UNESCAPED_UNICODE));
-        }
-        return response()->redirectTo('customer/project/index')->with('successTip',$msg);
+        $this->gate("客户管理-项目-录入");
+        if (!request("id"))$this->error("项目不存在,无法补充详细信息");
+        $errors = $this->validator(request()->input())->errors();
+        if (count($errors)>0)$this->success(["errors"=>$errors]);
+
+        /** @var Owner $owner */
+        $owner = app('OwnerService')->find(request("id"));
+        if (!$owner)$this->error("项目已被删除,无法操作");
+        $owner = app('OwnerService')->update($owner,[
+            "customer_id"           => request("customer_id"),
+            "warehouse_id"          => request("warehouse_id"),
+            "tax_rate"              => request("tax_rate"),
+            "linkman"               => request("linkman"),
+            "phone_number"          => request("phone_number"),
+            "user_owner_group_id"   => request("owner_group_id"),
+            "waring_line_on"        => request("waring_line_on"),
+            "description"           => request("description"),
+        ]);
+        $this->success($owner);
     }
 
     //获取货主下所有相关计费模型
@@ -214,10 +196,17 @@ class CustomerController extends Controller
         if(!Gate::allows('客户管理-项目-编辑')){ return redirect('denied');  }
         /** @var Owner $owner */
         $owner = app('OwnerService')->find($id);
+        $owner->loadCount(["ownerStoragePriceModels","ownerPriceOperations","ownerPriceExpresses","ownerPriceLogistics","ownerPriceDirectLogistics"]);
+        $isExist = false;
+        if($owner->owner_storage_price_models_count ||
+            $owner->owner_price_operations_count ||
+            $owner->owner_price_expresses_count ||
+            $owner->owner_price_logistics_count ||
+            $owner->owner_price_direct_logistics_count) $isExist = true;
         $customers = app('CustomerService')->getSelection();
         $ownerGroups = app('UserOwnerGroupService')->getSelection();
-        $storagePriceModels = app('OwnerStoragePriceModelService')->getSelection(["id","counting_type","using_type","minimum_area","price","unit_id"],["unit:id,name"]);
-        return response()->view('customer.project.create',compact("customers","ownerGroups","storagePriceModels",'owner'));
+        $warehouses = app('WarehouseService')->getSelection();
+        return response()->view('customer.project.create',compact("customers","ownerGroups","warehouses",'owner',"isExist"));
     }
 
     public function projectArea(Request $request)
@@ -400,23 +389,21 @@ class CustomerController extends Controller
     }
 
     private function validator(array $params){
-        $id = $params['id'] ?? null;
         $validator=Validator::make($params,[
-            'id' => ['sometimes','required_without_all:code,name'],
-            'code'=>['sometimes','required','max:50',$id ? "unique:owners,code,$id":'unique:owners,code'],
-            'name'=>['sometimes','required','max:50'],
-            'customer_id'=>['sometimes','required'],
-            'owner_group_id'=>['sometimes','required'],
-            'tax_rate' => ['sometimes',"nullable",'numeric'],
-            'waring_line_on' => ['sometimes',"nullable",'integer'],
+            'id' => ['required'],
+            'customer_id'=>['required'],
+            'owner_group_id'=>['required'],
+            'warehouse_id'=>['required'],
+            'tax_rate' => ["nullable",'numeric'],
+            'waring_line_on' => ["nullable",'integer'],
         ],[
             'required'=>':attribute 为必填项',
-            'unique'=>':attribute 已存在',
             'integer'=>':attribute 必须为整数',
             'numeric'=>':attribute 必须为数字',
         ],[
             'code'=>'项目代码',
             'name'=>'项目名称',
+            'warehouse_id'=>'仓库',
             'customer_id'=>'客户',
             'owner_group_id'=>'工作组',
             'tax_rate' => '税率',

+ 34 - 6
app/Http/Controllers/OwnerController.php

@@ -3,6 +3,7 @@
 namespace App\Http\Controllers;
 
 use App\Authority;
+use App\Components\AsyncResponse;
 use App\Events\CustomerStored;
 use App\Log;
 use App\Logistic;
@@ -16,6 +17,8 @@ use Illuminate\Support\Facades\Validator;
 
 class OwnerController extends Controller
 {
+    use AsyncResponse;
+
     /**
      * Display a listing of the resource.
      *
@@ -47,12 +50,6 @@ class OwnerController extends Controller
         return view('maintenance.owner.create');
     }
 
-    /**
-     * Store a newly created resource in storage.
-     *
-     * @param Request $request
-     * @return string
-     */
     public function store(Request $request)
     {
         if (!Gate::allows('货主-录入')) {
@@ -74,11 +71,39 @@ class OwnerController extends Controller
         return redirect('maintenance/owner/create')->with('successTip', $request->input('name') ?? '');
     }
 
+    public function apiStore()
+    {
+        $this->gate("货主-录入");
+
+        if (request("id"))$errors = $this->validatorUpdate(request()->input(),request("id"))->errors();
+        else $errors = $this->validatorCreate(request()->input())->errors();
+        if (count($errors)>0)$this->success(["errors"=>$errors]);
+
+        if (request("id")){
+            $owner = app("OwnerService")->find(request("id"));
+            if (!$owner)$this->error("项目已被删除");
+            if ($owner->name == request("name") && $owner->code == request("code"))
+                $this->success($owner);
+            $owner = app("OwnerService")->update($owner,[
+                "name" => request("name"),
+                "code" => request("code"),
+            ]);
+        }else $owner = app("OwnerService")->create([
+            "name" => request("name"),
+            "code" => request("code"),
+        ]);
+
+        $this->success($owner);
+    }
+
     protected function validatorCreate(array $data)
     {
         return Validator::make($data, [
             'code' => ['required', 'string', 'max:50', "unique:owners,code"],
             'name' => ['required', 'string', 'max:50'],
+        ],[],[
+            "code" => "货主代码",
+            "name" => "货主名称",
         ]);
     }
 
@@ -87,6 +112,9 @@ class OwnerController extends Controller
         return Validator::make($data, [
             'name' => ['required', 'string', 'max:50'],
             'code' => ['required', 'string', 'max:50', "unique:owners,code,$id"]
+        ],[],[
+            "code" => "货主代码",
+            "name" => "货主名称",
         ]);
     }
 

+ 547 - 79
app/Http/Controllers/PriceModelController.php

@@ -8,21 +8,26 @@ use App\Imports\OwnerPriceDirectLogisticDetailImport;
 use App\Imports\OwnerPriceLogisticDetailImport;
 use App\Owner;
 use App\OwnerPriceDirectLogistic;
+use App\OwnerPriceDirectLogisticCar;
 use App\OwnerPriceExpress;
 use App\OwnerPriceExpressProvince;
 use App\OwnerPriceLogistic;
+use App\OwnerPriceLogisticDetail;
 use App\OwnerPriceOperation;
-use App\OwnerPriceOperationItemOut;
+use App\OwnerPriceOperationItem;
+use App\OwnerStoragePriceModel;
+use App\Services\common\BatchUpdateService;
 use App\Services\common\ExportService;
 use App\Services\LogService;
-use App\Services\OwnerOutStorageRuleService;
+use App\Services\OwnerPriceOperationItemService;
 use App\Services\OwnerPriceOperationService;
 use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Database\Eloquent\Collection;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Gate;
 use Illuminate\Support\Facades\Validator;
-use Illuminate\Validation\Rule;
 use Maatwebsite\Excel\Facades\Excel;
 
 class PriceModelController extends Controller
@@ -64,6 +69,7 @@ class PriceModelController extends Controller
         if(!Gate::allows('计费模型-仓储-编辑')){ return redirect('denied');  }
         app('OwnerStoragePriceModelService')->update(["id"=>$request->input("id")],[
             "counting_type" => $request->input("counting_type"),
+            "name"          => $request->input("name"),
             "using_type"    => $request->input("using_type"),
             "minimum_area"  => $request->input("minimum_area"),
             "price"         => $request->input("price"),
@@ -85,6 +91,7 @@ class PriceModelController extends Controller
     private function storageValidator(array $params)
     {
         return Validator::make($params,[
+            'name'=>['required'],
             'counting_type'=>['required'],
             'using_type'=>['required'],
             'minimum_area'=>['nullable','numeric','min:0'],
@@ -97,6 +104,7 @@ class PriceModelController extends Controller
             'min'=>':attribute 不得小于0',
             'integer'=>':attribute 未选择',
         ],[
+            'name'          =>"名称",
             'counting_type' =>"计费类型",
             'using_type'    =>"用仓类型",
             'minimum_area'  =>"最低起租面积",
@@ -111,26 +119,26 @@ class PriceModelController extends Controller
         if(!Gate::allows('计费模型-作业-查询')){ return redirect('denied');  }
         $features = app("FeatureService")->getMapArray();
         OwnerPriceOperation::$features = $features;
-        $models = app('OwnerPriceOperationService')->paginate($request->input(),["ownerPriceOperationOwners","ownerInStorageRule"=>function($query){$query->with("unit");}])->append("featureFormat");
+        $models = app('OwnerPriceOperationService')->paginate($request->input(),["ownerPriceOperationOwners","items.unit"])->append("featureFormat");
         $owners = app("OwnerService")->getIntersectPermitting();
         return response()->view('maintenance.priceModel.operation.index',compact("models","owners"));
     }
 
     /* 获取出库模型规则 */
-    public function operationGetOutStorageRule(Request $request)
+    public function getItems(Request $request)
     {
         if(!Gate::allows('计费模型-作业-查询')){ return ["success"=>false,"data"=>"无权操作"];  }
-        /** @var OwnerOutStorageRuleService $service */
-        $service = app('OwnerOutStorageRuleService');
-        $ownerOutStorageRules = $service->get(["owner_price_operation_id"=>$request->input("id")],["unit"],true)->append("featureFormat");
-        return ["success"=>true,"data"=>$ownerOutStorageRules];
+        /** @var OwnerPriceOperationItemService $service */
+        $service = app('OwnerPriceOperationItemService');
+        $items = $service->get(["owner_price_operation_id"=>$request->input("id")],["unit"],true)->append("featureFormat");
+        return ["success"=>true,"data"=>$items];
     }
-    /* 修改出库模型规则 */
-    public function updateOutStorageRule(Request $request)
+    /* 修改规则 */
+    public function updateItem(Request $request)
     {
         if(!Gate::allows('计费模型-作业-编辑')){ return ["success"=>false,"data"=>"无权操作"];  }
-        /** @var OwnerOutStorageRuleService $service */
-        $service = app('OwnerOutStorageRuleService');
+        /** @var OwnerPriceOperationItemService $service */
+        $service = app('OwnerPriceOperationItemService');
         $row = $service->update(["id"=>$request->input("id")],[
             "amount"=>$request->input("amount"),
             "unit_id"=>$request->input("unit_id"),
@@ -143,11 +151,11 @@ class PriceModelController extends Controller
         return ["success"=>false,"data"=>"受影响数据数为:".$row];
     }
 
-    public function createOutStorageRule(Request $request)
+    public function createItem(Request $request)
     {
         if(!Gate::allows('计费模型-作业-编辑')){ return ["success"=>false,"data"=>"无权操作"];  }
-        /** @var OwnerOutStorageRuleService $service */
-        $service = app('OwnerOutStorageRuleService');
+        /** @var OwnerPriceOperationItemService $service */
+        $service = app('OwnerPriceOperationItemService');
         switch ($request->input("strategy")){
             case "起步":
                 $c = $service->isExist(["owner_price_operation_id"=>$request->input("owner_price_operation_id"),"strategy"=>"起步"]);
@@ -159,7 +167,6 @@ class PriceModelController extends Controller
                 break;
         }
         $data = $service->create($request->input());
-        LogService::log(__METHOD__,"计费模型-录入出库规则",json_encode($request->input()));
         $data->load("unit");
         return ["success"=>true,"data"=>$data];
     }
@@ -186,11 +193,11 @@ class PriceModelController extends Controller
             }
         }
         if (count($stack) > 0)return ["success"=>false,"data"=>"组标记错误,起始与结束标记必须对应"];
-        $row = app('OwnerOutStorageRuleService')->update(["id"=>$id],["feature"=>$feature]);
+        $row = app('OwnerPriceOperationItemService')->update(["id"=>$id],["feature"=>$feature]);
         if ($row != 1)return ["success"=>false,"data"=>"影响了“".$row."”行"];
         LogService::log(__METHOD__,"计费模型-修改出库特征",json_encode($request->input()));
-        OwnerPriceOperationItemOut::$features = $result["map"];
-        $rule = app('OwnerOutStorageRuleService')->find($id)->append("featureFormat");
+        OwnerPriceOperationItem::$features = $result["map"];
+        $rule = app('OwnerPriceOperationItemService')->find($id)->append("featureFormat");
         return ["success"=>true,"data"=>["featureFormat"=>$rule->featureFormat,"feature"=>$feature]];
     }
 
@@ -235,7 +242,7 @@ class PriceModelController extends Controller
     public function operationStore(Request $request)
     {
         if(!Gate::allows('计费模型-作业-录入')){ return redirect('denied');  }
-        $request->offsetSet("rules",json_decode($request->input("rules"),true));
+        $request->offsetSet("items",json_decode($request->input("items"),true));
         $request->offsetSet("owner_id",explode(',',$request->input("owner_id")));
         $this->operationValidator($request->input())->validate();
 
@@ -251,27 +258,19 @@ class PriceModelController extends Controller
             "feature" => $request->input("feature"),
         ]);
         //录入子表
-        if ($request->input("operation_type") == '入库') $service->insertRule([
-            "owner_price_operation_id" => $ownerPriceOperation->id,
-            "amount" => $request->input("rules")[0]["amount"],
-            "unit_id" => $request->input("rules")[0]["unit_id"],
-            "unit_price" => $request->input("rules")[0]["unit_price"],
-        ],"入库");
-        else{
-            $insert = [];
-            foreach ($request->input("rules") as $rule){
-                $insert[] = [
-                    "owner_price_operation_id" => $ownerPriceOperation->id,
-                    "amount" => $rule["amount"],
-                    "unit_id" => $rule["unit_id"],
-                    "unit_price" => $rule["unit_price"],
-                    "strategy" => $rule["strategy"],
-                    "feature" => $rule["feature"],
-                    "priority" => $rule["priority"],
-                ];
-            }
-            $service->insertRule($insert);
+        $insert = [];
+        foreach ($request->input("items") as $rule){
+            $insert[] = [
+                "owner_price_operation_id" => $ownerPriceOperation->id,
+                "amount" => $rule["amount"],
+                "unit_id" => $rule["unit_id"],
+                "unit_price" => $rule["unit_price"],
+                "strategy" => $rule["strategy"],
+                "feature" => $rule["feature"],
+                "priority" => $rule["priority"],
+            ];
         }
+        $service->insertItem($insert);
         //录入中间表
         /** @var OwnerPriceOperation $ownerPriceOperation */
         if ($request->input("owner_id"))$ownerPriceOperation->ownerPriceOperationOwners()->sync($request->input("owner_id"));
@@ -282,7 +281,7 @@ class PriceModelController extends Controller
     public function operationEdit($id)
     {
         if(!Gate::allows('计费模型-作业-编辑')){ return redirect('denied');  }
-        $model = app('OwnerPriceOperationService')->find($id,true,["ownerPriceOperationOwners"]);
+        $model = app('OwnerPriceOperationService')->find($id,["items"]);
         $owners = app("OwnerService")->getIntersectPermitting();
         $units = app('UnitService')->getSelection();
         return response()->view('maintenance.priceModel.operation.create',compact("owners","units","model"));
@@ -291,7 +290,7 @@ class PriceModelController extends Controller
     public function operationUpdate($id,Request $request)
     {
         if(!Gate::allows('计费模型-作业-编辑')){ return redirect('denied');  }
-        $request->offsetSet("rules",json_decode($request->input("rules"),true));
+        $request->offsetSet("items",json_decode($request->input("items"),true));
         $request->offsetSet("owner_id",explode(',',$request->input("owner_id")));
         $this->operationValidator($request->input(),$id)->validate();
 
@@ -305,29 +304,21 @@ class PriceModelController extends Controller
             "remark" => $request->input("remark"),
             "feature" => $request->input("feature"),
         ]);
-        $service->destroyRule($id, $model->operation_type);
+        $service->destroyItem($id);
         //录入子表
-        if ($request->input("operation_type") == '入库') $service->insertRule([
-            "owner_price_operation_id" => $model->id,
-            "amount" => $request->input("rules")[0]["amount"],
-            "unit_id" => $request->input("rules")[0]["unit_id"],
-            "unit_price" => $request->input("rules")[0]["unit_price"],
-        ],"入库");
-        else{
-            $insert = [];
-            foreach ($request->input("rules") as $rule){
-                $insert[] = [
-                    "owner_price_operation_id" => $model->id,
-                    "amount" => $rule["amount"],
-                    "unit_id" => $rule["unit_id"],
-                    "unit_price" => $rule["unit_price"],
-                    "strategy" => $rule["strategy"],
-                    "feature" => $rule["feature"],
-                    "priority" => $rule["priority"],
-                ];
-            }
-            $service->insertRule($insert);
+        $insert = [];
+        foreach ($request->input("items") as $rule){
+            $insert[] = [
+                "owner_price_operation_id" => $model->id,
+                "amount" => $rule["amount"],
+                "unit_id" => $rule["unit_id"],
+                "unit_price" => $rule["unit_price"],
+                "strategy" => $rule["strategy"],
+                "feature" => $rule["feature"],
+                "priority" => $rule["priority"],
+            ];
         }
+        $service->insertItem($insert);
         //录入中间表
         /** @var OwnerPriceOperation $model */
         if ($request->input("owner_id"))$model->ownerPriceOperationOwners()->sync($request->input("owner_id"));
@@ -338,7 +329,6 @@ class PriceModelController extends Controller
     private function operationValidator(array $params, $id= null)
     {
         return Validator::make($params,[
-            //required_with:id
             'operation_type'=>['required'],
             'owner_id'=>[function ($attribute, $value, $fail)use($params,$id) {
                 if ($params["strategy"] == '默认'){
@@ -355,15 +345,11 @@ class PriceModelController extends Controller
             }],
             'strategy'=>['required'],
             'name'=>['required',$id?"unique:owner_price_operations,name,$id":'unique:owner_price_operations,name'],
-            'priority'=>['required','integer','min:0','max:100'],
-            'rules.*.strategy'=>['required_if:operation_type,出库'],
-            'rules.*.amount'=>[Rule::requiredIf(function () use ($params) {
-                if ("operation_type" == "入库")return true;
-                return false;
-            }),"integer"],
-            'rules.*.unit_id'=>['required','integer'],
-            'rules.*.unit_price'=>['required','numeric',"min:0"],
-            'rules.*.priority'=>['required_if:operation_type,出库','integer','min:0','max:100'],
+            'priority'=>['sometimes','required','integer','min:0','max:100'],
+            'items.*.strategy'=>['required'],
+            'items.*.amount'=>["required","integer"],
+            'items.*.unit_id'=>['required','integer'],
+            'items.*.unit_price'=>['required','numeric',"min:0"],
         ],[
             'required'=>':attribute 为必填项',
             'min'=>':attribute 不得小于0',
@@ -375,7 +361,6 @@ class PriceModelController extends Controller
             'operation_type' =>"操作类型",
             'strategy'    =>"计费策略",
             'name'  =>"名称",
-            'priority' =>"优先级",
         ]);
     }
 
@@ -511,21 +496,28 @@ class PriceModelController extends Controller
             'name'=>['required',$id?"unique:owner_price_expresses,name,$id":'unique:owner_price_expresses,name'],
             'initial_weight'=>['required','numeric','min:0'],
             'additional_weight'=>['required','numeric','min:0'],
-            'owner_id'=>[function ($attribute, $value, $fail)use($id) {
-                $owners = app("OwnerPriceExpressService")->getExistOwnerName($value,$id);
+            'owner_id'=>[function ($attribute, $value, $fail)use($id,$params) {
+                $owners = app("OwnerPriceExpressService")->getExistOwnerName($value,$params["logistic_id"] ?? [],$id);
                 if ($owners)$fail("(".implode(',',$owners).') 已经绑定计费模型');
             }],
-            'logistic_id'=>[function ($attribute, $value, $fail)use($id) {
+            /*'logistic_id'=>[function ($attribute, $value, $fail)use($id) {
                 $logistics = app("OwnerPriceExpressService")->getExistLogisticName($value,$id);
                 if ($logistics)$fail("(".implode(',',$logistics).') 已经绑定计费模型');
-            }],
+            }],*/
+            'items.*.province_id'=>['sometimes','required'],
+            'items.*.additional_weight_price'=>['sometimes','required','numeric',"min:0"],
+            'items.*.initial_weight_price'=>['sometimes','required','numeric',"min:0"],
         ],[
             'required'=>':attribute 为必填项',
             'unique' => ':attribute 已存在',
+            'min' => ':attribute 不得小于0',
         ],[
             'name' =>"名称",
             'initial_weight'  =>"首重",
             'additional_weight'  =>"续重",
+            "items.*.province_id"=>"省份",
+            "items.*.additional_weight_price"=>"首重价格",
+            "items.*.initial_weight_price"=>"续重价格",
         ]);
     }
 
@@ -797,6 +789,19 @@ class PriceModelController extends Controller
                 $bool = app("OwnerPriceLogisticService")->checkRange($value);
                 if (!$bool)$fail("格式错误,值必须为连续的且最后一个值不允许封闭");
             }],
+            'owner_id'=>[function ($attribute, $value, $fail)use($id,$params) {
+                $owners = app("OwnerPriceExpressService")->getExistOwnerName($value,$params["logistic_id"] ?? [],$id,"ownerPriceLogistics");
+                if ($owners)$fail("(".implode(',',$owners).') 已经绑定计费模型');
+            }],
+            'items.*.unit_id'=>['sometimes','required'],
+            'items.*.range'=>['sometimes','required'],
+            'items.*.province_id'=>['sometimes','required'],
+            'items.*.city_id'=>['sometimes','required'],
+            'items.*.unit_price'=>['sometimes','nullable','numeric',"min:0"],
+            'items.*.delivery_fee'=>['sometimes','nullable','numeric',"min:0"],
+            'items.*.initial_fee'=>['sometimes','nullable','numeric',"min:0"],
+            'items.*.initial_amount'=>['sometimes','nullable','numeric',"min:0"],
+            'items.*.rate'=>['sometimes','nullable','numeric',"min:0"],
         ],[
             'required'=>':attribute 为必填项',
             'unique' => ':attribute 已存在',
@@ -811,6 +816,15 @@ class PriceModelController extends Controller
             'unit_range'  =>"区间值",
             'other_unit_id'  =>"单位二",
             'other_unit_range'  =>"区间值",
+            'items.*.unit_id'=>"单位",
+            'items.*.range'=>"区间",
+            'items.*.province_id'=>"省份",
+            'items.*.city_id'=>"城市",
+            'items.*.unit_price'=>"单价",
+            'items.*.delivery_fee'=>"送货费",
+            'items.*.initial_fee'=>"起始计费",
+            'items.*.initial_amount'=>"起始计数",
+            'items.*.rate'=>"费率",
         ]);
     }
 
@@ -969,4 +983,458 @@ class PriceModelController extends Controller
         ]);
     }
 
+    public function apiStoreStorage()
+    {
+        $this->gate("客户管理-项目-录入");
+        $errors = $this->storageValidator(request()->input())->errors();
+        if (count($errors)>0)$this->success(["errors"=>$errors]);
+
+        if (!request("owner_id"))$this->error("参数传递错误");
+        $values = [
+            "name"              => request("name"),
+            "counting_type"     => request("counting_type"),
+            "using_type"        => request("using_type"),
+            "minimum_area"      => request("minimum_area"),
+            "price"             => request("price"),
+            "discount_type"     => request("discount_type"),
+            "discount_value"    => request("discount_value"),
+            "unit_id"           => request("unit_id"),
+        ];
+        if (request("id"))app('OwnerStoragePriceModelService')->update(["id"=>request("id")],$values);
+        else{
+            DB::transaction(function ()use(&$model,$values){
+                $model = app('OwnerStoragePriceModelService')->create($values);
+                DB::insert(DB::raw("INSERT INTO owner_storage_price_model_owner VALUES(?,?)"),[$model->id,request("owner_id")]);
+                DB::commit();
+            });
+            $this->success($model->id);
+        }
+        $this->success();
+    }
+
+    public function apiStoreOperation()
+    {
+        $this->gate("客户管理-项目-录入");
+
+        $params = request()->input();
+        if (request("operation_type") == '入库'){
+            foreach ($params["items"] as $index => $it){
+                if (!$it || $it['strategy'] == '起步'){
+                    unset($params["items"][$index]);
+                    break;
+                }
+            }
+        }
+
+        $params["owner_id"] = [$params["owner_id"]];
+        $errors = $this->operationValidator($params,request("id"))->errors();
+        if (count($errors)>0)$this->success(["errors"=>$errors]);
+
+        if (!request("owner_id"))$this->error("参数传递错误");
+        if (request("id")){
+            $model = app('OwnerPriceOperationService')->find(request("id"),["items"]);
+            app('OwnerPriceOperationService')->findUpdate($model,[
+                "name"              => request("name"),
+                "operation_type"    => request("operation_type"),
+                "strategy"          => request("strategy"),
+                "feature"           => request("feature"),
+                "remark"            => request("remark"),
+            ]);
+            $delete = [];//需要删除子项
+            $update = [["id","strategy","amount","unit_id","unit_price","feature"]];//需要更新子项
+            $insert = [];//需要新增子项
+            foreach ($params["items"] as $item){
+                $obj = [
+                    "strategy"  => $item["strategy"],
+                    "amount"    => $item["amount"],
+                    "unit_id"   => $item["unit_id"],
+                    "unit_price"=> $item["unit_price"],
+                    "feature"   => $item["feature"],
+                ];
+                if (isset($item["id"])){
+                    $obj["id"] = $item["id"];
+                    $update[] = $obj;
+                    $delete[] = $item["id"];
+                } else{
+                    $obj["owner_price_operation_id"] = $model->id;
+                    $obj["feature"] = $item["feature"] ?? null;
+                    $insert[] = $obj;
+                }
+            }
+            $ids = array_column($model->items->toArray(),"id");
+            $delete = array_diff($ids,$delete);
+            if ($delete)app("OwnerPriceOperationItemService")->destroy($delete);
+            if (count($update) > 1)app(BatchUpdateService::class)->batchUpdate("owner_price_operation_items",$update);
+            if ($insert)app("OwnerPriceOperationItemService")->insert($insert);
+        }else{
+            DB::transaction(function ()use(&$model,$params){
+                $model = app('OwnerPriceOperationService')->create([
+                    "name"              => request("name"),
+                    "operation_type"    => request("operation_type"),
+                    "strategy"          => request("strategy"),
+                    "feature"           => request("feature"),
+                    "remark"            => request("remark"),
+                ]);
+                foreach ($params["items"] as &$item){
+                    $item["owner_price_operation_id"] = $model->id;
+                    if (!isset($item["feature"]))$item["feature"] = null;
+                    unset($item["features"]);
+                    unset($item["featureFormat"]);
+                }
+                app("OwnerPriceOperationItemService")->insert($params["items"]);
+                DB::insert(DB::raw("INSERT INTO owner_price_operation_owner VALUES(?,?)"),[$model->id,request("owner_id")]);
+                DB::commit();
+            });
+        }
+        /** @var OwnerPriceOperation $model */
+        $model->load("items");
+        $this->success($model);
+    }
+
+    public function apiStoreExpress()
+    {
+        $this->gate("客户管理-项目-录入");
+        $params = request()->input();
+        $params["logistic_id"] = $params["logistics"];
+        $errors = $this->expressValidator($params)->errors();
+        $exist = [];
+        foreach ($params["items"] as $index => $item){
+            if (isset($exist[$item["province_id"]]))$errors["items.".$index.".province_id"] = ["已存在"];
+            else $exist[$item["province_id"]] = true;
+        }
+        if (count($errors)>0)$this->success(["errors"=>$errors]);
+
+        DB::transaction(function ()use(&$model,$params){
+            $model = app('OwnerPriceExpressService')->create([
+                "name"              => request("name"),
+                "initial_weight"    => request("initial_weight"),
+                "additional_weight" => request("additional_weight"),
+            ]);
+            foreach ($params["items"] as &$item)$item["owner_price_express_id"] = $model->id;
+            OwnerPriceExpressProvince::query()->insert($params["items"]);
+            DB::insert(DB::raw("INSERT INTO owner_price_express_owner VALUES(?,?)"),[$model->id,request("owner_id")]);
+            /** @var OwnerPriceExpress $model */
+            $model->logistics()->syncWithoutDetaching(request("logistics"));
+            DB::commit();
+        });
+        $model->load("details");
+        $this->success($model);
+    }
+
+    public function apiStoreLogistic()
+    {
+        $this->gate("客户管理-项目-录入");
+        $params = request()->input();
+        $params["owner_id"] = [$params["owner_id"]];
+        $params["logistic_id"] = $params["logistics"];
+        $errors = $this->logisticValidator($params)->errors();
+        $exist = [];
+        foreach ($params["items"] as $index => $item){
+            $key = $item["unit_id"]."-".$item["range"]."-".$item["province_id"]."-".$item["city_id"];
+            if (isset($exist[$key]))$errors["items.".$index.".unit_id"] = ["该条已存在"];
+            else $exist[$key] = true;
+        }
+        if (count($errors)>0)$this->success(["errors"=>$errors]);
+        DB::transaction(function ()use(&$model,$params){
+            $model = app("OwnerPriceLogisticService")->create([
+                "name"              => request('name'),
+                "unit_range"        => request('unit_range'),
+                "unit_id"           => request('unit_id'),
+                "other_unit_range"  => request('other_unit_range'),
+                "other_unit_id"     => request('other_unit_id'),
+                "pick_up_price"     => request('pick_up_price'),
+                "fuel_price"        => request('fuel_price'),
+                "service_price"     => request('service_price'),
+            ]);
+            foreach ($params["items"] as &$param)$param["owner_price_logistic_id"] = $model->id;
+            OwnerPriceLogisticDetail::query()->insert($params["items"]);
+            DB::insert(DB::raw("INSERT INTO owner_price_logistic_owner VALUES(?,?)"),[$model->id,request("owner_id")]);
+            /** @var OwnerPriceLogistic $model */
+            $model->logistics()->syncWithoutDetaching(request("logistics"));
+            DB::commit();
+        });
+        $model->load("details");
+        $this->success($model);
+    }
+
+    public function apiStoreDirectLogistic()
+    {
+        $this->gate("客户管理-项目-录入");
+        $errors = $this->directLogisticValidator(request()->input())->errors();
+        $exist = [];
+        foreach (request("items") as $index=>$item){
+            if (isset($exist[$item['car_type_id']]))$errors["items.".$index.".car_type_id"] = ["已存在"];
+            else $exist[$item['car_type_id']] = true;
+        }
+        if (count($errors)>0)$this->success(["errors"=>$errors]);
+
+        $items = request()->input("items");
+        DB::transaction(function ()use(&$model,$items){
+            $model = app("OwnerPriceDirectLogisticService")->create([
+                "name"      => request("name"),
+                "base_km"   => request("base_km"),
+            ]);
+            foreach ($items as &$item)$item["owner_price_direct_logistic_id"] = $model->id;
+            OwnerPriceDirectLogisticCar::query()->insert($items);
+            DB::insert(DB::raw("INSERT INTO owner_price_direct_logistic_owner VALUES(?,?)"),[$model->id,request("owner_id")]);
+            DB::commit();
+        });
+        $model->load("details");
+        $this->success($model);
+    }
+
+    public function getPriceModel()
+    {
+        $owner = new Owner();
+        $owner->id = request("id");
+        $owner->load(["ownerStoragePriceModels","ownerPriceOperations.items","ownerPriceExpresses"=>function($query){
+            /** @var Builder $query */
+            $query->with(["details","logistics"]);
+        },"ownerPriceLogistics"=>function($query){
+            /** @var Builder $query */
+            $query->with(["details","logistics"]);
+        },"ownerPriceDirectLogistics.details"]);
+        $features = app("FeatureService")->getMapArray();
+        OwnerPriceOperation::$features = $features;
+        OwnerPriceOperationItem::$features = $features;
+        foreach ($owner->ownerPriceOperations as &$operation){
+            $operation["featureFormat"] = $operation->featureFormat;
+            foreach ($operation->items as &$item){
+                $item["featureFormat"] = $item->featureFormat;
+            }
+        }
+        $this->success($owner);
+    }
+
+    public function apiGetStorage()
+    {
+        $this->gate("客户管理-项目-录入");
+        $models = OwnerStoragePriceModel::query();
+        if (request("customer_id")){
+            $customerId = request("customer_id");
+            $models->whereHas("owners",function ($query)use($customerId){
+                /** @var Builder $query */
+                $query->where("customer_id",$customerId);
+            });
+        }
+        if (request("owner_id")){
+            $ownerId = request("owner_id");
+            $models->whereHas("owners",function ($query)use($ownerId){
+                /** @var Builder $query */
+                $query->where("id",$ownerId);
+            });
+        }
+        if (request("name")){
+            $models->where("name","like","%".request("name")."%");
+        }
+        $this->success($models->get());
+    }
+    public function apiGetOperation()
+    {
+        $this->gate("客户管理-项目-录入");
+        $models = OwnerPriceOperation::query()->with("items");
+        if (request("customer_id")){
+            $customerId = request("customer_id");
+            $models->whereHas("ownerPriceOperationOwners",function ($query)use($customerId){
+                /** @var Builder $query */
+                $query->where("customer_id",$customerId);
+            });
+        }
+        if (request("owner_id")){
+            $ownerId = request("owner_id");
+            $models->whereHas("ownerPriceOperationOwners",function ($query)use($ownerId){
+                /** @var Builder $query */
+                $query->where("id",$ownerId);
+            });
+        }
+        if (request("name")){
+            $models->where("name","like","%".request("name")."%");
+        }
+        $features = app("FeatureService")->getMapArray();
+        OwnerPriceOperation::$features = $features;
+        OwnerPriceOperationItem::$features = $features;
+        $models = $models->get();
+        foreach ($models as &$operation){
+            $operation["featureFormat"] = $operation->featureFormat;
+            $items = [[],[]];
+            foreach ($operation->items as $item){
+                $obj = [
+                    "strategy" => $item["strategy"],
+                    "amount" => $item["amount"],
+                    "unit_id" => $item["unit_id"],
+                    "unit_price" => $item["unit_price"],
+                    "feature" => $item["feature"],
+                    "featureFormat" => $item->featureFormat,
+                ];
+                if ($item["strategy"] == '起步')$items[0] = $obj;
+                if ($item["strategy"] == '默认')$items[1] = $obj;
+                if ($item["strategy"] == '特征')$items[] = $obj;
+            }
+            if (!$items[0])$items[0] = [
+                "strategy" => "起步",
+                "amount" => "",
+                "unit_id" => "",
+                "unit_price" => "",
+                "feature" => "",
+            ];
+            if (!$items[1])$items[1] = [
+                "strategy" => "默认",
+                "amount" => "",
+                "unit_id" => "",
+                "unit_price" => "",
+                "feature" => "",
+            ];
+            unset($operation["items"]);
+            $operation["items"] = $items;
+        }
+        $this->success($models);
+    }
+    public function apiGetExpress()
+    {
+        $this->gate("客户管理-项目-录入");
+        $models = OwnerPriceExpress::query()->with(["details","logistics:id"]);
+        if (request("customer_id")){
+            $customerId = request("customer_id");
+            $models->whereHas("owners",function ($query)use($customerId){
+                /** @var Builder $query */
+                $query->where("customer_id",$customerId);
+            });
+        }
+        if (request("owner_id")){
+            $ownerId = request("owner_id");
+            $models->whereHas("owners",function ($query)use($ownerId){
+                /** @var Builder $query */
+                $query->where("id",$ownerId);
+            });
+        }
+        if (request("logistic_id")){
+            $logisticId = request("logistic_id");
+            $models->whereHas("logistics",function ($query)use($logisticId){
+                /** @var Builder $query */
+                $query->where("id",$logisticId);
+            });
+        }
+        if (request("name")){
+            $models->where("name","like","%".request("name")."%");
+        }
+        $this->success($models->get());
+    }
+    public function apiGetLogistic()
+    {
+        $this->gate("客户管理-项目-录入");
+        $models = OwnerPriceLogistic::query()->with(["details","logistics"]);
+        if (request("customer_id")){
+            $customerId = request("customer_id");
+            $models->whereHas("owners",function ($query)use($customerId){
+                /** @var Builder $query */
+                $query->where("customer_id",$customerId);
+            });
+        }
+        if (request("owner_id")){
+            $ownerId = request("owner_id");
+            $models->whereHas("owners",function ($query)use($ownerId){
+                /** @var Builder $query */
+                $query->where("id",$ownerId);
+            });
+        }
+        if (request("logistic_id")){
+            $logisticId = request("logistic_id");
+            $models->whereHas("logistics",function ($query)use($logisticId){
+                /** @var Builder $query */
+                $query->where("id",$logisticId);
+            });
+        }
+        if (request("name")){
+            $models->where("name","like","%".request("name")."%");
+        }
+        $this->success($models->get());
+    }
+    public function apiGetDirectLogistic()
+    {
+        $this->gate("客户管理-项目-录入");
+        $models = OwnerPriceDirectLogistic::query()->with("details");
+        if (request("customer_id")){
+            $customerId = request("customer_id");
+            $models->whereHas("owners",function ($query)use($customerId){
+                /** @var Builder $query */
+                $query->where("customer_id",$customerId);
+            });
+        }
+        if (request("owner_id")){
+            $ownerId = request("owner_id");
+            $models->whereHas("owners",function ($query)use($ownerId){
+                /** @var Builder $query */
+                $query->where("id",$ownerId);
+            });
+        }
+        if (request("name")){
+            $models->where("name","like","%".request("name")."%");
+        }
+        $this->success($models->get());
+    }
+
+    public function apiDelStorage()
+    {
+        $this->gate("客户管理-项目-录入");
+        if (!request("id"))$this->error("非法参数");
+        app("OwnerStoragePriceModelService")->destroy(request("id"));
+        $this->success();
+    }
+    public function apiDelOperation()
+    {
+        $this->gate("客户管理-项目-录入");
+        if (!request("id"))$this->error("非法参数");
+        app("OwnerPriceOperationService")->destroy(request("id"));
+        $this->success();
+    }
+    public function apiDelOperationItem()
+    {
+        $this->gate("客户管理-项目-录入");
+        if (!request("id"))$this->error("非法参数");
+        app("OwnerPriceOperationItemService")->destroy(request("id"));
+        $this->success();
+    }
+    public function apiDelExpress()
+    {
+        $this->gate("客户管理-项目-录入");
+        if (!request("id"))$this->error("非法参数");
+        app("OwnerPriceExpressService")->destroy(request("id"));
+        $this->success();
+    }
+    public function apiDelExpressItem()
+    {
+        $this->gate("客户管理-项目-录入");
+        if (!request("id"))$this->error("非法参数");
+        app("OwnerPriceExpressService")->destroyDetail(request("id"));
+        $this->success();
+    }
+    public function apiDelLogistic()
+    {
+        $this->gate("客户管理-项目-录入");
+        if (!request("id"))$this->error("非法参数");
+        app("OwnerPriceLogisticService")->destroy(request("id"));
+        $this->success();
+    }
+    public function apiDelLogisticItem()
+    {
+        $this->gate("客户管理-项目-录入");
+        if (!request("id"))$this->error("非法参数");
+        app("OwnerPriceLogisticService")->destroyDetail(request("id"));
+        $this->success();
+    }
+    public function apiDelDirectLogistic()
+    {
+        $this->gate("客户管理-项目-录入");
+        if (!request("id"))$this->error("非法参数");
+        app("OwnerPriceDirectLogisticService")->destroy(request("id"));
+        $this->success();
+    }
+    public function apiDelDirectLogisticItem()
+    {
+        $this->gate("客户管理-项目-录入");
+        if (!request("id"))$this->error("非法参数");
+        app("OwnerPriceDirectLogisticService")->destroyDetail(request("id"));
+        $this->success();
+    }
+
 }

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

@@ -1050,7 +1050,7 @@ class ProcessController extends Controller
                     app('LogService')->log(__METHOD__,"二次加工单录入导入商品数据时添加货主".__FUNCTION__,json_encode($owner),Auth::user()['id']);
                 }
             }
-            $goods = Commodity::query()->with('barcodes')->where('owner_id',$owner->id)//->whereNull('owner_id') TODO 保留,暂时不知为何限定货主为空
+            $goods = Commodity::query()->with('barcodes')->where('owner_id',$owner->id)//->whereNull('owner_id')  保留,暂时不知为何限定货主为空
                 ->where('sku',$commodityData['sku'])->first();
             $commodity_barcodes = [];
             if (!$goods){

+ 3 - 4
app/Http/Controllers/TestController.php

@@ -15,9 +15,6 @@ use App\Console\Commands\CreateOwnerReport;
 use App\Console\Commands\SyncWmsCommoditiesInformation;
 use App\Console\Commands\SyncWMSOrderTask;
 use App\Console\Commands\WasSyncWmsAsnInformation;
-use App\Events\CancelOrder;
-use App\Http\Requests\ForeignHaiRobotic_taskUpdateRequest;
-use App\Http\Requests\TestAaRequest;
 use App\Imports\OrderTrackingImport;
 use App\InventoryAccount;
 use App\LaborReport;
@@ -159,7 +156,9 @@ sql;
     }
     public function zzd()
     {
-        dd(env("DB_HOST"));
+        $a = [1,2,3,4,5];
+        $c = [1,2,3,5,6];
+        dd(array_diff($c,$a));
     }
 
     public function zzd1()

+ 1 - 1
app/Http/Controllers/api/thirdPart/flux/ProcessController.php

@@ -177,7 +177,7 @@ class ProcessController extends Controller
             array_push($commoditiesTem['owner_id'],$owners[$oracleBasSkus[$i]->customerid]);
             if ($oracleBasSkus[$i]->alternate_sku1)$commodityBarCodeData[$oracleBasSkus[$i]->sku."_".$owners[$oracleBasSkus[$i]->customerid]]=["code"=>$oracleBasSkus[$i]->alternate_sku1,"commodity_id"=>'','created_at'=>Carbon::now()];
         }
-        //TODO 保留:根据条码与货主批量二次查找商品
+        //保留:根据条码与货主批量二次查找商品
         if (count($commoditiesData) > 0){
             app('CommodityService')->insert($commoditiesData);
             app('LogService')->log(__METHOD__, 'FLUX二次加工单接口录入商品__' . __FUNCTION__, json_encode($commoditiesData), Auth::user()['id']);

+ 1 - 1
app/Http/Controllers/api/thirdPart/weixin/WxController.php

@@ -2,7 +2,7 @@
 
 namespace App\Http\Controllers\Api\thirdPart\weixin;
 /**
- * TODO::接口路径(微信线上)的需要修改,因为route文件和路径都改成了新的标准
+ * 接口路径(微信线上)的需要修改,因为route文件和路径都改成了新的标准
  */
 use App\Unit;
 use App\User;

+ 1 - 1
app/MeasuringMachine.php

@@ -19,7 +19,7 @@ class MeasuringMachine extends Model
     ];
 
 
-    //TODO 上线下线
+    //上线下线
     public function turnOn(){
         if($this['status']=='在线')return;
         $this['status']='在线';

+ 6 - 1
app/Owner.php

@@ -29,7 +29,8 @@ class Owner extends Model
         "phone_number",         //联系电话
         "user_owner_group_id",  //项目组ID
         "waring_line_on",       //月单量预警
-        "description"           //描述
+        "description",          //描述
+        "warehouse_id"          //仓库ID
     ];
 
     public static function filterAuthorities(){
@@ -102,4 +103,8 @@ class Owner extends Model
     {   //直发车计费
         return $this->belongsToMany(OwnerPriceDirectLogistic::class,"owner_price_direct_logistic_owner","owner_id","owner_price_direct_logistic_id");
     }
+    public function warehouse()
+    {   //仓库
+        return $this->belongsTo(Warehouse::class,"warehouse_id","id");
+    }
 }

+ 3 - 8
app/OwnerPriceOperation.php

@@ -21,17 +21,12 @@ class OwnerPriceOperation extends Model
     public static $features = null;
     public static $columnMapping = null;
 
-
-    public function ownerInStorageRule()
-    {   //入库规则
-        return $this->hasOne(OwnerInStorageRule::class,"owner_price_operation_id","id");
-    }
-    public function ownerOutStorageRules()
+    public function items()
     {   //出库规则
-        return $this->hasMany(OwnerOutStorageRule::class,"owner_price_operation_id","id");
+        return $this->hasMany(OwnerPriceOperationItem::class,"owner_price_operation_id","id");
     }
     public function ownerPriceOperationOwners()
-    {   //货主中间表
+    {   //货主
         return $this->belongsToMany(Owner::class,"owner_price_operation_owner","owner_price_operation_id","owner_id");
     }
 

+ 2 - 2
app/OwnerPriceOperationItemOut.php → app/OwnerPriceOperationItem.php

@@ -6,13 +6,13 @@ use Illuminate\Database\Eloquent\Model;
 
 use App\Traits\LogModelChanging;
 
-class OwnerPriceOperationItemOut extends Model
+class OwnerPriceOperationItem extends Model
 {
     use LogModelChanging;
 
     protected $fillable = [
         "owner_price_operation_id",         //作业计费ID
-        "strategy",                         //出库策略
+        "strategy",                         //策略
         "amount",                           //起步数
         "unit_id",                          //单位ID
         "unit_price",                       //单价

+ 0 - 25
app/OwnerPriceOperationItemIn.php

@@ -1,25 +0,0 @@
-<?php
-
-namespace App;
-
-use Illuminate\Database\Eloquent\Model;
-
-use App\Traits\LogModelChanging;
-
-class OwnerPriceOperationItemIn extends Model
-{
-    use LogModelChanging;
-
-    protected $fillable = [
-        "owner_price_operation_id", //作业计费ID
-        "amount",                   //计量
-        "unit_id",                  //单位ID
-        "unit_price",               //单价
-    ];
-    public $timestamps=false;
-
-    public function unit()
-    {   //单位
-        return $this->hasOne(Unit::class,"id","unit_id");
-    }
-}

+ 5 - 0
app/OwnerStoragePriceModel.php

@@ -11,6 +11,7 @@ class OwnerStoragePriceModel extends Model
     use LogModelChanging;
 
     protected $fillable = [
+        "name",             //名称
         "counting_type",    //计费类型
         "using_type",       //用仓类型
         "minimum_area",     //最低起租面积
@@ -24,4 +25,8 @@ class OwnerStoragePriceModel extends Model
     {   //单位
         return $this->hasOne(Unit::class,"id","unit_id");
     }
+    public function owners()
+    {   //货主
+        return $this->belongsToMany(Owner::class,"owner_storage_price_model_owner","owner_storage_price_model_id","owner_id");
+    }
 }

+ 12 - 13
app/Providers/AppServiceProvider.php

@@ -42,10 +42,10 @@ use App\Services\OrderTrackingService;
 use App\Services\OwnerAreaReportService;
 use App\Services\OwnerBillReportService;
 use App\Services\OwnerFeeDetailService;
-use App\Services\OwnerOutStorageRuleService;
 use App\Services\OwnerPriceDirectLogisticService;
 use App\Services\OwnerPriceExpressService;
 use App\Services\OwnerPriceLogisticService;
+use App\Services\OwnerPriceOperationItemService;
 use App\Services\OwnerPriceOperationService;
 use App\Services\OwnerReportService;
 use App\Services\OwnerService;
@@ -75,7 +75,6 @@ use App\Services\UserService;
 use App\Services\WarehouseService;
 use App\Services\WaybillFinancialService;
 use App\Services\WeighExceptedService;
-use Illuminate\Foundation\Console\ModelMakeCommand;
 use Illuminate\Queue\Events\JobFailed;
 use Illuminate\Support\Facades\Queue;
 use Illuminate\Support\Facades\Schema;
@@ -134,14 +133,16 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('CheckActiveMenuService',CheckActiveMenuService::class);
         app()->singleton('CommodityBarcodeService',CommodityBarcodeService::class);
         app()->singleton('CommodityService', CommodityService::class);
+        app()->singleton('CustomerLogService',CustomerLogService::class);
+        app()->singleton('CustomerLogStatusService',CustomerLogStatusService::class);
         app()->singleton('CustomerService',CustomerService::class);
         app()->singleton('DataHandlerService',DataHandlerService::class);
         app()->singleton('DepositoryService',DepositoryService::class);
         app()->singleton('FeatureService',FeatureService::class);
         app()->singleton('ForeignHaiRoboticsService',ForeignHaiRoboticsService::class);
-        app()->singleton('InventoryDailyLogService',InventoryDailyLogService::class);
         app()->singleton('InventoryAccountMissionService',InventoryAccountMissionService::class);
         app()->singleton('InventoryCompareService',InventoryCompareService::class);
+        app()->singleton('InventoryDailyLogService',InventoryDailyLogService::class);
         app()->singleton('LaborReportsCountingRecordService',LaborReportsCountingRecordService::class);
         app()->singleton('LogService',LogService::class);
         app()->singleton('LogisticService',LogisticService::class);
@@ -151,10 +152,10 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('OracleDocAsnDetailService',OracleDocAsnDetailService::class);
         app()->singleton('OracleDocOrderHeaderService',OracleDOCOrderHeaderService::class);
         app()->singleton('OracleDocWaveDetailService',OracleDocWaveDetailService::class);
-        app()->singleton('OrderIssueProcessLogService',OrderIssueProcessLogService::class);
-        app()->singleton('OrderCommodityService',OrderCommodityService::class);
         app()->singleton('OrderCommodityAssignService',OrderCommodityAssignService::class);
+        app()->singleton('OrderCommodityService',OrderCommodityService::class);
         app()->singleton('OrderIssuePerformanceService',OrderIssuePerformanceService::class);
+        app()->singleton('OrderIssueProcessLogService',OrderIssueProcessLogService::class);
         app()->singleton('OrderIssueService',OrderIssueService::class);
         app()->singleton('OrderIssueWorkLoadService',OrderIssueWorkLoadService::class);
         app()->singleton('OrderPackageCommoditiesService',OrderPackageCommoditiesService::class);
@@ -164,20 +165,20 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('OwnerAreaReportService',OwnerAreaReportService::class);
         app()->singleton('OwnerBillReportService',OwnerBillReportService::class);
         app()->singleton('OwnerFeeDetailService',OwnerFeeDetailService::class);
-        app()->singleton('OwnerOutStorageRuleService',OwnerOutStorageRuleService::class);
+        app()->singleton('OwnerPriceDirectLogisticService',OwnerPriceDirectLogisticService::class);
         app()->singleton('OwnerPriceExpressService',OwnerPriceExpressService::class);
         app()->singleton('OwnerPriceLogisticService',OwnerPriceLogisticService::class);
-        app()->singleton('OwnerPriceDirectLogisticService',OwnerPriceDirectLogisticService::class);
+        app()->singleton('OwnerPriceOperationItemService',OwnerPriceOperationItemService::class);
         app()->singleton('OwnerPriceOperationService',OwnerPriceOperationService::class);
         app()->singleton('OwnerReportService',OwnerReportService::class);
         app()->singleton('OwnerService',OwnerService::class);
         app()->singleton('OwnerStoragePriceModelService',OwnerStoragePriceModelService::class);
-        app()->singleton('PackageStatisticsService',PackageStatisticsService::class);
         app()->singleton('PackageService',PackageService::class);
-        app()->singleton('ProcessesContentService',ProcessesContentService::class);
+        app()->singleton('PackageStatisticsService',PackageStatisticsService::class);
         app()->singleton('ProcessMethodService',ProcessMethodService::class);
         app()->singleton('ProcessService',ProcessService::class);
         app()->singleton('ProcessStatisticService',ProcessStatisticService::class);
+        app()->singleton('ProcessesContentService',ProcessesContentService::class);
         app()->singleton('RealtimePendingOrdersService',RealtimePendingOrdersService::class);
         app()->singleton('RejectedBillItemService',RejectedBillItemService::class);
         app()->singleton('RejectedBillService',RejectedBillService::class);
@@ -186,18 +187,16 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('StationService',StationService::class);
         app()->singleton('StationTaskBatchService',StationTaskBatchService::class);
         app()->singleton('StationTaskBatchTypeService',StationTaskBatchTypeService::class);
-        app()->singleton('StoreCheckingReceiveService',StoreCheckingReceiveService::class);
         app()->singleton('StoreCheckingReceiveItemService',StoreCheckingReceiveItemService::class);
+        app()->singleton('StoreCheckingReceiveService',StoreCheckingReceiveService::class);
         app()->singleton('StoreItemService',StoreItemService::class);
         app()->singleton('StoreService',StoreService::class);
         app()->singleton('UnitService',UnitService::class);
-        app()->singleton('UserService',UserService::class);
         app()->singleton('UserOwnerGroupService',UserOwnerGroupService::class);
+        app()->singleton('UserService',UserService::class);
         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);
     }
 
 

+ 1 - 1
app/RejectedBill.php

@@ -200,7 +200,7 @@ class RejectedBill extends Model
     {
         $orderIssue = $this->orderIssue;
         if($orderIssue)$orderIssue->update(['is_new_rejecting'=>'无','logistic_number_return'=>null]);
-        return parent::delete(); // TODO: Change the autogenerated stub
+        return parent::delete();
     }
 
 }

+ 3 - 3
app/Services/CheckActiveMenuService.php

@@ -29,7 +29,7 @@ class CheckActiveMenuService
             self::syncToDB();
             self::switchL1ToL2();
         } catch (\Exception $e) {
-            // TODO 同步异常的处理策略
+            // 同步异常的处理策略
             return;
         }
     }
@@ -62,7 +62,7 @@ class CheckActiveMenuService
                     //菜单点击入缓存
                     Redis::LPUSH('UserVisitMenuLogsL1', $userVisitMenuLog);
                 } catch (\Exception $e) {
-                    // TODO 缓存异常的处理策略
+                    //缓存异常的处理策略
                     $userVisitMenuLog->save();
                 }
             }
@@ -86,7 +86,7 @@ class CheckActiveMenuService
                 $result= self::getFromDB($user_id);
             }
         } catch (\Exception $e) {
-            // TODO 缓存异常的处理策略
+            //缓存异常的处理策略
             $result=self::getFromDB($user_id);
         }
 

+ 0 - 2
app/Services/CommodityService.php

@@ -724,8 +724,6 @@ Class CommodityService
         if(count($commodities)>0) $this->pushToCache($commodities);
     }
 
-    // TODO
-
     /**
      * @param array $ownerIds
      * @param array $skus

+ 1 - 1
app/Services/OrderCommodityService.php

@@ -224,7 +224,7 @@ Class OrderCommodityService
         return $inner_params;
     }
 
-    // TODO 更新后续添加进更新逻辑
+    //更新后续添加进更新逻辑
     public function getUpdateParamsByParamsAndDeleteIds(&$inner_params,&$ids)
     {
         $update_params = [['id','order_id', 'commodity_id', 'amount', 'location', 'created_at', 'updated_at']];

+ 1 - 1
app/Services/OrderService.php

@@ -1041,7 +1041,7 @@ class OrderService
 
         /** @var OwnerPriceOperationService $service */
         $service = app("OwnerPriceOperationService");
-        $work_fee = $service->matchRule($object,$mapping,$order->owner_id,"出库");
+        $work_fee = $service->matching($object,$mapping,$order->owner_id,"出库");
         if ($work_fee < 0)$work_fee = null;
 
        if (app("OwnerFeeDetailService")->create([

+ 18 - 5
app/Services/OwnerPriceExpressService.php

@@ -61,17 +61,30 @@ Class OwnerPriceExpressService
         return OwnerPriceExpressProvince::destroy($id);
     }
 
-    public function getExistOwnerName($owner_id, $id=null) :array
+    public function getExistOwnerName($owner_id, $logistic_id, $id=null, $type = 'ownerPriceExpresses') :array
     {
         if (!is_array($owner_id))$owner_id = [$owner_id];
-        $owners = Owner::query()->withCount(["ownerPriceExpresses"=>function($query)use($id){
+        if (!is_array($logistic_id))$logistic_id = [$logistic_id];
+        $owners = Owner::query()->with([$type=>function($query)use($id){
+            /** @var Builder $query */
             if ($id)$query->where("id","!=",$id);
+            $query->with(["logistics"]);
         }])->whereIn("id",$owner_id)->get();
-        $arr = [];
+        $result = [];
         foreach ($owners as $owner){
-            if ($owner->owner_price_expresses_count > 0)$arr[] = $owner->name;
+            $arr = [];
+            if ($owner->ownerPriceExpresses){
+                foreach ($owner->ownerPriceExpresses as $express){
+                    if ($express->logistics){
+                        foreach ($express->logistics as $logistic){
+                            if (array_search($logistic->id,$logistic_id) !== false)$arr[] = $logistic->name;
+                        }
+                    }
+                }
+            }
+            if (count($arr)>0)$result[] = "“".$owner->name."”已绑定:".implode(",",$arr);
         }
-        return $arr;
+        return $result;
     }
 
     public function getExistLogisticName($logistic_id, $id=null):array

+ 7 - 3
app/Services/OwnerPriceLogisticService.php

@@ -5,9 +5,9 @@ namespace App\Services;
 use App\OwnerPriceLogistic;
 use App\OwnerPriceLogisticDetail;
 use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Support\Facades\DB;
 use App\Traits\ServiceAppAop;
 
-
 Class OwnerPriceLogisticService
 {
     use ServiceAppAop;
@@ -39,8 +39,12 @@ Class OwnerPriceLogisticService
 
     public function destroy($id)
     {
-        OwnerPriceLogistic::destroy($id);
-        OwnerPriceLogisticDetail::query()->where("owner_price_logistic_id",$id)->delete();
+        DB::transaction(function ()use($id){
+            DB::table("owner_price_logistic_logistic")->where("owner_price_logistic_id",$id)->delete();
+            DB::table("owner_price_logistic_owner")->where("owner_price_logistic_id",$id)->delete();
+            OwnerPriceLogisticDetail::query()->where("owner_price_logistic_id",$id)->delete();
+            OwnerPriceLogistic::destroy($id);
+        });
     }
 
     public function updateDetail(array $params, array $values)

+ 20 - 10
app/Services/OwnerOutStorageRuleService.php → app/Services/OwnerPriceOperationItemService.php

@@ -2,21 +2,21 @@
 
 namespace App\Services;
 
-use App\OwnerOutStorageRule;
+use App\OwnerPriceOperationItem;
 use App\Traits\ServiceAppAop;
 
 
-Class OwnerOutStorageRuleService
+Class OwnerPriceOperationItemService
 {
     use ServiceAppAop;
     public function get(array $params, array $withs = [], $isTranslateFeature = false, array $translateColumn = [])
     {
         if ($isTranslateFeature){
             $features = app("FeatureService")->getMapArray();
-            OwnerOutStorageRule::$features = $features;
-            OwnerOutStorageRule::$columnMapping = $translateColumn;
+            OwnerPriceOperationItem::$features = $features;
+            OwnerPriceOperationItem::$columnMapping = $translateColumn;
         }
-        $rule = OwnerOutStorageRule::query();
+        $rule = OwnerPriceOperationItem::query();
         if ($withs)$rule->with($withs);
         foreach ($params as $column=>$param){
             $rule->where($column,$param);
@@ -26,7 +26,7 @@ Class OwnerOutStorageRuleService
 
     public function update(array $params, array $values)
     {
-        $query = OwnerOutStorageRule::query();
+        $query = OwnerPriceOperationItem::query();
         foreach ($params as $column=>$param){
             $query->where($column,$param);
         }
@@ -35,23 +35,33 @@ Class OwnerOutStorageRuleService
 
     public function create(array $params)
     {
-        return OwnerOutStorageRule::query()->create($params);
+        return OwnerPriceOperationItem::query()->create($params);
     }
 
-    public function findUpdate(OwnerOutStorageRule $rule, array $values)
+    public function findUpdate(OwnerPriceOperationItem $rule, array $values)
     {
         return $rule->update($values);
     }
 
     public function find($id)
     {
-        return OwnerOutStorageRule::query()->find($id);
+        return OwnerPriceOperationItem::query()->find($id);
+    }
+
+    public function insert($values)
+    {
+        return OwnerPriceOperationItem::query()->insert($values);
+    }
+
+    public function destroy($id)
+    {
+        return OwnerPriceOperationItem::destroy($id);
     }
 
 
     public function isExist(array $params)
     {
-        $query = OwnerOutStorageRule::query();
+        $query = OwnerPriceOperationItem::query();
         foreach ($params as $column=>$param){
             $query->where($column,$param);
         }

+ 40 - 42
app/Services/OwnerPriceOperationService.php

@@ -2,9 +2,8 @@
 
 namespace App\Services;
 
-use App\OwnerInStorageRule;
-use App\OwnerOutStorageRule;
 use App\OwnerPriceOperation;
+use App\OwnerPriceOperationItem;
 use App\Services\common\QueryService;
 use App\Unit;
 use Illuminate\Database\Eloquent\Builder;
@@ -50,8 +49,7 @@ Class OwnerPriceOperationService
 
     public function destroy($id)
     {
-        OwnerOutStorageRule::query()->where("owner_price_operation_id",$id)->delete();
-        OwnerInStorageRule::query()->where("owner_price_operation_id",$id)->delete();
+        OwnerPriceOperationItem::query()->where("owner_price_operation_id",$id)->delete();
         DB::table("owner_price_operation_owner")->where("owner_price_operation_id",$id)->delete();
         return OwnerPriceOperation::destroy($id);
     }
@@ -65,31 +63,20 @@ Class OwnerPriceOperationService
         return OwnerPriceOperation::query()->create($params);
     }
 
-    public function insertRule(array $params, $type = '出库')
+    public function insertItem(array $params)
     {
-        if ($type == '出库')OwnerOutStorageRule::query()->insert($params);
-        else OwnerInStorageRule::query()->insert($params);
+        OwnerPriceOperationItem::query()->insert($params);
     }
 
-    public function find($id, $isGetRule = false, $withs = [])
+    public function find($id, $withs = [])
     {
         $query = OwnerPriceOperation::query()->with($withs)->find($id);
-        if ($isGetRule){
-            if ($query->operation_type == '入库'){
-                $query->load("ownerInStorageRule");
-                $query->rules = $query->ownerInStorageRule ? json_encode([$query->ownerInStorageRule]) : null;
-            }else{
-                $query->load("ownerOutStorageRules");
-                $query->rules = json_encode($query->ownerOutStorageRules);
-            }
-        }
         return $query;
     }
 
-    public function destroyRule($id, $type)
+    public function destroyItem($id)
     {
-        if ($type=="入库")OwnerInStorageRule::query()->where("owner_price_operation_id",$id)->delete();
-        else OwnerOutStorageRule::query()->where("owner_price_operation_id",$id)->delete();
+        return OwnerPriceOperationItem::query()->where("owner_price_operation_id",$id)->delete();
     }
 
     public function findUpdate(OwnerPriceOperation $model, array $params)
@@ -109,27 +96,27 @@ Class OwnerPriceOperationService
      * @param string $type
      * @return double
      * 错误代码: -1:无匹配对象 -2:无计费模型 -3:未知单位 -4:sku为空 -5:货主未找到 -6:无箱规 -7:未匹配到计费模型
+     *
+     * 一. 2020-10-10 zzd
+     * 二. 2021-01-08 zzd
      */
-    public function matchRule($matchObject, $columnMapping, $owner_id, $type = '出库')
+    public function matching($matchObject, $columnMapping, $owner_id, $type = '出库')
     {
         $unitModels = Unit::query()->whereIn("name",["件","箱","单"])->get();
         $units = [];
         foreach ($unitModels as $unitModel)$units[$unitModel->id] = $unitModel->name;
 
-        $withs = $type=='出库' ? ['ownerOutStorageRules'=>function($query){
+        $rules = OwnerPriceOperation::query()->with(["items"=>function($query){
             /** @var Builder $query */
             $query->orderByRaw("CASE strategy  WHEN '起步' THEN 1 WHEN '默认' THEN 2 WHEN '特征' THEN 3 END DESC,priority DESC");
-        }] : ['ownerInStorageRule'] ;
-        $rules = OwnerPriceOperation::query()->with($withs)
-            ->where("operation_type",$type)
-            ->whereHas("ownerPriceOperationOwners",function ($query)use($owner_id){
+        }])->where("operation_type",$type)->whereHas("ownerPriceOperationOwners",function ($query)use($owner_id){
                 /** @var Builder $query */
                 $query->where("id",$owner_id);
-            })
-            ->orderByRaw("strategy desc,priority desc")->get(); //货主下的全部规则
+        })->orderByRaw("strategy desc,priority desc")->get(); //货主下的全部规则
+
         if (!$rules)return -2;
 
-        if ($type == '入库'){
+        /*if ($type == '入库'){
             $amountColumn = $columnMapping["amount"] ?? "amount";
             $packageColumn = $columnMapping["packages"] ?? "packages";
             $packages = $matchObject[$packageColumn] ?? false;
@@ -140,12 +127,12 @@ Class OwnerPriceOperationService
             if (!$amount)return -1;
             foreach ($rules as $rule){
                 $sum = $amount;
-                if (!$rule->ownerInStorageRule)continue;
+                if (!$rule->in)continue;
                 if ($rule->strategy == '特征'){
                     $bool = app("FeatureService")->matchFeature($rule->feature,$columnMapping,$matchObject);
                     if ($bool === true){
-                        if (!isset($units[$rule->ownerInStorageRule->unit_id])) return -3;
-                        if ($units[$rule->ownerInStorageRule->unit_id] == '箱'){ //为箱时同步商品寻找箱规
+                        if (!isset($units[$rule->in->unit_id])) return -3;
+                        if ($units[$rule->in->unit_id] == '箱'){ //为箱时同步商品寻找箱规
                             $sumTemp = 0;
                             $packageColumn = $columnMapping["packages"] ?? "packages";
                             foreach ($matchObject[$packageColumn] as $commodity){
@@ -154,12 +141,12 @@ Class OwnerPriceOperationService
                             $sum = $sumTemp;
                             if ($sum<0)return $sum;
                         }
-                        if ($units[$rule->ownerInStorageRule->unit_id] == '单')$sum = 1; //为单时数量设为1;
-                        return ceil($sum/$rule->ownerInStorageRule->amount)*$rule->ownerInStorageRule->unit_price;
+                        if ($units[$rule->in->unit_id] == '单')$sum = 1; //为单时数量设为1;
+                        return ceil($sum/$rule->in->amount)*$rule->in->unit_price;
                     };
                 }else{
-                    if (!isset($units[$rule->ownerInStorageRule->unit_id])) return -3;
-                    if ($units[$rule->ownerInStorageRule->unit_id] == '箱'){ //为箱时同步商品寻找箱规
+                    if (!isset($units[$rule->in->unit_id])) return -3;
+                    if ($units[$rule->in->unit_id] == '箱'){ //为箱时同步商品寻找箱规
                         $sumTemp = 0;
                         $packageColumn = $columnMapping["packages"] ?? "packages";
                         foreach ($matchObject[$packageColumn] as $commodity){
@@ -168,23 +155,23 @@ Class OwnerPriceOperationService
                         $sum = $sumTemp;
                         if ($sum<0)return $sum;
                     }
-                    if ($units[$rule->ownerInStorageRule->unit_id] == '单')$sum = 1; //为单时数量设为1;
-                    return ceil($sum/$rule->ownerInStorageRule->amount)*$rule->ownerInStorageRule->unit_price;
+                    if ($units[$rule->in->unit_id] == '单')$sum = 1; //为单时数量设为1;
+                    return ceil($sum/$rule->in->amount)*$rule->in->unit_price;
                 };
             }
             return -7;
-        }
+        }*/
         //出库
         foreach ($rules as $rule){
             if (!$rule->ownerOutStorageRules)continue;
             if ($rule->strategy == '特征'){
                 $bool = app("FeatureService")->matchFeature($rule->feature,$columnMapping,$matchObject);//匹配特征
                 if ($bool === true){
-                    $money = $this->matchOutStorage($rule->ownerOutStorageRules,$columnMapping,$matchObject,$units,$owner_id);
+                    $money = $this->matchItem($rule->ownerOutStorageRules,$columnMapping,$matchObject,$units,$owner_id,$type=='入库' ? true : false);
                     if ($money>0)return $money;
                 };
             }else{
-                $money = $this->matchOutStorage($rule->ownerOutStorageRules,$columnMapping,$matchObject,$units,$owner_id);
+                $money = $this->matchItem($rule->ownerOutStorageRules,$columnMapping,$matchObject,$units,$owner_id,$type=='入库' ? true : false);
                 if ($money>0)return $money;
             };
         }
@@ -198,7 +185,7 @@ Class OwnerPriceOperationService
         return ceil($amount/$pack);
     }
 
-    private function matchOutStorage($rules, $columnMapping, $matchObject, $units, $owner_id)
+    private function matchItem($rules, $columnMapping, $matchObject, $units, $owner_id, $isIn)
     {
         $amountColumn = $columnMapping["amount"] ?? "amount";
         $packageColumn = $columnMapping["packages"] ?? "packages";
@@ -210,6 +197,7 @@ Class OwnerPriceOperationService
         foreach ($rules as $rule){
             switch ($rule->strategy){
                 case "特征":
+                    $inMoney = 0;
                     foreach ($packages as &$package){
                         if ($package["price"] ?? false)continue;
                         if (!app("FeatureService")->matchFeature($rule->feature,["商品名称"=>$commodityColumn],["commodity"=>$package[$commodityColumn] ?? ''])) continue;
@@ -231,9 +219,14 @@ Class OwnerPriceOperationService
                             if ($amount<0)return $amount;
                             $package[$amountColumn] = $amount;
                         }
+                        $inMoney += $package[$amountColumn] * $package["price"];
+                    }
+                    if ($isIn && $inMoney !== 0){
+                        return $inMoney;
                     }
                     break;
                 case "默认":
+                    $inMoney = 0;
                     foreach ($packages as &$package){
                         if ($package["price"] ?? false)continue; //校验是否已匹配到
                         if (!$unitName)$unitName = $units[$rule->unit_id]; //校验单位是否一致
@@ -254,9 +247,14 @@ Class OwnerPriceOperationService
                             if ($amount<0)return $amount;
                             $package[$amountColumn] = $amount;
                         }
+                        $inMoney += $package[$amountColumn] * $package["price"];
+                    }
+                    if ($isIn && $inMoney !== 0){
+                        return $inMoney;
                     }
                     break;
                 default:
+                    if ($isIn)continue;
                     if ($unitName && $unitName != $units[$rule->unit_id])return -3; //校验单位是否一致
 
                     $money = $rule->amount * $rule->unit_price;

+ 2 - 2
app/Services/OwnerService.php

@@ -93,9 +93,9 @@ Class OwnerService
         },config('cache.expirations.rarelyChange'));
     }
 
-    public function find($id)
+    public function find($id, $with = [])
     {
-        return Owner::query()->find($id);
+        return Owner::query()->with($with)->find($id);
     }
 
     public function update(Owner $owner, array $values, array $related = [])

+ 2 - 0
app/Services/OwnerStoragePriceModelService.php

@@ -4,6 +4,7 @@ namespace App\Services;
 
 use App\OwnerReport;
 use App\OwnerStoragePriceModel;
+use Illuminate\Support\Facades\DB;
 use App\Traits\ServiceAppAop;
 
 
@@ -42,6 +43,7 @@ Class OwnerStoragePriceModelService
     }
     public function destroy($id)
     {
+        DB::delete(DB::raw("DELETE FROM owner_storage_price_model_owner WHERE owner_storage_price_model_id = ?"),[$id]);
         return OwnerStoragePriceModel::destroy($id);
     }
 

+ 5 - 1
app/Services/PackageService.php

@@ -4,7 +4,9 @@ namespace App\Services;
 
 use App\OrderPackage;
 use App\Services\common\QueryService;
+use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
 
 const TABLE = "order_packages.";
 use App\Traits\ServiceAppAop;
@@ -15,7 +17,9 @@ Class PackageService
     use ServiceAppAop;
     private function conditionQuery($params){
         $packages = OrderPackage::query()->with(['order'=>function($query){
-            $query->with('owner','logistic');
+            /** @var Builder $query */
+            $ownerIds=app('UserService')->getPermittingOwnerIds(Auth::user());
+            $query->with('owner','logistic')->whereIn("owner_id",$ownerIds ?? []);
         },'paperBox','measuringMachine'])->orderBy(TABLE.'id','DESC');
         if ($params['owner_id'] ?? false){
             $owner_id = explode(',',$params['owner_id']);

+ 1 - 1
app/Services/StoreService.php

@@ -315,7 +315,7 @@ Class StoreService
 
         $mapping = ["packages" => "storeItems", "商品名称" => "name", "订单类型" => "stored_method"];
 
-        $work_fee = $service->matchRule($store, $mapping, $store->owner_id, "入库");
+        $work_fee = $service->matching($store, $mapping, $store->owner_id, "入库");
         if ($work_fee < 0) $work_fee = null;
 
         if (app("OwnerFeeDetailService")->create([

+ 5 - 0
app/Services/WarehouseService.php

@@ -20,6 +20,11 @@ Class WarehouseService
         $this->instant($this->cacheService,'CacheService');
     }
 
+    public function getSelection($column = ['id', 'name'])
+    {
+        return Warehouse::query()->select($column)->get();
+    }
+
     public function firstOrCreate(array $params, array $values = null)
     {
         if ($values) return Warehouse::query()->firstOrCreate($params, $values);

+ 38 - 0
database/migrations/2021_01_07_145912_add_warehouse_id_column_owners_table.php

@@ -0,0 +1,38 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddWarehouseIdColumnOwnersTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('owners', function (Blueprint $table) {
+            $table->bigInteger("warehouse_id")->index()->nullable()->comment("外键仓库");
+        });
+        Schema::table('owner_storage_price_models', function (Blueprint $table) {
+            $table->string("name")->comment("名称");
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('owners', function (Blueprint $table) {
+            $table->dropColumn("warehouse_id");
+        });
+        Schema::table('owner_storage_price_models', function (Blueprint $table) {
+            $table->dropColumn("name");
+        });
+    }
+}

+ 43 - 0
database/migrations/2021_01_08_093237_delete_table_item_in_change_table_out.php

@@ -0,0 +1,43 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class DeleteTableItemInChangeTableOut extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::dropIfExists('owner_price_operation_item_ins');
+        Schema::table('owner_price_operation_item_outs', function (Blueprint $table) {
+            $table->rename("owner_price_operation_items");
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::create('owner_price_operation_item_ins', function (Blueprint $table) {
+            $table->id();
+            $table->bigInteger("owner_price_operation_id")->index()->comment("外键作业计费模型");
+            $table->enum("strategy",["起步","默认","特征"])->comment("出库策略");
+            $table->integer("amount")->nullable()->comment("起步数");
+            $table->bigInteger("unit_id")->index()->comment("外键单位");
+            $table->decimal("unit_price",8,4)->comment("单价");
+            $table->string("feature")->nullable()->comment("特征");
+            $table->integer("priority")->default(0)->index()->comment("匹配优先级(越大越优先)");
+        });
+        Schema::table('owner_price_operation_items', function (Blueprint $table) {
+            $table->rename("owner_price_operation_item_outs");
+        });
+    }
+}

+ 5 - 0
resources/sass/text.scss

@@ -112,6 +112,11 @@
     transform: scale(1.2);
     box-shadow: 0 0 9px 3px #999;
 }
+//放大标记-略小
+.sign-sm{
+    transform: scale(1.05);
+    box-shadow: 0 0 9px 3px #999;
+}
 //分隔线
 .hr-info{
     height:3px;

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

@@ -57,7 +57,7 @@
                             <span class="fa fa-plus" :id="'tag-'+i" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
                             <div class="dropdown-menu" :aria-labelledby="'tag-'+i">
                                 <div @click="$event.stopPropagation();" style="min-width: 250px">
-                                    <label class="w-75 ml-2"><input class="form-control form-control-sm" @keydown="submitTag(i,$event)" type="text" @input="search($event)"></label>
+                                    <label class="w-75 ml-2"><input placeholder="TAB键与回车键提交新标签" class="form-control form-control-sm" @keydown="submitTag(i,$event)" type="text" @input="search($event)"></label>
                                     <span v-if="searchTag.length>0">
                                         <a class="dropdown-item text-nowrap" v-for="tag in searchTag" @click="selected(i,tag)">
                                             @{{ tag.value }}

+ 663 - 158
resources/views/customer/project/create.blade.php

@@ -9,7 +9,7 @@
             </li>
         @endif
     @endcomponent
-    <div class="container-fluid card" id="container">
+    <div class="container-fluid card d-none" id="container">
         <div class="card-body offset-2">
             <div class="row">
                 <div class="col-2 form-inline cursor-pointer text-dark" @click="switchBase('one')">
@@ -44,7 +44,7 @@
                 </div>
                 <div class="col-2 form-inline cursor-pointer text-dark" @click="switchBase('three')">
                     <div class="h-100 w-25">
-                        <div class="h1 fillet text-center" :class="[base == 'three' ? 'sign' : '', (base!=='three' && !owner.ownerStoragePriceModels) ? 'bg-secondary border-secondary' : 'bg-info']">
+                        <div class="h1 fillet text-center" :class="[base == 'three' ? 'sign' : '', (base!=='three' && !isExist) ? 'bg-secondary border-secondary' : 'bg-info']">
                             <span class="fa fa-rmb ml-1 text-white "></span>
                         </div>
                     </div>
@@ -53,26 +53,23 @@
                     </div>
                 </div>
             </div>
-            <form method="POST" action="{{url('customer/project/store')}}" class="mt-5">
-                @csrf
-                <div v-if="base == 'one'">
-                    @include("customer.project.part._one")
-                </div>
-                <div v-if="base == 'two'">
-                    @include("customer.project.part._two")
-                </div>
-                <div v-if="base == 'three'">
-                    @include("customer.project.part._three")
-                </div>
-                <div class="row mt-3">
-                    <div class="pull-right offset-7">
-                        <button type="button" class="btn btn-info ml-1 text-white" v-show="base !== 'one'" @click="back()">上一步</button>
-                        <button type="button" class="btn btn-info ml-1 text-white" v-show="base !== 'three'" @click="next()">下一步</button>
-                        <button type="button" class="btn btn-success ml-1">完成</button>
-                        <button type="button" class="btn btn-secondary ml-1">重置</button>
-                    </div>
+            <div v-if="base == 'one'">
+                @include("customer.project.part._one")
+            </div>
+            <div v-if="base == 'two'">
+                @include("customer.project.part._two")
+            </div>
+            <div v-if="base == 'three'">
+                @include("customer.project.part._three")
+            </div>
+            <div class="row mt-3">
+                <div class="pull-right offset-7">
+                    <button type="button" class="btn btn-info ml-1 text-white" v-show="base !== 'one'" @click="back()">上一步</button>
+                    <button type="button" class="btn btn-info ml-1 text-white" v-show="base !== 'three'" @click="next()">下一步</button>
+                    <button type="button" class="btn btn-success ml-1" @click="success()">完成</button>
+                    <button type="button" class="btn btn-secondary ml-1" @click="reset()" v-show="base !== 'three'">重置</button>
                 </div>
-            </form>
+            </div>
         </div>
     </div>
 @stop
@@ -82,22 +79,8 @@
         new Vue({
             el:"#container",
             data:{
-                base:"three",
+                base:"one",
                 owner : {
-                    id:"{{old('id') ?? ($owner->id ?? '') }}",
-                    name : "{{old('name') ?? ($owner->name ?? '')}}",
-                    code : "{{old('code') ?? ($owner->code ?? '')}}",
-                    customer_id : "{{old('customer_id') ?? ($owner->customer_id ?? '')}}",
-                    customer_name : "{{ isset($owner) ? ($owner->customer ? $owner->customer->name : '') : ''}}",
-                    owner_group_name : "{{ isset($owner) ? ($owner->userOwnerGroup ? $owner->userOwnerGroup->name : '') : ''}}",
-                    owner_group_id : "{{old('owner_group_id') ?? ($owner->user_owner_group_id ?? '')}}",
-                    tax_rate : "{{old('tax_rate') ?? ($owner->tax_rate ?? '')}}",
-                    linkman : "{{old('linkman') ?? ($owner->linkman ?? '')}}",
-                    phone_number : "{{old('phone_number') ?? ($owner->phone_number ?? '')}}",
-                    description : "{{old('description') ?? ($owner->description ?? '')}}",
-                    waring_line_on : "{{old('waring_line_on') ?? ($owner->waring_line_on ?? '')}}",
-                },
-                ownerTemp : {
                     id:"{{$owner->id ?? ''}}",
                     name : "{{$owner->name ?? ''}}",
                     code : "{{$owner->code ?? ''}}",
@@ -105,24 +88,14 @@
                     customer_name : "{{ isset($owner) ? ($owner->customer ? $owner->customer->name : '') : ''}}",
                     owner_group_name : "{{ isset($owner) ? ($owner->userOwnerGroup ? $owner->userOwnerGroup->name : '') : ''}}",
                     owner_group_id : "{{$owner->user_owner_group_id ?? ''}}",
-                    owner_storage_price_model_id : "{{$owner->owner_storage_price_model_id ?? ''}}".split(','),
+                    warehouse_id : "{{ $owner->warehouse_id ?? ''}}",
                     tax_rate : "{{$owner->tax_rate ?? ''}}",
                     linkman : "{{$owner->linkman ?? ''}}",
                     phone_number : "{{$owner->phone_number ?? ''}}",
                     description : "{{$owner->description ?? ''}}",
                     waring_line_on : "{{$owner->waring_line_on ?? ''}}",
                 },
-                storagePriceModels : [
-                    @foreach($storagePriceModels as $storagePriceModel)
-                    {   id:"{{$storagePriceModel->id}}",
-                        counting_type : "{{$storagePriceModel->counting_type}}",
-                        using_type : "{{$storagePriceModel->using_type}}",
-                        minimum_area : "{{$storagePriceModel->minimum_area}}",
-                        price : "{{$storagePriceModel->price}}",
-                        unit_name : "{{$storagePriceModel->unit ? $storagePriceModel->unit->name : ''}}",
-                    },
-                    @endforeach
-                ],
+                ownerTemp : {},
                 customers : [
                     @foreach($customers as $customer)
                     {id:"{{$customer->id}}",name:"{{$customer->name}}"},
@@ -133,9 +106,13 @@
                     {id:"{{$ownerGroup->id}}",name:"{{$ownerGroup->name}}"},
                     @endforeach
                 ],
+                warehouses:[
+                    @foreach($warehouses as $warehouse)
+                    {id:"{{$warehouse->id}}",name:"{{$warehouse->name}}"},
+                    @endforeach
+                ],
                 style : '',
                 errors : {!! $errors !!}, //全部的错误提示
-                display:false,
                 upList:{ //控制元素的渐入展开与收起
                     storage : false,
                 },
@@ -195,9 +172,7 @@
                     feature_type:['商品名称','订单类型','承运商','店铺类型'],
                     logic : ['包含','不包含','等于'],
                 },
-                poolMapping:{//基础数据选择池的映射对象 供展示使用
-
-                },
+                poolMapping:{},//基础数据选择池的映射对象 供展示使用
                 selectedModel:{//已选定的计费模型
                     storage:[],
                     operation:[],
@@ -209,12 +184,18 @@
                 operationItems:{},//控制作业费子项的渐入展开
                 importError:[],//导入时的错误数据原因
                 isShowError:false,//是否展开导入错误信息
+                isExist:Boolean("{{$isExist ?? false}}"),
+                isLoad:false,//全局加载标记,符合条件时确保仅加载一次
+                introduce:{},//引入model
+                isSearch:false,//是否查询,用于加载动画显示
+                searchResult:[],//查询结果
+                searchResultMapping:{},//查询结果映射
+                selectedResult:"",
             },
             mounted(){
+                this.ownerTemp = this.owner;
                 $('[data-toggle="tooltip"]').tooltip();
-                if (this.errors.length===0 && this.owner.id){
-                    this.display = true;
-                }
+                $("#container").removeClass("d-none");
             },
             methods:{
                 //收起展开
@@ -224,8 +205,18 @@
                     this.upList[id] = !this.upList[id];
                     this.$forceUpdate();
                 },
+                //清除垃圾数据
+                _clearRefuse(){
+                    this.errors = [];
+                    this.importError = [];
+                    this.selectedResult = "";
+                    this.searchResult = [];
+                    this.searchResultMapping = {};
+                    this.introduce = {};
+                },
                 //切换选项
                 switchBase(base){
+                    if (!this.ownerTemp.id)return;
                     if (base === 'three') this._loadStorage();
                     if (base === this.base)return;
                     this.base = base;
@@ -233,6 +224,7 @@
                 //切换类型
                 switchType(type){
                     if (type === this.type)return;//相同终止是为了减少重复加载动作
+                    this._clearRefuse();//清除垃圾数据
                     let parent = $("#parent");
                     switch (type) {
                         case "storage":
@@ -262,13 +254,38 @@
                 next(){
                     switch (this.base) {
                         case "one":
-                            this._verifyOne();
+                            if (this._verifyOne())this.base = "two";
+                            break;
+                        case "two":
+                            if (this._verifyTwo())this.base = "three";
+                            this._loadStorage();
+                            break;
+                    }
+                },
+                //完成
+                success(){
+                    switch (this.base) {
+                        case "one":
+                            if (this._verifyOne())window.location.href = "{{url('customer/project/index')}}";
                             break;
                         case "two":
-                            this._verifyTwo();
+                            if (this._verifyTwo())window.location.href = "{{url('customer/project/index')}}";
                             break;
                         default:
-                            this._loadStorage();
+                            window.tempTip.confirm("<span class='text-danger'>确定后计费模型未保存项将被抛弃,您确认仍要完成吗?</span>",()=>{
+                                window.location.href = "{{url('customer/project/index')}}";
+                            });
+                            break;
+                    }
+                },
+                //重置
+                reset(){
+                    switch (this.base) {
+                        case "one":
+                            this.owner = this.ownerTemp;
+                            break;
+                        case "two":
+                            this.owner = this.ownerTemp;
                             break;
                     }
                 },
@@ -277,25 +294,83 @@
                     if (!this.owner.name){
                         this.errors["name"] = ["项目名称为必填项"];
                         this.$forceUpdate();
-                        return;
+                        return false;
                     }
                     if (!this.owner.code){
                         this.errors["code"] = ["项目代码为必填项"];
                         this.$forceUpdate();
-                        return;
+                        return false;
+                    }
+                    if (this.owner.name !== this.ownerTemp.name || this.owner.code !== this.ownerTemp.code){
+                        let url = "{{url('maintenance/owner/apiStore')}}";
+                        let params = {name:this.owner.name,code:this.owner.code,id:this.ownerTemp.id};
+                        let result = undefined;
+                        window.tempTip.postBasicRequest(url,params,res=>{
+                            if (res.errors){
+                                this.errors = res.errors;
+                                this.$forceUpdate();
+                                result = false;
+                                return;
+                            }
+                            this.errors = [];
+                            this.owner.id = res.id;
+                            this.ownerTemp.id = res.id;
+                            this.ownerTemp.name = res.name;
+                            this.ownerTemp.code = res.code;
+                            result = true;
+                        });
+                        while (result){
+                            if (typeof result !== "undefined")return result;
+                        }
                     }
-                    this._requestRequest({name:this.owner.name,code:this.owner.code},"two")
+                    return true;
                 },
                 //验证详细描述
                 _verifyTwo(){
-                    if (!this.owner.customer_id){
-                        this.errors["customer_id"] = ["必须选择客户"];
+                    let error = {};
+                    if (!this.owner.customer_id) error["customer_id"] = ["必须选择客户"];
+                    if (!this.owner.owner_group_id) error["owner_group_id"] = ["必须选择项目小组"];
+                    if (!this.owner.warehouse_id) error["warehouse_id"] = ["必须选择仓库"];
+                    if (JSON.stringify(error) !== "{}"){
+                        this.errors = error;
                         this.$forceUpdate();
+                        return;
                     }
-                    if (!this.owner.owner_group_id){
-                        this.errors["owner_group_id"] = ["必须选择项目小组"];
-                        this.$forceUpdate();
+                    let url = "{{url('customer/project/projectUpdate')}}";
+                    let params = this.owner;
+                    let old = this.ownerTemp;
+                    if (params.customer_id !== old.customer_id ||
+                    params.owner_group_id !== old.owner_group_id ||
+                    params.warehouse_id !== old.warehouse_id ||
+                    params.tax_rate !== old.tax_rate ||
+                    params.waring_line_on !== old.waring_line_on ||
+                    params.phone_number !== old.phone_number ||
+                    params.description !== old.description){
+                        let result = undefined;
+                        window.tempTip.postBasicRequest(url,params,res=>{
+                            if (res.errors){
+                                this.errors = res.errors;
+                                this.$forceUpdate();
+                                result = false;
+                                return;
+                            }
+                            this.errors = [];
+                            this.ownerTemp.customer_id = res.customer_id;
+                            this.ownerTemp.owner_group_id = res.owner_group_id;
+                            this.ownerTemp.warehouse_id = res.warehouse_id;
+                            this.ownerTemp.tax_rate = res.tax_rate;
+                            this.ownerTemp.waring_line_on = res.waring_line_on;
+                            this.ownerTemp.phone_number = res.phone_number;
+                            this.ownerTemp.description = res.description;
+                            this.ownerTemp.customer_name = params.customer_name;
+                            this.ownerTemp.owner_group_name = params.owner_group_name;
+                            result = true;
+                        });
+                        while (result){
+                            if (typeof result !== "undefined")return result;
+                        }
                     }
+                    return true;
                 },
                 //上一步
                 back(){
@@ -308,22 +383,44 @@
                             break;
                     }
                 },
-                //请求验证
-                _requestRequest(params, next){
-                    let url = "{{url('customer/project/verify')}}";
+                //加载计费模型
+                _loadPriceModel(){
+                    let url = "{{url('customer/project/getPriceModel')}}";
+                    let params = {id:this.ownerTemp.id};
                     window.tempTip.postBasicRequest(url,params,res=>{
-                        if (res.length > 0){
-                            this.errors = res;
-                            this.$forceUpdate();
-                        }else{
-                            this.base = next;
-                            this.errors = [];
+                        if (res.owner_storage_price_models.length>0)this.selectedModel.storage = res.owner_storage_price_models;
+                        if (res.owner_price_operations.length>0)this.selectedModel.operation = res.owner_price_operations;
+                        if (res.owner_price_expresses.length>0){
+                            this._loadExpress();
+                            res.owner_price_expresses.forEach((express,i)=>{
+                                express.logistics.forEach((logistic,j)=>{
+                                    express.logistics[j] = logistic.id;
+                                });
+                                res.owner_price_expresses[i] = JSON.parse(JSON.stringify(express).replace(/details/g,"items"));
+                            });
+                            this.selectedModel.express = res.owner_price_expresses;
+                        }
+                        if (res.owner_price_logistics.length>0){
+                            this._loadLogistic();
+                            res.owner_price_logistics.forEach((logistic,i)=>{
+                                logistic.logistics.forEach((l,j)=>{
+                                    logistic.logistics[j] = l.id;
+                                });
+                                res.owner_price_logistics[i] = JSON.parse(JSON.stringify(logistic).replace(/details/g,"items"));
+                            });
+                            this.selectedModel.logistic = res.owner_price_logistics;
+                        }
+                        if (res.owner_price_direct_logistics.length>0){
+                            this._loadDirectLogistic();
+                            this.selectedModel.directLogistic = JSON.parse(JSON.stringify(res.owner_price_direct_logistics[0]).replace(/details/g,"items"));
                         }
                     });
+                    this.isLoad = true;
                 },
                 //加载仓储所需基础信息
                 _loadStorage(){
                     if (!this.pool.units)this._getUnits();
+                    if (!this.isLoad && this.ownerTemp.id)this._loadPriceModel();//计费模型未被加载且项目ID存在时
                 },
                 //加载作业
                 _loadOperation(){
@@ -355,6 +452,24 @@
                 _loadDirectLogistic(){
                     if (!this.pool.cars)this._getCars();
                 },
+                //加载引入
+                loadIntroduce(){
+                    if (!this.pool.owners)this._getOwners();
+                    if (!this.pool.logistics)this._getLogistics();
+                },
+                //获取项目
+                _getOwners(){
+                    let url = "{{url('maintenance/owner/get')}}";
+                    window.tempTip.postBasicRequest(url,{},res=>{
+                        this.pool.owners = res;
+                        let mapping = [];
+                        res.forEach(owner=>{
+                            mapping[owner.id] = owner.name;
+                        });
+                        this.poolMapping.owners = mapping;
+                        this.$forceUpdate();
+                    });
+                },
                 //获取单位
                 _getUnits(){
                     let url = "{{url('maintenance/unit/getUnits')}}";
@@ -441,47 +556,53 @@
                     }
                 },
                 _verifyStorage(){
-                    if (!this.model.storage.counting_type){
-                        this.errors["counting_type"] = ["未选择计费类型"];
-                        this.$forceUpdate();
-                        return;
-                    }
-                    if (!this.model.storage.using_type){
-                        this.errors["using_type"] = ["未选择用仓类型"];
-                        this.$forceUpdate();
-                        return;
-                    }
-                    if (!this.model.storage.price){
-                        this.errors["price"] = ["未输入单价"];
-                        this.$forceUpdate();
-                        return;
-                    }
-                    if (!this.model.storage.discount_type){
-                        this.errors["discount_type"] = ["未选择减免类型"];
+                    let error = {};
+                    if (!this.model.storage.counting_type)error["counting_type"] = ["未选择计费类型"];
+                    if (!this.model.storage.name)error["name"] = ["未填写名称"];
+                    if (!this.model.storage.using_type)error["using_type"] = ["未选择用仓类型"];
+                    if (!this.model.storage.price)error["price"] = ["未输入单价"];
+                    if (!this.model.storage.discount_type)error["discount_type"] = ["未选择减免类型"];
+                    if (JSON.stringify(error) !== "{}"){
+                        this.errors = error;
                         this.$forceUpdate();
                         return;
                     }
-                    this.selectedModel.storage.unshift(this.model.storage);
-                    this.model.storage = {
-                        counting_type : "",
-                        using_type : "",
-                        minimum_area : "",
-                        price : "",
-                        discount_type : "无减免",
-                        discount_value : "",
-                        unit_id : "",
-                    };
-                    this.errors = [];
+                    let url = "{{url('maintenance/priceModel/apiStoreStorage')}}";
+                    let params = this.model.storage;
+                    params.owner_id = this.ownerTemp.id;
+                    window.tempTip.postBasicRequest(url,params,res=>{
+                        if (res && res.errors){
+                            this.errors = res.errors;
+                            return;
+                        }
+                        if (this.model.storage.id) this.selectedModel.storage[this.model.storage.index] = this.model.storage;
+                        else {
+                            this.model.storage.id = res;
+                            this.selectedModel.storage.unshift(this.model.storage);
+                        }
+                        this.model.storage = {
+                            name : "",
+                            counting_type : "",
+                            using_type : "",
+                            minimum_area : "",
+                            price : "",
+                            discount_type : "无减免",
+                            discount_value : "",
+                            unit_id : "",
+                        };
+                        this.errors = [];
+                    });
                 },
                 _verifyOperation() {
-                    if (this.selectedModel.operation.length>0){
-                        this.selectedModel.operation.forEach(operation=>{
+                    if (this.selectedModel.operation.length>0 && !this.model.operation.id){
+                        if (!this.selectedModel.operation.every(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;
+                                return false;
                             }
-                        });
+                            return true;
+                        }))return;
                     }
                     if (!this.model.operation.name){
                         this.errors["name"] = ["名称不得为空"];
@@ -494,20 +615,42 @@
                             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);
-                    this.model.operation = {
-                        operation_type:"入库",
-                        strategy:"默认",
-                        name:"",
-                        feature:"",
-                        items : [
-                            {strategy:"起步"},
-                            {strategy:"默认"},
-                            {strategy:"特征"},
-                        ],
-                    };
-                    this.errors = [];
+                    let url = "{{url('maintenance/priceModel/apiStoreOperation')}}";
+                    let params = this.model.operation;
+                    params.owner_id = this.ownerTemp.id;
+                    window.tempTip.postBasicRequest(url,params,res=>{
+                        if (res && res.errors){
+                            if (res.errors.owner_id){
+                                window.tempTip.show(res.errors.owner_id[0]);
+                                return;
+                            }
+                            this.errors = res.errors;
+                            return;
+                        }
+                        res.features = this.model.operation.features;
+                        res.featureFormat = this.model.operation.featureFormat;
+                        let sign = 0;
+                        if (res.operation_type === '入库') sign++;
+                        for (let i=0;i<res.items.length;i++){
+                            res.items[i].features = this.model.operation.items[sign]['features'];
+                            res.items[i].featureFormat = this.model.operation.items[sign]['featureFormat'];
+                            sign++;
+                        }
+                        if (params.id) this.selectedModel.operation[params.index] = res;
+                        else this.selectedModel.operation.push(res);
+                        this.model.operation = {
+                            operation_type:"入库",
+                            strategy:"默认",
+                            name:"",
+                            feature:"",
+                            items : [
+                                {strategy:"起步"},
+                                {strategy:"默认"},
+                                {strategy:"特征"},
+                            ],
+                        };
+                        this.errors = [];
+                    });
                 },
                 _verifyOperationItem(itemIndex){//验证作业费子项信息完整
                     let obj = this.model.operation.items[itemIndex];
@@ -543,17 +686,31 @@
                         this.$forceUpdate();
                         return;
                     }
-                    this.selectedModel.express.unshift(this.model.express);
-                    this.model.express = {
-                        name:"",
-                        logistics:[],
-                        initial_weight:"",
-                        additional_weight:"",
-                        items:[],
-                    };
-                    this.errors = [];
-                    this.importError = [];
-                    $(".selectpicker").filter('.express').selectpicker('val',[]);
+                    let url = "{{url('maintenance/priceModel/apiStoreExpress')}}";
+                    let params = this.model.express;
+                    params.owner_id = this.ownerTemp.id;
+                    window.tempTip.postBasicRequest(url,params,res=>{
+                        if (res && res.errors){
+                            this.errors = res.errors;
+                            if (res.errors.owner_id)window.tempTip.show(res.errors.owner_id[0]);
+                            return;
+                        }
+                        this.model.express.id = res.id;
+                        this.model.express.items.forEach((item,i)=>{
+                            item.id = res.details[i].id;
+                        });
+                        this.selectedModel.express.unshift(this.model.express);
+                        this.model.express = {
+                            name:"",
+                            logistics:[],
+                            initial_weight:"",
+                            additional_weight:"",
+                            items:[],
+                        };
+                        this.errors = [];
+                        this.importError = [];
+                        $(".selectpicker").filter('.express').selectpicker('val',[]);
+                    });
                 },
                 _verifyLogistic(){
                     let error = {};
@@ -567,15 +724,29 @@
                         this.$forceUpdate();
                         return;
                     }
-                    this.selectedModel.logistic.unshift(this.model.logistic);
-                    this.model.logistic = {
+                    let url = "{{url('maintenance/priceModel/apiStoreLogistic')}}";
+                    let params = this.model.logistic;
+                    params.owner_id = this.ownerTemp.id;
+                    window.tempTip.postBasicRequest(url,params,res=>{
+                        if (res && res.errors){
+                            this.errors = res.errors;
+                            return;
+                        }
+                        this.model.logistic.id = res.id;
+                        this.model.logistic.items.forEach((item,i)=>{
+                            item.id = res.details[i].id;
+                        });
+                        this.selectedModel.logistic.unshift(this.model.logistic);
+                        this.model.logistic = {
                             items:[],
                             other_ranges:[],
                             ranges:[],
-                    };
-                    this.errors = [];
-                    this.importError = [];
-                    $(".selectpicker").filter('.logistic').selectpicker('val',[]);
+                            logistics:[],
+                        };
+                        this.errors = [];
+                        this.importError = [];
+                        $(".selectpicker").filter('.logistic').selectpicker('val',[]);
+                    });
                 },
                 _verifyDirectLogistic(){
                     let error = {};
@@ -586,12 +757,25 @@
                         this.$forceUpdate();
                         return;
                     }
-                    this.selectedModel.directLogistic = this.model.directLogistic;
-                    this.model.directLogistic = {
-                        items:[],
-                    };
-                    this.errors = [];
-                    this.importError = [];
+                    let url = "{{url('maintenance/priceModel/apiStoreDirectLogistic')}}";
+                    let params = this.model.directLogistic;
+                    params.owner_id = this.ownerTemp.id;
+                    window.tempTip.postBasicRequest(url,params,res=>{
+                        if (res && res.errors){
+                            this.errors = res.errors;
+                            return;
+                        }
+                        this.model.directLogistic.id = res.id;
+                        this.model.directLogistic.items.forEach((item,i)=>{
+                            item.id = res.details[i].id;
+                        });
+                        this.selectedModel.directLogistic = this.model.directLogistic;
+                        this.model.directLogistic = {
+                            items:[],
+                        };
+                        this.errors = [];
+                        this.importError = [];
+                    });
                 },
                 //增加作业费特征子项
                 addOperationItem(){
@@ -622,6 +806,7 @@
                         if (!this.model.operation.items[index].feature){
                             this.model.operation.items[index].features = this._createFeature();
                             this.thisOperationItemIndex = index;
+                            this.$forceUpdate();
                             $("#addFeatureModal").modal("show");
                             return;
                         }
@@ -634,12 +819,13 @@
                     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=>{
-                        if (!res.data.data || res.data.data.length === 0){
-                            res.data.data = this._createFeature();
+                        if (!res || res.length === 0){
+                            res = this._createFeature();
                         }
-                        if (index === -1) this.model.operation.features = res.data.data;
-                        else this.model.operation.items[index].features = res.data.data;
+                        if (index === -1) this.model.operation.features = res;
+                        else this.model.operation.items[index].features = res;
                         this.thisOperationItemIndex = index;
+                        this.$forceUpdate();
                         $("#addFeatureModal").modal("show");
                     });
                 },
@@ -860,16 +1046,16 @@
                 },
                 //导入直发车子项
                 importDirectLogistic(e){
-                    tempTip.setIndex(1099);
+                    window.tempTip.setIndex(1099);
                     let file=e.target.files[0];
                     if (!file){
-                        tempTip.setDuration(3000);
-                        tempTip.show("未选择文件");
+                        window.tempTip.setDuration(3000);
+                        window.tempTip.show("未选择文件");
                         return;
                     }
                     let formData = new FormData();
                     formData.append("file",file);
-                    axios.post('{{url('maintenance/priceModel/directLogistic/import')}}',formData,{
+                    window.axios.post('{{url('maintenance/priceModel/directLogistic/import')}}',formData,{
                         'Content-Type':'multipart/form-data'
                     }).then(res=>{
                         if (res.data.success) {
@@ -883,21 +1069,340 @@
                                 });
                             }else this.model.directLogistic.items = res.data.data;
                             this.importError = res.data.errors;
-                            tempTip.setDuration(3000);
-                            tempTip.showSuccess("导入成功!");
+                            window.tempTip.setDuration(3000);
+                            window.tempTip.showSuccess("导入成功!");
                             return;
                         }
-                        tempTip.setDuration(3000);
-                        tempTip.show(res.data.data);
+                        window.tempTip.setDuration(3000);
+                        window.tempTip.show(res.data.data);
                     }).catch(err=> {
-                        tempTip.setDuration(3000);
-                        tempTip.show("网络错误:"+err);
+                        window.tempTip.setDuration(3000);
+                        window.tempTip.show("网络错误:"+err);
                     })
                 },
                 //删除直发车子项
                 delDirectLogisticItem(index){
                     this.$delete(this.model.directLogistic.items,index);
                 },
+                //改变客户
+                selectOwner(){
+                    let id = this.owner.customer_id;
+                    this.customers.some(customer=>{
+                        if (id === customer.id){
+                            this.owner.customer_name = customer.name;
+                            return true;
+                        }
+                    });
+                },
+                //改变小组
+                selectGroup(){
+                    let id = this.owner.owner_group_id;
+                    this.ownerGroups.some(group=>{
+                        if (id === group.id){
+                            this.owner.owner_group_name = group.name;
+                            return true;
+                        }
+                    });
+                },
+                //获取引入计费模型查询列表搜索
+                searchPriceModel(){
+                    this.isSearch = true;
+                    switch (this.type) {
+                        case "storage":
+                            this._getStoragePriceModel();
+                            break;
+                        case "operation":
+                            this._getOperationPriceModel();
+                            break;
+                        case "express":
+                            this._getExpressPriceModel();
+                            break;
+                        case "logistic":
+                            this._getLogisticPriceModel();
+                            break;
+                        default:
+                            this._getDirectLogisticPriceModel();
+                    }
+                },
+                _getStoragePriceModel(){
+                    let url = "{{url('maintenance/priceModel/apiGetStorage')}}";
+                    window.tempTip.postBasicRequest(url,this.introduce,res=>{
+                        let result = [];
+                        let mapping = {};
+                        res.forEach(model=> {
+                            let text = model.name+" ("+model.counting_type+"-"+model.using_type+")";
+                            result.push({id:model.id,text:text});
+                            mapping[model.id] = {
+                                name : model.name,
+                                counting_type : model.counting_type,
+                                using_type : model.using_type,
+                                minimum_area : model.minimum_area,
+                                price : model.price,
+                                discount_type : model.discount_type,
+                                discount_value : model.discount_value,
+                                unit_id : model.unit_id,
+                            };
+                        });
+                        this.searchResult = result;
+                        this.searchResultMapping = mapping;
+                        this.isSearch = false;
+                    });
+                },
+                _getOperationPriceModel(){
+                    let url = "{{url('maintenance/priceModel/apiGetOperation')}}";
+                    window.tempTip.postBasicRequest(url,this.introduce,res=>{
+                        let result = [];
+                        let mapping = {};
+                        res.forEach(model=> {
+                            let text = model.name+" ("+model.operation_type+"-"+model.strategy+")";
+                            result.push({id:model.id,text:text});
+                            mapping[model.id] = {
+                                name : model.name,
+                                operation_type : model.operation_type,
+                                strategy : model.strategy,
+                                feature : model.feature,
+                                featureFormat : model.featureFormat,
+                                remark : model.remark,
+                                items:model.items,
+                            };
+                        });
+                        this.searchResult = result;
+                        this.searchResultMapping = mapping;
+                        this.isSearch = false;
+                    });
+                },
+                _getExpressPriceModel(){
+                    let url = "{{url('maintenance/priceModel/apiGetExpress')}}";
+                    window.tempTip.postBasicRequest(url,this.introduce,res=>{
+                        let result = [];
+                        let mapping = {};
+                        res.forEach(model=> {
+                            let text = model.name+" (首重:"+model.initial_weight+"KG  续重:"+model.additional_weight+"KG)";
+                            result.push({id:model.id,text:text});
+                            let logistics = [];
+                            model.logistics.forEach(logistic=>{
+                                logistics.push(logistic.id);
+                            });
+                            let items = [];
+                            model.details.forEach(item=>{
+                               items.push({
+                                   province_id:item.province_id,
+                                   initial_weight_price:item.initial_weight_price,
+                                   additional_weight_price:item.additional_weight_price,
+                               });
+                            });
+                            mapping[model.id] = {
+                                logistics : logistics,
+                                name:model.name,
+                                initial_weight:model.initial_weight,
+                                additional_weight:model.additional_weight,
+                                items:items,
+                            };
+                        });
+                        this.searchResult = result;
+                        this.searchResultMapping = mapping;
+                        this.isSearch = false;
+                    });
+                },
+                _getLogisticPriceModel(){
+                    let url = "{{url('maintenance/priceModel/apiGetLogistic')}}";
+                    window.tempTip.postBasicRequest(url,this.introduce,res=>{
+                        let result = [];
+                        let mapping = {};
+                        res.forEach(model=> {
+                            let text = model.name+" (单位一:"+this.poolMapping.units[model.unit_id]+"["+model.unit_range+
+                                "] 单位二:"+this.poolMapping.units[model.other_unit_id]+"["+model.other_unit_range+"])";
+                            result.push({id:model.id,text:text});
+                            let logistics = [];
+                            model.logistics.forEach(logistic=>{
+                                logistics.push(logistic.id);
+                            });
+                            let items = [];
+                            model.details.forEach(item=>{
+                                items.push({
+                                    unit_id:item.unit_id,
+                                    range:item.range,
+                                    province_id:item.province_id,
+                                    city_id:item.city_id,
+                                    unit_price:item.unit_price,
+                                    delivery_fee:item.delivery_fee,
+                                    initial_fee:item.initial_fee,
+                                    initial_amount:item.initial_amount,
+                                    rate:item.rate,
+                                });
+                            });
+                            mapping[model.id] = {
+                                logistics : logistics,
+                                name:model.name,
+                                unit_range:model.unit_range,
+                                unit_id:model.unit_id,
+                                other_unit_range:model.other_unit_range,
+                                other_unit_id:model.other_unit_id,
+                                pick_up_price:model.pick_up_price,
+                                fuel_price:model.fuel_price,
+                                service_price:model.service_price,
+                                items:items,
+                            };
+                        });
+                        this.searchResult = result;
+                        this.searchResultMapping = mapping;
+                        this.isSearch = false;
+                    });
+                },
+                _getDirectLogisticPriceModel(){
+                    let url = "{{url('maintenance/priceModel/apiGetDirectLogistic')}}";
+                    window.tempTip.postBasicRequest(url,this.introduce,res=>{
+                        let result = [];
+                        let mapping = {};
+                        res.forEach(model=> {
+                            let text = model.name+" (起步数:"+model.base_km+"KM)";
+                            result.push({id:model.id,text:text});
+                            let items = [];
+                            model.details.forEach(item=>{
+                                items.push({
+                                    car_type_id:item.car_type_id,
+                                    base_fee:item.base_fee,
+                                    additional_fee:item.additional_fee,
+                                });
+                            });
+                            mapping[model.id] = {
+                                name:model.name,
+                                base_km:model.base_km,
+                                items:items,
+                            };
+                        });
+                        this.searchResult = result;
+                        this.searchResultMapping = mapping;
+                        this.isSearch = false;
+                    });
+                },
+                //提交引入
+                submitIntroduce(){
+                    if (!this.selectedResult || !this.searchResultMapping[this.selectedResult]){
+                        window.tempTip.setDuration(3000);
+                        window.tempTip.show("尚未选择引入项,请单击选择列表,如列表为空则无结果");
+                        return;
+                    }
+                    let model = this.searchResultMapping[this.selectedResult];
+                    switch (this.type) {
+                        case "storage":
+                            this.model.storage = model;
+                            break;
+                        case "operation":
+                            this.model.operation = model;
+                            break;
+                        case "express":
+                            this.model.express = model;
+                            break;
+                        case "logistic":
+                            this.model.logistic = model;
+                            break;
+                        default:
+                            this.model.directLogistic = model;
+                            break;
+                    }
+                    $("#introduce").modal('hide');
+                    window.tempTip.setDuration(2000);
+                    window.tempTip.showSuccess("引入成功");
+                },
+                //删除仓储
+                delStorage(item,index){
+                    window.tempTip.confirm("您确定要删除仓储计费“"+item.name+"”吗?",()=>{
+                        window.tempTip.postBasicRequest("{{url('maintenance/priceModel/apiDelStorage')}}",{id:item.id},res=>{
+                            this.$delete(this.selectedModel.storage,index);
+                            return "删除“"+item.name+"”成功";
+                        });
+                    });
+                },
+                //删除作业
+                delOperation(item,index){
+                    window.tempTip.confirm("您确定要删除作业计费“"+item.name+"”吗?",()=>{
+                        window.tempTip.postBasicRequest("{{url('maintenance/priceModel/apiDelOperation')}}",{id:item.id},res=>{
+                            this.$delete(this.selectedModel.operation,index);
+                            return "删除“"+item.name+"”成功";
+                        });
+                    });
+                },
+                //删除作业子项
+                deleteOperationItem(item,index,parentIndex){
+                    window.tempTip.confirm("您确定要删除该作业子项吗?",()=>{
+                        window.tempTip.postBasicRequest("{{url('maintenance/priceModel/apiDelOperationItem')}}",{id:item.id},res=>{
+                            this.$delete(this.selectedModel.operation[parentIndex].items,index);
+                            return "删除成功";
+                        });
+                    });
+                },
+                //删除快递
+                delExpress(item,index){
+                    window.tempTip.confirm("您确定要删除该快递计费“"+item.name+"”吗?",()=>{
+                        window.tempTip.postBasicRequest("{{url('maintenance/priceModel/apiDelExpress')}}",{id:item.id},res=>{
+                            this.$delete(this.selectedModel.express,index);
+                            return "删除“"+item.name+"”成功";
+                        });
+                    });
+                },
+                //删除快递子项
+                deleteExpressItem(item,index,parentIndex){
+                    window.tempTip.confirm("您确定要删除该快递计费子项吗?",()=>{
+                        window.tempTip.postBasicRequest("{{url('maintenance/priceModel/apiDelExpressItem')}}",{id:item.id},res=>{
+                            this.$delete(this.selectedModel.express[parentIndex].items,index);
+                            return "删除成功";
+                        });
+                    });
+                },
+                //删除物流
+                delLogistic(item,index){
+                    window.tempTip.confirm("您确定要删除该物流计费“"+item.name+"”吗?",()=>{
+                        window.tempTip.postBasicRequest("{{url('maintenance/priceModel/apiDelLogistic')}}",{id:item.id},res=>{
+                            this.$delete(this.selectedModel.logistic,index);
+                            return "删除“"+item.name+"”成功";
+                        });
+                    });
+                },
+                //删除物流子项
+                deleteLogisticItem(item,index,parentIndex){
+                    window.tempTip.confirm("您确定要删除该物流计费子项吗?",()=>{
+                        window.tempTip.postBasicRequest("{{url('maintenance/priceModel/apiDelLogisticItem')}}",{id:item.id},res=>{
+                            this.$delete(this.selectedModel.logistic[parentIndex].items,index);
+                            return "删除成功";
+                        });
+                    });
+                },
+                //删除直发车
+                delDirectLogistic(item){
+                    window.tempTip.confirm("您确定要删除该直发车计费“"+item.name+"”吗?",()=>{
+                        window.tempTip.postBasicRequest("{{url('maintenance/priceModel/apiDelDirectLogistic')}}",{id:item.id},res=>{
+                            this.selectedModel.directLogistic = {};
+                            return "删除“"+item.name+"”成功";
+                        });
+                    });
+                },
+                //删除直发车子项
+                deleteDirectLogisticItem(item,index){
+                    window.tempTip.confirm("您确定要删除该直发车计费子项吗?",()=>{
+                        window.tempTip.postBasicRequest("{{url('maintenance/priceModel/apiDelDirectLogisticItem')}}",{id:item.id},res=>{
+                            this.$delete(this.selectedModel.directLogistic.items,index);
+                            return "删除成功";
+                        });
+                    });
+                },
+                //编辑仓储
+                editStorage(index){
+                    this.switchType("storage");
+                    this.model.storage = JSON.parse(JSON.stringify(this.selectedModel.storage[index]));
+                    this.model.storage.index = index;
+                },
+                //编辑作业
+                editOperation(index){
+                    this.switchType("operation");
+                    this.model.operation = JSON.parse(JSON.stringify(this.selectedModel.operation[index]));
+                    if (this.model.operation.operation_type==='入库') this.model.operation.items.unshift({});
+                    this.model.operation.index = index;
+                },
+                //编辑快递
+                editExpress(){
+
+                },
             },
         });
     </script>

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

@@ -40,15 +40,15 @@
         </div>
         <div class="row" v-for="(item,i) in model.directLogistic.items">
             <label class="col-3">
-                <select class="form-control form-control-sm" v-model="item.car_type_id" :class="errors['item.'+i+'.car_type_id'] ? 'is-invalid' : ''">
+                <select class="form-control form-control-sm" v-model="item.car_type_id" :class="errors['items.'+i+'.car_type_id'] ? 'is-invalid' : ''">
                     <option v-for="car in pool.cars" :value="car.id">@{{ car.name }}</option>
                 </select>
             </label>
             <label class="col-3">
-                <input type="number" step="0.01" class="form-control form-control-sm" v-model="item.base_fee" :class="errors['item.'+i+'.base_fee'] ? 'is-invalid' : ''">
+                <input type="number" step="0.01" class="form-control form-control-sm" v-model="item.base_fee" :class="errors['items.'+i+'.base_fee'] ? 'is-invalid' : ''">
             </label>
             <label class="col-4">
-                <input type="number" step="0.01" class="form-control form-control-sm" v-model="item.additional_fee" :class="errors['item.'+i+'.additional_fee'] ? 'is-invalid' : ''">
+                <input type="number" step="0.01" class="form-control form-control-sm" v-model="item.additional_fee" :class="errors['items.'+i+'.additional_fee'] ? 'is-invalid' : ''">
             </label>
             <label class="col-2 cursor-pointer h3 font-weight-bold text-danger" @click="delDirectLogisticItem(i)">
                 &times;

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

@@ -6,7 +6,7 @@
 <div class="row mt-3">
     <label class="col-3">承运商</label>
     <label class="col-5"><select class="selectpicker express" multiple data-live-search="true" title="承运商(多选)"
-            v-model="model.express.logistics" :class="errors.logistics ? 'is-invalid' : ''">
+            v-model="model.express.logistics" :class="errors.logistic_id ? 'is-invalid' : ''">
         <option v-for="logistic in pool.logistics" :value="logistic.id" v-if="logistic.type != '物流'">@{{ logistic.name }}</option>
     </select></label>
 </div>
@@ -46,15 +46,15 @@
         </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' : ''">
+                <select class="form-control form-control-sm" v-model="item.province_id" :class="errors['items.'+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' : ''">
+                <input type="number" step="0.01" min="0" class="form-control form-control-sm" v-model="item.initial_weight_price" :class="errors['items.'+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' : ''">
+                <input type="number" step="0.01" min="0" class="form-control form-control-sm" v-model="item.additional_weight_price" :class="errors['items.'+i+'.additional_weight_price'] ? 'is-invalid' : ''">
             </label>
             <label class="col-3 cursor-pointer h3 font-weight-bold text-danger" @click="delExpressItem(i)">
                 &times;

+ 70 - 0
resources/views/customer/project/part/_introducePriceModel.blade.php

@@ -0,0 +1,70 @@
+<div class="modal fade" id="introduce">
+    <div class="modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h4 class="modal-title font-weight-bold">
+                    <span v-if="type==='storage'">仓储计费</span>
+                    <span v-if="type==='operation'">作业计费</span>
+                    <span v-if="type==='express'">快递计费</span>
+                    <span v-if="type==='logistic'">物流计费</span>
+                    <span v-if="type==='directLogistic'">直发车计费</span>
+                </h4>
+                <button type="button" class="close" data-dismiss="modal">&times;</button>
+            </div>
+
+            <div class="modal-body">
+                <div class="container-fluid">
+                    <div class="row">
+                        <div class="col-6">
+                            <div class="row">
+                                <label for="introduceCustomer" class="col-3">客户</label>
+                                <select id="introduceCustomer" class="form-control form-control-sm rounded-pill col-6"
+                                        @change="searchPriceModel()" v-model="introduce.customer_id">
+                                    <option v-for="customer in customers" :value="customer.id">@{{ customer.name }}</option>
+                                </select>
+                            </div>
+                            <div class="row mt-2">
+                                <label for="introduceOwner" class="col-3">项目</label>
+                                <select id="introduceOwner" class="form-control form-control-sm rounded-pill col-6"
+                                        @change="searchPriceModel()" v-model="introduce.owner_id">
+                                    <option v-for="ow in pool.owners" :value="ow.id" v-if="!introduce.customer_id || (ow.customer_id == introduce.customer_id)">@{{ ow.name }}</option>
+                                </select>
+                            </div>
+                            <div class="row mt-2" v-if="type=='express' || type=='logistic'">
+                                <label for="introduceLogistic" class="col-3">承运商</label>
+                                <select id="introduceLogistic" class="form-control form-control-sm rounded-pill col-6"
+                                        @change="searchPriceModel()" v-model="introduce.logistic_id">
+                                    <option v-for="logistic in pool.logistics" :value="logistic.id"
+                                    v-if="(type=='express' && logistic.type!='物流') || (type=='logistic' && logistic.type!='快递')">@{{ logistic.name }}</option>
+                                </select>
+                            </div>
+                            <div class="row mt-2">
+                                <label for="introduceName" class="col-3">名称</label>
+                                <input placeholder="模糊搜索,回车提交" @keydown.13="searchPriceModel()" id="introduceName" class="form-control form-control-sm rounded-pill col-8" v-model="introduce.name"/>
+                            </div>
+                        </div>
+                        <div class="col-6">
+                            <div class="row justify-content-center h-100 text-secondary">
+                                <div class="align-self-center h1" v-if="isSearch">
+                                    <i class="fa fa-spinner fa-pulse"></i>
+                                </div>
+                                <div v-else class="w-75">
+                                    <p v-for="re in searchResult" class="border border-2 rounded-pill p-1 mt-1 mb-0 cursor-pointer text-dark"
+                                       :class="re.id == selectedResult ? 'sign-sm' : ''" @click="selectedResult = re.id">
+                                        @{{ re.text }}
+                                    </p>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <div class="modal-footer">
+                <button type="button" class="btn btn-success" @click="submitIntroduce()">引入</button>
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+            </div>
+
+        </div>
+    </div>
+</div>

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

@@ -39,46 +39,46 @@
                     <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">
+                                <select class="form-control form-control-sm col-6" style="min-width: 80px" v-model="detail.unit_id" :class="'items.'+i+'.unit_id' ? 'is-invalid' : ''">
                                     <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">
+                                <select class="form-control form-control-sm col-6" style="min-width: 80px" v-model="detail.range" :class="'items.'+i+'.range' ? 'is-invalid' : ''">
                                     <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">
+                                <select class="form-control form-control-sm" v-model="detail.province_id" :class="'items.'+i+'.province_id' ? 'is-invalid' : ''">
                                     <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">
+                                <select class="form-control form-control-sm" v-model="detail.city_id" :class="'items.'+i+'.city_id' ? 'is-invalid' : ''">
                                     <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>
+                            <label><input type="number" min="0" step="0.001" class="form-control form-control-sm" v-model="detail.unit_price" :class="'items.'+i+'.unit_price' ? 'is-invalid' : ''"></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>
+                            <label><input type="number" min="0" step="0.001" class="form-control form-control-sm" v-model="detail.delivery_fee" :class="'items.'+i+'.delivery_fee' ? 'is-invalid' : ''"></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>
+                            <label><input type="number" min="0" step="0.001" class="form-control form-control-sm" v-model="detail.initial_fee" :class="'items.'+i+'.initial_fee' ? 'is-invalid' : ''"></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>
+                            <label><input type="number" min="0" class="form-control form-control-sm" v-model="detail.initial_amount" :class="'items.'+i+'.initial_amount' ? 'is-invalid' : ''"></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>
+                            <label><input type="number" min="0" step="0.001" class="form-control form-control-sm" v-model="detail.rate" :class="'items.'+i+'.rate' ? 'is-invalid' : ''"></label>
                         </td>
                         <td>
                             <button type="button" class="btn btn-sm btn-outline-danger" @click="delLogisticItem(i)">删</button>

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

@@ -1,13 +1,13 @@
 <div class="row">
     <label for="code" class="col-2 text-info">项目代码</label>
-    <input :readonly="display" type="text"  id="code" class="form-control form-control-sm col-7 mb-0" :class="errors.code ? 'is-invalid' : ''" v-model="owner.code">
+    <input type="text"  id="code" class="form-control form-control-sm col-7 mb-0" :class="errors.code ? 'is-invalid' : ''" v-model="owner.code">
     <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors.code">
         <strong>@{{ errors.code[0] }}</strong>
     </span>
 </div>
 <div class="row mt-3">
     <label for="name" class="col-2 text-info">项目名称</label>
-    <input :readonly="display" type="text"  id="name" class="form-control form-control-sm col-7 mb-0" :class="errors.name ? 'is-invalid' : style" v-model="owner.name">
+    <input type="text"  id="name" class="form-control form-control-sm col-7 mb-0" :class="errors.name ? 'is-invalid' : style" v-model="owner.name">
     <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors.name">
         <strong>@{{ errors.name[0] }}</strong>
     </span>

+ 21 - 19
resources/views/customer/project/part/_operation.blade.php

@@ -19,16 +19,18 @@
     </span>
 </div>
 <div class="row mt-3">
-    <label for="name" class="col-2">名称</label>
-    <input id="name" type="text" name="name" :class="errors.name ? 'is-invalid' : ''" class="col-6 form-control" v-model="model.operation.name">
+    <label class="col-2">名称</label>
+    <input type="text" :class="errors.name ? 'is-invalid' : ''" class="col-6 form-control" v-model="model.operation.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 class="col-2">特征:</label>
-    <label v-if="model.operation.feature">@{{ model.operation.featureFormat }}</label><br>
-    <button type="button" class="btn btn-dark col-2 ml-2" @click="showAddFeatureModal(-1,model.operation.feature)">调整特征</button>
+    <label class="col-8">
+        <label v-if="model.operation.feature">@{{ model.operation.featureFormat }}</label><br>
+        <button type="button" class="btn btn-dark col-2 ml-2" @click="showAddFeatureModal(-1,model.operation.feature)">调整特征</button>
+    </label>
 </div>
 <div class="row mt-3">
     {{--起步--}}
@@ -37,7 +39,7 @@
             <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>
+                    <option value="起步">起步</option>
                 </select></label>
             </div>
             <div class="row mt-2">
@@ -46,7 +48,7 @@
                        v-model="model.operation.items[0].amount" class="form-control" step="1"></label>
             </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 class="offset-3"><small class="text-danger font-weight-bold ml-3">起步数为必填项</small></div>
             </div>
             <div class="row mt-2">
                 <label class="col-3">单位</label>
@@ -55,7 +57,7 @@
                 </select></label>
             </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 class="offset-3"><small class="text-danger font-weight-bold ml-3">单位为必选项</small></div>
             </div>
             <div class="row mt-2">
                 <label class="col-3">单价</label>
@@ -63,7 +65,7 @@
                            :class="errors['items.0.unit_price'] ? 'is-invalid' : ''"></label>
             </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 class="offset-3"><small class="text-danger font-weight-bold ml-3">单价为必填项</small></div>
             </div>
         </div>
     </div>
@@ -71,13 +73,13 @@
     {{--默认--}}
     <div class="card row text-white offset-1 col-9 bg-info">
         <div class="card-header">
-            <div class="pull-left"><span @click="addOperationItem()" class="fa fa-plus-square-o" style="cursor: pointer"></span></div>
+            <div class="pull-left cursor-pointer text-white" @click="addOperationItem()"><small>新增</small>&nbsp;<span class="fa fa-plus-square-o"></span></div>
         </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>
+                    <option value="默认">默认</option>
                 </select></label>
             </div>
             <div class="row mt-2">
@@ -88,7 +90,7 @@
                 <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 class="offset-3"><small class="text-danger font-weight-bold ml-3">数量为必填项</small></div>
             </div>
             <div class="row mt-2">
                 <label class="col-3">单位</label>
@@ -97,7 +99,7 @@
                 </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 class="offset-3"><small class="text-danger font-weight-bold ml-3">单位为必填项</small></div>
             </div>
             <div class="row mt-2">
                 <label class="col-3">单价</label>
@@ -105,7 +107,7 @@
                            :class="errors['items.1.unit_price'] ? 'is-invalid' : ''"></label>
             </div>
             <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 class="offset-3"><small class="text-danger font-weight-bold ml-3">单价为必填项</small></div>
             </div>
         </div>
     </div>
@@ -113,14 +115,14 @@
     {{--特征--}}
     <div v-for="(item,i) in model.operation.items" class="card row text-white offset-1 col-9 bg-secondary" v-if="i>1">
         <div class="card-header">
-            <div class="pull-left"><span @click="addOperationItem()" class="fa fa-plus-square-o" style="cursor: pointer"></span></div>
-            <div class="pull-right"><span @click="delOperationItem(i)" class="fa fa-window-close-o" style="cursor: pointer"></span></div>
+            <div class="pull-left cursor-pointer text-white" @click="addOperationItem()"><small>新增</small>&nbsp;<span class="fa fa-plus-square-o"></span></div>
+            <div class="pull-right cursor-pointer text-white" @click="delOperationItem(i)"><small>删除</small>&nbsp;<span class="fa fa-window-close-o"></span></div>
         </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>
+                    <option value="特征">特征</option>
                 </select></label>
             </div>
             <div class="row mt-2">
@@ -128,7 +130,7 @@
                 <label class="col-5 mb-0"><input type="number" step="1" min="0" :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 class="offset-3"><small class="text-danger font-weight-bold ml-3">数量为必填项</small></div>
             </div>
             <div class="row mt-2">
                 <label class="col-3">单位</label>
@@ -137,7 +139,7 @@
                 </select></label>
             </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 class="offset-3"><small class="text-danger font-weight-bold ml-3">单位为必选项</small></div>
             </div>
             <div class="row mt-2">
                 <label class="col-3">单价</label>
@@ -145,7 +147,7 @@
                        :class="errors['items.'+i+'.unit_price'] ? 'is-invalid' : ''"></label>
             </div>
             <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 class="offset-3"><small class="text-danger font-weight-bold ml-3">单价为必填项</small></div>
             </div>
             <div class="row mt-2">
                 <label class="col-3">特征:</label>

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

@@ -1,4 +1,11 @@
 <div class="row">
+    <label for="name" class="col-2 text-info">名称</label>
+    <input id="name" type="text" :class="errors.name ? 'is-invalid' : ''" class="col-6 form-control" v-model="model.storage.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="counting_type" class="col-2 text-info">计费类型</label>
     <select id="counting_type" class="col-3 form-control"
             :class="errors.counting_type ? 'is-invalid' : ''" v-model="model.storage.counting_type">

+ 117 - 53
resources/views/customer/project/part/_three.blade.php

@@ -1,12 +1,13 @@
 <div class="row">
     <div class="col-6" id="parent">
-        <div class="card">
+        <div class="card" id="storage-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>
@@ -14,15 +15,18 @@
                         <th>单位</th>
                         <th>减免类型</th>
                         <th>减免值</th>
+                        <th></th>
                     </tr>
-                    <tr v-for="item in selectedModel.storage">
+                    <tr v-for="(item,i) in selectedModel.storage" style="cursor: pointer" @dblclick="editStorage(i)">
+                        <td>@{{ item.name }}</td>
                         <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>
+                        <td>@{{ poolMapping.units ? poolMapping.units[item.unit_id] : '' }}</td>
+                        <td class="cursor-pointer" @click.stop="delStorage(item,i)"><span class="font-weight-bold text-danger">&times;</span></td>
                     </tr>
                 </table>
             </div>
@@ -36,25 +40,41 @@
                     <div class="row font-weight-bold">
                         <div class="cursor-pointer" @click="show('operation-list-in')"><span class="fa" :class="upList['operation-list-in'] ? 'fa-caret-right' : 'fa-caret-down'"></span> 入库</div>
                     </div>
-                    <div class="container-fluid" v-for="(operation,i) in selectedModel.operation" v-if="operation.operation_type === '入库'" id="operation-list-in">
-                        <div class="row offset-1">
-                            <label class="font-weight-bold cursor-pointer" @click="show('operation-item-'+i)">
-                                <span class="fa" :class="upList['operation-item-'+i] ? 'fa-caret-right' : 'fa-caret-down'"></span>
-                                &nbsp;@{{ operation.strategy }}:
-                            </label>
-                            <label>@{{ operation.name }}</label>
-                            <label v-if="operation.remark" class="text-secondary">&nbsp;&nbsp;(@{{ operation.remark }})</label>
-                        </div>
-                        <div class="row offset-1 small mt-0" style="background-color: RGB(248,248,248)" v-if="operation.strategy === '特征'">
-                            @{{ operation.featureFormat }}
-                        </div>
-                        <div class="container-fluid offset-2" :id="'operation-item-'+i">
-                            <div v-for="item in operation.items" class="container-fluid">
-                                <div class="row"><label>@{{ item.strategy }}</label>:
-                                    <b>@{{ item.amount }}</b>/@{{ poolMapping.units[item.unit_id] }} (<b>@{{ item.unit_price }}</b>元)
+                    <div id="operation-list-in">
+                        <div class="container-fluid" v-for="(operation,i) in selectedModel.operation"
+                             @dblclick="editOperation(i)" style="cursor: pointer" v-if="operation.operation_type === '入库'">
+                            <div class="row">
+                                <div class="col-9 offset-1">
+                                    <label class="font-weight-bold cursor-pointer" @click.stop="show('operation-item-'+i)">
+                                        <span class="fa" :class="upList['operation-item-'+i] ? 'fa-caret-right' : 'fa-caret-down'"></span>
+                                        &nbsp;@{{ operation.strategy }}:
+                                    </label>
+                                    <label>@{{ operation.name }}</label>
+                                    <label v-if="operation.remark" class="text-secondary">&nbsp;&nbsp;(@{{ operation.remark }})</label>
                                 </div>
-                                <div class="row small mt-0" style="background-color: RGB(248,248,248)">
-                                    @{{ item.featureFormat }}
+                                <div class="col-1">
+                                    <span class="cursor-pointer text-danger font-weight-bold"
+                                          v-if="operation.strategy == '特征'" @click.stop="delOperation(operation,i)">&times;</span>
+                                </div>
+                            </div>
+                            <div class="row offset-1 small mt-0" style="background-color: RGB(248,248,248)" v-if="operation.strategy === '特征'">
+                                @{{ operation.featureFormat }}
+                            </div>
+                            <div class="container-fluid offset-2" :id="'operation-item-'+i">
+                                <div v-for="(item,j) in operation.items" class="container-fluid">
+                                    <div class="row">
+                                        <div class="col-10">
+                                            <label>@{{ item.strategy }}</label>:
+                                            <b>@{{ item.amount }}</b>&nbsp;@{{ poolMapping.units ? poolMapping.units[item.unit_id] : '' }} / <b>@{{ item.unit_price }}</b>元
+                                        </div>
+                                        <div class="col-1">
+                                            <span class="cursor-pointer text-danger font-weight-bold"
+                                                  v-if="item.strategy == '特征'" @click.stop="deleteOperationItem(item,j,i)">&times;</span>
+                                        </div>
+                                    </div>
+                                    <div class="row small mt-0 ml-1" style="background-color: RGB(248,248,248)" v-if="item.strategy == '特征'">
+                                        @{{ item.featureFormat }}
+                                    </div>
                                 </div>
                             </div>
                         </div>
@@ -62,25 +82,41 @@
                     <div class="row font-weight-bold">
                         <div class="cursor-pointer" @click="show('operation-list-out')"><span class="fa" :class="upList['operation-list-out'] ? 'fa-caret-right' : 'fa-caret-down'"></span> 出库</div>
                     </div>
-                    <div class="container-fluid" v-for="(operation,i) in selectedModel.operation" v-if="operation.operation_type === '出库'" id="operation-list-out">
-                        <div class="row offset-1">
-                            <label class="font-weight-bold cursor-pointer" @click="show('operation-item-'+i)">
-                                <span class="fa" :class="upList['operation-item-'+i] ? 'fa-caret-right' : 'fa-caret-down'"></span>
-                                &nbsp;@{{ operation.strategy }}:
-                            </label>
-                            <label>@{{ operation.name }}</label>
-                            <label v-if="operation.remark" class="text-secondary">&nbsp;&nbsp;(@{{ operation.remark }})</label>
-                        </div>
-                        <div class="row offset-1 small mt-0" style="background-color: RGB(248,248,248)" v-if="operation.strategy === '特征'">
-                            @{{ operation.featureFormat }}
-                        </div>
-                        <div class="container-fluid offset-2" :id="'operation-item-'+i">
-                            <div v-for="item in operation.items" class="container-fluid">
-                                <div class="row"><label>@{{ item.strategy }}</label>:
-                                    <b>@{{ item.amount }}</b>/@{{ poolMapping.units[item.unit_id] }} (<b>@{{ item.unit_price }}</b>元)
+                    <div id="operation-list-out">
+                        <div class="container-fluid" v-for="(operation,i) in selectedModel.operation"
+                             @dblclick="editOperation(i)" style="cursor: pointer" v-if="operation.operation_type === '出库'">
+                            <div class="row">
+                                <div class="col-9 offset-1">
+                                    <label class="font-weight-bold cursor-pointer" @click.stop="show('operation-item-'+i)">
+                                        <span class="fa" :class="upList['operation-item-'+i] ? 'fa-caret-right' : 'fa-caret-down'"></span>
+                                        &nbsp;@{{ operation.strategy }}:
+                                    </label>
+                                    <label>@{{ operation.name }}</label>
+                                    <label v-if="operation.remark" class="text-secondary">&nbsp;&nbsp;(@{{ operation.remark }})</label>
+                                </div>
+                                <div class="col-1">
+                                    <span class="cursor-pointer text-danger font-weight-bold"
+                                          v-if="operation.strategy == '特征'" @click.stop="delOperation(operation,i)">&times;</span>
                                 </div>
-                                <div class="row small mt-0" style="background-color: RGB(248,248,248)">
-                                    @{{ item.featureFormat }}
+                            </div>
+                            <div class="row offset-1 small mt-0" style="background-color: RGB(248,248,248)" v-if="operation.strategy === '特征'">
+                                @{{ operation.featureFormat }}
+                            </div>
+                            <div class="container-fluid offset-2" :id="'operation-item-'+i">
+                                <div v-for="(item,j) in operation.items" class="container-fluid">
+                                    <div class="row">
+                                        <div class="col-10">
+                                            <label>@{{ item.strategy }}</label>:
+                                            <b>@{{ item.amount }}</b>&nbsp;@{{ poolMapping.units ? poolMapping.units[item.unit_id] : '' }} / <b>@{{ item.unit_price }}</b>元
+                                        </div>
+                                        <div class="col-1">
+                                            <span class="cursor-pointer text-danger font-weight-bold"
+                                                  v-if="item.strategy == '特征'" @click.stop="deleteOperationItem(item,j,i)">&times;</span>
+                                        </div>
+                                    </div>
+                                    <div class="row small mt-0 ml-1" style="background-color: RGB(248,248,248)" v-if="item.strategy == '特征'">
+                                        @{{ item.featureFormat }}
+                                    </div>
                                 </div>
                             </div>
                         </div>
@@ -100,12 +136,13 @@
                         <th>首重值(KG)</th>
                         <th>续重值(KG)</th>
                         <th>详情</th>
+                        <th></th>
                     </tr>
-                    <tbody v-for="(express,i) in selectedModel.express">
+                    <tbody v-for="(express,i) in selectedModel.express" @click="editExpress()">
                         <tr>
                             <td>
                                 <div class="text-overflow-warp-100 small">
-                                    <label v-for="(logistic,j) in express.logistics" class="m-0">@{{ poolMapping.logistics[logistic] }}</label>
+                                    <label v-for="(logistic,j) in express.logistics" class="m-0">@{{ poolMapping.logistics ? poolMapping.logistics[logistic] : '' }}</label>
                                 </div>
                             </td>
                             <td>@{{ express.name }}</td>
@@ -114,6 +151,9 @@
                             <td @click="show('express-item-'+i)" class="cursor-pointer">
                                 <span class="fa" :class="upList['express-item-'+i] ? 'fa-angle-double-right' : 'fa-angle-double-down'"></span>
                                 &nbsp;@{{ express.items.length }} 省份</td>
+                            <td>
+                                <span class="cursor-pointer text-danger font-weight-bold" @click="delExpress(express,i)">&times;</span>
+                            </td>
                         </tr>
                         <tr>
                             <td colspan="5">
@@ -123,11 +163,15 @@
                                             <th>省份</th>
                                             <th>首重价格</th>
                                             <th>续重价格</th>
+                                            <th></th>
                                         </tr>
-                                        <tr v-for="(item,i) in express.items">
-                                            <td>@{{ poolMapping.provinces[item.province_id] }}</td>
+                                        <tr v-for="(item,j) in express.items">
+                                            <td>@{{ poolMapping.provinces ? poolMapping.provinces[item.province_id] : '' }}</td>
                                             <td>@{{ item.initial_weight_price }}</td>
                                             <td>@{{ item.additional_weight_price }}</td>
+                                            <td>
+                                                <span class="cursor-pointer text-danger font-weight-bold" @click="deleteExpressItem(item,j,i)">&times;</span>
+                                            </td>
                                         </tr>
                                     </table>
                                 </div>
@@ -154,18 +198,19 @@
                         <th>燃油附加费</th>
                         <th>信息服务费</th>
                         <th>详情</th>
+                        <th></th>
                     </tr>
                     <tbody v-for="(logistic,i) in selectedModel.logistic">
                         <tr>
                             <td>
                                 <div class="text-overflow-warp-100 small">
-                                    <label v-for="(logistic,j) in logistic.logistics" class="m-0">@{{ poolMapping.logistics[logistic] }}</label>
+                                    <label v-for="(logistic,j) in logistic.logistics" class="m-0">@{{ poolMapping.logistics ? poolMapping.logistics[logistic] : '' }}</label>
                                 </div>
                             </td>
                             <td>@{{ logistic.name }}</td>
-                            <td>@{{ poolMapping.units[logistic.unit_id] }}</td>
+                            <td>@{{ poolMapping.units ? poolMapping.units[logistic.unit_id] : '' }}</td>
                             <td>@{{ logistic.unit_range }}</td>
-                            <td>@{{ poolMapping.units[logistic.other_unit_id] }}</td>
+                            <td>@{{ poolMapping.units ? poolMapping.units[logistic.other_unit_id] : '' }}</td>
                             <td>@{{ logistic.other_unit_range }}</td>
                             <td>@{{ logistic.pick_up_price }}</td>
                             <td>@{{ logistic.fuel_price }}</td>
@@ -174,6 +219,9 @@
                                 <span class="fa" :class="upList['logistic-item-'+i] ? 'fa-angle-double-right' : 'fa-angle-double-down'"></span>
                                 &nbsp;@{{ logistic.items.length }} 地区
                             </td>
+                            <td>
+                                <span class="cursor-pointer text-danger font-weight-bold" @click="delLogistic(logistic,i)">&times;</span>
+                            </td>
                         </tr>
                         <tr>
                             <td colspan="9">
@@ -189,17 +237,21 @@
                                             <th>起始计费</th>
                                             <th>起始计数</th>
                                             <th>费率(%)</th>
+                                            <th></th>
                                         </tr>
-                                        <tr v-for="item in logistic.items">
-                                            <td class="font-weight-bold">@{{ poolMapping.provinces[item.province_id] }}</td>
-                                            <td class="font-weight-bold">@{{ poolMapping.cities[item.city_id] }}</td>
-                                            <td>@{{ poolMapping.units[item.unit_id] }}</td>
+                                        <tr v-for="(item,j) in logistic.items">
+                                            <td class="font-weight-bold">@{{ poolMapping.provinces ? poolMapping.provinces[item.province_id] : '' }}</td>
+                                            <td class="font-weight-bold">@{{ poolMapping.cities ? poolMapping.cities[item.city_id] : '' }}</td>
+                                            <td>@{{ poolMapping.units ? poolMapping.units[item.unit_id] : '' }}</td>
                                             <td>@{{ item.range }}</td>
                                             <td>@{{ item.unit_price }}</td>
                                             <td>@{{ item.delivery_fee }}</td>
                                             <td>@{{ item.initial_fee }}</td>
                                             <td>@{{ item.initial_amount }}</td>
                                             <td>@{{ item.rate }}<span v-if="item.rate" class="font-weight-bold">&nbsp;%</span></td>
+                                            <td>
+                                                <span class="cursor-pointer text-danger font-weight-bold" @click="deleteLogisticItem(item,j,i)">&times;</span>
+                                            </td>
                                         </tr>
                                     </table>
                                 </div>
@@ -217,6 +269,9 @@
                 <div class="row">
                     <label class="col-4">名称:<b>@{{ selectedModel.directLogistic.name }}</b></label>
                     <label class="col-4">起步数(KM):<b>@{{ selectedModel.directLogistic.base_km }}</b></label>
+                    <label class="col-1 offset-3" v-if="selectedModel.directLogistic.name">
+                        <span class="cursor-pointer text-danger font-weight-bold" @click="delDirectLogistic(selectedModel.directLogistic)">&times;</span>
+                    </label>
                 </div>
                 <div class="row">
                     <div class="cursor-pointer text-primary col-2" @click="show('directLogistic-item')">
@@ -227,11 +282,15 @@
                                 <th>车型</th>
                                 <th>起步费</th>
                                 <th>续费(元/KM)</th>
+                                <th></th>
                             </tr>
                             <tr v-for="(item,i) in selectedModel.directLogistic.items">
-                                <td>@{{ poolMapping.cars[item.car_type_id] }}</td>
+                                <td>@{{ poolMapping.cars ? poolMapping.cars[item.car_type_id] : '' }}</td>
                                 <td>@{{ item.base_fee }}</td>
                                 <td>@{{ item.additional_fee }}</td>
+                                <td>
+                                    <span class="cursor-pointer text-danger font-weight-bold" @click="deleteDirectLogisticItem(item,i)">&times;</span>
+                                </td>
                             </tr>
                         </table>
                     </div>
@@ -266,9 +325,14 @@
                 <div v-show="type == 'directLogistic'">
                     @include("customer.project.part._directLogistic")
                 </div>
+                @include("customer.project.part._introducePriceModel")
                 <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 class="col-2"></div>
+                    <button type="button" class="btn btn-success ml-1 col-4" @click="saveModel()">保存</button>
+                    <button type="button" class="btn btn-sm btn-info text-white offset-1 col-2"
+                            data-toggle="modal" data-target="#introduce" @click="loadIntroduce()">引入</button>
+                    <h5><span class="ml-0 fa fa-question-circle-o cursor-pointer"
+                              data-toggle="tooltip" data-placement="top" title="引入克隆一份已存在模型"></span></h5>
                 </div>
             </div>
         </div>

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

@@ -16,6 +16,15 @@
         <strong>@{{ errors.owner_group_id[0] }}</strong>
     </span>
 </div>
+<div class="row mt-3">
+    <label for="warehouse_id" class="col-2 text-info">仓库</label>
+    <select id="warehouse_id" v-model="owner.warehouse_id" class="form-control form-control-sm col-4 mb-0" :class="errors.warehouse_id ? 'is-invalid' : ''" >
+        <option v-for="warehouse in warehouses" :value="warehouse.id">@{{ warehouse.name }}</option>
+    </select>
+    <span class="invalid-feedback offset-2 mt-0" role="alert" v-if="errors.warehouse_id">
+        <strong>@{{ errors.warehouse_id[0] }}</strong>
+    </span>
+</div>
 <div class="row mt-3">
     <label for="tax_rate" class="col-2">税率<span class="badge badge-secondary">%</span></label>
     <input type="number" v-model="owner.tax_rate" step="0.01" id="tax_rate" class="form-control form-control-sm col-3 mb-0" :class="errors.tax_rate ? 'is-invalid' : ''">

+ 9 - 9
resources/views/maintenance/priceModel/operation/_addOutStorageRuleModal.blade.php → resources/views/maintenance/priceModel/operation/_addItemModal.blade.php

@@ -1,38 +1,38 @@
-<div class="modal fade" tabindex="-1" role="dialog" id="addOutStorageRule">
+<div class="modal fade" tabindex="-1" role="dialog" id="addItem">
     <div class="modal-dialog modal-dialog-centered">
         <div class="modal-content">
             <div class="modal-body">
                 <div class="mt-3 row">
                     <label for="strategy" class="col-4">计费策略</label>
-                    <select id="strategy" class="form-control form-control-sm col-6" v-model="rule.strategy">
-                        <optgroup v-if="existStrategy.starting && rule.strategy!='起步'" label="起步"></optgroup>
+                    <select id="strategy" class="form-control form-control-sm col-6" v-model="item.strategy">
+                        <optgroup v-if="existStrategy.starting && item.strategy!='起步'" label="起步"></optgroup>
                         <option v-else>起步</option>
-                        <optgroup v-if="existStrategy.default && rule.strategy!='默认'" label="默认"></optgroup>
+                        <optgroup v-if="existStrategy.default && item.strategy!='默认'" label="默认"></optgroup>
                         <option v-else>默认</option>
                         <option>特征</option>
                     </select>
                 </div>
                 <div class="mt-3 row">
                     <label for="amount" class="col-4">起步数</label>
-                    <input type="number" min="0" id="amount" class="form-control form-control-sm col-8"  v-model="rule.amount">
+                    <input type="number" min="0" id="amount" class="form-control form-control-sm col-8"  v-model="item.amount">
                 </div>
                 <div class="mt-3 row">
                     <label for="unit_id" class="col-4">单位</label>
-                    <select id="unit_id" class="form-control form-control-sm col-6" v-model="rule.unit_id">
+                    <select id="unit_id" class="form-control form-control-sm col-6" v-model="item.unit_id">
                         <option v-for="unit in units" :value="unit.id">@{{ unit.name }}</option>
                     </select>
                 </div>
                 <div class="mt-3 row">
                     <label for="unit_price" class="col-4">单价</label>
-                    <input type="number" min="0" step="0.001" id="unit_price" class="form-control form-control-sm col-8" v-model="rule.unit_price">
+                    <input type="number" min="0" step="0.001" id="unit_price" class="form-control form-control-sm col-8" v-model="item.unit_price">
                 </div>
                 <div class="mt-3 row">
                     <label for="priority" class="col-4">优先级</label>
-                    <input type="number" min="0" id="priority" class="form-control form-control-sm col-8" v-model="rule.priority">
+                    <input type="number" min="0" id="priority" class="form-control form-control-sm col-8" v-model="item.priority">
                 </div>
             </div>
             <div class="modal-footer">
-                <button type="button" class="btn btn-success" @click="submitRule()">提交</button>
+                <button type="button" class="btn btn-success" @click="submitItem()">提交</button>
             </div>
         </div>
     </div>

+ 35 - 36
resources/views/maintenance/priceModel/operation/create.blade.php

@@ -55,7 +55,7 @@
                     <strong>@{{ errors.name[0] }}</strong>
                 </span>
             </div>
-            <div class="row mt-3">
+            <div class="row mt-3" v-if="model.strategy == '特征'">
                 <label class="col-2">特征:</label>
                 <label v-if="model.feature">
                     @{{ model.feature }}
@@ -71,69 +71,68 @@
                 </span>
             </div>
             <div class="row mt-3">
-                <div v-for="(rule,i) in model.rules" class="card row text-white col-8" :class="i>0 ? 'bg-secondary mt-2' : 'bg-info'">
-                    <div class="card-header" v-if="model.operation_type=='出库'">
+                <div v-for="(item,i) in model.items" class="card row text-white col-8" :class="i>0 ? 'bg-secondary mt-2' : 'bg-info'">
+                    <div class="card-header">
                         <div class="pull-left" v-if="i==0"><span @click="addRule()" class="fa fa-plus-square-o" style="cursor: pointer"></span></div>
-                        <div class="pull-right" v-if="model.rules.length > 1"><span @click="delRule(i)" class="fa fa-window-close-o" style="cursor: pointer"></span></div>
+                        <div class="pull-right" v-if="model.items.length > 1"><span @click="delRule(i)" class="fa fa-window-close-o" style="cursor: pointer"></span></div>
                     </div>
                     <div class="card-body">
                         <div class="row">
                             <div class="col-4 form-inline">
-                                <label for="amount"><span v-if="model.operation_type=='出库'">起步数:</span><span v-else>计量:</span></label>
-                                <input id="amount" :readonly="(model.operation_type=='出库' && rule.strategy=='起步') || model.operation_type!='出库' ? false : true"
-                                       type="number" :class="errors['rules.'+i+'.amount'] ? 'is-invalid' : ''" v-model="rule.amount" class="form-control" required>
-                                <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors['rules.'+i+'.amount']">
+                                <label for="amount"><span v-if="item.strategy=='起步'">起步数:</span><span v-else>计量:</span></label>
+                                <input id="amount" type="number" :class="errors['items.'+i+'.amount'] ? 'is-invalid' : ''" v-model="item.amount" class="form-control" required>
+                                <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors['items.'+i+'.amount']">
                                     <strong>必须为整数</strong>
                                 </span>
                             </div>
                             <div class="col-4 form-inline">
                                 <label for="unit_id">单位:</label>
-                                <select id="unit_id" v-model="rule.unit_id" class="form-control" :class="errors['rules.'+i+'.unit_id'] ? 'is-invalid' : ''" required>
+                                <select id="unit_id" v-model="item.unit_id" class="form-control" :class="errors['items.'+i+'.unit_id'] ? 'is-invalid' : ''" required>
                                     <option v-for="unit in units" :value="unit.id">@{{ unit.name }}</option>
                                 </select>
-                                <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors['rules.'+i+'.unit_id']">
+                                <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors['items.'+i+'.unit_id']">
                                     <strong>必选项</strong>
                                 </span>
                             </div>
                             <div class="col-4 form-inline">
                                 <label for="unit_price">单价:</label>
-                                <input id="unit_price" type="number" min="0" step="0.001" class="form-control" v-model="rule.unit_price"  required
-                                       :class="errors['rules.'+i+'.unit_price'] ? 'is-invalid' : ''">
+                                <input id="unit_price" type="number" min="0" step="0.001" class="form-control" v-model="item.unit_price"  required
+                                       :class="errors['items.'+i+'.unit_price'] ? 'is-invalid' : ''">
                             </div>
-                            <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors['rules.'+i+'.unit_price']">
+                            <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors['items.'+i+'.unit_price']">
                                 <strong>必须为数字且不得为负</strong>
                             </span>
                         </div>
-                        <div class="row mt-2" v-if="model.operation_type=='出库'">
+                        <div class="row mt-2">
                             <label for="out_priority" class="col-2">优先级:</label>
-                            <input type="number" min="0" id="out_priority" v-model="rule.priority" :class="errors['rules.'+i+'.priority'] ? 'is-invalid' : ''" class="col-5 form-control">
-                            <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors['rules.'+i+'.priority']">
+                            <input type="number" min="0" id="out_priority" v-model="item.priority" :class="errors['items.'+i+'.priority'] ? 'is-invalid' : ''" class="col-5 form-control">
+                            <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors['items.'+i+'.priority']">
                                 <strong>必须为整数且数值区间为[0-100]</strong>
                             </span>
                         </div>
-                        <div class="row mt-2" v-if="model.operation_type=='出库'">
-                            <label for="out_storage_strategy" class="col-2">出库策略:</label>
-                            <select id="out_storage_strategy" v-model="rule.strategy" class="col-5 form-control"
-                                    @change="outRuleUnique(rule.strategy)"
-                                    :class="errors['rules.'+i+'.strategy'] ? 'is-invalid' : ''">
-                                <optgroup v-if="existStrategy.starting && rule.strategy!='起步'" label="起步"></optgroup>
+                        <div class="row mt-2">
+                            <label for="out_storage_strategy" class="col-2">策略:</label>
+                            <select id="out_storage_strategy" v-model="item.strategy" class="col-5 form-control"
+                                    @change="outRuleUnique(item.strategy)"
+                                    :class="errors['items.'+i+'.strategy'] ? 'is-invalid' : ''">
+                                <optgroup v-if="existStrategy.starting && item.strategy!='起步'" label="起步"></optgroup>
                                 <option v-else>起步</option>
-                                <optgroup v-if="existStrategy.default && rule.strategy!='默认'" label="默认"></optgroup>
+                                <optgroup v-if="existStrategy.default && item.strategy!='默认'" label="默认"></optgroup>
                                 <option v-else>默认</option>
                                 <option>特征</option>
                             </select>
-                            <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors['rules.'+i+'.strategy']">
+                            <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors['items.'+i+'.strategy']">
                                 <strong>必选项</strong>
                             </span>
                         </div>
-                        <div class="row mt-2" v-if="model.operation_type=='出库'">
+                        <div class="row mt-2" v-if="item.strategy == '特征'">
                             <label class="col-2">特征:</label>
-                            <label v-if="rule.feature">@{{ rule.feature }}</label>
-                            <button type="button" class="btn btn-dark col-2 ml-2" @click="showAddFeatureModal(i,rule.feature)">调整特征</button>
+                            <label v-if="item.feature">@{{ item.feature }}</label>
+                            <button type="button" class="btn btn-dark col-2 ml-2" @click="showAddFeatureModal(i,item.feature)">调整特征</button>
                         </div>
                     </div>
                 </div>
-                <label hidden><input name="rules" :value="JSON.stringify(model.rules)"></label>
+                <label hidden><input name="items" :value="JSON.stringify(model.items)"></label>
             </div>
             <div class="row mt-3">
                 <label for="remark" class="col-2">备注</label>
@@ -161,7 +160,7 @@
                     priority:"{{old('priority') ?? (isset($model) ? $model->priority : '')}}",
                     feature:"{{old('feature') ?? (isset($model) ? $model->feature : '')}}",
                     remark:"{{old('remark') ?? (isset($model) ? $model->remark : '')}}",
-                    rules:{!! old('rules') ? json_encode(old('rules')) : (isset($model)&&$model->rules ? $model->rules : "[{strategy:'',amount:'',unit_id:'',unit_price:'',feature:'',priority:''}]")!!},
+                    items:{!! old('items') ? json_encode(old('items')) : (isset($model)&&$model->items ? $model->items : "[{strategy:'',amount:'',unit_id:'',unit_price:'',feature:'',priority:''}]")!!},
                 },
                 owners : [
                     @foreach($owners as $owner)
@@ -187,15 +186,15 @@
                     if (strategy==='默认') this.existStrategy.default = true;
                     let startingSign = true;
                     let defaultSign = true;
-                    this.model.rules.forEach(rule=>{
-                        if (rule.strategy == '默认')defaultSign = false;
-                        if (rule.strategy == '起步')startingSign = false;
+                    this.model.items.forEach(item=>{
+                        if (item.strategy === '默认')defaultSign = false;
+                        if (item.strategy === '起步')startingSign = false;
                     });
                     if (startingSign)this.existStrategy.starting = false;
                     if (defaultSign)this.existStrategy.default = false;
                 },
                 addRule(){
-                    this.model.rules.push({
+                    this.model.items.push({
                         "strategy" : "",
                         "amount" : "",
                         "unit_id" : "",
@@ -205,7 +204,7 @@
                     });
                 },
                 delRule(index){
-                    this.$delete(this.model.rules,index);
+                    this.$delete(this.model.items,index);
                 },
                 showAddFeatureModal(index,feature){
                     if (!feature){
@@ -222,7 +221,7 @@
                         $("#addFeatureModal").modal("show");
                         return;
                     }
-                    if (this.oldFeature == feature) {
+                    if (this.oldFeature === feature) {
                         this.thisIndex = index;
                         $("#addFeatureModal").modal("show");
                         return;
@@ -274,7 +273,7 @@
                         .then(res=>{
                             if (res.data.success){
                                 if (this.thisIndex == '-1') this.model.feature = res.data.data;
-                                else this.model.rules[this.thisIndex].feature = res.data.data;
+                                else this.model.items[this.thisIndex].feature = res.data.data;
                                 $("#addFeatureModal").modal("hide");
                                 window.tempTip.setDuration(2000);
                                 window.tempTip.setIndex(1099);

+ 29 - 50
resources/views/maintenance/priceModel/operation/index.blade.php

@@ -7,7 +7,7 @@
         @component('maintenance.priceModel.operation.menu')@endcomponent
     </div>
     <div class="container-fluid mt-2" id="container">
-        @include("maintenance.priceModel.operation._addOutStorageRuleModal")
+        @include("maintenance.priceModel.operation._addItemModal")
         @include("maintenance.priceModel.operation._addFeature")
         <div id="form_div"></div>
         @if(Session::has('successTip'))
@@ -21,9 +21,6 @@
                 <th>类型</th>
                 <th>策略</th>
                 <th>项目</th>
-                <th>计量</th>
-                <th>单位</th>
-                <th>单价</th>
                 <th>优先级</th>
                 <th>特征</th>
                 <th>备注</th>
@@ -33,27 +30,13 @@
             <tr v-for="(model,i) in models" :id="'model-'+model.id">
                 <td>@{{ i+1 }}</td>
                 <td>
-                    <button v-if="model.operationType == '出库' && thisId != model.id" class="btn btn-sm btn-info" @click="showDetail(model.id)">维护详情</button>
-                    <button v-if="model.operationType == '出库' && thisId == model.id" class="btn btn-sm btn-dark" @click="thisId = ''">关闭详情</button>
+                    <button v-if="thisId != model.id" class="btn btn-sm btn-info" @click="showDetail(model.id,model.operationType)">维护详情</button>
+                    <button v-if="thisId == model.id" class="btn btn-sm btn-dark" @click="thisId = ''">关闭详情</button>
                 </td>
                 <td>@{{ model.name }}</td>
                 <td>@{{ model.operationType }}</td>
                 <td>@{{ model.strategy }}</td>
-                <td>
-                    <small v-for="owner in model.owners" class="m-0 font-weight-bold">@{{ owner.name }}<br></small>
-                </td>
-                <td>
-                    <label v-if="model.operationType == '出库'">/</label>
-                    <label v-else>@{{ model.ownerInStorageRuleAmount }}</label>
-                </td>
-                <td>
-                    <label v-if="model.operationType == '出库'">/</label>
-                    <label v-else>@{{ model.ownerInStorageRuleUnitName }}</label>
-                </td>
-                <td>
-                    <label v-if="model.operationType == '出库'">/</label>
-                    <label v-else>@{{ model.ownerInStorageRuleUnitPrice }}</label>
-                </td>
+                <td><small v-for="owner in model.owners" class="m-0 font-weight-bold">@{{ owner.name }}<br></small></td>
                 <td>@{{ model.priority }}</td>
                 <td>@{{ model.feature }}</td>
                 <td>@{{ model.remark }}</td>
@@ -77,15 +60,15 @@
                             <th class="text-center">特征</th>
                             <th></th>
                         </tr>
-                        <tr v-if="ownerOutStorageRules[thisId] && ownerOutStorageRules[thisId].length == 0">
+                        <tr v-if="items[thisId] && items[thisId].length == 0">
                             <td colspan="8">
-                                @can("计费模型-作业-编辑")<button class="btn btn-sm btn-outline-info" @click="showAddRuleModal()">新增</button>@endcan
+                                @can("计费模型-作业-编辑")<button class="btn btn-sm btn-outline-info" @click="showAddItemModal()">新增</button>@endcan
                             </td>
                         </tr>
-                        <tr v-for="(item,i) in ownerOutStorageRules[thisId]">
+                        <tr v-for="(item,i) in items[thisId]">
                             <td>
                                 <span v-if="updateDetailId != item.id">
-                                    @can("计费模型-作业-编辑")<button class="btn btn-sm btn-outline-info" @click="showAddRuleModal()" v-if="i==0">新增</button>
+                                    @can("计费模型-作业-编辑")<button class="btn btn-sm btn-outline-info" @click="showAddItemModal()" v-if="i==0">新增</button>
                                     <button class="btn btn-sm btn-outline-info" @click="showUpdateDetail(item.id)">修改</button>@endcan
                                 </span>
                                 <span v-else>
@@ -153,9 +136,6 @@
                         remark : "{{$model->remark}}",
                         priority : "{{$model->priority}}",
                         createdAt : "{{$model->created_at}}",
-                        ownerInStorageRuleAmount : "{{$model->ownerInStorageRule ? $model->ownerInStorageRule->amount : ''}}",
-                        ownerInStorageRuleUnitName : "{{$model->ownerInStorageRule ? ($model->ownerInStorageRule->unit ? $model->ownerInStorageRule->unit->name : '') : ''}}",
-                        ownerInStorageRuleUnitPrice : "{{$model->ownerInStorageRule ? $model->ownerInStorageRule->unit_price : ''}}",
                         owners : {!! $model->ownerPriceOperationOwners !!},
                     },
                     @endforeach
@@ -166,19 +146,18 @@
                     @endforeach
                 ],
                 thisId : "",
-                ownerOutStorageRules : [],
+                items : [],
                 updateDetailId : '',
                 units : null,
                 type : ['商品名称','订单类型','承运商','店铺类型'],
                 logic : ['包含','不包含','等于'],
-                rule : {
+                item : {
                     "strategy" : '特征',
                     "amount" : "",
                     "unit_id" : "",
                     "unit_price" : "",
                     "priority" : 0,
                 },
-                thisRuleIndex : "",
                 features : [],
                 existStrategy:{default:false,starting:false},
             },
@@ -197,16 +176,16 @@
                 this.form.init();
             },
             methods:{
-                showDetail(id){
-                    if (this.ownerOutStorageRules[id]){
+                showDetail(id,type){
+                    if (this.items[id]){
                         this.thisId = id;
                         $("#model-"+id).after($("#detail"));
                         return;
                     }
-                    window.axios.post("{{url('maintenance/priceModel/operation/getOutStorageRule')}}",{id:id})
+                    window.axios.post("{{url('maintenance/priceModel/operation/getItems')}}",{id:id,type:type})
                         .then(res=>{
                             if (res.data.success){
-                                this.ownerOutStorageRules[id] = res.data.data;
+                                this.items[id] = res.data.data;
                                 this.thisId = id;
                                 $("#model-"+id).after($("#detail"));
                                 return;
@@ -241,7 +220,7 @@
                     let unit_id = $("#detailUnit").val();
                     let unit_price = $("#detailUnitPrice").val();
                     let priority = $("#detailPriority").val();
-                    window.axios.post("{{url('maintenance/priceModel/operation/updateOutStorageRule')}}",
+                    window.axios.post("{{url('maintenance/priceModel/operation/updateItem')}}",
                         {id:item.id,amount:amount,unit_id:unit_id,unit_price:unit_price,priority:priority})
                         .then(res=>{
                             if (res.data.success){
@@ -269,34 +248,34 @@
                         window.tempTip.show("网络错误:"+err);
                     });
                 },
-                showAddRuleModal(){
+                showAddItemModal(){
                     if (!this.units)this._getUnits();
                     let startingSign = true;
                     let defaultSign = true;
-                    this.ownerOutStorageRules[this.thisId].forEach(rule=>{
-                        if (rule.strategy == '默认')defaultSign = false;
-                        if (rule.strategy == '起步')startingSign = false;
+                    this.items[this.thisId].forEach(item=>{
+                        if (item.strategy === '默认')defaultSign = false;
+                        if (item.strategy === '起步')startingSign = false;
                     });
                     if (!startingSign)this.existStrategy.starting = true;
                     if (!defaultSign)this.existStrategy.default = true;
-                    $("#addOutStorageRule").modal("show");
+                    $("#addItem").modal("show");
                 },
-                submitRule(){
-                    if (!this.thisId || !this.rule.strategy || !this.rule.unit_id || !this.rule.unit_price){
+                submitItem(){
+                    if (!this.thisId || !this.item.strategy || !this.item.unit_id || !this.item.unit_price){
                         window.tempTip.setDuration(3000);
                         window.tempTip.show("计费策略,单位,单价为必填项");
                         return;
                     }
-                    window.axios.post("{{url('maintenance/priceModel/operation/createOutStorageRule')}}",
-                        {owner_price_operation_id:this.thisId,strategy:this.rule.strategy,amount:this.rule.amount,unit_id:this.rule.unit_id,unit_price:this.rule.unit_price,priority:Number(this.rule.priority)})
+                    window.axios.post("{{url('maintenance/priceModel/operation/createItem')}}",
+                        {owner_price_operation_id:this.thisId,strategy:this.item.strategy,amount:this.item.amount,unit_id:this.item.unit_id,unit_price:this.item.unit_price,priority:Number(this.item.priority)})
                         .then(res=>{
                             if (res.data.success){
-                                this.ownerOutStorageRules[this.thisId].unshift(res.data.data);
+                                this.items[this.thisId].unshift(res.data.data);
                                 this.$forceUpdate();
                                 window.tempTip.setDuration(2000);
                                 window.tempTip.setIndex(1099);
                                 window.tempTip.showSuccess("新增出库策略成功");
-                                $("#addOutStorageRule").modal("hide");
+                                $("#addItem").modal("hide");
                                 return;
                             }
                             window.tempTip.setDuration(3000);
@@ -340,11 +319,11 @@
                 },
                 submitFeature(){
                     window.axios.post("{{url('maintenance/priceModel/operation/addFeature')}}",
-                        {id:this.ownerOutStorageRules[this.thisId][this.thisIndex].id,features:this.features})
+                        {id:this.items[this.thisId][this.thisIndex].id,features:this.features})
                         .then(res=>{
                             if (res.data.success){
-                                this.ownerOutStorageRules[this.thisId][this.thisIndex].featureFormat = res.data.data.featureFormat;
-                                this.ownerOutStorageRules[this.thisId][this.thisIndex].feature = res.data.data.feature;
+                                this.items[this.thisId][this.thisIndex].featureFormat = res.data.data.featureFormat;
+                                this.items[this.thisId][this.thisIndex].feature = res.data.data.feature;
                                 this.$forceUpdate();
                                 $("#addFeatureModal").modal("hide");
                                 window.tempTip.setDuration(2000);

+ 8 - 0
resources/views/maintenance/priceModel/storage/create.blade.php

@@ -17,6 +17,14 @@
             @csrf
             <label hidden><input :value="model.id" name="id"></label>
             <div class="row">
+                <label for="name" class="col-2">名称</label>
+                <input id="name" type="text" name="name" class="col-6 form-control"
+                       :class="errors.name ? 'is-invalid' : ''" v-model="model.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="counting_type" class="col-2 text-info">计费类型</label>
                 <select id="counting_type" name="counting_type" class="col-3 form-control"
                         :class="errors.counting_type ? 'is-invalid' : ''" v-model="model.counting_type">

+ 3 - 0
resources/views/maintenance/priceModel/storage/index.blade.php

@@ -13,6 +13,7 @@
         <table class="table table-hover table-striped text-nowrap">
             <tr>
                 <th>序号</th>
+                <th>名称</th>
                 <th>计费类型</th>
                 <th>用仓类型</th>
                 <th>最低起租面积</th>
@@ -24,6 +25,7 @@
             </tr>
             <tr v-for="(model,i) in models">
                 <td>@{{ i+1 }}</td>
+                <td>@{{ model.name }}</td>
                 <td>@{{ model.counting_type }}</td>
                 <td>@{{ model.using_type }}</td>
                 <td>@{{ model.minimum_area }}</td>
@@ -50,6 +52,7 @@
                     @foreach($models as $model)
                     {
                         id : "{{$model->id}}",
+                        name : "{{$model->name}}",
                         counting_type : "{{$model->counting_type}}",
                         using_type : "{{$model->using_type}}",
                         minimum_area : "{{$model->minimum_area}}",

+ 31 - 4
routes/web.php

@@ -51,6 +51,7 @@ Route::group(['prefix'=>'maintenance'],function(){
     });
     Route::group(['prefix'=>'owner'],function (){
         Route::post("get","OwnerController@get");
+        Route::post("apiStore","OwnerController@apiStore");
     });
     /** 教程 */
     Route::group(['prefix'=>'tutorial'],function(){
@@ -97,9 +98,9 @@ Route::group(['prefix'=>'maintenance'],function(){
 
         Route::group(['prefix'=>'operation'],function(){
             Route::get('create','PriceModelController@operationCreate');
-            Route::post('getOutStorageRule','PriceModelController@operationGetOutStorageRule');
-            Route::post('updateOutStorageRule','PriceModelController@updateOutStorageRule');
-            Route::post('createOutStorageRule','PriceModelController@createOutStorageRule');
+            Route::post('getItems','PriceModelController@getItems');
+            Route::post('updateItem','PriceModelController@updateItem');
+            Route::post('createItem','PriceModelController@createItem');
             Route::post('getFeatures','PriceModelController@getFeatures');
             Route::post('addFeature','PriceModelController@addFeature');
             Route::post('getFeature','PriceModelController@getFeature');
@@ -150,6 +151,29 @@ Route::group(['prefix'=>'maintenance'],function(){
         });
         Route::get('directLogistic','PriceModelController@directLogisticIndex');
         Route::post('directLogistic','PriceModelController@directLogisticStore');
+
+        //api 录入计费模型
+        Route::post('apiStoreStorage','PriceModelController@apiStoreStorage');
+        Route::post('apiStoreOperation','PriceModelController@apiStoreOperation');
+        Route::post('apiStoreExpress','PriceModelController@apiStoreExpress');
+        Route::post('apiStoreLogistic','PriceModelController@apiStoreLogistic');
+        Route::post('apiStoreDirectLogistic','PriceModelController@apiStoreDirectLogistic');
+        //api 获取计费模型
+        Route::post('apiGetStorage','PriceModelController@apiGetStorage');
+        Route::post('apiGetOperation','PriceModelController@apiGetOperation');
+        Route::post('apiGetExpress','PriceModelController@apiGetExpress');
+        Route::post('apiGetLogistic','PriceModelController@apiGetLogistic');
+        Route::post('apiGetDirectLogistic','PriceModelController@apiGetDirectLogistic');
+        //api 删除计费模型
+        Route::post('apiDelStorage','PriceModelController@apiDelStorage');
+        Route::post('apiDelOperation','PriceModelController@apiDelOperation');
+        Route::post('apiDelOperationItem','PriceModelController@apiDelOperationItem');
+        Route::post('apiDelExpress','PriceModelController@apiDelExpress');
+        Route::post('apiDelExpressItem','PriceModelController@apiDelExpressItem');
+        Route::post('apiDelLogistic','PriceModelController@apiDelLogistic');
+        Route::post('apiDelLogisticItem','PriceModelController@apiDelLogisticItem');
+        Route::post('apiDelDirectLogistic','PriceModelController@apiDelDirectLogistic');
+        Route::post('apiDelDirectLogisticItem','PriceModelController@apiDelDirectLogisticItem');
     });
     Route::group(['prefix'=>'unit'],function(){
         Route::post('getUnits','UnitsController@getUnits');
@@ -585,10 +609,13 @@ Route::group(['prefix'=>'customer'],function(){
         });
         Route::get('area','CustomerController@projectArea');
         Route::get('{id}/edit','CustomerController@projectEdit');
-        Route::post('store','CustomerController@projectStore');
+        Route::post('projectUpdate','CustomerController@projectUpdate');
         Route::post('getOwnerPriceModel','CustomerController@getOwnerPriceModel');
         Route::post('updateArea','CustomerController@updateArea');
         Route::post('verify','CustomerController@verifyProject');
+
+        //获取现有计费模型
+        Route::post('getPriceModel','PriceModelController@getPriceModel');
     });
     Route::group(['prefix'=>'finance'],function(){
         Route::group(['prefix'=>'instantBill'],function(){