127 lines
5.6 KiB
TypeScript
127 lines
5.6 KiB
TypeScript
"use client";
|
|
|
|
import { Ban, CheckCircle2, PauseCircle, Pencil, RotateCw } from "lucide-react";
|
|
import { api, formatDateTime } from "@/lib/api";
|
|
import type { StandardQAItem } from "@/lib/types";
|
|
import RiskBadge from "./RiskBadge";
|
|
import StatusBadge from "./StatusBadge";
|
|
|
|
export default function StandardQATable({ items, onChanged }: { items: StandardQAItem[]; onChanged: () => void }) {
|
|
async function action(id: number, path: string) {
|
|
try {
|
|
await api.post(`/standard-qa/${id}/${path}`, {});
|
|
onChanged();
|
|
} catch (error) {
|
|
alert(error instanceof Error ? error.message : "操作失败");
|
|
}
|
|
}
|
|
|
|
async function edit(item: StandardQAItem) {
|
|
const standardQuestion = window.prompt("标准问题", item.standard_question);
|
|
if (standardQuestion === null) return;
|
|
const standardAnswer = window.prompt("标准回答", item.standard_answer);
|
|
if (standardAnswer === null) return;
|
|
await api.patch(`/standard-qa/${item.id}`, {
|
|
standard_question: standardQuestion,
|
|
standard_answer: standardAnswer
|
|
});
|
|
onChanged();
|
|
}
|
|
|
|
return (
|
|
<div className="table-wrap rounded-md border border-line bg-white">
|
|
<table className="min-w-[1350px] w-full border-collapse text-left text-sm">
|
|
<thead className="bg-panel text-xs uppercase text-slate-500">
|
|
<tr>
|
|
<th className="px-4 py-3">标准问题</th>
|
|
<th className="px-4 py-3">标准回答</th>
|
|
<th className="px-4 py-3">相似问法</th>
|
|
<th className="px-4 py-3">主题</th>
|
|
<th className="px-4 py-3">标签</th>
|
|
<th className="px-4 py-3">阶段</th>
|
|
<th className="px-4 py-3">适用人群</th>
|
|
<th className="px-4 py-3">边界</th>
|
|
<th className="px-4 py-3">禁止表达</th>
|
|
<th className="px-4 py-3">来源</th>
|
|
<th className="px-4 py-3">状态</th>
|
|
<th className="px-4 py-3">更新</th>
|
|
<th className="px-4 py-3">操作</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{items.map((item) => (
|
|
<tr key={item.id} className="border-t border-line align-top">
|
|
<td className="max-w-sm px-4 py-3 font-medium text-ink">{item.standard_question}</td>
|
|
<td className="max-w-md whitespace-pre-wrap px-4 py-3">{item.standard_answer}</td>
|
|
<td className="px-4 py-3">{item.similar_questions.join("、") || "-"}</td>
|
|
<td className="px-4 py-3">{item.primary_topic}</td>
|
|
<td className="px-4 py-3">{item.problem_tags.join("、") || "-"}</td>
|
|
<td className="px-4 py-3">{item.course_stage}</td>
|
|
<td className="px-4 py-3">{item.audience_tags.join("、") || "-"}</td>
|
|
<td className="max-w-xs px-4 py-3">{item.answer_boundary ?? "-"}</td>
|
|
<td className="px-4 py-3">{item.forbidden_expressions.join("、") || "-"}</td>
|
|
<td className="px-4 py-3">
|
|
QA #{item.source_raw_qa_id}
|
|
<br />
|
|
场次 #{item.session_id}
|
|
</td>
|
|
<td className="space-y-2 px-4 py-3">
|
|
<StatusBadge status={item.audit_status} />
|
|
<StatusBadge status={item.call_status} />
|
|
<RiskBadge level={item.risk_level} />
|
|
</td>
|
|
<td className="px-4 py-3">{formatDateTime(item.updated_at)}</td>
|
|
<td className="px-4 py-3">
|
|
<div className="flex flex-wrap gap-2">
|
|
<button
|
|
onClick={() => edit(item)}
|
|
className="inline-flex h-8 items-center gap-1 rounded-md border border-line px-2 text-xs hover:bg-slate-50"
|
|
>
|
|
<Pencil className="h-3.5 w-3.5" aria-hidden />
|
|
编辑
|
|
</button>
|
|
<button
|
|
onClick={() => action(item.id, "mark-callable")}
|
|
className="inline-flex h-8 items-center gap-1 rounded-md border border-emerald-200 px-2 text-xs text-emerald-700 hover:bg-emerald-50"
|
|
>
|
|
<CheckCircle2 className="h-3.5 w-3.5" aria-hidden />
|
|
可调用
|
|
</button>
|
|
<button
|
|
onClick={() => action(item.id, "mark-not-callable")}
|
|
className="inline-flex h-8 items-center gap-1 rounded-md border border-line px-2 text-xs hover:bg-slate-50"
|
|
>
|
|
<PauseCircle className="h-3.5 w-3.5" aria-hidden />
|
|
暂不调用
|
|
</button>
|
|
<button
|
|
onClick={() => action(item.id, "need-review")}
|
|
className="inline-flex h-8 items-center gap-1 rounded-md border border-line px-2 text-xs hover:bg-slate-50"
|
|
>
|
|
<RotateCw className="h-3.5 w-3.5" aria-hidden />
|
|
复审
|
|
</button>
|
|
<button
|
|
onClick={() => action(item.id, "disable")}
|
|
className="inline-flex h-8 items-center gap-1 rounded-md border border-rose-200 px-2 text-xs text-rose-700 hover:bg-rose-50"
|
|
>
|
|
<Ban className="h-3.5 w-3.5" aria-hidden />
|
|
禁用
|
|
</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
{items.length === 0 ? (
|
|
<tr>
|
|
<td className="px-4 py-8 text-center text-slate-500" colSpan={13}>
|
|
暂无标准问答
|
|
</td>
|
|
</tr>
|
|
) : null}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
);
|
|
}
|