Browse Source

预约管理

master
wanghongjun 2 weeks ago
parent
commit
bc9933dea9
  1. 170
      app/Http/Controllers/Admin/ParkingReservationController.php
  2. 11
      app/Models/EventCalendar.php
  3. 19
      app/Models/ParkingReservation.php
  4. 8
      app/Models/ParkingSpaceType.php
  5. 12
      database/migrations/2026_03_20_162930_create_parking_reservation_table.php
  6. 14
      database/seeders/AdminMenuSeeder.php
  7. 9
      resources/lang/en/service.php
  8. 9
      resources/lang/zh-CN/service.php
  9. 9
      resources/lang/zh-TW/service.php
  10. 3
      routes/admin/api.php

170
app/Http/Controllers/Admin/ParkingReservationController.php

@ -2,15 +2,19 @@
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\AdminFloor;
use App\Models\AdminFloorRegion;
use App\Models\EventCalendar;
use App\Models\Parking;
use App\Models\ParkingChannel;
use App\Models\ParkingLicensePlate;
use App\Models\ParkingPattern;
use App\Models\ParkingReservation;
use App\Models\ParkingSpace;
use App\Models\ParkingSpaceAttributes;
use App\Models\ParkingSpaceType;
use App\Services\ApiResponseService;
use App\Services\ParkingAdminUserService;
use App\Services\ParkingReservationService;
use Exception;
use Illuminate\Http\JsonResponse;
@ -90,6 +94,7 @@ class ParkingReservationController extends BaseController
if ($request->has('space_attr_id')) {
$space_attr_id = $request->input('space_attr_id');
if (!empty($space_attr_id)) {
$query->where('space_attr_id', $space_attr_id);
}
}
if ($request->has('status')) {
@ -98,20 +103,74 @@ class ParkingReservationController extends BaseController
$query->where('status', $status);
}
}
if ($request->has('parking_id')) {
$parking_id = $request->input('parking_id');
if (!empty($parking_id)) {
$query->where('parking_id', $parking_id);
}
}
if ($request->has('member_type')) {
$member_type = $request->input('member_type');
if (!empty($member_type)) {
$query->where('member_type', $member_type);
}
}
if ($request->has('customer_id')) {
$customer_id = $request->input('customer_id');
if (!empty($customer_id)) {
$query->where('customer_id', $customer_id);
}
}
if ($request->has('member_id')) {
$member_id = $request->input('member_id');
if (!empty($member_id)) {
$query->where('member_id', $member_id);
}
}
if ($request->has('start_date')) {
$start_date = $request->input('start_date');
if (!empty($start_date)) {
$query->where('date', '>=', $start_date);
}
}
if ($request->has('end_date')) {
$end_date = $request->input('end_date');
if (!empty($end_date)) {
$query->where('date', '<=', $end_date);
}
}
if ($request->has('reserve_id')) {
$reserve_id = $request->input('reserve_id');
if (!empty($reserve_id)) {
$query->where('reserve_id', $reserve_id);
}
}
// 分页
$page = $request->input('page', 1);
$perPage = $request->input('per_page', 10);
$memberTypeArr = ParkingAdminUserService::$memberType;
$total = $query->count();
$items = $query->latest()->forPage($page, $perPage)->get()->each(
function ($item) {
function ($item) use ($memberTypeArr) {
$item['member_type'] = $memberTypeArr[$item['member_type']] ?? '';
$item['channel'] = ParkingChannel::getName($item['channel_id']);
$item['parking'] = Parking::getName($item['parking_id']);
$item['status'] = $this->service->getStatusStr(
$item['status']
);
$item['space_type'] = ParkingSpaceType::getName(
$item['space_type_id']
);
$item['space_attr'] = ParkingSpaceAttributes::getAttr(
$item['space_attr_id']
);
$item['license_plate'] = ParkingLicensePlate::getNumber(
$item['license_plate_id']
);
@ -125,7 +184,10 @@ class ParkingReservationController extends BaseController
$item['space_type_id'],
$item['license_plate_id'],
$item['floor_id'],
$item['floor_region_id']
$item['floor_region_id'],
$item['space_attr_id'],
$item['channel_id'],
$item['parking_id']
);
return $item;
}
@ -155,7 +217,9 @@ class ParkingReservationController extends BaseController
'space_attr_data' => ParkingSpaceAttributes::getData(),
'status_data' => get_select_data(
$this->service->getStatusArr()
)
),
'parking_list' => Parking::getData(),
'member_type' => get_select_data(ParkingAdminUserService::$memberType)
];
return $this->responseService->success($data);
} catch (Exception $e) {
@ -166,6 +230,58 @@ class ParkingReservationController extends BaseController
}
}
public function show(Request $request): JsonResponse
{
try {
$id = $request->input('id', 0);
$query = ParkingReservation::query();
$query->where('id', $id);
$page = $request->input('page', 1);
$perPage = $request->input('per_page', 10);
$memberTypeArr = ParkingAdminUserService::$memberType;
$total = $query->count();
$reservation_number = '';
$items = $query->latest()->forPage($page, $perPage)->get()->each(
function ($item) use ($memberTypeArr, &$reservation_number) {
$item['member_type'] = $memberTypeArr[$item['member_type']] ?? '';
$item['license_plate'] = ParkingLicensePlate::getNumber(
$item['license_plate_id']
);
$item['is_driver'] = $this->service->getIsDriver(
$item['is_driver']
);
$item['order_number'] = $item['reserve_id'];
$reservation_number = $item['reserve_id'];
unset(
$item['space_type_id'],
$item['license_plate_id'],
$item['floor_id'],
$item['floor_region_id'],
$item['space_attr_id'],
$item['channel_id'],
$item['parking_id'],
$item['status']
);
return $item;
}
);
return $this->responseService->success([
'items' => $items,
'total' => $total,
'page' => $page,
'per_page' => $perPage,
'last_page' => ceil($total / $perPage),
'reservation_number' => $reservation_number
]);
} catch (Exception $e) {
return $this->responseService->systemError(
__('exception.get_data_failed') . ':' . $e->getMessage()
);
}
}
public function statistics(Request $request): JsonResponse
{
try {
@ -204,4 +320,50 @@ class ParkingReservationController extends BaseController
}
}
public function getDateStatistics(Request $request): JsonResponse
{
try {
$param = $request->all();
$date = $param['date'] ?? date("Y-m-d", time());
$query = ParkingReservation::query();
$query->where('date', $date);
if (isset($param['parking_id'])) {
$query->where('parking_id', $param['parking_id']);
}
$total = $query->count();
$w = date('w', strtotime($date));
$week_str = __service("reservation.week{$w}");
$patternId = EventCalendar::getDatePatternId($date);
$space_set_name = '';
if ($patternId) {
$space_set_name = ParkingPattern::getName($patternId);
}
$space_type_ids = $query->pluck('space_type_id')->toArray();
$member_type_list = [];
if ($space_type_ids) {
$member_type_list = ParkingSpaceType::getData();
$counts = array_count_values((array)$space_type_ids);
foreach ($member_type_list as &$item) {
$item['count'] = $counts[$item['id']] ?? 0;
unset($item['id']);
}
}
$data = [
'date_str' => $date,
'space_set_name' => $space_set_name,
'total' => $total,
'week_str' => $week_str,
'member_type_list' => $member_type_list
];
return $this->responseService->success($data);
} catch (Exception $e) {
$m_prefix = __('exception.exception_handler.resource');
return $this->responseService->systemError(
$m_prefix . ':' . $e->getMessage()
);
}
}
}

