Browse Source

闸机管理

master
wanghongjun 7 days ago
parent
commit
6358e9a13b
  1. 153
      app/Http/Controllers/Admin/ParkingGateControlController.php
  2. 119
      app/Http/Controllers/Admin/ProhibitedPassageController.php
  3. 11
      app/Models/ParkingChannel.php
  4. 41
      app/Models/ParkingGateControl.php
  5. 35
      app/Models/ParkingProhibitedPassage.php
  6. 58
      app/Services/ParkingGateControlService.php
  7. 2
      app/Services/ParkingSpaceRepairService.php
  8. 44
      app/Services/ProhibitedPassageService.php
  9. 8
      app/common.php
  10. 40
      database/migrations/2026_06_09_143449_create_parking_gate_control_table.php
  11. 35
      database/migrations/2026_06_09_143449_create_parking_prohibited_passage_table.php
  12. 14
      database/seeders/AdminMenuSeeder.php
  13. 2
      resources/lang/en/menu.php
  14. 9
      resources/lang/en/service.php
  15. 2
      resources/lang/zh-CN/menu.php
  16. 9
      resources/lang/zh-CN/service.php
  17. 2
      resources/lang/zh-TW/menu.php
  18. 9
      resources/lang/zh-TW/service.php
  19. 11
      routes/admin/api.php

153
app/Http/Controllers/Admin/ParkingGateControlController.php

