Browse Source

车位属性管理,车位管理,上传中文翻译

master
wanghongjun 6 days ago
parent
commit
c5b2e1e7c6
  1. 174
      app/Http/Controllers/Admin/ParkingLicensePlateController.php
  2. 224
      app/Http/Controllers/Admin/ParkingSpaceTypeController.php
  3. 19
      app/Models/ParkingLicensePlate.php
  4. 20
      app/Models/ParkingSpaceAttributes.php
  5. 24
      app/Models/ParkingSpaceType.php
  6. 124
      app/Services/ParkingLicensePlateService.php
  7. 174
      app/Services/ParkingSpaceTypeService.php
  8. 3
      composer.json
  9. 593
      composer.lock
  10. 40
      database/migrations/2026_03_09_143728_create_parking_space_type_table.php
  11. 30
      database/migrations/2026_03_09_171738_create_parking_license_plate_table.php
  12. 30
      resources/lang/zh-CN/controller.php
  13. 60
      resources/lang/zh-CN/exception.php
  14. 13
      resources/lang/zh-CN/menu.php
  15. 22
      resources/lang/zh-CN/middleware.php
  16. 36
      resources/lang/zh-CN/service.php
  17. 72
      resources/lang/zh-CN/validation.php

174
app/Http/Controllers/Admin/ParkingLicensePlateController.php

@ -0,0 +1,174 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Exceptions\CustomException;
use App\Models\ParkingLicensePlate;
use App\Services\ApiResponseService;
use App\Services\ParkingLicensePlateService;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
class ParkingLicensePlateController extends BaseController
{
/**
* @var ApiResponseService
*/
protected ApiResponseService $responseService;
/**
* @var ParkingLicensePlateService
*/
protected ParkingLicensePlateService $LicensePlateService;
/**
* 构造函数
* @param ApiResponseService $responseService
* @param ParkingLicensePlateService $LicensePlateService
*/
public function __construct(
ApiResponseService $responseService,
ParkingLicensePlateService $LicensePlateService,
) {
$this->responseService = $responseService;
$this->LicensePlateService = $LicensePlateService;
}
/**
* Display a listing of the resource.
*/
public function index(Request $request): JsonResponse
{
try {
$query = ParkingLicensePlate::query();
// 车位类型搜索
$space_type_id = $request->input('space_type_id');
$query->where('space_type_id', '=', $space_type_id);
// 分页
$page = $request->input('page', 1);
$perPage = $request->input('per_page', 10);
$total = $query->count();
$items = $query->latest()->forPage($page, $perPage)->get();
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()
);
}
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
try {
$this->saveValidator($request->all());
$this->LicensePlateService->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.license_plate.create_failed') . ':' . $e->getMessage(
)
);
}
}
/**
* @param array $data
* @param int $id
* @return void
* @throws ValidationException
*/
protected function saveValidator(array $data, int $id = 0): void
{
$rules = [
'number' => 'required',
];
$messages = [
'number.required' => __(
'validation.license_plate.n_empty'
)
];
if ($id) {
$this->validateId($id, ParkingLicensePlate::class);
} else {
$rules['space_type_id'] = 'required';
$messages['space_type_id.required'] = __('validation.license_plate.type_empty');
}
$validator = Validator::make($data, $rules, $messages);
if ($validator->fails()) {
throw new ValidationException($validator);
}
}
/**
* @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->LicensePlateService->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.license_plate.update_failed') . ':' . $e->getMessage(
)
);
}
}
/**
* @param string $id
* @return JsonResponse
* @throws CustomException
* @throws ValidationException
*/
public function destroy(string $id): JsonResponse
{
try {
$this->validateId($id, ParkingLicensePlate::class);
$this->LicensePlateService->deleteModel($id);
return $this->responseService->success(
null,
__('admin.delete_succeeded')
);
} catch (ValidationException|CustomException $e) {
throw $e;
} catch (Exception $e) {
return $this->responseService->systemError(
__('exception.license_plate.destroy_failed') . ':'
. $e->getMessage()
);
}
}
}

224
app/Http/Controllers/Admin/ParkingSpaceTypeController.php