11
app/Models/EventCalendar.php

@ -38,4 +38,15 @@ class EventCalendar extends Model
{
return date('Y-m-d H:i', strtotime($value));
}
public static function getDatePatternId($date)
{
return self::query()->whereIn('status', [0, 1, 2])->where(
function ($query) use ($date) {
$query->whereRaw(
"'{$date}' BETWEEN start_time AND end_time"
);
}
)->value('pattern_id');
}
}

19
app/Models/ParkingReservation.php

@ -15,19 +15,28 @@ class ParkingReservation extends Model
= [
'reserve_id',
'space_type_id',
'space_attr_id',
'license_plate_type',
'license_plate_id',
'is_driver',
'floor_id',
'floor_region_id',
'status',
'confirm_at'
'confirm_at',
'customer_id',
'member_id',
'channel_id',
'member_type',
'parking_id',
'remark',
'date',
'operation',
'confirm_status',
'cancel_at',
'send_at'
];
protected $hidden
= [
'updated_at'
];
protected $hidden = [];
public function getCreatedAtAttribute($value): string
{

8
app/Models/ParkingSpaceType.php

@ -37,9 +37,13 @@ class ParkingSpaceType extends Model
return self::query()->where('id', $id)->value('name') ?? '';
}
public static function getData(): array
public static function getData($ids = []): array
{
return self::query()->select(['id', 'name'])->get()->each(
$query = self::query();
if ($ids) {
$query->whereIn('id', $ids);
}
return $query->select(['id', 'name'])->get()->each(
function ($item) {
$item['name']
= AdminTranslationService::getTranslationTypeName(

12
database/migrations/2026_03_20_162930_create_parking_reservation_table.php

@ -16,12 +16,24 @@ return new class extends Migration
$table->string('reserve_id', 12)->comment('预定编号');
$table->integer('space_type_id')->comment('车位类型');
$table->integer('license_plate_type')->comment('车牌类型');
$table->integer('space_attr_id')->comment('车位属性');
$table->integer('license_plate_id')->comment('车牌号码ID');
$table->tinyInteger('is_driver')->default(0)->comment('是否登记司机');
$table->integer('floor_id')->nullable()->comment('楼层ID');
$table->integer('floor_region_id')->nullable()->comment('楼层区域ID');
$table->tinyInteger('status')->default(0)->comment('状态 0待确定 1已确定 2已取消');
$table->timestamp('confirm_at')->nullable()->comment('确定时间');
$table->string('member_id', 50)->default('')->comment('客户ID');
$table->string('member_id', 50)->default('')->comment('会员ID');
$table->integer('channel_id')->nullable()->comment('通道ID');
$table->tinyInteger('member_type')->default(0)->comment('会员类型');
$table->integer('parking_id')->nullable()->comment('停车场id');
$table->string('remark', 255)->default('')->comment('备注');
$table->date('date')->comment('预约日期');
$table->string('varchar', 255)->default('')->comment('操作');
$table->string('confirm_status', 255)->default('')->comment('预约状态');
$table->timestamp('cancel_at')->nullable()->comment('取消时间');
$table->timestamp('send_at')->nullable()->comment('预约发起时间');
$table->timestamps();
$table->comment('车位预定列表');
$table->innoDb();

14
database/seeders/AdminMenuSeeder.php

@ -483,15 +483,15 @@ class AdminMenuSeeder extends Seeder
]
],
'parking_space_management' => [
'uri' => 'parkingManagement',
'uri' => 'parkingSpaceManagement',
'page_uri' => '/parkingmanagement/parkingManagement',
'child' => [
'read_only' => 'parkingManagement.index',
'add' => 'parkingManagement.store',
'edit' => 'parkingManagement.update',
'delete' => 'parkingManagement.destroy',
'batch_update_attr' => 'parkingManagement.batchUpdateAttr',
'batch_delete' => 'parkingManagement.batchDelete'
'read_only' => 'parkingSpaceManagement.index',
'add' => 'parkingSpaceManagement.store',
'edit' => 'parkingSpaceManagement.update',
'delete' => 'parkingSpaceManagement.destroy',
'batch_update_attr' => 'parkingSpaceManagement.batchUpdateAttr',
'batch_delete' => 'parkingSpaceManagement.batchDelete'
]
],
],

9
resources/lang/en/service.php

@ -50,7 +50,14 @@ return [
'yes' => 'yes',
'no' => 'No',
'fuel' => 'fuel',
'new_energy' => 'new energy'
'new_energy' => 'new energy',
'week0' => 'Sunday',
'week1' => 'Monday',
'week2' => 'Tuesday',
'week3' => 'Wednesday',
'week4' => 'Thursday',
'week5' => 'Friday',
'week6' => 'Saturday'
],
'parking_space' => [
'vacant' => 'vacant',

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

@ -50,7 +50,14 @@ return [
'yes' => '是',
'no' => '否',
'fuel' => '燃油',
'new_energy' => '新能源'
'new_energy' => '新能源',
'week0' => '星期日',
'week1' => '星期一',
'week2' => '星期二',
'week3' => '星期三',
'week4' => '星期四',
'week5' => '星期五',
'week6' => '星期六'
],
'parking_space' => [
'vacant' => '空置',

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

@ -50,7 +50,14 @@ return [
'yes' => '是',
'no' => '否',
'fuel' => '燃油',
'new_energy' => '新能源'
'new_energy' => '新能源',
'week0' => '星期日',
'week1' => '星期一',
'week2' => '星期二',
'week3' => '星期三',
'week4' => '星期四',
'week5' => '星期五',
'week6' => '星期六'
],
'parking_space' => [
'vacant' => '空置',

3
routes/admin/api.php

@ -105,6 +105,9 @@ Route::group(['prefix' => 'admin'], function () {
Route::get('/parkingReservation/search', [ParkingReservationController::class, 'search']);
Route::get('/parkingReservation/statistics', [ParkingReservationController::class, 'statistics']);
Route::get('/parkingReservation/rule', [ParkingReservationController::class, 'rule']);
Route::get('/parkingReservation/index', [ParkingReservationController::class, 'show']);
// 预约统计
Route::get('/parkingReservationStatistics/index', [ParkingReservationController::class, 'getDateStatistics']);
// 车位列表
Route::get('/parkingSpace', [ParkingSpaceController::class, 'index']);
Route::get('/parkingSpace/search', [ParkingSpaceController::class, 'search']);

Loading…
Cancel
Save