@ -0,0 +1,153 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Models\ParkingGateControl;
use App\Models\ParkingLicensePlate;
use App\Models\ParkingSpaceType;
use App\Services\ApiResponseService;
use App\Services\ParkingGateControlService;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ParkingGateControlController extends BaseController
{
protected string $menuUri = 'gateControl';
/**
* @var ParkingGateControlService
*/
protected ParkingGateControlService $service;
/**
* 构造函数
* @param ApiResponseService $responseService
* @param ParkingGateControlService $service
*/
public function __construct(
ApiResponseService $responseService,
ParkingGateControlService $service
) {
parent::__construct($responseService);
$this->service = $service;
}
/**
* @param Request $request
* @return JsonResponse
*/
public function index(Request $request): JsonResponse
{
try {
$query = ParkingGateControl::query();
if ($request->has('license_plate')) {
$license_plate = $request->input('license_plate');
if ($license_plate) {
$license_plate_id = ParkingLicensePlate::getValueId(
$license_plate
);
if ($license_plate_id) {
$query->where('license_plate_id', $license_plate_id);
} else {
$query->where('id', 0);
}
}
}
if ($request->has('member_type')) {
$member_type = $request->input('member_type');
if ($member_type) {
$query->where('member_type', $member_type);
}
}
if ($request->has('enter_at')) {
$enter_at = $request->input('enter_at');
if ($enter_at) {
$query->where('enter_at', '>=', $enter_at);
}
}
if ($request->has('leave_at')) {
$leave_at = $request->input('leave_at');
if ($leave_at) {
$query->where('leave_at', '<=', $leave_at);
}
}
if ($request->has('customer_id')) {
$customer_id = $request->input('customer_id');
if ($customer_id) {
$query->where('customer_id', $customer_id);
}
}
if ($request->has('member_id')) {
$member_id = $request->input('member_id');
if ($member_id) {
$query->where('member_id', $member_id);
}
}
// 分页
$page = $request->input('page', 1);
$perPage = $request->input('per_page', 10);
$total = $query->count();
$items = $query->latest()->forPage($page, $perPage)->get()->each(
function ($item) {
return $this->service->getItem($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 = [
'member_type_list' => ParkingSpaceType::getData()
];
return $this->responseService->success($data);
} catch (Exception $e) {
$m_prefix = __('exception.exception_handler.resource');
return $this->responseService->systemError(
$m_prefix . ':' . $e->getMessage()
);
}
}
public function show(string $id): JsonResponse
{
try {
$data = ParkingGateControl::query()->find($id);
return $this->responseService->success($this->service->getItem($data));
} catch (Exception $e) {
return $this->responseService->systemError(
__('exception.get_data_failed') . ':' . $e->getMessage()
);
}
}
}

119
app/Http/Controllers/Admin/ProhibitedPassageController.php

@ -0,0 +1,119 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Models\Parking;
use App\Models\ParkingLicensePlate;
use App\Models\ParkingProhibitedPassage;
use App\Services\ApiResponseService;
use App\Services\ProhibitedPassageService;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ProhibitedPassageController extends BaseController
{
protected string $menuUri = 'prohibitedPassage';
/**
* @var ProhibitedPassageService
*/
protected ProhibitedPassageService $service;
/**
* 构造函数
* @param ApiResponseService $responseService
* @param ProhibitedPassageService $service
*/
public function __construct(
ApiResponseService $responseService,
ProhibitedPassageService $service
) {
parent::__construct($responseService);
$this->service = $service;
}
/**
* @param Request $request
* @return JsonResponse
*/
public function index(Request $request): JsonResponse
{
try {
$query = ParkingProhibitedPassage::query();
if ($request->has('license_plate')) {
$license_plate = $request->input('license_plate');
if ($license_plate) {
$license_plate_id = ParkingLicensePlate::getValueId(
$license_plate
);
if ($license_plate_id) {
$query->where('license_plate_id', $license_plate_id);
} else {
$query->where('id', 0);
}
}
}
if ($request->has('parking_id')) {
$parking_id = $request->input('parking_id');
if ($parking_id) {
$query->where('parking_id', $parking_id);
}
}
if ($request->has('start_date')) {
$start_date = $request->input('start_date');
if ($start_date) {
$query->where(
'identify_at',
'>=',
$start_date . ' 00:00:00'
);
}
}
if ($request->has('end_date')) {
$end_date = $request->input('end_date');
if ($end_date) {
$query->where('identify_at', '<=', $end_date . ' 23:59:59');
}
}
$typeArr = $this->service->getType();
$remarkArr = $this->service->getRemark();
// 分页
$page = $request->input('page', 1);
$perPage = $request->input('per_page', 10);
$total = $query->count();
$items = $query->latest()->forPage($page, $perPage)->get()->each(
function ($item) use ($typeArr, $remarkArr) {
$item['license_plate'] = ParkingLicensePlate::getNumber(
$item['license_plate_id']
);
$item['parking'] = Parking::getName($item['parking_id']);
$item['type_str'] = $typeArr[$item['type']];
$item['remark'] = $remarkArr[$item['remark']];
$item['snapshot_img'] = get_image_url($item['snapshot_img']);
unset($item['parking_id'], $item['license_plate_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()
);
}
}
}

11
app/Models/ParkingChannel.php

@ -82,4 +82,15 @@ class ParkingChannel extends Model
{
return $value ? date("Y-m-d H:i:s", strtotime($value)) : $value;
}
public static function getFirst($id)
{
$item = self::query()->where('id', $id)->first();
$item['name'] = AdminTranslationService::getTranslationTypeName(
$id,
6,
$item['name']
);
return $item;
}
}

41
app/Models/ParkingGateControl.php

@ -0,0 +1,41 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ParkingGateControl extends Model
{
use HasFactory;
protected $table = 'parking_gate_control';
protected $fillable
= [
'license_plate_id',
'channel_id',
'enter_at',
'leave_at',
'leave_type',
'enter_img',
'leave_img'
];
protected $hidden
= [
'created_at',
'updated_at'
];
public function getEnterAtAttribute($value): string
{
return $value ? date("Y-m-d H:i:s", strtotime($value)) : $value;
}
public function getLeaveAtAttribute($value): string
{
return $value ? date("Y-m-d H:i:s", strtotime($value)) : '';
}
}

35
app/Models/ParkingProhibitedPassage.php

@ -0,0 +1,35 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ParkingProhibitedPassage extends Model
{
use HasFactory;
protected $table = 'parking_prohibited_passage';
protected $fillable
= [
'license_plate_id',
'parking_id',
'type',
'identify_at',
'remark',
'snapshot_img'
];
protected $hidden
= [
'created_at',
'updated_at'
];
public function getIdentifyAtAttribute($value): string
{
return $value ? date("Y-m-d H:i:s", strtotime($value)) : $value;
}
}

58
app/Services/ParkingGateControlService.php

@ -0,0 +1,58 @@
<?php
namespace App\Services;
use App\Models\Parking;
use App\Models\ParkingChannel;
use App\Models\ParkingLicensePlate;
use App\Models\ParkingReservation;
use App\Models\ParkingSpaceType;
class ParkingGateControlService extends BaseService
{
protected string $menuTitle = 'gate_control';
public static array $typeArr = [
1 => 'automatic',
2 => 'manual'
];
/**
* @return array|string[]
*/
public function getType(): array
{
$typeArr = self::$typeArr;
foreach ($typeArr as $key => $value) {
$typeArr[$key] = __service($this->menuTitle . '.' . $value);
}
return $typeArr;
}
public function getItem($item)
{
$typeArr = $this->getType();
$date = date("Y-m-d", strtotime($item['enter_at']));
$item['reserve_id'] = ParkingReservation::query()->where(
'license_plate_id',
$item['license_plate_id']
)->where('date', $date)->value('reserve_id');
$item['member_type'] = ParkingSpaceType::getName($item['member_type']);
$item['license_plate'] = ParkingLicensePlate::getNumber($item['license_plate_id']);
$ParkingChannel = ParkingChannel::getFirst($item['channel_id']);
$item['channel'] = '';
$item['parking'] = '';
if ($ParkingChannel) {
$item['channel'] = $ParkingChannel['name'];
$item['parking'] = Parking::getName($ParkingChannel['parking_id']);
}
$item['enter_type_str'] = $typeArr[$item['enter_type']];
$item['leave_type_str'] = $typeArr[$item['leave_type']] ?? '';
$item['dwell_time'] = get_time_difference_str($item['enter_at'], $item['leave_at']);
$item['enter_img'] = get_image_url($item['enter_img']);
$item['leave_img'] = get_image_url($item['leave_img']);
unset($item['license_plate_id'], $item['channel_id']);
return $item;
}
}

2
app/Services/ParkingSpaceRepairService.php

@ -24,7 +24,7 @@ class ParkingSpaceRepairService extends BaseService
{
$ParkingSpace = ParkingSpace::query()->find($item['space_id']);
$item['parking_space_number'] = $ParkingSpace['number'];
$Floor = AdminFloor::query()->find($ParkingSpace['floor_id']);
$Floor = AdminFloor::getFirst($ParkingSpace['floor_id']);
$item['floor'] = $Floor['name'];
$item['parking'] = Parking::getName($Floor['building_floor']);
$item['admin_user'] = AdminUsers::getUsername($item['admin_user_id']);

44
app/Services/ProhibitedPassageService.php

@ -0,0 +1,44 @@
<?php
namespace App\Services;
class ProhibitedPassageService extends BaseService
{
protected string $menuTitle = 'prohibited_passage';
public array $typeArr = [
1 => 'entrance',
2 => 'export'
];
public array $remarkArr = [
1 => 'remark1',
2 => 'remark2',
3 => 'remark3'
];
/**
* @return array|string[]
*/
public function getType(): array
{
$typeArr = $this->typeArr;
foreach ($typeArr as $key => $value) {
$typeArr[$key] = __service('channel_management.' . $value);
}
return $typeArr;
}
/**
* @return array|string[]
*/
public function getRemark(): array
{
$typeArr = $this->remarkArr;
foreach ($typeArr as $key => $value) {
$typeArr[$key] = __service($this->menuTitle . '.' . $value);
}
return $typeArr;
}
}

8
app/common.php

@ -111,11 +111,11 @@ if (!function_exists('get_ratio')) {
}
if (!function_exists('get_time_difference')) {
function get_time_difference(string $targetTime): array
function get_time_difference(string $targetTime, string $now_date = ''): array
{
try {
$target = new DateTime($targetTime);
$now = new DateTime();
$now = $now_date ? new DateTime($now_date) : new DateTime();
// 计算差值
$interval = $now->diff($target);
@ -152,10 +152,10 @@ if (!function_exists('get_time_difference')) {
}
if (!function_exists('get_time_difference_str')) {
function get_time_difference_str($date): string
function get_time_difference_str($date, $now_date = ''): string
{
$value = '';
$difference = get_time_difference($date);
$difference = get_time_difference($date, $now_date);
if (!isset($difference['error'])) {
if (!empty($difference['days'])) {
$value .= $difference['days'] . __('controller.parking_space.days');

40
database/migrations/2026_06_09_143449_create_parking_gate_control_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_gate_control', function (Blueprint $table) {
$table->id();
$table->integer('license_plate_id')->comment('车牌号码');
$table->integer('channel_id')->comment('入场通道');
$table->timestamp('enter_at')->comment('入场时间');
$table->timestamp('leave_at')->nullable()->comment('出场时间');
$table->tinyInteger('enter_type')->default(1)->comment('入场类型');
$table->tinyInteger('leave_type')->default(0)->comment('出场类型');
$table->string('enter_img', 255)->default('')->comment('入场图片');
$table->string('leave_img', 255)->default('')->comment('出场图片');
$table->integer('member_type')->default(0)->comment('客户类型');
$table->string('customer_id', 50)->default('')->comment('客户id');
$table->string('member_id', 50)->default('')->comment('会员id');
$table->timestamps();
$table->innoDb();
$table->comment('停车场闸机进出记录');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('parking_gate_control');
}
};

35
database/migrations/2026_06_09_143449_create_parking_prohibited_passage_table.php

@ -0,0 +1,35 @@
<?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_prohibited_passage', function (Blueprint $table) {
$table->id();
$table->integer('license_plate_id')->comment('车牌号码');
$table->integer('parking_id')->comment('停车场');
$table->tinyInteger('type')->default(1)->comment('1 进/ 2 出');
$table->timestamp('identify_at')->comment('识别时间');
$table->tinyInteger('remark')->default(1)->comment('原因');
$table->string('snapshot_img', 255)->default('')->comment('抓拍图片');
$table->timestamps();
$table->innoDb();
$table->comment('违禁通行记录');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('parking_prohibited_passage');
}
};

14
database/seeders/AdminMenuSeeder.php

@ -283,6 +283,20 @@ class AdminMenuSeeder extends Seeder
'child' => [
'read_only' => ''
]
],
'gate_control' => [
'uri' => 'gateControl',
'page_uri' => '/gate/gateControl',
'child' => [
'read_only' => 'gateControl.index'
]
],
'prohibited_passage' => [
'uri' => 'prohibitedPassage',
'page_uri' => '/prohibitedPassage/Lanevideo',
'child' => [
'read_only' => 'prohibitedPassage.index'
]
]
],
'statistics_report' => [

2
resources/lang/en/menu.php

@ -96,4 +96,6 @@ return [
'abnormal_ignore' => 'Ignore exceptions',
'allocation' => 'allocation',
'edit_remark' => "Editor's note",
'gate_control' => 'Gate control',
'prohibited_passage' => 'Record of prohibited passage'
];

9
resources/lang/en/service.php

@ -166,5 +166,14 @@ return [
'parking_repair_list' => [
'not_synced' => 'Not synced',
'synced' => 'Synchronized'
],
'gate_control' => [
'automatic' => 'Automatic entry',
'manual' => 'Manual entry'
],
'prohibited_passage' => [
'remark1' => 'No appointment, no entry allowed',
'remark2' => 'Blacklisted vehicles are prohibited from leaving the premises',
'remark3' => 'Appointment timed out and did not show up'
]
];

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

@ -96,4 +96,6 @@ return [
'abnormal_ignore' => '忽略异常',
'allocation' => '分配',
'edit_remark' => '编辑备注',
'gate_control' => '闸机控制',
'prohibited_passage' => '违禁通行记录'
];

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

@ -166,5 +166,14 @@ return [
'parking_repair_list' => [
'not_synced' => '未同步',
'synced' => '已同步'
],
'gate_control' => [
'automatic' => '自动入场',
'manual' => '手动入场'
],
'prohibited_passage' => [
'remark1' => '无预约,不可进场',
'remark2' => '黑名单车辆禁止离场',
'remark3' => '预约超时未到场'
]
];

2
resources/lang/zh-TW/menu.php

@ -96,4 +96,6 @@ return [
'abnormal_ignore' => '忽略异常',
'allocation' => '分配',
'edit_remark' => '編輯備註',
'gate_control' => '閘機控制',
'prohibited_passage' => '違禁通行記錄'
];

9
resources/lang/zh-TW/service.php

@ -166,5 +166,14 @@ return [
'parking_repair_list' => [
'not_synced' => '未同步',
'synced' => '已同步'
],
'gate_control' => [
'automatic' => '自動入場',
'manual' => '手動入場'
],
'prohibited_passage' => [
'remark1' => '無預約,不可進場',
'remark2' => '黑名單車輛禁止離場',
'remark3' => '預約超時未到場'
]
];

11
routes/admin/api.php

@ -40,6 +40,8 @@ use App\Http\Controllers\Admin\ParkingWhitelistController;
use App\Http\Controllers\Admin\ParkingAbnormalController;
use App\Http\Controllers\Admin\ParkingAlarmInformationController;
use App\Http\Controllers\Admin\ParkingSpaceRepairController;
use App\Http\Controllers\Admin\ParkingGateControlController;
use App\Http\Controllers\Admin\ProhibitedPassageController;
Route::group(['prefix' => 'admin'], function () {
@ -201,7 +203,7 @@ Route::group(['prefix' => 'admin'], function () {
Route::get('/notice/setting', [NoticeController::class, 'create']);
Route::post('/notice/setting', [NoticeController::class, 'setting']);
Route::get('/notice/show/{id}', [NoticeController::class, 'show']);
// 异常占用
// 告警信息管理
Route::get('/alarmInformation', [ParkingAlarmInformationController::class, 'index']);
Route::get('/alarmInformation/search', [ParkingAlarmInformationController::class, 'search']);
Route::get('/alarmInformation/show/{id}', [ParkingAlarmInformationController::class, 'show']);
@ -233,7 +235,12 @@ Route::group(['prefix' => 'admin'], function () {
Route::put('/parkingCamera/{id}', [ParkingCameraController::class, 'update']);
Route::delete('/parkingCamera/{id}', [ParkingCameraController::class, 'destroy']);
Route::get('/parkingCamera/rule', [ParkingCameraController::class, 'rule']);
// 闸机控制
Route::get('/gateControl', [ParkingGateControlController::class, 'index']);
Route::get('/gateControl/search', [ParkingGateControlController::class, 'search']);
Route::get('/gateControl/show/{id}', [ParkingGateControlController::class, 'show']);
// 违禁通行记录
Route::get('/prohibitedPassage', [ProhibitedPassageController::class, 'index']);
// 系统总配置
Route::get('/config/index', [ConfigController::class, 'index']);
Route::put('/config/{id}', [ConfigController::class, 'update']);

Loading…
Cancel
Save