logService = $logService; $this->logService->menuTitle = 'cat_attr'; } /** * 创建车牌号码 * @param array $data * @throws Exception */ public function createModel(array $data) { try { DB::beginTransaction(); $model = $this->createData($data); DB::commit(); return $model; } catch (Exception $e) { DB::rollBack(); throw $e; } } /** * @param $data * @throws Exception */ public function createData($data) { $license = ParkingLicensePlate::query()->whereRaw( 'BINARY `number` = ?', [$data['number']] )->first(); if ($license && $license['space_type_id']) { throw new Exception(__('service.license_plate.number_exists')); } if ($license) { return $this->updateData( $license['id'], $data['number'], $data['space_type_id'] ); } else { return $this->createNumber($data['number'], $data['space_type_id']); } } public function createNumber($number, $space_type_id = 0) { $model = ParkingLicensePlate::query()->create([ '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, $space_type_id = 0) { $id = ParkingLicensePlate::getValueId($number); if (!$id) { $model = $this->createNumber($number, $space_type_id); $id = $model->id; } return $id; } public function updateData($id, $number, $space_type_id) { $update = [ 'number' => $number, 'space_type_id' => $space_type_id, 'updated_at' => date("Y-m-d H:i:s", time()) ]; $model = ParkingLicensePlate::query()->findOrFail($id); $oldValues = $model->toArray(); $model->update($update); $this->logService->logUpdated($model, $oldValues, 'license_plate.update'); return $model; } /** * @param array $data * @param int $id * @throws Exception */ public function updateModel(array $data, int $id) { try { DB::beginTransaction(); // 验证 $existsWhere = [ ['id', '<>', $id] ]; if (ParkingLicensePlate::query()->where($existsWhere)->whereRaw( 'BINARY `number` = ?', [$data['number']] )->exists()) { throw new Exception(__('service.license_plate.number_exists')); } // 更新 $model = ParkingLicensePlate::query()->findOrFail($id); $oldValues = $model->toArray(); $model->update([ 'number' => $data['number'], 'updated_at' => get_datetime() ]); $this->logService->logUpdated($model, $oldValues, 'license_plate.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 = ParkingLicensePlate::query()->findOrFail($id); $this->logService->logDeleted($model, 'license_plate.delete'); $model->delete(); DB::commit(); return true; } catch (Exception $e) { DB::rollBack(); throw $e; } } public function clearModel($space_type_id): bool { try { DB::beginTransaction(); $oldLicensePlate = ParkingLicensePlate::query()->where( 'space_type_id', $space_type_id ) ->select()->get()->toArray(); if (empty($oldLicensePlate)) { throw new Exception(__('service.license_plate.not_clear')); } $this->logService->logDeletedData( new ParkingLicensePlate(), 'license_plate.delete', $oldLicensePlate ); ParkingLicensePlate::query()->where('space_type_id', $space_type_id) ->delete(); DB::commit(); return true; } catch (Exception $e) { DB::rollBack(); throw $e; } } public function createLicenseId($number, $space_type_id = 0) { if (strlen($number) > 20) { return 0; } $license_id = ParkingLicensePlate::getValueId($number); if (!$license_id) { if (!$space_type_id) { $space_type = ParkingSpaceType::getDefaultData(); $space_type_id = $space_type['id'] ?? 0; } $licenseModel = $this->createData([ 'number' => $number, 'space_type_id' => $space_type_id ]); $license_id = $licenseModel->id; } return $license_id; } // 验证车牌格式 public function validateLicensePlate($license_plate): string { $plate = str_replace(' ', '', $license_plate); // 2. 根据车牌类型选择正则 if ($this->isMainlandChinaPlate($plate)) { // 中国大陆车牌校验(禁止 I、O) $pattern = '/^[\x{4e00}-\x{9fa5}][A-Z](?:[A-HJ-NP-Z0-9]{6}|(?:[DF][A-HJ-NP-Z0-9][0-9]{5}|[0-9]{6}[DF]))$/u'; if (!preg_match($pattern, $plate)) { return __validation('parking_space.zh_plate'); } } elseif ($this->isHongKongPlate($plate)) { // 中国香港车牌校验(禁止 I、O、Q) $pattern = '/^[A-HJ-NPR-Z0-9]{1,8}$/'; if (!preg_match($pattern, $plate)) { return __validation('parking_space.hk_plate'); } } else { return __validation('parking_space.error_plate'); } return ''; } private function isMainlandChinaPlate(string $plate): bool { // 长度校验:普通车牌7位,新能源车牌8位[reference:12][reference:13] $length = mb_strlen($plate); if (!in_array($length, [7, 8])) { return false; } // 基础格式校验:首字为汉字,第二位为大写字母 if (!preg_match('/^[\x{4e00}-\x{9fa5}][A-Z]/u', $plate)) { return false; } return true; } private function isHongKongPlate(string $plate): bool { // 长度校验:1-8位 $length = strlen($plate); if ($length < 1 || $length > 8) { return false; } // 仅包含字母和数字 return ctype_alnum($plate); } }