11 changed files with 375 additions and 4 deletions
@ -0,0 +1,62 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Exports; |
||||
|
|
||||
|
use App\Services\OperationLogService; |
||||
|
use App\Services\UtilizationRateService; |
||||
|
use Maatwebsite\Excel\Concerns\FromArray; |
||||
|
use Maatwebsite\Excel\Concerns\WithHeadings; |
||||
|
|
||||
|
class UtilizationRateExport implements FromArray, WithHeadings |
||||
|
{ |
||||
|
public array $parents = []; |
||||
|
public UtilizationRateService $service; |
||||
|
|
||||
|
public function __construct($parents) |
||||
|
{ |
||||
|
$this->parents = $parents; |
||||
|
$this->service = new UtilizationRateService( |
||||
|
new OperationLogService() |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
public function array(): array |
||||
|
{ |
||||
|
$data = []; |
||||
|
$index = 1; |
||||
|
$query = $this->service->searchQuery($this->parents); |
||||
|
$list = $query->select()->get()->toArray(); |
||||
|
foreach ($list as $item) { |
||||
|
$item = $this->service->getItem($item); |
||||
|
$data[] = [ |
||||
|
'index' => $index, |
||||
|
'start_time' => $item['start_time'], |
||||
|
'end_time' => $item['end_time'], |
||||
|
'floor' => $item['floor'], |
||||
|
'number' => $item['number'], |
||||
|
'space_type' => $item['space_type'], |
||||
|
'space_attr' => $item['space_attr'], |
||||
|
'rate' => $item['rate'] |
||||
|
]; |
||||
|
$index += 1; |
||||
|
} |
||||
|
return $data; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @return array |
||||
|
*/ |
||||
|
public function headings(): array |
||||
|
{ |
||||
|
return [ |
||||
|
__('exports.global.index'), |
||||
|
__('exports.event_calendar.export3'), |
||||
|
__('exports.event_calendar.export5'), |
||||
|
__('exports.parking_space.floor'), |
||||
|
__('exports.parking_space.number'), |
||||
|
__('exports.parking_space.space_type'), |
||||
|
__('exports.parking_space.space_attr'), |
||||
|
__('exports.utilization_rate.rate'), |
||||
|
]; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,138 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Http\Controllers\Admin; |
||||
|
|
||||
|
use App\Exports\UtilizationRateExport; |
||||
|
use App\Models\AdminFloor; |
||||
|
use App\Models\ParkingSpace; |
||||
|
use App\Models\ParkingSpaceType; |
||||
|
use App\Models\ParkingUtilizationRate; |
||||
|
use App\Services\ApiResponseService; |
||||
|
use App\Services\UtilizationRateService; |
||||
|
use Exception; |
||||
|
use Illuminate\Http\JsonResponse; |
||||
|
use Illuminate\Http\Request; |
||||
|
use Maatwebsite\Excel\Facades\Excel; |
||||
|
use Symfony\Component\HttpFoundation\BinaryFileResponse; |
||||
|
|
||||
|
class UtilizationRateController extends BaseController |
||||
|
{ |
||||
|
protected string $menuUri = 'utilizationRate'; |
||||
|
|
||||
|
/** |
||||
|
* @var UtilizationRateService |
||||
|
*/ |
||||
|
protected UtilizationRateService $service; |
||||
|
|
||||
|
/** |
||||
|
* 构造函数 |
||||
|
* @param ApiResponseService $responseService |
||||
|
* @param UtilizationRateService $service |
||||
|
*/ |
||||
|
public function __construct( |
||||
|
ApiResponseService $responseService, |
||||
|
UtilizationRateService $service |
||||
|
) { |
||||
|
parent::__construct($responseService); |
||||
|
$this->service = $service; |
||||
|
} |
||||
|
|
||||
|
public function index(Request $request): JsonResponse |
||||
|
{ |
||||
|
try { |
||||
|
$query = $this->service->searchQuery($request->all()); |
||||
|
|
||||
|
// 分页 |
||||
|
$page = $request->input('page', 1); |
||||
|
$perPage = $request->input('per_page', 10); |
||||
|
|
||||
|
$total = $query->count(); |
||||
|
$items = $query->latest()->forPage($page, $perPage)->select()->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 illustration(Request $request): JsonResponse |
||||
|
{ |
||||
|
try { |
||||
|
$data = []; |
||||
|
$query = $this->service->searchQuery($request->all()); |
||||
|
$list = $query->select()->get()->toArray(); |
||||
|
$tempData = []; |
||||
|
foreach ($list as $item) { |
||||
|
$date_type = $item['date_type']; |
||||
|
$format = 'H:i'; |
||||
|
if ($date_type == 2) { |
||||
|
$format = 'm/d'; |
||||
|
} |
||||
|
$key = date($format, strtotime($item['end_time'])); |
||||
|
$tempData[$key][] = $item['rate']; |
||||
|
} |
||||
|
foreach ($tempData as $date => $value) { |
||||
|
$count = count($value); |
||||
|
$sum = 0; |
||||
|
foreach ($value as $val) { |
||||
|
$sum += $val; |
||||
|
} |
||||
|
$rate = 0; |
||||
|
if ($sum > 0) { |
||||
|
$rate = round($sum / $count, 2); |
||||
|
} |
||||
|
$data[] = [ |
||||
|
'time' => $date, |
||||
|
'rate' => $rate |
||||
|
]; |
||||
|
} |
||||
|
return $this->responseService->success($data); |
||||
|
} catch (Exception $e) { |
||||
|
$m_prefix = __('exception.exception_handler.resource'); |
||||
|
return $this->responseService->systemError( |
||||
|
$m_prefix . ':' . $e->getMessage() |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public function search(): JsonResponse |
||||
|
{ |
||||
|
try { |
||||
|
$data = [ |
||||
|
'floor_list' => AdminFloor::getData(), |
||||
|
'space_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() |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param Request $request |
||||
|
* @return BinaryFileResponse |
||||
|
*/ |
||||
|
public function export(Request $request): BinaryFileResponse |
||||
|
{ |
||||
|
return Excel::download( |
||||
|
new UtilizationRateExport($request->all()), |
||||
|
set_space_underline(__('exports.access_record.list')) |
||||
|
. get_datetime('date_') |
||||
|
. '.xlsx' |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Models; |
||||
|
|
||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
|
use Illuminate\Database\Eloquent\Model; |
||||
|
|
||||
|
class ParkingUtilizationRate extends Model |
||||
|
{ |
||||
|
use HasFactory; |
||||
|
|
||||
|
protected $table = 'parking_utilization_rate'; |
||||
|
|
||||
|
public $timestamps = false; |
||||
|
|
||||
|
protected $fillable |
||||
|
= [ |
||||
|
'space_id', |
||||
|
'start_time', |
||||
|
'end_time', |
||||
|
'date_type', |
||||
|
'rate' |
||||
|
]; |
||||
|
protected $hidden |
||||
|
= [ |
||||
|
'created_at', |
||||
|
'updated_at' |
||||
|
]; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,91 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Services; |
||||
|
|
||||
|
use App\Models\AdminFloor; |
||||
|
use App\Models\ParkingSpace; |
||||
|
use App\Models\ParkingSpaceAttributes; |
||||
|
use App\Models\ParkingSpaceType; |
||||
|
use App\Models\ParkingUtilizationRate; |
||||
|
use Illuminate\Database\Eloquent\Builder; |
||||
|
|
||||
|
class UtilizationRateService extends BaseService |
||||
|
{ |
||||
|
protected string $menuTitle = 'utilization_rate'; |
||||
|
|
||||
|
public function getItem($item) |
||||
|
{ |
||||
|
$item['floor'] = ''; |
||||
|
$item['number'] = ''; |
||||
|
$item['space_type'] = ''; |
||||
|
$item['space_attr'] = ''; |
||||
|
$parkingSpace = ParkingSpace::query()->find( |
||||
|
$item['space_id'] |
||||
|
); |
||||
|
if ($parkingSpace) { |
||||
|
$item['floor'] = AdminFloor::getName( |
||||
|
$parkingSpace['floor_id'] |
||||
|
); |
||||
|
$item['number'] = $parkingSpace['number']; |
||||
|
$item['space_type'] = ParkingSpaceType::getName( |
||||
|
$parkingSpace['space_type_id'] |
||||
|
); |
||||
|
$item['space_attr'] = ParkingSpaceAttributes::getAttr( |
||||
|
$parkingSpace['space_attr_id'] |
||||
|
); |
||||
|
} |
||||
|
$item['rate'] = rtrim($item['rate'], ' ') . '%'; |
||||
|
$format = $item['date_type'] == 1 ? 'Y/m/d H:i' : 'Y/m/d'; |
||||
|
$item['start_time'] = date($format, strtotime($item['start_time'])); |
||||
|
$item['end_time'] = date($format, strtotime($item['end_time'])); |
||||
|
unset($item['space_id'], $item['date_type']); |
||||
|
return $item; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param $parents |
||||
|
* @return Builder |
||||
|
*/ |
||||
|
public function searchQuery($parents): Builder |
||||
|
{ |
||||
|
$query = ParkingUtilizationRate::query(); |
||||
|
$start_time = $parents['start_time'] ?? |
||||
|
get_datetime('date') . ' 00:00:00'; |
||||
|
$ent_time = $parents['end_time'] ?? |
||||
|
get_datetime('date') . ' 23:59:59'; |
||||
|
|
||||
|
$start_date = get_datetime('date', strtotime($start_time)); |
||||
|
$end_date = get_datetime('date', strtotime($ent_time)); |
||||
|
$date_type = $start_date == $end_date ? 1 : 2; |
||||
|
|
||||
|
$query->where('date_type', $date_type); |
||||
|
$query->where('start_time', '>=', $start_time); |
||||
|
$query->where('end_time', '<', $ent_time); |
||||
|
|
||||
|
$spaceIdsWhere = []; |
||||
|
if (isset($parents['floor_id']) && $parents['floor_id']) { |
||||
|
$spaceIdsWhere['floor_id'] = $parents['floor_id']; |
||||
|
} |
||||
|
if (isset($parents['number']) && $parents['number']) { |
||||
|
$spaceIdsWhere['number'] = $parents['number']; |
||||
|
} |
||||
|
|
||||
|
if (isset($parents['parking_space_type']) |
||||
|
&& $parents['parking_space_type'] |
||||
|
) { |
||||
|
$spaceIdsWhere['space_type_id'] = $parents['parking_space_type']; |
||||
|
} |
||||
|
|
||||
|
if ($spaceIdsWhere) { |
||||
|
$spaceIds = ParkingSpace::query()->where($spaceIdsWhere)->pluck( |
||||
|
'id' |
||||
|
); |
||||
|
if ($spaceIds) { |
||||
|
$query->whereIn('space_id', $spaceIds); |
||||
|
} else { |
||||
|
$query->where('id', 0); |
||||
|
} |
||||
|
} |
||||
|
return $query; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
<?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_utilization_rate', function (Blueprint $table) { |
||||
|
$table->id(); |
||||
|
$table->integer('space_id')->comment('车位id'); |
||||
|
$table->dateTime('start_time')->comment('开始时间'); |
||||
|
$table->dateTime('end_time')->comment('结束时间'); |
||||
|
$table->tinyInteger('date_type')->default(1)->comment('类型 1小时 2天'); |
||||
|
$table->float('rate', 5)->comment('使用率'); |
||||
|
$table->timestamp('created_at'); |
||||
|
$table->index('space_id', 'space_id'); |
||||
|
$table->comment('车位使用率'); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Reverse the migrations. |
||||
|
*/ |
||||
|
public function down(): void |
||||
|
{ |
||||
|
Schema::dropIfExists('parking_utilization_rate'); |
||||
|
} |
||||
|
}; |
||||
Loading…
Reference in new issue