Files

139 lines
5.6 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { Check, EyeOff, FileX, Pencil, ShieldAlert, Sparkles, X } from "lucide-react";
import type { ReactNode } from "react";
import { api } from "@/lib/api";
import type { RawQAItem } from "@/lib/types";
import RiskBadge from "./RiskBadge";
import StatusBadge from "./StatusBadge";
function Field({ label, children }: { label: string; children: ReactNode }) {
return (
<div>
<div className="mb-1 text-xs font-medium text-slate-500">{label}</div>
<div className="whitespace-pre-wrap text-sm leading-6 text-ink">{children || "-"}</div>
</div>
);
}
export default function QAReviewCard({ item, onChanged }: { item: RawQAItem; onChanged: () => void }) {
async function action(path: string) {
await api.post(`/raw-qa/${item.id}/${path}`, {});
onChanged();
}
async function editAndApprove() {
const standardQuestion = window.prompt("标准问题", item.suggested_standard_question ?? item.normalized_question ?? "");
if (standardQuestion === null) return;
const standardAnswer = window.prompt("标准回答", item.suggested_standard_answer ?? item.normalized_answer ?? "");
if (standardAnswer === null) return;
await api.patch(`/raw-qa/${item.id}`, {
suggested_standard_question: standardQuestion,
suggested_standard_answer: standardAnswer
});
await action("approve");
}
return (
<article className="rounded-md border border-line bg-white p-5">
<div className="mb-4 flex flex-wrap items-center justify-between gap-3">
<div className="flex flex-wrap items-center gap-2">
<span className="text-sm font-semibold text-ink">{item.qa_code}</span>
<RiskBadge level={item.risk_level} />
<StatusBadge status={item.review_status} />
{item.need_desensitization ? (
<span className="rounded-md border border-amber-200 bg-amber-50 px-2 py-1 text-xs font-medium text-amber-700">
</span>
) : null}
</div>
<div className="text-xs text-slate-500"> #{item.session_id}</div>
</div>
<div className="grid gap-5 lg:grid-cols-2">
<Field label="原始问题">{item.raw_question}</Field>
<Field label="问题整理版">{item.normalized_question}</Field>
<Field label="原始回答">{item.raw_answer}</Field>
<Field label="回答整理版">{item.normalized_answer}</Field>
<Field label="AI 建议标准问题">{item.suggested_standard_question}</Field>
<Field label="AI 建议标准回答">{item.suggested_standard_answer}</Field>
</div>
<div className="mt-5 grid gap-3 border-t border-line pt-4 text-sm md:grid-cols-2 xl:grid-cols-4">
<div>
<span className="text-slate-500"></span>
{item.primary_topic}
</div>
<div>
<span className="text-slate-500"></span>
{item.course_stage}
</div>
<div>
<span className="text-slate-500"></span>
{item.problem_tags.join("、") || "-"}
</div>
<div>
<span className="text-slate-500"></span>
{item.source_timestamp || "-"}
</div>
</div>
<div className="mt-4 rounded-md border border-amber-200 bg-amber-50 p-3 text-sm text-amber-900">
{item.risk_notes || "无风险说明"}
</div>
<div className="mt-5 flex flex-wrap gap-2">
<button
onClick={() => action("approve")}
className="inline-flex h-9 items-center gap-2 rounded-md bg-jade px-3 text-sm font-medium text-white hover:bg-teal-800"
>
<Check className="h-4 w-4" aria-hidden />
</button>
<button
onClick={editAndApprove}
className="inline-flex h-9 items-center gap-2 rounded-md border border-line bg-white px-3 text-sm font-medium text-ink hover:bg-slate-50"
>
<Pencil className="h-4 w-4" aria-hidden />
</button>
<button
onClick={() => action("revise")}
className="inline-flex h-9 items-center gap-2 rounded-md border border-line bg-white px-3 text-sm font-medium text-ink hover:bg-slate-50"
>
<Sparkles className="h-4 w-4" aria-hidden />
</button>
<button
onClick={() => action("reject")}
className="inline-flex h-9 items-center gap-2 rounded-md border border-line bg-white px-3 text-sm font-medium text-ink hover:bg-slate-50"
>
<FileX className="h-4 w-4" aria-hidden />
</button>
<button
onClick={() => action("forbid")}
className="inline-flex h-9 items-center gap-2 rounded-md border border-rose-200 bg-white px-3 text-sm font-medium text-rose-700 hover:bg-rose-50"
>
<X className="h-4 w-4" aria-hidden />
使
</button>
<button
onClick={() => action("mark-high-risk")}
className="inline-flex h-9 items-center gap-2 rounded-md border border-orange-200 bg-white px-3 text-sm font-medium text-orange-700 hover:bg-orange-50"
>
<ShieldAlert className="h-4 w-4" aria-hidden />
</button>
<button
onClick={() => action("mark-desensitization")}
className="inline-flex h-9 items-center gap-2 rounded-md border border-amber-200 bg-white px-3 text-sm font-medium text-amber-700 hover:bg-amber-50"
>
<EyeOff className="h-4 w-4" aria-hidden />
</button>
</div>
</article>
);
}