CoachController.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. <?php
  2. namespace App\Http\Controllers\Client;
  3. use Illuminate\Http\Request;
  4. use App\Http\Controllers\Controller;
  5. use Illuminate\Support\Facades\Auth;
  6. use App\Services\Client\CoachService;
  7. use App\Http\Requests\Client\Coach\ListNearbyCoachRequest;
  8. /**
  9. * @group 用户端
  10. *
  11. * 技师相关的API接口
  12. */
  13. class CoachController extends Controller
  14. {
  15. protected CoachService $service;
  16. public function __construct(CoachService $service)
  17. {
  18. $this->service = $service;
  19. }
  20. /**
  21. * [技师]获取附近技师列表
  22. *
  23. * @description 根据用户当前位置获取指定范围内的技师列表,支持分页和距离筛选
  24. *
  25. * 业务流程:
  26. * 1. 验证用户位置和分页参数
  27. * 2. 获取系统设置的最大搜索半径
  28. * 3. 查询指定范围内的技师
  29. * 4. 根据技师个人设置的接单距离筛选
  30. * 5. 返回分页后的技师列表
  31. *
  32. * 筛选规则:
  33. * - 技师必须通过基本信息认证
  34. * - 技师必须通过实名认证
  35. * - 技师必须通过资质认证
  36. * - 如果技师设置了接单距离,���户距离必须在范围内
  37. * - 未设置接单距离的技师,只要在系统搜索半径内就显示
  38. *
  39. * 排序规则:
  40. * - 按照技师到用户的实际距离升序排序
  41. * - 未获取到距离的技师排在最后
  42. *
  43. * @authenticated 需要用户登录认证
  44. *
  45. * @queryParam page int 当前页码,默认1. Example: 1
  46. * @queryParam per_page int 每页数量,默认15. Example: 15
  47. * @queryParam latitude float required 用户当前纬度坐标(-90到90). Example: 39.9042
  48. * @queryParam longitude float required 用户当前经度坐标(-180到180). Example: 116.4074
  49. *
  50. * @response scenario=success {
  51. * "code": 200,
  52. * "message": "success",
  53. * "data": {
  54. * "items": [
  55. * {
  56. * "id": 6,
  57. * "user_id": 12,
  58. * "info_record_id": 53,
  59. * "real_auth_record_id": 1,
  60. * "qualification_record_id": 1,
  61. * "shop_id": null,
  62. * "level": 1,
  63. * "virtual_order": 0,
  64. * "score": "5.00",
  65. * "work_status": 2,
  66. * "virtual_status": 1,
  67. * "state": 2,
  68. * "created_at": "2024-11-19 18:25:04",
  69. * "updated_at": "2024-12-13 08:01:02",
  70. * "deleted_at": null,
  71. * "is_vip": 1,
  72. * "vip_time": null,
  73. * "invite_code": null,
  74. * "qr_code": null,
  75. * "formal_photo": null,
  76. * "formal_photo_remark": null,
  77. * "formal_photo_updated_at": null,
  78. * "formal_photo_admin_id": null,
  79. * "newcomer_sort": 0,
  80. * "newcomer_sort_updated_at": null,
  81. * "newcomer_sort_admin_id": null,
  82. * "distance": 0,
  83. * "state_text": "正常服务",
  84. * "info": {
  85. * "id": 53,
  86. * "nickname": "张三1",
  87. * "avatar": null,
  88. * "gender": "1",
  89. * "state_text": ""
  90. * },
  91. * "distance": 2.5 // 用户到技师的距离(公里)
  92. * }
  93. * ],
  94. * "total": 1 // 符合条件的技师总数
  95. * }
  96. * }
  97. *
  98. * @response status=401 scenario="未登录" {
  99. * "message": "用户未登录"
  100. * }
  101. * @response status=400 scenario="状态异常" {
  102. * "message": "用户状态异常"
  103. * }
  104. * @response status=422 scenario="参数错误" {
  105. * "message": "验证错误",
  106. * "errors": {
  107. * "latitude": ["纬度不能为空"],
  108. * "longitude": ["经度不能为空"]
  109. * }
  110. * }
  111. * @response status=500 scenario="系统错误" {
  112. * "message": "Redis服务不可用"
  113. * }
  114. */
  115. public function list(ListNearbyCoachRequest $request)
  116. {
  117. // 获取验证后的数据
  118. $validated = $request->validated();
  119. // 调用服务层获取技师列表
  120. return $this->success($this->service->getNearCoachList(
  121. Auth::user()->id, // 当前登录用户ID
  122. $validated['latitude'], // 用户当前纬度
  123. $validated['longitude'] // 用户当前经度
  124. ));
  125. }
  126. /**
  127. * [技师]获取技师详情
  128. *
  129. * 根据ID获取技师的详细信息
  130. *
  131. * @authenticated
  132. *
  133. * @urlParam id int required 技师ID. Example: 6
  134. *
  135. * @queryParam latitude float 纬度. Example: 34.0522
  136. * @queryParam longitude float 经度. Example: -118.2437
  137. *
  138. * @response {
  139. * "code": 200,
  140. * "message": "获取成功",
  141. * "data": {
  142. * "id": 1,
  143. * "name": "技师A",
  144. * "latitude": 34.0522,
  145. * "longitude": -118.2437,
  146. * "details": "详细信息"
  147. * }
  148. * }
  149. */
  150. public function detail(Request $request, $id)
  151. {
  152. $latitude = $request->input('latitude');
  153. $longitude = $request->input('longitude');
  154. return $this->success($this->service->getCoachDetail($id, $latitude, $longitude));
  155. }
  156. /**
  157. * [技师]获取可预约时间段
  158. *
  159. * @description 获取指定技师的可预约时间段列表,包含日期、星期、时间段等信息
  160. *
  161. * @queryParam coach_id int required 技师ID Example: 6
  162. * @queryParam date string 日期(格式:Y-m-d) Example: 2024-03-22
  163. *
  164. * @response {
  165. * "data": {
  166. * "date": "2024-03-22",
  167. * "day_of_week": "星期五",
  168. * "is_today": false,
  169. * "time_slots": [
  170. * {
  171. * "start_time": "09:00",
  172. * "end_time": "09:30",
  173. * "is_available": true,
  174. * "duration": 30
  175. * }
  176. * ],
  177. * "total_slots": 1,
  178. * "updated_at": "2024-03-22 10:00:00"
  179. * }
  180. * }
  181. * @response 404 {
  182. * "message": "技师不存在"
  183. * }
  184. * @response 400 {
  185. * "message": "技师状态异常"
  186. * }
  187. * @response 400 {
  188. * "message": "不能查询过去的日期"
  189. * }
  190. * @response 400 {
  191. * "message": "只能查询未来30天内的时间段"
  192. * }
  193. */
  194. public function getSchedule(Request $request)
  195. {
  196. // 验证参数
  197. $validated = $request->validate([
  198. 'coach_id' => 'required|integer|exists:coach_users,id',
  199. 'date' => 'nullable|date_format:Y-m-d',
  200. ]);
  201. // 调用service获取技师可预约时间段
  202. return $this->success($this->service->getSchedule($validated['coach_id'], $validated['date'] ?? null));
  203. }
  204. }