Browse Source

异常占用

master
wanghongjun 2 weeks ago
parent
commit
ade4d684af
  1. 177
      app/Http/Controllers/Admin/ParkingAbnormalController.php
  2. 16
      app/Http/Controllers/Admin/ParkingSpaceController.php
  3. 46
      app/Models/ParkingAbnormal.php
  4. 5
      app/Models/ParkingReservation.php
  5. 177
      app/Services/ParkingAbnormalService.php
  6. 23
      app/common.php
  7. 40
      database/migrations/2026_06_04_143449_create_parking_abnormal_table.php
  8. 4
      database/seeders/AdminMenuSeeder.php
  9. 3
      resources/lang/en/log.php
  10. 4
      resources/lang/en/menu.php
  11. 16
      resources/lang/en/service.php
  12. 3
      resources/lang/zh-CN/log.php
  13. 4
      resources/lang/zh-CN/menu.php
  14. 16
      resources/lang/zh-CN/service.php
  15. 3
      resources/lang/zh-TW/log.php
  16. 4
      resources/lang/zh-TW/menu.php
  17. 16
      resources/lang/zh-TW/service.php
  18. 5
      routes/admin/api.php

177
app/Http/Controllers/Admin/ParkingAbnormalController.php

@ -0,0 +1,177 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Exceptions\CustomException;
use App\Models\ParkingAbnormal;
use App\Services\ApiResponseService;
use App\Services\ParkingAbnormalService;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
class ParkingAbnormalController extends BaseController
{
protected string $menuUri = 'abnormalResourceUsage';
/**
* @var ParkingAbnormalService
*/
protected ParkingAbnormalService $service;
/**
* 构造函数
* @param ApiResponseService $responseService
* @param ParkingAbnormalService $service
*/
public function __construct(
ApiResponseService $responseService,
ParkingAbnormalService $service
) {
parent::__construct($responseService);
$this->service = $service;
}
/**
* @param Request $request
* @return JsonResponse
*/
public function index(Request $request): JsonResponse
{
try {
$query = ParkingAbnormal::query();
if ($request->has('parking_id')) {
$parking_id = $request->input('parking_id');
if ($parking_id) {
$query->where('parking_id', $parking_id);
}
}
if ($request->has('date_type')) {
$date_type = $request->input('date_type');
$start_date = '';
if ($date_type == 1) {
$start_date = date('Y-m-d 00:00:00', time());
} else {
if ($date_type == 2) {
$start_date = date(
'Y-m-d 00:00:00',
strtotime('-3 day')
);
} else {
if ($date_type == 3) {
$start_date = date(
'Y-m-d 00:00:00',
strtotime('-7 day')
);
} else {
if ($date_type == 4) {
$start_date = date(
'Y-m-d 00:00:00',
strtotime('-1 month')
);
} else {
if ($date_type == 5) {
$start_date = date(
'Y-m-d 00:00:00',
strtotime('-3 month')
);
}
}
}
}
}
if ($start_date) {
$end_date = date('Y-m-d 23:59:59', time());
$query->whereBetween('enter_at', [$start_date, $end_date]);
}
}
if ($request->has('status')) {
$status = $request->input('status');
if ($status) {
$query->where('status', $status);
}
}
if ($request->has('operation_type')) {
$operation_type = $request->input('operation_type');
if ($operation_type) {
$query->where('operation_type', $operation_type);
}
}
// 分页
$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()
);
}
}
public function handle(Request $request): JsonResponse
{
try {
$data = $request->all();
$this->validateId($data['id'] ?? 0, ParkingAbnormal::class);
$this->service->updateOperationType(
$data['id'],
$data['reason'] ?? ''
);
return $this->responseService->success(
null,
__('admin.operation_successful')
);
} catch (ValidationException|CustomException $e) {
throw $e;
} catch (Exception $e) {
return $this->responseService->systemError(
__('admin.operation_failed') . ':'
. $e->getMessage()
);
}
}
public function ignore(Request $request): JsonResponse
{
try {
$data = $request->all();
$this->validateId($data['id'] ?? 0, ParkingAbnormal::class);
$this->service->updateOperationType(
$data['id'],
$data['reason'] ?? '',
2
);
return $this->responseService->success(
null,
__('admin.operation_successful')
);
} catch (ValidationException|CustomException $e) {
throw $e;
} catch (Exception $e) {
return $this->responseService->systemError(
__('admin.operation_failed') . ':'
. $e->getMessage()
);
}
}
}

