智慧教务系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

372 lines
13 KiB

<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\job\transfer\schedule;
use app\model\member\Member;
use app\model\course\Course;
use app\model\course_booking\CourseBooking;
use app\model\notification\Notification;
use core\base\BaseJob;
use think\facade\Log;
/**
* 定时检查学员课程有效期和课时数量发送提醒任务
* 监控学员课程状态,及时发送相关提醒通知
*/
class StudentCourseReminderJob extends BaseJob
{
/**
* 执行定时任务
* @param mixed ...$data 任务参数
* @return bool 处理结果
*/
public function doJob(...$data)
{
Log::write('开始执行学员课程提醒任务');
try {
// 检查课程有效期提醒
$expiryResult = $this->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}");
}
}