@ -0,0 +1,224 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Exceptions\CustomException;
use App\Models\ParkingSpaceAttributes;
use App\Models\ParkingSpaceType;
use App\Services\ApiResponseService;
use App\Services\ParkingSpaceTypeService;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
class ParkingSpaceTypeController extends BaseController
{
/**
* @var ApiResponseService
*/
protected ApiResponseService $responseService;
/**
* @var ParkingSpaceTypeService
*/
protected ParkingSpaceTypeService $SpaceTypeService;
/**
* 构造函数
* @param ApiResponseService $responseService
* @param ParkingSpaceTypeService $SpaceTypeService
*/
public function __construct(
ApiResponseService $responseService,
ParkingSpaceTypeService $SpaceTypeService,
) {
$this->responseService = $responseService;
$this->SpaceTypeService = $SpaceTypeService;
}
/**
* Display a listing of the resource.
*/
public function index(Request $request): JsonResponse
{
try {
$query = ParkingSpaceType::query();
// 分页
$page = $request->input('page', 1);
$perPage = $request->input('per_page', 10);
$total = $query->count();
$items = $query->latest()->forPage($page, $perPage)->get();
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()
);
}
}
/**
* Show the form for creating a new resource.
*/
public function create(): JsonResponse
{
try {
$data = [
'color_list' => $this->SpaceTypeService->getColorList(),
'attr_list' => ParkingSpaceAttributes::getList()
];
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
{
try {
$this->saveValidator($request->all());
$this->SpaceTypeService->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.space_type.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',
];
$messages = [
'name.required' => __(
'validation.space_type.n_empty'
)
];
if ($id) {
$this->validateId($id, ParkingSpaceAttributes::class);
}
$validator = Validator::make($data, $rules, $messages);
if ($validator->fails()) {
throw new ValidationException($validator);
}
}
/**
* Display the specified resource.
*/
public function show(string $id): JsonResponse
{
return $this->extracted($id);
}
protected function extracted(string $id): JsonResponse
{
try {
$this->validateId($id, ParkingSpaceType::class);
$data = [
'color_list' => $this->SpaceTypeService->getColorList(),
'attr_list' => ParkingSpaceAttributes::getList(),
'item' => ParkingSpaceType::query()->findOrFail($id)->toArray()
];
return $this->responseService->success($data);
} catch (Exception $e) {
return $this->responseService->systemError(
__('exception.get_data_failed') . ':' . $e->getMessage()
);
}
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id): JsonResponse
{
return $this->extracted($id);
}
/**
* @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->SpaceTypeService->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.space_type.update_failed') . ':' . $e->getMessage(
)
);
}
}
/**
* @param string $id
* @return JsonResponse
* @throws CustomException
* @throws ValidationException
*/
public function destroy(string $id): JsonResponse
{
try {
$this->validateId($id, ParkingSpaceType::class);
$this->SpaceTypeService->deleteModel($id);
return $this->responseService->success(
null,
__('admin.delete_succeeded')
);
} catch (ValidationException|CustomException $e) {
throw $e;
} catch (Exception $e) {
return $this->responseService->systemError(
__('exception.space_type.destroy_failed') . ':'
. $e->getMessage()
);
}
}
}

19
app/Models/ParkingLicensePlate.php

@ -0,0 +1,19 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ParkingLicensePlate extends Model
{
use HasFactory;
protected $table = 'parking_license_plate';
protected $hidden = [
'created_at',
'updated_at',
'deleted_at'
];
}

20
app/Models/ParkingSpaceAttributes.php

@ -11,10 +11,20 @@ class ParkingSpaceAttributes extends Model
protected $table = 'parking_space_attributes'; protected $table = 'parking_space_attributes';
protected $hidden = [ protected $hidden
'created_at', = [
'updated_at', 'created_at',
'deleted_at' 'updated_at',
]; 'deleted_at'
];
/**
* @return array
*/
public static function getList(): array
{
return self::query()->get()->select(
['id as attributes_id', 'attributes']
)->toArray();
}
} }

24
app/Models/ParkingSpaceType.php

@ -0,0 +1,24 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class ParkingSpaceType extends Model
{
use HasFactory, SoftDeletes;
protected $table = 'parking_space_type';
protected $fillable
= [
'id',
'name'
];
protected $hidden
= [
'created_at',
'updated_at',
'deleted_at'
];
}

124
app/Services/ParkingLicensePlateService.php

@ -0,0 +1,124 @@
<?php
namespace App\Services;
use App\Models\ParkingLicensePlate;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class ParkingLicensePlateService
{
/**
* @var OperationLogService
*/
private OperationLogService $logService;
/**
* 构造函数
* @param OperationLogService $logService
*/
public function __construct(OperationLogService $logService)
{
$this->logService = $logService;
}
/**
* 创建车牌号码
* @param array $data
* @return Model|Builder
* @throws Exception
*/
public function createModel(array $data): Model|Builder
{
try {
DB::beginTransaction();
if (ParkingLicensePlate::query()->where('number', $data['number'])
->exists()
) {
throw new Exception(__('service.license_plate.number_exists'));
}
$model = ParkingLicensePlate::query()->create([
'number' => $data['number'],
'space_type_id' => $data['space_type_id'],
'created_at' => get_datetime()
]);
$this->logService->logCreated($model, '创建车牌号码');
DB::commit();
return $model;
} catch (Exception $e) {
DB::rollBack();
throw $e;
}
}
/**
* @param array $data
* @param int $id
* @return Model|Builder
* @throws Exception
*/
public function updateModel(array $data, int $id): Model|Builder
{
try {
DB::beginTransaction();
// 验证
$existsWhere = [
['number', '=', $data['number']],
['id', '<>', $id]
];
if (ParkingLicensePlate::query()->where($existsWhere)->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, '更新车牌号码');
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, '删除车牌号码');
$model->delete();
DB::commit();
return true;
} catch (Exception $e) {
DB::rollBack();
throw $e;
}
}
}

