Browse Source

feat:技师端-获取技师信息

刘学玺 4 months ago
parent
commit
e2b9ee87dd

+ 72 - 41
app/Http/Controllers/Coach/AccountController.php

@@ -3,8 +3,11 @@
 namespace App\Http\Controllers\Coach;
 
 use App\Http\Controllers\Controller;
+use App\Http\Requests\Coach\SubmitBaseInfoRequest;
+use App\Http\Requests\Coach\SubmitQualificationRequest;
+use App\Http\Requests\Coach\SubmitRealNameRequest;
 use App\Services\Coach\AccountService;
-use Illuminate\Http\Request;
+use App\Traits\ResponseTrait;
 use Illuminate\Support\Facades\Auth;
 
 /**
@@ -14,6 +17,8 @@ use Illuminate\Support\Facades\Auth;
  */
 class AccountController extends Controller
 {
+    use ResponseTrait;
+
     protected AccountService $service;
 
     public function __construct(AccountService $service)
@@ -28,33 +33,24 @@ class AccountController extends Controller
      *
      * @authenticated
      *
-     * @bodyParam nickname string required 昵称 Example: 张三
+     * @bodyParam nickname string required 昵称(2-20个字符) Example: 张三
      * @bodyParam avatar string required 头像URL Example: http://example.com/avatar.jpg
-     * @bodyParam gender string required 性别 Example: 1
+     * @bodyParam gender string required 性别(1:男 2:女) Example: 1
      * @bodyParam mobile string required 手机号 Example: 13800138000
-     * @bodyParam birthday date required 出生日期 Example: 1990-01-01
-     * @bodyParam work_years integer required 工作年限 Example: 5
+     * @bodyParam birthday date required 出生日期(年龄需满18岁) Example: 1990-01-01
+     * @bodyParam work_years integer required 工作年限(0-99) Example: 5
      * @bodyParam intention_city string required 意向城市 Example: 北京
-     * @bodyParam introduction string required 个人简介 Example: 专业按摩师,从业5年
+     * @bodyParam introduction string required 个人简介(10-255个字符) Example: 专业按摩师,从业5年
      *
      * @response {
      *  "message": "基本信息提交成功"
      * }
      */
-    public function submitBaseInfo(Request $request)
+    public function submitBaseInfo(SubmitBaseInfoRequest $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',
-        ]);
+        $data = $request->validated();
 
-        return $this->service->submitBaseInfo(Auth::user()->id, $data);
+        return $this->success($this->service->submitBaseInfo(Auth::user(), $data));
     }
 
     /**
@@ -64,27 +60,21 @@ class AccountController extends Controller
      *
      * @authenticated
      *
-     * @bodyParam qual_type string required 资质类型 Example: 高级按摩师
-     * @bodyParam qual_no string required 资质证书编号 Example: XZ2024001
+     * @bodyParam qual_type string required 资质类型(按摩师/理疗师等) Example: 高级按摩师
+     * @bodyParam qual_no string required 资质证书编号(5-50个字符) 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
+     * @bodyParam valid_end date required 有效期结束日期(必须大于开始日期) Example: 2029-01-01
      *
      * @response {
      *  "message": "资质信息提交成功"
      * }
      */
-    public function submitQualification(Request $request)
+    public function submitQualification(SubmitQualificationRequest $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',
-        ]);
+        $data = $request->validated();
 
-        return $this->service->submitQualification(Auth::user()->id, $data);
+        return $this->success($this->service->submitQualification(Auth::user(), $data));
     }
 
     /**
@@ -94,8 +84,8 @@ class AccountController extends Controller
      *
      * @authenticated
      *
-     * @bodyParam real_name string required 姓名 Example: 张三
-     * @bodyParam id_card string required 身份证号 Example: 370602199001011234
+     * @bodyParam real_name string required 姓名(2-20个字符) Example: 张三
+     * @bodyParam id_card string required 身份证号(18位) 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
@@ -104,16 +94,57 @@ class AccountController extends Controller
      *  "message": "实名认证信息提交成功"
      * }
      */
