99 lines
3.0 KiB
PHP
99 lines
3.0 KiB
PHP
<?php
|
|
|
|
/**
|
|
* 文件功能:节日福利年度调度校验规则
|
|
*
|
|
* 负责校验 yearly 模式下的月/日/时间、多天与多轮次组合是否合法。
|
|
*/
|
|
|
|
namespace App\Rules;
|
|
|
|
use Closure;
|
|
use Illuminate\Contracts\Validation\DataAwareRule;
|
|
use Illuminate\Contracts\Validation\ValidationRule;
|
|
use Illuminate\Translation\PotentiallyTranslatedString;
|
|
|
|
/**
|
|
* 类功能:校验节日福利年度调度配置的组合合法性。
|
|
*/
|
|
class HolidayEventScheduleRule implements DataAwareRule, ValidationRule
|
|
{
|
|
/**
|
|
* 当前请求的全部字段。
|
|
*
|
|
* @var array<string, mixed>
|
|
*/
|
|
protected array $data = [];
|
|
|
|
/**
|
|
* 注入待校验的完整数据集。
|
|
*
|
|
* @param array<string, mixed> $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('同一天多轮发送的最后一轮不能跨到次日,请缩短间隔或减少次数。');
|
|
}
|
|
}
|
|
}
|