停车场管理系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

269 lines
7.4 KiB

<?php
namespace App\Services;
use App\Models\ParkingLicensePlate;
use App\Models\ParkingSpaceType;
use Exception;
use Illuminate\Support\Facades\DB;
class ParkingLicensePlateService
{
/**
* @var OperationLogService
*/
private OperationLogService $logService;
/**
* 构造函数
* @param OperationLogService $logService
*/
public function __construct(OperationLogService $logService)
{
$this->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}|(?:[A-HJ-NP-Z0-9][0-9]{4}|[A-HJ-NP-Z0-9]{5}))$/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);
}
}