Przeglądaj źródła

fixed:技师端-获取技师详情(包含订单数量、工作状态)

刘学玺 4 miesięcy temu
rodzic
commit
427d569b2a

+ 57 - 94
app/Enums/OrderStatus.php

@@ -4,125 +4,100 @@ namespace App\Enums;
 
 /**
  * 订单状态枚举类
+ *
+ * 定义了订单从创建到完成的所有可能状态
+ * 状态流转顺序:
+ * 已创建 -> 已支付 -> 已接单 -> 已出发 -> 已到达 -> 开始服务 -> 服务中 -> 服务结束 -> 撤离中 -> 已完成
+ * 任意状态都可以变为:已取消
  */
 enum OrderStatus: int
 {
     /**
-     * 订单状态:下单
+     * 订单状态:已创建
+     * 用户创建订单但尚未支付的状态
      */
-    case CREATED = 1;
+    case CREATED = 1;    // 订单初始状态
 
     /**
-     * 订单状态:指定
+     * 订单状态:已支付
+     * 用户完成支付,等待技师接单
      */
-    case ASSIGNED = 2;
+    case PAID = 2;       // 可以进入抢单流程
 
     /**
-     * 订单状态:支付
+     * 订单状态:已接单
+     * 技师接受订单,准备提供服务
      */
-    case PAID = 3;
+    case ACCEPTED = 3;   // 技师已确认接单
 
     /**
-     * 订单状态:取消
+     * 订单状态:已出发
+     * 技师已经出发前往服务地点
      */
-    case CANCELLED = 4;
+    case DEPARTED = 4;   // 技师开始前往目的地
 
     /**
-     * 订单状态:退款中
+     * 订单状态:已到达
+     * 技师已到达服务地点
      */
-    case REFUNDING = 5;
-
-    /**
-     * 订单状态:退款成功
-     */
-    case REFUNDED = 6;
-
-    /**
-     * 订单状态:退款失败
-     */
-    case REFUND_FAILED = 7;
-
-    /**
-     * 订单状态:接单
-     */
-    case ACCEPTED = 8;
-
-    /**
-     * 订单状态:出发
-     */
-    case DEPARTED = 9;
-
-    /**
-     * 订单状态:到达
-     */
-    case ARRIVED = 10;
+    case ARRIVED = 5;    // 技师已到达用户位置
 
     /**
      * 订单状态:开始服务
+     * 技师开始提供服务
      */
-    case STARTED = 11;
+    case SERVICE_START = 6;  // 正式开始服务
 
     /**
      * 订单状态:服务中
+     * 技师正在提供服务
      */
-    case SERVING = 12;
+    case SERVICING = 7;     // 服务进行中
 
     /**
      * 订单状态:服务结束
+     * 技师已完成服务内容
      */
-    case FINISHED = 13;
-
-    /**
-     * 订单状态:撤离
-     */
-    case LEFT = 14;
-
-    /**
-     * 订单状态:已评价
-     */
-    case COMMENTED = 15;
+    case SERVICE_END = 8;   // 服务内容已完成
 
     /**
-     * 订单状态:已拒单
+     * 订单状态:撤离中
+     * 技师正在离开服务地点
      */
-    case REJECTED = 16;
+    case LEAVING = 9;       // 技师正在返程
 
     /**
-     * 订单状态:报警
+     * 订单状态:已完成
+     * 订单全部流程结束
      */
-    case ALARM = 17;
+    case COMPLETED = 10;    // 订单完成状态
 
     /**
-     * 订单状态:服务完成
+     * 订单状态:已取消
+     * 订单被取消(可能是用户取消或系统取消)
      */
-    case COMPLETED = 18;
+    case CANCELLED = 11;    // 订单终止状态
 
     /**
      * 获取状态的显示文本
+     * 将状态值转换为对应的中文描述
      *
      * @return string 状态的中文描述
      */
     public function label(): string
     {
         return match ($this) {
-            self::CREATED => '下单',
-            self::ASSIGNED => '指定',
-            self::PAID => '支付',
-            self::CANCELLED => '取消',
-            self::REFUNDING => '退款中',
-            self::REFUNDED => '退款成功',
-            self::REFUND_FAILED => '退款失败',
-            self::ACCEPTED => '接单',
-            self::DEPARTED => '出发',
-            self::ARRIVED => '到达',
-            self::STARTED => '开始服务',
-            self::SERVING => '服务中',
-            self::FINISHED => '服务结束',
-            self::LEFT => '撤离',
-            self::COMMENTED => '已评价',
-            self::REJECTED => '已拒单',
-            self::ALARM => '报警',
-            self::COMPLETED => '服务完成',
+            self::CREATED => '已创建',        // 订单创建完成
+            self::PAID => '已支付',           // 支付完成
+            self::ACCEPTED => '已接单',       // 技师接单
+            self::DEPARTED => '已出发',       // 技师出发
+            self::ARRIVED => '已到达',        // 技师到达
+            self::SERVICE_START => '开始服务', // 开始提供服务
+            self::SERVICING => '服务中',      // 服务进行中
+            self::SERVICE_END => '服务结束',   // 服务完成
+            self::LEAVING => '撤离中',        // 技师离开
+            self::COMPLETED => '已完成',      // 订单完结
+            self::CANCELLED => '已取消',      // 订单取消
         };
     }
 
@@ -157,22 +132,16 @@ enum OrderStatus: int
     {
         return match ($value) {
             self::CREATED->value => self::CREATED,
-            self::ASSIGNED->value => self::ASSIGNED,
             self::PAID->value => self::PAID,
-            self::CANCELLED->value => self::CANCELLED,
-            self::REFUNDING->value => self::REFUNDING,
-            self::REFUNDED->value => self::REFUNDED,
-            self::REFUND_FAILED->value => self::REFUND_FAILED,
             self::ACCEPTED->value => self::ACCEPTED,
             self::DEPARTED->value => self::DEPARTED,
             self::ARRIVED->value => self::ARRIVED,
-            self::SERVING->value => self::SERVING,
-            self::FINISHED->value => self::FINISHED,
-            self::LEFT->value => self::LEFT,
-            self::COMMENTED->value => self::COMMENTED,
-            self::REJECTED->value => self::REJECTED,
-            self::ALARM->value => self::ALARM,
+            self::SERVICE_START->value => self::SERVICE_START,
+            self::SERVICING->value => self::SERVICING,
+            self::SERVICE_END->value => self::SERVICE_END,
+            self::LEAVING->value => self::LEAVING,
             self::COMPLETED->value => self::COMPLETED,
+            self::CANCELLED->value => self::CANCELLED,
             default => null
         };
     }
@@ -196,22 +165,16 @@ enum OrderStatus: int
     {
         return [
             self::CREATED->value => self::CREATED->label(),
-            self::ASSIGNED->value => self::ASSIGNED->label(),
             self::PAID->value => self::PAID->label(),
-            self::CANCELLED->value => self::CANCELLED->label(),
-            self::REFUNDING->value => self::REFUNDING->label(),
-            self::REFUNDED->value => self::REFUNDED->label(),
-            self::REFUND_FAILED->value => self::REFUND_FAILED->label(),
             self::ACCEPTED->value => self::ACCEPTED->label(),
             self::DEPARTED->value => self::DEPARTED->label(),
             self::ARRIVED->value => self::ARRIVED->label(),
-            self::SERVING->value => self::SERVING->label(),
-            self::FINISHED->value => self::FINISHED->label(),
-            self::LEFT->value => self::LEFT->label(),
-            self::COMMENTED->value => self::COMMENTED->label(),
-            self::REJECTED->value => self::REJECTED->label(),
-            self::ALARM->value => self::ALARM->label(),
+            self::SERVICE_START->value => self::SERVICE_START->label(),
+            self::SERVICING->value => self::SERVICING->label(),
+            self::SERVICE_END->value => self::SERVICE_END->label(),
+            self::LEAVING->value => self::LEAVING->label(),
             self::COMPLETED->value => self::COMPLETED->label(),
+            self::CANCELLED->value => self::CANCELLED->label(),
         ];
     }
 }

