Browse Source

feat:技师端-信息、实名、资质提交

刘学玺 4 months ago
parent
commit
1e4a1782ae

+ 119 - 0
app/Http/Controllers/Coach/AccountController.php

@@ -0,0 +1,119 @@
+<?php
+
+namespace App\Http\Controllers\Coach;
+
+use App\Http\Controllers\Controller;
+use App\Services\Coach\AccountService;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
+
+/**
+ * @group 技师端
+ *
+ * 技师账户相关的API接口
+ */
+class AccountController extends Controller
+{
+    protected AccountService $service;
+
+    public function __construct(AccountService $service)
+    {
+        $this->service = $service;
+    }
+
+    /**
+     * [账户]提交基本信息
+     *
+     * @description 提交技师的基本个人信息
+     *
+     * @authenticated
+     *
+     * @bodyParam nickname string required 昵称 Example: 张三
+     * @bodyParam avatar string required 头像URL Example: http://example.com/avatar.jpg
+     * @bodyParam gender string required 性别 Example: 1
+     * @bodyParam mobile string required 手机号 Example: 13800138000
+     * @bodyParam birthday date required 出生日期 Example: 1990-01-01
+     * @bodyParam work_years integer required 工作年限 Example: 5
+     * @bodyParam intention_city string required 意向城市 Example: 北京
+     * @bodyParam introduction string required 个人简介 Example: 专业按摩师,从业5年
+     *
+     * @response {
+     *  "message": "基本信息提交成功"
+     * }
+     */
+    public function submitBaseInfo(Request $request)
+    {
+        $data = $request->validate([
+            'nickname' => 'required|string|max:255',
+            'avatar' => 'required|url|max:255',
+            'gender' => 'required|string|max:255',
+            'mobile' => 'required|string|max:255',
+            'birthday' => 'required|date',
+            'work_years' => 'required|integer',
+            'intention_city' => 'required|string|max:255',
+            'introduction' => 'required|string|max:255',
+        ]);
+
+        return $this->service->submitBaseInfo(Auth::user()->id, $data);
+    }
+
+    /**
+     * [账户]提交资质信息
+     *
+     * @description 提交技师的资质认证信息
+     *
+     * @authenticated
+     *
+     * @bodyParam qual_type string required 资质类型 Example: 高级按摩师
+     * @bodyParam qual_no string required 资质证书编号 Example: XZ2024001
+     * @bodyParam qual_photo string required 资质证书照片 Example: http://example.com/cert.jpg
+     * @bodyParam valid_start date required 有效期开始日期 Example: 2024-01-01
+     * @bodyParam valid_end date required 有效期结束日期 Example: 2029-01-01
+     *
+     * @response {
+     *  "message": "资质信息提交成功"
+     * }
+     */
+    public function submitQualification(Request $request)
+    {
+        $data = $request->validate([
+            'qual_type' => 'required|string|max:255',
+            'qual_no' => 'required|string|max:255',
+            'qual_photo' => 'required|string|max:255|url',
+            'valid_start' => 'required|date',
+            'valid_end' => 'required|date|after:valid_start',
+        ]);
+
+        return $this->service->submitQualification(Auth::user()->id, $data);
+    }
+
+    /**
+     * [账户]提交实名认证
+     *
+     * @description 提交技师的实名认证信息
+     *
+     * @authenticated
+     *
+     * @bodyParam real_name string required 姓名 Example: 张三
+     * @bodyParam id_card string required 身份证号 Example: 370602199001011234
+     * @bodyParam id_card_front_photo string required 身份证正面照片 Example: http://example.com/front.jpg
+     * @bodyParam id_card_back_photo string required 身份证反面照片 Example: http://example.com/back.jpg
+     * @bodyParam id_card_hand_photo string required 手持身份证照片 Example: http://example.com/hold.jpg
+     *
+     * @response {
+     *  "message": "实名认证信息提交成功"
+     * }
+     */
+    public function submitRealName(Request $request)
+    {
+        $data = $request->validate([
+            'real_name' => 'required|string|max:50',
+            'id_card' => 'required|string|size:18',
+            'id_card_front_photo' => 'required|string|max:255|url',
+            'id_card_back_photo' => 'required|string|max:255|url',
+            'id_card_hand_photo' => 'required|string|max:255|url',
+        ]);
+
+        return $this->service->submitRealName(Auth::user()->id, $data);
+    }
+}

+ 6 - 3
app/Models/CoachQualRecord.php