16
app/Http/Controllers/Admin/ParkingSpaceController.php

@ -308,21 +308,7 @@ class ParkingSpaceController extends BaseController
$data['parking_space_type'] = ParkingSpaceType::getName($item['space_type_id']); $data['parking_space_type'] = ParkingSpaceType::getName($item['space_type_id']);
$data['berthing_time_str'] = ''; $data['berthing_time_str'] = '';
if ($item['berthing_time']) { if ($item['berthing_time']) {
$difference = get_time_difference($item['berthing_time']); $data['berthing_time_str'] = get_time_difference_str($item['berthing_time']);
if (!isset($difference['error'])) {
if (!empty($difference['days'])) {
$data['berthing_time_str'] .= $difference['days'] . __('controller.parking_space.days');
}
if (!empty($difference['hours']) || !empty($data['berthing_time_str'])) {
$data['berthing_time_str'] .= $difference['hours'] . __('controller.parking_space.hours');
}
if (!empty($difference['minutes']) || !empty($data['berthing_time_str'])) {
$data['berthing_time_str'] .= $difference['minutes'] . __('controller.parking_space.minutes');
}
if (!empty($difference['seconds']) || !empty($data['berthing_time_str'])) {
$data['berthing_time_str'] .= $difference['seconds'] . __('controller.parking_space.seconds');
}
}
} }
$data['recognition_rate'] = $item['recognition']; $data['recognition_rate'] = $item['recognition'];
$data['recognition'] = $this->service->getRecognition( $data['recognition'] = $this->service->getRecognition(

46
app/Models/ParkingAbnormal.php

@ -0,0 +1,46 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ParkingAbnormal extends Model
{
use HasFactory;
protected $table = 'parking_abnormal';
protected $fillable
= [
'space_id',
'parking_id',
'license_plate_id',
'enter_at',
'type',
'status',
'operation_type',
'handle_reason',
'reason',
'operation_at',
'reservation_id'
];
protected $hidden
= [
'created_at',
'update_at'
];
public function getEnterAtAttribute($value): string
{
return $value ? date("Y-m-d H:i:s", strtotime($value)) : $value;
}
public function getOperationAtAttribute($value): string
{
return $value ? date("Y-m-d H:i:s", strtotime($value)) : '';
}
}

5
app/Models/ParkingReservation.php

@ -49,4 +49,9 @@ class ParkingReservation extends Model
? '' ? ''
: get_datetime('date_time', strtotime($value)); : get_datetime('date_time', strtotime($value));
} }
public static function getReserveId($id)
{
return self::query()->where('id', $id)->value('reserve_id');
}
} }

177
app/Services/ParkingAbnormalService.php

