|
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
|
|
namespace App\Models;
|
|
|
|
|
|
|
|
|
|
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
|
|
|
|
|
|
|
|
|
|
class VisitTime extends SoftDeletesModel
|
|
|
|
|
|
{
|
|
|
|
|
|
use HasFactory;
|
|
|
|
|
|
|
|
|
|
|
|
protected $table = 'visit_times';
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 关联访问申请
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function visits()
|
|
|
|
|
|
{
|
|
|
|
|
|
return $this->hasMany(Visit::class, 'visit_time_id');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取时段文本
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function getTimeTextAttribute()
|
|
|
|
|
|
{
|
|
|
|
|
|
return $this->start_time . ' - ' . $this->end_time;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取时段时长(分钟)
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function getDuration()
|
|
|
|
|
|
{
|
|
|
|
|
|
$start = \Carbon\Carbon::createFromFormat('H:i', $this->start_time);
|
|
|
|
|
|
$end = \Carbon\Carbon::createFromFormat('H:i', $this->end_time);
|
|
|
|
|
|
|
|
|
|
|
|
return $end->diffInMinutes($start);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 检查时间是否冲突
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function hasTimeConflict($startTime, $endTime, $excludeId = null)
|
|
|
|
|
|
{
|
|
|
|
|
|
$query = self::where(function ($q) use ($startTime, $endTime) {
|
|
|
|
|
|
$q->where(function ($q1) use ($startTime, $endTime) {
|
|
|
|
|
|
// 新时段开始时间在现有时段内
|
|
|
|
|
|
$q1->where('start_time', '<=', $startTime)
|
|
|
|
|
|
->where('end_time', '>', $startTime);
|
|
|
|
|
|
})->orWhere(function ($q2) use ($startTime, $endTime) {
|
|
|
|
|
|
// 新时段结束时间在现有时段内
|
|
|
|
|
|
$q2->where('start_time', '<', $endTime)
|
|
|
|
|
|
->where('end_time', '>=', $endTime);
|
|
|
|
|
|
})->orWhere(function ($q3) use ($startTime, $endTime) {
|
|
|
|
|
|
// 新时段完全包含现有时段
|
|
|
|
|
|
$q3->where('start_time', '>=', $startTime)
|
|
|
|
|
|
->where('end_time', '<=', $endTime);
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if ($excludeId) {
|
|
|
|
|
|
$query->where('id', '!=', $excludeId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return $query->exists();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 检查指定时间是否在时段内
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function isTimeInRange($time)
|
|
|
|
|
|
{
|
|
|
|
|
|
$checkTime = \Carbon\Carbon::createFromFormat('H:i', $time);
|
|
|
|
|
|
$startTime = \Carbon\Carbon::createFromFormat('H:i', $this->start_time);
|
|
|
|
|
|
$endTime = \Carbon\Carbon::createFromFormat('H:i', $this->end_time);
|
|
|
|
|
|
|
|
|
|
|
|
return $checkTime->between($startTime, $endTime);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取可用的时段列表
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function getAvailableTimes($date = null)
|
|
|
|
|
|
{
|
|
|
|
|
|
$query = self::orderBy('start_time');
|
|
|
|
|
|
|
|
|
|
|
|
if ($date) {
|
|
|
|
|
|
// 可以根据日期过滤,比如某些时段在特定日期不可用
|
|
|
|
|
|
// 这里可以根据实际需求扩展
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return $query->get();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 检查时段是否可用
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function isAvailable($date = null)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 基本检查
|
|
|
|
|
|
if (empty($this->start_time) || empty($this->end_time)) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查时间格式
|
|
|
|
|
|
try {
|
|
|
|
|
|
$start = \Carbon\Carbon::createFromFormat('H:i', $this->start_time);
|
|
|
|
|
|
$end = \Carbon\Carbon::createFromFormat('H:i', $this->end_time);
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查开始时间不能晚于结束时间
|
|
|
|
|
|
if ($start->gte($end)) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 可以根据日期进行更复杂的检查
|
|
|
|
|
|
if ($date) {
|
|
|
|
|
|
// 例如:检查是否是工作日、节假日等
|
|
|
|
|
|
// 这里可以根据实际需求扩展
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取时段统计信息
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function getStatistics()
|
|
|
|
|
|
{
|
|
|
|
|
|
$visits = $this->visits();
|
|
|
|
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
|
'time_text' => $this->getTimeTextAttribute(),
|
|
|
|
|
|
'duration' => $this->getDuration(),
|
|
|
|
|
|
'total_visits' => $visits->count(),
|
|
|
|
|
|
'today_visits' => $visits->whereDate('date', today())->count(),
|
|
|
|
|
|
'this_week_visits' => $visits->whereBetween('date', [
|
|
|
|
|
|
now()->startOfWeek(),
|
|
|
|
|
|
now()->endOfWeek()
|
|
|
|
|
|
])->count(),
|
|
|
|
|
|
'this_month_visits' => $visits->whereMonth('date', now()->month)->count(),
|
|
|
|
|
|
];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取时段使用率
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function getUsageRate($date = null)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!$date) {
|
|
|
|
|
|
$date = today();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$visits = $this->visits()->whereDate('date', $date)->count();
|
|
|
|
|
|
$maxCapacity = 10; // 假设每个时段最大容量为10人,可以根据实际需求调整
|
|
|
|
|
|
|
|
|
|
|
|
return min(100, ($visits / $maxCapacity) * 100);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 验证时段数据
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function validate()
|
|
|
|
|
|
{
|
|
|
|
|
|
$errors = [];
|
|
|
|
|
|
|
|
|
|
|
|
if (empty($this->start_time)) {
|
|
|
|
|
|
$errors[] = '开始时间不能为空';
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (empty($this->end_time)) {
|
|
|
|
|
|
$errors[] = '结束时间不能为空';
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!empty($this->start_time) && !empty($this->end_time)) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
$start = \Carbon\Carbon::createFromFormat('H:i', $this->start_time);
|
|
|
|
|
|
$end = \Carbon\Carbon::createFromFormat('H:i', $this->end_time);
|
|
|
|
|
|
|
|
|
|
|
|
if ($start->gte($end)) {
|
|
|
|
|
|
$errors[] = '开始时间不能晚于或等于结束时间';
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
|
$errors[] = '时间格式不正确';
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return $errors;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|