123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- <?php
- namespace App\Http\Controllers\Client;
- use Illuminate\Http\Request;
- use App\Http\Controllers\Controller;
- use Illuminate\Support\Facades\Auth;
- use App\Services\Client\CoachService;
- use App\Http\Requests\Client\Coach\ListNearbyCoachRequest;
- /**
- * @group 用户端
- *
- * 技师相关的API接口
- */
- class CoachController extends Controller
- {
- protected CoachService $service;
- public function __construct(CoachService $service)
- {
- $this->service = $service;
- }
- /**
- * [技师]获取附近技师列表
- *
- * @description 根据用户当前位置获取指定范围内的技师列表,支持分页和距离筛选
- *
- * 业务流程:
- * 1. 验证用户位置和分页参数
- * 2. 获取系统设置的最大搜索半径
- * 3. 查询指定范围内的技师
- * 4. 根据技师个人设置的接单距离筛选
- * 5. 返回分页后的技师列表
- *
- * 筛选规则:
- * - 技师必须通过基本信息认证
- * - 技师必须通过实名认证
- * - 技师必须通过资质认证
- * - 如果技师设置了接单距离,户距离必须在范围内
- * - 未设置接单距离的技师,只要在系统搜索半径内就显示
- *
- * 排序规则:
- * - 按照技师到用户的实际距离升序排序
- * - 未获取到距离的技师排在最后
- *
- * @authenticated 需要用户登录认证
- *
- * @queryParam page int 当前页码,默认1. Example: 1
- * @queryParam per_page int 每页数量,默认15. Example: 15
- * @queryParam latitude float required 用户当前纬度坐标(-90到90). Example: 39.9042
- * @queryParam longitude float required 用户当前经度坐标(-180到180). Example: 116.4074
- *
- * @response scenario=success {
- * "code": 200,
- * "message": "success",
- * "data": {
- * "items": [
- * {
- * "id": 6,
- * "user_id": 12,
- * "info_record_id": 53,
- * "real_auth_record_id": 1,
- * "qualification_record_id": 1,
- * "shop_id": null,
- * "level": 1,
- * "virtual_order": 0,
- * "score": "5.00",
- * "work_status": 2,
- * "virtual_status": 1,
- * "state": 2,
- * "created_at": "2024-11-19 18:25:04",
- * "updated_at": "2024-12-13 08:01:02",
- * "deleted_at": null,
- * "is_vip": 1,
- * "vip_time": null,
- * "invite_code": null,
- * "qr_code": null,
- * "formal_photo": null,
- * "formal_photo_remark": null,
- * "formal_photo_updated_at": null,
- * "formal_photo_admin_id": null,
- * "newcomer_sort": 0,
- * "newcomer_sort_updated_at": null,
- * "newcomer_sort_admin_id": null,
- * "distance": 0,
- * "state_text": "正常服务",
- * "info": {
- * "id": 53,
- * "nickname": "张三1",
- * "avatar": null,
- * "gender": "1",
- * "state_text": ""
- * },
- * "distance": 2.5 // 用户到技师的距离(公里)
- * }
- * ],
- * "total": 1 // 符合条件的技师总数
- * }
- * }
- *
- * @response status=401 scenario="未登录" {
- * "message": "用户未登录"
- * }
- * @response status=400 scenario="状态异常" {
- * "message": "用户状态异常"
- * }
- * @response status=422 scenario="参数错误" {
- * "message": "验证错误",
- * "errors": {
- * "latitude": ["纬度不能为空"],
- * "longitude": ["经度不能为空"]
- * }
- * }
- * @response status=500 scenario="系统错误" {
- * "message": "Redis服务不可用"
- * }
- */
- public function list(ListNearbyCoachRequest $request)
- {
- // 获取验证后的数据
- $validated = $request->validated();
- // 调用服务层获取技师列表
- return $this->success($this->service->getNearCoachList(
- Auth::user()->id, // 当前登录用户ID
- $validated['latitude'], // 用户当前纬度
- $validated['longitude'] // 用户当前经度
- ));
- }
- /**
- * [技师]获取技师详情
- *
- * @description 获取技师的详细信息,包括基本资料、认证状态、位置信息和距离计算
- *
- * 业务流程:
- * 1. 验证用户登录状态和权限
- * 2. 验证技师ID的有效性
- * 3. 获取技师基本信息和认证状态
- * 4. 如果提供了用户坐标,计算与技师的距离
- * 5. 返回完整的技师信息
- *
- * 数据验证:
- * - 技师必须存在且状态正常
- * - 技师必须通过各项认证
- * - 坐标格式必须正确(如果提供)
- *
- * @authenticated 需要用户登录认证
- *
- * @urlParam id required int 技师ID. Example: 6
- * @queryParam latitude float 用户当前纬度坐标(-90到90). Example: 39.9042
- * @queryParam longitude float 用户当前经度坐标(-180到180). Example: 116.4074
- *
- * @response scenario=success {
- * "code": 200,
- * "message": "success",
- * "data": {
- * "id": 6,
- * "user_id": 12,
- * "info_record_id": 53,
- * "real_auth_record_id": 1,
- * "qualification_record_id": 1,
- * "shop_id": null,
- * "level": 1,
- * "virtual_order": 0,
- * "score": "5.00",
- * "work_status": 2,
- * "virtual_status": 1,
- * "state": 2,
- * "created_at": "2024-11-19 18:25:04",
- * "updated_at": "2024-12-13 08:01:02",
- * "is_vip": 1,
- * "distance": 2.5, // 用户到技师的距离(公里)
- * "state_text": "正常服务",
- * "info": {
- * "id": 53,
- * "nickname": "张三1",
- * "avatar": null,
- * "gender": "1",
- * "state_text": ""
- * }
- * }
- * }
- *
- * @response status=401 scenario="未登录" {
- * "message": "用户未登录"
- * }
- * @response status=400 scenario="状态异常" {
- * "message": "用户状态异常"
- * }
- * @response status=404 scenario="不存在" {
- * "message": "技师不存在"
- * }
- * @response status=422 scenario="参数错误" {
- * "message": "无效的经纬度坐标"
- * }
- * @response status=500 scenario="系统错误" {
- * "message": "Redis服务不可用"
- * }
- */
- public function detail(Request $request, $id)
- {
- // 获取用户当前位置坐标
- $latitude = $request->input('latitude');
- $longitude = $request->input('longitude');
- // 调用服务层获取技师详情
- return $this->success($this->service->getCoachDetail($id, $latitude, $longitude));
- }
- /**
- * [技师]获取可预约时间段
- *
- * @description 获取指定技师的可预约时间段列表,包含日期、星期、时间段等信息
- *
- * @queryParam coach_id int required 技师ID Example: 6
- * @queryParam date string 日期(格式:Y-m-d) Example: 2024-03-22
- *
- * @response {
- * "data": {
- * "date": "2024-03-22",
- * "day_of_week": "星期五",
- * "is_today": false,
- * "time_slots": [
- * {
- * "start_time": "09:00",
- * "end_time": "09:30",
- * "is_available": true,
- * "duration": 30
- * }
- * ],
- * "total_slots": 1,
- * "updated_at": "2024-03-22 10:00:00"
- * }
- * }
- * @response 404 {
- * "message": "技师不存在"
- * }
- * @response 400 {
- * "message": "技师状态异常"
- * }
- * @response 400 {
- * "message": "不能查询过去的日期"
- * }
- * @response 400 {
- * "message": "只能查询未来30天内的时间段"
- * }
- */
- public function getSchedule(Request $request)
- {
- // 验证参数
- $validated = $request->validate([
- 'coach_id' => 'required|integer|exists:coach_users,id',
- 'date' => 'nullable|date_format:Y-m-d',
- ]);
- // 调用service获取技师可预约时间段
- return $this->success($this->service->getSchedule($validated['coach_id'], $validated['date'] ?? null));
- }
- }
|