Browse Source

通道管理

master
wanghongjun 2 weeks ago
parent
commit
4bafc37cdd
  1. 308
      app/Http/Controllers/Admin/ParkingChannelController.php
  2. 33
      app/Models/ParkingChannel.php
  3. 52
      app/Models/ParkingGuardBooth.php
  4. 176
      app/Services/ParkingChannelService.php
  5. 36
      database/migrations/2026_06_02_143449_create_parking_channel_table.php
  6. 32
      database/migrations/2026_06_02_143449_create_parking_guard_booth_table.php
  7. 5
      resources/lang/en/log.php
  8. 5
      resources/lang/zh-CN/log.php
  9. 5
      resources/lang/zh-TW/log.php
  10. 10
      routes/admin/api.php

308
app/Http/Controllers/Admin/ParkingChannelController.php

@ -0,0 +1,308 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Exceptions\CustomException;
use App\Models\Parking;
use App\Models\ParkingChannel;
use App\Models\ParkingGuardBooth;
use App\Services\AdminTranslationService;
use App\Services\ApiResponseService;
use App\Services\ParkingChannelService;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
class ParkingChannelController extends BaseController
{
protected string $menuUri = 'channelManagement';
/**
* @var ParkingChannelService
*/
protected ParkingChannelService $service;
/**
* 构造函数
* @param ApiResponseService $responseService
* @param ParkingChannelService $service
*/
public function __construct(
ApiResponseService $responseService,
ParkingChannelService $service
) {
parent::__construct($responseService);
$this->service = $service;
}
/**
* @param Request $request
* @return JsonResponse
*/
public function index(Request $request): JsonResponse
{
try {
$query = ParkingChannel::query();
if ($request->has('type')) {
$type = $request->input('type');
if ($type) {
$query->where('type', $type);
}
}
if ($request->has('name')) {
$name = $request->input('name');
if ($name) {
$query->where('name', 'like', "%{$name}%");
}
}
if ($request->has('create_start_time')
&& $request->has(
'create_end_time'
)
) {
$create_start_time = $request->input('create_start_time');
$create_end_time = $request->input('create_end_time');
if ($create_start_time && $create_end_time) {
$query->whereBetween('created_at', [
$create_start_time . ' 00:00:00',
$create_end_time . ' 23:59:59'
]);
}
}
// 分页
$page = $request->input('page', 1);
$perPage = $request->input('per_page', 10);
$typeArr = ParkingChannelService::getType();
$positionArr = ParkingChannelService::getPosition();
$total = $query->count();
$items = $query->latest()->forPage($page, $perPage)->get()->each(
function ($item) use ($typeArr, $positionArr) {
$item['name']
= AdminTranslationService::getTranslationTypeName(
$item['id'],
6,
$item['name']
);
$item['type_str'] = $typeArr[$item['type']];
$item['position_str'] = $positionArr[$item['position']];
$item['guard_booth'] = ParkingGuardBooth::getName($item['guard_booth_id']);
$item['parking'] = Parking::getName($item['parking_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()
);
}
}
/**
* 列表搜索数据
* @return JsonResponse
*/
public function search(): JsonResponse
{
try {
$data = [
'type_list' => get_select_data(ParkingChannelService::getType())
];
return $this->responseService->success($data);
} catch (Exception $e) {
$m_prefix = __('exception.exception_handler.resource');
return $this->responseService->systemError(
$m_prefix . ':' . $e->getMessage()
);
}
}
/**
* @return JsonResponse
*/
public function create(): JsonResponse
{
try {
$data = [
'type_list' => get_select_data(
ParkingChannelService::getType()
),
'position_list' => get_select_data(
ParkingChannelService::getPosition()
),
'parking_list' => Parking::getData(),
'guard_booth_list' => ParkingGuardBooth::getData()
];
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->service->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.admin_floor.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',
'type' => 'required',
'position' => 'required',
'parking_id' => 'required',
'guard_booth_id' => 'required'
];
$messages = [
'name.required' => __(
'validation.channel_management.n_empty'
),
'type.required' => __(
'validation.channel_management.t_empty'
),
'position.required' => __(
'validation.channel_management.po_empty'
),
'parking_id.required' => __(
'validation.channel_management.pa_empty'
),
'guard_booth_id.required' => __(
'validation.channel_management.g_empty'
)
];
if ($id) {
$this->validateId($id, ParkingChannel::class);
}
$validator = Validator::make($data, $rules, $messages);
if ($validator->fails()) {
throw new ValidationException($validator);
}
}
/**
* @param string $id
* @return JsonResponse
*/
public function edit(string $id): JsonResponse
{
try {
$this->validateId($id, ParkingChannel::class);
$data = [
'type_list' => get_select_data(
ParkingChannelService::$typeArr
),
'position_list' => get_select_data(
ParkingChannelService::$positionArr
),
'parking_list' => Parking::getData(),
'guard_booth_list' => ParkingGuardBooth::getData(),
'item' => ParkingChannel::query()->find($id)
];
$Translation = AdminTranslationService::getTranslation(
$data['item']['id'],
6
);
$data['item']['en_name'] = $Translation['en'] ?? '';
$data['item']['tw_name'] = $Translation['zh_tw'] ?? '';
return $this->responseService->success($data);
} catch (Exception $e) {
return $this->responseService->systemError(
__('exception.get_data_failed') . ':' . $e->getMessage()
);
}
}
/**
* @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->service->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.admin_floor.update_failed') . ':'
. $e->getMessage()
);
}
}
/**
* @param string $id
* @return JsonResponse
* @throws CustomException
* @throws ValidationException
*/
public function destroy(string $id): JsonResponse
{
try {
$this->validateId($id, ParkingChannel::class);
$this->service->deleteModel($id);
return $this->responseService->success(
null,
__('admin.delete_succeeded')
);
} catch (ValidationException|CustomException $e) {
throw $e;
} catch (Exception $e) {
return $this->responseService->systemError(
__('exception.admin_floor.destroy_failed') . ':'
. $e->getMessage()
);
}
}
}

33
app/Models/ParkingChannel.php

@ -0,0 +1,33 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class ParkingChannel extends Model
{
use HasFactory, SoftDeletes;
protected $table = 'parking_channel';
protected $fillable = [
'name',
'type',
'position',
'parking_id',
'guard_booth_id',
'third_party_channel'
];
protected $hidden = [
'updated_at',
'deleted_at'
];
public function getCreatedAtAttribute($value): string
{
return $value ? date("Y-m-d H:i:s", strtotime($value)) : $value;
}
}

52
app/Models/ParkingGuardBooth.php

@ -0,0 +1,52 @@
<?php
namespace App\Models;
use App\Services\AdminTranslationService;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class ParkingGuardBooth extends Model
{
use HasFactory, SoftDeletes;
protected $table = 'parking_guard_booth';
protected $fillable
= [
'name',
'remake'
];
protected $hidden
= [
'updated_at',
'deleted_at'
];
public static function getData()
{
return self::query()->select(['id', 'name'])->get()->each(
function ($item) {
$item['name'] = AdminTranslationService::getTranslationTypeName(
$item['id'],
7,
$item['name']
);
return $item;
}
)->toArray();
}
public function getCreatedAtAttribute($value): string
{
return $value ? date("Y-m-d H:i:s", strtotime($value)) : $value;
}
public static function getName($id)
{
$name = self::query()->value('name');
return AdminTranslationService::getTranslationTypeName($id, 7, $name);
}
}

176
app/Services/ParkingChannelService.php

@ -0,0 +1,176 @@
<?php
namespace App\Services;
use App\Models\ParkingChannel;
use Exception;
use Illuminate\Support\Facades\DB;
class ParkingChannelService extends BaseService
{
protected string $menuTitle = 'channel_management';
public static array $typeArr = [
1 => 'entrance',
2 => 'export'
];
public static array $positionArr = [
1 => 'on-site',
2 => 'off-site'
];
/**
* @return array|string[]
*/
public static function getType(): array
{
$typeArr = self::$typeArr;
foreach ($typeArr as $key => $value) {
$typeArr[$key] = __('service.channel_management.' . $value);
}
return $typeArr;
}
/**
* @return array|string[]
*/
public static function getPosition(): array
{
$positionArr = self::$positionArr;
foreach ($positionArr as $key => $value) {
$positionArr[$key] = __('service.channel_management.' . $value);
}
return $positionArr;
}
/**
* @param array $data
* @throws Exception
*/
public function createModel(array $data)
{
try {
DB::beginTransaction();
$existsWhere = [
['name', '=', $data['name']],
['parking_id', '=', $data['parking_id']],
['guard_booth_id', '=', $data['guard_booth_id']]
];
if (ParkingChannel::query()->where($existsWhere)->exists()) {
throw new Exception(__('service.channel_management.name_exists'));
}
$model = ParkingChannel::query()->create([
'name' => $data['name'],
'type' => $data['type'],
'position' => $data['position'],
'parking_id' => $data['parking_id'],
'guard_booth_id' => $data['guard_booth_id'],
'third_party_channel' => $data['third_party_channel'] ?? '',
'created_at' => get_datetime()
]);
$this->logService->logCreated($model, 'channel_management.create');
AdminTranslationService::saveTranslation(
$data['name'],
$data['en_name'] ?? '',
$data['tw_name'] ?? '',
$model->id,
6
);
DB::commit();
return $model;
} catch (Exception $e) {
DB::rollBack();
throw $e;
}
}
/**
* @param array $data
* @param int $id
* @throws Exception
*/
public function updateModel(array $data, int $id)
{
try {
DB::beginTransaction();
// 验证
$existsWhere = [
['name', '=', $data['name']],
['parking_id', '=', $data['parking_id']],
['guard_booth_id', '=', $data['guard_booth_id']],
['id', '<>', $id]
];
if (ParkingChannel::query()->where($existsWhere)->exists()) {
throw new Exception(__('service.channel_management.name_exists'));
}
// 更新
$model = ParkingChannel::query()->findOrFail($id);
$oldValues = $model->toArray();
$model->update([
'name' => $data['name'],
'type' => $data['type'],
'position' => $data['position'],
'parking_id' => $data['parking_id'],
'guard_booth_id' => $data['guard_booth_id'],
'third_party_channel' => $data['third_party_channel'] ?? '',
'updated_at' => get_datetime()
]);
$this->logService->logUpdated(
$model,
$oldValues,
'channel_management.update'
);
AdminTranslationService::saveTranslation(
$data['name'],
$data['en_name'] ?? '',
$data['tw_name'] ?? '',
$id,
6
);
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 = ParkingChannel::query()->findOrFail($id);
$this->logService->logDeleted($model, 'channel_management.delete');
$model->delete();
AdminTranslationService::syncDelete($id, 6);
DB::commit();
return true;
} catch (Exception $e) {
DB::rollBack();
throw $e;
}
}
}

36
database/migrations/2026_06_02_143449_create_parking_channel_table.php

@ -0,0 +1,36 @@
<?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_channel', function (Blueprint $table) {
$table->id();
$table->string('name', 50)->comment('通道名称');
$table->tinyInteger('type')->default(1)->comment('通道类型');
$table->tinyInteger('position')->default(1)->comment('通道位置');
$table->integer('parking_id')->comment('所属停车场');
$table->integer('guard_booth_id')->comment('所属岗亭');
$table->string('third_party_channel', 255)->default('')->comment('第三方通道');
$table->timestamps();
$table->softDeletes();
$table->innoDb();
$table->comment('停车场通道');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('parking_channel');
}
};

32
database/migrations/2026_06_02_143449_create_parking_guard_booth_table.php

@ -0,0 +1,32 @@
<?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_guard_booth', function (Blueprint $table) {
$table->id();
$table->string('name', 50)->comment('岗亭名称');
$table->string('remake', 255)->default('')->comment('备注');
$table->timestamps();
$table->softDeletes();
$table->innoDb();
$table->comment('停车场通道');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('parking_guard_booth');
}
};

