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

1. mapUtil.php 中添加高德计算某经纬点至多个其它经纬点的距离算法
2. 查找附近批发店,并建立关系

shizhongqi пре 4 месеци
родитељ
комит
2da0ce0f8d

+ 20 - 1
app-hd/controllers/GhsController.php

@@ -3,7 +3,6 @@
 namespace hd\controllers;
 
 use biz\ghs\classes\GhsClass;
-use biz\recharge\classes\RechargeHbClass;
 use biz\shop\classes\ShopClass;
 use bizGhs\custom\classes\CustomClass;
 use bizGhs\custom\classes\CustomLevelClass;
@@ -442,4 +441,24 @@ class GhsController extends BaseController
         util::complete('载入成功');
     }
 
+    //寻找附近批发店
+    public function actionSearchNearbyGhs()
+    {
+        $shop = $this->shop;
+        $toLat = $shop['lat'] ?? '';
+        $toLnt = $shop['long'] ?? '';
+        if ($toLat == '' || $toLnt == '') {
+            util::fail('门店未定位');
+        }
+
+        if ($shop['province'] == '' || $shop['city'] == '') {
+            util::fail('门店未设置所在省市');
+        }
+
+        // 找出附近批发店,之后自动给建立关系,然后补充二个店之间的距离
+        GhsClass::buildNearbyGhsRelations($shop['id'], $this->shop->pfShopId, $shop['province'], $shop['city'], $toLat, $toLnt);
+
+        util::complete();
+    }
+
 }

+ 23 - 3
app-hd/controllers/ShopController.php

@@ -144,7 +144,7 @@ class ShopController extends BaseController
 
     //更新门店 ssh 2020.2.29
     public function actionUpdate()
-    {
+    {util::complete();
         $data = Yii::$app->request->post();
         $data['sjId'] = $this->sjId;
         $id = isset($data['id']) ? $data['id'] : 0;
@@ -155,8 +155,28 @@ class ShopController extends BaseController
         $mobile = $data['mobile'];
         //手机号具有唯一性,暂时不允许修改 --- 同批发端 app-ghs/controllers/ShopController.php 保持一致
         unset($data['mobile']);
-        ShopClass::updateShop($shop, $data);
-        util::complete();
+
+        // 添加事务处理
+        $connection = Yii::$app->db;
+        $transaction = $connection->beginTransaction();
+        try {
+            ShopClass::updateShop($shop, $data);
+
+            // 找出附近批发店,之后自动给建立关系,然后补充二个店之间的距离(app-hd GhsController actionInfo),计算距离使用高德接口
+            if(isset($data['openLocation']) && $data['openLocation'] == 1){
+                $toLat = $data['lat'] ?? null;
+                $toLnt = $data['long'] ?? null;
+                $province = $data['province'] ?? '';
+                $city = $data['city'] ?? '';
+                \biz\ghs\classes\GhsClass::buildNearbyGhsRelations($id, $this->shop->pfShopId, $province, $city, $toLat, $toLnt);
+            }
+            $transaction->commit();
+            util::complete();
+        } catch (\Exception $exception) {
+            $transaction->rollBack();
+            Yii::error("更新门店失败:" . $exception->getMessage());
+            util::fail('更新门店失败');
+        }
     }
 
     public function actionAdd()

+ 68 - 0
biz/ghs/classes/GhsClass.php

@@ -328,4 +328,72 @@ class GhsClass extends BaseClass
         util::fail('找不到供货商');
     }
 