174
app/Services/ParkingSpaceTypeService.php

@ -0,0 +1,174 @@
<?php
namespace App\Services;
use App\Models\ParkingSpaceType;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class ParkingSpaceTypeService
{
/**
* @var array|string[]
*/
protected array $color
= [
'red',
'green',
'yellow',
'blue',
'purple',
'cyan',
'white'
];
/**
* @var OperationLogService
*/
private OperationLogService $logService;
/**
* 构造函数
* @param OperationLogService $logService
*/
public function __construct(OperationLogService $logService)
{
$this->logService = $logService;
}
/**
* 返回翻译的颜色选择列表
* @return array
*/
public function getColorList(): array
{
$colorArr = [];
foreach ($this->color as $value) {
$colorArr[$value] = __('service.space_type.' . $value);
}
return get_select_data($colorArr);
}
/**
* 创建车位属性
* @param array $data
* @return Model|Builder
* @throws Exception
*/
public function createModel(array $data): Model|Builder
{
try {
DB::beginTransaction();
if (ParkingSpaceType::query()->where('name', $data['name'])->exists(
)
) {
throw new Exception(__('service.space_type.name_exists'));
}
$createData = $this->getSaveData($data);
$createData['created_at'] = get_datetime();
$model = ParkingSpaceType::query()->create($createData);
$this->logService->logCreated($model, '创建车位类型');
DB::commit();
return $model;
} catch (Exception $e) {
DB::rollBack();
throw $e;
}
}
/**
* @param array $data
* @return array
*/
protected function getSaveData(array $data): array
{
$saveData = [
'name' => $data['name'],
'is_default' => $data['is_default'],
'default_color_occupy' => $data['default_color_occupy'] ?? '',
'default_color_vacant' => $data['default_color_vacant'] ?? '',
'default_color_warning' => $data['default_color_warning'] ?? '',
'default_is_flicker' => $data['default_is_flicker'] ?? '0'
];
if (isset($data['attributes_id'])) {
$saveData['attributes_id'] = $data['attributes_id'];
}
$saveData['attr_color_occupy'] = $data['attr_color_occupy'] ?? '';
$saveData['attr_color_vacant'] = $data['attr_color_vacant'] ?? '';
$saveData['attr_color_warning'] = $data['attr_color_warning'] ?? '';
if (isset($data['attr_is_warning'])) {
$saveData['attr_is_warning'] = $data['attr_is_warning'];
}
return $saveData;
}
/**
* @param array $data
* @param int $id
* @return Model|Builder
* @throws Exception
*/
public function updateModel(array $data, int $id): Model|Builder
{
try {
DB::beginTransaction();
// 验证
$existsWhere = [
['name', '=', $data['name']],
['id', '<>', $id]
];
if (ParkingSpaceType::query()->where($existsWhere)->exists()) {
throw new Exception(__('service.space_type.name_exists'));
}
// 更新
$model = ParkingSpaceType::query()->findOrFail($id);
$oldValues = $model->toArray();
$saveData = $this->getSaveData($data);
$saveData['updated_at'] = get_datetime();
$model->update($saveData);
$this->logService->logUpdated($model, $oldValues, '更新车位类型');
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 = ParkingSpaceType::query()->findOrFail($id);
$this->logService->logDeleted($model, '删除车位类型');
$model->delete();
DB::commit();
return true;
} catch (Exception $e) {
DB::rollBack();
throw $e;
}
}
}

3
composer.json

