"use client"; import { AlertTriangle, CheckCircle2, LocateFixed, Sparkles } from "lucide-react"; import { Badge } from "@/components/ui/Badge"; import { TextInput } from "@/components/ui/TextInput"; import { buttonClass } from "@/lib/ui/variants"; import type { DecisionDraft, Verdict } from "@/lib/review/decisions"; import type { ReviewConflict } from "@/lib/review/sse"; interface ConflictCardProps { index: number; total: number; conflict: ReviewConflict; draft: DecisionDraft; missing: boolean; // R1:命中段内联预览(无段号/越界时为 null,回退到「跳转」按钮)。 snippet: string | null; // 该冲突能否在正文里定位(决定是否显示「跳转」——定位不到就别给会失败的入口)。 locatable: boolean; // 正在 AI 改写(采纳无补丁冲突时):禁用按钮 + 显示进度,避免重复点。 rewriting: boolean; onVerdict: (index: number, verdict: Verdict) => void; onNote: (index: number, note: string) => void; onJump: (index: number) => void; } // R2:采纳改法=朱砂主按钮(primary),忽略/手改=次级(secondary),不再三者同权。 const VERDICT_OPTIONS: { value: Verdict; label: string; primary: boolean }[] = [ { value: "accept", label: "采纳改法", primary: true }, { value: "ignore", label: "忽略", primary: false }, { value: "manual", label: "手改", primary: false }, ]; // 裁决按钮样式:激活=朱砂填充;未激活的主按钮=朱砂描边强调,次级=低对比描边。 function verdictClass(active: boolean, primary: boolean): string { if (active) return buttonClass({ variant: "primary", size: "sm" }); if (primary) return buttonClass({ variant: "outline", size: "sm" }); return buttonClass({ variant: "secondary", size: "sm" }); } // 单个冲突报告卡(UX §6.4):五类徽标 + where + refs + suggestion + 裁决三态。 // 冲突=赭红;未决/缺判时加图标+文案(不单靠色,a11y §10)。 export function ConflictCard({ index, total, conflict, draft, missing, snippet, locatable, rewriting, onVerdict, onNote, onJump, }: ConflictCardProps) { const resolved = draft.verdict !== null; return (
{conflict.type}
{conflict.suggestion}
{snippet}) : null}
选择手改后,说明会随验收裁决一起保存,正文请在左侧直接修改。