From 191c10e7a158c83c3d3aa0a83795f09eb657a7fa Mon Sep 17 00:00:00 2001 From: wanghongjun <1445693971@qq.com> Date: Tue, 24 Mar 2026 17:27:24 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BD=A6=E4=BD=8D=E5=88=97=E8=A1=A8=E3=80=81?= =?UTF-8?q?=E8=BD=A6=E4=BD=8D=E9=A2=84=E5=AE=9A=E5=88=97=E8=A1=A8=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...arkingLicensePlateImportTemplateExport.php | 16 ++ app/Exports/ParkingSpaceExport.php | 59 +++++ .../Admin/ParkingReservationController.php | 205 +++++++++++++++ .../Admin/ParkingSpaceController.php | 247 ++++++++++++++++++ app/Imports/ParkingLicensePlateImport.php | 50 ++++ app/Models/AdminFloor.php | 10 +- app/Models/AdminFloorRegion.php | 4 + app/Models/AdminOperationLog.php | 8 - app/Models/ParkingLicensePlate.php | 5 + app/Models/ParkingReservation.php | 43 +++ app/Models/ParkingSpace.php | 42 +++ app/Models/ParkingSpaceAttributes.php | 10 + app/Models/ParkingSpaceType.php | 15 +- app/Services/BaseService.php | 20 ++ app/Services/ParkingReservationService.php | 73 ++++++ app/Services/ParkingSpaceService.php | 150 +++++++++++ app/common.php | 1 + ...62930_create_parking_reservation_table.php | 38 +++ ...3_23_143449_create_parking_space_table.php | 36 +++ resources/lang/zh-CN/exception.php | 4 + resources/lang/zh-CN/exports.php | 21 +- resources/lang/zh-CN/service.php | 35 ++- resources/lang/zh-CN/validation.php | 16 +- routes/admin/api.php | 12 + 24 files changed, 1092 insertions(+), 28 deletions(-) create mode 100644 app/Exports/ParkingLicensePlateImportTemplateExport.php create mode 100644 app/Exports/ParkingSpaceExport.php create mode 100644 app/Http/Controllers/Admin/ParkingReservationController.php create mode 100644 app/Http/Controllers/Admin/ParkingSpaceController.php create mode 100644 app/Imports/ParkingLicensePlateImport.php create mode 100644 app/Models/ParkingReservation.php create mode 100644 app/Models/ParkingSpace.php create mode 100644 app/Services/BaseService.php create mode 100644 app/Services/ParkingReservationService.php create mode 100644 app/Services/ParkingSpaceService.php create mode 100644 database/migrations/2026_03_20_162930_create_parking_reservation_table.php create mode 100644 database/migrations/2026_03_23_143449_create_parking_space_table.php diff --git a/app/Exports/ParkingLicensePlateImportTemplateExport.php b/app/Exports/ParkingLicensePlateImportTemplateExport.php new file mode 100644 index 0000000..91a0c7a --- /dev/null +++ b/app/Exports/ParkingLicensePlateImportTemplateExport.php @@ -0,0 +1,16 @@ +each( + function ($item) use (&$data) { + $oldItem = (new ParkingSpaceService( + new OperationLogService() + ))->optionItems($item); + $data[] = [ + 'id' => $oldItem['id'], + 'floor' => $oldItem['floor'], + 'number' => $oldItem['number'], + 'space_attr' => $oldItem['space_attr'], + 'license_plate' => $oldItem['license_plate'], + 'berthing_time' => $oldItem['berthing_time'], + 'recognition' => $oldItem['recognition'], + 'status' => $oldItem['status'], + 'space_type' => $oldItem['space_type'], + 'operation_type' => $oldItem['operation_type'], + 'updated_at' => $oldItem['updated_at'] + ]; + } + ); + return $data; + } + + /** + * @return array + */ + public function headings(): array + { + return [ + __('exports.global.index'), + __('exports.parking_space.floor'), + __('exports.parking_space.number'), + __('exports.parking_space.space_attr'), + __('exports.parking_space.license_plate'), + __('exports.parking_space.berthing_time'), + __('exports.parking_space.recognition'), + __('exports.parking_space.status'), + __('exports.parking_space.space_type'), + __('exports.parking_space.operation_type'), + __('exports.parking_space.updated_at') + ]; + } +} diff --git a/app/Http/Controllers/Admin/ParkingReservationController.php b/app/Http/Controllers/Admin/ParkingReservationController.php new file mode 100644 index 0000000..e2f98fa --- /dev/null +++ b/app/Http/Controllers/Admin/ParkingReservationController.php @@ -0,0 +1,205 @@ +responseService = $responseService; + $this->service = $service; + } + + public function index(Request $request): JsonResponse + { + try { + $query = ParkingReservation::query(); + + // 车牌号码搜索 + if ($request->has('license_plate')) { + $license_plate = $request->input('license_plate'); + if (!empty($license_plate)) { + $license_plate_id_arr = ParkingLicensePlate::query()->where( + 'number', + 'like', + "%{$license_plate}%" + )->pluck('id'); + $license_plate_id_arr ? $query->whereIn( + 'license_plate_id', + $license_plate_id_arr + ) : $query->where('id', 0); + } + } + // 楼层 + if ($request->has('floor_id')) { + $floor_id = $request->input('floor_id'); + if (!empty($floor_id)) { + $query->where('floor_id', $floor_id); + } + } + if ($request->has('space_number')) { + $space_number = $request->input('space_number'); + if (!empty($space_number)) { + $license_plate_id_arr = ParkingSpace::query()->where( + 'number', + $space_number + )->pluck('license_plate_id'); + $license_plate_id_arr ? $query->whereIn( + 'license_plate_id', + $license_plate_id_arr + ) : $query->where('id', 0); + } + } + if ($request->has('space_type_id')) { + $space_type_id = $request->input('space_type_id'); + if (!empty($space_type_id)) { + $query->where('space_type_id', $space_type_id); + } + } + if ($request->has('space_attr_id')) { + $space_attr_id = $request->input('space_attr_id'); + if (!empty($space_attr_id)) { + } + } + if ($request->has('status')) { + $status = $request->input('status'); + if (!empty($status)) { + $query->where('status', $status); + } + } + + // 分页 + $page = $request->input('page', 1); + $perPage = $request->input('per_page', 10); + + $total = $query->count(); + $items = $query->latest()->forPage($page, $perPage)->get()->each( + function ($item) { + $item['status'] = $this->service->getStatusStr( + $item['status'] + ); + $item['space_type'] = ParkingSpaceType::getName( + $item['space_type_id'] + ); + $item['license_plate'] = ParkingLicensePlate::getNumber( + $item['license_plate_id'] + ); + $item['is_driver'] = $this->service->getIsDriver( + $item['is_driver'] + ); + $item['floor'] = AdminFloor::getName($item['floor_id']); + $item['floor_region'] = AdminFloorRegion::getName($item['floor_region_id']); + unset( + $item['space_type_id'], + $item['license_plate_id'], + $item['floor_id'], + $item['floor_region_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() + ); + } + } + + public function search(): JsonResponse + { + try { + $data = [ + 'floor_data' => AdminFloor::getData(), + 'space_type_data' => ParkingSpaceType::getData(), + 'space_attr_data' => ParkingSpaceAttributes::getData(), + 'status_data' => get_select_data( + $this->service->getStatusArr() + ) + ]; + return $this->responseService->success($data); + } catch (Exception $e) { + $m_prefix = __('exception.exception_handler.resource'); + return $this->responseService->systemError( + $m_prefix . ':' . $e->getMessage() + ); + } + } + + public function statistics(Request $request): JsonResponse + { + try { + $start_at = date("Y-m-d 00:00:00"); + $end_at = date("Y-m-d 23:59:59"); + if ($request->has('appointment_date')) { + $appointment_date = $request->input('appointment_date'); + if (!empty($appointment_date)) { + $start_at = date( + "Y-m-d 00:00:00", + strtotime($appointment_date) + ); + $end_at = date( + "Y-m-d 23:59:59", + strtotime($appointment_date) + ); + } + } + $today_count = $this->service->getCount($start_at, $end_at); + $present_count = $this->service->getBePresentCount( + $start_at, + $end_at + ); + $absent_count = $today_count - $present_count; + $data = [ + 'today_count' => $today_count, + 'present_count' => $present_count, + 'absent_count' => max($absent_count, 0) + ]; + return $this->responseService->success($data); + } catch (Exception $e) { + $m_prefix = __('exception.exception_handler.resource'); + return $this->responseService->systemError( + $m_prefix . ':' . $e->getMessage() + ); + } + } + +} diff --git a/app/Http/Controllers/Admin/ParkingSpaceController.php b/app/Http/Controllers/Admin/ParkingSpaceController.php new file mode 100644 index 0000000..d3ceee3 --- /dev/null +++ b/app/Http/Controllers/Admin/ParkingSpaceController.php @@ -0,0 +1,247 @@ +responseService = $responseService; + $this->service = $service; + } + + /** + * Display a listing of the resource. + */ + public function index(Request $request): JsonResponse + { + try { + $query = ParkingSpace::query(); + + if ($request->has('license_plate')) { + $license_plate = $request->input('license_plate'); + if (!empty($license_plate)) { + $license_plate_id_arr = ParkingLicensePlate::query()->where( + 'number', + 'like', + "%{$license_plate}%" + )->pluck('id'); + $license_plate_id_arr ? $query->whereIn( + 'license_plate_id', + $license_plate_id_arr + ) : $query->where('id', 0); + } + } + + if ($request->has('floor')) { + $floor = $request->input('floor'); + if (!empty($floor)) { + $query->where('floor_id', $floor); + } + } + + if ($request->has('number')) { + $number = $request->input('number'); + if (!empty($number)) { + $query->where('number', 'like', "%{$number}%"); + } + } + + if ($request->has('space_type')) { + $space_type = $request->input('space_type'); + if (!empty($space_type)) { + $query->where('space_type_id', $space_type); + } + } + + if ($request->has('space_attr')) { + $space_attr = $request->input('space_attr'); + if (!empty($space_attr)) { + $query->where('space_attr_id', $space_attr); + } + } + + if ($request->has('status')) { + $status = $request->input('status'); + if (!empty($status)) { + $query->where('status', $status); + } + } + + // 分页 + $page = $request->input('page', 1); + $perPage = $request->input('per_page', 10); + $query->orderBy('id'); + $total = $query->count(); + $_this = $this; + $items = $query->latest()->forPage($page, $perPage)->get()->each( + function ($item) use ($_this) { + return $_this->service->optionItems($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 = [ + 'floor_data' => AdminFloor::query()->select(['id', 'name']) + ->get()->toArray(), + 'space_type_data' => ParkingSpaceType::query()->select( + ['id', 'name'] + )->get()->toArray(), + 'space_attr_data' => ParkingSpaceAttributes::query()->select( + ['id', 'attributes'] + )->get()->toArray(), + 'status_data' => get_select_data( + $this->service->getStatusArr() + ) + ]; + return $this->responseService->success($data); + } catch (Exception $e) { + $m_prefix = __('exception.exception_handler.resource'); + return $this->responseService->systemError( + $m_prefix . ':' . $e->getMessage() + ); + } + } + + public function updateType(Request $request): JsonResponse + { + try { + $rules = [ + 'space_type_id' => 'required|numeric', + 'space_ids' => 'required|array' + ]; + $messages = [ + 'space_type_id.required' => __( + 'validation.parking_space.type_id_empty' + ), + 'space_type_id.numeric' => __( + 'validation.parking_space.type_id_numeric' + ), + 'space_ids.required' => __( + 'validation.parking_space.ids_empty' + ), + 'space_ids.array' => __( + 'validation.parking_space.ids_array' + ) + ]; + $validator = Validator::make($request->all(), $rules, $messages); + + if ($validator->fails()) { + throw new ValidationException($validator); + } + $this->service->updateData($request->all()); + return $this->responseService->success( + null, + __('admin.update_succeeded') + ); + } catch (Exception $e) { + return $this->responseService->systemError( + __('exception.parking_space.update_type_failed') . ':' + . $e->getMessage() + ); + } + } + + public function updateAttr(Request $request): JsonResponse + { + try { + $rules = [ + 'space_attr_id' => 'required|numeric', + 'space_ids' => 'required|array' + ]; + $messages = [ + 'space_attr_id.required' => __( + 'validation.parking_space.attr_id_empty' + ), + 'space_attr_id.numeric' => __( + 'validation.parking_space.attr_id_numeric' + ), + 'space_ids.required' => __( + 'validation.parking_space.ids_empty' + ), + 'space_ids.array' => __( + 'validation.parking_space.ids_array' + ) + ]; + $validator = Validator::make($request->all(), $rules, $messages); + + if ($validator->fails()) { + throw new ValidationException($validator); + } + $this->service->updateData($request->all(), 'space_attr_id'); + return $this->responseService->success( + null, + __('admin.update_succeeded') + ); + } catch (Exception $e) { + return $this->responseService->systemError( + __('exception.parking_space.update_attr_failed') . ':' + . $e->getMessage() + ); + } + } + + /** + * @return BinaryFileResponse + */ + public function export(): BinaryFileResponse + { + return Excel::download( + new ParkingSpaceExport(), + __('exports.parking_space.list') . time() . '.xlsx' + ); + } +} diff --git a/app/Imports/ParkingLicensePlateImport.php b/app/Imports/ParkingLicensePlateImport.php new file mode 100644 index 0000000..960b92d --- /dev/null +++ b/app/Imports/ParkingLicensePlateImport.php @@ -0,0 +1,50 @@ +logService = new OperationLogService(); + } + + /** + * @param array $row + * @return ParkingLicensePlate + */ + public function model(array $row): ParkingLicensePlate + { + $data = []; + foreach ($row as $value) { + $data[] = $value; + } + $where = [ + 'number' => $data[0], + 'space_type_id' => $data[1] + ]; + if (!ParkingLicensePlate::query()->where($where) + ->exists() + ) { + $model = new ParkingLicensePlate([ + 'number' => $data[0], + 'space_type_id' => $data[1], + 'created_at' => get_datetime() + ]); + $this->logService->logCreated($model, '创建车牌号码'); + return $model; + } + return new ParkingLicensePlate(); + } +} diff --git a/app/Models/AdminFloor.php b/app/Models/AdminFloor.php index 944c699..68ba4a3 100644 --- a/app/Models/AdminFloor.php +++ b/app/Models/AdminFloor.php @@ -24,5 +24,13 @@ class AdminFloor extends Model 'deleted_at' ]; - + public static function getName($id) + { + return self::query()->where('id', $id)->value('name') ?? ''; + } + + public static function getData(): array + { + return self::query()->select(['id', 'name'])->get()->toArray(); + } } diff --git a/app/Models/AdminFloorRegion.php b/app/Models/AdminFloorRegion.php index ebd5cdf..0cfb319 100644 --- a/app/Models/AdminFloorRegion.php +++ b/app/Models/AdminFloorRegion.php @@ -38,4 +38,8 @@ class AdminFloorRegion extends Model return $count != $existsCount; } + public static function getName($id) + { + return self::query()->where('id', $id)->value('name') ?? ''; + } } diff --git a/app/Models/AdminOperationLog.php b/app/Models/AdminOperationLog.php index 578d819..e2fa6ad 100644 --- a/app/Models/AdminOperationLog.php +++ b/app/Models/AdminOperationLog.php @@ -41,14 +41,6 @@ class AdminOperationLog extends Model 'updated_at' ]; - /** - * 获取进行此操作的用户 - */ - public function user() - { - return $this->belongsTo(User::class); - } - /** * 获取关联的模型 */ diff --git a/app/Models/ParkingLicensePlate.php b/app/Models/ParkingLicensePlate.php index abd2b3b..7ed6171 100644 --- a/app/Models/ParkingLicensePlate.php +++ b/app/Models/ParkingLicensePlate.php @@ -22,4 +22,9 @@ class ParkingLicensePlate extends Model 'updated_at', 'deleted_at' ]; + + public static function getNumber($id) + { + return self::query()->where('id', $id)->value('number') ?? ''; + } } diff --git a/app/Models/ParkingReservation.php b/app/Models/ParkingReservation.php new file mode 100644 index 0000000..5bc4ec8 --- /dev/null +++ b/app/Models/ParkingReservation.php @@ -0,0 +1,43 @@ +toArray(); } + + public static function getAttr($id) + { + return self::query()->where('id', $id)->value('attributes') ?? ''; + } + + public static function getData(): array + { + return self::query()->select(['id', 'attributes'])->get()->toArray(); + } } diff --git a/app/Models/ParkingSpaceType.php b/app/Models/ParkingSpaceType.php index 4e0f850..64f1c5a 100644 --- a/app/Models/ParkingSpaceType.php +++ b/app/Models/ParkingSpaceType.php @@ -9,9 +9,10 @@ use Illuminate\Database\Eloquent\SoftDeletes; class ParkingSpaceType extends Model { use HasFactory, SoftDeletes; + protected $table = 'parking_space_type'; protected $fillable - = [ + = [ 'id', 'name', 'is_default', @@ -26,9 +27,19 @@ class ParkingSpaceType extends Model 'attr_color_warning' ]; protected $hidden - = [ + = [ 'created_at', 'updated_at', 'deleted_at' ]; + + public static function getName($id) + { + return self::query()->where('id', $id)->value('name') ?? ''; + } + + public static function getData(): array + { + return self::query()->select(['id', 'name'])->get()->toArray(); + } } diff --git a/app/Services/BaseService.php b/app/Services/BaseService.php new file mode 100644 index 0000000..9503617 --- /dev/null +++ b/app/Services/BaseService.php @@ -0,0 +1,20 @@ +logService = $logService; + } +} diff --git a/app/Services/ParkingReservationService.php b/app/Services/ParkingReservationService.php new file mode 100644 index 0000000..df28653 --- /dev/null +++ b/app/Services/ParkingReservationService.php @@ -0,0 +1,73 @@ +statusArr[$status] ?? ''; + if ($value) { + return __('service.reservation.' . $value); + } + return $value; + } + + public function getStatusArr(): array + { + $arr = []; + foreach ($this->statusArr as $key => $value) { + $arr[$key] = __('service.reservation.' . $value); + } + return $arr; + } + + public function getIsDriver($is_driver): string + { + $value = $this->isDriver[$is_driver] ?? ''; + if ($value) { + return __('service.reservation.' . $value); + } + return $value; + } + + /** + * @param string $start + * @param string $end + * @return int + */ + public function getCount(string $start, string $end): int + { + return ParkingReservation::query()->whereBetween( + 'confirm_at', + [$start, $end] + )->where('status', 1)->count(); + } + + public function getBePresentCount(string $start, string $end): int + { + $license_plate_id_arr = ParkingReservation::query()->whereBetween( + 'confirm_at', + [$start, $end] + )->where('status', 1)->pluck('license_plate_id'); + return ParkingSpace::query()->whereIn( + 'license_plate_id', + $license_plate_id_arr + )->count(); + } +} diff --git a/app/Services/ParkingSpaceService.php b/app/Services/ParkingSpaceService.php new file mode 100644 index 0000000..bf2570f --- /dev/null +++ b/app/Services/ParkingSpaceService.php @@ -0,0 +1,150 @@ +statusArr[$status] ?? ''; + if ($value) { + return __('service.parking_space.' . $value); + } + return $value; + } + + public function getRecognition($recognition): string + { + if ($recognition) { + return __('service.parking_space.' . $recognition); + } + return '-'; + } + + public function getOperationType($operation_type): string + { + $value = $this->operationType[$operation_type] ?? ''; + if ($value) { + return __('service.parking_space.' . $value); + } + return '-'; + } + + public function getStatusArr(): array + { + $arr = []; + foreach ($this->statusArr as $key => $value) { + $arr[$key] = __('service.parking_space.' . $value); + } + return $arr; + } + + public function optionItems($item) + { + $item['floor'] = AdminFloor::getName($item['floor_id']); + $item['space_attr'] = ParkingSpaceAttributes::getAttr( + $item['space_attr_id'] + ); + $item['space_type'] = ParkingSpaceType::getName( + $item['space_type_id'] + ); + $license_plate = ParkingLicensePlate::getNumber( + $item['license_plate_id'] + ); + $item['license_plate'] = $license_plate ?: '-'; + $item['berthing_time'] = is_null($item['berthing_time']) + ? '-' : $item['berthing_time']; + $item['recognition'] = $this->getRecognition( + $item['recognition'] + ); + $item['status'] = $this->getStatusStr( + $item['status'] + ); + $item['operation_type'] = $this->getOperationType( + $item['operation_type'] + ); + unset( + $item['floor_id'], $item['space_attr_id'], + $item['space_type_id'], $item['license_plate_id'] + ); + return $item; + } + + /** + * 更新车位数据 + * @param array $data + * @param string $key + * @return Builder + * @throws Exception + */ + public function updateData( + array $data, + string $key = 'space_type_id' + ): Builder { + try { + DB::beginTransaction(); + + $ids = $data['space_ids']; + $data_id = $data[$key]; + + $model = ParkingSpace::query()->whereIn('id', $ids)->select(); + $oldValues = $model->get()->toArray(); + + $updateData = [ + $key => $data_id, + 'updated_at' => get_datetime() + ]; + $model->update($updateData); + + $str = $key == 'space_type_id' ? '类型' : '属性'; + + $newValue = $oldValues; + $newValue[$key] = $data_id; + $newValue['updated_at'] = $updateData['updated_at']; + + $this->logService->logUpdatedData( + new ParkingSpace(), + $oldValues, + "更新车位" . $str, + $newValue + ); + DB::commit(); + return $model; + } catch (Exception $e) { + DB::rollBack(); + throw $e; + } + } +} diff --git a/app/common.php b/app/common.php index 87f5b25..122f6ff 100644 --- a/app/common.php +++ b/app/common.php @@ -35,6 +35,7 @@ if (!function_exists('get_datetime')) { $format = match ($type) { 'date' => 'Y-m-d', 'datetime' => 'Y-m-d H:i:s', + 'date_time' => 'Y-m-d H:i' }; return date($format, $times); } diff --git a/database/migrations/2026_03_20_162930_create_parking_reservation_table.php b/database/migrations/2026_03_20_162930_create_parking_reservation_table.php new file mode 100644 index 0000000..cfc23b6 --- /dev/null +++ b/database/migrations/2026_03_20_162930_create_parking_reservation_table.php @@ -0,0 +1,38 @@ +id(); + $table->string('reserve_id', 12)->comment('预定编号'); + $table->integer('space_type_id')->comment('车位类型'); + $table->integer('license_plate_type')->comment('车牌类型'); + $table->integer('license_plate_id')->comment('车牌号码ID'); + $table->tinyInteger('is_driver')->default(0)->comment('是否登记司机'); + $table->integer('floor_id')->nullable()->comment('楼层ID'); + $table->integer('floor_region_id')->nullable()->comment('楼层区域ID'); + $table->tinyInteger('status')->default(0)->comment('状态 0待确定 1已确定 2已取消'); + $table->timestamp('confirm_at')->nullable()->comment('确定时间'); + $table->timestamps(); + $table->comment('车位预定列表'); + $table->innoDb(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('parking_reservation'); + } +}; 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 new file mode 100644 index 0000000..20a259f --- /dev/null +++ b/database/migrations/2026_03_23_143449_create_parking_space_table.php @@ -0,0 +1,36 @@ +id(); + $table->integer('floor_id')->comment('楼层id'); + $table->string('number', 50)->default('')->comment('车位号码'); + $table->integer('space_attr_id')->comment('车位属性id'); + $table->integer('license_plate_id')->nullable()->comment('车牌号码'); + $table->timestamp('berthing_time')->nullable()->comment('停泊时间'); + $table->string('recognition', 50)->default('')->nullable()->comment('车牌识别度'); + $table->tinyInteger('status')->default(0)->comment('状态 0空置 1占用'); + $table->integer('space_type_id')->comment('车位类型id'); + $table->tinyInteger('operation_type')->default(0)->comment('操作类型'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('parking_space'); + } +}; diff --git a/resources/lang/zh-CN/exception.php b/resources/lang/zh-CN/exception.php index 3fdaccd..6e9f21f 100644 --- a/resources/lang/zh-CN/exception.php +++ b/resources/lang/zh-CN/exception.php @@ -57,5 +57,9 @@ return [ 'update_failed' => '更新车牌号码失败', 'destroy_failed' => '删除车牌号码失败', 'clear_failed' => '清除车牌号码失败' + ], + 'parking_space' => [ + 'update_type_failed' => '修改车位类型失败', + 'update_attr_failed' => '修改车位属性失败' ] ]; diff --git a/resources/lang/zh-CN/exports.php b/resources/lang/zh-CN/exports.php index f405d6b..7fe4c96 100644 --- a/resources/lang/zh-CN/exports.php +++ b/resources/lang/zh-CN/exports.php @@ -1,15 +1,28 @@ [ - 'license' => '车牌号码', + 'vip_list' => [ + 'license' => '车牌号码', 'import_template' => 'VIP名单导入模板', - 'list' => 'VIP名单' + 'list' => 'VIP名单' ], - 'global' => [ + 'global' => [ 'index' => '序号', 'admin' => '操作员' ], 'license_plate' => [ 'import_template' => '车牌管理导入模板' + ], + 'parking_space' => [ + 'list' => '车位列表', + 'floor' => '楼层', + 'number' => '车位号码', + 'space_attr' => '车位属性', + 'license_plate' => '车牌号码', + 'berthing_time' => '停泊时间', + 'recognition' => '车牌识别度', + 'status' => '状态', + 'space_type' => '车位类型', + 'operation_type' => '操作类型', + 'updated_at' => '最后更新时间', ] ]; diff --git a/resources/lang/zh-CN/service.php b/resources/lang/zh-CN/service.php index 82696e7..51a886a 100644 --- a/resources/lang/zh-CN/service.php +++ b/resources/lang/zh-CN/service.php @@ -21,18 +21,35 @@ return [ 'attributes_exists' => '车位属性名称已存在' ], 'space_type' => [ - 'red' => '红色', - 'green' => '绿色', - 'yellow' => '黄色', - 'blue' => '蓝色', - 'purple' => '紫色', - 'cyan' => '青色', - 'white' => '白色', - 'name_exists' => '车位类型名称已存在', + 'red' => '红色', + 'green' => '绿色', + 'yellow' => '黄色', + 'blue' => '蓝色', + 'purple' => '紫色', + 'cyan' => '青色', + 'white' => '白色', + 'name_exists' => '车位类型名称已存在', 'license_exists' => '请先清空车牌,即可删除' ], - 'license_plate' => [ + 'license_plate' => [ 'number_exists' => '车牌号码已存在', 'not_clear' => '没有车牌需要清除' + ], + 'reservation' => [ + 'undetermined' => '待确定', + 'confirmed' => '已确定', + 'canceled' => '已取消', + 'yes' => '是', + 'no' => '否' + ], + 'parking_space' => [ + 'vacant' => '空置', + 'occupy' => '占用', + 'high' => '高', + 'middle' => '中', + 'land' => '低', + 'no_cars' => '车位状态无车更新有车', + 'yes_cars' => '车位状态有车更新无车', + 'number_update' => '车牌号更新' ] ]; diff --git a/resources/lang/zh-CN/validation.php b/resources/lang/zh-CN/validation.php index 21d2024..e6fa13d 100644 --- a/resources/lang/zh-CN/validation.php +++ b/resources/lang/zh-CN/validation.php @@ -58,15 +58,23 @@ return [ 'file_mimes' => '导入文件类型必须是xlsx|xls|csv', 'file_max' => '导入文件最大不超过2048' ], - 'space_attributes' => [ + 'space_attributes' => [ 'a_empty' => '车位属性名称不能为空', 'i_empty' => '汇入图示不能为空' ], - 'space_type' => [ + 'space_type' => [ 'n_empty' => '车位类型名称不能为空' ], - 'license_plate' => [ - 'n_empty' => '车牌号码不能为空', + 'license_plate' => [ + 'n_empty' => '车牌号码不能为空', 'type_empty' => '车位类型不能为空' + ], + 'type_id_empty' => [ + 'type_id_empty' => '车位类型数据不能为空', + 'type_id_numeric' => '车位类型数据必须是数字', + 'attr_id_empty' => '车位属性数据不能为空', + 'attr_id_numeric' => '车位属性数据必须是数字', + 'ids_empty' => '车位数据不能为空', + 'ids_array' => '车位数据必须是数组', ] ]; diff --git a/routes/admin/api.php b/routes/admin/api.php index 7db8c39..3501c9a 100644 --- a/routes/admin/api.php +++ b/routes/admin/api.php @@ -8,6 +8,8 @@ use App\Http\Controllers\Admin\VipAccessRecordController; use App\Http\Controllers\Admin\VipListController; use App\Http\Controllers\Admin\OperationLogController; use App\Http\Controllers\Admin\ParkingLicensePlateController; +use App\Http\Controllers\Admin\ParkingReservationController; +use App\Http\Controllers\Admin\ParkingSpaceController; use App\Http\Controllers\Admin\ParkingSpaceAttributesController; use App\Http\Controllers\Admin\ParkingSpaceTypeController; use App\Http\Controllers\Admin\RolesController; @@ -31,6 +33,15 @@ Route::group(['prefix' => 'admin'], function () { // 首页 Route::get('/index', [IndexController::class, 'index']); Route::get('/menu', [IndexController::class, 'menu']); + // 车位预定列表 + Route::get('/parkingReservation', [ParkingReservationController::class, 'index']); + Route::get('/parkingReservation/search', [ParkingReservationController::class, 'search']); + Route::get('/parkingReservation/statistics', [ParkingReservationController::class, 'statistics']); + // 车位列表 + Route::get('/parkingSpace', [ParkingSpaceController::class, 'index']); + Route::get('/parkingSpace/search', [ParkingSpaceController::class, 'search']); + Route::post('parkingSpace/updateType', [ParkingSpaceController::class, 'updateType']); + Route::post('parkingSpace/updateAttr', [ParkingSpaceController::class, 'updateAttr']); //车位类型管理 Route::get('/spaceType', [ParkingSpaceTypeController::class, 'index']); Route::get('/spaceType/create', [ParkingSpaceTypeController::class, 'create']); @@ -112,4 +123,5 @@ Route::group(['prefix' => 'admin'], function () { Route::get('/vipList/import_template', [VipListController::class, 'importTemplate']); Route::get('/vipList/export', [VipListController::class, 'export']); Route::get('/licensePlate/import_template', [ParkingLicensePlateController::class, 'importTemplate']); + Route::get('/parkingSpace/export', [ParkingSpaceController::class, 'export']); });