checkCourseExpiryReminders(); // 检查课时余量提醒 $hoursResult = $this->checkRemainingHoursReminders(); // 检查预约课程提醒 $bookingResult = $this->checkUpcomingBookingReminders(); // 检查长期未上课提醒 $inactiveResult = $this->checkInactiveStudentReminders(); // 检查课程完成祝贺 $completionResult = $this->checkCourseCompletionCongratulations(); Log::write('学员课程提醒任务执行完成', [ 'expiry_reminders' => $expiryResult['count'], 'hours_reminders' => $hoursResult['count'], 'booking_reminders' => $bookingResult['count'], 'inactive_reminders' => $inactiveResult['count'], 'completion_congratulations' => $completionResult['count'] ]); return true; } catch (\Exception $e) { Log::write('学员课程提醒任务执行失败:' . $e->getMessage()); throw $e; } } /** * 检查课程有效期提醒 * @return array 处理结果 */ protected function checkCourseExpiryReminders() { $currentDate = date('Y-m-d'); // 查找7天内即将过期的课程 $expiringCourses = Course::where('valid_until', '>', $currentDate) ->where('valid_until', '<=', date('Y-m-d', strtotime('+7 days'))) ->where('status', 1) ->select(); $count = 0; foreach ($expiringCourses as $course) { // 检查是否已发送过提醒 $reminderSent = $this->checkReminderSent($course->member_id, 'course_expiry', $course->id); if (!$reminderSent) { $daysLeft = ceil((strtotime($course->valid_until) - strtotime($currentDate)) / 86400); $this->sendCourseExpiryReminder($course, $daysLeft); $this->recordReminderSent($course->member_id, 'course_expiry', $course->id); $count++; Log::write("发送课程过期提醒:学员ID {$course->member_id}, 课程ID {$course->id}, 剩余 {$daysLeft} 天"); } } return ['count' => $count]; } /** * 检查课时余量提醒 * @return array 处理结果 */ protected function checkRemainingHoursReminders() { // 查找剩余课时少于3节的有效课程 $lowHoursCourses = Course::where('remaining_hours', '>', 0) ->where('remaining_hours', '<=', 3) ->where('status', 1) ->select(); $count = 0; foreach ($lowHoursCourses as $course) { // 检查是否已发送过提醒 $reminderSent = $this->checkReminderSent($course->member_id, 'low_hours', $course->id); if (!$reminderSent) { $this->sendLowHoursReminder($course); $this->recordReminderSent($course->member_id, 'low_hours', $course->id); $count++; Log::write("发送课时不足提醒:学员ID {$course->member_id}, 课程ID {$course->id}, 剩余 {$course->remaining_hours} 课时"); } } return ['count' => $count]; } /** * 检查预约课程提醒 * @return array 处理结果 */ protected function checkUpcomingBookingReminders() { $tomorrow = date('Y-m-d', strtotime('+1 day')); // 查找明天的预约课程 $tomorrowBookings = CourseBooking::where('booking_date', $tomorrow) ->where('status', 1) ->select(); $count = 0; foreach ($tomorrowBookings as $booking) { // 检查是否已发送过提醒 $reminderSent = $this->checkReminderSent($booking->member_id, 'booking_reminder', $booking->id); if (!$reminderSent) { $this->sendBookingReminder($booking); $this->recordReminderSent($booking->member_id, 'booking_reminder', $booking->id); $count++; Log::write("发送预约提醒:学员ID {$booking->member_id}, 预约ID {$booking->id}"); } } return ['count' => $count]; } /** * 检查长期未上课提醒 * @return array 处理结果 */ protected function checkInactiveStudentReminders() { $thirtyDaysAgo = date('Y-m-d', strtotime('-30 days')); // 查找有有效课程但30天内没有上课的学员 $inactiveMembers = Member::whereHas('courses', function($query) { $query->where('status', 1)->where('remaining_hours', '>', 0); })->whereDoesntHave('courseBookings', function($query) use ($thirtyDaysAgo) { $query->where('booking_date', '>=', $thirtyDaysAgo) ->where('status', 'completed'); })->select(); $count = 0; foreach ($inactiveMembers as $member) { // 检查是否已发送过提醒 $reminderSent = $this->checkReminderSent($member->id, 'inactive_student', $member->id); if (!$reminderSent) { $this->sendInactiveStudentReminder($member); $this->recordReminderSent($member->id, 'inactive_student', $member->id); $count++; Log::write("发送长期未上课提醒:学员ID {$member->id}"); } } return ['count' => $count]; } /** * 检查课程完成祝贺 * @return array 处理结果 */ protected function checkCourseCompletionCongratulations() { // 查找今日刚完成的课程(剩余课时为0且今日有完成的预约) $today = date('Y-m-d'); $completedCourses = Course::where('remaining_hours', 0) ->where('status', 1) ->whereHas('courseBookings', function($query) use ($today) { $query->where('booking_date', $today) ->where('status', 'completed'); })->select(); $count = 0; foreach ($completedCourses as $course) { // 检查是否已发送过祝贺 $congratsSent = $this->checkReminderSent($course->member_id, 'course_completion', $course->id); if (!$congratsSent) { $this->sendCourseCompletionCongratulations($course); $this->recordReminderSent($course->member_id, 'course_completion', $course->id); // 更新课程状态为已完成 $course->status = 3; // 假设3为已完成状态 $course->completed_at = date('Y-m-d H:i:s'); $course->save(); $count++; Log::write("发送课程完成祝贺:学员ID {$course->member_id}, 课程ID {$course->id}"); } } return ['count' => $count]; } /** * 发送课程过期提醒 * @param Course $course 课程对象 * @param int $daysLeft 剩余天数 */ protected function sendCourseExpiryReminder($course, $daysLeft) { $member = Member::find($course->member_id); if (!$member) return; $message = "亲爱的{$member->nickname},您的课程《{$course->course_name}》将在{$daysLeft}天后过期,请尽快安排上课时间。"; $this->createNotification($member->id, 'course_expiry', '课程即将过期提醒', $message, [ 'course_id' => $course->id, 'days_left' => $daysLeft ]); } /** * 发送课时不足提醒 * @param Course $course 课程对象 */ protected function sendLowHoursReminder($course) { $member = Member::find($course->member_id); if (!$member) return; $message = "亲爱的{$member->nickname},您的课程《{$course->course_name}》还剩{$course->remaining_hours}节课,建议及时续费以确保学习连续性。"; $this->createNotification($member->id, 'low_hours', '课时不足提醒', $message, [ 'course_id' => $course->id, 'remaining_hours' => $course->remaining_hours ]); } /** * 发送预约课程提醒 * @param CourseBooking $booking 预约对象 */ protected function sendBookingReminder($booking) { $member = Member::find($booking->member_id); $course = Course::find($booking->course_id); if (!$member || !$course) return; $message = "亲爱的{$member->nickname},您预约的课程《{$course->course_name}》将在明天{$booking->time_slot}开始,请准时参加。"; $this->createNotification($member->id, 'booking_reminder', '课程预约提醒', $message, [ 'booking_id' => $booking->id, 'course_id' => $booking->course_id, 'booking_date' => $booking->booking_date, 'time_slot' => $booking->time_slot ]); } /** * 发送长期未上课提醒 * @param Member $member 学员对象 */ protected function sendInactiveStudentReminder($member) { $message = "亲爱的{$member->nickname},您已经很久没有上课了。坚持学习才能看到更好的效果,快来预约课程吧!"; $this->createNotification($member->id, 'inactive_student', '久未上课提醒', $message, [ 'member_id' => $member->id ]); } /** * 发送课程完成祝贺 * @param Course $course 课程对象 */ protected function sendCourseCompletionCongratulations($course) { $member = Member::find($course->member_id); if (!$member) return; $message = "恭喜{$member->nickname}!您已成功完成《{$course->course_name}》课程的全部学习,感谢您的坚持和努力!"; $this->createNotification($member->id, 'course_completion', '课程完成祝贺', $message, [ 'course_id' => $course->id, 'completion_date' => date('Y-m-d') ]); } /** * 检查是否已发送过提醒 * @param int $memberId 学员ID * @param string $type 提醒类型 * @param int $relatedId 相关ID * @return bool */ protected function checkReminderSent($memberId, $type, $relatedId) { $today = date('Y-m-d'); $exists = Notification::where('member_id', $memberId) ->where('type', $type) ->where('related_id', $relatedId) ->where('created_at', '>=', $today . ' 00:00:00') ->count(); return $exists > 0; } /** * 记录已发送的提醒 * @param int $memberId 学员ID * @param string $type 提醒类型 * @param int $relatedId 相关ID */ protected function recordReminderSent($memberId, $type, $relatedId) { // 这个方法可以用于记录提醒发送日志,避免重复发送 Log::write("记录提醒发送:学员ID {$memberId}, 类型: {$type}, 相关ID: {$relatedId}"); } /** * 创建通知记录 * @param int $memberId 学员ID * @param string $type 通知类型 * @param string $title 标题 * @param string $message 消息内容 * @param array $extra 额外数据 */ protected function createNotification($memberId, $type, $title, $message, $extra = []) { $notification = new Notification(); $notification->member_id = $memberId; $notification->type = $type; $notification->title = $title; $notification->message = $message; $notification->extra_data = json_encode($extra); $notification->status = 'sent'; $notification->created_at = date('Y-m-d H:i:s'); $notification->save(); // 这里可以扩展实际的通知发送逻辑 // 比如调用短信服务、邮件服务、推送服务等 Log::write("创建通知:学员ID {$memberId}, 类型: {$type}, 标题: {$title}"); } }