Browse Source

fixed:距离不要自己算,用redis geo方法算

Yin Bin 4 months ago
parent
commit
4839c32e42
5 changed files with 154 additions and 29 deletions
  1. 4 2
      .vscode/launch.json
  2. 12 9
      app/Logging/CustomizeFormatter.php
  3. 136 17
      app/Services/Client/CoachService.php
  4. 1 0
      composer.json
  5. 1 1
      composer.lock

+ 4 - 2
.vscode/launch.json

@@ -16,7 +16,7 @@
             ],
             "runtimeArgs": [
                 "-dxdebug.mode=debug",
-                "-dxdebug.start_with_request=trigger",
+                "-dxdebug.start_with_request=yes",
                 "-dxdebug.log_level=7"
             ],
             "cwd": "${workspaceRoot}",
@@ -45,7 +45,9 @@
             "cwd": "${fileDirname}",
             "port": 0,
             "runtimeArgs": [
-                "-dxdebug.start_with_request=yes"
+                "-dxdebug.mode=debug",
+                "-dxdebug.start_with_request=yes",
+                "-dxdebug.log_level=7"
             ],
             "env": {
                 "XDEBUG_MODE": "debug,develop",

+ 12 - 9
app/Logging/CustomizeFormatter.php

@@ -4,6 +4,7 @@ namespace App\Logging;
 
 use Illuminate\Log\Logger;
 use Monolog\Formatter\LineFormatter;
+use Monolog\LogRecord;
 
 class CustomizeFormatter
 {
@@ -21,19 +22,20 @@ class CustomizeFormatter
             ));
 
             // 添加更严格的过滤器
