> */ public function rules(): array { $type = $this->input('type', 'discussion'); $severities = Discussion::SEVERITIES[$type] ?? []; $isAssessment = $type === Discussion::TYPE_ASSESSMENT; $isAnnotation = in_array($type, Discussion::INJECTED_TYPES, true); $sentenceOnly = in_array($type, Discussion::SENTENCE_ONLY_TYPES, true); // 不收锚点的类型传了 422,免得静默丢掉 $anchor = fn (array $rules) => in_array($type, Discussion::ANCHORED_TYPES, true) ? ['sometimes', 'nullable', ...$rules] : ['prohibited']; return [ 'target_type' => ['required', 'string', Rule::in($sentenceOnly ? ['sentence'] : Discussion::TARGET_TYPES)], 'target_id' => ['required', 'uuid'], 'type' => ['sometimes', 'string', Rule::in(Discussion::COMMENT_TYPES)], 'title' => $isAnnotation || $isAssessment ? ['sometimes', 'nullable', 'string', 'max:256'] : ['required', 'string', 'max:256'], 'content' => match ($type) { Discussion::TYPE_COMMENTARY => ['required', 'string', 'max:20000', 'regex:'.Discussion::COMMENTARY_PATTERN], Discussion::TYPE_NOTE => ['required', 'string', 'max:20000'], default => ['sometimes', 'nullable', 'string', 'max:20000'], }, 'severity' => match (true) { $isAssessment => ['required', 'string', 'regex:'.Discussion::ASSESSMENT_METHOD_PATTERN], $severities === [] => ['prohibited'], default => ['sometimes', 'nullable', 'string', Rule::in($severities)], }, 'score' => $isAssessment ? ['required', 'integer', 'between:0,100'] : ['prohibited'], 'pos_start' => $anchor(['integer', 'min:0']), 'pos_end' => $anchor(['integer', 'min:0', 'gte:pos_start']), 'quote_exact' => $anchor(['string', 'max:1024']), 'quote_prefix' => $anchor(['string', 'max:1024']), 'quote_suffix' => $anchor(['string', 'max:1024']), 'tpl_id' => ['sometimes', 'nullable', 'uuid'], 'notify' => ['sometimes', 'boolean'], ]; } /** * @return array */ public function messages(): array { $messages = [ 'content.regex' => __('messages.discussion_commentary_format'), 'severity.prohibited' => __('messages.discussion_severity_not_allowed'), 'severity.regex' => __('messages.discussion_assessment_method'), 'score.prohibited' => __('messages.discussion_score_not_allowed'), ]; if (in_array($this->input('type'), Discussion::INJECTED_TYPES, true)) { $messages['target_type.in'] = __('messages.discussion_annotation_target'); } elseif ($this->input('type') === Discussion::TYPE_GLOSSARY) { $messages['target_type.in'] = __('messages.discussion_glossary_target'); } elseif ($this->input('type') === Discussion::TYPE_ASSESSMENT) { $messages['target_type.in'] = __('messages.discussion_assessment_target'); } foreach (self::ANCHOR_FIELDS as $field) { $messages["{$field}.prohibited"] = __('messages.discussion_anchor_thread'); } return $messages; } }