From bf91835d70d0e4680be10d3330ef6bf7386eee90 Mon Sep 17 00:00:00 2001 From: wanghongjun <1445693971@qq.com> Date: Fri, 29 May 2026 17:01:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=81=9C=E8=BD=A6=E5=9C=BA=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E4=BA=BA=E5=91=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Admin/parkingAttendantController.php | 254 ++++++++++++++++++ app/Models/ParkingAdminUser.php | 33 +++ app/Services/ParkingAdminUserService.php | 105 ++++++++ ...082121_create_parking_admin_user_table.php | 34 +++ resources/lang/en/log.php | 10 + resources/lang/en/validation.php | 9 +- resources/lang/zh-CN/log.php | 10 + resources/lang/zh-CN/validation.php | 21 +- resources/lang/zh-TW/log.php | 10 + resources/lang/zh-TW/validation.php | 9 +- routes/admin/api.php | 9 + 11 files changed, 495 insertions(+), 9 deletions(-) create mode 100644 app/Http/Controllers/Admin/parkingAttendantController.php create mode 100644 app/Models/ParkingAdminUser.php create mode 100644 app/Services/ParkingAdminUserService.php create mode 100644 database/migrations/2026_01_29_082121_create_parking_admin_user_table.php diff --git a/app/Http/Controllers/Admin/parkingAttendantController.php b/app/Http/Controllers/Admin/parkingAttendantController.php new file mode 100644 index 0000000..dd9e9e7 --- /dev/null +++ b/app/Http/Controllers/Admin/parkingAttendantController.php @@ -0,0 +1,254 @@ +service = $service; + } + + + /** + * @return JsonResponse + */ + public function search(): JsonResponse + { + try { + $data = [ + 'member_type_list' => get_select_data( + ParkingAdminUserService::$memberType + ) + ]; + return $this->responseService->success($data); + } catch (Exception $e) { + $m_prefix = __('exception.exception_handler.resource'); + return $this->responseService->systemError( + $m_prefix . ':' . $e->getMessage() + ); + } + } + + public function index(Request $request): JsonResponse + { + try { + $query = ParkingAdminUser::query(); + + if ($request->has('name')) { + $name = $request->input('name'); + if (!empty($name)) { + $query->where('name', 'like', "%{$name}%"); + } + } + + if ($request->has('phone')) { + $phone = $request->input('phone'); + if (!empty($phone)) { + $query->where('phone', $phone); + } + } + + if ($request->has('member_type')) { + $member_type = $request->input('member_type'); + if (!empty($member_type)) { + $query->where('member_type', $member_type); + } + } + + // 分页 + $page = $request->input('page', 1); + $perPage = $request->input('per_page', 10); + $query->orderBy('id'); + $total = $query->count(); + $memberType = ParkingAdminUserService::$memberType; + + $items = $query->latest()->forPage($page, $perPage)->get()->each( + function ($item) use ($memberType) { + $item['member_type'] = $memberType[$item['member_type']]; + 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() + ); + } + } + + /** + * @param Request $request + * @return JsonResponse + * @throws CustomException + * @throws ValidationException + */ + public function store(Request $request): JsonResponse + { + try { + $this->saveValidator($request->all()); + $this->service->createModel($request->all()); + 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() + ); + } + } + + /** + * @param array $data + * @param int $id + * @return void + */ + protected function saveValidator(array $data, int $id = 0): void + { + $rules = [ + 'name' => 'required', + 'phone' => 'required', + 'member_type' => 'required', + ]; + $messages = [ + 'name.required' => __( + 'validation.parking_attendant.n_empty' + ), + 'phone.required' => __( + 'validation.parking_attendant.p_empty' + ), + 'member_type.required' => __( + 'validation.parking_attendant.m_empty' + ), + ]; + $model = ParkingAdminUser::query(); + + if ($id) { + $this->validateId($id, ParkingAdminUser::class); + $model->where([ + ['name', '=', $data['name']], + ['id', '<>', $id] + ]); + } else { + $model->where('name', $data['name']); + } + + if ($model->exists()) { + throw new CustomException( + __('validation.parking_attendant.name_exists') + ); + } + + $validator = Validator::make($data, $rules, $messages); + + if ($validator->fails()) { + throw new ValidationException($validator); + } + } + + public function edit($id): JsonResponse + { + try { + $this->validateId($id, ParkingAdminUser::class); + $item = ParkingAdminUser::query()->findOrFail($id); + $data = [ + 'item' => $item, + 'member_type_list' => get_select_data( + ParkingAdminUserService::$memberType + ), + ]; + 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); + $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 string $id + * @return JsonResponse + * @throws ValidationException + */ + public function destroy(string $id): JsonResponse + { + try { + $this->validateId($id, ParkingAdminUser::class); + $this->service->deleteModel($id); + return $this->responseService->success( + null, + __('admin.delete_succeeded') + ); + } catch (ValidationException $e) { + throw $e; + } catch (Exception $e) { + return $this->responseService->systemError( + __('admin.operation_failed') . ':' + . $e->getMessage() + ); + } + } +} diff --git a/app/Models/ParkingAdminUser.php b/app/Models/ParkingAdminUser.php new file mode 100644 index 0000000..7cfe015 --- /dev/null +++ b/app/Models/ParkingAdminUser.php @@ -0,0 +1,33 @@ + 'DIS', + 2 => 'OMHK', + 3 => 'MBHK', + 4 => 'GBA', + 5 => 'YUC', + 6 => 'VMHK', + 7 => 'ST', + 8 => 'RCIM', + 9 => 'OMCN', + 10 => 'MBCN', + 11 => 'PUBLIC' + ]; + protected string $menuTitle = 'parking_attendant'; + + // 创建 + + public function createModel(array $data) + { + try { + DB::beginTransaction(); + + $model = ParkingAdminUser::query()->create([ + 'name' => $data['name'], + 'phone' => $data['phone'], + 'member_type' => $data['member_type'], + 'created_at' => get_datetime() + ]); + + $this->logService->logCreated($model, 'parking_attendant.create'); + + DB::commit(); + return $model; + } catch (Exception $e) { + DB::rollBack(); + throw $e; + } + } + + // 创建 + public function updateModel(array $data, $id) + { + try { + DB::beginTransaction(); + + $model = ParkingAdminUser::query()->findOrFail($id); + $oldValue = $model->toArray(); + + $update = [ + 'name' => $data['name'], + 'phone' => $data['phone'], + 'member_type' => $data['member_type'], + 'status' => $data['status'] ?? 1, + 'updated_at' => get_datetime() + ]; + $model->update($update); + + $this->logService->logUpdated( + $model, + $oldValue, + 'parking_attendant.update' + ); + + DB::commit(); + return $model; + } catch (Exception $e) { + DB::rollBack(); + throw $e; + } + } + + public function deleteModel(int $id): bool + { + try { + DB::beginTransaction(); + + $model = ParkingAdminUser::query()->findOrFail($id); + + $this->logService->logDeleted( + $model, + 'parking_attendant.delete' + ); + + $model->delete(); + DB::commit(); + return true; + } catch (Exception $e) { + DB::rollBack(); + throw $e; + } + } +} diff --git a/database/migrations/2026_01_29_082121_create_parking_admin_user_table.php b/database/migrations/2026_01_29_082121_create_parking_admin_user_table.php new file mode 100644 index 0000000..279a1a6 --- /dev/null +++ b/database/migrations/2026_01_29_082121_create_parking_admin_user_table.php @@ -0,0 +1,34 @@ +id(); + $table->string('name', 50)->default('')->comment('管理人员名称'); + $table->string('phone', 20)->default('')->comment('手机号'); + $table->tinyInteger('member_type')->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_admin_user'); + } +}; diff --git a/resources/lang/en/log.php b/resources/lang/en/log.php index 82c087a..e583a74 100644 --- a/resources/lang/en/log.php +++ b/resources/lang/en/log.php @@ -90,5 +90,15 @@ return [ 'space_type_attr' => [ 'create' => 'Create parking space type attributes', 'delete' => 'Delete parking space type attribute' + ], + 'parking_management' => [ + 'create' => 'Create parking lot information', + 'update' => 'Update parking lot information', + 'delete' => 'Delete parking lot information' + ], + 'parking_attendant' => [ + 'create' => 'Create a parking lot administrator', + 'update' => 'Update parking lot administrator', + 'delete' => 'Delete parking lot administrator' ] ]; diff --git a/resources/lang/en/validation.php b/resources/lang/en/validation.php index 99ff464..d343f69 100644 --- a/resources/lang/en/validation.php +++ b/resources/lang/en/validation.php @@ -124,6 +124,13 @@ return [ 'e_empty' => 'The closing time cannot be empty', 'e_length' => 'The length of the business closing time must be 5', 'a_empty' => 'Position cannot be empty', - 'error_time' => 'The end time cannot be less than the start time' + 'error_time' => 'The end time cannot be less than the start time', + 'name_exists' => 'The parking lot name already exists' + ], + 'parking_attendant' => [ + 'n_empty' => 'The name of the management personnel cannot be empty', + 'p_empty' => 'The phone number cannot be empty', + 'm_empty' => 'Member type cannot be empty', + 'name_exists' => 'The name of the management personnel already exists', ] ]; diff --git a/resources/lang/zh-CN/log.php b/resources/lang/zh-CN/log.php index 5245e0a..93f9702 100644 --- a/resources/lang/zh-CN/log.php +++ b/resources/lang/zh-CN/log.php @@ -90,5 +90,15 @@ return [ 'space_type_attr' => [ 'create' => '创建车位类型属性', 'delete' => '删除车位类型属性' + ], + 'parking_management' => [ + 'create' => '创建停车场信息', + 'update' => '更新停车场信息', + 'delete' => '删除停车场信息' + ], + 'parking_attendant' => [ + 'create' => '创建停车场管理员', + 'update' => '更新停车场管理员', + 'delete' => '删除停车场管理员' ] ]; diff --git a/resources/lang/zh-CN/validation.php b/resources/lang/zh-CN/validation.php index 703612c..8c352b4 100644 --- a/resources/lang/zh-CN/validation.php +++ b/resources/lang/zh-CN/validation.php @@ -118,12 +118,19 @@ return [ 'c_in' => '更新数据只能是0或1', ], 'parking_management' => [ - 'n_empty' => '停车场名称不能为空', - 'o_empty' => '营业开始时间不能为空', - 'o_length' => '营业开始时间长度必须是5', - 'e_empty' => '营业结束时间不能为空', - 'e_length' => '营业结束时间长度必须是5', - 'a_empty' => '位置不能为空', - 'error_time' => '结束时间不能小于开始时间' + 'n_empty' => '停车场名称不能为空', + 'o_empty' => '营业开始时间不能为空', + 'o_length' => '营业开始时间长度必须是5', + 'e_empty' => '营业结束时间不能为空', + 'e_length' => '营业结束时间长度必须是5', + 'a_empty' => '位置不能为空', + 'error_time' => '结束时间不能小于开始时间', + 'name_exists' => '停车场名称已存在' + ], + 'parking_attendant' => [ + 'n_empty' => '管理人员名称不能为空', + 'p_empty' => '手机号不能为空', + 'm_empty' => '会员类型不能为空', + 'name_exists' => '管理人员名称已存在', ] ]; diff --git a/resources/lang/zh-TW/log.php b/resources/lang/zh-TW/log.php index a4bf006..b9f7c33 100644 --- a/resources/lang/zh-TW/log.php +++ b/resources/lang/zh-TW/log.php @@ -90,5 +90,15 @@ return [ 'space_type_attr' => [ 'create' => '創建車位類型内容', 'delete' => '删除車位類型内容' + ], + 'parking_management' => [ + 'create' => '創建停車場資訊', + 'update' => '更新停車場資訊', + 'delete' => '删除停車場資訊' + ], + 'parking_attendant' => [ + 'create' => '創建停車場管理員', + 'update' => '更新停車場管理員', + 'delete' => '删除停車場管理員' ] ]; diff --git a/resources/lang/zh-TW/validation.php b/resources/lang/zh-TW/validation.php index 3e24401..07109c8 100644 --- a/resources/lang/zh-TW/validation.php +++ b/resources/lang/zh-TW/validation.php @@ -124,6 +124,13 @@ return [ 'e_empty' => '營業結束時間不能為空', 'e_length' => '營業結束時間長度必須是5', 'a_empty' => '位置不能為空', - 'error_time' => '結束時間不能小於開始時間' + 'error_time' => '結束時間不能小於開始時間', + 'name_exists' => '停車場名稱已存在' + ], + 'parking_attendant' => [ + 'n_empty' => '管理人員名稱不能為空', + 'p_empty' => '手機號不能為空', + 'm_empty' => '會員類型不能為空', + 'name_exists' => '管理人員名稱已存在', ] ]; diff --git a/routes/admin/api.php b/routes/admin/api.php index eda1682..792ef35 100644 --- a/routes/admin/api.php +++ b/routes/admin/api.php @@ -29,6 +29,7 @@ use App\Http\Controllers\Admin\LicensePlateRecognitionController; use App\Http\Controllers\Admin\ParkingBehaviorController; use App\Http\Controllers\Admin\ParkingManagementController; use App\Http\Controllers\Admin\ParkingManagementListController; +use App\Http\Controllers\Admin\parkingAttendantController; Route::group(['prefix' => 'admin'], function () { @@ -219,6 +220,14 @@ Route::group(['prefix' => 'admin'], function () { Route::get('/parkingList/search', [ParkingManagementListController::class, 'search']); Route::get('/parkingList', [ParkingManagementListController::class, 'index']); Route::get('/parkingList/rule', [ParkingManagementListController::class, 'rule']); + // 停车场管理人员 + Route::get('/parkingAttendant', [parkingAttendantController::class, 'index']); + Route::get('/parkingAttendant/search', [parkingAttendantController::class, 'search']); + Route::post('/parkingAttendant', [parkingAttendantController::class, 'store']); + Route::get('/parkingAttendant/edit/{id}', [parkingAttendantController::class, 'edit']); + Route::put('/parkingAttendant/{id}', [parkingAttendantController::class, 'update']); + Route::delete('/parkingAttendant/{id}', [parkingAttendantController::class, 'destroy']); + Route::get('/parkingAttendant/rule', [parkingAttendantController::class, 'rule']); // 角色 Route::get('/roles', [RolesController::class, 'index']); Route::get('/roles/create', [RolesController::class, 'create']);