dongxiaoqin 1 год назад
Родитель
Сommit
b9b8e75edc
1 измененных файлов с 82 добавлено и 37 удалено
  1. 82 37
      app/common/command/AutomaticDispatch.php

+ 82 - 37
app/common/command/AutomaticDispatch.php

@@ -100,29 +100,48 @@ class AutomaticDispatch extends Command
      * 派单给平台工程师
      */
     protected function platformWorker($item) {
-        $real_distance = Db::raw("ST_Distance_Sphere(
-                POINT({$item['lon']}, {$item['lat']}),
-                POINT(lon, lat)
-            ) AS real_distance");
+
+        // 定义地球半径(单位:千米)
+        $earthRadius = 6371;
+
+        // 定义 Haversine 公式计算距离的 SQL 片段
+        $distanceCalculation = "{$earthRadius} * 2 * ASIN(SQRT(
+            POWER(SIN((RADIANS({$item['lat']}) - RADIANS(a.lat)) / 2), 2) +
+            COS(RADIANS({$item['lat']})) * COS(RADIANS(a.lat)) *
+            POWER(SIN((RADIANS({$item['lon']}) - RADIANS(a.lon)) / 2), 2)
+        ))";
+        // 计算距离的字段定义
+        $real_distance = Db::raw("{$distanceCalculation} AS real_distance");
+
         // 获取符合条件的工程师
-        $worker = MasterWorker::alias('a')->leftJoin('master_worker_score b','a.id = b.worker_id')
-        ->where([
-            ['is_disable','=',0],
-            ['work_status','=',0],
-            ['accept_order_status','=',1],
-            ['city','=',$item['city']],
-            ['tenant_id','=',0]
-        ])
-        ->whereRaw('FIND_IN_SET('.$item['goods_category_id'].', a.category_ids)')
-        ->whereRaw("ST_Distance_Sphere(
-            POINT({$item['lon']}, {$item['lat']}),
-            POINT(lon, lat)
-        ) <= distance")
-        ->field(['a.id','a.tenant_id','a.distance','a.lon','a.lat','a.worker_number','a.real_name','b.comprehensive_score','b.weight_score',$real_distance])
-        ->orderRaw('(b.comprehensive_score + b.weight_score) desc')
-        ->limit(100)
-        ->select()
-        ->toArray();
+        $worker = MasterWorker::alias('a')
+            ->leftJoin('master_worker_score b', 'a.id = b.worker_id')
+            ->where([
+                ['is_disable', '=', 0],
+                ['work_status', '=', 0],
+                ['accept_order_status', '=', 1],
+                ['city', '=', $item['city']],
+                ['tenant_id', '=', 0]
+            ])
+            ->whereRaw('FIND_IN_SET(' . $item['goods_category_id'] . ', a.category_ids)')
+            ->whereRaw("{$distanceCalculation} <= a.distance")
+            ->field([
+                'a.id',
+                'a.tenant_id',
+                'a.distance',
+                'a.lon',
+                'a.lat',
+                'a.worker_number',
+                'a.real_name',
+                'b.comprehensive_score',
+                'b.weight_score',
+                $real_distance
+            ])
+            ->orderRaw('(b.comprehensive_score + b.weight_score) desc')
+            ->limit(100)
+            ->select()
+            ->toArray();
+
         $queue = [];
         foreach($worker as $key => $value) {  
             //过滤已接过此单的师傅
@@ -187,29 +206,55 @@ class AutomaticDispatch extends Command
      * 派单给门店负责人
      */
     protected function teamWorker($item) {
-        $real_distance = Db::raw("ST_Distance_Sphere(
-            POINT({$item['lon']}, {$item['lat']}),
-            POINT(lon, lat)
-        ) AS real_distance");
+       
+        // 地球半径,单位:千米
+        $earthRadius = 6371;
+
+        // 定义 Haversine 公式计算距离的 SQL 片段
+        $distanceCalculation = "{$earthRadius} * 2 * ASIN(SQRT(
+            POWER(SIN((RADIANS({$item['lat']}) - RADIANS(lat)) / 2), 2) +
+            COS(RADIANS({$item['lat']})) * COS(RADIANS(lat)) *
+            POWER(SIN((RADIANS({$item['lon']}) - RADIANS(lon)) / 2), 2)
+        ))";
+
+        // 计算距离的字段定义
+        $real_distance = Db::raw("{$distanceCalculation} AS real_distance");
 
-        $isAm = date("H",strtotime($item['appointment_time'])) < 12 ? 1 : 0;
+        // 判断预约时间是上午还是下午
+        $isAm = date("H", strtotime($item['appointment_time'])) < 12 ? 1 : 0;
+        // 根据上午或下午构建查询条件
         $whereRaw = $isAm ? 'am_order < am_limit' : 'pm_order < pm_limit';
-        // 获取符合条件的工程师
+
+        // 获取符合条件的工程师团队
         $worker = MasterWorkerTeam::where([
-           ['accept_order_status','=',1],
-            ['city','=',$item['city']],
+            ['accept_order_status', '=', 1],
+            ['city', '=', $item['city']],
         ])
         ->whereRaw($whereRaw)
-        ->whereRaw('FIND_IN_SET('.$item['goods_category_id'].', goods_category_ids)')
-        ->whereRaw("ST_Distance_Sphere(
-            POINT({$item['lon']}, {$item['lat']}),
-            POINT(lon, lat)
-        ) <= distance")
-        ->field(['id','lon','lat','distance','tenant_id','team_name','master_worker_id','am_order','am_limit','pm_order','pm_limit','min_order','comprehensive_score', $real_distance])
-        ->order('comprehensive_score','desc')
+        ->whereRaw('FIND_IN_SET(' . $item['goods_category_id'] . ', goods_category_ids)')
+        // 使用 Haversine 公式替换 ST_Distance_Sphere 函数进行距离筛选
+        ->whereRaw("{$distanceCalculation} <= distance")
+        ->field([
+            'id',
+            'lon',
+            'lat',
+            'distance',
+            'tenant_id',
+            'team_name',
+            'master_worker_id',
+            'am_order',
+            'am_limit',
+            'pm_order',
+            'pm_limit',
+            'min_order',
+            'comprehensive_score',
+            $real_distance
+        ])
+        ->order('comprehensive_score', 'desc')
         ->limit(100)
         ->select()
         ->toArray();
+
         $minQueue = [];
         $queue = [];
         foreach($worker as $key => $value) {