+    // 建立附近批发店关系
+    public static function buildNearbyGhsRelations($shopId, $pfShopId, $province, $city, $toLat, $toLnt)
+    {
+        if (empty($toLat) || empty($toLnt)) {
+            util::fail('门店未定位');
+        }
+
+        if (empty($province) || empty($city)) {
+            util::fail('门店未设置所在省市');
+        }
+
+        // 按省市查找
+        $nearbyShops = ShopClass::getAllByCondition(['ptStyle'=>2, 'province'=>$province, 'city'=>$city, 'actTime>=' => strtotime('yesterday')], null, 'id, merchantName, lat, long');
+        if (empty($nearbyShops)) {
+            return;
+        }
+
+        $origins = [];
+        $validNearbyShops = [];
+        foreach ($nearbyShops as $nearbyShop) {
+            if ($nearbyShop['id'] == $pfShopId) {
+                continue;
+            }
+            if ($nearbyShop['lat'] && $nearbyShop['long']) {
+                $origins[] = [
+                    'lat' => $nearbyShop['lat'],
+                    'lng' => $nearbyShop['long'],
+                ];
+                $validNearbyShops[] = $nearbyShop;
+            }
+        }
+
+        if (empty($origins)) {
+            return;
+        }
+
+        // 高德批量测距接口最多支持 100 个起点,需分批处理
+        $chunkOrigins = array_chunk($origins, 100);
+        $allDistances = [];
+
+        foreach ($chunkOrigins as $chunk) {
+            $distances = \common\components\mapUtil::calculateBatchDistance($chunk, $toLnt, $toLat);
+            $allDistances = array_merge($allDistances, $distances);
+        }
+
+        // 建立关系前要先执照距离从小到大排序
+        // 注意:array_multisort($allDistances, SORT_ASC, $validNearbyShops) 能保证 $allDistances 与 $validNearbyShops 保持索引同步,
+        // 即排序后 $validNearbyShops[$i] 就是排序后第 $i 小距离的门店信息,$allDistances[$i] 为其对应距离。
+        array_multisort($allDistances, SORT_ASC, $validNearbyShops);
+
+        // 取前6个
+        $allDistances = array_slice($allDistances, 0, 6);
+        $validNearbyShops = array_slice($validNearbyShops, 0, 6);
+
+        // 建立关系并保存距离
+        foreach ($validNearbyShops as $index => $nearbyShop) {
+            $ghsShopId = $nearbyShop['id'];
+            $distance = $allDistances[$index] ?? 0;
+
+            // 调用 GhsClass::build 建立关系 (返回的 $ghs 包含 id 和 customId)
+            $ghs = self::build($ghsShopId, $shopId);
+            if (!empty($ghs) && $distance > 0) {
+                $ghsId = $ghs['id'];
+                self::updateById($ghsId, ['distance' => $distance]);
+            }
+        }
+    }
+
 }

+ 40 - 0
common/components/mapUtil.php

@@ -47,6 +47,46 @@ class mapUtil
         return $distance;
     }
 
+    /**
+     * 批量计算多个起点到一个终点的距离 (高德 V3 距离测量接口)
+     * @param array $origins 起点坐标数组,例如:[['lng' => '116.481028', 'lat' => '39.989643'], ...]
+     * @param string $toLnt 终点经度
+     * @param string $toLat 终点纬度
+     * @param int $type 路径计算的方式和方法 (0:直线距离, 1:驾车, 3:步行)
+     * @return array
+     */
+    public static function calculateBatchDistance($origins, $toLnt, $toLat, $type = 1)
+    {
+        if (empty($origins)) {
+            return [];
+        }
+
+        // 将起点数组拼接成高德要求的格式: lng1,lat1|lng2,lat2
+        $originStrs = [];
+        foreach ($origins as $origin) {
+            $originStrs[] = $origin['lng'] . ',' . $origin['lat'];
+        }
+        $originsParam = implode('|', $originStrs);
+        $destinationParam = $toLnt . ',' . $toLat;
+
+        $domain = getenv('YII_ENV') == 'production' ? 'https://restapi.amap.com' : 'http://restapi.amap.com';
+        $url = $domain . "/v3/distance?key=" . self::$thirdMapKey . "&origins={$originsParam}&destination={$destinationParam}&type={$type}";
+
+        $curl = new curl\Curl();
+        $result = $curl->get($url);
+        $result = \yii\helpers\Json::decode($result);
+
+        $distances = [];
+        if (!empty($result['status']) && $result['status'] == 1 && !empty($result['results'])) {
+            foreach ($result['results'] as $index => $res) {
+                // 返回的结果顺序与传入的 origins 顺序一致
+                $distances[$index] = $res['distance'] ?? 0; 
+            }
+        }
+        
+        return $distances;
+    }
+
     //逆地址解析,根据经纬度解析出中文地址 ssh
     public static function resolveLocation($lat, $long)
     {