diff --git a/niucloud/app/job/transfer/schedule/CourseScheduleJob.php b/niucloud/app/job/transfer/schedule/CourseScheduleJob.php index a280a184..8a83e6ee 100755 --- a/niucloud/app/job/transfer/schedule/CourseScheduleJob.php +++ b/niucloud/app/job/transfer/schedule/CourseScheduleJob.php @@ -9,21 +9,21 @@ use think\facade\Log; class CourseScheduleJob extends BaseJob { /** - * 执行任务,将最新的自动排课复制到未来7天 + * 执行任务,将自动排课模板复制到未来7天 * @param mixed ...$data 任务参数(BaseJob要求) * @return array 处理结果 */ public function doJob(...$data) { Log::write('开始执行自动排课任务'); - + try { - // 直接执行排课任务,生成未来7天的可预约时间段 + // 执行排课任务,生成未来7天的可预约时间段 $result = $this->copyCoursesToFutureDays(7); - + Log::write('自动排课任务执行完成,插入:' . $result['inserted'] . ',跳过:' . $result['skipped']); return true; - + } catch (\Exception $e) { Log::write('自动排课任务执行失败:' . $e->getMessage()); throw $e; @@ -31,45 +31,43 @@ class CourseScheduleJob extends BaseJob } /** - * 将今天的自动排课复制到未来指定天数,生成可预约的课程时间段 + * 将自动排课模板复制到未来指定天数,生成可预约的课程时间段 * @param int $days 未来天数,默认7天 * @return array 处理结果 */ public function copyCoursesToFutureDays($days = 7) { - $today = date('Y-m-d'); - - // 获取今天所有auto_schedule=1的课程 + // 获取所有auto_schedule=1的课程作为模板(不限制日期) $autoSchedules = CourseSchedule::where('auto_schedule', 1) - ->where('course_date', $today) ->select(); - - Log::write('找到' . count($autoSchedules) . '个今日自动排课模板'); - + + Log::write('找到' . count($autoSchedules) . '个自动排课模板'); + $results = [ 'status' => 'success', - 'base_date' => $today, 'total' => count($autoSchedules), 'inserted' => 0, 'skipped' => 0, + 'user_modified' => 0, 'details' => [] ]; - + if (count($autoSchedules) == 0) { - Log::write('今日没有找到自动排课,跳过执行'); + Log::write('没有找到自动排课模板,跳过执行'); return $results; } - - // 遍历每个自动排课计划,为未来指定天数生成可预约时间段 + + // 遍历每个自动排课模板,为未来指定天数生成可预约时间段 foreach ($autoSchedules as $schedule) { $courseResults = $this->copyCourseToFutureDays($schedule, $days); $results['inserted'] += $courseResults['inserted']; $results['skipped'] += $courseResults['skipped']; + $results['user_modified'] += $courseResults['user_modified']; $results['details'][] = $courseResults; } - - Log::write('自动排课完成,共插入' . $results['inserted'] . '个课程,跳过' . $results['skipped'] . '个已存在课程'); - + + Log::write('自动排课完成,共插入' . $results['inserted'] . '个课程,跳过' . $results['skipped'] . '个已存在课程,用户干预' . $results['user_modified'] . '个课程'); + return $results; } @@ -88,18 +86,19 @@ class CourseScheduleJob extends BaseJob 'time_slot' => $schedule->time_slot, 'inserted' => 0, 'skipped' => 0, + 'user_modified' => 0, 'dates' => [] ]; - + // 从明天开始,复制到未来指定天数 for ($i = 1; $i <= $days; $i++) { // 计算目标日期 $targetDate = date('Y-m-d', strtotime("+{$i} days")); - + // 检查该日期是否有相同的课程安排 - $exists = $this->checkCourseExists($schedule, $targetDate); - - if (!$exists) { + $checkResult = $this->checkCourseExists($schedule, $targetDate); + + if (!$checkResult['exists']) { // 如果不存在,则插入新的课程安排 $newSchedule = $this->createNewSchedule($schedule, $targetDate); $result['inserted']++; @@ -108,15 +107,35 @@ class CourseScheduleJob extends BaseJob 'status' => 'inserted', '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 { + // 课程已存在(自动排课生成的) $result['skipped']++; $result['dates'][] = [ '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; } @@ -128,66 +147,88 @@ class CourseScheduleJob extends BaseJob */ public function processAutoSchedule($month, $year) { - // 获取所有auto_schedule=1的课程 - $autoSchedules = CourseSchedule::where('auto_schedule', 1)->where('course_date', date('Y-m-d'))->select(); + // 获取所有auto_schedule=1的课程作为模板 + $autoSchedules = CourseSchedule::where('auto_schedule', 1)->select(); $results = []; foreach ($autoSchedules as $schedule) { - // 构造课程日期(基于给定的月份和年份) - $courseDate = $this->getCourseDate($schedule->course_date, $month, $year); + // 获取该月份的所有日期 + $daysInMonth = date('t', mktime(0, 0, 0, $month, 1, $year)); - // 检查该月份是否有相同的课程安排 - $exists = $this->checkCourseExists($schedule, $courseDate); + for ($day = 1; $day <= $daysInMonth; $day++) { + $courseDate = sprintf('%04d-%02d-%02d', $year, $month, $day); - if (!$exists) { - // 如果不存在,则插入新的课程安排 - $newSchedule = $this->createNewSchedule($schedule, $courseDate); - $results[] = [ - 'status' => 'inserted', - 'schedule' => $newSchedule - ]; - } else { - $results[] = [ - 'status' => 'exists', - 'schedule' => $schedule - ]; + // 检查该日期是否有相同的课程安排 + $checkResult = $this->checkCourseExists($schedule, $courseDate); + + if (!$checkResult['exists']) { + // 如果不存在,则插入新的课程安排 + $newSchedule = $this->createNewSchedule($schedule, $courseDate); + $results[] = [ + 'status' => 'inserted', + 'schedule' => $newSchedule, + 'date' => $courseDate + ]; + } 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; } + /** - * 根据原始课程日期和目标月份、年份计算新的课程日期 - * @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 string $courseDate 课程日期 - * @return bool 是否存在 + * @return array 检查结果 ['exists' => bool, 'auto_schedule' => bool, 'skip_reason' => string] */ 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) ->where('venue_id', $schedule->venue_id) ->where('course_date', $courseDate) ->where('time_slot', $schedule->time_slot) ->where('course_id', $schedule->course_id); - })->count(); + })->find(); - return $exists > 0; + 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' => true, + 'auto_schedule' => true, + 'skip_reason' => 'auto_exists', + 'existing_id' => $existing->id + ]; } /**