-    public function submitRealName(Request $request)
+    public function submitRealName(SubmitRealNameRequest $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',
-        ]);
+        $data = $request->validated();
+
+        return $this->success($this->service->submitRealName(Auth::user(), $data));
+    }
 
-        return $this->service->submitRealName(Auth::user()->id, $data);
+    /**
+     * [账户]获取技师信息
+     *
+     * @description 获取技师的基本信息、资质信息和实名信息
+     *
+     * @authenticated
+     *
+     * @response {
+     *   "data": {
+     *     "base_info": {
+     *       "nickname": "张三",
+     *       "avatar": "http://example.com/avatar.jpg",
+     *       "gender": "1",
+     *       "mobile": "138****8000",
+     *       "birthday": "1990-01-01",
+     *       "work_years": 5,
+     *       "intention_city": "北京",
+     *       "introduction": "专业按摩师,从业5年",
+     *       "state": 1,
+     *       "audit_remark": "审核通过"
+     *     },
+     *     "qualification": {
+     *       "qual_type": "高级按摩师",
+     *       "qual_no": "XZ2024001",
+     *       "qual_photo": "http://example.com/cert.jpg",
+     *       "valid_start": "2024-01-01",
+     *       "valid_end": "2029-01-01",
+     *       "state": 1,
+     *       "audit_remark": "审核通过"
+     *     },
+     *     "real_name": {
+     *       "real_name": "张三",
+     *       "id_card": "370602****1234",
+     *       "id_card_front_photo": "http://example.com/front.jpg",
+     *       "id_card_back_photo": "http://example.com/back.jpg",
+     *       "id_card_hand_photo": "http://example.com/hold.jpg",
+     *       "state": 1,
+     *       "audit_remark": "审核通过"
+     *     }
+     *   }
+     * }
+     */
+    public function info()
+    {
+        return $this->success($this->service->getCoachInfo(Auth::user()));
     }
 }

+ 58 - 0
app/Http/Requests/Coach/SubmitBaseInfoRequest.php

@@ -0,0 +1,58 @@
+<?php
+
+namespace App\Http\Requests\Coach;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class SubmitBaseInfoRequest extends FormRequest
+{
+    public function authorize()
+    {
+        return true;
+    }
+
+    public function rules()
+    {
+        return [
+            'nickname' => 'required|string|min:2|max:20',
+            'avatar' => 'required|url|max:255',
+            'gender' => 'required|in:1,2',
+            'mobile' => ['required', 'string', 'regex:/^1[3-9]\d{9}$/'],
+            'birthday' => [
+                'required',
+                'date',
+                'before:'.now()->subYears(18)->format('Y-m-d'),
+            ],
+            'work_years' => 'required|integer|min:0|max:99',
+            'intention_city' => 'required|string|max:50',
+            'introduction' => 'required|string|min:10|max:255',
+        ];
+    }
+
+    public function messages()
+    {
+        return [
+            'nickname.required' => '昵称不能为空',
+            'nickname.min' => '昵称不能少于2个字符',
+            'nickname.max' => '昵称不能超过20个字符',
+            'avatar.required' => '头像不能为空',
+            'avatar.url' => '头像必须是有效的URL地址',
+            'gender.required' => '性别不能为空',
+            'gender.in' => '性别只能是1(男)或2(女)',
+            'mobile.required' => '手机号不能为空',
+            'mobile.regex' => '手机号格式不正确',
+            'birthday.required' => '出生日期不能为空',
+            'birthday.date' => '出生日期格式不正确',
+            'birthday.before' => '年龄必须满18岁',
+            'work_years.required' => '工作年限不能为空',
+            'work_years.integer' => '工作年限必须是整数',
+            'work_years.min' => '工作年限不能小于0年',
+            'work_years.max' => '工作年限不能超过99年',
+            'intention_city.required' => '意向城市不能为空',
+            'intention_city.max' => '意向城市不能超过50个字符',
+            'introduction.required' => '个人简介不能为空',
+            'introduction.min' => '个人简介不能少于10个字符',
+            'introduction.max' => '个人简介不能超过255个字符',
+        ];
+    }
+}

