OrderController.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. <?php
  2. namespace App\Admin\Controllers;
  3. use App\Services\OrderService;
  4. use Illuminate\Http\Request;
  5. use Slowlyo\OwlAdmin\Controllers\AdminController;
  6. /**
  7. * @group 后台
  8. * 订单管理
  9. *
  10. * @property OrderService $service
  11. */
  12. class OrderController extends AdminController
  13. {
  14. protected string $serviceName = OrderService::class;
  15. public function list()
  16. {
  17. $crud = $this->baseCRUD()
  18. ->filterTogglable(false)
  19. ->headerToolbar([
  20. $this->createButton('dialog'),
  21. ...$this->baseHeaderToolBar(),
  22. ])
  23. ->columns([
  24. amis()->TableColumn('id', 'ID')->sortable(),
  25. amis()->TableColumn('user_id', '用户编号'),
  26. amis()->TableColumn('coach_id', '技师编号'),
  27. amis()->TableColumn('service_id', '项目编号'),
  28. amis()->TableColumn('channel_id', '渠道编号'),
  29. amis()->TableColumn('shop_id', '店铺编号'),
  30. amis()->TableColumn('customer_service_id', '跟单客服编号'),
  31. amis()->TableColumn('order_type', '订单类型'),
  32. amis()->TableColumn('order_source', '订单来源'),
  33. amis()->TableColumn('total_amount', '订单金额'),
  34. amis()->TableColumn('service_amount', '项目金额'),
  35. amis()->TableColumn('traffic_amount', '路程金额'),
  36. amis()->TableColumn('service_snapshot', '项目快照'),
  37. amis()->TableColumn('service_time', '服务时间'),
  38. amis()->TableColumn('distance', '目的地距离(米)')->sortable(),
  39. amis()->TableColumn('latitude', '目的地纬度'),
  40. amis()->TableColumn('longitude', '目的地经度'),
  41. amis()->TableColumn('location', '目的地定位地址'),
  42. amis()->TableColumn('address', '目的地详细地址'),
  43. amis()->TableColumn('area_code', '目的地行政区划代码'),
  44. amis()->TableColumn('remark', '订单备注'),
  45. amis()->TableColumn('state', '订单状态'),
  46. amis()->TableColumn('created_at', admin_trans('admin.created_at'))->type('datetime')->sortable(),
  47. amis()->TableColumn('updated_at', admin_trans('admin.updated_at'))->type('datetime')->sortable(),
  48. $this->rowActions('dialog'),
  49. ]);
  50. return $this->baseList($crud);
  51. }
  52. public function form($isEdit = false)
  53. {
  54. return $this->baseForm()->body([
  55. amis()->TextControl('user_id', '用户编号'),
  56. amis()->TextControl('coach_id', '技师编号'),
  57. amis()->TextControl('service_id', '项目编号'),
  58. amis()->TextControl('channel_id', '渠道编号'),
  59. amis()->TextControl('shop_id', '店铺编号'),
  60. amis()->TextControl('customer_service_id', '跟单客服编号'),
  61. amis()->TextControl('order_type', '订单类型'),
  62. amis()->TextControl('order_source', '订单来源'),
  63. amis()->TextControl('total_amount', '订单金额'),
  64. amis()->TextControl('service_amount', '项目金额'),
  65. amis()->TextControl('traffic_amount', '路程金额'),
  66. amis()->TextControl('service_snapshot', '项目快照'),
  67. amis()->TextControl('service_time', '服务时间'),
  68. amis()->TextControl('distance', '目的地距离(米)'),
  69. amis()->TextControl('latitude', '目的地纬度'),
  70. amis()->TextControl('longitude', '目的地经度'),
  71. amis()->TextControl('location', '目的地定位地址'),
  72. amis()->TextControl('address', '目的地详细地址'),
  73. amis()->TextControl('area_code', '目的地行政区划代码'),
  74. amis()->TextControl('remark', '订单备注'),
  75. amis()->TextControl('state', '订单状态'),
  76. ]);
  77. }
  78. public function detail()
  79. {
  80. return $this->baseDetail()->body([
  81. amis()->TextControl('id', 'ID')->static(),
  82. amis()->TextControl('user_id', '用户编号')->static(),
  83. amis()->TextControl('coach_id', '技师编号')->static(),
  84. amis()->TextControl('service_id', '项目编号')->static(),
  85. amis()->TextControl('channel_id', '渠道编号')->static(),
  86. amis()->TextControl('shop_id', '店铺编号')->static(),
  87. amis()->TextControl('customer_service_id', '跟单客服编号')->static(),
  88. amis()->TextControl('order_type', '订单类型')->static(),
  89. amis()->TextControl('order_source', '订单来源')->static(),
  90. amis()->TextControl('total_amount', '订单金额')->static(),
  91. amis()->TextControl('service_amount', '项目金额')->static(),
  92. amis()->TextControl('traffic_amount', '路程金额')->static(),
  93. amis()->TextControl('service_snapshot', '项目快照')->static(),
  94. amis()->TextControl('service_time', '服务时间')->static(),
  95. amis()->TextControl('distance', '目的地距离(米)')->static(),
  96. amis()->TextControl('latitude', '目的地纬度')->static(),
  97. amis()->TextControl('longitude', '目的地经度')->static(),
  98. amis()->TextControl('location', '目的地定位地址')->static(),
  99. amis()->TextControl('address', '目的地详细地址')->static(),
  100. amis()->TextControl('area_code', '目的地行政区划代码')->static(),
  101. amis()->TextControl('remark', '订单备注')->static(),
  102. amis()->TextControl('state', '订单状态')->static(),
  103. amis()->TextControl('created_at', admin_trans('admin.created_at'))->static(),
  104. amis()->TextControl('updated_at', admin_trans('admin.updated_at'))->static(),
  105. ]);
  106. }
  107. /**
  108. * [订单管理]更换订单技师
  109. *
  110. * @description 更换订单的服务技师
  111. *
  112. * @header x-xsrf-token required CSRF令牌 Example: your_csrf_token
  113. *
  114. * @bodyParam order_id integer required 订单ID Example: 1
  115. * @bodyParam new_coach_id integer required 新技师ID Example: 2
  116. * @bodyParam reason string optional 更换原因 Example: 技师临时有事
  117. *
  118. * @response {
  119. * "code": 200,
  120. * "message": "更换技师成功",
  121. * "data": null
  122. * }
  123. */
  124. public function changeCoach(Request $request)
  125. {
  126. $validated = $request->validate([
  127. 'order_id' => 'required|integer|exists:order,id',
  128. 'new_coach_id' => 'required|integer|exists:coach_users,id',
  129. 'reason' => 'nullable|string|max:255',
  130. ]);
  131. return $this->service->changeOrderCoach($validated);
  132. }
  133. /**
  134. * [订单管理]指定抢单技师
  135. *
  136. * @description 为订单指定抢单技师
  137. *
  138. * @header x-xsrf-token required CSRF令牌 Example: your_csrf_token
  139. *
  140. * @bodyParam order_id integer required 订单ID Example: 1
  141. * @bodyParam coach_id integer required 技师ID Example: 2
  142. * @bodyParam remark string optional 备注 Example: 平台指派
  143. *
  144. * @response {
  145. * "code": 200,
  146. * "message": "指定技师成功",
  147. * "data": null
  148. * }
  149. */
  150. public function assignCoach(Request $request)
  151. {
  152. $validated = $request->validate([
  153. 'order_id' => 'required|integer|exists:order,id',
  154. 'coach_id' => 'required|integer|exists:coach_users,id',
  155. 'remark' => 'nullable|string|max:255',
  156. ]);
  157. return $this->service->assignOrderCoach($validated);
  158. }
  159. /**
  160. * [订单管理]获取订单抢单技师列表
  161. *
  162. * @description 获取参与抢单的技师列表
  163. *
  164. * @header x-xsrf-token required CSRF令牌 Example: your_csrf_token
  165. *
  166. * @urlParam order_id integer required 订单ID Example: 1
  167. *
  168. * @response {
  169. * "code": 200,
  170. * "message": "获取成功",
  171. * "data": [{
  172. * "id": 1,
  173. * "coach_id": 100,
  174. * "nickname": "技师A",
  175. * "avatar": "https://example.com/avatar.jpg",
  176. * "distance": "1.5",
  177. * "state": 1,
  178. * "created_at": "2024-03-20 10:00:00"
  179. * }]
  180. * }
  181. */
  182. public function getOrderGrabList(Request $request, $orderId)
  183. {
  184. return $this->service->getOrderGrabList($orderId);
  185. }
  186. /**
  187. * [订单管理]获取附近技师列表
  188. *
  189. * @description 获取订单附近的技师列表
  190. *
  191. * @header x-xsrf-token required CSRF令牌 Example: your_csrf_token
  192. *
  193. * @urlParam orderId integer required 订单ID Example: 1
  194. *
  195. * @queryParam distance integer optional 搜索范围(米) Example: 5000
  196. *
  197. * @response {
  198. * "code": 200,
  199. * "message": "获取成功",
  200. * "data": [{
  201. * "id": 1,
  202. * "nickname": "技师A",
  203. * "avatar": "https://example.com/avatar.jpg",
  204. * "distance": "1.5",
  205. * "work_status": 1,
  206. * "work_status_text": "空闲",
  207. * "rating": "4.8",
  208. * "order_count": 100,
  209. * "created_at": "2024-03-20 10:00:00"
  210. * }]
  211. * }
  212. */
  213. public function getNearbyCoaches(Request $request, $orderId)
  214. {
  215. $validated = $request->validate([
  216. 'distance' => 'nullable|integer|min:1000|max:50000',
  217. ]);
  218. return $this->service->getNearbyCoaches($orderId, $validated['distance'] ?? 5000);
  219. }
  220. /**
  221. * [订单管理]重置订单技师
  222. *
  223. * @description 重置订单技师,将订单改为抢单模式
  224. *
  225. * @header x-xsrf-token required CSRF令牌 Example: your_csrf_token
  226. *
  227. * @bodyParam order_id integer required 订单ID Example: 1
  228. * @bodyParam reason string optional 重置原因 Example: 技师无法服务
  229. *
  230. * @response {
  231. * "code": 200,
  232. * "message": "重置技师成功",
  233. * "data": null
  234. * }
  235. */
  236. public function resetCoach(Request $request)
  237. {
  238. $validated = $request->validate([
  239. 'order_id' => 'required|integer|exists:order,id',
  240. 'reason' => 'nullable|string|max:255',
  241. ]);
  242. return $this->service->resetOrderCoach($validated);
  243. }
  244. /**
  245. * [订单管理]临时接单
  246. *
  247. * @description 管理员代替技师接单
  248. *
  249. * @header x-xsrf-token required CSRF令牌 Example: your_csrf_token
  250. *
  251. * @bodyParam order_id integer required 订单ID Example: 1
  252. * @bodyParam reason string optional 接单原因 Example: 客户要求指定技师
  253. *
  254. * @response {
  255. * "code": 200,
  256. * "message": "接单成功",
  257. * "data": null
  258. * }
  259. */
  260. public function temporaryAccept(Request $request)
  261. {
  262. $validated = $request->validate([
  263. 'order_id' => 'required|integer|exists:order,id',
  264. 'reason' => 'nullable|string|max:255',
  265. ]);
  266. return $this->service->temporaryAcceptOrder($validated);
  267. }
  268. /**
  269. * [订单管理]开始服务
  270. *
  271. * @description 管理员代替技师开始服务
  272. *
  273. * @header x-xsrf-token required CSRF令牌 Example: your_csrf_token
  274. *
  275. * @bodyParam order_id integer required 订单ID Example: 1
  276. * @bodyParam reason string optional 原因 Example: 用户核销码无法扫描
  277. *
  278. * @response {
  279. * "code": 200,
  280. * "message": "开始服务成功",
  281. * "data": null
  282. * }
  283. */
  284. public function startService(Request $request)
  285. {
  286. $validated = $request->validate([
  287. 'order_id' => 'required|integer|exists:order,id',
  288. 'reason' => 'nullable|string|max:255',
  289. ]);
  290. return $this->service->startOrderService($validated);
  291. }
  292. /**
  293. * [订单管理]结束服务
  294. *
  295. * @description 管理员代替技师结束服务
  296. *
  297. * @header x-xsrf-token required CSRF令牌 Example: your_csrf_token
  298. *
  299. * @bodyParam order_id integer required 订单ID Example: 1
  300. * @bodyParam reason string optional 原因 Example: 用户要求提前结束服务
  301. *
  302. * @response {
  303. * "code": 200,
  304. * "message": "结束服务成功",
  305. * "data": null
  306. * }
  307. */
  308. public function endService(Request $request)
  309. {
  310. $validated = $request->validate([
  311. 'order_id' => 'required|integer|exists:order,id',
  312. 'reason' => 'nullable|string|max:255',
  313. ]);
  314. return $this->service->endOrderService($validated);
  315. }
  316. /**
  317. * [订单管理]处理报警
  318. *
  319. * @description 处理技师报警事件
  320. *
  321. * @header x-xsrf-token required CSRF令牌 Example: your_csrf_token
  322. *
  323. * @bodyParam exc_record_id integer required 异常记录ID Example: 1
  324. * @bodyParam handle_result string required 处理结果 Example: 已电话联系技师,确认安全
  325. *
  326. * @response {
  327. * "code": 200,
  328. * "message": "处理成功",
  329. * "data": null
  330. * }
  331. */
  332. public function handleAlarm(Request $request)
  333. {
  334. $validated = $request->validate([
  335. 'exc_record_id' => 'required|integer|exists:order_exc_records,id',
  336. 'handle_result' => 'required|string|max:255',
  337. ]);
  338. return $this->service->handleOrderAlarm($validated);
  339. }
  340. }