Ver Fonte

fixed:技师端-优化开通项目列表

刘学玺 há 4 meses atrás
pai
commit
69ff5e5eb0

+ 30 - 20
app/Http/Controllers/Coach/ProjectController.php

@@ -2,11 +2,11 @@
 
 namespace App\Http\Controllers\Coach;
 
-use App\Http\Controllers\Controller;
-use App\Services\Coach\ProjectService;
-use App\Traits\ResponseTrait;
 use Illuminate\Http\Request;
+use App\Traits\ResponseTrait;
+use App\Http\Controllers\Controller;
 use Illuminate\Support\Facades\Auth;
+use App\Services\Coach\ProjectService;
 
 /**
  * @group 技师端
@@ -27,30 +27,40 @@ class ProjectController extends Controller
     /**
      * [项目]获取可开通项目列表
      *
-     * @description 获取技师可以开通的项目列表
+     * @description 获取技师可以开通的项目列表,包含项目的基本信息、价格信息和服务说明,以及是否已开通状态
      *
-     * @authenticated
+     * @authenticated 需要技师身份认证
      *
      * @response {
-     *   "data": {
-     *     "items": [
-     *       {
-     *         "id": 1,
-     *         "name": "精油推拿",
-     *         "cover": "http://example.com/cover.jpg",
-     *         "price": "188.00",
-     *         "duration": 60,
-     *         "description": "项目描述",
-     *         "qualification_requirements": "资质要求"
-     *       }
-     *     ],
-     *     "total": 10
-     *   }
+     *   "status": true,
+     *   "message": "获取成功",
+     *   "data": [
+     *     {
+     *       "id": 1,                    // 项目ID
+     *       "title": "精油推拿",         // 项目标题
+     *       "subtitle": "专业精油推拿",  // 项目副标题
+     *       "cover": "http://example.com/cover.jpg", // 项目封面图
+     *       "price": "188.00",          // 项目价格
+     *       "original_price": "288.00", // 原价
+     *       "sales": 100,               // 销量
+     *       "duration": 60,             // 服务时长(分钟)
+     *       "project_desc": "项目描述",  // 项目描述
+     *       "service_desc": "服务说明",  // 服务说明
+     *       "type": 1,                  // 项目类型
+     *       "is_opened": false          // 是否已开通
+     *     }
+     *   ]
+     * }
+     *
+     * @response 404 {
+     *   "message": "技师信息不存在"
      * }
      */
     public function getAvailableProjects()
     {
-        return $this->success($this->service->getAvailableProjects(Auth::user()->id));
+        return $this->success(
+            $this->service->getAvailableProjects(Auth::user()->coach)
+        );
     }
 
     /**

+ 55 - 48
app/Services/Coach/ProjectService.php

@@ -2,11 +2,12 @@
 
 namespace App\Services\Coach;
 
-use App\Enums\ProjectStatus;
-use App\Enums\TechnicianStatus;
-use App\Models\MemberUser;
 use App\Models\Project;
+use App\Models\CoachUser;
+use App\Models\MemberUser;
+use App\Enums\ProjectStatus;
 use App\Models\SettingGroup;
+use App\Enums\TechnicianStatus;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Log;
 
@@ -15,53 +16,59 @@ class ProjectService
     /**
      * 获取所有可以开通的项目列表
      *
-     * @param  int  $userId  技师用户ID
+     * 业务流程:
+     * 1. 获取所有状态为开放的项目
+     * 2. 通过关联查询检查项目开通状态
+     * 3. 返回项目列表
+     *
+     * 注意事项:
+     * - 只返回状态为开放的项目
+     * - 已开通的项目必须是状态正常的
+     * - 使用 leftJoin 优化查询性能
+     * - 在数据库层面计算开通状态文本
+     *
+     * @param CoachUser $coach 技师对象
+     * @return array 项目列表,每个项目包含:
+     *        - id: int 项目ID
+     *        - title: string 项目标题
+     *        - subtitle: string|null 项目副标题
+     *        - cover: string 项目封面图
+     *        - price: decimal 项目价格
+     *        - original_price: decimal 原价
+     *        - sales: int 销量
+     *        - duration: int 服务时长(分钟)
+     *        - project_desc: string 项目描述
+     *        - service_desc: string 服务说明
+     *        - type: int 项目类型
+     *        - is_opened: bool 是否已开通
+     *        - opened_text: string 开通状态文本(已开通|未开通)
      */
-    public function getAvailableProjects(int $userId): array
+    public function getAvailableProjects(CoachUser $coach): array
     {
-        try {
-            // 加载用户和技师信息
-            $user = MemberUser::with(['coach', 'coach.projects'])->findOrFail($userId);
-            abort_if(! $user->coach, 404, '技师信息不存在');
-
-            // 获取所有可开通的项目
-            $projects = Project::where('state', ProjectStatus::OPEN->value)
-                ->select([
-                    'id',
-                    'title',
-                    'subtitle',
-                    'cover',
-                    'price',
-                    'original_price',
-                    'sales',
-                    'duration',
-                    'project_desc',
-                    'service_desc',
-                    'type',
-                ])
-                ->get();
-
-            // 记录日志
-            Log::info('获取可开通项目列表成功', [
-                'user_id' => $userId,
-                'coach_id' => $user->coach->id,
-                'project_count' => $projects->count(),
-            ]);
-
-            return [
-                'items' => $projects,
-                'total' => $projects->count(),
-            ];
-
-        } catch (\Exception $e) {
-            Log::error('获取可开通项目列表失败', [
-                'user_id' => $userId,
-                'error' => $e->getMessage(),
-                'file' => $e->getFile(),
-                'line' => $e->getLine(),
-            ]);
-            throw $e;
-        }
+        // 使用 leftJoin 优化查询,避免 N+1 问题
+        return Project::where('project.state', ProjectStatus::OPEN->value)
+            ->leftJoin('coach_project', function ($join) use ($coach) {
+                $join->on('project.id', '=', 'coach_project.project_id')
+                    ->where('coach_project.coach_id', '=', $coach->id)
+                    ->where('coach_project.state', '=', ProjectStatus::OPEN->value);
+            })
+            ->select([
+                'project.id',
+                'project.title',
+                'project.subtitle',
+                'project.cover',
+                'project.price',
+                'project.original_price',
+                'project.sales',
+                'project.duration',
+                'project.project_desc',
+                'project.service_desc',
+                'project.type',
+                DB::raw('CASE WHEN coach_project.id IS NOT NULL THEN true ELSE false END as is_opened'),
+                DB::raw('CASE WHEN coach_project.id IS NOT NULL THEN "已开通" ELSE "未开通" END as opened_text'),
+            ])
+            ->get()
+            ->toArray();
     }
 
     /**