@ -0,0 +1,177 @@
<?php
namespace App\Services;
use App\Models\AdminFloor;
use App\Models\Parking;
use App\Models\ParkingAbnormal;
use App\Models\ParkingLicensePlate;
use App\Models\ParkingReservation;
use App\Models\ParkingSpace;
use App\Models\ParkingSpaceAttributes;
use App\Models\ParkingSpaceType;
use Exception;
use Illuminate\Support\Facades\DB;
class ParkingAbnormalService extends BaseService
{
public array $typeArr
= [
1 => 'occupancy',
];
public array $statusArr
= [
'unprocessed',
'processed'
];
public array $operationTypeArr
= [
1 => 'handle',
2 => 'ignore'
];
public array $reasonArr
= [
1 => 'reason1',
2 => 'reason2',
3 => 'reason3',
4 => 'reason4'
];
public array $dateArr
= [
1 => 'today',
2 => 'days3',
3 => 'week',
4 => 'month',
5 => 'month3'
];
protected string $menuTitle = 'abnormal_resource_usage';
/**
* @return array|string[]
*/
public function getDateArr(): array
{
$dateArr = $this->dateArr;
foreach ($dateArr as $key => $value) {
$dateArr[$key] = __service($this->menuTitle . '.' . $value);
}
return $dateArr;
}
public function getItem($item)
{
$item['parking'] = Parking::getName($item['parking_id']);
$ParkingSpace = ParkingSpace::query()->find($item['space_id']);
$item['floor'] = AdminFloor::getName($ParkingSpace['floor_id']);
$item['parking_space_number'] = $ParkingSpace['number'];
$item['parking_space_type'] = ParkingSpaceType::getName(
$ParkingSpace['space_type_id']
);
$item['parking_space_attr'] = ParkingSpaceAttributes::getAttr(
$ParkingSpace['space_attr_id']
);
$item['license_plate'] = ParkingLicensePlate::getNumber(
$item['license_plate_id']
);
$item['duration'] = get_time_difference_str($item['enter_at']);
$typeArr = $this->getType();
$item['type'] = $typeArr[$item['type']];
$statusArr = $this->getStatus();
$item['status'] = $statusArr[$item['status']];
$operationTypeArr = $this->getOperationType();
$item['operation_type'] = $operationTypeArr[$item['operation_type']] ??
'';
$reasonArr = $this->getReason();
$item['reason'] = $reasonArr[$item['reason']] ?? '';
$item['reservation_id'] = ParkingReservation::getReserveId(
$item['reservation_id']
);
unset(
$item['parking_id'],
$item['space_id'],
$item['license_plate_id']
);
return $item;
}
/**
* @return array|string[]
*/
public function getType(): array
{
$typeArr = $this->typeArr;
foreach ($typeArr as $key => $value) {
$typeArr[$key] = __service($this->menuTitle . '.' . $value);
}
return $typeArr;
}
/**
* @return array|string[]
*/
public function getStatus(): array
{
$typeArr = $this->statusArr;
foreach ($typeArr as $key => $value) {
$typeArr[$key] = __service($this->menuTitle . '.' . $value);
}
return $typeArr;
}
/**
* @return array|string[]
*/
public function getOperationType(): array
{
$operationTypeArr = $this->operationTypeArr;
foreach ($operationTypeArr as $key => $value) {
$operationTypeArr[$key] = __service(
$this->menuTitle . '.' . $value
);
}
return $operationTypeArr;
}
/**
* @return array|string[]
*/
public function getReason(): array
{
$reasonArr = $this->reasonArr;
foreach ($reasonArr as $key => $value) {
$reasonArr[$key] = __service($this->menuTitle . '.' . $value);
}
return $reasonArr;
}
public function updateOperationType($id, $reason, $operation_type = 1)
{
try {
DB::beginTransaction();
$model = ParkingAbnormal::query()->findOrFail($id);
$oldValue = $model->toArray();
$model->update([
'operation_type' => $operation_type,
'handle_reason' => $reason,
'operation_at' => get_datetime(),
'updated_at' => get_datetime()
]);
$this->logService->logUpdated(
$model,
$oldValue,
$this->menuTitle . '.operation'
);
DB::commit();
return $model;
} catch (Exception $e) {
DB::rollBack();
throw $e;
}
}
}

23
app/common.php