+ 64 - 47
app/Http/Controllers/Coach/AccountController.php

@@ -451,80 +451,97 @@ class AccountController extends Controller
      *
      * @description 获取当前登录技师的详细信息,包括基本信息、认证状态、位置信息、统计数据等
      *
+     * 业务流程:
+     * 1. 获取技师基本信息和关联数据
+     * 2. 生成技师工号和邀请码
+     * 3. 获取钱包和认证状态信息
+     * 4. 获取位置和店铺信息
+     * 5. 获取统计数据
+     * 6. 组装返回数据
+     *
      * @authenticated 需要技师身份认证
      *
-     * @response {
+     * @group 技师端-账户
+     *
+     * @responseFile 200 responses/coach/account/detail.json
+     * @response 200 {
      *   "status": true,
      *   "message": "获取成功",
      *   "data": {
-     *     "coach_no": "00000001",
-     *     "mobile": "13800138000",
-     *     "nickname": "张三",
-     *     "avatar": "https://example.com/avatar.jpg",
-     *     "age": 25,
-     *     "gender": 1,
-     *     "work_years": 5,
-     *     "intention_city": "杭州",
-     *     "life_photos": [
+     *     "coach_no": "00000001",                // 技师工号
+     *     "mobile": "138****8000",               // 手机号(脱敏)
+     *     "nickname": "张三",                     // 昵称
+     *     "avatar": "https://example.com/avatar.jpg", // 头像URL
+     *     "age": 25,                             // 年龄
+     *     "gender": 1,                           // 性别(1:男 2:女)
+     *     "work_years": 5,                       // 工作年限
+     *     "intention_city": "杭州",               // 意向城市
+     *     "life_photos": [                       // 生活照片数组
      *       "https://example.com/photo1.jpg",
      *       "https://example.com/photo2.jpg"
      *     ],
-     *     "introduction": "专业按摩师,从业5年",
-     *     "state": 1,
-     *     "state_text": "正常",
-     *     "invite_code": "C1",
-     *     "wallet": {
-     *       "balance": 1000,
-     *       "frozen": 200,
-     *       "total_income": 5000,
-     *       "today_income": 300,
-     *       "withdrawable": 800
+     *     "introduction": "专业按摩师,从业5年",    // 个人简介
+     *     "state": 1,                            // 状态值
+     *     "state_text": "正常",                   // 状态文本
+     *     "work_status": 2,                      // 工作状态(1:休息中 2:工作中-空闲 3:工作中-忙碌)
+     *     "work_status_text": "空闲中",           // 工作状态文本
+     *     "invite_code": "C1",                   // 邀请码
+     *     "wallet": {                            // 钱包信息
+     *       "balance": 1000.00,                  // 余额
+     *       "frozen": 200.00,                    // 冻结金额
+     *       "total_income": 5000.00,             // 总收入
+     *       "today_income": 300.00,              // 今日收入
+     *       "withdrawable": 800.00               // 可提现金额
      *     },
-     *     "auth_status": {
-     *       "base_info": {
-     *         "state": 1,
-     *         "state_text": "已通过",
-     *         "audit_remark": "审核通过",
-     *         "updated_at": "2024-03-22 10:00:00"
+     *     "auth_status": {                       // 认证状态信息
+     *       "base_info": {                       // 基本信息认证
+     *         "state": 1,                        // 状态值
+     *         "state_text": "已通过",             // 状态文本
+     *         "audit_remark": "审核通过",          // 审核备注
+     *         "updated_at": "2024-03-22 10:00:00" // 更新时间
      *       },
-     *       "real_name": {
+     *       "real_name": {                       // 实名认证
      *         "state": 1,
      *         "state_text": "已通过",
      *         "audit_remark": "审核通过",
      *         "updated_at": "2024-03-22 10:00:00"
      *       },
-     *       "qualification": {
+     *       "qualification": {                    // 资质认证
      *         "state": 1,
      *         "state_text": "已通过",
      *         "audit_remark": "审核通过",
      *         "updated_at": "2024-03-22 10:00:00"
      *       }
      *     },
-     *     "location": {
-     *       "province": "浙江省",
-     *       "city": "杭州市",
-     *       "district": "西湖区",
-     *       "address": "文三路478号",
-     *       "adcode": "330106",
-     *       "longitude": 120.12345,
-     *       "latitude": 30.12345
+     *     "location": {                          // 位置信息
+     *       "province": "浙江省",                 // 省份
+     *       "city": "杭州市",                     // 城市
+     *       "district": "西湖区",                 // 区县
+     *       "address": "文三路478号",             // 详细地址
+     *       "adcode": "330106",                  // 行政区划代码
+     *       "longitude": 120.12345,              // 经度
+     *       "latitude": 30.12345                 // 纬度
      *     },
-     *     "shop": {
-     *       "id": 1,
-     *       "name": "示例店铺",
-     *       "address": "杭州市西湖区文三路478号",
-     *       "phone": "0571-88888888"
+     *     "shop": {                              // 店铺信息
+     *       "id": 1,                             // 店铺ID
+     *       "name": "示例店铺",                   // 店铺名称
+     *       "address": "杭州市西湖区文三路478号",   // 店铺地址
+     *       "phone": "0571-88888888"             // 联系电话
      *     },
-     *     "statistics": {
-     *       "order_count": 100,
-     *       "completed_order_count": 80,
-     *       "level": 2,
-     *       "level_text": "中级技师",
-     *       "rating": 4.8
+     *     "statistics": {                        // 统计数据
+     *       "order_count": 100,                  // 总订单数
+     *       "completed_order_count": 80,         // 已完成订单数
+     *       "pending_order_count": 5,            // 未完成订单数
+     *       "level": 2,                          // 技师等级
+     *       "level_text": "中级技师",             // 等级文本
+     *       "rating": 4.8,                       // 评分
+     *       "grab_order_count": 50,              // 抢单数量
+     *       "carrying_order_count": 3            // 带接单数量(已支付但未被接单的订单数)
      *     }
      *   }
      * }
      * @response 404 {
+     *   "status": false,
      *   "message": "技师信息不存在"
      * }
      */

+ 73 - 23
app/Services/Coach/AccountService.php

@@ -2,6 +2,7 @@
 
 namespace App\Services\Coach;
 
+use App\Models\Order;
 use App\Models\ShopInfo;
 use App\Models\CoachUser;
 use App\Enums\OrderStatus;
@@ -13,6 +14,7 @@ use App\Models\CoachSchedule;
 use App\Models\CoachStatistic;
 use App\Enums\TechnicianStatus;
 use App\Models\CoachInfoRecord;
+use App\Models\OrderGrabRecord;
 use Illuminate\Support\Facades\DB;
 use App\Enums\TechnicianAuthStatus;
 use App\Enums\TechnicianWorkStatus;
@@ -281,7 +283,6 @@ class AccountService
      */
     public function getCoachDetail(): array
     {
-        // 获取技师信息并预加载关联,避免 N+1 问题
         $coach = Auth::user()->coach->load([
             'latestInfoRecord',
             'latestRealRecord',
@@ -294,6 +295,15 @@ class AccountService
         // 获取基本信息
         $baseInfo = $this->formatBaseInfo($coach->latestInfoRecord);
 
+        // 获取订单统计
+        $orderStats = $this->getOrderStatistics($coach->id);
+
+        // 获取评分统计
+        $statistics = $this->formatStatistics($coach->statistics);
+
+        // 合并所有统计数据
+        $statistics = array_merge($orderStats, $statistics);
+
         // 生成技师工号
         $coachNo = str_pad($coach->id, 8, '0', STR_PAD_LEFT);
 
@@ -312,9 +322,6 @@ class AccountService
         // 获取店铺信息
         $shop = $this->formatShop($coach->shop);
 
-        // 获取统计信息
-        $statistics = $this->formatStatistics($coach->statistics);
-
         // 组装返回数据
         return array_merge(
             [
@@ -326,6 +333,8 @@ class AccountService
             [
                 'state' => $coach->state,
                 'state_text' => TechnicianStatus::fromValue($coach->state)?->label(),
+                'work_status' => $coach->work_status,  // 工作状态
+                'work_status_text' => TechnicianWorkStatus::fromValue($coach->work_status)?->label(),  // 状态文本
             ],
             [
                 'auth_status' => $authStatus,
@@ -433,26 +442,26 @@ class AccountService
     }
 
     /**
-     * 格式化统计信息
-     * 处理技师的订单统计和等级信息
+     * 格式化评分统计信息
+     * 处理技师的评分和等级信息
      *
-     * 业务逻辑:
-     * 1. 获取订单相关统计数据
-     * 2. 获取技师等级信息
-     * 3. 获取评分信息
-     * 4. 处理默认值
-     *
-     * @param CoachStatistic|null $statistics 统计对象
-     * @return array 格式化后的统计信息
+     * @param CoachStatistic|null $statistics 评分统计对象
+     * @return array 格式化后的评分信息
      */
     private function formatStatistics(?CoachStatistic $statistics): array
     {
+        if (!$statistics) {
+            return [
+                'level' => 1,                    // 技师等级
+                'level_text' => $this->getLevelText(1),  // 等级文本
+                'rating' => 5.0,                 // 评分
+            ];
+        }
+
         return [
-            'order_count' => $statistics?->order_count ?? 0,              // 总订单数
-            'completed_order_count' => $statistics?->completed_order_count ?? 0,  // 已完成订单数
-            'level' => $statistics?->level ?? 1,                          // 技师等级
-            'level_text' => $this->getLevelText($statistics?->level ?? 1),  // 等级文本
-            'rating' => $statistics?->rating ?? 5.0,                      // 评分
+            'level' => $statistics->level ?? 1,
+            'level_text' => $this->getLevelText($statistics->level ?? 1),
+            'rating' => $statistics->rating ?? 5.0,
         ];
     }
 
@@ -513,7 +522,7 @@ class AccountService
      */
     private function formatQualification($qual)
     {
-        // 资质类型文本映
+        // 资质类型文本映
         $qualTypeMap = [
             1 => '初级按摩师',
             2 => '中级按摩师',
@@ -838,7 +847,7 @@ class AccountService
                     $range['start_minutes'] <= $prevRange['end_minutes'],
                     400,
                     "时间段 {$prevRange['start_time']}-{$prevRange['end_time']} 和 " .
-                        "{$range['start_time']}-{$range['end_time']} 之间存在重叠"
+                        "{$range['start_time']}-{$range['end_time']} 之间重叠"
                 );
             }
         });
@@ -951,7 +960,7 @@ class AccountService
                         OrderStatus::ACCEPTED->value,   // 已接单
                         OrderStatus::DEPARTED->value,   // 已出发
                         OrderStatus::ARRIVED->value,    // 已到达
-                        OrderStatus::SERVING->value,    // 服务中
+                        OrderStatus::SERVICING->value,    // 服务中
                     ])
                     ->exists();
 
@@ -1340,7 +1349,7 @@ class AccountService
      */
     private function getWalletInfo(int $coachId): array
     {
-        // 获取技师对象及其钱包关联
+        // 获取技师及其钱包关联
         $coach = CoachUser::with('wallet')->find($coachId);
 
         // 如果钱包不存在,返回默认值
@@ -1568,4 +1577,45 @@ class AccountService
             'list' => $list
         ];
     }
+
+    /**
+     * 获取订单统计数据
+     *
+     * @param int $coachId 技师ID
+     * @return array 订单统计数据
+     */
+    private function getOrderStatistics(int $coachId): array
+    {
+        // 从 Order 表获取订单统计
+        $orderStats = Order::where('coach_id', $coachId)
+            ->selectRaw('
+                COUNT(*) as total_count,
+                SUM(CASE WHEN state = ? THEN 1 ELSE 0 END) as completed_count,
+                SUM(CASE WHEN state IN (?,?,?,?,?,?,?,?) THEN 1 ELSE 0 END) as pending_count,
+                SUM(CASE WHEN state = ? THEN 1 ELSE 0 END) as carrying_count
+            ', [
+                OrderStatus::COMPLETED->value,  // 已完成
+                OrderStatus::PAID->value,       // 已支付
+                OrderStatus::ACCEPTED->value,   // 已接单
+                OrderStatus::DEPARTED->value,   // 已出发
+                OrderStatus::ARRIVED->value,    // 已到达
+                OrderStatus::SERVICE_START->value, // 开始服务
+                OrderStatus::SERVICING->value,  // 服务中
+                OrderStatus::SERVICE_END->value, // 服务结束
+                OrderStatus::LEAVING->value,    // 撤离中
+                OrderStatus::PAID->value        // 带接单(已支付)
+            ])
+            ->first();
+
+        // 获取抢单数量
+        $grabOrderCount = OrderGrabRecord::where('coach_id', $coachId)->count();
+
+        return [
+            'order_count' => $orderStats->total_count ?? 0,         // 总订单数
+            'completed_order_count' => $orderStats->completed_count ?? 0,  // 已完成订单数
+            'pending_order_count' => $orderStats->pending_count ?? 0,      // 进行中订单数
+            'carrying_order_count' => $orderStats->carrying_count ?? 0,    // 带接单数量
+            'grab_order_count' => $grabOrderCount,                  // 抢单数量
+        ];
+    }
 }