|
|
@ -9,7 +9,7 @@ use think\facade\Log; |
|
|
class CourseScheduleJob extends BaseJob |
|
|
class CourseScheduleJob extends BaseJob |
|
|
{ |
|
|
{ |
|
|
/** |
|
|
/** |
|
|
* 执行任务,将最新的自动排课复制到未来7天 |
|
|
* 执行任务,将自动排课模板复制到未来7天 |
|
|
* @param mixed ...$data 任务参数(BaseJob要求) |
|
|
* @param mixed ...$data 任务参数(BaseJob要求) |
|
|
* @return array 处理结果 |
|
|
* @return array 处理结果 |
|
|
*/ |
|
|
*/ |
|
|
@ -18,7 +18,7 @@ class CourseScheduleJob extends BaseJob |
|
|
Log::write('开始执行自动排课任务'); |
|
|
Log::write('开始执行自动排课任务'); |
|
|
|
|
|
|
|
|
try { |
|
|
try { |
|
|
// 直接执行排课任务,生成未来7天的可预约时间段 |
|
|
// 执行排课任务,生成未来7天的可预约时间段 |
|
|
$result = $this->copyCoursesToFutureDays(7); |
|
|
$result = $this->copyCoursesToFutureDays(7); |
|
|
|
|
|
|
|
|
Log::write('自动排课任务执行完成,插入:' . $result['inserted'] . ',跳过:' . $result['skipped']); |
|
|
Log::write('自动排课任务执行完成,插入:' . $result['inserted'] . ',跳过:' . $result['skipped']); |
|
|
@ -31,44 +31,42 @@ class CourseScheduleJob extends BaseJob |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* 将今天的自动排课复制到未来指定天数,生成可预约的课程时间段 |
|
|
* 将自动排课模板复制到未来指定天数,生成可预约的课程时间段 |
|
|
* @param int $days 未来天数,默认7天 |
|
|
* @param int $days 未来天数,默认7天 |
|
|
* @return array 处理结果 |
|
|
* @return array 处理结果 |
|
|
*/ |
|
|
*/ |
|
|
public function copyCoursesToFutureDays($days = 7) |
|
|
public function copyCoursesToFutureDays($days = 7) |
|
|
{ |
|
|
{ |
|
|
$today = date('Y-m-d'); |
|
|
// 获取所有auto_schedule=1的课程作为模板(不限制日期) |
|
|
|
|
|
|
|
|
// 获取今天所有auto_schedule=1的课程 |
|
|
|
|
|
$autoSchedules = CourseSchedule::where('auto_schedule', 1) |
|
|
$autoSchedules = CourseSchedule::where('auto_schedule', 1) |
|
|
->where('course_date', $today) |
|
|
|
|
|
->select(); |
|
|
->select(); |
|
|
|
|
|
|
|
|
Log::write('找到' . count($autoSchedules) . '个今日自动排课模板'); |
|
|
Log::write('找到' . count($autoSchedules) . '个自动排课模板'); |
|
|
|
|
|
|
|
|
$results = [ |
|
|
$results = [ |
|
|
'status' => 'success', |
|
|
'status' => 'success', |
|
|
'base_date' => $today, |
|
|
|
|
|
'total' => count($autoSchedules), |
|
|
'total' => count($autoSchedules), |
|
|
'inserted' => 0, |
|
|
'inserted' => 0, |
|
|
'skipped' => 0, |
|
|
'skipped' => 0, |
|
|
|
|
|
'user_modified' => 0, |
|
|
'details' => [] |
|
|
'details' => [] |
|
|
]; |
|
|
]; |
|
|
|
|
|
|
|
|
if (count($autoSchedules) == 0) { |
|
|
if (count($autoSchedules) == 0) { |
|
|
Log::write('今日没有找到自动排课,跳过执行'); |
|
|
Log::write('没有找到自动排课模板,跳过执行'); |
|
|
return $results; |
|
|
return $results; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 遍历每个自动排课计划,为未来指定天数生成可预约时间段 |
|
|
// 遍历每个自动排课模板,为未来指定天数生成可预约时间段 |
|
|
foreach ($autoSchedules as $schedule) { |
|
|
foreach ($autoSchedules as $schedule) { |
|
|
$courseResults = $this->copyCourseToFutureDays($schedule, $days); |
|
|
$courseResults = $this->copyCourseToFutureDays($schedule, $days); |
|
|
$results['inserted'] += $courseResults['inserted']; |
|
|
$results['inserted'] += $courseResults['inserted']; |
|
|
$results['skipped'] += $courseResults['skipped']; |
|
|
$results['skipped'] += $courseResults['skipped']; |
|
|
|
|
|
$results['user_modified'] += $courseResults['user_modified']; |
|
|
$results['details'][] = $courseResults; |
|
|
$results['details'][] = $courseResults; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Log::write('自动排课完成,共插入' . $results['inserted'] . '个课程,跳过' . $results['skipped'] . '个已存在课程'); |
|
|
Log::write('自动排课完成,共插入' . $results['inserted'] . '个课程,跳过' . $results['skipped'] . '个已存在课程,用户干预' . $results['user_modified'] . '个课程'); |
|
|
|
|
|
|
|
|
return $results; |
|
|
return $results; |
|
|
} |
|
|
} |
|
|
@ -88,6 +86,7 @@ class CourseScheduleJob extends BaseJob |
|
|
'time_slot' => $schedule->time_slot, |
|
|
'time_slot' => $schedule->time_slot, |
|
|
'inserted' => 0, |
|
|
'inserted' => 0, |
|
|
'skipped' => 0, |
|
|
'skipped' => 0, |
|
|
|
|
|
'user_modified' => 0, |
|
|
'dates' => [] |
|
|
'dates' => [] |
|
|
]; |
|
|
]; |
|
|
|
|
|
|
|
|
@ -97,9 +96,9 @@ class CourseScheduleJob extends BaseJob |
|
|
$targetDate = date('Y-m-d', strtotime("+{$i} days")); |
|
|
$targetDate = date('Y-m-d', strtotime("+{$i} days")); |
|
|
|
|
|
|
|
|
// 检查该日期是否有相同的课程安排 |
|
|
// 检查该日期是否有相同的课程安排 |
|
|
$exists = $this->checkCourseExists($schedule, $targetDate); |
|
|
$checkResult = $this->checkCourseExists($schedule, $targetDate); |
|
|
|
|
|
|
|
|
if (!$exists) { |
|
|
if (!$checkResult['exists']) { |
|
|
// 如果不存在,则插入新的课程安排 |
|
|
// 如果不存在,则插入新的课程安排 |
|
|
$newSchedule = $this->createNewSchedule($schedule, $targetDate); |
|
|
$newSchedule = $this->createNewSchedule($schedule, $targetDate); |
|
|
$result['inserted']++; |
|
|
$result['inserted']++; |
|
|
@ -108,15 +107,35 @@ class CourseScheduleJob extends BaseJob |
|
|
'status' => 'inserted', |
|
|
'status' => 'inserted', |
|
|
'id' => $newSchedule->id |
|
|
'id' => $newSchedule->id |
|
|
]; |
|
|
]; |
|
|
|
|
|
} elseif ($checkResult['skip_reason'] === 'user_modified') { |
|
|
|
|
|
// 用户已手动修改此课程,跳过并记录 |
|
|
|
|
|
$result['user_modified']++; |
|
|
|
|
|
$result['dates'][] = [ |
|
|
|
|
|
'date' => $targetDate, |
|
|
|
|
|
'status' => 'user_modified', |
|
|
|
|
|
'reason' => '用户已取消自动排课', |
|
|
|
|
|
'existing_id' => $checkResult['existing_id'] |
|
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
|
|
// 记录用户干预的日志 |
|
|
|
|
|
Log::write("用户干预检测:课程ID {$schedule->course_id} 在 {$targetDate} 已被用户手动修改,跳过自动排课"); |
|
|
} else { |
|
|
} else { |
|
|
|
|
|
// 课程已存在(自动排课生成的) |
|
|
$result['skipped']++; |
|
|
$result['skipped']++; |
|
|
$result['dates'][] = [ |
|
|
$result['dates'][] = [ |
|
|
'date' => $targetDate, |
|
|
'date' => $targetDate, |
|
|
'status' => 'skipped' |
|
|
'status' => 'auto_exists', |
|
|
|
|
|
'reason' => '自动排课已存在', |
|
|
|
|
|
'existing_id' => $checkResult['existing_id'] |
|
|
]; |
|
|
]; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 记录用户干预统计 |
|
|
|
|
|
if ($result['user_modified'] > 0) { |
|
|
|
|
|
Log::write("课程ID {$schedule->course_id}:用户干预了 {$result['user_modified']} 个时间段,尊重用户选择跳过自动排课"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
return $result; |
|
|
return $result; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -128,66 +147,88 @@ class CourseScheduleJob extends BaseJob |
|
|
*/ |
|
|
*/ |
|
|
public function processAutoSchedule($month, $year) |
|
|
public function processAutoSchedule($month, $year) |
|
|
{ |
|
|
{ |
|
|
// 获取所有auto_schedule=1的课程 |
|
|
// 获取所有auto_schedule=1的课程作为模板 |
|
|
$autoSchedules = CourseSchedule::where('auto_schedule', 1)->where('course_date', date('Y-m-d'))->select(); |
|
|
$autoSchedules = CourseSchedule::where('auto_schedule', 1)->select(); |
|
|
|
|
|
|
|
|
$results = []; |
|
|
$results = []; |
|
|
foreach ($autoSchedules as $schedule) { |
|
|
foreach ($autoSchedules as $schedule) { |
|
|
// 构造课程日期(基于给定的月份和年份) |
|
|
// 获取该月份的所有日期 |
|
|
$courseDate = $this->getCourseDate($schedule->course_date, $month, $year); |
|
|
$daysInMonth = date('t', mktime(0, 0, 0, $month, 1, $year)); |
|
|
|
|
|
|
|
|
// 检查该月份是否有相同的课程安排 |
|
|
for ($day = 1; $day <= $daysInMonth; $day++) { |
|
|
$exists = $this->checkCourseExists($schedule, $courseDate); |
|
|
$courseDate = sprintf('%04d-%02d-%02d', $year, $month, $day); |
|
|
|
|
|
|
|
|
if (!$exists) { |
|
|
// 检查该日期是否有相同的课程安排 |
|
|
// 如果不存在,则插入新的课程安排 |
|
|
$checkResult = $this->checkCourseExists($schedule, $courseDate); |
|
|
$newSchedule = $this->createNewSchedule($schedule, $courseDate); |
|
|
|
|
|
$results[] = [ |
|
|
if (!$checkResult['exists']) { |
|
|
'status' => 'inserted', |
|
|
// 如果不存在,则插入新的课程安排 |
|
|
'schedule' => $newSchedule |
|
|
$newSchedule = $this->createNewSchedule($schedule, $courseDate); |
|
|
]; |
|
|
$results[] = [ |
|
|
} else { |
|
|
'status' => 'inserted', |
|
|
$results[] = [ |
|
|
'schedule' => $newSchedule, |
|
|
'status' => 'exists', |
|
|
'date' => $courseDate |
|
|
'schedule' => $schedule |
|
|
]; |
|
|
]; |
|
|
} elseif ($checkResult['skip_reason'] === 'user_modified') { |
|
|
|
|
|
// 用户已手动修改此课程 |
|
|
|
|
|
$results[] = [ |
|
|
|
|
|
'status' => 'user_modified', |
|
|
|
|
|
'schedule' => $schedule, |
|
|
|
|
|
'date' => $courseDate, |
|
|
|
|
|
'reason' => '用户已取消自动排课' |
|
|
|
|
|
]; |
|
|
|
|
|
} else { |
|
|
|
|
|
// 课程已存在(自动排课生成的) |
|
|
|
|
|
$results[] = [ |
|
|
|
|
|
'status' => 'auto_exists', |
|
|
|
|
|
'schedule' => $schedule, |
|
|
|
|
|
'date' => $courseDate |
|
|
|
|
|
]; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return $results; |
|
|
return $results; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 根据原始课程日期和目标月份、年份计算新的课程日期 |
|
|
|
|
|
* @param string $originalDate 原始课程日期(格式:Y-m-d) |
|
|
|
|
|
* @param int $targetMonth 目标月份 |
|
|
|
|
|
* @param int $targetYear 目标年份 |
|
|
|
|
|
* @return string 新的课程日期 |
|
|
|
|
|
*/ |
|
|
|
|
|
protected function getCourseDate($originalDate, $targetMonth, $targetYear) |
|
|
|
|
|
{ |
|
|
|
|
|
$date = \DateTime::createFromFormat('Y-m-d', $originalDate); |
|
|
|
|
|
$date->setDate($targetYear, $targetMonth, $date->format('d')); |
|
|
|
|
|
return $date->format('Y-m-d'); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* 检查指定日期是否有相同的课程安排 |
|
|
* 检查指定日期是否有相同的课程安排,或者用户已取消自动排课 |
|
|
* @param CourseSchedule $schedule 原始课程安排 |
|
|
* @param CourseSchedule $schedule 原始课程安排 |
|
|
* @param string $courseDate 课程日期 |
|
|
* @param string $courseDate 课程日期 |
|
|
* @return bool 是否存在 |
|
|
* @return array 检查结果 ['exists' => bool, 'auto_schedule' => bool, 'skip_reason' => string] |
|
|
*/ |
|
|
*/ |
|
|
protected function checkCourseExists(CourseSchedule $schedule, $courseDate) |
|
|
protected function checkCourseExists(CourseSchedule $schedule, $courseDate) |
|
|
{ |
|
|
{ |
|
|
$exists = CourseSchedule::where(function ($query) use ($schedule, $courseDate) { |
|
|
$existing = CourseSchedule::where(function ($query) use ($schedule, $courseDate) { |
|
|
$query->where('campus_id', $schedule->campus_id) |
|
|
$query->where('campus_id', $schedule->campus_id) |
|
|
->where('venue_id', $schedule->venue_id) |
|
|
->where('venue_id', $schedule->venue_id) |
|
|
->where('course_date', $courseDate) |
|
|
->where('course_date', $courseDate) |
|
|
->where('time_slot', $schedule->time_slot) |
|
|
->where('time_slot', $schedule->time_slot) |
|
|
->where('course_id', $schedule->course_id); |
|
|
->where('course_id', $schedule->course_id); |
|
|
})->count(); |
|
|
})->find(); |
|
|
|
|
|
|
|
|
|
|
|
if (!$existing) { |
|
|
|
|
|
return ['exists' => false, 'auto_schedule' => false, 'skip_reason' => '']; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 如果课程存在但auto_schedule=0,说明用户已手动修改,跳过自动排课 |
|
|
|
|
|
if ($existing->auto_schedule == 0) { |
|
|
|
|
|
return [ |
|
|
|
|
|
'exists' => true, |
|
|
|
|
|
'auto_schedule' => false, |
|
|
|
|
|
'skip_reason' => 'user_modified', |
|
|
|
|
|
'existing_id' => $existing->id |
|
|
|
|
|
]; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
return $exists > 0; |
|
|
// 课程存在且仍是自动排课状态 |
|
|
|
|
|
return [ |
|
|
|
|
|
'exists' => true, |
|
|
|
|
|
'auto_schedule' => true, |
|
|
|
|
|
'skip_reason' => 'auto_exists', |
|
|
|
|
|
'existing_id' => $existing->id |
|
|
|
|
|
]; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
|