"use client"; import React, { useState, useEffect } from "react"; import { generateAITestcase } from "@/app/actions/ai-testcase"; import { getProblemData } from "@/app/actions/getProblem"; import { addProblemTestcase, updateProblemTestcase, deleteProblemTestcase, } from "@/components/creater/problem-maintain"; import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { toast } from "sonner"; interface Testcase { id: string; expectedOutput: string; inputs: { name: string; value: string }[]; } export default function EditTestcasePanel({ problemId }: { problemId: string }) { const [testcases, setTestcases] = useState([]); const [isGenerating, setIsGenerating] = useState(false); // 加载测试用例 useEffect(() => { async function fetch() { try { const data = await getProblemData(problemId); setTestcases(data.testcases || []); } catch (err) { console.error("加载测试用例失败:", err); toast.error("加载测试用例失败"); } } fetch(); }, [problemId]); // 本地添加测试用例 const handleAddTestcase = () => setTestcases((prev) => [ ...prev, { id: `new-${Date.now()}-${Math.random()}`, expectedOutput: "", inputs: [{ name: "input1", value: "" }] }, ]); // AI 生成测试用例 const handleAITestcase = async () => { setIsGenerating(true); try { const ai = await generateAITestcase({ problemId }); setTestcases((prev) => [ ...prev, { id: `new-${Date.now()}-${Math.random()}`, expectedOutput: ai.expectedOutput, inputs: ai.inputs }, ]); window.scrollTo({ top: document.body.scrollHeight, behavior: "smooth" }); } catch (err) { console.error(err); toast.error("AI 生成测试用例失败"); } finally { setIsGenerating(false); } }; // 删除测试用例(本地 + 服务器) const handleRemoveTestcase = async (idx: number) => { const tc = testcases[idx]; if (!tc.id.startsWith("new-")) { try { const res = await deleteProblemTestcase(problemId, tc.id); if (res.success) toast.success("删除测试用例成功"); else toast.error("删除测试用例失败"); } catch (err) { console.error(err); toast.error("删除测试用例异常"); } } setTestcases((prev) => prev.filter((_, i) => i !== idx)); }; // 修改预期输出 const handleExpectedOutputChange = (idx: number, val: string) => setTestcases((prev) => { const c = [...prev]; c[idx] = { ...c[idx], expectedOutput: val }; return c; }); // 修改输入参数 const handleInputChange = ( tIdx: number, iIdx: number, field: "name" | "value", val: string ) => setTestcases((prev) => { const c = [...prev]; const newInputs = [...c[tIdx].inputs]; newInputs[iIdx] = { ...newInputs[iIdx], [field]: val }; c[tIdx] = { ...c[tIdx], inputs: newInputs }; return c; }); // 添加输入参数 const handleAddInput = (tIdx: number) => setTestcases((prev) => { const c = [...prev]; const inputs = [...c[tIdx].inputs, { name: `input${c[tIdx].inputs.length + 1}`, value: "" }]; c[tIdx] = { ...c[tIdx], inputs }; return c; }); // 删除输入参数 const handleRemoveInput = (tIdx: number, iIdx: number) => setTestcases((prev) => { const c = [...prev]; const inputs = c[tIdx].inputs.filter((_, i) => i !== iIdx); c[tIdx] = { ...c[tIdx], inputs }; return c; }); // 保存所有测试用例,并刷新最新数据 const handleSaveAll = async () => { try { for (let i = 0; i < testcases.length; i++) { const tc = testcases[i]; if (tc.expectedOutput.trim() === "" || tc.inputs.some(inp => !inp.name.trim() || !inp.value.trim())) { toast.error(`第 ${i + 1} 个测试用例存在空的输入或输出,保存失败`); return; } if (tc.id.startsWith("new-")) { const res = await addProblemTestcase(problemId, tc.expectedOutput, tc.inputs); if (res.success) { toast.success(`新增测试用例 ${i + 1} 成功`); } else { toast.error(`新增测试用例 ${i + 1} 失败`); } } else { const res = await updateProblemTestcase(problemId, tc.id, tc.expectedOutput, tc.inputs); if (res.success) toast.success(`更新测试用例 ${i + 1} 成功`); else toast.error(`更新测试用例 ${i + 1} 失败`); } } // 保存完成后刷新最新测试用例 const data = await getProblemData(problemId); setTestcases(data.testcases || []); toast.success("测试用例保存并刷新成功"); } catch (err) { console.error(err); toast.error("保存测试用例异常"); } }; return ( 测试用例
{testcases.map((tc, idx) => (

测试用例 {idx + 1}

handleExpectedOutputChange(idx, e.target.value)} placeholder="输入预期输出" />
{tc.inputs.map((inp, iIdx) => (
handleInputChange(idx, iIdx, "name", e.target.value)} placeholder="参数名称" />
handleInputChange(idx, iIdx, "value", e.target.value)} placeholder="参数值" />
{iIdx > 0 && ( )}
))}
))}
); }