Browse Source

feat:技师端-技师接单

刘学玺 4 months ago
parent
commit
061c5aeaa8

+ 2 - 0
.gitignore

@@ -31,3 +31,5 @@ public/admin-assets
 /owl-admin.code-workspace
 .DS_Store
 .vscode/settings.json
+doc/bin/doc
+.vscode/settings.json

+ 26 - 0
app/Http/Controllers/Coach/OrderController.php

@@ -131,4 +131,30 @@ class OrderController extends Controller
     {
         return $this->service->grabOrder(Auth::user()->id, $order_id);
     }
+
+    /**
+     * [订单]接单
+     *
+     * @description 技师接受已分配的订单
+     *
+     * @authenticated
+     *
+     * @urlParam order_id integer required 订单ID Example: 1
+     *
+     * @response {
+     *   "message": "接单成功",
+     *   "order_id": 1,
+     *   "order_no": "202403210001"
+     * }
+     * @response 400 {
+     *   "message": "订单状态异常,无法接单"
+     * }
+     * @response 403 {
+     *   "message": "该订单未分配给您"
+     * }
+     */
+    public function acceptOrder(int $order_id)
+    {
+        return $this->service->acceptOrder(Auth::user()->id, $order_id);
+    }
 }

+ 62 - 10
app/Services/Coach/OrderService.php

@@ -4,6 +4,7 @@ namespace App\Services\Coach;
 
 use App\Enums\OrderGrabRecordStatus;
 use App\Enums\OrderStatus;
+use App\Enums\OrderType;
 use App\Enums\ProjectStatus;
 use App\Enums\TechnicianAuthStatus;
 use App\Enums\TechnicianLocationType;
@@ -345,6 +346,9 @@ class OrderService
                 // 验证订单状态
                 abort_if($order->state !== OrderStatus::CREATED->value, 400, '订单状态异常,无法抢单');
 
+                // 验证订单类型
+                abort_if($order->type !== OrderType::GRAB->value, 400, '该订单不是抢单类型');
+
                 // 检查技师是否已参与抢单
                 $existingGrab = $coach->grabRecords()
                     ->where('order_id', $orderId)
@@ -402,17 +406,65 @@ class OrderService
     }
 
     /**
-     * 计算两点之间的距离(公里)
+     * 技师接单
+     *
+     * @param  int  $userId  技师用户ID
+     * @param  int  $orderId  订单ID
      */
-    private function calculateDistance($lat1, $lon1, $lat2, $lon2): float
+    public function acceptOrder(int $userId, int $orderId): array
     {
-        $theta = $lon1 - $lon2;
-        $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1))
-            * cos(deg2rad($lat2)) * cos(deg2rad($theta));
-        $dist = acos($dist);
-        $dist = rad2deg($dist);
-        $miles = $dist * 60 * 1.1515;
-
-        return round($miles * 1.609344, 1);  // 转换为公里并保留一位小数
+        return DB::transaction(function () use ($userId, $orderId) {
+            try {
+                // 加载用户和技师信息
+                $user = MemberUser::with([
+                    'coach',
+                    'coach.info',
+                    'coach.real',
+                    'coach.qual',
+                ])->findOrFail($userId);
+
+                // 验证技师信息
+                [$coach, $location] = $this->validateCoach($user);
+
+                // 获取订单信息并加锁
+                $order = Order::lockForUpdate()->findOrFail($orderId);
+
+                // 验证订单状态
+                abort_if($order->state !== OrderStatus::ASSIGNED->value, 400, '订单状态异常,无法接单');
+
+                // 验证订单是否分配给该技师
+                abort_if($order->coach_id !== $coach->id, 403, '该订单未分配给您');
+
+                // 更新订单状态
+                $order->update([
+                    'state' => OrderStatus::ACCEPTED->value,
+                    'accepted_at' => now(),
+                ]);
+
+                // 记录日志
+                Log::info('技师接单成功', [
+                    'user_id' => $userId,
+                    'coach_id' => $coach->id,
+                    'order_id' => $orderId,
+                    'order_no' => $order->order_no,
+                ]);
+
+                return [
+                    'message' => '接单成功',
+                    'order_id' => $orderId,
+                    'order_no' => $order->order_no,
+                ];
+
+            } catch (\Exception $e) {
+                Log::error('技师接单失败', [
+                    'user_id' => $userId,
+                    'order_id' => $orderId,
+                    'error' => $e->getMessage(),
+                    'file' => $e->getFile(),
+                    'line' => $e->getLine(),
+                ]);
+                throw $e;
+            }
+        });
     }
 }

+ 0 - 11
doc/run_live_server.bat

@@ -1,11 +0,0 @@
-@echo off
-rem 指定live-server的路径,这里假设live-server.exe在当前目录下
-
-rem 获取本机IP地址
-for /f "tokens=2 delims=:" %%a in ('ipconfig ^| findstr /r "IPv4.*[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*"') do (
-    set ip=%%a
-)
-set ip=%ip:~1%
-
-rem 启动live-server,使用更高的端口号9000
-live-server --host=%ip% --port=9000

+ 0 - 5
doc/run_live_server.sh

@@ -1,5 +0,0 @@
-# 指定live-server的路径,这里假设live-server在当前目录下
-# 获取本机IP地址
-ip=$(hostname -I | awk '{print $1}')
-# 启动live-server,使用更高的端口号9000
-live-server --host=$ip --port=9000

+ 1 - 0
routes/api.php

@@ -147,6 +147,7 @@ Route::middleware(['auth:sanctum', 'verified'])->prefix('coach')->group(function
         Route::get('/', [CoachOrderController::class, 'getOrderList']);
         Route::get('/grab', [CoachOrderController::class, 'getGrabList']);
         Route::post('/grab/{order_id}', [CoachOrderController::class, 'grabOrder']);
+        Route::post('/accept/{order_id}', [CoachOrderController::class, 'acceptOrder']);
     });
 
     // 获取技师位置信息