AccountController.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. <?php
  2. namespace App\Http\Controllers\Coach;
  3. use Illuminate\Http\Request;
  4. use App\Traits\ResponseTrait;
  5. use App\Traits\LocationDataTrait;
  6. use Illuminate\Support\Facades\Log;
  7. use App\Http\Controllers\Controller;
  8. use Illuminate\Support\Facades\Auth;
  9. use App\Enums\TechnicianLocationType;
  10. use App\Services\Coach\AccountService;
  11. use App\Http\Requests\Coach\SetLocationRequest;
  12. use App\Http\Requests\Coach\SubmitBaseInfoRequest;
  13. use App\Http\Requests\Coach\SubmitRealNameRequest;
  14. use App\Http\Requests\Coach\SubmitQualificationRequest;
  15. /**
  16. * @group 技师端
  17. *
  18. * 技师账户相关的API接口
  19. */
  20. class AccountController extends Controller
  21. {
  22. use ResponseTrait;
  23. use LocationDataTrait;
  24. protected AccountService $service;
  25. public function __construct(AccountService $service)
  26. {
  27. $this->service = $service;
  28. }
  29. /**
  30. * [账户]提交基本信息
  31. *
  32. * @description 提交技师的基本个人信息
  33. *
  34. * @authenticated
  35. *
  36. * @bodyParam nickname string nullable 昵称(2-20个字符) Example: 张三
  37. * @bodyParam avatar string nullable 头像图片 Example: base64或其他格式的图片数据
  38. * @bodyParam gender string required 性别(1:男 2:女) Example: 1
  39. * @bodyParam mobile string required 手机号 Example: 13800138000
  40. * @bodyParam birthday date nullable 出生日期(年龄需满18岁) Example: 1990-01-01
  41. * @bodyParam work_years integer nullable 工作年限(0-99) Example: 5
  42. * @bodyParam intention_city string nullable 意向城市 Example: 北京
  43. * @bodyParam introduction string nullable 个人简介(10-255个字符) Example: 专业按摩师,从业5年
  44. *
  45. * @response {
  46. * "message": "基本信息提交成功"
  47. * }
  48. */
  49. public function submitBaseInfo(SubmitBaseInfoRequest $request)
  50. {
  51. $data = $request->validated();
  52. return $this->success($this->service->submitBaseInfo(Auth::user(), $data));
  53. }
  54. /**
  55. * [账户]提交资质信息
  56. *
  57. * @description 提交技师的资质认证信息,包括资质照片、营业执照和健康证
  58. *
  59. * @authenticated
  60. *
  61. * @bodyParam qual_type int required 资质类型(1:初级按摩师 2:中级按摩师 3:高级按摩师) Example: 1
  62. * @bodyParam qual_photo string required 资质证书照片 Example: base64或其他格式的图片数据
  63. * @bodyParam business_license string required 营业执照照片 Example: base64或其他格式的图片数据
  64. * @bodyParam health_cert string required 健康证照片 Example: base64或其他格式的图片数据
  65. *
  66. * @response {
  67. * "message": "资质信息提交成功"
  68. * }
  69. */
  70. public function submitQualification(SubmitQualificationRequest $request)
  71. {
  72. $data = $request->validated();
  73. return $this->success($this->service->submitQualification(Auth::user(), $data));
  74. }
  75. /**
  76. * [账户]提交实名认证
  77. *
  78. * @description 提交技师的实名认证信息
  79. *
  80. * @authenticated
  81. *
  82. * @bodyParam real_name string nullable 姓名(2-20个字符) Example: 张三
  83. * @bodyParam id_card string nullable 身份证号(18位) Example: 370602199001011234
  84. * @bodyParam id_card_front_photo string required 身份证正面照片 Example: base64或其他格式的图片数据
  85. * @bodyParam id_card_back_photo string required 身份证反面照片 Example: base64或其他格式的图片数据
  86. * @bodyParam id_card_hand_photo string required 手持身份证照片 Example: base64或其他格式的图片数据
  87. *
  88. * @response {
  89. * "message": "实名认证信息提交成功"
  90. * }
  91. */
  92. public function submitRealName(SubmitRealNameRequest $request)
  93. {
  94. $data = $request->validated();
  95. return $this->success($this->service->submitRealName(Auth::user(), $data));
  96. }
  97. /**
  98. * [账户]获取技师信息
  99. *
  100. * @description 获取技师的基本信息、资质信息和实名认证信息
  101. *
  102. * @authenticated
  103. *
  104. * @response {
  105. * "data": {
  106. * "base_info": {
  107. * "nickname": "张三",
  108. * "avatar": "base64或其他格式的图片数据",
  109. * "gender": "1",
  110. * "mobile": "138****8000",
  111. * "birthday": "1990-01-01",
  112. * "work_years": 5,
  113. * "intention_city": "北京",
  114. * "introduction": "专业按摩师,从业5年",
  115. * "state": 1,
  116. * "state_text": "已通过",
  117. * "audit_remark": "审核通过"
  118. * },
  119. * "qualification": {
  120. * "qual_type": "高级按摩师",
  121. * "qual_photo": "base64或其他格式的图片数据",
  122. * "business_license": "base64或其他格式的图片数据",
  123. * "health_cert": "base64或其他格式的图片数据",
  124. * "state": 1,
  125. * "state_text": "已通过",
  126. * "audit_remark": "审核通过"
  127. * },
  128. * "real_name": {
  129. * "real_name": "张三",
  130. * "id_card": "370602****1234",
  131. * "id_card_front_photo": "base64或其他格式的图片数据",
  132. * "id_card_back_photo": "base64或其他格式的图片数据",
  133. * "id_card_hand_photo": "base64或其他格式的图片数据",
  134. * "state": 1,
  135. * "state_text": "已通过",
  136. * "audit_remark": "审核通过"
  137. * }
  138. * }
  139. * }
  140. * @response 404 {
  141. * "message": "用户不存在"
  142. * }
  143. * @response 404 {
  144. * "message": "技师信息不存在"
  145. * }
  146. */
  147. public function info()
  148. {
  149. return $this->success($this->service->getCoachInfo(Auth::user()));
  150. }
  151. /**
  152. * [账户]设置技师位置信息
  153. *
  154. * @description 设置技师的当前位置或常用位置
  155. *
  156. * @authenticated
  157. *
  158. * @bodyParam latitude float required 纬度 Example: 39.9042
  159. * @bodyParam longitude float required 经度 Example: 116.4074
  160. * @bodyParam type int nullable 位置类型(1:当前位置 2:常用位置) Example: 2
  161. * @bodyParam province string nullable 省份 Example: 北京市
  162. * @bodyParam city string nullable 城市 Example: 北京市
  163. * @bodyParam district string nullable 区县 Example: 朝阳区
  164. * @bodyParam address string nullable 详细地址 Example: 建国路93号万达广场
  165. * @bodyParam adcode string nullable 行政区划代码 Example: 110105
  166. *
  167. * @response {
  168. * "message": "位置信息设置成功"
  169. * }
  170. */
  171. public function setLocation(SetLocationRequest $request)
  172. {
  173. // 获取验证后的数据
  174. $validated = $request->validated();
  175. // 确保用户和技师存在
  176. $user = Auth::user();
  177. abort_if(!$user->coach, 404, '技师信息不存在');
  178. // 提取位置信息
  179. $locationInfo = $this->extractLocationInfo($validated);
  180. // 传递技师ID给服务层
  181. $this->service->setLocation(
  182. $user->coach->id,
  183. $validated['latitude'],
  184. $validated['longitude'],
  185. $validated['type'] ?? TechnicianLocationType::COMMON->value,
  186. $locationInfo
  187. );
  188. return $this->success(['message' => '位置信息设置成功']);
  189. }
  190. /**
  191. * [账户]获取技师位置信息
  192. *
  193. * @description 取技师的当前位置和常用位置信息
  194. *
  195. * @authenticated
  196. *
  197. * @response {
  198. * "data": {
  199. * "current": {
  200. * "address": "北京市朝阳区建国路93号万达广场"
  201. * },
  202. * "common": {
  203. * "address": "北京市海淀区中关村大街1号"
  204. * }
  205. * }
  206. *idid
  207. */
  208. public function getLocation()
  209. {
  210. $result = $this->service->getLocation(Auth::user()->id);
  211. return $this->success($result);
  212. }
  213. /**
  214. * [账户]设置排班时间
  215. *
  216. * @description 设置技师每天通用的排班时间段
  217. *
  218. * @authenticated
  219. *
  220. * @bodyParam time_ranges array required 时间段数组
  221. * @bodyParam time_ranges[].start_time string required 开始时间(HH:mm格式) Example: "09:00"
  222. * @bodyParam time_ranges[].end_time string required 结束时间(HH:mm格式) Example: "12:00"
  223. *
  224. * @response {
  225. * "status": true,
  226. * "message": "排班设置成功",
  227. * "data": {
  228. * "coach_id": 1,
  229. * "time_ranges": [
  230. * {
  231. * "start_time": "09:00",
  232. * "end_time": "12:00"
  233. * },
  234. * {
  235. * "start_time": "14:00",
  236. * "end_time": "18:00"
  237. * }
  238. * ]
  239. * }
  240. * }
  241. * @response 400 {
  242. * "message": "时间段格式错误"
  243. * }
  244. * @response 400 {
  245. * "message": "时间格式错误,应为HH:mm格式"
  246. * }
  247. * @response 400 {
  248. * "message": "结束时间必须大于开始时间"
  249. * }
  250. * @response 400 {
  251. * "message": "时间段之间不能重叠"
  252. * }
  253. */
  254. public function setSchedule(Request $request)
  255. {
  256. $validated = $request->validate([
  257. 'time_ranges' => 'required|array|min:1',
  258. 'time_ranges.*.start_time' => [
  259. 'required',
  260. 'string',
  261. 'regex:/^([01][0-9]|2[0-3]):[0-5][0-9]$/',
  262. ],
  263. 'time_ranges.*.end_time' => [
  264. 'required',
  265. 'string',
  266. 'regex:/^([01][0-9]|2[0-3]):[0-5][0-9]$/',
  267. ],
  268. ], [
  269. 'time_ranges.required' => '必须设置时间段',
  270. 'time_ranges.array' => '时间段必须是数组格式',
  271. 'time_ranges.min' => '至少设置一个时间段',
  272. 'time_ranges.*.start_time.required' => '开始时间不能为空',
  273. 'time_ranges.*.start_time.regex' => '开始时间格式错误,应为HH:mm格式',
  274. 'time_ranges.*.end_time.required' => '结束时间不能为空',
  275. 'time_ranges.*.end_time.regex' => '结束时间格式错误,应为HH:mm格式',
  276. ]);
  277. return $this->success(
  278. $this->service->setSchedule(Auth::user()->id, $validated['time_ranges'])
  279. );
  280. }
  281. /**
  282. * [账户]更改技师工作状态
  283. *
  284. * @description 更改技师的工作状态(休息中/工作中),工作状态会自动判断为空闲或忙碌
  285. *
  286. * @authenticated
  287. *
  288. * @bodyParam status int required 状态(1:休息中 2:工作中) Example: 2
  289. *
  290. * @response {
  291. * "status": true,
  292. * "message": "状态更新成功",
  293. * "data": {
  294. * "work_status": 2,
  295. * "work_status_text": "空闲中",
  296. * "updated_at": "2024-03-20 10:00:00"
  297. * }
  298. * }
  299. * @response 400 {
  300. * "message": "无效的状态值"
  301. * }
  302. * @response 422 {
  303. * "message": "当前状态不能更改为休息状态"
  304. * }
  305. */
  306. public function updateWorkStatus(Request $request)
  307. {
  308. $validated = $request->validate([
  309. 'status' => 'required|integer|in:1,2',
  310. ], [
  311. 'status.required' => '状态不能为空',
  312. 'status.integer' => '状态必须是整数',
  313. 'status.in' => '无效的状态值',
  314. ]);
  315. return $this->success(
  316. $this->service->updateWorkStatus(Auth::user()->id, $validated['status'])
  317. );
  318. }
  319. /**
  320. * [账户]获取技师工作状态
  321. *
  322. * @description 获取技师当前工作状态
  323. *
  324. * @authenticated
  325. *
  326. * @response {
  327. * "data": {
  328. * "work_status": 2,
  329. * "work_status_text": "空闲中",
  330. * "updated_at": "2024-03-22 10:00:00"
  331. * }
  332. * }
  333. * @response 404 {
  334. * "message": "技师不存在"
  335. * }
  336. */
  337. public function getWorkStatus()
  338. {
  339. return $this->success(
  340. $this->service->getWorkStatus(Auth::user()->coach->id)
  341. );
  342. }
  343. /**
  344. * [账户]获取技师排班信息
  345. *
  346. * @return \Illuminate\Http\JsonResponse
  347. *
  348. * @description 技师获取自己的排班时间段信息
  349. *
  350. * @response {
  351. * "status": true,
  352. * "message": "获取成功",
  353. * "data": {
  354. * "time_ranges": [
  355. * {
  356. * "start_time": "09:00",
  357. * "end_time": "12:00"
  358. * },
  359. * {
  360. * "start_time": "14:00",
  361. * "end_time": "18:00"
  362. * }
  363. * ],
  364. * "updated_at": "2024-03-20 10:00:00"
  365. * }
  366. * }
  367. */
  368. public function getSchedule()
  369. {
  370. $schedule = $this->service->getSchedule(Auth::id());
  371. return $this->success($schedule);
  372. }
  373. }