+ 42 - 0
app/Http/Requests/Coach/SubmitQualificationRequest.php

@@ -0,0 +1,42 @@
+<?php
+
+namespace App\Http\Requests\Coach;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class SubmitQualificationRequest extends FormRequest
+{
+    public function authorize()
+    {
+        return true;
+    }
+
+    public function rules()
+    {
+        return [
+            'qual_type' => 'required|string|max:50',
+            'qual_no' => 'required|string|min:5|max:50',
+            'qual_photo' => 'required|url|max:255',
+            'valid_start' => 'required|date|date_format:Y-m-d',
+            'valid_end' => 'required|date|date_format:Y-m-d|after:valid_start',
+        ];
+    }
+
+    public function messages()
+    {
+        return [
+            'qual_type.required' => '资质类型不能为空',
+            'qual_type.max' => '资质类型不能超过50个字符',
+            'qual_no.required' => '资质证书编号不能为空',
+            'qual_no.min' => '资质证书编号不能少于5个字符',
+            'qual_no.max' => '资质证书编号不能超过50个字符',
+            'qual_photo.required' => '资质证书照片不能为空',
+            'qual_photo.url' => '资质证书照片必须是有效的URL地址',
+            'valid_start.required' => '有效期开始日期不能为空',
+            'valid_start.date' => '有效期开始日期格式不正确',
+            'valid_end.required' => '有效期结束日期不能为空',
+            'valid_end.date' => '有效期结束日期格式不正确',
+            'valid_end.after' => '有效期结束日期必须大于开始日期',
+        ];
+    }
+}

+ 47 - 0
app/Http/Requests/Coach/SubmitRealNameRequest.php

@@ -0,0 +1,47 @@
+<?php
+
+namespace App\Http\Requests\Coach;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class SubmitRealNameRequest extends FormRequest
+{
+    public function authorize()
+    {
+        return true;
+    }
+
+    public function rules()
+    {
+        return [
+            'real_name' => 'required|string|min:2|max:20',
+            'id_card' => [
+                'required',
+                'string',
+                'size:18',
+                'regex:/^[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dX]$/',
+            ],
+            'id_card_front_photo' => 'required|url|max:255',
+            'id_card_back_photo' => 'required|url|max:255',
+            'id_card_hand_photo' => 'required|url|max:255',
+        ];
+    }
+
+    public function messages()
+    {
+        return [
+            'real_name.required' => '姓名不能为空',
+            'real_name.min' => '姓名不能少于2个字符',
+            'real_name.max' => '姓名不能超过20个字符',
+            'id_card.required' => '身份证号不能为空',
+            'id_card.size' => '身份证号必须是18位',
+            'id_card.regex' => '身份证号格式不正确',
+            'id_card_front_photo.required' => '身份证正面照片不能为空',
+            'id_card_front_photo.url' => '身份证正面照片必须是有效的URL地址',
+            'id_card_back_photo.required' => '身份证反面照片不能为空',
+            'id_card_back_photo.url' => '身份证反面照片必须是有效的URL地址',
+            'id_card_hand_photo.required' => '手持身份证照片不能为空',
+            'id_card_hand_photo.url' => '手持身份证照片必须是有效的URL地址',
+        ];
+    }
+}

+ 2 - 2
app/Models/MemberUser.php

@@ -2,12 +2,12 @@
 
 namespace App\Models;
 
-use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Eloquent\Relations\HasMany;
 use Illuminate\Database\Eloquent\SoftDeletes;