5
resources/lang/en/log.php

@ -101,5 +101,10 @@ return [
'create' => 'Create a parking lot administrator',
'update' => 'Update parking lot administrator',
'delete' => 'Delete parking lot administrator'
],
'channel_management' => [
'create' => 'Create channel',
'update' => 'Update channel',
'delete' => 'Delete channel'
]
];

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

@ -101,5 +101,10 @@ return [
'create' => '创建停车场管理员',
'update' => '更新停车场管理员',
'delete' => '删除停车场管理员'
],
'channel_management' => [
'create' => '创建通道',
'update' => '更新通道',
'delete' => '删除通道'
]
];

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

@ -101,5 +101,10 @@ return [
'create' => '創建停車場管理員',
'update' => '更新停車場管理員',
'delete' => '删除停車場管理員'
],
'channel_management' => [
'create' => '創建通道',
'update' => '更新通道',
'delete' => '删除通道'
]
];

10
routes/admin/api.php

@ -31,6 +31,7 @@ use App\Http\Controllers\Admin\ParkingManagementController;
use App\Http\Controllers\Admin\ParkingManagementListController;
use App\Http\Controllers\Admin\ParkingAttendantController;
use App\Http\Controllers\Admin\RegionalManagementController;
use App\Http\Controllers\Admin\ParkingChannelController;
Route::group(['prefix' => 'admin'], function () {
@ -238,6 +239,15 @@ Route::group(['prefix' => 'admin'], function () {
Route::delete('/regionalManagement/{id}', [RegionalManagementController::class, 'destroy']);
Route::get('/regionalManagement/rule', [RegionalManagementController::class, 'rule']);
Route::get('/regionalManagement/search', [RegionalManagementController::class, 'search']);
// 通道管理
Route::get('/channelManagement', [ParkingChannelController::class, 'index']);
Route::get('/channelManagement/create', [ParkingChannelController::class, 'create']);
Route::post('/channelManagement', [ParkingChannelController::class, 'store']);
Route::get('/channelManagement/edit/{id}', [ParkingChannelController::class, 'edit']);
Route::put('/channelManagement/{id}', [ParkingChannelController::class, 'update']);
Route::delete('/channelManagement/{id}', [ParkingChannelController::class, 'destroy']);
Route::get('/channelManagement/rule', [ParkingChannelController::class, 'rule']);
Route::get('/channelManagement/search', [ParkingChannelController::class, 'search']);
// 角色
Route::get('/roles', [RolesController::class, 'index']);
Route::get('/roles/create', [RolesController::class, 'create']);

Loading…
Cancel
Save