-            $handler->pushProcessor(function ($record) {
+            $handler->pushProcessor(function (LogRecord $record): LogRecord {
                 // 1. 允许SQL日志
-                if (str_contains($record['message'], 'sql:')) {
+                if (str_contains($record->message, 'sql:')) {
                     return $record;
                 }
 
                 // 2. 过滤所有来自vendor目录的日志
-                if (isset($record['file']) && str_contains($record['file'], '/vendor/')) {
-                    return false;
+                if (isset($record->extra['file']) && str_contains($record->extra['file'], '/vendor/')) {
+                    $record->extra['filtered'] = true;
+                    return $record;
                 }
 
                 // 3. 过滤框架的默认日志通道
-                if (isset($record['channel']) && in_array($record['channel'], [
+                if (in_array($record->channel, [
                     'laravel',
                     'framework',
                     'security',
@@ -41,16 +43,17 @@ class CustomizeFormatter
                     'schedule',
                     'queue',
                 ])) {
-                    return false;
+                    $record->extra['filtered'] = true;
+                    return $record;
                 }
 
                 // 4. 只允许来自app目录的日志
-                if (isset($record['file']) && str_contains($record['file'], '/app/')) {
+                if (isset($record->extra['file']) && str_contains($record->extra['file'], '/app/')) {
                     return $record;
                 }
 
-                // 5. 默认过滤掉所有其他日志
-                return false;
+                $record->extra['filtered'] = true;
+                return $record;
             });
         }
     }

+ 136 - 17
app/Services/Client/CoachService.php

@@ -5,6 +5,7 @@ namespace App\Services\Client;
 use App\Models\CoachUser;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Redis;
+use Illuminate\Support\Facades\Log;
 
 class CoachService
 {
@@ -18,7 +19,17 @@ class CoachService
         // 获取当前用户
         $user = Auth::user();
 
+        Log::info('Current user and coordinates:', [
+            'user' => $user ? $user->id : null,
+            'latitude' => $latitude,
+            'longitude' => $longitude,
+        ]);
+
         // 检查用户状态
+        if (!$user) {
+            throw new \Exception('用户未登录');
+        }
+
         if ($user->state !== 'enable') {
             throw new \Exception('用户状态异常');
         }
@@ -68,10 +79,34 @@ class CoachService
      */
     public function getCoachDetail($coachId, $latitude, $longitude)
     {
+        // 检查Redis连接
+        try {
+            $pingResult = Redis::connection()->ping();
+            Log::info('Redis connection test:', ['ping_result' => $pingResult]);
+        } catch (\Exception $e) {
+            Log::error('Redis connection error:', ['error' => $e->getMessage()]);
+            throw new \Exception('Redis连接失败:' . $e->getMessage());
+        }
+
+        // 检查Redis中的所有位置数据
+        $allLocations = Redis::zrange('coach_locations', 0, -1, 'WITHSCORES');
+        Log::info('All locations in Redis:', ['locations' => $allLocations]);
+
         // 获取当前用户
         $user = Auth::user();
 
+        Log::info('Current user and coordinates:', [
+            'user' => $user ? $user->id : null,
+            'latitude' => $latitude,
+            'longitude' => $longitude,
+            'coach_id' => $coachId
+        ]);
+
         // 检查用户状态
+        if (!$user) {
+            throw new \Exception('用户未登录');
+        }
+
         if ($user->state !== 'enable') {
             throw new \Exception('用户状态异常');
         }
@@ -97,32 +132,116 @@ class CoachService
         $homeLocation = Redis::geopos('coach_locations', $coachId.'_home');
         $workLocation = Redis::geopos('coach_locations', $coachId.'_work');
 
-        // 计算距离
-        $distanceHome = $homeLocation && ! empty($homeLocation[0]) ? $this->calculateDistance($latitude, $longitude, $homeLocation[0][1], $homeLocation[0][0]) : null;
+        Log::info('Coach locations from Redis:', [
+            'coach_id' => $coachId,
+            'home_location' => $homeLocation,
+            'work_location' => $workLocation,
+            'home_key' => $coachId.'_home',
+            'work_key' => $coachId.'_work'
+        ]);
+
+        // 检查输入的经纬度是否有效
+        if (!is_numeric($latitude) || !is_numeric($longitude)) {
+            Log::error('Invalid coordinates:', ['latitude' => $latitude, 'longitude' => $longitude]);
+            throw new \Exception('无效的经纬度坐标');
+        }
 
-        $distanceWork = $workLocation && ! empty($workLocation[0]) ? $this->calculateDistance($latitude, $longitude, $workLocation[0][1], $workLocation[0][0]) : null;
+        // 临时存储用户当前位置用于计算距离
+        $tempKey = 'user_temp_'.$user->id;
+        $addResult = Redis::geoadd('coach_locations', $longitude, $latitude, $tempKey);
+
+        Log::info('User location added to Redis:', [
+            'temp_key' => $tempKey,
+            'latitude' => $latitude,
+            'longitude' => $longitude,
+            'add_result' => $addResult
+        ]);
+
+        // 计算距离(单位:km)
+        $distanceHome = null;
+        $distanceWork = null;
+
+        if ($homeLocation && !empty($homeLocation[0])) {
+            $distanceHome = Redis::geodist('coach_locations', $tempKey, $coachId.'_home', 'km');
+            Log::info('Home distance calculation:', [
+                'from' => $tempKey,
+                'to' => $coachId.'_home',
+                'distance' => $distanceHome,
+                'home_location' => $homeLocation[0]
+            ]);
+        }
+
+        if ($workLocation && !empty($workLocation[0])) {
+            $distanceWork = Redis::geodist('coach_locations', $tempKey, $coachId.'_work', 'km');
+            Log::info('Work distance calculation:', [
+                'from' => $tempKey,
+                'to' => $coachId.'_work',
+                'distance' => $distanceWork,
+                'work_location' => $workLocation[0]
+            ]);
+        }
+
+        Log::info('Distance calculation results:', [
+            'distance_home' => $distanceHome,
+            'distance_work' => $distanceWork,
+            'temp_key' => $tempKey,
+            'coach_id' => $coachId
+        ]);
+
+        // 删除临时位置点
+        Redis::zrem('coach_locations', $tempKey);
 
         // 选择最近的距离
-        $coach->distance = round(min(array_filter([$distanceHome, $distanceWork])), 2);
+        $distances = array_filter([$distanceHome, $distanceWork]);
+        $coach->distance = !empty($distances) ? round(min($distances), 2) : null;
 
         return $coach;
     }
 
-    // 添加一个计算距离的方法
-    private function calculateDistance($lat1, $lon1, $lat2, $lon2)
+    /**
+     * 设置技师位置信息
+     *
+     * @param int $coachId 技师ID
+     * @param float $latitude 纬度
+     * @param float $longitude 经度
+     * @param string $type 位置类型 (home|work)
+     * @return bool
+     * @throws \Exception
+     */
+    public function setCoachLocation($coachId, $latitude, $longitude, $type = 'home')
     {
-        // 实现距离计算逻辑
-        $earthRadius = 6371; // 地球半径,单位为公里
-
-        $dLat = deg2rad($lat2 - $lat1);
-        $dLon = deg2rad($lon2 - $lon1);
-
-        $a = sin($dLat / 2) * sin($dLat / 2) +
-            cos(deg2rad($lat1)) * cos(deg2rad($lat2)) *
-            sin($dLon / 2) * sin($dLon / 2);
+        if (!is_numeric($latitude) || !is_numeric($longitude)) {
+            Log::error('Invalid coordinates in setCoachLocation:', [
+                'coach_id' => $coachId,
+                'latitude' => $latitude,
+                'longitude' => $longitude
+            ]);
+            throw new \Exception('无效的经纬度坐标');
+        }
 
-        $c = 2 * atan2(sqrt($a), sqrt(1 - $a));
+        if (!in_array($type, ['home', 'work'])) {
+            throw new \Exception('无效的位置类型,必须是 home 或 work');
+        }
 
-        return $earthRadius * $c;
+        $key = $coachId . '_' . $type;
+        $result = Redis::geoadd('coach_locations', $longitude, $latitude, $key);
+
+        Log::info('Coach location set:', [
+            'coach_id' => $coachId,
+            'type' => $type,
+            'key' => $key,
+            'latitude' => $latitude,
+            'longitude' => $longitude,
+            'result' => $result
+        ]);
+
+        // 验证数据是否成功写入
+        $location = Redis::geopos('coach_locations', $key);
+        Log::info('Verify location after set:', [
+            'key' => $key,
+            'location' => $location
+        ]);
+
+        return $result;
     }
 }

+ 1 - 0
composer.json

@@ -11,6 +11,7 @@
         "laravel/framework": "v11.30.0",
         "laravel/sanctum": "^4.0",
         "laravel/tinker": "^2.9",
+        "monolog/monolog": "^3.5",
         "rap2hpoutre/laravel-log-viewer": "^2.4",
         "slowlyo/owl-admin": "^4.0",
         "slowlyo/owl-dict": "^1.3",

+ 1 - 1
composer.lock

@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "a2bbcb91c79d4f98e16588186df3d666",
+    "content-hash": "2224fcbb5f1c30bcc61b02a2fb21724f",
     "packages": [
         {
             "name": "brick/math",