'require|in:all,specified', 'user_ids' => 'checkUserIds', 'title' => 'require|max:50', 'content' => 'require|max:1000', 'target_url' => 'max:200|checkTargetUrl', ]; protected $message = [ 'recipient_scope.require' => '请选择接收范围', 'recipient_scope.in' => '接收范围错误', 'title.require' => '请输入消息标题', 'title.max' => '消息标题不能超过50个字符', 'content.require' => '请输入消息内容', 'content.max' => '消息内容不能超过1000个字符', 'target_url.max' => '跳转路径不能超过200个字符', ]; protected function sceneSend() { return $this->only(['recipient_scope', 'user_ids', 'title', 'content', 'target_url']); } protected function checkUserIds($value, $rule, array $data) { if (($data['recipient_scope'] ?? '') !== 'specified') { return true; } if (!is_array($value) || empty($value)) { return '请至少填写一位指定用户ID'; } foreach ($value as $userId) { if (!is_numeric($userId) || (int) $userId <= 0) { return '指定用户ID格式错误'; } } return true; } protected function checkTargetUrl($value) { if ($value === null || $value === '') { return true; } return is_string($value) && str_starts_with($value, '/') && !str_starts_with($value, '//') ? true : '跳转路径必须以单个 / 开头'; } }