BikeController.php 64 KB

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