*/ protected array $data = []; /** * 注入待校验的完整数据集。 * * @param array $data */ public function setData(array $data): static { $this->data = $data; return $this; } /** * 运行年度调度规则校验。 * * @param Closure(string, ?string=): PotentiallyTranslatedString $fail */ public function validate(string $attribute, mixed $value, Closure $fail): void { $repeatType = (string) ($this->data['repeat_type'] ?? $value ?? ''); if ($repeatType !== 'yearly') { return; } $month = (int) ($this->data['schedule_month'] ?? 0); $day = (int) ($this->data['schedule_day'] ?? 0); $time = (string) ($this->data['schedule_time'] ?? ''); $durationDays = (int) ($this->data['duration_days'] ?? 0); $dailyOccurrences = (int) ($this->data['daily_occurrences'] ?? 0); $intervalMinutes = $this->data['occurrence_interval_minutes']; if ($month < 1 || $month > 12) { $fail('年度节日模式必须设置有效的触发月份。'); } if ($day < 1 || $day > 31) { $fail('年度节日模式必须设置有效的触发日期。'); } if ($month > 0 && $day > 0 && ! checkdate($month, $day, 2024)) { $fail('所选月份和日期不是有效的公历节日日期。'); } if (! preg_match('/^\d{2}:\d{2}$/', $time)) { $fail('年度节日模式必须设置首轮开始时间。'); return; } if ($durationDays < 1 || $durationDays > 31) { $fail('连续发放天数必须在 1 到 31 天之间。'); } if ($dailyOccurrences < 1 || $dailyOccurrences > 24) { $fail('每天发送次数必须在 1 到 24 次之间。'); } if ($dailyOccurrences > 1 && ((int) $intervalMinutes) < 1) { $fail('同一天多轮发送时,必须设置大于 0 的间隔分钟数。'); } [$hour, $minute] = array_map('intval', explode(':', $time)); $startMinutes = $hour * 60 + $minute; $lastOffsetMinutes = max(0, ($dailyOccurrences - 1) * (int) ($intervalMinutes ?? 0)); if ($startMinutes + $lastOffsetMinutes >= 1440) { $fail('同一天多轮发送的最后一轮不能跨到次日,请缩短间隔或减少次数。'); } } }