|
|
|
@ -51,42 +51,98 @@ class HandleCourseSchedule extends BaseJob |
|
|
|
try { |
|
|
|
Db::startTrans(); |
|
|
|
|
|
|
|
// 批量更新,避免循环操作 |
|
|
|
$yesterday = date('Y-m-d', strtotime('-1 day')); |
|
|
|
|
|
|
|
// 先查询需要更新的记录数量 |
|
|
|
$totalCount = CourseSchedule::where('course_date', '<', date('Y-m-d')) |
|
|
|
->where('status', '<>', 'completed') // 避免重复更新已完成的课程 |
|
|
|
->count(); |
|
|
|
|
|
|
|
if ($totalCount == 0) { |
|
|
|
Log::write('没有需要更新状态的过期课程'); |
|
|
|
Db::commit(); |
|
|
|
return [ |
|
|
|
'status' => 'success', |
|
|
|
'total_count' => 0, |
|
|
|
'updated_count' => 0, |
|
|
|
'message' => '没有需要更新状态的过期课程' |
|
|
|
]; |
|
|
|
} |
|
|
|
$currentDate = date('Y-m-d'); |
|
|
|
$currentTime = date('H:i:s'); |
|
|
|
$currentDateTime = date('Y-m-d H:i:s'); |
|
|
|
|
|
|
|
// 先处理time_slot,解析并更新start_time和end_time字段 |
|
|
|
$this->updateTimeFields(); |
|
|
|
|
|
|
|
$completedCount = 0; |
|
|
|
$upcomingCount = 0; |
|
|
|
$ongoingCount = 0; |
|
|
|
$pendingCount = 0; |
|
|
|
|
|
|
|
// 批量更新过期课程状态 |
|
|
|
$affectedRows = CourseSchedule::where('course_date', '<', date('Y-m-d')) |
|
|
|
->where('status', '<>', 'completed') // 避免重复更新 |
|
|
|
// 1. 更新已完成课程:course_date < 当天的课程 |
|
|
|
$completedRows = CourseSchedule::where('course_date', '<', $currentDate) |
|
|
|
->where('status', '<>', 'completed') |
|
|
|
->update([ |
|
|
|
'status' => 'completed', |
|
|
|
'updated_at' => time() |
|
|
|
]); |
|
|
|
$completedCount = $completedRows; |
|
|
|
|
|
|
|
// 2. 处理今天的课程,需要根据时间段判断状态 |
|
|
|
$todaySchedules = CourseSchedule::where('course_date', '=', $currentDate) |
|
|
|
->whereIn('status', ['pending', 'upcoming', 'ongoing']) |
|
|
|
->select(); |
|
|
|
|
|
|
|
foreach ($todaySchedules as $schedule) { |
|
|
|
$startTime = $schedule['start_time']; |
|
|
|
$endTime = $schedule['end_time']; |
|
|
|
|
|
|
|
if (empty($startTime) || empty($endTime)) { |
|
|
|
// 如果没有解析出时间,尝试从time_slot解析 |
|
|
|
$timeData = $this->parseTimeSlot($schedule['time_slot']); |
|
|
|
if ($timeData) { |
|
|
|
$startTime = $timeData['start_time']; |
|
|
|
$endTime = $timeData['end_time']; |
|
|
|
|
|
|
|
Log::write('批量更新了' . $affectedRows . '个过期课程状态为已完成,总共检查了' . $totalCount . '个课程'); |
|
|
|
// 更新数据库中的时间字段 |
|
|
|
CourseSchedule::where('id', $schedule['id'])->update([ |
|
|
|
'start_time' => $startTime, |
|
|
|
'end_time' => $endTime |
|
|
|
]); |
|
|
|
} else { |
|
|
|
continue; // 无法解析时间,跳过 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 判断课程状态 |
|
|
|
$newStatus = $this->determineStatus($currentTime, $startTime, $endTime); |
|
|
|
|
|
|
|
if ($newStatus !== $schedule['status']) { |
|
|
|
CourseSchedule::where('id', $schedule['id'])->update([ |
|
|
|
'status' => $newStatus, |
|
|
|
'updated_at' => time() |
|
|
|
]); |
|
|
|
|
|
|
|
switch ($newStatus) { |
|
|
|
case 'upcoming': |
|
|
|
$upcomingCount++; |
|
|
|
break; |
|
|
|
case 'ongoing': |
|
|
|
$ongoingCount++; |
|
|
|
break; |
|
|
|
case 'completed': |
|
|
|
$completedCount++; |
|
|
|
break; |
|
|
|
default: |
|
|
|
$pendingCount++; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 3. 重置未来日期的课程为pending状态 |
|
|
|
$futureRows = CourseSchedule::where('course_date', '>', $currentDate) |
|
|
|
->where('status', '<>', 'pending') |
|
|
|
->update([ |
|
|
|
'status' => 'pending', |
|
|
|
'updated_at' => time() |
|
|
|
]); |
|
|
|
$pendingCount += $futureRows; |
|
|
|
|
|
|
|
Log::write("课程状态更新完成 - 已完成: {$completedCount}个, 即将开始: {$upcomingCount}个, 进行中: {$ongoingCount}个, 待安排: {$pendingCount}个"); |
|
|
|
|
|
|
|
Db::commit(); |
|
|
|
|
|
|
|
return [ |
|
|
|
'status' => 'success', |
|
|
|
'total_count' => $totalCount, |
|
|
|
'updated_count' => $affectedRows, |
|
|
|
'message' => '成功更新' . $affectedRows . '个过期课程状态' |
|
|
|
'completed_count' => $completedCount, |
|
|
|
'upcoming_count' => $upcomingCount, |
|
|
|
'ongoing_count' => $ongoingCount, |
|
|
|
'pending_count' => $pendingCount |
|
|
|
]; |
|
|
|
|
|
|
|
} catch (\Exception $e) { |
|
|
|
@ -100,4 +156,87 @@ class HandleCourseSchedule extends BaseJob |
|
|
|
]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 更新课程安排表的start_time和end_time字段 |
|
|
|
*/ |
|
|
|
private function updateTimeFields() |
|
|
|
{ |
|
|
|
try { |
|
|
|
// 查询所有没有start_time或end_time的记录 |
|
|
|
$schedules = CourseSchedule::where(function($query) { |
|
|
|
$query->whereNull('start_time') |
|
|
|
->whereOr('end_time', null) |
|
|
|
->whereOr('start_time', '') |
|
|
|
->whereOr('end_time', ''); |
|
|
|
})->select(); |
|
|
|
|
|
|
|
foreach ($schedules as $schedule) { |
|
|
|
$timeData = $this->parseTimeSlot($schedule['time_slot']); |
|
|
|
if ($timeData) { |
|
|
|
CourseSchedule::where('id', $schedule['id'])->update([ |
|
|
|
'start_time' => $timeData['start_time'], |
|
|
|
'end_time' => $timeData['end_time'] |
|
|
|
]); |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (\Exception $e) { |
|
|
|
Log::write('更新时间字段失败:' . $e->getMessage()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 解析time_slot字符串,提取开始和结束时间 |
|
|
|
* @param string $timeSlot 格式如 "09:00-10:30" |
|
|
|
* @return array|null |
|
|
|
*/ |
|
|
|
private function parseTimeSlot($timeSlot) |
|
|
|
{ |
|
|
|
if (empty($timeSlot)) { |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
// 支持多种格式:09:00-10:30, 09:00~10:30, 9:00-10:30 |
|
|
|
if (preg_match('/(\d{1,2}:\d{2})\s*[-~~]\s*(\d{1,2}:\d{2})/', $timeSlot, $matches)) { |
|
|
|
return [ |
|
|
|
'start_time' => $matches[1], |
|
|
|
'end_time' => $matches[2] |
|
|
|
]; |
|
|
|
} |
|
|
|
|
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 根据当前时间和课程时间段判断课程状态 |
|
|
|
* @param string $currentTime 当前时间 H:i:s |
|
|
|
* @param string $startTime 开始时间 H:i:s |
|
|
|
* @param string $endTime 结束时间 H:i:s |
|
|
|
* @return string |
|
|
|
*/ |
|
|
|
private function determineStatus($currentTime, $startTime, $endTime) |
|
|
|
{ |
|
|
|
$currentTimestamp = strtotime($currentTime); |
|
|
|
$startTimestamp = strtotime($startTime); |
|
|
|
$endTimestamp = strtotime($endTime); |
|
|
|
|
|
|
|
// 如果当前时间在课程时间段内,状态为进行中 |
|
|
|
if ($currentTimestamp >= $startTimestamp && $currentTimestamp <= $endTimestamp) { |
|
|
|
return 'ongoing'; |
|
|
|
} |
|
|
|
|
|
|
|
// 如果课程已结束,状态为已完成 |
|
|
|
if ($currentTimestamp > $endTimestamp) { |
|
|
|
return 'completed'; |
|
|
|
} |
|
|
|
|
|
|
|
// 如果距离开始时间不足6小时,状态为即将开始 |
|
|
|
$timeDiff = $startTimestamp - $currentTimestamp; |
|
|
|
if ($timeDiff <= 6 * 3600 && $timeDiff > 0) { // 6小时 = 6 * 60 * 60 秒 |
|
|
|
return 'upcoming'; |
|
|
|
} |
|
|
|
|
|
|
|
// 其他情况为待安排 |
|
|
|
return 'pending'; |
|
|
|
} |
|
|
|
} |
|
|
|
|