@ -151,6 +151,29 @@ if (!function_exists('get_time_difference')) {
} }
} }
if (!function_exists('get_time_difference_str')) {
function get_time_difference_str($date): string
{
$value = '';
$difference = get_time_difference($date);
if (!isset($difference['error'])) {
if (!empty($difference['days'])) {
$value .= $difference['days'] . __('controller.parking_space.days');
}
if (!empty($difference['hours']) || !empty($value)) {
$value .= $difference['hours'] . __('controller.parking_space.hours');
}
if (!empty($difference['minutes']) || !empty($value)) {
$value .= $difference['minutes'] . __('controller.parking_space.minutes');
}
if (!empty($difference['seconds']) || !empty($value)) {
$value .= $difference['seconds'] . __('controller.parking_space.seconds');
}
}
return $value;
}
}
if (!function_exists('get_image_url')) { if (!function_exists('get_image_url')) {
function get_image_url($image_url): string function get_image_url($image_url): string
{ {

40
database/migrations/2026_06_04_143449_create_parking_abnormal_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_abnormal', function (Blueprint $table) {
$table->id();
$table->integer('space_id')->comment('车位id');
$table->integer('parking_id')->comment('停车场ID');
$table->integer('license_plate_id')->comment('车牌号码');
$table->timestamp('enter_at')->comment('入场时间');
$table->tinyInteger('type')->default(1)->comment('异常类型');
$table->tinyInteger('status')->default(0)->comment('异常状态');
$table->tinyInteger('operation_type')->default(0)->comment('操作类型');
$table->string('handle_reason', 255)->default('')->comment('处理原因');
$table->tinyInteger('reason')->default(1)->comment('异常原因');
$table->timestamp('operation_at')->nullable()->comment('操作时间');
$table->integer('reservation_id')->nullable()->comment('预约id');
$table->timestamps();
$table->innoDb();
$table->comment('白名单');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('parking_abnormal');
}
};

4
database/seeders/AdminMenuSeeder.php

@ -261,7 +261,9 @@ class AdminMenuSeeder extends Seeder
'uri' => 'abnormalResourceUsage', 'uri' => 'abnormalResourceUsage',
'page_uri' => '/info/abnormalResourceUsage', 'page_uri' => '/info/abnormalResourceUsage',
'child' => [ 'child' => [
'read_only' => 'abnormalResourceUsage.index' 'read_only' => 'abnormalResourceUsage.index',
'abnormal_handle' => 'abnormalResourceUsage.handle',
'abnormal_ignore' => 'abnormalResourceUsage.ignore'
] ]
] ]
], ],

3
resources/lang/en/log.php

@ -131,5 +131,8 @@ return [
'create' => 'Create whitelist', 'create' => 'Create whitelist',
'update' => 'Update whitelist', 'update' => 'Update whitelist',
'delete' => 'Remove from whitelist' 'delete' => 'Remove from whitelist'
],
'abnormal_resource_usage' => [
'operation' => 'Update operation type'
] ]
]; ];

4
resources/lang/en/menu.php

@ -91,5 +91,7 @@ return [
'region_list' => 'region list', 'region_list' => 'region list',
'synchronize_list' => 'Synchronize List', 'synchronize_list' => 'Synchronize List',
'batch_parking_repair' => 'Batch import of maintenance parking spaces', 'batch_parking_repair' => 'Batch import of maintenance parking spaces',
'batch_update_attr' => 'Batch modify attributes' 'batch_update_attr' => 'Batch modify attributes',
'abnormal_handle' => 'handle exceptions',
'abnormal_ignore' => 'Ignore exceptions'
]; ];

16
resources/lang/en/service.php

@ -131,5 +131,21 @@ return [
], ],
'whitelist' => [ 'whitelist' => [
'number_exists' => 'The license plate number already exists' 'number_exists' => 'The license plate number already exists'
],
'abnormal_resource_usage' => [
'occupancy' => 'Abnormal occupancy',
'unprocessed' => 'unprocessed',
'processed' => 'Processed',
'handle' => 'handle',
'ignore' => 'ignore',
'reason1' => 'Unpredited vehicle parking',
'reason2' => 'Inconsistent with reserved parking space attributes',
'reason3' => 'Inconsistent with the reserved parking space type',
'reason4' => 'Inconsistent type',
'today' => 'that day',
'days3' => 'Over the past three days',
'week' => 'the past week',
'month' => 'Last month',
'month3' => 'Last March'
] ]
]; ];

3
resources/lang/zh-CN/log.php

@ -131,5 +131,8 @@ return [
'create' => '创建白名单', 'create' => '创建白名单',
'update' => '更新白名单', 'update' => '更新白名单',
'delete' => '删除白名单' 'delete' => '删除白名单'
],
'abnormal_resource_usage' => [
'operation' => '更新操作类型'
] ]
]; ];

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

@ -91,5 +91,7 @@ return [
'region_list' => '区域列表', 'region_list' => '区域列表',
'synchronize_list' => '同步列表', 'synchronize_list' => '同步列表',
'batch_parking_repair' => '批量导入维修车位', 'batch_parking_repair' => '批量导入维修车位',
'batch_update_attr' => '批量修改属性' 'batch_update_attr' => '批量修改属性',
'abnormal_handle' => '处理异常',
'abnormal_ignore' => '忽略异常'
]; ];

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

