BikeController.php 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524
  1. <?php
  2. namespace App\Http\Controllers\App;
  3. use App\Filters\BikeFilter;
  4. use App\Handlers\Aes128Handler;
  5. use App\Handlers\BaseBikeControl;
  6. use App\Handlers\BikeStatusInfoSyncHandler;
  7. use App\Http\Requests\RemarkRequest;
  8. use App\Http\Resources\App\BikeOnlineResource;
  9. use App\Http\Resources\App\BikeResource;
  10. use App\Http\Resources\App\OrderRentResource;
  11. use App\Http\Resources\App\OrderResource;
  12. use App\Jobs\AutoCloseBikeLockJob;
  13. use App\Models\AdminUser;
  14. use App\Models\Area;
  15. use App\Models\Bike;
  16. // use App\Models\BikeTrouble;
  17. use App\Models\BoxBinding;
  18. use App\Models\LocationsLog;
  19. use App\Models\Order;
  20. use App\Models\OrderBikeOperate;
  21. use App\Models\OrderRent;
  22. use App\Models\User;
  23. use App\Models\WorkerBikeOperate;
  24. use App\Models\WorkOrder;
  25. use App\Utils\Admin;
  26. use App\Utils\GaodeMaps;
  27. use App\Utils\Runtime;
  28. use Carbon\Carbon;
  29. use Illuminate\Http\Request;
  30. use App\Http\Controllers\Controller;
  31. use Illuminate\Support\Facades\DB;
  32. use Illuminate\Support\Facades\Log;
  33. use Illuminate\Support\Facades\Redis;
  34. use Matrix\Exception;
  35. class BikeController extends AppBaseController
  36. {
  37. /**
  38. * getBikeInfoByBikeNo 根据车辆编号查找车辆基础信息
  39. *
  40. * @param Request $request
  41. * @return \Illuminate\Http\JsonResponse
  42. * @author Fx
  43. *
  44. */
  45. public function getBikeInfoByBikeNo(Request $request)
  46. {
  47. $bike_no = $request->get('bike_no') ?? '';
  48. if (empty($bike_no)) return $this->error('请输入正确车牌号');
  49. $bikeInfo = Bike::query()->where('bike_no', $bike_no);
  50. if (!Admin::isAdministrator() && !Admin::isNormalAdministrator()) {
  51. $bikeInfo = $bikeInfo->whereIn('put_area_id', self::$areaIds);
  52. }
  53. $bikeInfo = $bikeInfo->first();
  54. if (empty($bikeInfo)) return $this->error('找不到车辆信息,请检查车牌号');
  55. $data = [];
  56. $model = $bikeInfo;
  57. $tab_name = '';
  58. if (!(bool)$model->is_link) {
  59. // 离线
  60. $tab_name = '中控离线';
  61. } elseif ((bool)$model->is_trouble) {
  62. // 故障上线
  63. if ((bool)$model->put_status) {
  64. $tab_name = '故障';
  65. } else {
  66. // 故障下线
  67. $tab_name = '故障下线';
  68. }
  69. } elseif (!(bool)$model->is_low_battery_power) {
  70. // 低电量
  71. $tab_name = '低电量';
  72. } elseif (!(bool)$model->put_status) {
  73. // 下线 未投放
  74. $tab_name = '未投放';
  75. } elseif ((bool)$model->is_riding) {
  76. //骑行中
  77. $tab_name = '骑行中';
  78. } elseif (!(bool)$model->is_in_parking) {
  79. // 不在停车区
  80. $tab_name = '不在停车区';
  81. } else {
  82. // 未骑行
  83. $tab_name = '未骑行';
  84. }
  85. $lastLocation = LocationsLog::getNewestLocationTimeByBikeNo($bike_no);
  86. $workInfo = [];
  87. if (app()->redis->hexists(BikeStatusInfoSyncHandler::REDIS_RIDE_BIKE_WORKER_ORDERS_TAG, $bikeInfo->bike_no)) {
  88. $work_id = app()->redis->hget(BikeStatusInfoSyncHandler::REDIS_RIDE_BIKE_WORKER_ORDERS_TAG, $bikeInfo->bike_no);
  89. $work = AdminUser::find($work_id);
  90. $workInfo = [
  91. 'name' => $work->name,
  92. 'phone' => $work->phone,
  93. ];
  94. }
  95. // 车辆信息
  96. $data['bike_info']['bike_no'] = $bike_no;
  97. $data['bike_info']['box_no'] = $bikeInfo->box_no;
  98. $data['bike_info']['id'] = $bikeInfo->id;
  99. $data['bike_info']['is_lock'] = $bikeInfo->is_lock;
  100. $data['bike_info']['battery_power'] = $bikeInfo->battery_power;
  101. $data['bike_info']['is_trouble'] = $bikeInfo->is_trouble; // 是否故障
  102. $data['bike_info']['is_link'] = $bikeInfo->put_status; // 是否在线
  103. $data['bike_info']['area_name'] = Area::query()->find($bikeInfo->put_area_id)->name ?? ''; //车辆区域地址
  104. $data['bike_info']['tab_name'] = $tab_name; //状态
  105. $data['bike_info']['last_location'] = GaodeMaps::getAddress([$lastLocation['location']['lng'], $lastLocation['location']['lat']]); //最后定位位置
  106. $data['bike_info']['last_time'] = $lastLocation['time']; //最后定位时间
  107. $data['bike_info']['workInfo'] = $workInfo; //最后定位时间
  108. $data['bike_info']['remark'] = $bikeInfo->remark ?? ''; //最后定位时间
  109. //最近订单 取最
  110. $order = Order::query()->where('bike_id', $bikeInfo->id)->orderByDesc('id')->with('users')->first();
  111. $orderRent = OrderRent::query()->where('bike_id', $bikeInfo->id)->orderByDesc('id')->with('users')->first();
  112. $data2 = [];
  113. if (!empty($order) && !empty($orderRent)) {
  114. if ($orderRent->start_use_bike_time > $order->start_use_bike_time) {
  115. // $user = User::query()->find($v->user_id);
  116. $data1['bike_no'] = $orderRent->bike_no;
  117. $data1['username'] = $orderRent->users->nickname . "(" . $orderRent->users->truename . ")" ?? '';
  118. $data1['mobile'] = $orderRent->users->mobile ?? '';
  119. $data1['order_status'] = OrderRent::$statusMaps[$orderRent->status];
  120. $data1['start_use_bike_time'] = $orderRent->start_use_bike_time;
  121. $data1['end_use_bike_time'] = $orderRent->end_use_bike_time;
  122. $data1['start_use_bike_time_app'] = date('m/d H:i', strtotime($orderRent->start_use_bike_time));
  123. $data1['end_use_bike_time_app'] = $orderRent->end_use_bike_time ? date('m/d H:i', strtotime($orderRent->end_use_bike_time)) : '';
  124. } else {
  125. $data1['bike_no'] = $order->bike_no;
  126. $data1['username'] = $order->users->nickname . "(" . $order->users->truename . ")" ?? '';
  127. $data1['mobile'] = $order->users->mobile ?? '';
  128. $data1['order_status'] = Order::$statusMaps[$order->status];
  129. $data1['start_use_bike_time'] = $order->start_use_bike_time;
  130. $data1['end_use_bike_time'] = $order->end_use_bike_time;
  131. $data1['start_use_bike_time_app'] = date('m/d H:i', strtotime($order->start_use_bike_time));
  132. $data1['end_use_bike_time_app'] = $order->end_use_bike_time ? date('m/d H:i', strtotime($order->end_use_bike_time)) : '';
  133. }
  134. $data2[] = $data1;
  135. } else if (!empty($order)) {
  136. $data1['bike_no'] = $order->bike_no;
  137. $data1['username'] = $order->users->nickname . "(" . $order->users->truename . ")" ?? '';
  138. $data1['mobile'] = $order->users->mobile ?? '';
  139. $data1['order_status'] = Order::$statusMaps[$order->status];
  140. $data1['start_use_bike_time'] = $order->start_use_bike_time;
  141. $data1['end_use_bike_time'] = $order->end_use_bike_time;
  142. $data1['start_use_bike_time_app'] = date('m/d H:i', strtotime($order->start_use_bike_time));
  143. $data1['end_use_bike_time_app'] = $order->end_use_bike_time ? date('m/d H:i', strtotime($order->end_use_bike_time)) : '';
  144. $data2[] = $data1;
  145. } else if (!empty($orderRent)) {
  146. $data1['bike_no'] = $orderRent->bike_no;
  147. $data1['username'] = $orderRent->users->nickname . "(" . $orderRent->users->truename . ")" ?? '';
  148. $data1['mobile'] = $orderRent->users->mobile ?? '';
  149. $data1['order_status'] = OrderRent::$statusMaps[$orderRent->status];
  150. $data1['start_use_bike_time'] = $orderRent->start_use_bike_time;
  151. $data1['end_use_bike_time'] = $orderRent->end_use_bike_time;
  152. $data1['start_use_bike_time_app'] = date('m/d H:i', strtotime($orderRent->start_use_bike_time));
  153. $data1['end_use_bike_time_app'] = $orderRent->end_use_bike_time ? date('m/d H:i', strtotime($orderRent->end_use_bike_time)) : '';
  154. $data2[] = $data1;
  155. }
  156. $data['bike_order'] = $data2;
  157. return $this->ok($data);
  158. }
  159. /**
  160. * updateBikeInfo 根据车辆id 修改车辆信息
  161. *
  162. * @param Request $request
  163. * @return \Illuminate\Http\JsonResponse
  164. * @author Fx
  165. *
  166. */
  167. public function updateBikeInfo(Request $request)
  168. {
  169. $admin_id = Admin::user()->id;
  170. if (!Admin::isAdministrator()) {
  171. return $this->error('暂无权限');
  172. }
  173. $bike_id = $request->get('bike_id') ?? '';
  174. if (empty($bike_id)) return $this->error('参数错误');
  175. $bike = Bike::query()->whereIn('put_area_id', self::$areaIds)->find($bike_id);
  176. if (empty($bike)) return $this->error('找不到该车辆信息,请检查车牌号');
  177. $bike_no = $request->get('bike_no') ?? '';
  178. $box_no = $request->get('box_no') ?? '';
  179. $bike_remarks = $request->get('bike_remarks') ?? '';
  180. if (empty($bike_no) && empty($box_no) && empty($bike_remarks)) {
  181. // 都为空
  182. return $this->error('请输入要修改的内容');
  183. }
  184. // 不为空修改
  185. if (!empty($bike_no)) {
  186. $verifyBikeNo = Bike::query()->where('bike_no', $bike_no)->first();
  187. if (!empty($verifyBikeNo)) {
  188. if ($verifyBikeNo->id !== $bike->id) {
  189. return $this->error('车辆编号已存在,不可修改');
  190. }
  191. }
  192. $bike->bike_no = $bike_no;
  193. }
  194. $date = Carbon::now();
  195. if (!empty($bike_remarks)) {
  196. $bike->remark = $bike_remarks . $date;
  197. }
  198. if (!empty($box_no)) {
  199. $verifyBikeNo = Bike::query()->where('box_no', $box_no)->first();
  200. if (!empty($verifyBikeNo)) {
  201. if ($verifyBikeNo->id !== $bike->id) {
  202. return $this->error('中控编号已存在,不可修改');
  203. }
  204. }
  205. // 中控绑定操作
  206. $box = BoxBinding::query()->where('box_no', $box_no)->first();
  207. if (empty($box)) return $this->error('找不到此设备信息,请联系管理员');
  208. if ($box->is_binding == BoxBinding::BINDING_YES) return $this->error('此设备已经绑定过');
  209. $blu_key = $blu_ase_key = '';
  210. switch ((int)$box->manufacturer) {
  211. case BoxBinding::TBT:
  212. $blu_key = config('systemConfig.blu_key');
  213. try {
  214. $blu_ase_key = Aes128Handler::genKey($blu_key, $box_no);
  215. } catch (\Exception $e) {
  216. return $this->error($e->getMessage());
  217. }
  218. break;
  219. case BoxBinding::WKM:
  220. $blu_key = $box->bluetooth_token;
  221. $blu_ase_key = $box->bluetooth_token;
  222. break;
  223. }
  224. $inputs['blu_key'] = $blu_key;
  225. $inputs['blu_ase_key'] = $blu_ase_key;
  226. try {
  227. DB::beginTransaction();
  228. $bike->blu_key = $blu_key;
  229. $bike->blu_ase_key = $blu_ase_key;
  230. $box->is_binding = BoxBinding::BINDING_YES;
  231. $box->save();
  232. $bike->save();
  233. DB::commit();
  234. return $this->ok(BikeResource::make($bike));
  235. } catch (\Exception $e) {
  236. DB::rollBack();
  237. Log::error($e->getMessage());
  238. return $this->error('修改失败,请联系管理员');
  239. }
  240. }
  241. $bool = $bike->save();
  242. if ($bool) {
  243. return $this->ok('修改成功');
  244. } else {
  245. return $this->error('修改失败,请联系管理员');
  246. }
  247. }
  248. /**
  249. * bikeLocation 车辆位置轨迹
  250. *
  251. * @param Request $request
  252. * @return \Illuminate\Http\JsonResponse
  253. * @author Fx
  254. *
  255. */
  256. public function bikeLocation(Request $request)
  257. {
  258. $bike_no = $request->get('bike_no') ?? '';
  259. $time_between = $request->get('time_between') ?? []; // time_between 时间区间
  260. if (empty($bike_no) || empty($time_between)) return $this->error('参数错误');
  261. $locationLog = LocationsLog::where('bike_no', $bike_no)
  262. ->where('created_at', '>=', Carbon::parse($time_between[0])->toDateString())
  263. ->where('created_at', '<=', Carbon::parse($time_between[1])->toDateString())
  264. ->whereBetween('latitude', [3, 53])->whereBetween('longitude', [73, 136])->orderBy('box_time', 'asc')
  265. ->get(['longitude', 'latitude', 'type']);
  266. $data = [];
  267. $userLocation = [];
  268. $workerLocation = [];
  269. $noLocatioin = [];
  270. $old_type = '';
  271. $item = [];
  272. $Locations = [];
  273. foreach ($locationLog as $v) {
  274. $data[] = [$v->longitude, $v->latitude];
  275. if (empty($old_type)) {
  276. $old_type = $v->type;
  277. }
  278. if ($v->type !== $old_type) {
  279. if ($old_type == LocationsLog::USER_LOCATION) {
  280. $userLocation[] = $item;
  281. $Locations[] = [
  282. 'points' => $item,
  283. 'role' => LocationsLog::USER_LOCATION,
  284. 'borderColor' => '#18D3B8',
  285. 'borderWidth' => '3',
  286. 'color' => '#18D3B8',
  287. 'width' => '4'];
  288. } else if ($old_type == LocationsLog::WORKER_LOCATION) {
  289. $workerLocation[] = $item;
  290. $Locations[] = [
  291. 'role' => LocationsLog::WORKER_LOCATION,
  292. 'points' => $item,
  293. 'borderColor' => '#ff6477',
  294. 'borderWidth' => '3',
  295. 'color' => '#ff6477',
  296. 'width' => '4'
  297. ];
  298. } else {
  299. $noLocatioin[] = $item;
  300. $Locations[] = [
  301. 'points' => $item,
  302. 'borderColor' => '#d684dd',
  303. 'borderWidth' => '3',
  304. 'color' => '#d684dd',
  305. 'width' => '4',
  306. 'role' => LocationsLog::NO_LOCATION
  307. ];
  308. }
  309. $old_type = '';
  310. $item = [];
  311. $item[] = ['longitude' => $v->longitude, 'latitude' => $v->latitude];
  312. } else {
  313. $item[] = ['longitude' => $v->longitude, 'latitude' => $v->latitude];
  314. }
  315. unset($v->_id);
  316. }
  317. if (empty($data)) return $this->ok($data);
  318. $wx_data = $locationLog->toArray();
  319. $start_point = [
  320. 'zIndex' => 100,
  321. 'id' => 'start',
  322. 'width' => 32,
  323. 'height' => 32,
  324. 'iconPath' => 'http://resource.bike.hanyiyun.com/common/start-location-mark.png',
  325. ];
  326. $end_point = [
  327. 'zIndex' => 100,
  328. 'id' => 'end',
  329. 'width' => 32,
  330. 'height' => 32,
  331. 'iconPath' => 'http://resource.bike.hanyiyun.com/common/end-location-mark.png',
  332. ];
  333. $res = [
  334. 'points' => [array_merge($wx_data[0], $start_point), array_merge(end($wx_data), $end_point)],
  335. 'all_locations' => $Locations
  336. ];
  337. return $this->ok($res);
  338. }
  339. /**
  340. * bikePosition 获取车辆真实位置点(mongodb)
  341. *
  342. * @param Request $request
  343. * @return \Illuminate\Http\JsonResponse
  344. * @author Fx
  345. *
  346. */
  347. public function bikePosition(Request $request)
  348. {
  349. $bike_no = $request->get('bike_no') ?? '';
  350. if (empty($bike_no)) return $this->error('参数错误');
  351. $position = LocationsLog::getNewestLocationByBikeNo($bike_no);
  352. if (empty($position)) return $this->ok([]);
  353. return $this->ok([$position['lng'], $position['lat']]);
  354. }
  355. /**
  356. * sweepCodeLocation 扫码位置 近200条
  357. *
  358. * @param Request $request
  359. * @return \Illuminate\Http\JsonResponse
  360. * @author Fx
  361. *
  362. */
  363. public function sweepCodeLocation(Request $request)
  364. {
  365. $bike_id = $request->get('bike_id') ?? '';
  366. if (empty($bike_id)) return $this->error('参数错误');
  367. $threeAgo = Carbon::today()->subDays(3);
  368. $order = Order::query()
  369. ->where('bike_id', $bike_id)
  370. // ->where('created_at','>',$threeAgo)
  371. ->orderByDesc('id')
  372. ->limit(100)
  373. ->get(['start_use_bike_time', 'start_use_bike_location']);
  374. $data = [];
  375. if (!empty($order)) {
  376. foreach ($order as $v) {
  377. $dataItem['time'] = $v->start_use_bike_time;
  378. $obj = json_decode($v->start_use_bike_location);
  379. $dataItem['location'] = [$obj->longitude, $obj->latitude];
  380. $data[] = $dataItem;
  381. }
  382. }
  383. $orderRent = OrderRent::query()
  384. ->where('bike_id', $bike_id)
  385. // ->where('created_at','>',$threeAgo)
  386. ->orderByDesc('id')
  387. ->limit(100)
  388. ->get(['start_use_bike_time', 'start_use_bike_location']);
  389. $dataRent = [];
  390. if (!empty($orderRent)) {
  391. foreach ($orderRent as $v) {
  392. $dataRentItem['time'] = $v->start_use_bike_time;
  393. $objRent = json_decode($v->start_use_bike_location);
  394. $dataRentItem['location'] = [$objRent->longitude, $objRent->latitude];
  395. $dataRent[] = $dataRentItem;
  396. }
  397. }
  398. return $this->ok(array_merge($data, $dataRent));
  399. }
  400. public function updateRemark(RemarkRequest $request, $id)
  401. {
  402. //
  403. $bike = Bike::find($id);
  404. $inputs = $request->validated();
  405. // Log::info($id);
  406. $bike->update($inputs);
  407. return $this->ok('修改成功');
  408. }
  409. /**
  410. * latelyOrders 车辆最近订单
  411. *
  412. * @param Request $request
  413. * @return \Illuminate\Http\JsonResponse
  414. * @author Fx
  415. *
  416. */
  417. public function latelyOrders(Request $request)
  418. {
  419. $bike_id = $request->get('bike_id') ?? '';
  420. if (empty($bike_id)) return $this->error('参数错误');
  421. $order = Order::query()
  422. ->where('bike_id', $bike_id)
  423. ->with('users')
  424. ->orderByDesc('id')
  425. ->paginate();
  426. // $data = [];
  427. // if (!empty($order)) {
  428. // foreach ($order as $v) {
  429. // // $user = User::query()->find($v->user_id);
  430. // $data1['bike_no'] = $v->bike_no;
  431. // $data1['username'] = $v->users->nickname ?? '';
  432. // $data1['mobile'] = $v->users->mobile ?? '';
  433. // $data1['order_status'] = Order::$statusMaps[$v->status];
  434. // $data1['start_use_bike_time'] = $v->start_use_bike_time;
  435. // $data1['end_use_bike_time'] = $v->end_use_bike_time;
  436. // $data[] = $data1;
  437. // }
  438. // }
  439. return $this->ok(OrderResource::collection($order));
  440. }
  441. /**
  442. * latelyOrderRent 最近日租订单
  443. *
  444. * @param Request $request
  445. * @return \Illuminate\Http\JsonResponse
  446. * @author Fx
  447. *
  448. */
  449. public function latelyOrderRent(Request $request)
  450. {
  451. $bike_id = $request->get('bike_id') ?? '';
  452. if (empty($bike_id)) return $this->error('参数错误');
  453. $order = OrderRent::query()
  454. ->where('bike_id', $bike_id)
  455. ->with('users')
  456. ->orderByDesc('id')
  457. ->paginate();
  458. return $this->ok(OrderRentResource::collection($order));
  459. }
  460. /**
  461. * locksLog 车辆开锁关锁记录 近3天
  462. *
  463. * @param Request $request
  464. * @return \Illuminate\Http\JsonResponse
  465. * @author Fx
  466. *
  467. */
  468. public function locksLog(Request $request)
  469. {
  470. $bike_id = $request->get('bike_id') ?? '';
  471. if (empty($bike_id)) return $this->error('参数错误');
  472. $typeArr = [OrderBikeOperate::TYPE_OPEN_BIKE,
  473. OrderBikeOperate::TYPE_CLONE_BIKE,
  474. OrderBikeOperate::TYPE_PAUSE_OPEN_BIKE,
  475. OrderBikeOperate::TYPE_PAUSE_CLONE_BIKE];
  476. // 普通用户操作
  477. $threeAgo = Carbon::today()->subDays(3);
  478. $lock1 = OrderBikeOperate::query()
  479. ->whereIn('type', $typeArr)
  480. ->where('is_admin', OrderBikeOperate::IS_ADMIN_NO)
  481. ->where('bike_id', $bike_id)
  482. ->where('created_at', '>', $threeAgo)
  483. ->with('users')
  484. ->orderByDesc('id')
  485. ->get();
  486. $data1 = [];
  487. $open_bike = [];
  488. $close_bike = [];
  489. $open_pause_bike = [];
  490. $close_pause_bike = [];
  491. if (!empty($lock1)) {
  492. foreach ($lock1 as $v) {
  493. // $user = User::query()->find($v->user_id);
  494. $dataItem1['username'] = $v->users->nickname ?? '';
  495. $dataItem1['mobile'] = $v->users->mobile ?? '';
  496. $dataItem1['operate_time'] = date("Y/m/d H:i:s", strtotime($v->created_at));
  497. $dataItem1['name'] = $v->name;
  498. $dataItem1['location'] = [$v->longitude, $v->latitude];
  499. if ($v->type == OrderBikeOperate::TYPE_OPEN_BIKE) {
  500. $open_bike[] = $dataItem1;
  501. } elseif ($v->type == OrderBikeOperate::TYPE_CLONE_BIKE) {
  502. $close_bike[] = $dataItem1;
  503. } elseif ($v->type == OrderBikeOperate::TYPE_PAUSE_OPEN_BIKE) {
  504. $open_pause_bike[] = $dataItem1;
  505. } elseif ($v->type == OrderBikeOperate::TYPE_PAUSE_CLONE_BIKE) {
  506. $close_pause_bike[] = $dataItem1;
  507. }
  508. }
  509. }
  510. // 管理员操作
  511. $lock2 = OrderBikeOperate::query()
  512. ->whereIn('type', $typeArr)
  513. ->where('is_admin', OrderBikeOperate::IS_ADMIN_YES)
  514. ->where('bike_id', $bike_id)
  515. ->where('created_at', '>', $threeAgo)
  516. ->with('adminUsers')
  517. ->orderByDesc('id')
  518. ->get();
  519. $data2 = [];
  520. if (!empty($lock2)) {
  521. foreach ($lock2 as $v) {
  522. // $user = AdminUser::query()->find($v->user_id);
  523. $dataItem2['username'] = $v->adminUsers->name ?? '';
  524. $dataItem2['mobile'] = $v->adminUsers->phone ?? '';
  525. $dataItem2['operate_time'] = date("Y/m/d H:i:s", strtotime($v->created_at));
  526. $dataItem2['name'] = $v->name;
  527. $dataItem2['location'] = [$v->longitude, $v->latitude];
  528. if ($v->type == OrderBikeOperate::TYPE_OPEN_BIKE) {
  529. $open_bike[] = $dataItem2;
  530. } elseif ($v->type == OrderBikeOperate::TYPE_CLONE_BIKE) {
  531. $close_bike[] = $dataItem2;
  532. } elseif ($v->type == OrderBikeOperate::TYPE_PAUSE_OPEN_BIKE) {
  533. $open_pause_bike[] = $dataItem2;
  534. } elseif ($v->type == OrderBikeOperate::TYPE_PAUSE_CLONE_BIKE) {
  535. $close_pause_bike[] = $dataItem2;
  536. }
  537. }
  538. }
  539. // $data = array_merge($data1, $data2);
  540. $data = [
  541. 'open_bike' => $open_bike,
  542. 'close_bike' => $close_bike,
  543. 'open_pause_bike' => $open_pause_bike,
  544. 'close_pause_bike' => $close_pause_bike
  545. ];
  546. return $this->ok($data);
  547. }
  548. /**
  549. * bikeOnLineLog 车辆上线下线记录
  550. *
  551. * @param Request $request
  552. * @return \Illuminate\Http\JsonResponse
  553. * @author Fx
  554. *
  555. */
  556. public function bikeOnLineLog(Request $request)
  557. {
  558. $bike_id = $request->get('bike_id') ?? '';
  559. if (empty($bike_id)) return $this->error('参数错误');
  560. $bikeOnLine = WorkerBikeOperate::query()
  561. ->where('bike_id', $bike_id)
  562. ->whereIn('type', [WorkerBikeOperate::TYPE_ONLINE, WorkerBikeOperate::TYPE_OFFLINE])
  563. ->with('workers')
  564. ->orderByDesc('id')
  565. ->paginate();
  566. // $data = [];
  567. // if (!empty($bikeOnLine)) {
  568. // foreach ($bikeOnLine as $v) {
  569. // $item['reason'] = $v->reason;
  570. // $item['name'] = $v->name;
  571. // $item['created_at'] = date("Y/m/d H:i:s", strtotime($v->created_at));
  572. // $item['username'] = $v->workers->name;
  573. // $item['mobile'] = $v->workers->phone;
  574. // $data[] = $item;
  575. // }
  576. // }
  577. return $this->ok(BikeOnlineResource::collection($bikeOnLine));
  578. }
  579. /**
  580. * repairOptions 可报修选项
  581. *
  582. * @return \Illuminate\Http\JsonResponse
  583. * @author Fx
  584. *
  585. */
  586. public function repairOptions()
  587. {
  588. // $repair_part = BikeTrouble::$troublePartMaps;
  589. $repair_part = WorkOrder::$typeMaps;
  590. $data = [];
  591. foreach ($repair_part as $k => $v) {
  592. $dateItem['id'] = $k;
  593. $dateItem['name'] = $v;
  594. $dateItem['select'] = false;
  595. $data[] = $dateItem;
  596. }
  597. return $this->ok($data);
  598. }
  599. /**
  600. * bikeRepair 车辆报修
  601. *
  602. * @param Request $request
  603. * @return \Illuminate\Http\JsonResponse
  604. * @author Fx
  605. *
  606. */
  607. public function bikeRepair(Request $request)
  608. {
  609. $bike_no = $request->get('bike_no') ?? '';
  610. $box_no = $request->get('box_no') ?? '';
  611. $trouble_part = $request->get('trouble_part') ?? ''; // 报修部位
  612. $reason = $request->get('reason') ?? ''; // 原因
  613. if (empty($trouble_part)) return $this->error('请选择报修部位');
  614. if (empty($reason) || empty($bike_no)) return $this->error('请填写报修原因');
  615. if (!empty($bike_no)) {
  616. $bike = Bike::query()->where('bike_no', $bike_no)->first();
  617. if (!empty($bike)) {
  618. if ($bike->put_status == Bike::PUT_STATUS_NO) {
  619. return $this->error('车辆已下线,无需报修,如需报修请先手动上线');
  620. }
  621. DB::beginTransaction();
  622. try {
  623. // 更新车辆状态 下线
  624. $bike->put_status = Bike::PUT_STATUS_NO;
  625. $bike->is_trouble = Bike::TROUBLE_YES;
  626. $bool1 = $bike->save();
  627. // 更新redis
  628. (new BikeStatusInfoSyncHandler())->toBikeOffLineStatus($bike->bike_no);
  629. if (!$bool1) {
  630. DB::rollBack();
  631. Log::error('更新车辆状态失败');
  632. }
  633. // 插入下线记录
  634. $worker_bike_operate = new WorkerBikeOperate();
  635. $worker_bike_operate->type = WorkerBikeOperate::TYPE_OFFLINE;
  636. $worker_bike_operate->name = WorkerBikeOperate::$typeMaps[WorkerBikeOperate::TYPE_OFFLINE];
  637. $worker_bike_operate->bike_id = $bike->id;
  638. $last_location = json_decode($bike->last_location);
  639. $worker_bike_operate->latitude = empty($last_location->lat) ? 0 : $last_location->lat;
  640. $worker_bike_operate->longitude = empty($last_location->lng) ? 0 : $last_location->lng;
  641. $worker_bike_operate->worker_id = Admin::user()->id;
  642. // foreach ($trouble_part as $v){
  643. // $reason .= BikeTrouble::$troublePartMaps[$v] . ',';
  644. // }
  645. $worker_bike_operate->reason = $reason;
  646. $bool2 = $worker_bike_operate->save();
  647. if (!$bool2) {
  648. DB::rollBack();
  649. Log::error('插入下线记录失败');
  650. }
  651. // 插入报修信息
  652. // $bike_trouble = new BikeTrouble();
  653. // $bike_trouble->trouble_no = 'T-'.$this->generateTroubleNo(); //故障号
  654. // $bike_trouble->user_id = Admin::user()->id;
  655. // $bike_trouble->bike_id = $bike->id;
  656. // $bike_trouble->area_id = $bike->put_area_id;// 区域id
  657. // $bike_trouble->trouble_part = json_encode($trouble_part);
  658. // $bike_trouble->trouble_grade = count($trouble_part)==1 ? BikeTrouble::getTroubleGrade($trouble_part[0]): BikeTrouble::TROUBLE_GRADE_TWO ;// 故障等级 故障部位大于1 默认高级故障
  659. // // $bike_trouble->up_trouble_type = 0 // 上报问题类型
  660. // $bool3 = $bike_trouble->save();
  661. //生成工单
  662. //插入工单
  663. $work_order_data = [
  664. 'work_no' => WorkOrder::makeWorkNo(),
  665. 'type' => $trouble_part,
  666. 'type_name' => WorkOrder::$typeMaps[$trouble_part],
  667. 'bike_no' => $bike->bike_no,
  668. 'bike_id' => $bike->id,
  669. 'source' => WorkOrder::SOURCE_REPAIR,
  670. 'area_id' => $bike->put_area_id,
  671. 'admin_id' => Admin::user()->id,
  672. 'reason' => $reason,
  673. ];
  674. $work_order_verify = [
  675. 'bike_id' => $bike->id,
  676. 'type' => $trouble_part, // 工单类型
  677. 'status' => WorkOrder::STATUS_NO
  678. ];
  679. WorkOrder::firstOrCreate($work_order_verify, $work_order_data);
  680. DB::commit();
  681. return $this->ok('报修成功');
  682. } catch (\Exception $exception) {
  683. DB::rollBack();
  684. Log::info($exception->getMessage());
  685. return $this->error('操作失败请联系管理员');
  686. }
  687. }
  688. }
  689. if (!empty($box_no)) {
  690. $bike = Bike::query()->where('box_no', $box_no)->first();
  691. if (!empty($bike)) {
  692. try {
  693. // 更新车辆状态 下线
  694. $bike->put_status = Bike::PUT_STATUS_NO;
  695. $bike->is_trouble = Bike::TROUBLE_YES;
  696. $bool1 = $bike->save();
  697. // 更新redis
  698. (new BikeStatusInfoSyncHandler())->toBikeOffLineStatus($bike->bike_no);
  699. if (!$bool1) {
  700. DB::rollBack();
  701. Log::error('更新车辆状态失败');
  702. }
  703. // 插入下线记录
  704. $worker_bike_operate = new WorkerBikeOperate();
  705. $worker_bike_operate->type = WorkerBikeOperate::TYPE_OFFLINE;
  706. $worker_bike_operate->name = WorkerBikeOperate::$typeMaps[WorkerBikeOperate::TYPE_OFFLINE];
  707. $worker_bike_operate->bike_id = $bike->id;
  708. $last_location = json_decode($bike->last_location);
  709. $worker_bike_operate->latitude = empty($last_location['lat']) ? 0 : $last_location['lat'];
  710. $worker_bike_operate->longitude = empty($last_location['lng']) ? 0 : $last_location['lng'];
  711. $worker_bike_operate->worker_id = Admin::user()->id;
  712. $worker_bike_operate->reason = $reason;
  713. $bool2 = $worker_bike_operate->save();
  714. if (!$bool2) {
  715. DB::rollBack();
  716. Log::error('插入下线记录失败');
  717. }
  718. // 插入报修信息
  719. // $bike_trouble = new BikeTrouble();
  720. // $bike_trouble->trouble_no = 'T-' . $this->generateTroubleNo(); //故障号
  721. // $bike_trouble->user_id = Admin::user()->id;
  722. // $bike_trouble->bike_id = $bike->id;
  723. // $bike_trouble->area_id = $bike->put_area_id;// 区域id
  724. // $bike_trouble->trouble_part = json_encode($trouble_part);
  725. // $bike_trouble->trouble_grade = 3; // 故障等级
  726. // // $bike_trouble->up_trouble_type = 0 // 上报问题类型
  727. // $bool3 = $bike_trouble->save();
  728. //生成工单
  729. // 插入工单
  730. $work_order_data = [
  731. 'work_no' => WorkOrder::makeWorkNo(),
  732. 'type' => $trouble_part,
  733. 'type_name' => WorkOrder::$typeMaps[$trouble_part],
  734. 'bike_no' => $bike->bike_no,
  735. 'bike_id' => $bike->id,
  736. 'source' => WorkOrder::SOURCE_REPAIR,
  737. 'area_id' => $bike->put_area_id,
  738. 'admin_id' => Admin::user()->id,
  739. 'reason' => $reason,
  740. ];
  741. $work_order_verify = [
  742. 'bike_id' => $bike->id,
  743. 'type' => $trouble_part,
  744. 'status' => WorkOrder::STATUS_NO
  745. ];
  746. WorkOrder::firstOrCreate($work_order_verify, $work_order_data);
  747. DB::commit();
  748. return $this->ok('报修成功');
  749. } catch (\Exception $exception) {
  750. DB::rollBack();
  751. Log::info($exception->getMessage());
  752. return $this->error('操作失败请联系管理员');
  753. }
  754. } else {
  755. return $this->error('找不到该车辆信息');
  756. }
  757. } else {
  758. return $this->error('参数错误');
  759. }
  760. }
  761. /**
  762. * generateTroubleNo 生成故障号
  763. *
  764. * @return string
  765. * @author Fx
  766. *
  767. */
  768. private function generateTroubleNo()
  769. {
  770. $time = date('YmdHis', time());
  771. $randNum = mt_rand(1111, 9999);
  772. return $time . $randNum;
  773. }
  774. /**
  775. * bikeList 车辆列表
  776. *
  777. * @param BikeFilter $filter
  778. * @return \Illuminate\Http\JsonResponse
  779. * @author Fx
  780. *
  781. */
  782. public function bikeList(BikeFilter $filter)
  783. {
  784. $area_ids = self::$areaIds;
  785. $bikelist = Bike::query()
  786. ->whereIn('put_area_id', $area_ids)
  787. ->whereNotNull('box_no')
  788. ->filter($filter)
  789. ->orderByDesc('id')
  790. ->paginate();
  791. return $this->ok(BikeResource::collection($bikelist));
  792. }
  793. /**
  794. * bikeStatistics 车辆统计
  795. *
  796. * @param BikeFilter $filter
  797. * @return \Illuminate\Http\JsonResponse
  798. * @author Fx
  799. *
  800. */
  801. public function bikeStatistics(BikeFilter $filter)
  802. {
  803. $data = [];
  804. $area_ids = self::$areaIds;
  805. // 总车辆数
  806. $data['total_bikes'] = Bike::query()
  807. ->whereIn('put_area_id', $area_ids)
  808. ->filter($filter)
  809. ->count('id');
  810. // 上线车辆数
  811. $data['put_total_bikes'] = Bike::query()
  812. ->whereIn('put_area_id', $area_ids)
  813. ->filter($filter)
  814. ->where('put_status', Bike::PUT_STATUS_YES)
  815. ->count('id');
  816. // 在线车辆数
  817. $data['line_total_bikes'] = Bike::query()
  818. ->whereIn('put_area_id', $area_ids)
  819. ->filter($filter)
  820. ->where('is_link', Bike::LINK_ONLINE)
  821. ->count('id');
  822. //故障车辆
  823. $data['trouble_total_bikes'] = Bike::query()
  824. ->whereIn('put_area_id', $area_ids)
  825. ->filter($filter)
  826. ->where('is_trouble', Bike::TROUBLE_YES)
  827. ->count('id');
  828. //今日使用
  829. $data['today_use_total_bikes'] = Bike::query()
  830. ->whereIn('put_area_id', $area_ids)
  831. ->filter($filter)
  832. ->where('last_use_bike_end_time', '>', Carbon::today())
  833. ->count('id');
  834. //低电量
  835. $data['low_battery_total_bikes'] = Bike::query()
  836. ->whereIn('put_area_id', $area_ids)
  837. ->filter($filter)
  838. ->where('is_low_battery_power', Bike::BATTERY_POWER_LOW)
  839. ->count('id');
  840. //骑行中
  841. $data['riding_total_bikes'] = Bike::query()
  842. ->whereIn('put_area_id', $area_ids)
  843. ->filter($filter)
  844. ->where('is_riding', Bike::RIDING_YES)
  845. ->count('id');
  846. //未使用
  847. $data['not_riding_total_bikes'] = Bike::query()
  848. ->whereIn('put_area_id', $area_ids)
  849. ->filter($filter)
  850. ->where('is_riding', Bike::RIDING_NO)
  851. ->count('id');
  852. return $this->ok($data);
  853. }
  854. /**
  855. * bikeLogin 车辆上线 (投放)
  856. *
  857. * @param Request $request
  858. * @return \Illuminate\Http\JsonResponse
  859. * @author Fx
  860. *
  861. */
  862. public function bikeLogin(Request $request)
  863. {
  864. $bike_id = $request->get('bike_id') ?? '';
  865. if (empty($bike_id)) return $this->error('参数错误');
  866. try {
  867. DB::beginTransaction();
  868. $bike = Bike::query()->find($bike_id);
  869. if (empty($bike)) return $this->error('找不到车辆');
  870. if ($bike->put_status == Bike::PUT_STATUS_YES) return $this->error('车辆已在线');
  871. // 更新车辆上线
  872. $bike->put_status = Bike::PUT_STATUS_YES;
  873. $bike->save();
  874. // 插入上线记录
  875. $worker_bike_operate = new WorkerBikeOperate();
  876. $worker_bike_operate->type = WorkerBikeOperate::TYPE_ONLINE;
  877. $worker_bike_operate->name = WorkerBikeOperate::$typeMaps[WorkerBikeOperate::TYPE_ONLINE];
  878. $worker_bike_operate->reason = "工作人员操作上线";
  879. $last_location = object_array(json_decode($bike->last_location));
  880. $worker_bike_operate->bike_id = $bike_id;
  881. $worker_bike_operate->latitude = empty($last_location['lat']) ? 0 : $last_location['lat'];
  882. $worker_bike_operate->longitude = empty($last_location['lng']) ? 0 : $last_location['lng'];
  883. $worker_bike_operate->worker_id = Admin::user()->id;
  884. $worker_bike_operate->save();
  885. //更新redis
  886. $lastLocation = LocationsLog::getNewestLocationByBikeNo($bike->bike_no);
  887. (new BikeStatusInfoSyncHandler())->toBikeOnLineStatus($bike->bike_no, $lastLocation['lng'], $lastLocation['lat']);
  888. DB::commit();
  889. return $this->ok('操作成功');
  890. } catch (\Exception $e) {
  891. DB::rollBack();
  892. Log::error($e->getMessage());
  893. return $this->error('操作失败,请联系管理员');
  894. }
  895. }
  896. /**
  897. * bikeLogout 车辆下线(不投放)
  898. *
  899. * @param Request $request
  900. * @return \Illuminate\Http\JsonResponse
  901. * @author Fx
  902. *
  903. */
  904. public function bikeLogout(Request $request)
  905. {
  906. $bike_id = $request->get('bike_id') ?? '';
  907. if (empty($bike_id)) return $this->error('参数错误');
  908. try {
  909. DB::beginTransaction();
  910. $bike = Bike::query()->find($bike_id);
  911. if (empty($bike)) return $this->error('找不到车辆');
  912. if ($bike->put_status == Bike::PUT_STATUS_NO) return $this->error('车辆已下线');
  913. // 更新车辆下线
  914. $bike->put_status = Bike::PUT_STATUS_NO;
  915. $bike->save();
  916. // 插入下线记录
  917. $worker_bike_operate = new WorkerBikeOperate();
  918. $worker_bike_operate->type = WorkerBikeOperate::TYPE_OFFLINE;
  919. $worker_bike_operate->name = WorkerBikeOperate::$typeMaps[WorkerBikeOperate::TYPE_OFFLINE];
  920. $worker_bike_operate->reason = "工作人员操作下线";
  921. $last_location = object_array(json_decode($bike->last_location));
  922. $worker_bike_operate->bike_id = $bike_id;
  923. $worker_bike_operate->latitude = empty($last_location['lat']) ? 0 : $last_location['lat'];
  924. $worker_bike_operate->longitude = empty($last_location['lng']) ? 0 : $last_location['lng'];
  925. $worker_bike_operate->worker_id = Admin::user()->id;
  926. $worker_bike_operate->save();
  927. // 更新redis
  928. (new BikeStatusInfoSyncHandler())->toBikeOffLineStatus($bike->bike_no);
  929. DB::commit();
  930. return $this->ok('操作成功');
  931. } catch (\Exception $e) {
  932. DB::rollBack();
  933. Log::error($e->getMessage());
  934. return $this->error('操作失败,请联系管理员');
  935. }
  936. }
  937. /**
  938. * bikeBell 响铃
  939. *
  940. * @param Request $request
  941. * @return \Illuminate\Http\JsonResponse
  942. * @author Fx
  943. *
  944. */
  945. public function bikeBell(Request $request)
  946. {
  947. $bike_id = $request->get('bike_id') ?? '';
  948. if (empty($bike_id)) return $this->error('参数错误');
  949. $bike = Bike::query()->find($bike_id);
  950. if (empty($bike)) return $this->error('找不到车辆');
  951. // $box_no = "003448483"; // 测试写死
  952. $box_no = $bike->box_no;
  953. $bool = (new BaseBikeControl($box_no))::bellBike();
  954. if ($bool) {
  955. return $this->ok('操作成功,请寻找响铃车辆');
  956. } else {
  957. return $this->error('操作失败,请联系管理员');
  958. }
  959. }
  960. /**
  961. * openBikeLock 开锁
  962. *
  963. * @param Request $request
  964. * @return \Illuminate\Http\JsonResponse
  965. * @author Fx
  966. *
  967. */
  968. public function openBikeLock(Request $request)
  969. {
  970. $bike_id = $request->get('bike_id') ?? '';
  971. if (empty($bike_id)) return $this->error('参数错误');
  972. $bike = Bike::query()->find($bike_id);
  973. if (empty($bike)) return $this->error('找不到车辆');
  974. // $box_no = "003448483"; // 测试写死
  975. $box_no = $bike->box_no;
  976. try {
  977. // 增加worker操作车辆记录
  978. $worker_bike_operate = new WorkerBikeOperate();
  979. $worker_bike_operate->type = WorkerBikeOperate::TYPE_OPEN_BIKE_LOCK;
  980. $worker_bike_operate->name = WorkerBikeOperate::$typeMaps[WorkerBikeOperate::TYPE_OPEN_BIKE_LOCK];
  981. $worker_bike_operate->bike_id = $bike_id;
  982. $last_location = object_array(json_decode($bike->last_location));
  983. // Log::info($last_location);
  984. $worker_bike_operate->latitude = empty($last_location['lat']) ? 0 : $last_location['lat'];
  985. $worker_bike_operate->longitude = empty($last_location['lng']) ? 0 : $last_location['lng'];
  986. $worker_bike_operate->reason = "工作人员开锁";
  987. $worker_bike_operate->worker_id = Admin::user()->id;
  988. $worker_bike_operate->save();
  989. } catch (\Exception $e) {
  990. Log::error('开锁记录生成失败');
  991. return $this->error('开锁失败,请联系管理员');
  992. }
  993. $bool = (new BaseBikeControl($box_no))::openLock();
  994. if ($bool) {
  995. // DB::beginTransaction();
  996. try {
  997. $bike->is_lock = Bike::LOCK_NO;
  998. $bike->save();
  999. AutoCloseBikeLockJob::dispatch($bike)->delay(Carbon::now()->addMinutes(config('queue.delay.autoCloseBikeLock')));
  1000. // 修改redis
  1001. $is_riding = $bike->is_riding;
  1002. if (!(bool)$is_riding) {
  1003. (new BikeStatusInfoSyncHandler())->toBikeRideStatus(BikeStatusInfoSyncHandler::ROLE_WORKER, $bike->bike_no, ['id' => Admin::user()->id, 'area_id' => $bike->put_area_id, 'bike_id' => $bike_id]);
  1004. }
  1005. /* // 更新orders redis
  1006. Redis::connection()->hset('ride_orders', $order->bike_no, serialize([
  1007. 'id' => $order->id,
  1008. 'bike_no' => $order->bike_no,
  1009. 'bike_id' => $order->bike_id,
  1010. 'area_id' => $order->area_id
  1011. ]));
  1012. DB::commit();*/
  1013. } catch (\Exception $e) {
  1014. // DB::rollBack();
  1015. Log::error('车辆状态骑行更新失败');
  1016. }
  1017. return $this->ok('操作成功,请寻找响铃车辆');
  1018. } else {
  1019. return $this->error('开锁失败,请联系管理员');
  1020. }
  1021. }
  1022. /**
  1023. * closeBikeLock 关锁
  1024. *
  1025. * @param Request $request
  1026. * @return \Illuminate\Http\JsonResponse
  1027. * @author Fx
  1028. *
  1029. */
  1030. public function closeBikeLock(Request $request)
  1031. {
  1032. $bike_id = $request->get('bike_id') ?? '';
  1033. if (empty($bike_id)) return $this->error('参数错误');
  1034. $bike = Bike::query()->find($bike_id);
  1035. if (empty($bike)) return $this->error('找不到车辆');
  1036. if ((bool)$bike->is_riding) {
  1037. return $this->error('车辆骑行中,不可关锁');
  1038. }
  1039. try {
  1040. // 增加worker操作车辆记录
  1041. $worker_bike_operate = new WorkerBikeOperate();
  1042. $worker_bike_operate->type = WorkerBikeOperate::TYPE_CLOSE_BIKE_LOCK;
  1043. $worker_bike_operate->name = WorkerBikeOperate::$typeMaps[WorkerBikeOperate::TYPE_CLOSE_BIKE_LOCK];
  1044. $worker_bike_operate->bike_id = $bike_id;
  1045. $last_location = object_array(json_decode($bike->last_location));
  1046. $worker_bike_operate->latitude = empty($last_location['lat']) ? 0 : $last_location['lat'];
  1047. $worker_bike_operate->longitude = empty($last_location['lng']) ? 0 : $last_location['lng'];
  1048. $worker_bike_operate->reason = "工作人员关锁";
  1049. $worker_bike_operate->worker_id = Admin::user()->id;
  1050. $worker_bike_operate->save();
  1051. } catch (\Exception $e) {
  1052. Log::error('关锁记录生成失败');
  1053. return $this->error('关锁失败,请联系管理员');
  1054. }
  1055. // $box_no = "003448483"; // 测试写死
  1056. $box_no = $bike->box_no;
  1057. //添加工作人员操作车辆记录
  1058. // 删除redis订单
  1059. $bike_location = LocationsLog::getNewestLocationByBikeNo($bike->bike_no);
  1060. (new BikeStatusInfoSyncHandler())->toBikeWaitRideStatus($bike->bike_no, $bike_location['lng'], $bike_location['lat'], $bike->put_status);
  1061. $bool = (new BaseBikeControl($box_no))::closeLock();
  1062. if ($bool) {
  1063. try {
  1064. // 车辆改为未骑行
  1065. // $bike->is_riding = Bike::RIDING_NO;
  1066. $bike->last_use_bike_end_time = Carbon::now();
  1067. $bike->is_lock = Bike::LOCK_YES;
  1068. $bike->save();
  1069. $lastLocation = LocationsLog::getNewestLocationByBikeNo($bike->bike_no);
  1070. // 修改redis
  1071. (new BikeStatusInfoSyncHandler())->toBikeWaitRideStatus($bike->bike_no, $lastLocation['lng'], $lastLocation['lat'], $bike->put_status);
  1072. } catch (\Exception $e) {
  1073. Log::error('车辆状态未骑行更新失败');
  1074. }
  1075. return $this->ok('操作成功');
  1076. } else {
  1077. return $this->error('操作失败,请联系管理员');
  1078. }
  1079. }
  1080. /**
  1081. * openBatteryLock 开电池锁
  1082. *
  1083. * @param Request $request
  1084. * @return \Illuminate\Http\JsonResponse
  1085. * @author Fx
  1086. *
  1087. */
  1088. public function openBatteryLock(Request $request)
  1089. {
  1090. $bike_id = $request->get('bike_id') ?? '';
  1091. if (empty($bike_id)) return $this->error('参数错误');
  1092. $bike = Bike::query()->find($bike_id);
  1093. if (empty($bike)) return $this->error('找不到车辆');
  1094. try {
  1095. // 增加worker操作车辆记录
  1096. $worker_bike_operate = new WorkerBikeOperate();
  1097. $worker_bike_operate->type = WorkerBikeOperate::TYPE_OPEN_BATTERY_LOCK;
  1098. $worker_bike_operate->name = WorkerBikeOperate::$typeMaps[WorkerBikeOperate::TYPE_OPEN_BATTERY_LOCK];
  1099. $worker_bike_operate->bike_id = $bike_id;
  1100. $last_location = object_array(json_decode($bike->last_location));
  1101. $worker_bike_operate->latitude = empty($last_location['lat']) ? 0 : $last_location['lat'];
  1102. $worker_bike_operate->longitude = empty($last_location['lng']) ? 0 : $last_location['lng'];
  1103. $worker_bike_operate->reason = "工作人员开电池锁";
  1104. $worker_bike_operate->worker_id = Admin::user()->id;
  1105. $worker_bike_operate->save();
  1106. } catch (\Exception $e) {
  1107. Log::error('开电池锁记录生成失败');
  1108. return $this->error('开电池锁失败,请联系管理员');
  1109. }
  1110. // $box_no = "003448483"; // 测试写死
  1111. $box_no = $bike->box_no;
  1112. $bool = (new BaseBikeControl($box_no))::openBatteryLock();
  1113. if ($bool) {
  1114. return $this->ok('操作开电池锁成功');
  1115. } else {
  1116. return $this->error('开电池锁失败,请联系管理员');
  1117. }
  1118. }
  1119. /**
  1120. * rebootBox 重启中控
  1121. *
  1122. * @param Request $request
  1123. * @return \Illuminate\Http\JsonResponse
  1124. * @author Fx
  1125. *
  1126. */
  1127. public function rebootBox(Request $request)
  1128. {
  1129. $bike_id = $request->get('bike_id') ?? '';
  1130. if (empty($bike_id)) return $this->error('参数错误');
  1131. $bike = Bike::query()->find($bike_id);
  1132. if (empty($bike)) return $this->error('找不到车辆');
  1133. try {
  1134. // 增加worker操作车辆记录
  1135. $worker_bike_operate = new WorkerBikeOperate();
  1136. $worker_bike_operate->type = WorkerBikeOperate::TYPE_REBOOT_BOX;
  1137. $worker_bike_operate->name = WorkerBikeOperate::$typeMaps[WorkerBikeOperate::TYPE_REBOOT_BOX];
  1138. $worker_bike_operate->bike_id = $bike_id;
  1139. $last_location = object_array(json_decode($bike->last_location));
  1140. $worker_bike_operate->latitude = empty($last_location['lat']) ? 0 : $last_location['lat'];
  1141. $worker_bike_operate->longitude = empty($last_location['lng']) ? 0 : $last_location['lng'];
  1142. $worker_bike_operate->reason = "工作人员重启中控";
  1143. $worker_bike_operate->worker_id = Admin::user()->id;
  1144. $worker_bike_operate->save();
  1145. } catch (\Exception $e) {
  1146. Log::error('工作人员重启中控失败');
  1147. return $this->error('工作人员重启中控失败,请联系管理员');
  1148. }
  1149. // $box_no = "003448483"; // 测试写死
  1150. $box_no = $bike->box_no;
  1151. $bool = (new BaseBikeControl($box_no))::rebootBox();
  1152. if ($bool) {
  1153. return $this->ok('重启中控成功');
  1154. } else {
  1155. return $this->error('重启中控失败,请联系管理员');
  1156. }
  1157. }
  1158. /**
  1159. * repairInParking 设为在停车区
  1160. *
  1161. * @param Request $request
  1162. * @return \Illuminate\Http\JsonResponse
  1163. * @author Fx
  1164. *
  1165. */
  1166. public function repairInParking(Request $request)
  1167. {
  1168. $bike_id = $request->get('bike_id') ?? '';
  1169. if (empty($bike_id)) return $this->error('参数错误');
  1170. $bike = Bike::query()->find($bike_id);
  1171. if (empty($bike)) return $this->error('找不到车辆');
  1172. try {
  1173. $bike->is_in_parking = Bike::IN_PARKING_YES;
  1174. $bike->save();
  1175. return $this->ok('操作成功');
  1176. } catch (\Exception $e) {
  1177. Log::error($e->getMessage());
  1178. return $this->error('操作失败,请联系管理员');
  1179. }
  1180. }
  1181. /**
  1182. * newBikeLocation 立即定位
  1183. *
  1184. * @param Request $request
  1185. * @return \Illuminate\Http\JsonResponse
  1186. * @author Fx
  1187. *
  1188. */
  1189. public function newBikeLocation(Request $request)
  1190. {
  1191. $bike_id = $request->get('bike_id') ?? '';
  1192. if (empty($bike_id)) return $this->error('参数错误');
  1193. $bike = Bike::query()->find($bike_id);
  1194. if (empty($bike)) return $this->error('找不到车辆');
  1195. try {
  1196. // 增加worker操作车辆记录
  1197. $worker_bike_operate = new WorkerBikeOperate();
  1198. $worker_bike_operate->type = WorkerBikeOperate::TYPE_NOW_BIKE_LOCATION;
  1199. $worker_bike_operate->name = WorkerBikeOperate::$typeMaps[WorkerBikeOperate::TYPE_NOW_BIKE_LOCATION];
  1200. $worker_bike_operate->bike_id = $bike_id;
  1201. $last_location = object_array(json_decode($bike->last_location));
  1202. $worker_bike_operate->latitude = empty($last_location['lat']) ? 0 : $last_location['lat'];
  1203. $worker_bike_operate->longitude = empty($last_location['lng']) ? 0 : $last_location['lng'];
  1204. $worker_bike_operate->reason = "工作人员立即定位车辆";
  1205. $worker_bike_operate->worker_id = Admin::user()->id;
  1206. $worker_bike_operate->save();
  1207. } catch (\Exception $e) {
  1208. Log::error('工作人员立即定位车辆失败');
  1209. return $this->error('工作人员立即定位车辆失败,请联系管理员');
  1210. }
  1211. // $box_no = "003448483"; // 测试写死
  1212. $box_no = $bike->box_no;
  1213. $bool = (new BaseBikeControl($box_no))::nowBikeLocation();
  1214. if ($bool) {
  1215. return $this->ok('立即定位车辆成功');
  1216. } else {
  1217. return $this->error('立即定位车辆失败,请联系管理员');
  1218. }
  1219. }
  1220. /**
  1221. * newBikeBatteryMSG 立即更新电池信息
  1222. *
  1223. * @param Request $request
  1224. * @return \Illuminate\Http\JsonResponse
  1225. * @author Fx
  1226. *
  1227. */
  1228. public function newBikeBatteryMSG(Request $request)
  1229. {
  1230. $bike_id = $request->get('bike_id') ?? '';
  1231. if (empty($bike_id)) return $this->error('参数错误');
  1232. $bike = Bike::query()->find($bike_id);
  1233. if (empty($bike)) return $this->error('找不到车辆');
  1234. try {
  1235. // 增加worker操作车辆记录
  1236. $worker_bike_operate = new WorkerBikeOperate();
  1237. $worker_bike_operate->type = WorkerBikeOperate::TYPE_NOW_BIKE_BATTERY_MSG;
  1238. $worker_bike_operate->name = WorkerBikeOperate::$typeMaps[WorkerBikeOperate::TYPE_NOW_BIKE_BATTERY_MSG];
  1239. $worker_bike_operate->bike_id = $bike_id;
  1240. $last_location = object_array(json_decode($bike->last_location));
  1241. $worker_bike_operate->latitude = empty($last_location['lat']) ? 0 : $last_location['lat'];
  1242. $worker_bike_operate->longitude = empty($last_location['lng']) ? 0 : $last_location['lng'];
  1243. $worker_bike_operate->reason = "工作人员立即更新电池信息";
  1244. $worker_bike_operate->worker_id = Admin::user()->id;
  1245. $worker_bike_operate->save();
  1246. } catch (\Exception $e) {
  1247. Log::error('工作人员立即更新电池信息失败');
  1248. return $this->error('工作人员立即更新电池信息失败,请联系管理员');
  1249. }
  1250. // $box_no = "003448483"; // 测试写死
  1251. $box_no = $bike->box_no;
  1252. $bool = (new BaseBikeControl($box_no))::nowBikeBatteryMSG();
  1253. if ($bool) {
  1254. return $this->ok('立即更新电池信息成功');
  1255. } else {
  1256. return $this->error('立即更新电池信息失败,请联系管理员');
  1257. }
  1258. }
  1259. /**
  1260. * closeBatteryLock 关电池锁
  1261. *
  1262. * @param Request $request
  1263. * @return \Illuminate\Http\JsonResponse
  1264. * @author Fx
  1265. *
  1266. */
  1267. public function closeBatteryLock(Request $request)
  1268. {
  1269. $bike_id = $request->get('bike_id') ?? '';
  1270. if (empty($bike_id)) return $this->error('参数错误');
  1271. $bike = Bike::query()->find($bike_id);
  1272. if (empty($bike)) return $this->error('找不到车辆');
  1273. try {
  1274. // 增加worker操作车辆记录
  1275. $worker_bike_operate = new WorkerBikeOperate();
  1276. $worker_bike_operate->type = WorkerBikeOperate::TYPE_CLOSE_BATTERY_LOCK;
  1277. $worker_bike_operate->name = WorkerBikeOperate::$typeMaps[WorkerBikeOperate::TYPE_CLOSE_BATTERY_LOCK];
  1278. $worker_bike_operate->bike_id = $bike_id;
  1279. $last_location = object_array(json_decode($bike->last_location));
  1280. $worker_bike_operate->latitude = empty($last_location['lat']) ? 0 : $last_location['lat'];
  1281. $worker_bike_operate->longitude = empty($last_location['lng']) ? 0 : $last_location['lng'];
  1282. $worker_bike_operate->reason = "工作人员开电池锁";
  1283. $worker_bike_operate->worker_id = Admin::user()->id;
  1284. $worker_bike_operate->save();
  1285. } catch (\Exception $e) {
  1286. Log::error('关电池锁记录生成失败');
  1287. return $this->error('关电池锁失败,请联系管理员');
  1288. }
  1289. // $box_no = "003448483"; // 测试写死
  1290. $box_no = $bike->box_no;
  1291. $bool = (new BaseBikeControl($box_no))::closeBatteryLock();
  1292. if ($bool) {
  1293. return $this->ok('操作关电池锁成功');
  1294. } else {
  1295. return $this->error('关电池锁失败,请联系管理员');
  1296. }
  1297. }
  1298. /**
  1299. * getKey 获取蓝牙密钥
  1300. *
  1301. * @param Request $request
  1302. * @return \Illuminate\Http\JsonResponse
  1303. * @author Fx
  1304. *
  1305. */
  1306. public function getKey(Request $request)
  1307. {
  1308. $box_no = $request->get('box_no');
  1309. $bike = Bike::where('box_no', $box_no)->first();
  1310. $key = $bike->blu_ase_key ?? '';
  1311. return $this->ok(['key' => $key]);
  1312. }
  1313. /**
  1314. * orderLocation 订单轨迹
  1315. *
  1316. * @param Request $request
  1317. * @return \Illuminate\Http\JsonResponse
  1318. * @author Fx
  1319. *
  1320. */
  1321. public function getLocationByBikeNoAndTime(Request $request)
  1322. {
  1323. // $order_id = $request->get('order_id') ?? '';
  1324. $bike_no = $request->get('bike_no') ?? '';
  1325. $time_between = $request->get('time_between') ?? []; // time_between 时间区间
  1326. if (empty($bike_no) || empty($time_between)) return $this->error('参数错误');
  1327. // if (empty($order_id)) return $this->error('参数错误');
  1328. $orderLocations = [];
  1329. $locationsTimes = [];
  1330. try {
  1331. $locationsLog = LocationsLog::where('bike_no', $bike_no)
  1332. ->where('created_at', '>=', Carbon::parse($time_between[0])->toDateString())
  1333. ->where('created_at', '<=', Carbon::parse($time_between[1])->toDateString())
  1334. ->whereBetween('latitude', [3, 53])->whereBetween('longitude', [73, 136])->orderBy('created_at', 'asc')
  1335. ->get();
  1336. // $locationsLog = LocationsLog::query()
  1337. // ->where('order_id', (int)$order_id)
  1338. // ->where('is_rent', LocationsLog::RENT_NO)
  1339. // ->whereBetween('latitude', [3, 53])
  1340. // ->whereBetween('longitude', [73, 136])
  1341. // ->orderBy('created_at', 'asc')->get();
  1342. } catch (\Exception $exception) {
  1343. Log::info($exception->getMessage());
  1344. }
  1345. if (!empty($locationsLog)) {
  1346. // foreach ($locationsLog as $vv) {
  1347. // $orderLocations[] = [$vv->longitude, $vv->latitude];
  1348. // $locationsTimes[] = Carbon::parse($vv->created_at)->format('Y-m-d H:i:s');
  1349. // }
  1350. $data = [];
  1351. $dataTimes = [];
  1352. $userLocation = [];
  1353. $workerLocation = [];
  1354. $noLocatioin = [];
  1355. $old_type = '';
  1356. $item = [];
  1357. $timesData = [];
  1358. $Locations = [];
  1359. foreach ($locationsLog as $v) {
  1360. $data[] = [$v->longitude, $v->latitude];
  1361. $dataTimes[] = Carbon::parse($v->created_at)->format('Y-m-d H:i:s');
  1362. if (empty($old_type)) {
  1363. $old_type = $v->type;
  1364. }
  1365. if ($v->type !== $old_type) {
  1366. if ($old_type == LocationsLog::USER_LOCATION) {
  1367. $userLocation[] = ['locations' => $item, 'times' => $timesData];
  1368. $Locations[] = ['data' => ['locations' => $item, 'times' => $timesData], 'role' => LocationsLog::USER_LOCATION];
  1369. } else if ($old_type == LocationsLog::WORKER_LOCATION) {
  1370. $workerLocation[] = ['locations' => $item, 'times' => $timesData];
  1371. $Locations[] = ['data' => ['locations' => $item, 'times' => $timesData], 'role' => LocationsLog::WORKER_LOCATION];
  1372. } else {
  1373. $noLocatioin[] = ['locations' => $item, 'times' => $timesData];
  1374. $Locations[] = ['data' => ['locations' => $item, 'times' => $timesData], 'role' => LocationsLog::NO_LOCATION];
  1375. }
  1376. $old_type = '';
  1377. $item = [];
  1378. $timesData = [];
  1379. $item[] = [$v->longitude, $v->latitude];
  1380. $timesData[] = Carbon::parse($v->created_at)->format('Y-m-d H:i:s');
  1381. } else {
  1382. $item[] = [$v->longitude, $v->latitude];
  1383. $timesData[] = Carbon::parse($v->created_at)->format('Y-m-d H:i:s');
  1384. }
  1385. unset($v->_id);
  1386. }
  1387. }
  1388. if (empty($data)) return $this->ok($data);
  1389. $wx_data = $locationsLog->toArray();
  1390. $res = [
  1391. 'locations' => $data,
  1392. 'locationsTimes' => $dataTimes,
  1393. 'start_location' => $data[0],
  1394. 'end_location' => end($data),
  1395. 'wx_locations' => $wx_data,
  1396. 'wx_start_location' => $wx_data[0],
  1397. 'wx_end_location' => end($wx_data),
  1398. 'user_location' => $userLocation,
  1399. 'worker_location' => $workerLocation,
  1400. 'no_locatioin' => $noLocatioin,
  1401. 'all_locations' => $Locations
  1402. ];
  1403. return $this->ok($res);
  1404. }
  1405. }