@ -9,7 +9,8 @@
"guzzlehttp/guzzle": "^7.2", "guzzlehttp/guzzle": "^7.2",
"laravel/framework": "^10.0", "laravel/framework": "^10.0",
"laravel/sanctum": "^3.2", "laravel/sanctum": "^3.2",
"laravel/tinker": "^2.8" "laravel/tinker": "^2.8",
"maatwebsite/excel": "^3.1"
}, },
"require-dev": { "require-dev": {
"fakerphp/faker": "^1.9.1", "fakerphp/faker": "^1.9.1",

593
composer.lock

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "bfe12996eeecb6fdc8713a9fd9d431f8", "content-hash": "d44d0e67fdb59e187c377426d95d5cc0",
"packages": [ "packages": [
{ {
"name": "brick/math", "name": "brick/math",
@ -135,6 +135,162 @@
], ],
"time": "2023-12-11T17:09:12+00:00" "time": "2023-12-11T17:09:12+00:00"
}, },
{
"name": "composer/pcre",
"version": "3.3.2",
"source": {
"type": "git",
"url": "https://github.com/composer/pcre.git",
"reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
"reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0"
},
"conflict": {
"phpstan/phpstan": "<1.11.10"
},
"require-dev": {
"phpstan/phpstan": "^1.12 || ^2",
"phpstan/phpstan-strict-rules": "^1 || ^2",
"phpunit/phpunit": "^8 || ^9"
},
"type": "library",
"extra": {
"phpstan": {
"includes": [
"extension.neon"
]
},
"branch-alias": {
"dev-main": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Pcre\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
}
],
"description": "PCRE wrapping library that offers type-safe preg_* replacements.",
"keywords": [
"PCRE",
"preg",
"regex",
"regular expression"
],
"support": {
"issues": "https://github.com/composer/pcre/issues",
"source": "https://github.com/composer/pcre/tree/3.3.2"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2024-11-12T16:29:46+00:00"
},
{
"name": "composer/semver",
"version": "3.4.4",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
"reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95",
"reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95",
"shasum": ""
},
"require": {
"php": "^5.3.2 || ^7.0 || ^8.0"
},
"require-dev": {
"phpstan/phpstan": "^1.11",
"symfony/phpunit-bridge": "^3 || ^7"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Semver\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nils Adermann",
"email": "naderman@naderman.de",
"homepage": "http://www.naderman.de"
},
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
},
{
"name": "Rob Bast",
"email": "rob.bast@gmail.com",
"homepage": "http://robbast.nl"
}
],
"description": "Semver library that offers utilities, version constraint parsing and validation.",
"keywords": [
"semantic",
"semver",
"validation",
"versioning"
],
"support": {
"irc": "ircs://irc.libera.chat:6697/composer",
"issues": "https://github.com/composer/semver/issues",
"source": "https://github.com/composer/semver/tree/3.4.4"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
}
],
"time": "2025-08-20T19:15:30+00:00"
},
{ {
"name": "dflydev/dot-access-data", "name": "dflydev/dot-access-data",
"version": "v3.0.3", "version": "v3.0.3",
@ -508,6 +664,67 @@
], ],
"time": "2025-03-06T22:45:56+00:00" "time": "2025-03-06T22:45:56+00:00"
}, },
{
"name": "ezyang/htmlpurifier",
"version": "v4.19.0",
"source": {
"type": "git",
"url": "https://github.com/ezyang/htmlpurifier.git",
"reference": "b287d2a16aceffbf6e0295559b39662612b77fcf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/b287d2a16aceffbf6e0295559b39662612b77fcf",
"reference": "b287d2a16aceffbf6e0295559b39662612b77fcf",
"shasum": ""
},
"require": {
"php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0"
},
"require-dev": {
"cerdic/css-tidy": "^1.7 || ^2.0",
"simpletest/simpletest": "dev-master"
},
"suggest": {
"cerdic/css-tidy": "If you want to use the filter 'Filter.ExtractStyleBlocks'.",
"ext-bcmath": "Used for unit conversion and imagecrash protection",
"ext-iconv": "Converts text to and from non-UTF-8 encodings",
"ext-tidy": "Used for pretty-printing HTML"
},
"type": "library",
"autoload": {
"files": [
"library/HTMLPurifier.composer.php"
],
"psr-0": {
"HTMLPurifier": "library/"
},
"exclude-from-classmap": [
"/library/HTMLPurifier/Language/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-2.1-or-later"
],
"authors": [
{
"name": "Edward Z. Yang",
"email": "admin@htmlpurifier.org",
"homepage": "http://ezyang.com"
}
],
"description": "Standards compliant HTML filter written in PHP",
"homepage": "http://htmlpurifier.org/",
"keywords": [
"html"
],
"support": {
"issues": "https://github.com/ezyang/htmlpurifier/issues",
"source": "https://github.com/ezyang/htmlpurifier/tree/v4.19.0"
},
"time": "2025-10-17T16:34:55+00:00"
},
{ {
"name": "fruitcake/php-cors", "name": "fruitcake/php-cors",
"version": "v1.4.0", "version": "v1.4.0",
@ -1888,6 +2105,272 @@
], ],
"time": "2024-09-21T08:32:55+00:00" "time": "2024-09-21T08:32:55+00:00"
}, },
{
"name": "maatwebsite/excel",
"version": "3.1.67",
"source": {
"type": "git",
"url": "https://github.com/SpartnerNL/Laravel-Excel.git",
"reference": "e508e34a502a3acc3329b464dad257378a7edb4d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/e508e34a502a3acc3329b464dad257378a7edb4d",
"reference": "e508e34a502a3acc3329b464dad257378a7edb4d",
"shasum": ""
},
"require": {
"composer/semver": "^3.3",
"ext-json": "*",
"illuminate/support": "5.8.*||^6.0||^7.0||^8.0||^9.0||^10.0||^11.0||^12.0",
"php": "^7.0||^8.0",
"phpoffice/phpspreadsheet": "^1.30.0",
"psr/simple-cache": "^1.0||^2.0||^3.0"
},
"require-dev": {
"laravel/scout": "^7.0||^8.0||^9.0||^10.0",
"orchestra/testbench": "^6.0||^7.0||^8.0||^9.0||^10.0",
"predis/predis": "^1.1"
},
"type": "library",
"extra": {
"laravel": {
"aliases": {
"Excel": "Maatwebsite\\Excel\\Facades\\Excel"
},
"providers": [
"Maatwebsite\\Excel\\ExcelServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Maatwebsite\\Excel\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Patrick Brouwers",
"email": "patrick@spartner.nl"
}
],
"description": "Supercharged Excel exports and imports in Laravel",
"keywords": [
"PHPExcel",
"batch",
"csv",
"excel",
"export",
"import",
"laravel",
"php",
"phpspreadsheet"
],
"support": {
"issues": "https://github.com/SpartnerNL/Laravel-Excel/issues",
"source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.67"
},
"funding": [
{
"url": "https://laravel-excel.com/commercial-support",
"type": "custom"
},
{
"url": "https://github.com/patrickbrouwers",
"type": "github"
}
],
"time": "2025-08-26T09:13:16+00:00"
},
{
"name": "maennchen/zipstream-php",
"version": "3.1.2",
"source": {
"type": "git",
"url": "https://github.com/maennchen/ZipStream-PHP.git",
"reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/aeadcf5c412332eb426c0f9b4485f6accba2a99f",
"reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"ext-zlib": "*",
"php-64bit": "^8.2"
},
"require-dev": {
"brianium/paratest": "^7.7",
"ext-zip": "*",
"friendsofphp/php-cs-fixer": "^3.16",
"guzzlehttp/guzzle": "^7.5",
"mikey179/vfsstream": "^1.6",
"php-coveralls/php-coveralls": "^2.5",
"phpunit/phpunit": "^11.0",
"vimeo/psalm": "^6.0"
},
"suggest": {
"guzzlehttp/psr7": "^2.4",
"psr/http-message": "^2.0"
},
"type": "library",
"autoload": {
"psr-4": {
"ZipStream\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Paul Duncan",
"email": "pabs@pablotron.org"
},
{
"name": "Jonatan Männchen",
"email": "jonatan@maennchen.ch"
},
{
"name": "Jesse Donat",
"email": "donatj@gmail.com"
},
{
"name": "András Kolesár",
"email": "kolesar@kolesar.hu"
}
],
"description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
"keywords": [
"stream",
"zip"
],
"support": {
"issues": "https://github.com/maennchen/ZipStream-PHP/issues",
"source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.2"
},
"funding": [
{
"url": "https://github.com/maennchen",
"type": "github"
}
],
"time": "2025-01-27T12:07:53+00:00"
},
{
"name": "markbaker/complex",
"version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/MarkBaker/PHPComplex.git",
"reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/95c56caa1cf5c766ad6d65b6344b807c1e8405b9",
"reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "dev-master",
"phpcompatibility/php-compatibility": "^9.3",
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
"squizlabs/php_codesniffer": "^3.7"
},
"type": "library",
"autoload": {
"psr-4": {
"Complex\\": "classes/src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mark Baker",
"email": "mark@lange.demon.co.uk"
}
],
"description": "PHP Class for working with complex numbers",
"homepage": "https://github.com/MarkBaker/PHPComplex",
"keywords": [
"complex",
"mathematics"
],
"support": {
"issues": "https://github.com/MarkBaker/PHPComplex/issues",
"source": "https://github.com/MarkBaker/PHPComplex/tree/3.0.2"
},
"time": "2022-12-06T16:21:08+00:00"
},
{
"name": "markbaker/matrix",
"version": "3.0.1",
"source": {
"type": "git",
"url": "https://github.com/MarkBaker/PHPMatrix.git",
"reference": "728434227fe21be27ff6d86621a1b13107a2562c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/728434227fe21be27ff6d86621a1b13107a2562c",
"reference": "728434227fe21be27ff6d86621a1b13107a2562c",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "dev-master",
"phpcompatibility/php-compatibility": "^9.3",
"phpdocumentor/phpdocumentor": "2.*",
"phploc/phploc": "^4.0",
"phpmd/phpmd": "2.*",
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
"sebastian/phpcpd": "^4.0",
"squizlabs/php_codesniffer": "^3.7"
},
"type": "library",
"autoload": {
"psr-4": {
"Matrix\\": "classes/src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mark Baker",
"email": "mark@demon-angel.eu"
}
],
"description": "PHP Class for working with matrices",
"homepage": "https://github.com/MarkBaker/PHPMatrix",
"keywords": [
"mathematics",
"matrix",
"vector"
],
"support": {
"issues": "https://github.com/MarkBaker/PHPMatrix/issues",
"source": "https://github.com/MarkBaker/PHPMatrix/tree/3.0.1"
},
"time": "2022-12-02T22:17:43+00:00"
},
{ {
"name": "monolog/monolog", "name": "monolog/monolog",
"version": "3.10.0", "version": "3.10.0",
@ -2395,6 +2878,114 @@
], ],
"time": "2024-11-21T10:36:35+00:00" "time": "2024-11-21T10:36:35+00:00"
}, },
{
"name": "phpoffice/phpspreadsheet",
"version": "1.30.2",
"source": {
"type": "git",
"url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
"reference": "09cdde5e2f078b9a3358dd217e2c8cb4dac84be2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/09cdde5e2f078b9a3358dd217e2c8cb4dac84be2",
"reference": "09cdde5e2f078b9a3358dd217e2c8cb4dac84be2",
"shasum": ""
},
"require": {
"composer/pcre": "^1||^2||^3",
"ext-ctype": "*",
"ext-dom": "*",
"ext-fileinfo": "*",
"ext-gd": "*",
"ext-iconv": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-simplexml": "*",
"ext-xml": "*",
"ext-xmlreader": "*",
"ext-xmlwriter": "*",
"ext-zip": "*",
"ext-zlib": "*",
"ezyang/htmlpurifier": "^4.15",
"maennchen/zipstream-php": "^2.1 || ^3.0",
"markbaker/complex": "^3.0",
"markbaker/matrix": "^3.0",
"php": ">=7.4.0 <8.5.0",
"psr/simple-cache": "^1.0 || ^2.0 || ^3.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "dev-main",
"doctrine/instantiator": "^1.5",
"dompdf/dompdf": "^1.0 || ^2.0 || ^3.0",
"friendsofphp/php-cs-fixer": "^3.2",
"mitoteam/jpgraph": "^10.3",
"mpdf/mpdf": "^8.1.1",
"phpcompatibility/php-compatibility": "^9.3",
"phpstan/phpstan": "^1.1",
"phpstan/phpstan-phpunit": "^1.0",
"phpunit/phpunit": "^8.5 || ^9.0",
"squizlabs/php_codesniffer": "^3.7",
"tecnickcom/tcpdf": "^6.5"
},
"suggest": {
"dompdf/dompdf": "Option for rendering PDF with PDF Writer",
"ext-intl": "PHP Internationalization Functions",
"mitoteam/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers",
"mpdf/mpdf": "Option for rendering PDF with PDF Writer",
"tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer"
},
"type": "library",
"autoload": {
"psr-4": {
"PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Maarten Balliauw",
"homepage": "https://blog.maartenballiauw.be"
},
{
"name": "Mark Baker",
"homepage": "https://markbakeruk.net"
},
{
"name": "Franck Lefevre",
"homepage": "https://rootslabs.net"
},
{
"name": "Erik Tilt"
},
{
"name": "Adrien Crivelli"
},
{
"name": "Owen Leibman"
}
],
"description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine",
"homepage": "https://github.com/PHPOffice/PhpSpreadsheet",
"keywords": [
"OpenXML",
"excel",
"gnumeric",
"ods",
"php",
"spreadsheet",
"xls",
"xlsx"
],
"support": {
"issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues",
"source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.30.2"
},
"time": "2026-01-11T05:58:24+00:00"
},
{ {
"name": "phpoption/phpoption", "name": "phpoption/phpoption",
"version": "1.9.5", "version": "1.9.5",

40
database/migrations/2026_03_09_143728_create_parking_space_type_table.php

@ -0,0 +1,40 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('parking_space_type', function (Blueprint $table) {
$table->id();
$table->string('name')->unique()->comment('车位类型名称');
$table->tinyInteger('is_default')->default(0)->comment('是否为默认车位类型 0否 1是');
$table->string('default_color_occupy', 50)->nullable()->comment('默认指示灯颜色(占用)');
$table->string('default_color_vacant', 50)->nullable()->comment('默认指示灯颜色(空置)');
$table->string('default_color_warning', 50)->nullable()->comment('默认报警指示灯颜色');
$table->tinyInteger('default_is_warning')->default(0)->comment('默认是否报警 0否 1是');
$table->tinyInteger('default_is_flicker')->default(0)->comment('默认是否闪烁 0否 1是');
$table->integer('attributes_id')->nullable()->comment('车位属性ID');
$table->string('attr_color_occupy', 50)->nullable()->comment('车位属性指示灯颜色(占用)');
$table->string('attr_color_vacant', 50)->nullable()->comment('车位属性指示灯颜色(空置)');
$table->string('attr_color_warning', 50)->nullable()->comment('车位属性报警指示灯颜色');
$table->tinyInteger('attr_is_warning')->nullable()->comment('车位属性是否报警 0否 1是');
$table->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('parking_space_type');
}
};

30
database/migrations/2026_03_09_171738_create_parking_license_plate_table.php

@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('parking_license_plate', function (Blueprint $table) {
$table->id();
$table->string('number', 20)->unique()->comment('车牌号码');
$table->integer('space_type_id')->comment('车位类型id');
$table->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('parking_license_plate');
}
};

30
resources/lang/zh-CN/controller.php

@ -0,0 +1,30 @@
<?php
return [
'rule' => [
'store_success' => '添加角色成功',
'update_success' => '更新角色成功'
],
'user' => [],
'config' => [
'parking_lot' => '车场配置',
'parking_lot_id' => '本地停车场ID',
'parking_lot_sum' => '车场总车位数',
'parking_lot_image_path' => '车位图片路径',
'zombie_car_parking_duration' => '僵尸车停车时长',
'numberplate_fuzzy_search' => '车牌模糊检索方式',
'automatically_clear_photo_cycle' => '自动清除照片周期',
'third_party' => '第三方平台配置',
'report_data_switch' => '上报数据开关',
'third_parking_lot_id' => '第三方平台车场ID',
'report_api_url' => '上报接口地址',
'report_cycle' => '上报周期',
],
'upload' => [
'empty_file' => '没有文件上传',
'empty_image' => '没有图片上传'
],
'import' => [
'success' => '导入成功'
]
];

60
resources/lang/zh-CN/exception.php

@ -0,0 +1,60 @@
<?php
return [
'get_user_info_failed' => '获取用户信息失败',
'get_user_info_list_failed' => '获取用户信息失败',
'admin_user' => [
'create_failed' => '创建用户失败',
'update_failed' => '更新用户失败',
'destroy_failed' => '删除用户失败'
],
'admin_role' => [
'create_failed' => '创建角色失败',
'update_failed' => '更新角色失败',
'destroy_failed' => '删除角色失败'
],
'update_admin_config_failed' => '更新配置失败',
'get_data_failed' => '获取数据失败',
'exception_handler' => [
'login' => '请先登录',
'resource' => '资源不存在',
'api' => '接口不存在',
'role' => '没有操作权限',
'frequent' => '请求过于频繁,请稍后再试',
'system' => '系统错误'
],
'admin_translation' => [
'create_failed' => '创建翻译失败',
'update_failed' => '更新翻译失败',
'destroy_failed' => '删除翻译失败'
],
'admin_floor' => [
'create_failed' => '创建楼层失败',
'update_failed' => '更新楼层失败',
'destroy_failed' => '删除楼层失败'
],
'upload' => [
'error' => '上传失败'
],
'admin_vip_list' => [
'create_failed' => '创建VIP名单失败',
'update_failed' => '更新VIP名单失败',
'destroy_failed' => '删除VIP名单失败',
'import_failed' => '上传失败'
],
'space_attributes' => [
'create_failed' => '创建车位属性失败',
'update_failed' => '更新车位属性失败',
'destroy_failed' => '删除车位属性失败'
],
'space_type' => [
'create_failed' => '创建车位类型失败',
'update_failed' => '更新车位类型失败',
'destroy_failed' => '删除车位类型失败'
],
'license_plate' => [
'create_failed' => '创建车牌号码失败',
'update_failed' => '更新车牌号码失败',
'destroy_failed' => '删除车牌号码失败'
]
];

13
resources/lang/zh-CN/menu.php

@ -0,0 +1,13 @@
<?php
return [
'model_manage' => '模式管理',
'cat_status' => '车位状态',
'special_car_manage' => '特别车位管理',
'information_center' => '信息中心',
'statistics_report' => '统计报表',
'device_manage' => '设备管理',
'system_manage' => '系统管理',
'user_manage' => '用户管理',
'role_manage' => '角色管理',
];

22
resources/lang/zh-CN/middleware.php

@ -0,0 +1,22 @@
<?php
return [
'auth' => [
'token_exists' => '缺少认证令牌',
'token_invalid' => '认证令牌无效',
'user_disabled' => '用户已被禁用',
'use_json' => '请求必须使用 JSON 格式',
'login_invalid' => '登录失效'
],
'api' => [
'login' => '请先登录',
'permission' => '没有操作权限',
'resource' => '资源不存在',
'data' => '数据验证失败',
'system' => '系统错误'
],
'check' => [
'user_auth' => '你无权访问!'
]
];

36
resources/lang/zh-CN/service.php

@ -0,0 +1,36 @@
<?php
return [
'admin_role' => [
'name_exists' => '角色名称已存在',
'menu_error' => '角色编号参数有误'
],
'admin_user' => [
'name_exists' => '用户账号已存在'
],
'admin_translation' => [
'data_exists' => '翻译配置已存在'
],
'admin_floor' => [
'name_exists' => '楼层名称已存在'
],
'admin_vip_list' => [
'license_exists' => '车牌号码已存在'
],
'space_attributes' => [
'attributes_exists' => '车位属性名称已存在'
],
'space_type' => [
'red' => '红色',
'green' => '绿色',
'yellow' => '黄色',
'blue' => '蓝色',
'purple' => '紫色',
'cyan' => '青色',
'white' => '白色',
'name_exists' => '车位类型名称已存在'
],
'license_plate' => [
'number_exists' => '车牌号码已存在'
]
];

72
resources/lang/zh-CN/validation.php

@ -0,0 +1,72 @@
<?php
return [
'auth' => [
'u_empty' => '用户名不能为空',
'p_empty' => '密码不能为空',
'u_p_error' => '账号或密码错误',
'u_disabled' => '账号已被禁用'
],
'admin_user' => [
'l_a_empty' => '登录账号不能为空',
'l_a_alpha_num' => '登录账号只能是英文字母和数字',
'l_a_between' => '登录账号长度必须4-20',
'r_empty' => '用户角色不能为空',
's_p_empty' => '所属停车场不能为空',
'p_empty' => '初始密码不能为空',
'p_between' => '初始密码长度必须12-30',
'email' => '电邮地址格式错误',
's_empty' => '状态不能为空',
's_in' => '状态至必须是0或1'
],
'admin_role' => [
'n_empty' => '角色名称不能为空',
'n_max' => '角色名称最多50个字符',
'm_empty' => '角色权限不能为空',
'm_array' => '角色权限数据必须是数组',
'r_max' => '角色名称最多50个字符'
],
'admin_config' => [
'content_empty' => '配置数据不能为空',
'parking_lot_id_empty' => '本地停车场ID配置不能为空',
'parking_lot_sum_empty' => '车场总车位数配置不能为空',
'parking_lot_sum_num' => '车场总车位数配置必须是数字',
'zombie_car_empty' => '僵尸车停车时长配置不能为空',
'zombie_car_num' => '僵尸车停车时长配置必须是数字'
],
'id_empty' => '编号不能为空',
'id_numeric' => '编号必须是数字',
'admin_translation' => [
'en_empty' => '英文翻译不能为空',
'zh_cn_empty' => '中文简体翻译不能为空',
'zh_tw_empty' => '中文繁体翻译不能为空'
],
'admin_floor' => [
'n_empty' => '楼层名称不能为空',
'n_max' => '楼层名称最多50个字符',
'r_array' => '楼层名称数据必须是数组',
],
'upload' => [
'i_empty' => '图片文件不能为空',
'i_image' => '上传文件必须是图片',
'i_max' => '上传图片文件不可超过10MB'
],
'admin_list_vip' => [
'l_empty' => '车牌号码不能为空',
'l_max' => '车牌号码最多20个字符',
'file_empty' => '导入文件不能为空',
'file_mimes' => '导入文件类型必须是xlsx|xls|csv',
'file_max' => '导入文件最大不超过2048'
],
'space_attributes' => [
'a_empty' => '车位属性名称不能为空',
'i_empty' => '汇入图示不能为空'
],
'space_type' => [
'n_empty' => '车位类型名称不能为空'
],
'license_plate' => [
'n_empty' => '车牌号码不能为空',
'type_empty' => '车位类型不能为空'
]
];
Loading…
Cancel
Save