input('thresholds', [])) ->map(fn ($value): string => trim((string) $value)) ->filter(fn (string $value): bool => $value !== '') ->values() ->all(); $this->merge([ 'thresholds' => $thresholds, ]); } /** * 方法功能:返回等级经验阈值表单的校验规则。 * * @return array|string> */ public function rules(): array { return [ 'thresholds' => ['required', 'array', 'min:1', $this->strictlyIncreasingRule(), $this->maxLevelLimitRule()], 'thresholds.*' => ['required', 'integer', 'min:1'], ]; } /** * 方法功能:返回中文校验错误消息。 * * @return array */ public function messages(): array { return [ 'thresholds.required' => '请至少配置一个等级经验阈值。', 'thresholds.array' => '等级经验阈值提交格式不正确。', 'thresholds.min' => '请至少保留一个等级经验阈值。', 'thresholds.*.required' => '等级经验阈值不能为空。', 'thresholds.*.integer' => '等级经验阈值必须是整数。', 'thresholds.*.min' => '等级经验阈值必须大于 0。', ]; } /** * 方法功能:自定义校验阈值必须严格递增。 */ private function strictlyIncreasingRule(): ValidationRule { return new class implements ValidationRule { /** * 方法功能:执行严格递增校验。 * * @param Closure(string): void $fail */ public function validate(string $attribute, mixed $value, Closure $fail): void { if (! is_array($value)) { return; } $previous = null; foreach ($value as $index => $threshold) { if (! is_numeric($threshold)) { continue; } $current = (int) $threshold; // 每一级累计经验必须大于前一级,避免等级计算出现倒挂。 if ($previous !== null && $current <= $previous) { $fail('等级经验阈值必须按等级从小到大严格递增,第 '.($index + 1).' 级配置不正确。'); return; } $previous = $current; } } }; } /** * 方法功能:校验等级阈值数量不能超过用户最高可达等级。 */ private function maxLevelLimitRule(): ValidationRule { return new class((int) Sysparam::getValue('maxlevel', '99')) implements ValidationRule { /** * 方法功能:构造数量上限校验器。 */ public function __construct( private readonly int $maxLevel ) {} /** * 方法功能:执行阈值数量与最高等级的上限校验。 * * @param Closure(string): void $fail */ public function validate(string $attribute, mixed $value, Closure $fail): void { if (! is_array($value) || $this->maxLevel < 1) { return; } // 阈值行数对应可升级的等级数,不能超过用户最高可达等级。 if (count($value) > $this->maxLevel) { $fail('等级经验阈值数量不能超过用户最高可达等级,请先提高最高等级或删除多余等级。'); } } }; } }