From 2a3769b95c09aa5d3205fa9a54bcd38a08a47033 Mon Sep 17 00:00:00 2001 From: fly6516 Date: Fri, 20 Jun 2025 17:31:33 +0800 Subject: [PATCH] fix(testcase): fix testcase add data failure due to index did not refresh index after save testcase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为测试用例添加唯一的临时 ID,避免重复 - 新增测试用例时检查输入和输出不能为空 - 保存测试用例时显示具体的成功和失败信息 - 保存完成后刷新最新测试用例数据 - 优化代码结构,提高可读性和可维护性 --- .../creater/edit-testcase-panel.tsx | 62 ++++++++++++------- 1 file changed, 39 insertions(+), 23 deletions(-) diff --git a/src/components/creater/edit-testcase-panel.tsx b/src/components/creater/edit-testcase-panel.tsx index 23275fb..882eabd 100644 --- a/src/components/creater/edit-testcase-panel.tsx +++ b/src/components/creater/edit-testcase-panel.tsx @@ -24,7 +24,7 @@ export default function EditTestcasePanel({ problemId }: { problemId: string }) const [testcases, setTestcases] = useState([]); const [isGenerating, setIsGenerating] = useState(false); - // 1) Load existing testcases + // 加载测试用例 useEffect(() => { async function fetch() { try { @@ -38,21 +38,21 @@ export default function EditTestcasePanel({ problemId }: { problemId: string }) fetch(); }, [problemId]); - // 2) Local add + // 本地添加测试用例 const handleAddTestcase = () => setTestcases((prev) => [ ...prev, - { id: `new-${Date.now()}`, expectedOutput: "", inputs: [{ name: "input1", value: "" }] }, + { id: `new-${Date.now()}-${Math.random()}`, expectedOutput: "", inputs: [{ name: "input1", value: "" }] }, ]); - // 3) AI generation + // AI 生成测试用例 const handleAITestcase = async () => { setIsGenerating(true); try { const ai = await generateAITestcase({ problemId }); setTestcases((prev) => [ ...prev, - { id: `new-${Date.now()}`, expectedOutput: ai.expectedOutput, inputs: ai.inputs }, + { id: `new-${Date.now()}-${Math.random()}`, expectedOutput: ai.expectedOutput, inputs: ai.inputs }, ]); window.scrollTo({ top: document.body.scrollHeight, behavior: "smooth" }); } catch (err) { @@ -63,7 +63,7 @@ export default function EditTestcasePanel({ problemId }: { problemId: string }) } }; - // 4) Remove (local + remote if existing) + // 删除测试用例(本地 + 服务器) const handleRemoveTestcase = async (idx: number) => { const tc = testcases[idx]; if (!tc.id.startsWith("new-")) { @@ -79,14 +79,15 @@ export default function EditTestcasePanel({ problemId }: { problemId: string }) setTestcases((prev) => prev.filter((_, i) => i !== idx)); }; - // 5) Field updates + // 修改预期输出 const handleExpectedOutputChange = (idx: number, val: string) => setTestcases((prev) => { const c = [...prev]; - c[idx].expectedOutput = val; + c[idx] = { ...c[idx], expectedOutput: val }; return c; }); + // 修改输入参数 const handleInputChange = ( tIdx: number, iIdx: number, @@ -95,43 +96,58 @@ export default function EditTestcasePanel({ problemId }: { problemId: string }) ) => setTestcases((prev) => { const c = [...prev]; - c[tIdx].inputs[iIdx][field] = val; + 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]; - c[tIdx].inputs.push({ name: `input${c[tIdx].inputs.length + 1}`, value: "" }); + 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]; - c[tIdx].inputs.splice(iIdx, 1); + const inputs = c[tIdx].inputs.filter((_, i) => i !== iIdx); + c[tIdx] = { ...c[tIdx], inputs }; return c; }); - // 6) Persist all changes + // 保存所有测试用例,并刷新最新数据 const handleSaveAll = async () => { try { - for (const tc of testcases) { + 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("新增测试用例成功"); - else toast.error("新增测试用例失败"); + 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("更新测试用例成功"); - else toast.error("更新测试用例失败"); + 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("保存测试用例异常");