From df8cff886952c1e80b3187a44a230b039342b88a Mon Sep 17 00:00:00 2001 From: wuhui_zzw <1760308791@qq.com> Date: Tue, 29 Aug 2023 10:36:27 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=EF=BC=9A=E5=95=86=E5=93=81?= =?UTF-8?q?=E8=AF=A6=E6=83=85=20-=20=E7=89=A9=E6=B5=81=E5=88=87=E6=8D=A2?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E4=B8=AD=E4=B8=8D=E6=98=BE=E7=A4=BA=E4=B8=8D?= =?UTF-8?q?=E7=AC=A6=E5=90=88=E6=9D=A1=E4=BB=B6=E7=9A=84=E7=89=A9=E6=B5=81?= =?UTF-8?q?=20=E4=BC=98=E5=8C=96=EF=BC=9A=E5=95=86=E5=93=81=E8=AF=A6?= =?UTF-8?q?=E6=83=85=20-=20=E9=BB=98=E8=AE=A4=E6=98=BE=E7=A4=BA=E8=BF=90?= =?UTF-8?q?=E8=B4=B9=E6=9C=80=E4=BD=8E=E7=9A=84=E7=89=A9=E6=B5=81=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- beike/Models/Logistics.php | 51 +++++++++ .../Http/Controllers/ProductController.php | 15 ++- .../TotalServices/ShippingService.php | 101 ++++++++++-------- themes/default/product/product.blade.php | 3 + .../default/shared/select-logistics.blade.php | 2 +- 5 files changed, 123 insertions(+), 49 deletions(-) diff --git a/beike/Models/Logistics.php b/beike/Models/Logistics.php index 6994b056..ce8fca91 100644 --- a/beike/Models/Logistics.php +++ b/beike/Models/Logistics.php @@ -37,6 +37,7 @@ class Logistics extends Base{ public static function getAll(int $countryId,$field = ['id','name','warehouse_name','type','day_min','day_max']){ $list = self::select($field) ->whereRaw(\DB::raw('FIND_IN_SET('.$countryId.',country_ids)')) + ->with(['weights']) ->orderBy('position','ASC') ->orderBy('id','ASC') ->get(); @@ -45,7 +46,57 @@ class Logistics extends Base{ return $list ? $list->toArray() : []; } + /** + * Common: 物流过滤 - 根据商品和物流列表过滤 仅返回有效的物流 + * Author: wu-hui + * Time: 2023/08/29 10:02 + * @param $logisticsList + * @param $productsList + * @return array|array[] + */ + public static function LogisticsFiltering($logisticsList,$productsList){ + $eligibleList = array_map(function($logisticsItem) use ($productsList){ + // 判断:物流是否按照重量计算 weight:按重量计费,num:按数量计费,free:卖家包邮 + if($logisticsItem['type'] == 'weight'){ + $weights = (array)$logisticsItem['weights'];// 续重区间列表 + $firstWeight = (float)$logisticsItem['first_weight'];// 首重 + if(!$weights) { + $logisticsItem = []; + }else{ + // 循环判断:只要有一个商品不符合条件 则当前物流不可用; + foreach($productsList as $productItem){ + $surplusWeight = $productItem['sum_weight'] - $firstWeight;// 总重量 - 减首重 = 剩余重量 + // 判断:如果剩余重量小于等于0 则符合条件;否则计算续重区间 + if($surplusWeight <= 0){ + continue; + }else{ + $eligibleCount = collect($weights) + ->where('min','<=',$surplusWeight) + ->where('max','>',$surplusWeight) + ->count(); + if($eligibleCount <= 0) { + $logisticsItem = []; + break; + } + } + } + } + } + + return $logisticsItem; + },$logisticsList); + + return array_filter($eligibleList); + } + + public function country(){ return $this->belongsTo(Country::class,'country_id','id'); } + + public function weights(){ + return $this->hasMany(LogisticsWeight::class,'logistics_id','id'); + } + + } diff --git a/beike/Shop/Http/Controllers/ProductController.php b/beike/Shop/Http/Controllers/ProductController.php index 6e6e1f48..b12431f1 100644 --- a/beike/Shop/Http/Controllers/ProductController.php +++ b/beike/Shop/Http/Controllers/ProductController.php @@ -149,7 +149,14 @@ class ProductController extends Controller return json_success(trans('common.success'),$totals); } - // 获取物流列表 + /** + * Common: 获取物流列表 + * Author: wu-hui + * Time: 2023/08/29 10:06 + * @param Request $request + * @return array + * @throws \Exception + */ public function productsLogistics(Request $request){ $data = [ 'list' => [], @@ -191,10 +198,14 @@ class ProductController extends Controller $request->change_logistics_id = $logisticsItem['id']; $totals = $this->computeOrderMoney($request); $shipping = array_column($totals['data'],null,'code')['shipping'] ?? []; - $logisticsItem['shipping_fee'] = $shipping['show_tips'] == 0 ? $shipping['amount_format'] : trans('shop/carts.to_be_negotiated'); + // $logisticsItem['shipping_fee'] = $shipping['show_tips'] == 0 ? $shipping['amount_format'] : trans('shop/carts.to_be_negotiated'); + if($shipping['show_tips'] == 0) $logisticsItem['shipping_fee'] = $shipping['amount_format']; + else $logisticsItem = []; } } + + $data['list'] = array_filter($data['list']); return json_success(trans('common.success'),$data); } diff --git a/beike/Shop/Services/TotalServices/ShippingService.php b/beike/Shop/Services/TotalServices/ShippingService.php index d4c43522..714dcbb9 100644 --- a/beike/Shop/Services/TotalServices/ShippingService.php +++ b/beike/Shop/Services/TotalServices/ShippingService.php @@ -21,7 +21,8 @@ use Beike\Shop\Services\CheckoutService; use Illuminate\Support\Str; class ShippingService{ - protected static $country; + protected static $country;// 国家信息 + protected static $productsList;// 商品分组统计列表 // 运费计算 public static function getTotal(CheckoutService $checkout): ?array{ @@ -50,40 +51,33 @@ class ShippingService{ $amount = (float)(new $className)->getShippingFee($checkout); } else{ + // 商品信息处理 获取同一个商品的数量、重量 + $products = $totalService->getCartProducts(); + self::$productsList = collect($products)->groupBy('product_id')->map(function($group){ + $firstInfo = $group->first(); + $productWeightInfo = Product::query() + ->select(['id','weight','weight_class']) + ->find($firstInfo['product_id']); + if($productWeightInfo) $productWeightInfo = $productWeightInfo->toArray(); + // 重量转换 - 物流重量单位为 千克;商品重量需要进行转换 + $weight = $productWeightInfo['weight'] ?? 0; + $sumQuantity = $group->sum('quantity'); + $sumWeight = (float)sprintf("%.2f",($weight * $sumQuantity)); + $weightClass = $productWeightInfo['weight_class']; + $sumWeight = Weight::convert($sumWeight,$weightClass);// 总重量 单位:克 + return [ + 'product_id' => $firstInfo['product_id'], + 'sum_quantity' => $sumQuantity, + 'sum_weight' => $sumWeight, + 'weight' => $weight, + 'weight_class' => $weightClass, + ]; + }); // 通过物流进行计算 $logisticsId = (int)$checkout->cart->shipping_method_code; $logisticsInfo = self::getLogistics($logisticsId,$checkout->cart); - if($logisticsInfo) { - // 商品信息处理 获取同一个商品的数量 - $products = $totalService->getCartProducts(); - $productsList = collect($products)->groupBy('product_id')->map(function($group){ - $firstInfo = $group->first(); - $productWeightInfo = Product::query() - ->select(['id','weight','weight_class']) - ->find($firstInfo['product_id']); - if($productWeightInfo) $productWeightInfo = $productWeightInfo->toArray(); - // 重量转换 - 物流重量单位为 千克;商品重量需要进行转换 - $weight = $productWeightInfo['weight'] ?? 0; - $sumQuantity = $group->sum('quantity'); - $sumWeight = (float)sprintf("%.2f",($weight * $sumQuantity)); - $weightClass = $productWeightInfo['weight_class']; - $sumWeight = Weight::convert($sumWeight,$weightClass);// 总重量 单位:克 - return [ - 'product_id' => $firstInfo['product_id'], - 'sum_quantity' => $sumQuantity, - 'sum_weight' => $sumWeight, - 'weight' => $weight, - 'weight_class' => $weightClass, - ]; - }); - // weight:按重量计费,num:按数量计费,free:卖家包邮 - $logisticsHandleFun = 'compute_'.$logisticsInfo['type']; - $amount = self::$logisticsHandleFun($logisticsInfo,$productsList); - } - else{ - // 如果还是不能获取物流信息 则显示 待协商 - $showTips = 1; - } + if($logisticsInfo) $amount = $logisticsInfo['amount'];// 存在物流 获取运费 + else $showTips = 1;// 如果还是不能获取物流信息 则显示 待协商 } $totalData = [ 'code' => 'shipping', @@ -109,7 +103,7 @@ class ShippingService{ * @return array|mixed|mixed[] */ private static function getLogistics($logisticsId,$cart){ - $logisticsField = ['type', 'name','first_weight','first_weight_fee','continuation_weight_max','add_weight','continuation_weight_fee','num_fee']; + $logisticsField = ['id','type', 'name','first_weight','first_weight_fee','continuation_weight_max','add_weight','continuation_weight_fee','num_fee']; // 判断:客服端是否切换国家 如果存在切换的国家id 则使用切换的国家id;不存在则继续执行 $countryId = (int)request()->input('products_country_id'); if($countryId > 0) { @@ -120,6 +114,7 @@ class ShippingService{ // 同时存在国家ID 获取物流ID $logisticsInfo = Logistics::query() ->whereRaw(\DB::raw('FIND_IN_SET('.$countryId.',country_ids)')) + ->with(['weights']) ->where('id',$logisticsId) ->select($logisticsField) ->first(); @@ -127,7 +122,9 @@ class ShippingService{ // 刷新国家信息 self::refreshCurrentCountry($countryId); - return $logisticsInfo->toArray(); + $logisticsList = [$logisticsInfo->toArray()]; + + goto logisticsListHandle; } } // 仅存在国家ID时 @@ -146,25 +143,41 @@ class ShippingService{ // 刷新国家信息 self::refreshCurrentCountry($countryId); - return $logisticsList[0] ?? []; }else{ // 获取物流信息 $logisticsInfo = Logistics::query() + ->with(['weights']) ->select($logisticsField) ->find($logisticsId); - return $logisticsInfo ? $logisticsInfo->toArray() : []; + $logisticsList = [$logisticsInfo ? $logisticsInfo->toArray() : []]; } + // 根据已查询的物流列表 筛选出符合条件的物流并且返回第一个 + logisticsListHandle: + $eligibleLogisticsList = Logistics::LogisticsFiltering($logisticsList,self::$productsList); + // 循环计算物流运费 + foreach($eligibleLogisticsList as &$eligibleLogisticsListItem){ + // weight:按重量计费,num:按数量计费,free:卖家包邮 + $logisticsHandleFun = 'compute_'.$eligibleLogisticsListItem['type']; + $eligibleLogisticsListItem['amount'] = (float)self::$logisticsHandleFun($eligibleLogisticsListItem); + } + // 存在多个物流 需要获取运费最小的物流 + if(count($eligibleLogisticsList) > 1){ + $amounts = array_column($eligibleLogisticsList,'amount'); + array_multisort($amounts,SORT_ASC,$eligibleLogisticsList); + } + + + return $eligibleLogisticsList[0] ?? []; } /** * Common: 运费计算 - 物流运费 - 运费计算(按重量计费) * Author: wu-hui * Time: 2023/08/22 15:34 * @param $logisticsInfo - * @param $productsList * @return float|int */ - private static function compute_weight($logisticsInfo,$productsList){ + private static function compute_weight($logisticsInfo){ /** * 计算规则: * 总重量 - 低于首重;则运费 = 【首重运费】 @@ -176,7 +189,7 @@ class ShippingService{ $addWeight = (float)$logisticsInfo['add_weight'];// 每增加重量 $continuationWeightFee = (float)$logisticsInfo['continuation_weight_fee'];// 续重运费 // 循环处理商品 - foreach($productsList as $productInfo){ + foreach(self::$productsList as $productInfo){ // 首重运费 $amount += (float)sprintf("%.2f",$firstWeightFee); // 判断:如果总重量超过首重 则计算续重运费 @@ -191,10 +204,9 @@ class ShippingService{ * Author: wu-hui * Time: 2023/08/22 14:47 * @param $logisticsInfo - * @param $productsList * @return float|int */ - private static function compute_num($logisticsInfo,$productsList){ + private static function compute_num($logisticsInfo){ /** * 计算规则: * 购买数量 - 低于首件数量;则运费 = 【首件运费】 @@ -206,7 +218,7 @@ class ShippingService{ $addWeight = (int)$logisticsInfo['add_weight'];// 每增加件 $continuationWeightFee = (float)$logisticsInfo['continuation_weight_fee'];// 续件运费 // 循环处理商品 - foreach($productsList as $productInfo){ + foreach(self::$productsList as $productInfo){ // 首件运费 $amount += (float)sprintf("%.2f",$firstWeightFee); // 判断:如果数量超过首件数量 则计算续件运费 @@ -221,10 +233,9 @@ class ShippingService{ * Author: wu-hui * Time: 2023/08/22 11:59 * @param $logisticsInfo - * @param $productsList * @return int */ - private static function compute_free($logisticsInfo,$productsList){ + private static function compute_free($logisticsInfo){ return 0; } @@ -240,8 +251,6 @@ class ShippingService{ - - /** * 通过配送方式获取插件编码 * diff --git a/themes/default/product/product.blade.php b/themes/default/product/product.blade.php index 4537ffc8..6eaf7dd1 100644 --- a/themes/default/product/product.blade.php +++ b/themes/default/product/product.blade.php @@ -623,6 +623,7 @@ _this.goods_list = list; _this.computeOrderMoney(); + _this.$refs['select-logistics'].getLogisticsList() // let price = 0; // if (this.numPrices.light == 0) { @@ -653,7 +654,9 @@ }; }) _this.goods_list = list; + _this.computeOrderMoney(); + _this.$refs['select-logistics'].getLogisticsList() } } }, diff --git a/themes/default/shared/select-logistics.blade.php b/themes/default/shared/select-logistics.blade.php index 582974da..ea900178 100644 --- a/themes/default/shared/select-logistics.blade.php +++ b/themes/default/shared/select-logistics.blade.php @@ -99,7 +99,7 @@ goods_list: JSON.stringify(_this.goods_list), }).then((res) => { if(res.status === 'success'){ - _this.logistics_list = res.data.list || {}; + _this.logistics_list = Object.values(Object.assign({},res.data.list || {})) ; _this.country = res.data.country || {}; } })