+use Illuminate\Foundation\Auth\User as Authenticatable;
 use Laravel\Sanctum\HasApiTokens;
 
-class MemberUser extends Model
+class MemberUser extends Authenticatable
 {
     use HasApiTokens, SoftDeletes;
 

+ 238 - 60
app/Services/Coach/AccountService.php

@@ -2,86 +2,89 @@
 
 namespace App\Services\Coach;
 
-use App\Models\MemberUser;
+use App\Enums\TechnicianAuthStatus;
+use Illuminate\Support\Facades\Cache;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Log;
 
 class AccountService
 {
+    private const CACHE_KEY_PREFIX = 'coach_info_';
+
+    private const CACHE_TTL = 300; // 5分钟
+
     /**
      * 提交技师基本信息
      */
-    public function submitBaseInfo(int $userId, array $data)
+    public function submitBaseInfo($user, array $data)
     {
         DB::beginTransaction();
         try {
-            // 获取当前登录用户
-            $user = MemberUser::find($userId);
-            $coach = $user->coach;
+            $this->setTransactionConfig();
+
+            abort_if(! $user->coach, 404, '技师信息不存在');
+
+            // 检查是否有待审核的记录
+            $pendingRecord = $user->coach->infoRecords()
+                ->where('state', TechnicianAuthStatus::AUDITING->value)
+                ->exists();
+            abort_if($pendingRecord, 422, '已有待审核的基本信息记录');
 
             // 创建技师信息
-            $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'],
-                ]
-            );
+            $record = $user->coach->infoRecords()->create(array_merge($data, [
+                'state' => TechnicianAuthStatus::AUDITING->value,
+            ]));
+
+            // 清除技师信息缓存
+            $this->clearCoachCache($user->coach->id);
 
             DB::commit();
 
+            $this->logInfo('技师提交基本信息成功', $user, $data);
+
             return ['message' => '基本信息提交成功'];
 
         } catch (\Exception $e) {
             DB::rollBack();
-            Log::error('提交技师基本信息失败:', [
-                'message' => $e->getMessage(),
-                'data' => $data,
-            ]);
+            $this->logError('提交技师基本信息失败', $user, $data, $e);
             throw $e;
         }
     }
 
     /**
      * 提交技师资质信息
-     *
-     * @param  int  $userId  用户ID
-     * @param  array  $data  资质信息数据
-     *
-     * @throws \Exception 提交失败时抛出异常
      */
-    public function submitQualification(int $userId, array $data)
+    public function submitQualification($user, 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'],
-            ]);
+            $this->setTransactionConfig();
+
+            abort_if(! $user->coach, 404, '技师信息不存在');
+
+            // 检查是否有待审核的记录
+            $pendingRecord = $user->coach->qualRecords()
+                ->where('state', TechnicianAuthStatus::AUDITING->value)
+                ->exists();
+            abort_if($pendingRecord, 422, '已有待审核的资质信息记录');
+
+            // 创建资质信息
+            $record = $user->coach->qualRecords()->create(array_merge($data, [
+                'state' => TechnicianAuthStatus::AUDITING->value,
+            ]));
+
+            // 清除技师信息缓存
+            $this->clearCoachCache($user->coach->id);
 
             DB::commit();
 
+            $this->logInfo('技师提交资质信息成功', $user, $data);
+
             return ['message' => '资质信息提交成功'];
 
         } catch (\Exception $e) {
             DB::rollBack();
-            Log::error('提交技师资质信息失败:', [
-                'message' => $e->getMessage(),
-                'data' => $data,
-            ]);
+            $this->logError('提交技师资质信息失败', $user, $data, $e);
             throw $e;
         }
     }
@@ -89,34 +92,209 @@ class AccountService
     /**
      * 提交实名认证信息
      */
