diff --git a/app/Http/Controllers/Admin/ParkingSpaceController.php b/app/Http/Controllers/Admin/ParkingSpaceController.php index 16a52f4..1500f26 100644 --- a/app/Http/Controllers/Admin/ParkingSpaceController.php +++ b/app/Http/Controllers/Admin/ParkingSpaceController.php @@ -2,14 +2,17 @@ namespace App\Http\Controllers\Admin; +use App\Exceptions\CustomException; use App\Exports\ParkingSpaceExport; -use App\Http\Controllers\Controller; use App\Models\AdminFloor; +use App\Models\AdminFloorRegion; +use App\Models\Parking; use App\Models\ParkingLicensePlate; use App\Models\ParkingPatternSpace; use App\Models\ParkingSpace; use App\Models\ParkingSpaceAttributes; use App\Models\ParkingSpaceType; +use App\Services\AdminFloorService; use App\Services\ApiResponseService; use App\Services\EventCalendarService; use App\Services\ParkingSpaceService; @@ -361,50 +364,211 @@ class ParkingSpaceController extends BaseController } } + /** + * @return JsonResponse + */ + public function create(): JsonResponse + { + try { + $data = [ + 'parking_list' => Parking::getData(), + 'space_attr_list' => ParkingSpaceAttributes::getData() + ]; + return $this->responseService->success($data); + } catch (Exception $e) { + return $this->responseService->systemError( + __('exception.get_data_failed') . ':' . $e->getMessage() + ); + } + } + + /** + * @param Request $request + * @return JsonResponse + * @throws CustomException + * @throws ValidationException + */ public function store(Request $request): JsonResponse { - $data = $request->all(); - if (ParkingSpace::query()->where('number', $data['number']) - ->exists() - ) { - return $this->responseService->systemError('车位号码已存在'); + 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() + ); } - $floor_id = AdminFloor::query()->where('name', $data['floor_name']) - ->value('id'); - if (!$floor_id) { - return $this->responseService->systemError('楼层不存在'); + } + + /** + * @param array $data + * @param int $id + * @return void + * @throws ValidationException + */ + protected function saveValidator(array $data, int $id = 0): void + { + $rules = [ + 'parking_id' => 'required', + 'floor_id' => 'required', + 'region_id' => 'required', + 'space_attr_id' => 'required', + 'number' => 'required' + ]; + $messages = [ + 'parking_id.required' => __validation('parking_space.pi_empty'), + 'floor_id.required' => __validation('parking_space.fi_empty'), + 'region_id.required' => __validation('parking_space.ri_empty'), + 'space_attr_id.required' => __validation('parking_space.a_empty'), + 'number.required' => __validation('parking_space.n_empty') + ]; + if ($id) { + $this->validateId($id, ParkingSpace::class); } - $space_attr_id = ParkingSpaceAttributes::query()->where( - 'attributes', - $data['attr_name'] - )->value('id'); - if (!$space_attr_id) { - return $this->responseService->systemError('车位属性不存在'); + $validator = Validator::make($data, $rules, $messages); + + if ($validator->fails()) { + throw new ValidationException($validator); } - $space_type_id = ParkingSpaceType::getValueId($data['type_name']); - if (!$space_type_id) { - return $this->responseService->systemError('车位类型不存在'); + } + + /** + * @param string $id + * @return JsonResponse + */ + public function edit(string $id): JsonResponse + { + try { + $this->validateId($id, ParkingSpace::class); + $item = ParkingSpace::query()->find($id, [ + 'id', + 'floor_id', + 'number', + 'region_id', + 'space_attr_id' + ]); + $item['parking_id'] = AdminFloor::query()->where( + 'id', + $item['floor_id'] + )->value('building_floor'); + $data = [ + 'parking_list' => Parking::getData(), + 'floor_list' => AdminFloorService::getSelectList( + $item['parking_id'], + [ + 'id as floor_id', + 'name as floor_name' + ] + ), + 'floor_region_list' => AdminFloorRegion::getFloorRegion( + $item['floor_id'] + ), + 'space_attr_list' => ParkingSpaceAttributes::getData(), + '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 ValidationException + */ + public function update(Request $request, string $id): JsonResponse + { + try { + $this->saveValidator($request->all(), $id); + $this->service->updateModel($request->all(), $id); + return $this->responseService->success( + null, + __('admin.update_succeeded') + ); + } catch (ValidationException $e) { + throw $e; + } catch (Exception $e) { + return $this->responseService->systemError( + __('admin.operation_failed') . ':' + . $e->getMessage() + ); } - $license_plate_id = 0; - $status = 0; - if (isset($data['license_plate'])) { - $license_plate_id = ParkingLicensePlate::getValueId( - $data['license_plate'] + } + + /** + * @param string $id + * @return JsonResponse + * @throws ValidationException + */ + public function destroy(string $id): JsonResponse + { + try { + $this->validateId($id, ParkingSpace::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() ); - if ($license_plate_id) { - $status = 1; - } else { - return $this->responseService->systemError('车牌号码不存在'); + } + } + + /** + * @param Request $request + * @return JsonResponse + * @throws CustomException + * @throws ValidationException + */ + public function batchDelete(Request $request): JsonResponse + { + try { + $data = $request->all(); + $rules = [ + 'ids' => 'required|array', + ]; + $messages = [ + 'ids.required' => __validation( + 'parking_repair_list.ids_empty' + ), + 'ids.array' => __validation( + 'parking_repair_list.ids_array' + ), + ]; + $validator = Validator::make($data, $rules, $messages); + + if ($validator->fails()) { + throw new ValidationException($validator); } + $ids = $data['ids']; + $this->service->batchDeleteModel($ids); + 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() + ); } - $this->service->createData([ - 'floor_id' => $floor_id, - 'number' => $data['number'], - 'space_attr_id' => $space_attr_id, - 'space_type_id' => $space_type_id, - 'license_plate_id' => $license_plate_id, - 'status' => $status - ]); - return $this->responseService->success('', __('admin.operation_successful')); } } diff --git a/app/Models/AdminFloorRegion.php b/app/Models/AdminFloorRegion.php index 12f89da..c3775fd 100644 --- a/app/Models/AdminFloorRegion.php +++ b/app/Models/AdminFloorRegion.php @@ -38,9 +38,17 @@ class AdminFloorRegion extends Model */ public static function getFloorRegion(int $floor_id): array { - $columns = ['id','name']; - return self::query()->where('floor_id', $floor_id)->where('status', 1)->select($columns) - ->get()->toArray(); + $columns = ['id', 'name']; + return self::query()->where('floor_id', $floor_id)->where('status', 1) + ->select($columns) + ->get()->each(function ($item) { + $item['name'] = AdminTranslationService::getTranslationTypeName( + $item['id'], + 5, + $item['name'] + ); + return $item; + })->toArray(); } public static function getName($id) diff --git a/app/Models/ParkingSpace.php b/app/Models/ParkingSpace.php index 0b65bac..d8b6699 100644 --- a/app/Models/ParkingSpace.php +++ b/app/Models/ParkingSpace.php @@ -4,10 +4,11 @@ namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\SoftDeletes; class ParkingSpace extends Model { - use HasFactory; + use HasFactory, SoftDeletes; protected $table = 'parking_space'; @@ -24,12 +25,15 @@ class ParkingSpace extends Model 'operation_type', 'pic_url', 'customer_id', - 'member_id' + 'member_id', + 'region_id' ]; protected $hidden = [ - 'created_at' + 'created_at', + 'updated_at', + 'deleted_at' ]; diff --git a/app/Services/AdminFloorService.php b/app/Services/AdminFloorService.php index 84317e2..1fbe907 100644 --- a/app/Services/AdminFloorService.php +++ b/app/Services/AdminFloorService.php @@ -175,6 +175,7 @@ class AdminFloorService if (isset($item['pic_url'])) { $item['pic_url'] = get_image_url($item['pic_url']); } + $item['floor_name'] = AdminTranslationService::getTranslationTypeName($item['floor_id'], 4, $item['floor_name']); } return $list; } @@ -186,6 +187,7 @@ class AdminFloorService foreach ($data as &$item) { if (isset($item['image_url'])) { $item['pic_url'] = get_image_url($item['image_url']); + $item['name'] = AdminTranslationService::getTranslationTypeName($item['id'], 4, $item['name']); } } return $data; diff --git a/app/Services/ParkingSpaceService.php b/app/Services/ParkingSpaceService.php index 793497e..2ee8199 100644 --- a/app/Services/ParkingSpaceService.php +++ b/app/Services/ParkingSpaceService.php @@ -199,6 +199,12 @@ class ParkingSpaceService extends BaseService ) { throw new Exception(__('service.parking_space.number_exists')); } + if (empty($data['space_type_id'])) { + $res = ParkingSpaceType::getDefaultData(); + if ($res) { + $data['space_type_id'] = $res['id']; + } + } $model = $this->createData($data); DB::commit(); return $model; @@ -212,6 +218,7 @@ class ParkingSpaceService extends BaseService { $model = ParkingSpace::query()->create([ 'floor_id' => $data['floor_id'], + 'region_id' => $data['region_id'], 'number' => $data['number'], 'space_attr_id' => $data['space_attr_id'], 'license_plate_id' => $data['license_plate_id'] ?? 0, @@ -360,4 +367,107 @@ class ParkingSpaceService extends BaseService $HikParkingCameraService->updatelight($body); } } + + /** + * @param array $data + * @param int $id + * @throws Exception + */ + public function updateModel(array $data, int $id) + { + try { + DB::beginTransaction(); + + // 验证 + $existsWhere = [ + ['number', '=', $data['number']], + ['id', '<>', $id] + ]; + if (ParkingSpace::query()->where($existsWhere)->exists()) { + throw new Exception(__service('parking_space.number_exists')); + } + + $space_type_id = 0; + $res = ParkingSpaceType::getDefaultData(); + if ($res) { + $space_type_id = $res['id']; + } + + // 更新 + $model = ParkingSpace::query()->findOrFail($id); + $oldValues = $model->toArray(); + + $model->update([ + 'floor_id' => $data['floor_id'], + 'region_id' => $data['region_id'], + 'number' => $data['number'], + 'space_attr_id' => $data['space_attr_id'], + 'space_type_id' => $space_type_id, + 'updated_at' => get_datetime() + ]); + + $this->logService->logUpdated( + $model, + $oldValues, + 'parking_space.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 = ParkingSpace::query()->findOrFail($id); + + $this->logService->logDeleted($model, 'parking_space.delete'); + + $model->delete(); + + DB::commit(); + return true; + } catch (Exception $e) { + DB::rollBack(); + throw $e; + } + } + + /** + * @param $ids + * @return bool + * @throws Exception + */ + public function batchDeleteModel($ids): bool + { + try { + DB::beginTransaction(); + + foreach ($ids as $id) { + $model = ParkingSpace::query()->findOrFail($id); + $this->logService->logDeleted( + $model, + 'parking_space.delete' + ); + $model->delete(); + } + + DB::commit(); + return true; + } catch (Exception $e) { + DB::rollBack(); + throw $e; + } + } } diff --git a/database/migrations/2026_03_23_143449_create_parking_space_table.php b/database/migrations/2026_03_23_143449_create_parking_space_table.php index 51f0a58..2c77b24 100644 --- a/database/migrations/2026_03_23_143449_create_parking_space_table.php +++ b/database/migrations/2026_03_23_143449_create_parking_space_table.php @@ -14,6 +14,7 @@ return new class extends Migration Schema::create('parking_space', function (Blueprint $table) { $table->id(); $table->integer('floor_id')->comment('楼层id'); + $table->integer('region_id')->default(0)->comment('区域id'); $table->string('number', 50)->default('')->comment('车位号码'); $table->integer('space_attr_id')->comment('车位属性id'); $table->integer('license_plate_id')->default(0)->comment('车牌号码'); @@ -27,6 +28,8 @@ return new class extends Migration $table->string('customer_id', 50)->default('')->comment('客户ID'); $table->string('member_id', 50)->default('')->comment('会员ID'); $table->timestamps(); + $table->softDeletes(); + $table->innoDb(); }); } diff --git a/resources/lang/en/log.php b/resources/lang/en/log.php index 953f603..07fee2d 100644 --- a/resources/lang/en/log.php +++ b/resources/lang/en/log.php @@ -71,6 +71,8 @@ return [ ], 'parking_space' => [ 'create' => 'Create parking space', + 'update' => 'Update parking spaces', + 'delete' => 'Delete parking space' ], 'parking_pattern' => [ 'create' => 'Create activity mode', diff --git a/resources/lang/en/validation.php b/resources/lang/en/validation.php index e582198..bd66b1f 100644 --- a/resources/lang/en/validation.php +++ b/resources/lang/en/validation.php @@ -78,7 +78,12 @@ return [ 'ids_array' => 'Parking data must be an array', 'status_empty' => 'The parking space status cannot be empty', 'status_numeric' => 'The parking space status must be a number', - 'status_in' => 'The parking status can only be 0 or 1' + 'status_in' => 'The parking status can only be 0 or 1', + 'pi_empty' => 'The parking lot cannot be empty', + 'fi_empty' => 'Floor cannot be empty', + 'ri_empty' => 'Region cannot be empty', + 'a_empty' => 'Parking space attribute cannot be empty', + 'n_empty' => 'The parking number cannot be empty' ], 'map' => [ 'f_empty' => 'The floor number cannot be empty', @@ -172,12 +177,12 @@ return [ 'c_array' => 'The passage channel data must be an array', ], 'parking_repair_list' => [ - 'psn_empty' => '車位號碼不能為空', - 's_empty' => '維修開始時間不能為空', - 'e_empty' => '維修結束時間不能為空', - 'ids_empty' => '請選擇要删除的數據', - 'ids_array' => '所選數據必須是數組', - 'date_error' => '開始時間不能大於結束時間' + 'psn_empty' => 'The parking number cannot be empty', + 's_empty' => 'The start time of maintenance cannot be empty', + 'e_empty' => 'The repair end time cannot be empty', + 'ids_empty' => 'Please select the data to be deleted', + 'ids_array' => 'The selected data must be an array', + 'date_error' => 'The start time cannot be greater than the end time' ], 'gate_control' => [ 'n_empty' => 'Order number or license plate number cannot be empty', diff --git a/resources/lang/zh-CN/log.php b/resources/lang/zh-CN/log.php index 3e48301..488336a 100644 --- a/resources/lang/zh-CN/log.php +++ b/resources/lang/zh-CN/log.php @@ -71,6 +71,8 @@ return [ ], 'parking_space' => [ 'create' => '创建车位', + 'update' => '更新车位', + 'delete' => '删除车位' ], 'parking_pattern' => [ 'create' => '创建活动模式', diff --git a/resources/lang/zh-CN/validation.php b/resources/lang/zh-CN/validation.php index c3717d4..e62c650 100644 --- a/resources/lang/zh-CN/validation.php +++ b/resources/lang/zh-CN/validation.php @@ -78,7 +78,12 @@ return [ 'ids_array' => '车位数据必须是数组', 'status_empty' => '车位状态不能为空', 'status_numeric' => '车位状态必须是数字', - 'status_in' => '车位状态只能是0或1' + 'status_in' => '车位状态只能是0或1', + 'pi_empty' => '停车场不能为空', + 'fi_empty' => '楼层不能为空', + 'ri_empty' => '区域不能为空', + 'a_empty' => '车位属性不能为空', + 'n_empty' => '车位号码不能为空' ], 'map' => [ 'f_empty' => '楼层编号不能为空', diff --git a/resources/lang/zh-TW/log.php b/resources/lang/zh-TW/log.php index dd08bcf..2da50c0 100644 --- a/resources/lang/zh-TW/log.php +++ b/resources/lang/zh-TW/log.php @@ -71,6 +71,8 @@ return [ ], 'parking_space' => [ 'create' => '創建車位', + 'update' => '更新車位', + 'delete' => '删除車位' ], 'parking_pattern' => [ 'create' => '創建活動模式', @@ -145,7 +147,7 @@ return [ 'delete' => '删除維修車位' ], 'gate_control' => [ - 'create_enter' => '创建入场记录', - 'update_leave' => '更新离场记录' + 'create_enter' => '創建入場記錄', + 'update_leave' => '更新離場記錄' ] ]; diff --git a/resources/lang/zh-TW/validation.php b/resources/lang/zh-TW/validation.php index 856b0fe..1679f00 100644 --- a/resources/lang/zh-TW/validation.php +++ b/resources/lang/zh-TW/validation.php @@ -78,7 +78,12 @@ return [ 'ids_array' => '車位數據必須是數組', 'status_empty' => '車位狀態不能為空', 'status_numeric' => '車位狀態必須是數位', - 'status_in' => '車位狀態只能是0或1' + 'status_in' => '車位狀態只能是0或1', + 'pi_empty' => '停車場不能為空', + 'fi_empty' => '樓層不能為空', + 'ri_empty' => '區域不能為空', + 'a_empty' => '車位内容不能為空', + 'n_empty' => '車位號碼不能為空' ], 'map' => [ 'f_empty' => '樓層編號不能為空', @@ -172,12 +177,12 @@ return [ 'c_array' => '通行通道數據必須是數組', ], 'parking_repair_list' => [ - 'psn_empty' => 'The parking number cannot be empty', - 's_empty' => 'The start time of maintenance cannot be empty', - 'e_empty' => 'The repair end time cannot be empty', - 'ids_empty' => 'Please select the data to be deleted', - 'ids_array' => 'The selected data must be an array', - 'date_error' => 'The start time cannot be greater than the end time' + 'psn_empty' => '車位號碼不能為空', + 's_empty' => '維修開始時間不能為空', + 'e_empty' => '維修結束時間不能為空', + 'ids_empty' => '請選擇要删除的數據', + 'ids_array' => '所選數據必須是數組', + 'date_error' => '開始時間不能大於結束時間' ], 'gate_control' => [ 'n_empty' => '訂單號碼或車牌號碼不能為空', diff --git a/routes/admin/api.php b/routes/admin/api.php index b60a28e..f67eb9f 100644 --- a/routes/admin/api.php +++ b/routes/admin/api.php @@ -50,7 +50,6 @@ Route::group(['prefix' => 'admin'], function () { Route::get('/isapi', [AuthController::class, 'isApi']); // get测试区 - Route::get('parkingSpace/create', [ParkingSpaceController::class, 'store']); // 需要认证的接口 Route::middleware(['admin.auth'])->group(function () { @@ -122,6 +121,13 @@ Route::group(['prefix' => 'admin'], function () { Route::post('/parkingSpace/information', [ParkingSpaceController::class, 'information']); Route::post('/parkingSpace/updateStatus', [ParkingSpaceController::class, 'updateStatus']); Route::get('/parkingSpace/rule', [ParkingSpaceController::class, 'rule']); + Route::get('/parkingSpaceManagement/create', [ParkingSpaceController::class, 'create']); + Route::post('/parkingSpaceManagement', [ParkingSpaceController::class, 'store']); + Route::get('/parkingSpaceManagement/edit/{id}', [ParkingSpaceController::class, 'edit']); + Route::put('/parkingSpaceManagement/{id}', [ParkingSpaceController::class, 'update']); + Route::delete('/parkingSpaceManagement/{id}', [ParkingSpaceController::class, 'destroy']); + Route::post('/parkingSpaceManagement/batchDelete', [ParkingSpaceController::class, 'batchDelete']); + Route::post('/parkingSpaceManagement/batchUpdateAttr', [ParkingSpaceController::class, 'updateAttr']); //车位类型管理 Route::get('/spaceType', [ParkingSpaceTypeController::class, 'index']); Route::get('/spaceType/create', [ParkingSpaceTypeController::class, 'create']);