From 6358e9a13bc8521bb4df8f4868d87ee73449a145 Mon Sep 17 00:00:00 2001 From: wanghongjun <1445693971@qq.com> Date: Tue, 9 Jun 2026 14:04:05 +0800 Subject: [PATCH] =?UTF-8?q?=E9=97=B8=E6=9C=BA=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Admin/ParkingGateControlController.php | 153 ++++++++++++++++++ .../Admin/ProhibitedPassageController.php | 119 ++++++++++++++ app/Models/ParkingChannel.php | 11 ++ app/Models/ParkingGateControl.php | 41 +++++ app/Models/ParkingProhibitedPassage.php | 35 ++++ app/Services/ParkingGateControlService.php | 58 +++++++ app/Services/ParkingSpaceRepairService.php | 2 +- app/Services/ProhibitedPassageService.php | 44 +++++ app/common.php | 8 +- ...3449_create_parking_gate_control_table.php | 40 +++++ ...reate_parking_prohibited_passage_table.php | 35 ++++ database/seeders/AdminMenuSeeder.php | 14 ++ resources/lang/en/menu.php | 2 + resources/lang/en/service.php | 9 ++ resources/lang/zh-CN/menu.php | 2 + resources/lang/zh-CN/service.php | 9 ++ resources/lang/zh-TW/menu.php | 2 + resources/lang/zh-TW/service.php | 9 ++ routes/admin/api.php | 11 +- 19 files changed, 597 insertions(+), 7 deletions(-) create mode 100644 app/Http/Controllers/Admin/ParkingGateControlController.php create mode 100644 app/Http/Controllers/Admin/ProhibitedPassageController.php create mode 100644 app/Models/ParkingGateControl.php create mode 100644 app/Models/ParkingProhibitedPassage.php create mode 100644 app/Services/ParkingGateControlService.php create mode 100644 app/Services/ProhibitedPassageService.php create mode 100644 database/migrations/2026_06_09_143449_create_parking_gate_control_table.php create mode 100644 database/migrations/2026_06_09_143449_create_parking_prohibited_passage_table.php diff --git a/app/Http/Controllers/Admin/ParkingGateControlController.php b/app/Http/Controllers/Admin/ParkingGateControlController.php new file mode 100644 index 0000000..fc8facf --- /dev/null +++ b/app/Http/Controllers/Admin/ParkingGateControlController.php @@ -0,0 +1,153 @@ +service = $service; + } + + /** + * @param Request $request + * @return JsonResponse + */ + public function index(Request $request): JsonResponse + { + try { + $query = ParkingGateControl::query(); + + if ($request->has('license_plate')) { + $license_plate = $request->input('license_plate'); + if ($license_plate) { + $license_plate_id = ParkingLicensePlate::getValueId( + $license_plate + ); + if ($license_plate_id) { + $query->where('license_plate_id', $license_plate_id); + } else { + $query->where('id', 0); + } + } + } + + if ($request->has('member_type')) { + $member_type = $request->input('member_type'); + if ($member_type) { + $query->where('member_type', $member_type); + } + } + + if ($request->has('enter_at')) { + $enter_at = $request->input('enter_at'); + if ($enter_at) { + $query->where('enter_at', '>=', $enter_at); + } + } + + if ($request->has('leave_at')) { + $leave_at = $request->input('leave_at'); + if ($leave_at) { + $query->where('leave_at', '<=', $leave_at); + } + } + + if ($request->has('customer_id')) { + $customer_id = $request->input('customer_id'); + if ($customer_id) { + $query->where('customer_id', $customer_id); + } + } + + if ($request->has('member_id')) { + $member_id = $request->input('member_id'); + if ($member_id) { + $query->where('member_id', $member_id); + } + } + + // 分页 + $page = $request->input('page', 1); + $perPage = $request->input('per_page', 10); + + $total = $query->count(); + $items = $query->latest()->forPage($page, $perPage)->get()->each( + function ($item) { + return $this->service->getItem($item); + } + ); + + return $this->responseService->success([ + 'items' => $items, + 'total' => $total, + 'page' => $page, + 'per_page' => $perPage, + 'last_page' => ceil($total / $perPage), + ]); + } catch (Exception $e) { + $m_prefix = __('exception.exception_handler.resource'); + return $this->responseService->systemError( + $m_prefix . ':' . $e->getMessage() + ); + } + } + + /** + * 列表搜索数据 + * @return JsonResponse + */ + public function search(): JsonResponse + { + try { + $data = [ + 'member_type_list' => ParkingSpaceType::getData() + ]; + return $this->responseService->success($data); + } catch (Exception $e) { + $m_prefix = __('exception.exception_handler.resource'); + return $this->responseService->systemError( + $m_prefix . ':' . $e->getMessage() + ); + } + } + + public function show(string $id): JsonResponse + { + try { + $data = ParkingGateControl::query()->find($id); + return $this->responseService->success($this->service->getItem($data)); + } catch (Exception $e) { + return $this->responseService->systemError( + __('exception.get_data_failed') . ':' . $e->getMessage() + ); + } + } + + +} diff --git a/app/Http/Controllers/Admin/ProhibitedPassageController.php b/app/Http/Controllers/Admin/ProhibitedPassageController.php new file mode 100644 index 0000000..57e46c7 --- /dev/null +++ b/app/Http/Controllers/Admin/ProhibitedPassageController.php @@ -0,0 +1,119 @@ +service = $service; + } + + /** + * @param Request $request + * @return JsonResponse + */ + public function index(Request $request): JsonResponse + { + try { + $query = ParkingProhibitedPassage::query(); + + if ($request->has('license_plate')) { + $license_plate = $request->input('license_plate'); + if ($license_plate) { + $license_plate_id = ParkingLicensePlate::getValueId( + $license_plate + ); + if ($license_plate_id) { + $query->where('license_plate_id', $license_plate_id); + } else { + $query->where('id', 0); + } + } + } + + if ($request->has('parking_id')) { + $parking_id = $request->input('parking_id'); + if ($parking_id) { + $query->where('parking_id', $parking_id); + } + } + + if ($request->has('start_date')) { + $start_date = $request->input('start_date'); + if ($start_date) { + $query->where( + 'identify_at', + '>=', + $start_date . ' 00:00:00' + ); + } + } + + if ($request->has('end_date')) { + $end_date = $request->input('end_date'); + if ($end_date) { + $query->where('identify_at', '<=', $end_date . ' 23:59:59'); + } + } + $typeArr = $this->service->getType(); + $remarkArr = $this->service->getRemark(); + // 分页 + $page = $request->input('page', 1); + $perPage = $request->input('per_page', 10); + + $total = $query->count(); + $items = $query->latest()->forPage($page, $perPage)->get()->each( + function ($item) use ($typeArr, $remarkArr) { + $item['license_plate'] = ParkingLicensePlate::getNumber( + $item['license_plate_id'] + ); + $item['parking'] = Parking::getName($item['parking_id']); + $item['type_str'] = $typeArr[$item['type']]; + $item['remark'] = $remarkArr[$item['remark']]; + $item['snapshot_img'] = get_image_url($item['snapshot_img']); + unset($item['parking_id'], $item['license_plate_id']); + return $item; + } + ); + + return $this->responseService->success([ + 'items' => $items, + 'total' => $total, + 'page' => $page, + 'per_page' => $perPage, + 'last_page' => ceil($total / $perPage), + ]); + } catch (Exception $e) { + $m_prefix = __('exception.exception_handler.resource'); + return $this->responseService->systemError( + $m_prefix . ':' . $e->getMessage() + ); + } + } + +} diff --git a/app/Models/ParkingChannel.php b/app/Models/ParkingChannel.php index afeab5a..33112f2 100644 --- a/app/Models/ParkingChannel.php +++ b/app/Models/ParkingChannel.php @@ -82,4 +82,15 @@ class ParkingChannel extends Model { return $value ? date("Y-m-d H:i:s", strtotime($value)) : $value; } + + public static function getFirst($id) + { + $item = self::query()->where('id', $id)->first(); + $item['name'] = AdminTranslationService::getTranslationTypeName( + $id, + 6, + $item['name'] + ); + return $item; + } } diff --git a/app/Models/ParkingGateControl.php b/app/Models/ParkingGateControl.php new file mode 100644 index 0000000..a1f4e9d --- /dev/null +++ b/app/Models/ParkingGateControl.php @@ -0,0 +1,41 @@ + 'automatic', + 2 => 'manual' + ]; + + /** + * @return array|string[] + */ + public function getType(): array + { + $typeArr = self::$typeArr; + foreach ($typeArr as $key => $value) { + $typeArr[$key] = __service($this->menuTitle . '.' . $value); + } + return $typeArr; + } + + public function getItem($item) + { + $typeArr = $this->getType(); + $date = date("Y-m-d", strtotime($item['enter_at'])); + $item['reserve_id'] = ParkingReservation::query()->where( + 'license_plate_id', + $item['license_plate_id'] + )->where('date', $date)->value('reserve_id'); + $item['member_type'] = ParkingSpaceType::getName($item['member_type']); + $item['license_plate'] = ParkingLicensePlate::getNumber($item['license_plate_id']); + $ParkingChannel = ParkingChannel::getFirst($item['channel_id']); + $item['channel'] = ''; + $item['parking'] = ''; + if ($ParkingChannel) { + $item['channel'] = $ParkingChannel['name']; + $item['parking'] = Parking::getName($ParkingChannel['parking_id']); + } + $item['enter_type_str'] = $typeArr[$item['enter_type']]; + $item['leave_type_str'] = $typeArr[$item['leave_type']] ?? ''; + $item['dwell_time'] = get_time_difference_str($item['enter_at'], $item['leave_at']); + + $item['enter_img'] = get_image_url($item['enter_img']); + $item['leave_img'] = get_image_url($item['leave_img']); + unset($item['license_plate_id'], $item['channel_id']); + return $item; + } +} diff --git a/app/Services/ParkingSpaceRepairService.php b/app/Services/ParkingSpaceRepairService.php index 49018ca..ab95ac5 100644 --- a/app/Services/ParkingSpaceRepairService.php +++ b/app/Services/ParkingSpaceRepairService.php @@ -24,7 +24,7 @@ class ParkingSpaceRepairService extends BaseService { $ParkingSpace = ParkingSpace::query()->find($item['space_id']); $item['parking_space_number'] = $ParkingSpace['number']; - $Floor = AdminFloor::query()->find($ParkingSpace['floor_id']); + $Floor = AdminFloor::getFirst($ParkingSpace['floor_id']); $item['floor'] = $Floor['name']; $item['parking'] = Parking::getName($Floor['building_floor']); $item['admin_user'] = AdminUsers::getUsername($item['admin_user_id']); diff --git a/app/Services/ProhibitedPassageService.php b/app/Services/ProhibitedPassageService.php new file mode 100644 index 0000000..cc37e5d --- /dev/null +++ b/app/Services/ProhibitedPassageService.php @@ -0,0 +1,44 @@ + 'entrance', + 2 => 'export' + ]; + + public array $remarkArr = [ + 1 => 'remark1', + 2 => 'remark2', + 3 => 'remark3' + ]; + + /** + * @return array|string[] + */ + public function getType(): array + { + $typeArr = $this->typeArr; + foreach ($typeArr as $key => $value) { + $typeArr[$key] = __service('channel_management.' . $value); + } + return $typeArr; + } + + /** + * @return array|string[] + */ + public function getRemark(): array + { + $typeArr = $this->remarkArr; + foreach ($typeArr as $key => $value) { + $typeArr[$key] = __service($this->menuTitle . '.' . $value); + } + return $typeArr; + } + +} diff --git a/app/common.php b/app/common.php index fff5b77..8b1c544 100644 --- a/app/common.php +++ b/app/common.php @@ -111,11 +111,11 @@ if (!function_exists('get_ratio')) { } if (!function_exists('get_time_difference')) { - function get_time_difference(string $targetTime): array + function get_time_difference(string $targetTime, string $now_date = ''): array { try { $target = new DateTime($targetTime); - $now = new DateTime(); + $now = $now_date ? new DateTime($now_date) : new DateTime(); // 计算差值 $interval = $now->diff($target); @@ -152,10 +152,10 @@ if (!function_exists('get_time_difference')) { } if (!function_exists('get_time_difference_str')) { - function get_time_difference_str($date): string + function get_time_difference_str($date, $now_date = ''): string { $value = ''; - $difference = get_time_difference($date); + $difference = get_time_difference($date, $now_date); if (!isset($difference['error'])) { if (!empty($difference['days'])) { $value .= $difference['days'] . __('controller.parking_space.days'); diff --git a/database/migrations/2026_06_09_143449_create_parking_gate_control_table.php b/database/migrations/2026_06_09_143449_create_parking_gate_control_table.php new file mode 100644 index 0000000..519b1af --- /dev/null +++ b/database/migrations/2026_06_09_143449_create_parking_gate_control_table.php @@ -0,0 +1,40 @@ +id(); + $table->integer('license_plate_id')->comment('车牌号码'); + $table->integer('channel_id')->comment('入场通道'); + $table->timestamp('enter_at')->comment('入场时间'); + $table->timestamp('leave_at')->nullable()->comment('出场时间'); + $table->tinyInteger('enter_type')->default(1)->comment('入场类型'); + $table->tinyInteger('leave_type')->default(0)->comment('出场类型'); + $table->string('enter_img', 255)->default('')->comment('入场图片'); + $table->string('leave_img', 255)->default('')->comment('出场图片'); + $table->integer('member_type')->default(0)->comment('客户类型'); + $table->string('customer_id', 50)->default('')->comment('客户id'); + $table->string('member_id', 50)->default('')->comment('会员id'); + $table->timestamps(); + $table->innoDb(); + $table->comment('停车场闸机进出记录'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('parking_gate_control'); + } +}; diff --git a/database/migrations/2026_06_09_143449_create_parking_prohibited_passage_table.php b/database/migrations/2026_06_09_143449_create_parking_prohibited_passage_table.php new file mode 100644 index 0000000..00f6960 --- /dev/null +++ b/database/migrations/2026_06_09_143449_create_parking_prohibited_passage_table.php @@ -0,0 +1,35 @@ +id(); + $table->integer('license_plate_id')->comment('车牌号码'); + $table->integer('parking_id')->comment('停车场'); + $table->tinyInteger('type')->default(1)->comment('1 进/ 2 出'); + $table->timestamp('identify_at')->comment('识别时间'); + $table->tinyInteger('remark')->default(1)->comment('原因'); + $table->string('snapshot_img', 255)->default('')->comment('抓拍图片'); + $table->timestamps(); + $table->innoDb(); + $table->comment('违禁通行记录'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('parking_prohibited_passage'); + } +}; diff --git a/database/seeders/AdminMenuSeeder.php b/database/seeders/AdminMenuSeeder.php index e7216ca..7dc70f4 100644 --- a/database/seeders/AdminMenuSeeder.php +++ b/database/seeders/AdminMenuSeeder.php @@ -283,6 +283,20 @@ class AdminMenuSeeder extends Seeder 'child' => [ 'read_only' => '' ] + ], + 'gate_control' => [ + 'uri' => 'gateControl', + 'page_uri' => '/gate/gateControl', + 'child' => [ + 'read_only' => 'gateControl.index' + ] + ], + 'prohibited_passage' => [ + 'uri' => 'prohibitedPassage', + 'page_uri' => '/prohibitedPassage/Lanevideo', + 'child' => [ + 'read_only' => 'prohibitedPassage.index' + ] ] ], 'statistics_report' => [ diff --git a/resources/lang/en/menu.php b/resources/lang/en/menu.php index 2a4b862..2e84c0c 100644 --- a/resources/lang/en/menu.php +++ b/resources/lang/en/menu.php @@ -96,4 +96,6 @@ return [ 'abnormal_ignore' => 'Ignore exceptions', 'allocation' => 'allocation', 'edit_remark' => "Editor's note", + 'gate_control' => 'Gate control', + 'prohibited_passage' => 'Record of prohibited passage' ]; diff --git a/resources/lang/en/service.php b/resources/lang/en/service.php index fc735d6..828cd6b 100644 --- a/resources/lang/en/service.php +++ b/resources/lang/en/service.php @@ -166,5 +166,14 @@ return [ 'parking_repair_list' => [ 'not_synced' => 'Not synced', 'synced' => 'Synchronized' + ], + 'gate_control' => [ + 'automatic' => 'Automatic entry', + 'manual' => 'Manual entry' + ], + 'prohibited_passage' => [ + 'remark1' => 'No appointment, no entry allowed', + 'remark2' => 'Blacklisted vehicles are prohibited from leaving the premises', + 'remark3' => 'Appointment timed out and did not show up' ] ]; diff --git a/resources/lang/zh-CN/menu.php b/resources/lang/zh-CN/menu.php index 687ca22..d7ecec5 100644 --- a/resources/lang/zh-CN/menu.php +++ b/resources/lang/zh-CN/menu.php @@ -96,4 +96,6 @@ return [ 'abnormal_ignore' => '忽略异常', 'allocation' => '分配', 'edit_remark' => '编辑备注', + 'gate_control' => '闸机控制', + 'prohibited_passage' => '违禁通行记录' ]; diff --git a/resources/lang/zh-CN/service.php b/resources/lang/zh-CN/service.php index 8868b1b..f2d93d0 100644 --- a/resources/lang/zh-CN/service.php +++ b/resources/lang/zh-CN/service.php @@ -166,5 +166,14 @@ return [ 'parking_repair_list' => [ 'not_synced' => '未同步', 'synced' => '已同步' + ], + 'gate_control' => [ + 'automatic' => '自动入场', + 'manual' => '手动入场' + ], + 'prohibited_passage' => [ + 'remark1' => '无预约,不可进场', + 'remark2' => '黑名单车辆禁止离场', + 'remark3' => '预约超时未到场' ] ]; diff --git a/resources/lang/zh-TW/menu.php b/resources/lang/zh-TW/menu.php index 9543e0e..5b6e406 100644 --- a/resources/lang/zh-TW/menu.php +++ b/resources/lang/zh-TW/menu.php @@ -96,4 +96,6 @@ return [ 'abnormal_ignore' => '忽略异常', 'allocation' => '分配', 'edit_remark' => '編輯備註', + 'gate_control' => '閘機控制', + 'prohibited_passage' => '違禁通行記錄' ]; diff --git a/resources/lang/zh-TW/service.php b/resources/lang/zh-TW/service.php index fcee6d5..914d0e8 100644 --- a/resources/lang/zh-TW/service.php +++ b/resources/lang/zh-TW/service.php @@ -166,5 +166,14 @@ return [ 'parking_repair_list' => [ 'not_synced' => '未同步', 'synced' => '已同步' + ], + 'gate_control' => [ + 'automatic' => '自動入場', + 'manual' => '手動入場' + ], + 'prohibited_passage' => [ + 'remark1' => '無預約,不可進場', + 'remark2' => '黑名單車輛禁止離場', + 'remark3' => '預約超時未到場' ] ]; diff --git a/routes/admin/api.php b/routes/admin/api.php index 47dc5ef..9366e31 100644 --- a/routes/admin/api.php +++ b/routes/admin/api.php @@ -40,6 +40,8 @@ use App\Http\Controllers\Admin\ParkingWhitelistController; use App\Http\Controllers\Admin\ParkingAbnormalController; use App\Http\Controllers\Admin\ParkingAlarmInformationController; use App\Http\Controllers\Admin\ParkingSpaceRepairController; +use App\Http\Controllers\Admin\ParkingGateControlController; +use App\Http\Controllers\Admin\ProhibitedPassageController; Route::group(['prefix' => 'admin'], function () { @@ -201,7 +203,7 @@ Route::group(['prefix' => 'admin'], function () { Route::get('/notice/setting', [NoticeController::class, 'create']); Route::post('/notice/setting', [NoticeController::class, 'setting']); Route::get('/notice/show/{id}', [NoticeController::class, 'show']); - // 异常占用 + // 告警信息管理 Route::get('/alarmInformation', [ParkingAlarmInformationController::class, 'index']); Route::get('/alarmInformation/search', [ParkingAlarmInformationController::class, 'search']); Route::get('/alarmInformation/show/{id}', [ParkingAlarmInformationController::class, 'show']); @@ -233,7 +235,12 @@ Route::group(['prefix' => 'admin'], function () { Route::put('/parkingCamera/{id}', [ParkingCameraController::class, 'update']); Route::delete('/parkingCamera/{id}', [ParkingCameraController::class, 'destroy']); Route::get('/parkingCamera/rule', [ParkingCameraController::class, 'rule']); - + // 闸机控制 + Route::get('/gateControl', [ParkingGateControlController::class, 'index']); + Route::get('/gateControl/search', [ParkingGateControlController::class, 'search']); + Route::get('/gateControl/show/{id}', [ParkingGateControlController::class, 'show']); + // 违禁通行记录 + Route::get('/prohibitedPassage', [ProhibitedPassageController::class, 'index']); // 系统总配置 Route::get('/config/index', [ConfigController::class, 'index']); Route::put('/config/{id}', [ConfigController::class, 'update']);