diff --git a/app/Http/Controllers/Admin/FloorController.php b/app/Http/Controllers/Admin/FloorController.php index c4ba0fa..70b6826 100644 --- a/app/Http/Controllers/Admin/FloorController.php +++ b/app/Http/Controllers/Admin/FloorController.php @@ -93,10 +93,7 @@ class FloorController extends BaseController $item['building_floor'] ); $item['status_str'] = $statusArr[$item['status']]; - $item['parking_space_count'] = ParkingSpace::query()->where( - 'floor_id', - $item['id'] - )->count(); + $item['parking_space_count'] = ParkingSpace::getFloorCount($item['id']);; $open_time_res = option_time($item['open_time']); $item['open_time'] = $open_time_res['time']; $item['open_time_str'] = $open_time_res['str']; diff --git a/app/Http/Controllers/Admin/RegionalManagementController.php b/app/Http/Controllers/Admin/RegionalManagementController.php new file mode 100644 index 0000000..cca86d7 --- /dev/null +++ b/app/Http/Controllers/Admin/RegionalManagementController.php @@ -0,0 +1,282 @@ +service = $service; + } + + /** + * @param Request $request + * @return JsonResponse + */ + public function index(Request $request): JsonResponse + { + try { + $query = AdminFloorRegion::query(); + + if ($request->has('floor_id')) { + $floor_id = $request->input('floor_id'); + if ($floor_id) { + $query->where('floor_id', $floor_id); + } + } + + if ($request->has('name')) { + $name = $request->input('name'); + if ($name) { + $query->where('name', 'like', "%{$name}%"); + } + } + + if ($request->has('create_start_time') + && $request->has( + 'create_end_time' + ) + ) { + $create_start_time = $request->input('create_start_time'); + $create_end_time = $request->input('create_end_time'); + if ($create_start_time && $create_end_time) { + $query->whereBetween('created_at', [ + $create_start_time . ' 00:00:00', + $create_end_time . ' 23:59:59' + ]); + } + } + + // 分页 + $page = $request->input('page', 1); + $perPage = $request->input('per_page', 10); + $statusArr = AdminFloorRegionService::getStatus(); + $total = $query->count(); + $items = $query->latest()->forPage($page, $perPage)->get()->each( + function ($item) use ($statusArr) { + $item['name'] + = AdminTranslationService::getTranslationTypeName( + $item['id'], + 5, + $item['name'] + ); + $item['floor'] = AdminFloor::getName($item['floor_id']); + $item['status_str'] = $statusArr[$item['status']]; + $item['parking_space_count'] = ParkingSpace::getFloorCount( + $item['floor_id'] + ); + $open_time_res = option_time($item['open_time']); + $item['open_time'] = $open_time_res['time']; + $item['open_time_str'] = $open_time_res['str']; + $close_time_res = option_time($item['close_time']); + $item['close_time'] = $close_time_res['time']; + $item['close_time_str'] = $close_time_res['str']; + 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() + ); + } + } + + /** + * 列表搜索数据 + * @return JsonResponse + */ + public function search(): JsonResponse + { + try { + $data = [ + 'floor_list' => AdminFloor::getData() + ]; + return $this->responseService->success($data); + } 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( + __('exception.admin_floor.create_failed') . ':' + . $e->getMessage() + ); + } + } + + /** + * @param array $data + * @param int $id + * @return void + * @throws ValidationException + */ + protected function saveValidator(array $data, int $id = 0): void + { + $rules = [ + 'name' => 'required|max:50', + 'open_time' => 'required|size:5', + 'close_time' => 'required|size:5', + ]; + $messages = [ + 'name.required' => __('validation.admin_floor.n_empty'), + 'name.max' => __('validation.admin_floor.n_max'), + 'open_time.required' => __( + 'validation.parking_management.o_empty' + ), + 'open_time.size' => __( + 'validation.parking_management.o_length' + ), + 'close_time.required' => __( + 'validation.parking_management.c_empty' + ), + 'close_time.size' => __( + 'validation.parking_management.c_length' + ) + ]; + if ($id) { + $this->validateId($id, AdminFloorRegion::class); + } + $validator = Validator::make($data, $rules, $messages); + + if ($validator->fails()) { + throw new ValidationException($validator); + } + } + + /** + * @param string $id + * @return JsonResponse + */ + public function edit(string $id): JsonResponse + { + try { + $this->validateId($id, AdminFloorRegion::class); + $data = [ + 'building_floor_list' => get_select_data( + AdminFloorService::getBuildingFloor() + ), + 'floor_list' => AdminFloor::getData(), + 'item' => AdminFloorRegion::query()->find($id) + ]; + $AdminFloor = AdminFloor::getFirst($data['item']['floor_id']); + $data['item']['building_floor'] = $AdminFloor['building_floor'] ?? ''; + 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 { + $this->saveValidator($request->all(), $id); + $this->service->updateModel($request->all(), $id); + return $this->responseService->success( + null, + __('admin.update_succeeded') + ); + } catch (ValidationException|CustomException $e) { + throw $e; + } catch (Exception $e) { + return $this->responseService->systemError( + __('exception.admin_floor.update_failed') . ':' + . $e->getMessage() + ); + } + } + + /** + * @param string $id + * @return JsonResponse + * @throws CustomException + * @throws ValidationException + */ + public function destroy(string $id): JsonResponse + { + try { + $this->validateId($id, AdminFloorRegion::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( + __('exception.admin_floor.destroy_failed') . ':' + . $e->getMessage() + ); + } + } +} diff --git a/app/Models/AdminFloor.php b/app/Models/AdminFloor.php index ffee0dd..9cadf89 100644 --- a/app/Models/AdminFloor.php +++ b/app/Models/AdminFloor.php @@ -28,14 +28,10 @@ class AdminFloor extends Model 'deleted_at' ]; - public function getCreatedAtAttribute($value): string - { - return $value ? date("Y-m-d H:i:s", strtotime($value)) : $value; - } - public static function getName($id) { - return self::query()->where('id', $id)->value('name') ?? ''; + $name = self::query()->where('id', $id)->value('name') ?? ''; + return AdminTranslationService::getTranslationTypeName($id, 4, $name); } public static function getData(): array @@ -53,4 +49,20 @@ class AdminFloor extends Model } )->toArray() ?? []; } + + public static function getFirst($id) + { + $item = self::query()->where(['status' => 1, 'id' => $id])->first(); + $item['name'] = AdminTranslationService::getTranslationTypeName( + $item['id'], + 4, + $item['name'] + ); + return $item; + } + + public function getCreatedAtAttribute($value): string + { + return $value ? date("Y-m-d H:i:s", strtotime($value)) : $value; + } } diff --git a/app/Models/AdminFloorRegion.php b/app/Models/AdminFloorRegion.php index 35867c0..12f89da 100644 --- a/app/Models/AdminFloorRegion.php +++ b/app/Models/AdminFloorRegion.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Services\AdminTranslationService; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; @@ -12,13 +13,25 @@ class AdminFloorRegion extends Model protected $table = 'admin_floor_region'; + protected $fillable = [ + 'name', + 'floor_id', + 'open_time', + 'close_time', + 'status' + ]; + protected $hidden = [ - 'created_at', 'updated_at', 'deleted_at' ]; + public function getCreatedAtAttribute($value): string + { + return $value ? date("Y-m-d H:i:s", strtotime($value)) : $value; + } + /** * @param int $floor_id * @return array @@ -26,20 +39,13 @@ class AdminFloorRegion extends Model public static function getFloorRegion(int $floor_id): array { $columns = ['id','name']; - return self::query()->where('floor_id', $floor_id)->select($columns) + return self::query()->where('floor_id', $floor_id)->where('status', 1)->select($columns) ->get()->toArray(); } - public static function existsRoleMenu($floor_id, $nameArr): bool - { - $count = count($nameArr); - $existsCount = self::query()->where('floor_id', $floor_id) - ->whereIn('name', $nameArr)->count(); - return $count != $existsCount; - } - public static function getName($id) { - return self::query()->where('id', $id)->value('name') ?? ''; + $name = self::query()->where('id', $id)->where('status', 1)->value('name') ?? ''; + return AdminTranslationService::getTranslationTypeName($id, 5, $name); } } diff --git a/app/Models/AdminTranslation.php b/app/Models/AdminTranslation.php index 257f1ae..fb8566b 100644 --- a/app/Models/AdminTranslation.php +++ b/app/Models/AdminTranslation.php @@ -32,5 +32,6 @@ class AdminTranslation extends Model 2 车位属性 3 停车场 4 楼层管理 + 5 区域管理 */ } diff --git a/app/Models/ParkingSpace.php b/app/Models/ParkingSpace.php index b87499b..e17501f 100644 --- a/app/Models/ParkingSpace.php +++ b/app/Models/ParkingSpace.php @@ -91,4 +91,9 @@ class ParkingSpace extends Model } return $model->count(); } + + public static function getFloorCount($floor_id) + { + return self::query()->where('floor_id', $floor_id)->count(); + } } diff --git a/app/Services/AdminFloorRegionService.php b/app/Services/AdminFloorRegionService.php new file mode 100644 index 0000000..27b4053 --- /dev/null +++ b/app/Services/AdminFloorRegionService.php @@ -0,0 +1,148 @@ + $value) { + $statusArr[$key] = __('admin.' . $value); + } + return $statusArr; + } + + /** + * 创建角色 + * @param array $data + * @throws Exception + */ + public function createModel(array $data) + { + try { + DB::beginTransaction(); + + $existsWhere = [ + ['name', '=', $data['name']], + ['floor_id', '=', $data['floor_id']] + ]; + if (AdminFloorRegion::query()->where($existsWhere)->exists()) { + throw new Exception(__('service.admin_floor.name_exists')); + } + + $model = AdminFloorRegion::query()->create([ + 'name' => $data['name'], + 'floor_id' => $data['floor_id'], + 'open_time' => $data['open_time'], + 'close_time' => $data['close_time'], + 'created_at' => get_datetime() + ]); + + $this->logService->logCreated($model, 'admin_floor.region_create'); + + AdminTranslationService::saveTranslation( + $data['name'], + $data['en_name'] ?? '', + $data['tw_name'] ?? '', + $model->id, + 5 + ); + + 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(); + + // 验证 + $existsWhere = [ + ['name', '=', $data['name']], + ['floor_id', '=', $data['floor_id']], + ['id', '<>', $id] + ]; + if (AdminFloorRegion::query()->where($existsWhere)->exists()) { + throw new Exception(__('service.admin_role.name_exists')); + } + + // 更新 + $model = AdminFloorRegion::query()->findOrFail($id); + $oldValues = $model->toArray(); + + $model->update([ + 'name' => $data['name'], + 'floor_id' => $data['floor_id'], + 'open_time' => $data['open_time'], + 'close_time' => $data['close_time'], + 'updated_at' => get_datetime() + ]); + + $this->logService->logUpdated( + $model, + $oldValues, + 'admin_floor.region_update' + ); + + AdminTranslationService::saveTranslation( + $data['name'], + $data['en_name'] ?? '', + $data['tw_name'] ?? '', + $id, + 5 + ); + + 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 = AdminFloorRegion::query()->findOrFail($id); + + $this->logService->logDeleted($model, 'admin_floor.region_delete'); + + $model->delete(); + + DB::commit(); + return true; + } catch (Exception $e) { + DB::rollBack(); + throw $e; + } + } +} diff --git a/app/Services/AdminFloorService.php b/app/Services/AdminFloorService.php index fd0bb17..07aad14 100644 --- a/app/Services/AdminFloorService.php +++ b/app/Services/AdminFloorService.php @@ -82,31 +82,6 @@ class AdminFloorService } } - /** - * 同步添加区域关联数据 - * @param int $floor_id - * @param array $regionData - * @return void - */ - private function addAdminFloorRegion(int $floor_id, array $regionData): void - { - $regionSaveData = []; - foreach ($regionData as $value) { - $regionSaveData[] = [ - 'floor_id' => $floor_id, - 'name' => $value['name'], - 'created_at' => get_datetime() - ]; - } - AdminFloorRegion::query()->insert($regionSaveData); - $AdminRoleMenuData = AdminFloorRegion::getFloorRegion($floor_id); - $this->logService->logCreatedData( - new AdminFloorRegion(), - 'admin_floor.region_create', - $AdminRoleMenuData - ); - } - /** * @param array $data * @param int $id @@ -157,18 +132,6 @@ class AdminFloorService } } - protected function delAdminFloorRegion($floor_id): void - { - $oldData = AdminFloorRegion::query()->where('floor_id', $floor_id) - ->select()->get()->toArray(); - $this->logService->logDeletedData( - new AdminFloorRegion(), - 'admin_floor.region_delete', - $oldData - ); - AdminFloorRegion::query()->where('floor_id', $floor_id)->delete(); - } - /** * @param $id * @return bool diff --git a/app/common.php b/app/common.php index 7f47f0e..b54fefb 100644 --- a/app/common.php +++ b/app/common.php @@ -186,12 +186,15 @@ if (!function_exists('get_year_month_days')) { if (!function_exists('option_time')) { function option_time($time): array { - $str = 'AM'; - $end_str = 'PM'; - $arr = explode(':', $time); - if ($arr[0] > 12) { - $time = ($arr[0] - 12) . ':' . $arr[1]; - $str = $end_str; + $str = ''; + if ($time) { + $str = 'AM'; + $end_str = 'PM'; + $arr = explode(':', $time); + if ($arr[0] > 12) { + $time = ($arr[0] - 12) . ':' . $arr[1]; + $str = $end_str; + } } return [ 'time' => $time, diff --git a/database/migrations/2026_02_12_171402_create_admin_floor_region_table.php b/database/migrations/2026_02_12_171402_create_admin_floor_region_table.php index 0288e13..b45d246 100644 --- a/database/migrations/2026_02_12_171402_create_admin_floor_region_table.php +++ b/database/migrations/2026_02_12_171402_create_admin_floor_region_table.php @@ -15,6 +15,9 @@ return new class extends Migration $table->id(); $table->integer('floor_id')->comment('楼层ID'); $table->string('name')->comment('区域名称'); + $table->char('open_time', 5)->comment('开门时间'); + $table->char('close_time', 5)->comment('关门时间'); + $table->tinyInteger('status')->default(1)->comment('状态'); $table->timestamps(); $table->innoDb(); }); diff --git a/resources/lang/en/log.php b/resources/lang/en/log.php index e583a74..e6dfb25 100644 --- a/resources/lang/en/log.php +++ b/resources/lang/en/log.php @@ -10,8 +10,9 @@ return [ 'create' => 'Create floor', 'update' => 'Update floors', 'delete' => 'Delete floor', - 'region_create' => 'Create floor associated area', - 'region_delete' => 'Delete role association menu', + 'region_create' => 'Create floor area', + 'region_update' => 'Update floor area', + 'region_delete' => 'Delete Character Menu' ], 'role' => [ 'create' => 'Create Role', diff --git a/resources/lang/zh-CN/log.php b/resources/lang/zh-CN/log.php index 93f9702..a5160e5 100644 --- a/resources/lang/zh-CN/log.php +++ b/resources/lang/zh-CN/log.php @@ -10,8 +10,9 @@ return [ 'create' => '创建楼层', 'update' => '更新楼层', 'delete' => '删除楼层', - 'region_create' => '创建楼层关联区域', - 'region_delete' => '删除角色关联菜单', + 'region_create' => '创建楼层区域', + 'region_update' => '更新楼层区域', + 'region_delete' => '删除角色菜单' ], 'role' => [ 'create' => '创建角色', diff --git a/resources/lang/zh-TW/log.php b/resources/lang/zh-TW/log.php index b9f7c33..a697c8b 100644 --- a/resources/lang/zh-TW/log.php +++ b/resources/lang/zh-TW/log.php @@ -10,8 +10,9 @@ return [ 'create' => '創建樓層', 'update' => '更新樓層', 'delete' => '删除樓層', - 'region_create' => '創建樓層關聯區域', - 'region_delete' => '删除角色關聯選單', + 'region_create' => '創建樓層區域', + 'region_update' => '更新樓層區域', + 'region_delete' => '删除角色選單' ], 'role' => [ 'create' => '創建角色', diff --git a/routes/admin/api.php b/routes/admin/api.php index 792ef35..9d7b570 100644 --- a/routes/admin/api.php +++ b/routes/admin/api.php @@ -30,6 +30,7 @@ use App\Http\Controllers\Admin\ParkingBehaviorController; use App\Http\Controllers\Admin\ParkingManagementController; use App\Http\Controllers\Admin\ParkingManagementListController; use App\Http\Controllers\Admin\parkingAttendantController; +use App\Http\Controllers\Admin\RegionalManagementController; Route::group(['prefix' => 'admin'], function () { @@ -228,6 +229,14 @@ Route::group(['prefix' => 'admin'], function () { Route::put('/parkingAttendant/{id}', [parkingAttendantController::class, 'update']); Route::delete('/parkingAttendant/{id}', [parkingAttendantController::class, 'destroy']); Route::get('/parkingAttendant/rule', [parkingAttendantController::class, 'rule']); + // 楼层配置 + Route::get('/regionalManagement', [RegionalManagementController::class, 'index']); + Route::post('/regionalManagement', [RegionalManagementController::class, 'store']); + Route::get('/regionalManagement/edit/{id}', [RegionalManagementController::class, 'edit']); + Route::put('/regionalManagement/{id}', [RegionalManagementController::class, 'update']); + Route::delete('/regionalManagement/{id}', [RegionalManagementController::class, 'destroy']); + Route::get('/regionalManagement/rule', [RegionalManagementController::class, 'rule']); + Route::get('/regionalManagement/search', [RegionalManagementController::class, 'search']); // 角色 Route::get('/roles', [RolesController::class, 'index']); Route::get('/roles/create', [RolesController::class, 'create']);