mirror of
https://github.com/massbug/judge4c.git
synced 2025-07-03 15:20:50 +00:00
fix(testcase): fix testcase add data failure due to index did not refresh index after save testcase
- 为测试用例添加唯一的临时 ID,避免重复 - 新增测试用例时检查输入和输出不能为空 - 保存测试用例时显示具体的成功和失败信息 - 保存完成后刷新最新测试用例数据 - 优化代码结构,提高可读性和可维护性
This commit is contained in:
parent
5bfa5fd642
commit
2a3769b95c
@ -24,7 +24,7 @@ export default function EditTestcasePanel({ problemId }: { problemId: string })
|
|||||||
const [testcases, setTestcases] = useState<Testcase[]>([]);
|
const [testcases, setTestcases] = useState<Testcase[]>([]);
|
||||||
const [isGenerating, setIsGenerating] = useState(false);
|
const [isGenerating, setIsGenerating] = useState(false);
|
||||||
|
|
||||||
// 1) Load existing testcases
|
// 加载测试用例
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetch() {
|
async function fetch() {
|
||||||
try {
|
try {
|
||||||
@ -38,21 +38,21 @@ export default function EditTestcasePanel({ problemId }: { problemId: string })
|
|||||||
fetch();
|
fetch();
|
||||||
}, [problemId]);
|
}, [problemId]);
|
||||||
|
|
||||||
// 2) Local add
|
// 本地添加测试用例
|
||||||
const handleAddTestcase = () =>
|
const handleAddTestcase = () =>
|
||||||
setTestcases((prev) => [
|
setTestcases((prev) => [
|
||||||
...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 () => {
|
const handleAITestcase = async () => {
|
||||||
setIsGenerating(true);
|
setIsGenerating(true);
|
||||||
try {
|
try {
|
||||||
const ai = await generateAITestcase({ problemId });
|
const ai = await generateAITestcase({ problemId });
|
||||||
setTestcases((prev) => [
|
setTestcases((prev) => [
|
||||||
...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" });
|
window.scrollTo({ top: document.body.scrollHeight, behavior: "smooth" });
|
||||||
} catch (err) {
|
} 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 handleRemoveTestcase = async (idx: number) => {
|
||||||
const tc = testcases[idx];
|
const tc = testcases[idx];
|
||||||
if (!tc.id.startsWith("new-")) {
|
if (!tc.id.startsWith("new-")) {
|
||||||
@ -79,14 +79,15 @@ export default function EditTestcasePanel({ problemId }: { problemId: string })
|
|||||||
setTestcases((prev) => prev.filter((_, i) => i !== idx));
|
setTestcases((prev) => prev.filter((_, i) => i !== idx));
|
||||||
};
|
};
|
||||||
|
|
||||||
// 5) Field updates
|
// 修改预期输出
|
||||||
const handleExpectedOutputChange = (idx: number, val: string) =>
|
const handleExpectedOutputChange = (idx: number, val: string) =>
|
||||||
setTestcases((prev) => {
|
setTestcases((prev) => {
|
||||||
const c = [...prev];
|
const c = [...prev];
|
||||||
c[idx].expectedOutput = val;
|
c[idx] = { ...c[idx], expectedOutput: val };
|
||||||
return c;
|
return c;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 修改输入参数
|
||||||
const handleInputChange = (
|
const handleInputChange = (
|
||||||
tIdx: number,
|
tIdx: number,
|
||||||
iIdx: number,
|
iIdx: number,
|
||||||
@ -95,43 +96,58 @@ export default function EditTestcasePanel({ problemId }: { problemId: string })
|
|||||||
) =>
|
) =>
|
||||||
setTestcases((prev) => {
|
setTestcases((prev) => {
|
||||||
const c = [...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;
|
return c;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 添加输入参数
|
||||||
const handleAddInput = (tIdx: number) =>
|
const handleAddInput = (tIdx: number) =>
|
||||||
setTestcases((prev) => {
|
setTestcases((prev) => {
|
||||||
const c = [...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;
|
return c;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 删除输入参数
|
||||||
const handleRemoveInput = (tIdx: number, iIdx: number) =>
|
const handleRemoveInput = (tIdx: number, iIdx: number) =>
|
||||||
setTestcases((prev) => {
|
setTestcases((prev) => {
|
||||||
const c = [...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;
|
return c;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 6) Persist all changes
|
// 保存所有测试用例,并刷新最新数据
|
||||||
const handleSaveAll = async () => {
|
const handleSaveAll = async () => {
|
||||||
try {
|
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-")) {
|
if (tc.id.startsWith("new-")) {
|
||||||
const res = await addProblemTestcase(problemId, tc.expectedOutput, tc.inputs);
|
const res = await addProblemTestcase(problemId, tc.expectedOutput, tc.inputs);
|
||||||
if (res.success) toast.success("新增测试用例成功");
|
if (res.success) {
|
||||||
else toast.error("新增测试用例失败");
|
toast.success(`新增测试用例 ${i + 1} 成功`);
|
||||||
|
} else {
|
||||||
|
toast.error(`新增测试用例 ${i + 1} 失败`);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const res = await updateProblemTestcase(
|
const res = await updateProblemTestcase(problemId, tc.id, tc.expectedOutput, tc.inputs);
|
||||||
problemId,
|
if (res.success) toast.success(`更新测试用例 ${i + 1} 成功`);
|
||||||
tc.id,
|
else toast.error(`更新测试用例 ${i + 1} 失败`);
|
||||||
tc.expectedOutput,
|
|
||||||
tc.inputs
|
|
||||||
);
|
|
||||||
if (res.success) toast.success("更新测试用例成功");
|
|
||||||
else toast.error("更新测试用例失败");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 保存完成后刷新最新测试用例
|
||||||
|
const data = await getProblemData(problemId);
|
||||||
|
setTestcases(data.testcases || []);
|
||||||
|
toast.success("测试用例保存并刷新成功");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
toast.error("保存测试用例异常");
|
toast.error("保存测试用例异常");
|
||||||
|
Loading…
Reference in New Issue
Block a user