@@ -10,16 +10,19 @@ use Slowlyo\OwlAdmin\Models\BaseModel as Model;
  */
 class CoachQualRecord extends Model
 {
-	use SoftDeletes;
+    use SoftDeletes;
 
-	protected $table = 'coach_qual_records';
+    protected $table = 'coach_qual_records';
+
+    protected $guarded = [];
 
     /**
      * @Author FelixYin
+     *
      * @description 资质记录所属技师
      */
     public function coach()
     {
         return $this->belongsTo('App\Models\CoachUser', 'coach_id');
     }
-}
+}

+ 5 - 3
app/Models/CoachRealRecord.php

@@ -10,7 +10,9 @@ use Slowlyo\OwlAdmin\Models\BaseModel as Model;
  */
 class CoachRealRecord extends Model
 {
-	use SoftDeletes;
+    use SoftDeletes;
 
-	protected $table = 'coach_real_records';
-}
+    protected $table = 'coach_real_records';
+
+    protected $guarded = [];
+}

+ 122 - 0
app/Services/Coach/AccountService.php

@@ -0,0 +1,122 @@
+<?php
+
+namespace App\Services\Coach;
+
+use App\Models\MemberUser;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Log;
+
+class AccountService
+{
+    /**
+     * 提交技师基本信息
+     */
+    public function submitBaseInfo(int $userId, array $data)
+    {
+        DB::beginTransaction();
+        try {
+            // 获取当前登录用户
+            $user = MemberUser::find($userId);
+            $coach = $user->coach;
+
+            // 创建技师信息
+            $coach->infoRecords()->create(
+                [
+                    'nickname' => $data['nickname'],
+                    'avatar' => $data['avatar'],
+                    'gender' => $data['gender'],
+                    'mobile' => $data['mobile'],
+                    'birthday' => $data['birthday'],
+                    'work_years' => $data['work_years'],
+                    'intention_city' => $data['intention_city'],
+                    'introduction' => $data['introduction'],
+                ]
+            );
+
+            DB::commit();
+
+            return ['message' => '基本信息提交成功'];
+
+        } catch (\Exception $e) {
+            DB::rollBack();
+            Log::error('提交技师基本信息失败:', [
+                'message' => $e->getMessage(),
+                'data' => $data,
+            ]);
+            throw $e;
+        }
+    }
+
+    /**
+     * 提交技师资质信息
+     *
+     * @param  int  $userId  用户ID
+     * @param  array  $data  资质信息数据
+     *
+     * @throws \Exception 提交失败时抛出异常
+     */
+    public function submitQualification(int $userId, array $data)
+    {
+        DB::beginTransaction();
+        try {
+            // 获取当前登录用户
+            $user = MemberUser::find($userId);
+            $coach = $user->coach;
+
+            // 更新技师资质信息
+            $coach->qualRecords()->create([
+                'qual_type' => $data['qual_type'],
+                'qual_no' => $data['qual_no'],
+                'qual_photo' => $data['qual_photo'],
+                'valid_start' => $data['valid_start'],
+                'valid_end' => $data['valid_end'],
+            ]);
+
+            DB::commit();
+
+            return ['message' => '资质信息提交成功'];
+
+        } catch (\Exception $e) {
+            DB::rollBack();
+            Log::error('提交技师资质信息失败:', [
+                'message' => $e->getMessage(),
+                'data' => $data,
+            ]);
+            throw $e;
+        }
+    }
+
+    /**
+     * 提交实名认证信息
+     */
+    public function submitRealName(int $userId, array $data)
+    {
+        DB::beginTransaction();
+        try {
+            // 获取当前登录用户
+            $user = MemberUser::find($userId);
+            $coach = $user->coach;
+
+            // 更新实名信息
+            $coach->realRecords()->create([
+                'real_name' => $data['real_name'],
+                'id_card' => $data['id_card'],
+                'id_card_front_photo' => $data['id_card_front_photo'],
+                'id_card_back_photo' => $data['id_card_back_photo'],
+                'id_card_hand_photo' => $data['id_card_hand_photo'],
+            ]);
+
+            DB::commit();
+
+            return ['message' => '实名认证信息提交成功'];
+
+        } catch (\Exception $e) {
+            DB::rollBack();
+            Log::error('提交实名认证信息失败:', [
+                'message' => $e->getMessage(),
+                'data' => $data,
+            ]);
+            throw $e;
+        }
+    }
+}

+ 100 - 88
routes/api.php

@@ -18,108 +18,120 @@ use Illuminate\Support\Facades\Route;
 Route::get('scribe/update-token/{mobile}', [ScribeController::class, 'updateAuthToken']);
 Route::get('/enums', [EnumController::class, 'getEnumData']);
 