@ -131,5 +131,21 @@ return [
], ],
'whitelist' => [ 'whitelist' => [
'number_exists' => '车牌号码已存在' 'number_exists' => '车牌号码已存在'
],
'abnormal_resource_usage' => [
'occupancy' => '异常占用',
'unprocessed' => '未处理',
'processed' => '已处理',
'handle' => '处理',
'ignore' => '忽略',
'reason1' => '未预约车辆停车',
'reason2' => '与预约车位属性不一致',
'reason3' => '与预约车位类型不一致',
'reason4' => '类型不一致',
'today' => '当天',
'days3' => '过去三天',
'week' => '过去一周',
'month' => '过去一月',
'month3' => '过去三月'
] ]
]; ];

3
resources/lang/zh-TW/log.php

@ -131,5 +131,8 @@ return [
'create' => '創建白名單', 'create' => '創建白名單',
'update' => '更新白名單', 'update' => '更新白名單',
'delete' => '删除白名單' 'delete' => '删除白名單'
],
'abnormal_resource_usage' => [
'operation' => '更新操作類型'
] ]
]; ];

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

@ -91,5 +91,7 @@ return [
'region_list' => '區域清單', 'region_list' => '區域清單',
'synchronize_list' => '同步清單', 'synchronize_list' => '同步清單',
'batch_parking_repair' => '批量導入維修車位', 'batch_parking_repair' => '批量導入維修車位',
'batch_update_attr' => '批量修改内容' 'batch_update_attr' => '批量修改内容',
'abnormal_handle' => '處理异常',
'abnormal_ignore' => '忽略异常'
]; ];

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

@ -131,5 +131,21 @@ return [
], ],
'whitelist' => [ 'whitelist' => [
'number_exists' => '車牌號碼已存在' 'number_exists' => '車牌號碼已存在'
],
'abnormal_resource_usage' => [
'occupancy' => '异常佔用',
'unprocessed' => '未處理',
'processed' => '已處理',
'handle' => '處理',
'ignore' => '忽略',
'reason1' => '未預約車輛停車',
'reason2' => '與預約車位内容不一致',
'reason3' => '與預約車位類型不一致',
'reason4' => '類型不一致',
'today' => '當天',
'days3' => '過去三天',
'week' => '過去一周',
'month' => '過去一月',
'month3' => '過去三月'
] ]
]; ];

5
routes/admin/api.php

@ -37,6 +37,7 @@ use App\Http\Controllers\Admin\ParkingDepartureReasonController;
use App\Http\Controllers\Admin\ChannelPermissionsController; use App\Http\Controllers\Admin\ChannelPermissionsController;
use App\Http\Controllers\Admin\ParkingEquipmentController; use App\Http\Controllers\Admin\ParkingEquipmentController;
use App\Http\Controllers\Admin\ParkingWhitelistController; use App\Http\Controllers\Admin\ParkingWhitelistController;
use App\Http\Controllers\Admin\ParkingAbnormalController;
Route::group(['prefix' => 'admin'], function () { Route::group(['prefix' => 'admin'], function () {
@ -186,6 +187,10 @@ Route::group(['prefix' => 'admin'], function () {
Route::get('/notice/setting', [NoticeController::class, 'create']); Route::get('/notice/setting', [NoticeController::class, 'create']);
Route::post('/notice/setting', [NoticeController::class, 'setting']); Route::post('/notice/setting', [NoticeController::class, 'setting']);
Route::get('/notice/show/{id}', [NoticeController::class, 'show']); Route::get('/notice/show/{id}', [NoticeController::class, 'show']);
// 异常占用
Route::get('/abnormalResourceUsage', [ParkingAbnormalController::class, 'index']);
Route::post('/abnormalResourceUsage/handle', [ParkingAbnormalController::class, 'handle']);
Route::post('/abnormalResourceUsage/ignore', [ParkingAbnormalController::class, 'ignore']);
// 车牌识别率 // 车牌识别率
Route::get('/licensePlateRecognition', [LicensePlateRecognitionController::class, 'index']); Route::get('/licensePlateRecognition', [LicensePlateRecognitionController::class, 'index']);
Route::get('/licensePlateRecognition/curveGraph', [LicensePlateRecognitionController::class, 'curveGraph']); Route::get('/licensePlateRecognition/curveGraph', [LicensePlateRecognitionController::class, 'curveGraph']);

Loading…
Cancel
Save