From 0570328152cc293f5486ee7e0b3beaa342b8d3f9 Mon Sep 17 00:00:00 2001 From: liuwei Date: Tue, 10 Jun 2025 16:27:51 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=A0=E5=85=A5=E5=91=A8=E6=9C=9F=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E9=87=8C=E9=9D=A2=E7=9A=84=E6=AF=8F=E4=B8=AA=E5=91=A8?= =?UTF-8?q?=E6=9C=9F=E7=9A=84=E5=85=B7=E4=BD=93=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../templates/message_push_management.html | 58 ++++++++++ db/task_db.py | 14 ++- plugins/message_push_task/main.py | 105 ++++++++++++++++-- 3 files changed, 161 insertions(+), 16 deletions(-) diff --git a/admin/dashboard/templates/message_push_management.html b/admin/dashboard/templates/message_push_management.html index f82055b..20c5913 100644 --- a/admin/dashboard/templates/message_push_management.html +++ b/admin/dashboard/templates/message_push_management.html @@ -236,6 +236,49 @@ + + + + + + + + + + + + + + + + + + + + + \ - Optional[datetime]: + def _calculate_next_schedule_time(self, current_time: datetime, interval: str, end_time: datetime = None, + recurring_time: str = None, weekly_days: List[int] = None, + monthly_day: int = None) -> Optional[datetime]: """计算下次执行时间 Args: current_time: 当前执行时间 interval: 重复间隔(daily/weekly/monthly) end_time: 结束时间 + recurring_time: 重复执行时间(HH:mm格式) + weekly_days: 每周执行日列表(0-6,0表示周日) + monthly_day: 每月执行日(1-31) Returns: 下次执行时间,如果已超过结束时间则返回None """ try: if not end_time or current_time < end_time: + # 解析执行时间 + if recurring_time: + try: + hour, minute = map(int, recurring_time.split(':')) + if not (0 <= hour <= 23 and 0 <= minute <= 59): + self.LOG.error(f"无效的执行时间格式: {recurring_time}") + return None + except ValueError: + self.LOG.error(f"执行时间格式错误: {recurring_time}") + return None + else: + hour, minute = current_time.hour, current_time.minute + if interval == 'daily': - next_time = current_time.replace(day=current_time.day + 1) - elif interval == 'weekly': - next_time = current_time.replace(day=current_time.day + 7) - elif interval == 'monthly': - # 处理月份边界情况 - if current_time.month == 12: - next_time = current_time.replace(year=current_time.year + 1, month=1) + # 如果是首次执行,使用当前时间 + if current_time == datetime.now(): + next_time = current_time else: - next_time = current_time.replace(month=current_time.month + 1) + # 否则,设置为明天的同一时间 + next_time = current_time + timedelta(days=1) + next_time = next_time.replace(hour=hour, minute=minute) + + elif interval == 'weekly' and weekly_days: + # 验证每周执行日 + if not all(0 <= day <= 6 for day in weekly_days): + self.LOG.error(f"无效的每周执行日: {weekly_days}") + return None + + # 获取当前是周几(0-6,0表示周日) + current_weekday = current_time.weekday() + # 找到下一个执行日 + next_weekday = None + for day in sorted(weekly_days): + if day > current_weekday: + next_weekday = day + break + if next_weekday is None: + # 如果当前是本周最后一个执行日,则从下周第一个执行日开始 + next_weekday = min(weekly_days) + days_ahead = 7 - current_weekday + next_weekday + else: + days_ahead = next_weekday - current_weekday + + next_time = current_time + timedelta(days=days_ahead) + next_time = next_time.replace(hour=hour, minute=minute) + + elif interval == 'monthly' and monthly_day: + # 验证每月执行日 + if not (1 <= monthly_day <= 31): + self.LOG.error(f"无效的每月执行日: {monthly_day}") + return None + + # 获取当前日期 + current_day = current_time.day + # 计算下一个执行日期 + if current_day < monthly_day: + # 如果当前日期小于执行日期,则在本月执行 + try: + next_time = current_time.replace(day=monthly_day) + except ValueError: + # 处理无效日期(如2月30日) + if current_time.month == 12: + next_time = current_time.replace(year=current_time.year + 1, month=1, day=1) + else: + next_time = current_time.replace(month=current_time.month + 1, day=1) + else: + # 否则在下个月执行 + if current_time.month == 12: + next_time = current_time.replace(year=current_time.year + 1, month=1, day=1) + else: + next_time = current_time.replace(month=current_time.month + 1, day=1) + + # 尝试设置到指定的日期 + try: + next_time = next_time.replace(day=monthly_day) + except ValueError: + # 如果下个月的指定日期无效,则使用下个月的最后一天 + if next_time.month == 12: + next_time = next_time.replace(year=next_time.year + 1, month=1, day=1) + else: + next_time = next_time.replace(month=next_time.month + 1, day=1) + next_time = next_time - timedelta(days=1) + + next_time = next_time.replace(hour=hour, minute=minute) else: return None