-// 无需认证的公开路由
-Route::prefix('account')->group(function () {
-    // 发送验证码
-    Route::post('send-code', [AccountController::class, 'sendVerifyCode']);
-    // 手机号登录
-    Route::post('login', [AccountController::class, 'login']);
-    // 微信登录
-    Route::post('wx-login', [AccountController::class, 'wxLogin']);
-});
+// 客户端路由组
+Route::prefix('client')->group(function () {
 
-// 需要认证的路由组
-Route::middleware('auth:sanctum')->group(function () {
-    // 账号相关
+    // 无需认证的公开路由
     Route::prefix('account')->group(function () {
-        // 退出登录
-        Route::post('logout', [AccountController::class, 'logout']);
-        // 注销账号
-        Route::delete('/', [AccountController::class, 'destroy']);
+        // 发送验证码
+        Route::post('send-code', [AccountController::class, 'sendVerifyCode']);
+        // 手机号登录
+        Route::post('login', [AccountController::class, 'login']);
+        // 微信登录
+        Route::post('wx-login', [AccountController::class, 'wxLogin']);
     });
 
-    // 用户相关
-    Route::prefix('user')->group(function () {
-        // 获取用户信息
-        Route::get('/', [UserController::class, 'show']);
-        // 用户注册
-        Route::post('/', [UserController::class, 'register']);
-        // 更新用户信息
-        Route::put('/', [UserController::class, 'update']);
-
-        // 提现
-        Route::post('withdraw', [UserController::class, 'withdraw']);
-
-        // 用户反馈
-        // Route::post('/feedback', [UserController::class, 'feedback']);
-        // 申请成为技师
-        Route::post('/apply-coach', [UserController::class, 'applyCoach']);
-        // 生成邀请码
-        Route::get('/invite-code', [UserController::class, 'generateInviteCode']);
-    });
+    // 需要认证的路由组
+    Route::middleware('auth:sanctum')->group(function () {
+        // 账号相关
+        Route::prefix('account')->group(function () {
+            // 退出登录
+            Route::post('logout', [AccountController::class, 'logout']);
+            // 注销账号
+            Route::delete('/', [AccountController::class, 'destroy']);
+        });
 
-    // 项目相关
-    Route::prefix('project')->group(function () {
-        Route::get('/', [ProjectController::class, 'index']); // 获取项目列表
-        Route::get('/detail', [ProjectController::class, 'detail']); // 获取项目详情
-        Route::get('/coach-list', [ProjectController::class, 'coachProjectList']); // 获取技师开通的项目列表
-    });
+        // 用户相关
+        Route::prefix('user')->group(function () {
+            // 获取用户信息
+            Route::get('/', [UserController::class, 'show']);
+            // 用户注册
+            Route::post('/', [UserController::class, 'register']);
+            // 更新用户信息
+            Route::put('/', [UserController::class, 'update']);
+
+            // 提现
+            Route::post('withdraw', [UserController::class, 'withdraw']);
+
+            // 用户反馈
+            // Route::post('/feedback', [UserController::class, 'feedback']);
+            // 申请成为技师
+            Route::post('/apply-coach', [UserController::class, 'applyCoach']);
+            // 生成邀请码
+            Route::get('/invite-code', [UserController::class, 'generateInviteCode']);
+        });
 
-    // 技师相关
-    Route::prefix('coach')->group(function () {
-        Route::prefix('location')->group(function () {
-            Route::get('/', [CoachLocationController::class, 'index']); // 获取所有技师定位
-            Route::post('/', [CoachLocationController::class, 'store']); // 创建新的技师定位
-            Route::delete('/{id}', [CoachLocationController::class, 'destroy']);    // 删除技师定位
+        // 项目相关
+        Route::prefix('project')->group(function () {
+            Route::get('/', [ProjectController::class, 'index']); // 获取项目列表
+            Route::get('/detail', [ProjectController::class, 'detail']); // 获取项目详情
+            Route::get('/coach-list', [ProjectController::class, 'coachProjectList']); // 获取技师开通的项目列表
         });
-        Route::get('/', [CoachController::class, 'list']); // 获取技师列表
-        Route::get('/{id}', [CoachController::class, 'detail']); // 获取技师详情
 
-    });
+        // 技师相关
+        Route::prefix('coach')->group(function () {
+            Route::prefix('location')->group(function () {
+                Route::get('/', [CoachLocationController::class, 'index']); // 获取所有技师定位
+                Route::post('/', [CoachLocationController::class, 'store']); // 创建新的技师定位
+                Route::delete('/{id}', [CoachLocationController::class, 'destroy']);    // 删除技师定位
+            });
+            Route::get('/', [CoachController::class, 'list']); // 获取技师列表
+            Route::get('/{id}', [CoachController::class, 'detail']); // 获取技师详情
 
-    // 用户地址相关
-    Route::prefix('address')->group(function () {
-        Route::get('default', [UserAddressController::class, 'getDefault']);
-        Route::post('/', [UserAddressController::class, 'store']);
-        Route::put('/{id}', [UserAddressController::class, 'update']);
-        Route::delete('/{id}', [UserAddressController::class, 'destroy']);
-        Route::put('/{id}/default', [UserAddressController::class, 'setDefault']);
-    });
+        });
 
-    // 订单相关
-    Route::prefix('orders')->group(function () {
-        Route::post('initialize', [OrderController::class, 'initialize']);
-        Route::post('create', [OrderController::class, 'create']);
-        Route::post('cancel', [OrderController::class, 'cancel']);
-        Route::post('finish', [OrderController::class, 'finish']);
-        Route::post('confirm-leave', [OrderController::class, 'confirmLeave']);
-        Route::get('list', [OrderController::class, 'list']);
-        Route::get('detail/{id}', [OrderController::class, 'detail']);
-        Route::post('add-time', [OrderController::class, 'addTime']);
-        Route::post('calculate-order-amount', [OrderController::class, 'calculateOrderAmount']);
-        // Route::post('refund/{id}', [OrderController::class, 'refund']);
-        // Route::post('get-agent-config', [OrderController::class, 'getAgentConfig']);
-        // Route::post('get-coach-config', [OrderController::class, 'getCoachConfig']);
-        // Route::post('calculate-delivery-fee', [OrderController::class, 'calculateDeliveryFee']);
-        Route::get('grab-list', [OrderController::class, 'getOrderGrabList']);
-    });
+        // 用户地址相关
+        Route::prefix('address')->group(function () {
+            Route::get('default', [UserAddressController::class, 'getDefault']);
+            Route::post('/', [UserAddressController::class, 'store']);
+            Route::put('/{id}', [UserAddressController::class, 'update']);
+            Route::delete('/{id}', [UserAddressController::class, 'destroy']);
+            Route::put('/{id}/default', [UserAddressController::class, 'setDefault']);
+        });
 
-    // 钱包相关
-    Route::prefix('wallet')->group(function () {
-        Route::get('records', [WalletController::class, 'records']);
-        // 获取钱包信息
-        Route::get('wallet', [WalletController::class, 'wallet']);
-    });
+        // 订单相关
+        Route::prefix('orders')->group(function () {
+            Route::post('initialize', [OrderController::class, 'initialize']);
+            Route::post('create', [OrderController::class, 'create']);
+            Route::post('cancel', [OrderController::class, 'cancel']);
+            Route::post('finish', [OrderController::class, 'finish']);
+            Route::post('confirm-leave', [OrderController::class, 'confirmLeave']);
+            Route::get('list', [OrderController::class, 'list']);
+            Route::get('detail/{id}', [OrderController::class, 'detail']);
+            Route::post('add-time', [OrderController::class, 'addTime']);
+            Route::post('calculate-order-amount', [OrderController::class, 'calculateOrderAmount']);
+            // Route::post('refund/{id}', [OrderController::class, 'refund']);
+            // Route::post('get-agent-config', [OrderController::class, 'getAgentConfig']);
+            // Route::post('get-coach-config', [OrderController::class, 'getCoachConfig']);
+            // Route::post('calculate-delivery-fee', [OrderController::class, 'calculateDeliveryFee']);
+            Route::get('grab-list', [OrderController::class, 'getOrderGrabList']);
+        });
+
+        // 钱包相关
+        Route::prefix('wallet')->group(function () {
+            Route::get('records', [WalletController::class, 'records']);
+            // 获取钱包信息
+            Route::get('wallet', [WalletController::class, 'wallet']);
+        });
+
+        // 团队管理路由
+        Route::prefix('team')->group(function () {
+            Route::get('list', [MarketDistTeamController::class, 'index'])->name('team.list');
+        });
 
-    // 团队管理路由
-    Route::prefix('team')->group(function () {
-        Route::get('list', [MarketDistTeamController::class, 'index'])->name('team.list');
     });
 
-    // 技师端路由组
-    Route::prefix('coach')->middleware(['auth:sanctum'])->group(function () {
-        // 技师端路由组
-        Route::get('orders/grab-list', [CoachOrderController::class, 'getGrabList']);
+});
+
+// 技师端路由组
+Route::prefix('coach')->middleware(['auth:sanctum'])->group(function () {
+    // 账户相关路由组
+    Route::prefix('account')->group(function () {
+        Route::post('base-info', [App\Http\Controllers\Coach\AccountController::class, 'submitBaseInfo']);
+        Route::post('qualification', [App\Http\Controllers\Coach\AccountController::class, 'submitQualification']);
+        Route::post('real-name', [App\Http\Controllers\Coach\AccountController::class, 'submitRealName']);
     });
 
+    // 订单相关路由
+    Route::get('orders/grab-list', [CoachOrderController::class, 'getGrabList']);
 });