diff --git a/app/Exports/ParkingWhitelistExport.php b/app/Exports/ParkingWhitelistExport.php new file mode 100644 index 0000000..fd34517 --- /dev/null +++ b/app/Exports/ParkingWhitelistExport.php @@ -0,0 +1,54 @@ +toArray(); + $index = 1; + foreach ($list as $item) { + $item = ParkingWhitelistService::getItemData($item); + $data[] = [ + $index, + $item['license_plate'], + $item['parking'], + $item['channel_str'], + $item['reason'], + $item['member_type_str'], + $item['admin_username'], + $item['created_at'] + ]; + $index += 1; + } + return $data; + } + + /** + * @return array + */ + public function headings(): array + { + return [ + __exports('global.index'), + __exports('parking_space.license_plate'), + __exports('whitelist.parking'), + __exports('whitelist.channel'), + __exports('whitelist.reason'), + __exports('whitelist.member_type'), + __exports('operation_log.operation_name'), + __exports('operation_log.created_at') + ]; + } +} diff --git a/app/Exports/ParkingWhitelistTemplateExport.php b/app/Exports/ParkingWhitelistTemplateExport.php new file mode 100644 index 0000000..48f6f5e --- /dev/null +++ b/app/Exports/ParkingWhitelistTemplateExport.php @@ -0,0 +1,47 @@ +service = $service; + } + + /** + * @param Request $request + * @return JsonResponse + */ + public function index(Request $request): JsonResponse + { + try { + $query = ParkingWhitelist::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); + } + } + } + + // 分页 + $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 create(): JsonResponse + { + try { + $data = [ + 'parking_list' => Parking::getData(), + 'member_type_list' => ParkingSpaceType::getData(), + 'channel_list' => ParkingChannel::getData() + ]; + return $this->responseService->success($data); + } catch (Exception $e) { + return $this->responseService->systemError( + __('exception.get_data_failed') . ':' . $e->getMessage() + ); + } + } + + /** + * @param string $id + * @return JsonResponse + */ + public function edit(string $id): JsonResponse + { + try { + $this->validateId($id, ParkingWhitelist::class); + $data = [ + 'parking_list' => Parking::getData(), + 'member_type_list' => ParkingSpaceType::getData(), + 'channel_list' => ParkingChannel::getData() + ]; + $item = ParkingWhitelist::query()->find($id); + $item['license_plate'] = ParkingLicensePlate::getNumber( + $item['license_plate_id'] + ); + unset( + $item['license_plate_id'], + $item['admin_user_id'], + $item['created_at'], + $item['status'] + ); + $data['item'] = $item; + return $this->responseService->success($data); + } catch (Exception $e) { + return $this->responseService->systemError( + __('exception.get_data_failed') . ':' . $e->getMessage() + ); + } + } + + /** + * @param Request $request + * @param string $id + * @return JsonResponse + * @throws CustomException + * @throws ValidationException + */ + public function update(Request $request, string $id): JsonResponse + { + try { + $data = $request->all(); + $this->saveValidator($data, $id); + $data['admin_user_id'] = $this->adminUserId; + $this->service->updateModel($data, $id); + return $this->responseService->success( + null, + __('admin.update_succeeded') + ); + } catch (ValidationException|CustomException $e) { + throw $e; + } catch (Exception $e) { + return $this->responseService->systemError( + __('admin.operation_failed') . ':' + . $e->getMessage() + ); + } + } + + /** + * @param array $data + * @param int $id + * @return void + * @throws ValidationException + */ + protected function saveValidator(array $data, int $id = 0): void + { + $rules = [ + 'license_plate' => 'required', + 'parking_id' => 'required', + 'reason' => 'required', + 'channel_ids' => 'required|array' + ]; + $messages = [ + 'license_plate.required' => __( + 'validation.channel_management.l_empty' + ), + 'parking_id.required' => __( + 'validation.channel_management.pa_empty' + ), + 'reason.required' => __( + 'validation.channel_management.n_empty' + ), + 'channel_ids.required' => __( + 'validation.channel_permissions.c_empty' + ), + 'channel_ids.array' => __( + 'validation.channel_permissions.c_array' + ) + ]; + if ($id) { + $this->validateId($id, ParkingChannel::class); + } + $validator = Validator::make($data, $rules, $messages); + + if ($validator->fails()) { + throw new ValidationException($validator); + } + } + + /** + * @param string $id + * @return JsonResponse + * @throws CustomException + * @throws ValidationException + */ + public function destroy(string $id): JsonResponse + { + try { + $this->validateId($id, ParkingWhitelist::class); + $this->service->deleteModel($id); + return $this->responseService->success( + null, + __('admin.delete_succeeded') + ); + } catch (ValidationException|CustomException $e) { + throw $e; + } catch (Exception $e) { + return $this->responseService->systemError( + __('admin.operation_failed') . ':' + . $e->getMessage() + ); + } + } + + public function downloadTemplate() + { + return Excel::download( + new ParkingWhitelistTemplateExport(), + set_space_underline(__exports('whitelist.list')) + . get_datetime('date_') + . '.xlsx' + ); + } + + public function batchImport(Request $request) + { + try { + // 1. 验证上传的文件 + $data = $request->all(); + $validator = Validator::make($data, [ + 'file' => 'required|mimes:xlsx,xls,csv,txt|max:2048' + ], [ + 'file.required' => __validation('admin_list_vip.file_empty'), + 'file.mimes' => __validation('admin_list_vip.file_mimes'), + 'file.max' => __validation('admin_list_vip.file_max') + ]); + if ($validator->fails()) { + throw new ValidationException($validator); + } + + // 2. 获取上传的文件 + $file = $request->file('file'); + + // 3. 正确的做法:先存储文件,再获取绝对路径进行导入 + $path = $file->store('imports'); + + // 4. 执行导入(使用存储后的绝对路径) + // storage_path('app') 获取 storage/app 的绝对路径 + Excel::import( + new ParkingWhitelistImport($this->adminUserId), + storage_path('app/' . $path) + ); + + // 5. (可选)导入完成后删除临时文件 + Storage::delete($path); + + return $this->responseService->success( + __('controller.import.success') + ); + } catch (ValidationException $e) { + throw $e; + } catch (Exception $e) { + return $this->responseService->systemError( + __('exception.admin_vip_list.import_failed') . ':' + . $e->getMessage() + ); + } + } + + /** + * @param Request $request + * @return JsonResponse + * @throws CustomException + * @throws ValidationException + */ + public function store(Request $request): JsonResponse + { + try { + $data = $request->all(); + $this->saveValidator($data); + $data['admin_user_id'] = $this->adminUserId; + $this->service->createModel($data); + return $this->responseService->success( + null, + __('admin.save_succeeded') + ); + } catch (ValidationException|CustomException $e) { + throw $e; + } catch (Exception $e) { + return $this->responseService->systemError( + __('admin.operation_failed') . ':' + . $e->getMessage() + ); + } + } + + public function export() + { + return Excel::download( + new ParkingWhitelistExport(), + set_space_underline(__exports('whitelist.export_list')) + . get_datetime('date_') + . '.xlsx' + ); + } +} diff --git a/app/Imports/ParkingWhitelistImport.php b/app/Imports/ParkingWhitelistImport.php new file mode 100644 index 0000000..660253e --- /dev/null +++ b/app/Imports/ParkingWhitelistImport.php @@ -0,0 +1,77 @@ +user_id = $admin_user_id; + } + + public function model(array $row) + { + if ($this->index == 1) { + $this->index += 1; + return; + } + $license_plate = $row[1]; + if (empty($license_plate)) { + return; + } + $parking_name = $row[2]; + if (empty($parking_name)) { + return; + } + $parking_id = Parking::getValueId($parking_name); + if (empty($parking_id)) { + return; + } + $channel_name = $row[3]; + if (empty($channel_name)) { + return; + } + $channel_arr = explode(',', $channel_name); + $channelIds = ParkingChannel::query()->whereIn('name', $channel_arr)->pluck('id')->toArray(); + if (empty($channelIds)) { + return; + } + $reason = $row[4]; + if (empty($reason)) { + return; + } + $type_str = $row[5]; + $space_type_id = 0; + if (!empty($type_str)) { + $space_type_id = ParkingSpaceType::getValueId($type_str); + } + + $data = [ + 'license_plate' => $license_plate, + 'parking_id' => $parking_id, + 'reason' => $reason, + 'channel_ids' => $channelIds, + 'admin_user_id' => $this->user_id, + 'member_type' => $space_type_id + ]; + + $service = new ParkingWhitelistService(new OperationLogService()); + $service->createModel($data); + $this->index += 1; + } + + public function chunkSize(): int + { + return 1000; // 设置每次处理的行数,有助于避免内存问题并可能改善表头解析 + } +} diff --git a/app/Models/Parking.php b/app/Models/Parking.php index 727fde7..52acd60 100644 --- a/app/Models/Parking.php +++ b/app/Models/Parking.php @@ -48,9 +48,9 @@ class Parking extends Model return ''; } - public static function getValueId($number) + public static function getValueId($name) { - return self::query()->where('number', $number)->value('id') ?? ''; + return self::query()->where('name', $name)->value('id') ?? ''; } public static function getData() diff --git a/app/Models/ParkingWhitelist.php b/app/Models/ParkingWhitelist.php new file mode 100644 index 0000000..42c0b63 --- /dev/null +++ b/app/Models/ParkingWhitelist.php @@ -0,0 +1,41 @@ +createNumber($data['number'], $data['space_type_id']); + } + + public function createNumber($number, $space_type_id = 0) + { $model = ParkingLicensePlate::query()->create([ - 'number' => $data['number'], - 'space_type_id' => $data['space_type_id'], + 'number' => $number, + 'space_type_id' => $space_type_id, 'created_at' => get_datetime() ]); $this->logService->logCreated($model, 'license_plate.create'); return $model; } + public function saveNumber($number) + { + $id = ParkingLicensePlate::getValueId($number); + if (!$id) { + $model = $this->createNumber($number); + $id = $model->id; + } + return $id; + } + /** * @param array $data * @param int $id diff --git a/app/Services/ParkingWhitelistService.php b/app/Services/ParkingWhitelistService.php new file mode 100644 index 0000000..efa9d9d --- /dev/null +++ b/app/Services/ParkingWhitelistService.php @@ -0,0 +1,176 @@ +getItem($item); + } + + public function getItem($item) + { + $item['license_plate'] = ParkingLicensePlate::getNumber( + $item['license_plate_id'] + ); + $item['parking'] = Parking::getName($item['parking_id']); + $channel_list = ParkingChannel::getChannelData( + $item['channel_ids'] + ); + $item['channel_str'] = ''; + if ($channel_list) { + $channel_arr = array_column((array)$channel_list, 'name'); + $item['channel_str'] = implode(',', $channel_arr); + } + $item['member_type_str'] + = ParkingSpaceType::getName($item['member_type']); + $item['admin_username'] = AdminUsers::getUsername( + $item['admin_user_id'] + ); + unset( + $item['license_plate_id'], + $item['parking_id'], + $item['channel_ids'], + $item['member_type'], + $item['admin_user_id'], + $item['status'] + ); + return $item; + } + + /** + * @param array $data + * @throws Exception + */ + public function createModel(array $data) + { + try { + DB::beginTransaction(); + + $license_plate = $data['license_plate']; + $LicensePlate = new ParkingLicensePlateService($this->logService); + $license_plate_id = $LicensePlate->saveNumber($license_plate); + + $existsWhere = [ + ['license_plate_id', '=', $license_plate_id] + ]; + if (ParkingWhitelist::query()->where($existsWhere)->exists()) { + throw new Exception( + __service($this->menuTitle . '.number_exists') + ); + } + + $channel_ids = implode(',', $data['channel_ids']); + $model = ParkingWhitelist::query()->create([ + 'license_plate_id' => $license_plate_id, + 'parking_id' => $data['parking_id'], + 'member_type' => $data['member_type'] ?? 0, + 'admin_user_id' => $data['admin_user_id'], + 'channel_ids' => $channel_ids ?? '', + 'reason' => $data['reason'], + 'created_at' => get_datetime() + ]); + + $this->logService->logCreated( + $model, + $this->menuTitle . '.create' + ); + + DB::commit(); + return $model; + } catch (Exception $e) { + DB::rollBack(); + throw $e; + } + } + + /** + * @param array $data + * @param int $id + * @throws Exception + */ + public function updateModel(array $data, int $id) + { + try { + DB::beginTransaction(); + + $license_plate = $data['license_plate']; + $LicensePlate = new ParkingLicensePlateService($this->logService); + $license_plate_id = $LicensePlate->saveNumber($license_plate); + // 验证 + $existsWhere = [ + ['license_plate_id', '=', $license_plate_id], + ['id', '<>', $id] + ]; + if (ParkingWhitelist::query()->where($existsWhere)->exists()) { + throw new Exception( + __service($this->menuTitle . '.number_exists') + ); + } + + // 更新 + $model = ParkingWhitelist::query()->findOrFail($id); + $oldValues = $model->toArray(); + + $channel_ids = implode(',', $data['channel_ids']); + $model->update([ + 'license_plate_id' => $license_plate_id, + 'parking_id' => $data['parking_id'], + 'member_type' => $data['member_type'] ?? 0, + 'admin_user_id' => $data['admin_user_id'], + 'channel_ids' => $channel_ids ?? '', + 'reason' => $data['reason'], + 'updated_at' => get_datetime() + ]); + + $this->logService->logUpdated( + $model, + $oldValues, + $this->menuTitle . '.update' + ); + + DB::commit(); + return $model; + } catch (Exception $e) { + DB::rollBack(); + throw $e; + } + } + + /** + * @param $id + * @return bool + * @throws Exception + */ + public function deleteModel($id): bool + { + try { + DB::beginTransaction(); + + $model = ParkingWhitelist::query()->findOrFail($id); + + $this->logService->logDeleted($model, $this->menuTitle . '.delete'); + + $model->delete(); + + DB::commit(); + return true; + } catch (Exception $e) { + DB::rollBack(); + throw $e; + } + } +} diff --git a/app/common.php b/app/common.php index 9b84cc0..421b2ca 100644 --- a/app/common.php +++ b/app/common.php @@ -216,3 +216,10 @@ if (!function_exists('__service')) { return __('service.' . $str); } } + +if (!function_exists('__exports')) { + function __exports($str): string + { + return __('exports.' . $str); + } +} diff --git a/database/migrations/2026_06_04_143449_create_parking_whitelist_table.php b/database/migrations/2026_06_04_143449_create_parking_whitelist_table.php new file mode 100644 index 0000000..1565209 --- /dev/null +++ b/database/migrations/2026_06_04_143449_create_parking_whitelist_table.php @@ -0,0 +1,37 @@ +id(); + $table->integer('license_plate_id')->comment('车牌号码'); + $table->integer('parking_id')->comment('停车场'); + $table->integer('member_type')->default(0)->comment('身份类型'); + $table->integer('admin_user_id')->default(0)->comment('操作员'); + $table->text('channel_ids')->comment('通行通道'); + $table->string('reason', 300)->default('')->comment('通行原因'); + $table->tinyInteger('status')->default(1)->comment('状态'); + $table->timestamps(); + $table->softDeletes(); + $table->innoDb(); + $table->comment('白名单'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('parking_whitelist'); + } +}; diff --git a/database/seeders/AdminMenuSeeder.php b/database/seeders/AdminMenuSeeder.php index 6b9e555..7e11240 100644 --- a/database/seeders/AdminMenuSeeder.php +++ b/database/seeders/AdminMenuSeeder.php @@ -225,17 +225,17 @@ class AdminMenuSeeder extends Seeder 'view_details' => 'vipAccessRecord.show' ] ], - 'special' => [ - 'uri' => 'special', + 'whitelist' => [ + 'uri' => 'whitelist', 'page_uri' => '/special/whitelist', 'child' => [ - 'read_only' => 'special.index', - 'add' => 'special.store', - 'edit' => 'special.update', - 'delete' => 'special.destroy', - 'batch_import' => 'special.batchImport', - 'export' => 'special.export', - 'download_template' => 'special.downloadTemplate', + 'read_only' => 'whitelist.index', + 'add' => 'whitelist.store', + 'edit' => 'whitelist.update', + 'delete' => 'whitelist.destroy', + 'batch_import' => 'whitelist.batchImport', + 'export' => 'whitelist.export', + 'download_template' => 'whitelist.downloadTemplate', ] ] ], diff --git a/resources/lang/en/exports.php b/resources/lang/en/exports.php index e4fc412..032f18c 100644 --- a/resources/lang/en/exports.php +++ b/resources/lang/en/exports.php @@ -82,5 +82,13 @@ return [ 'middle_ratio' => 'Low license plate recognition accuracy', 'manual_count' => 'Number of manual modifications', 'manual_ratio' => 'Manually modify the ratio' + ], + 'whitelist' => [ + 'list' => 'White List Import Template', + 'export_list' => 'Whitelist vehicle list', + 'parking' => 'parking lot', + 'channel' => 'Access channel', + 'reason' => 'Reason for passage', + 'member_type' => 'Identity type' ] ]; diff --git a/resources/lang/en/log.php b/resources/lang/en/log.php index d148a9b..23344ed 100644 --- a/resources/lang/en/log.php +++ b/resources/lang/en/log.php @@ -126,5 +126,10 @@ return [ 'create' => 'Create device', 'update' => 'Update device', 'delete' => 'Delete device' + ], + 'whitelist' => [ + 'create' => 'Create whitelist', + 'update' => 'Update whitelist', + 'delete' => 'Remove from whitelist' ] ]; diff --git a/resources/lang/en/menu.php b/resources/lang/en/menu.php index 0faed2d..2dba93d 100644 --- a/resources/lang/en/menu.php +++ b/resources/lang/en/menu.php @@ -74,7 +74,7 @@ return [ 'appointment_list' => 'Appointment List', 'appointment_statistics' => 'Appointment Statistics', 'parking_repair_list' => 'List of maintenance parking spaces', - 'special' => 'whitelist', + 'whitelist' => 'whitelist', 'alarm_information' => 'Alarm information management', 'abnormal_resource_usage' => 'Abnormal occupancy', 'channel_permissions' => 'Channel permission management', diff --git a/resources/lang/en/service.php b/resources/lang/en/service.php index 7b5346f..ea4a4be 100644 --- a/resources/lang/en/service.php +++ b/resources/lang/en/service.php @@ -128,5 +128,8 @@ return [ 'type4' => '32 inch display screen', 'type5' => 'Koto recognition camera', 'name_exists' => 'The same type of device name already exists' + ], + 'whitelist' => [ + 'number_exists' => 'The license plate number already exists' ] ]; diff --git a/resources/lang/en/validation.php b/resources/lang/en/validation.php index d772330..90f731e 100644 --- a/resources/lang/en/validation.php +++ b/resources/lang/en/validation.php @@ -163,5 +163,12 @@ return [ 'ip_empty' => 'The device IP cannot be empty', 'ip' => 'Device IP format error', 'sn_empty' => 'The device code cannot be empty' + ], + 'whitelist' => [ + 'l_empty' => 'The license plate number cannot be empty', + 'pa_empty' => 'The parking lot cannot be empty', + 'n_empty' => 'The reason for passage cannot be empty', + 'c_empty' => 'The passage cannot be empty', + 'c_array' => 'The passage channel data must be an array', ] ]; diff --git a/resources/lang/zh-CN/exports.php b/resources/lang/zh-CN/exports.php index 7b0509a..85ab45c 100644 --- a/resources/lang/zh-CN/exports.php +++ b/resources/lang/zh-CN/exports.php @@ -82,5 +82,13 @@ return [ 'middle_ratio' => '低车牌识别度', 'manual_count' => '手动修改次数', 'manual_ratio' => '手动修改比例' + ], + 'whitelist' => [ + 'list' => '白名单导入模板', + 'export_list' => '白名单车辆列表', + 'parking' => '停车场', + 'channel' => '通行通道', + 'reason' => '通行原因', + 'member_type' => '身份类型' ] ]; diff --git a/resources/lang/zh-CN/log.php b/resources/lang/zh-CN/log.php index 712eb94..3714048 100644 --- a/resources/lang/zh-CN/log.php +++ b/resources/lang/zh-CN/log.php @@ -126,5 +126,10 @@ return [ 'create' => '创建设备', 'update' => '更新设备', 'delete' => '删除设备' + ], + 'whitelist' => [ + 'create' => '创建白名单', + 'update' => '更新白名单', + 'delete' => '删除白名单' ] ]; diff --git a/resources/lang/zh-CN/menu.php b/resources/lang/zh-CN/menu.php index 9cef709..59df05a 100644 --- a/resources/lang/zh-CN/menu.php +++ b/resources/lang/zh-CN/menu.php @@ -74,7 +74,7 @@ return [ 'appointment_list' => '预约列表', 'appointment_statistics' => '预约统计', 'parking_repair_list' => '维修车位列表', - 'special' => '白名单', + 'whitelist' => '白名单', 'alarm_information' => '告警信息管理', 'abnormal_resource_usage' => '异常占用', 'channel_permissions' => '通道权限管理', diff --git a/resources/lang/zh-CN/service.php b/resources/lang/zh-CN/service.php index 761d67a..d7f947e 100644 --- a/resources/lang/zh-CN/service.php +++ b/resources/lang/zh-CN/service.php @@ -128,5 +128,8 @@ return [ 'type4' => '32寸显示屏', 'type5' => '科拓识别相机', 'name_exists' => '同类型设备名称已存在' + ], + 'whitelist' => [ + 'number_exists' => '车牌号码已存在' ] ]; diff --git a/resources/lang/zh-CN/validation.php b/resources/lang/zh-CN/validation.php index 1822409..0d5d037 100644 --- a/resources/lang/zh-CN/validation.php +++ b/resources/lang/zh-CN/validation.php @@ -163,5 +163,12 @@ return [ 'ip_empty' => '设备IP不能为空', 'ip' => '设备IP格式错误', 'sn_empty' => '设备编码不能为空' + ], + 'whitelist' => [ + 'l_empty' => '车牌号码不能为空', + 'pa_empty' => '停车场不能为空', + 'n_empty' => '通行原因不能为空', + 'c_empty' => '通行通道不能为空', + 'c_array' => '通行通道数据必须是数组', ] ]; diff --git a/resources/lang/zh-TW/exports.php b/resources/lang/zh-TW/exports.php index beac9fc..1ce25ad 100644 --- a/resources/lang/zh-TW/exports.php +++ b/resources/lang/zh-TW/exports.php @@ -82,5 +82,13 @@ return [ 'middle_ratio' => '低車牌識別度', 'manual_count' => '手動修改次數', 'manual_ratio' => '手動修改比例' + ], + 'whitelist' => [ + 'list' => '白名單導入範本', + 'export_list' => '白名單車輛清單', + 'parking' => '停車場', + 'channel' => '通行通道', + 'reason' => '通行原因', + 'member_type' => '身份類型' ] ]; diff --git a/resources/lang/zh-TW/log.php b/resources/lang/zh-TW/log.php index 8e64aa1..4df3292 100644 --- a/resources/lang/zh-TW/log.php +++ b/resources/lang/zh-TW/log.php @@ -126,5 +126,10 @@ return [ 'create' => '創建設備', 'update' => '更新設備', 'delete' => '删除設備' + ], + 'whitelist' => [ + 'create' => '創建白名單', + 'update' => '更新白名單', + 'delete' => '删除白名單' ] ]; diff --git a/resources/lang/zh-TW/menu.php b/resources/lang/zh-TW/menu.php index a3effc7..13cb141 100644 --- a/resources/lang/zh-TW/menu.php +++ b/resources/lang/zh-TW/menu.php @@ -74,7 +74,7 @@ return [ 'appointment_list' => '預約清單', 'appointment_statistics' => '預約統計', 'parking_repair_list' => '維修車位清單', - 'special' => '白名單', + 'whitelist' => '白名單', 'alarm_information' => '告警資訊管理', 'abnormal_resource_usage' => '异常佔用', 'channel_permissions' => '通道許可權管理', diff --git a/resources/lang/zh-TW/service.php b/resources/lang/zh-TW/service.php index b8c489d..40a543b 100644 --- a/resources/lang/zh-TW/service.php +++ b/resources/lang/zh-TW/service.php @@ -128,5 +128,8 @@ return [ 'type4' => '32寸顯示幕', 'type5' => '科拓識別相機', 'name_exists' => '同類型設備名稱已存在' + ], + 'whitelist' => [ + 'number_exists' => '車牌號碼已存在' ] ]; diff --git a/resources/lang/zh-TW/validation.php b/resources/lang/zh-TW/validation.php index 332bd0f..6b36b67 100644 --- a/resources/lang/zh-TW/validation.php +++ b/resources/lang/zh-TW/validation.php @@ -163,5 +163,12 @@ return [ 'ip_empty' => '設備IP不能為空', 'ip' => '設備IP格式錯誤', 'sn_empty' => '設備編碼不能為空' + ], + 'whitelist' => [ + 'l_empty' => '車牌號碼不能為空', + 'pa_empty' => '停車場不能為空', + 'n_empty' => '通行原因不能為空', + 'c_empty' => '通行通道不能為空', + 'c_array' => '通行通道數據必須是數組', ] ]; diff --git a/routes/admin/api.php b/routes/admin/api.php index 3f72bed..81d6165 100644 --- a/routes/admin/api.php +++ b/routes/admin/api.php @@ -36,6 +36,7 @@ use App\Http\Controllers\Admin\GuardBoothManagementController; use App\Http\Controllers\Admin\ParkingDepartureReasonController; use App\Http\Controllers\Admin\ChannelPermissionsController; use App\Http\Controllers\Admin\ParkingEquipmentController; +use App\Http\Controllers\Admin\ParkingWhitelistController; Route::group(['prefix' => 'admin'], function () { @@ -168,6 +169,16 @@ Route::group(['prefix' => 'admin'], function () { Route::get('/vipAccessRecord', [VipAccessRecordController::class, 'index']); Route::get('/vipAccessRecord/rule', [VipAccessRecordController::class, 'rule']); Route::get('/vipAccessRecord/{id}', [VipAccessRecordController::class, 'show']); + // 白名单 + Route::get('/whitelist', [ParkingWhitelistController::class, 'index']); + Route::get('/whitelist/create', [ParkingWhitelistController::class, 'create']); + Route::post('/whitelist', [ParkingWhitelistController::class, 'store']); + Route::get('/whitelist/edit/{id}', [ParkingWhitelistController::class, 'edit']); + Route::put('/whitelist/{id}', [ParkingWhitelistController::class, 'update']); + Route::delete('/whitelist/{id}', [ParkingWhitelistController::class, 'destroy']); + Route::get('/whitelist/rule', [ParkingWhitelistController::class, 'rule']); + Route::get('/whitelist/search', [ParkingWhitelistController::class, 'search']); + Route::post('/whitelist/batchImport', [ParkingWhitelistController::class, 'batchImport']); // 警报&通知 Route::get('/notice', [NoticeController::class, 'index']); Route::get('/notice/index', [NoticeController::class, 'message']); @@ -318,4 +329,6 @@ Route::group(['prefix' => 'admin'], function () { Route::get('/notice/export', [NoticeController::class, 'export']); Route::get('/parkingBehavior/export', [ParkingBehaviorController::class, 'export']); Route::get('/licensePlateRecognition/export', [LicensePlateRecognitionController::class, 'export']); + Route::get('/whitelist/downloadTemplate', [ParkingWhitelistController::class, 'downloadTemplate']); + Route::get('/whitelist/export', [ParkingWhitelistController::class, 'export']); });