-    public function submitRealName(int $userId, array $data)
+    public function submitRealName($user, 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'],
-            ]);
+            $this->setTransactionConfig();
+
+            abort_if(! $user->coach, 404, '技师信息不存在');
+
+            // 检查是否有待审核的记录
+            $pendingRecord = $user->coach->realRecords()
+                ->where('state', TechnicianAuthStatus::AUDITING->value)
+                ->exists();
+            abort_if($pendingRecord, 422, '已有待审核的实名认证信息');
+
+            // 创建实名认证信息
+            $record = $user->coach->realRecords()->create(array_merge($data, [
+                'state' => TechnicianAuthStatus::AUDITING->value,
+            ]));
+
+            // 清除技师信息缓存
+            $this->clearCoachCache($user->coach->id);
 
             DB::commit();
 
+            $this->logInfo('技师提交实名认证信息成功', $user, $this->maskSensitiveData($data));
+
             return ['message' => '实名认证信息提交成功'];
 
         } catch (\Exception $e) {
             DB::rollBack();
-            Log::error('提交实名认证信息失败:', [
-                'message' => $e->getMessage(),
-                'data' => $data,
-            ]);
+            $this->logError('提交实名认证信息失败', $user, $this->maskSensitiveData($data), $e);
+            throw $e;
+        }
+    }
+
+    /**
+     * 获取技师信息
+     */
+    public function getCoachInfo($user)
+    {
+        try {
+            abort_if(! $user, 404, '用户不存在');
+            abort_if(! $user->coach, 404, '技师信息不存在');
+
+            return Cache::remember(
+                self::CACHE_KEY_PREFIX.$user->coach->id,
+                self::CACHE_TTL,
+                function () use ($user) {
+                    return $this->fetchCoachInfo($user->coach);
+                }
+            );
+        } catch (\Exception $e) {
+            $this->logError('获取技师信息失败', $user, [], $e);
             throw $e;
         }
     }
+
+    /**
+     * 设置事务配置
+     */
+    private function setTransactionConfig()
+    {
+        DB::statement('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED');
+        DB::statement('SET SESSION innodb_lock_wait_timeout=10');
+    }
+
+    /**
+     * 记录信息日志
+     */
+    private function logInfo(string $message, $user, array $data)
+    {
+        Log::info($message, [
+            'user_id' => $user->id,
+            'coach_id' => $user->coach->id,
+            'data' => $data,
+            'ip' => request()->ip(),
+            'timestamp' => now()->toDateTimeString(),
+        ]);
+    }
+
+    /**
+     * 记录错误日志
+     */
+    private function logError(string $message, $user, array $data, \Exception $e)
+    {
+        Log::error($message, [
+            'user_id' => $user->id,
+            'coach_id' => $user->coach->id ?? null,
+            'data' => $data,
+            'error' => $e->getMessage(),
+            'file' => $e->getFile(),
+            'line' => $e->getLine(),
+            'ip' => request()->ip(),
+            'timestamp' => now()->toDateTimeString(),
+        ]);
+    }
+
+    /**
+     * 获取技师详细信息
+     */
+    private function fetchCoachInfo($coach)
+    {
+        $baseInfo = $coach->infoRecords()->latest()->first();
+        $qualification = $coach->qualRecords()->latest()->first();
+        $realName = $coach->realRecords()->latest()->first();
+
+        return [
+            'base_info' => $baseInfo ? $this->formatBaseInfo($baseInfo) : null,
+            'qualification' => $qualification ? $this->formatQualification($qualification) : null,
+            'real_name' => $realName ? $this->formatRealName($realName) : null,
+        ];
+    }
+
+    /**
+     * 格式化基本信息
+     */
+    private function formatBaseInfo($info)
+    {
+        return [
+            'nickname' => $info->nickname,
+            'avatar' => $info->avatar,
+            'gender' => $info->gender,
+            'mobile' => $this->maskMobile($info->mobile),
+            'birthday' => $info->birthday,
+            'work_years' => $info->work_years,
+            'intention_city' => $info->intention_city,
+            'introduction' => $info->introduction,
+            'state' => $info->state,
+            'state_text' => TechnicianAuthStatus::fromValue($info->state)->label(),
+            'audit_remark' => $info->audit_remark,
+        ];
+    }
+
+    /**
+     * 格式化资质信息
+     */
+    private function formatQualification($qual)
+    {
+        return [
+            'qual_type' => $qual->qual_type,
+            'qual_no' => $qual->qual_no,
+            'qual_photo' => $qual->qual_photo,
+            'valid_start' => $qual->valid_start,
+            'valid_end' => $qual->valid_end,
+            'state' => $qual->state,
+            'state_text' => TechnicianAuthStatus::fromValue($qual->state)->label(),
+            'audit_remark' => $qual->audit_remark,
+        ];
+    }
+
+    /**
+     * 格式化实名信息
+     */
+    private function formatRealName($real)
+    {
+        return [
+            'real_name' => $real->real_name,
+            'id_card' => $this->maskIdCard($real->id_card),
+            'id_card_front_photo' => $real->id_card_front_photo,
+            'id_card_back_photo' => $real->id_card_back_photo,
+            'id_card_hand_photo' => $real->id_card_hand_photo,
+            'state' => $real->state,
+            'state_text' => TechnicianAuthStatus::fromValue($real->state)->label(),
+            'audit_remark' => $real->audit_remark,
+        ];
+    }
+
+    /**
+     * 手机号脱敏
+     */
+    private function maskMobile($mobile)
+    {
+        return substr_replace($mobile, '****', 3, 4);
+    }
+
+    /**
+     * 身份证号脱敏
+     */
+    private function maskIdCard($idCard)
+    {
+        return substr_replace($idCard, '****', 6, 8);
+    }
+
+    /**
+     * 敏感数据脱敏
+     */
+    private function maskSensitiveData(array $data)
+    {
+        if (isset($data['id_card'])) {
+            $data['id_card'] = $this->maskIdCard($data['id_card']);
+        }
+        if (isset($data['mobile'])) {
+            $data['mobile'] = $this->maskMobile($data['mobile']);
+        }
+
+        return $data;
+    }
+
+    /**
+     * 清除技师信息缓存
+     */
+    private function clearCoachCache($coachId)
+    {
+        Cache::forget(self::CACHE_KEY_PREFIX.$coachId);
+    }
 }

+ 15 - 0
app/Traits/ResponseTrait.php

@@ -0,0 +1,15 @@
+<?php
+
+namespace App\Traits;
+
+trait ResponseTrait
+{
+    protected function success($data = [], $message = 'success')
+    {
+        return [
+            'code' => 0,
+            'message' => $message,
+            'data' => $data,
+        ];
+    }
+}

+ 6 - 3
routes/api.php

@@ -124,12 +124,15 @@ Route::prefix('client')->group(function () {
 });
 
 // 技师端路由组
-Route::prefix('coach')->middleware(['auth:sanctum'])->group(function () {
+Route::prefix('coach')->middleware(['auth:sanctum', 'throttle:6,1'])->group(function () {
     // 账户相关路由组
     Route::prefix('account')->group(function () {
-        Route::post('base-info', [App\Http\Controllers\Coach\AccountController::class, 'submitBaseInfo']);
+        Route::post('base-info', [App\Http\Controllers\Coach\AccountController::class, 'submitBaseInfo'])
+            ->name('coach.account.base-info');
         Route::post('qualification', [App\Http\Controllers\Coach\AccountController::class, 'submitQualification']);
-        Route::post('real-name', [App\Http\Controllers\Coach\AccountController::class, 'submitRealName']);
+        Route::post('real-name', [App\Http\Controllers\Coach\AccountController::class, 'submitRealName'])
+            ->middleware('throttle:3,1');  // 实名认证限制更严格
+        Route::get('info', [App\Http\Controllers\Coach\AccountController::class, 'info']);
     });
 
     // 订单相关路由