2025-06-20 14:25:07 +00:00
|
|
|
"use client";
|
2025-06-16 10:37:25 +00:00
|
|
|
|
2025-06-20 15:36:44 +00:00
|
|
|
import { toast } from "sonner";
|
2025-06-20 14:25:07 +00:00
|
|
|
import { Label } from "@/components/ui/label";
|
2025-06-20 15:36:44 +00:00
|
|
|
import { Language } from "@/generated/client";
|
2025-06-20 14:25:07 +00:00
|
|
|
import { Button } from "@/components/ui/button";
|
2025-06-20 15:36:44 +00:00
|
|
|
import React, { useEffect, useState } from "react";
|
2025-06-20 14:25:07 +00:00
|
|
|
import { CoreEditor } from "@/components/core-editor";
|
2025-06-20 15:36:44 +00:00
|
|
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
|
|
|
import { getProblemData } from "@/app/actions/getProblem";
|
|
|
|
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
|
|
|
import { PanelLayout } from "@/features/problems/layouts/panel-layout";
|
|
|
|
import { updateProblemTemplate } from "@/components/creater/problem-maintain";
|
2025-06-16 10:37:25 +00:00
|
|
|
|
|
|
|
interface Template {
|
|
|
|
language: string;
|
2025-06-17 07:24:43 +00:00
|
|
|
content: string;
|
2025-06-16 10:37:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
interface EditCodePanelProps {
|
|
|
|
problemId: string;
|
|
|
|
}
|
|
|
|
|
2025-06-20 03:42:10 +00:00
|
|
|
export default function EditCodePanel({ problemId }: EditCodePanelProps) {
|
2025-06-17 07:24:43 +00:00
|
|
|
const [codeTemplate, setCodeTemplate] = useState<Template>({
|
2025-06-20 14:25:07 +00:00
|
|
|
language: "cpp",
|
2025-06-17 07:24:43 +00:00
|
|
|
content: `// 默认代码模板 for Problem ${problemId}`,
|
|
|
|
});
|
|
|
|
const [templates, setTemplates] = useState<Template[]>([]);
|
|
|
|
|
|
|
|
useEffect(() => {
|
2025-06-20 03:42:10 +00:00
|
|
|
async function fetchTemplates() {
|
2025-06-17 07:24:43 +00:00
|
|
|
try {
|
|
|
|
const problem = await getProblemData(problemId);
|
|
|
|
setTemplates(problem.templates);
|
2025-06-20 14:25:07 +00:00
|
|
|
const sel =
|
|
|
|
problem.templates.find((t) => t.language === "cpp") ||
|
|
|
|
problem.templates[0];
|
2025-06-20 03:42:10 +00:00
|
|
|
if (sel) setCodeTemplate(sel);
|
2025-06-17 07:24:43 +00:00
|
|
|
} catch (err) {
|
2025-06-20 14:25:07 +00:00
|
|
|
console.error("加载问题数据失败:", err);
|
|
|
|
toast.error("加载问题数据失败");
|
2025-06-17 07:24:43 +00:00
|
|
|
}
|
|
|
|
}
|
2025-06-20 03:42:10 +00:00
|
|
|
fetchTemplates();
|
2025-06-17 07:24:43 +00:00
|
|
|
}, [problemId]);
|
|
|
|
|
|
|
|
const handleLanguageChange = (language: string) => {
|
2025-06-20 14:25:07 +00:00
|
|
|
const sel = templates.find((t) => t.language === language);
|
2025-06-20 03:42:10 +00:00
|
|
|
if (sel) setCodeTemplate(sel);
|
2025-06-17 07:24:43 +00:00
|
|
|
};
|
2025-06-16 10:37:25 +00:00
|
|
|
|
2025-06-17 07:24:43 +00:00
|
|
|
const handleSave = async (): Promise<void> => {
|
|
|
|
try {
|
2025-06-20 03:42:10 +00:00
|
|
|
const res = await updateProblemTemplate(
|
2025-06-20 14:25:07 +00:00
|
|
|
problemId,
|
|
|
|
codeTemplate.language as Language,
|
|
|
|
codeTemplate.content
|
2025-06-20 03:42:10 +00:00
|
|
|
);
|
|
|
|
if (res.success) {
|
2025-06-20 14:25:07 +00:00
|
|
|
toast.success("保存成功");
|
2025-06-17 07:24:43 +00:00
|
|
|
} else {
|
2025-06-20 14:25:07 +00:00
|
|
|
toast.error("保存失败");
|
2025-06-17 07:24:43 +00:00
|
|
|
}
|
|
|
|
} catch (error) {
|
2025-06-20 14:25:07 +00:00
|
|
|
console.error("保存异常:", error);
|
|
|
|
toast.error("保存异常");
|
2025-06-17 07:24:43 +00:00
|
|
|
}
|
2025-06-16 10:37:25 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
2025-06-20 15:36:44 +00:00
|
|
|
<PanelLayout>
|
|
|
|
<ScrollArea className="h-full">
|
|
|
|
<Card className="w-full rounded-none border-none bg-background">
|
|
|
|
<CardHeader className="px-6 py-4">
|
|
|
|
<div className="flex items-center justify-between">
|
|
|
|
<span>代码模板</span>
|
|
|
|
<Button onClick={handleSave}>保存</Button>
|
2025-06-17 07:24:43 +00:00
|
|
|
</div>
|
2025-06-20 15:36:44 +00:00
|
|
|
</CardHeader>
|
|
|
|
<CardContent>
|
|
|
|
<div className="space-y-6">
|
|
|
|
<div className="space-y-2">
|
|
|
|
<Label htmlFor="language-select">编程语言</Label>
|
|
|
|
<select
|
|
|
|
id="language-select"
|
|
|
|
className="block w-full p-2 border border-gray-300 rounded-md dark:bg-gray-800 dark:border-gray-700"
|
|
|
|
value={codeTemplate.language}
|
|
|
|
onChange={(e) => handleLanguageChange(e.target.value)}
|
|
|
|
>
|
|
|
|
{templates.map((t) => (
|
|
|
|
<option key={t.language} value={t.language}>
|
|
|
|
{t.language.toUpperCase()}
|
|
|
|
</option>
|
|
|
|
))}
|
|
|
|
</select>
|
|
|
|
</div>
|
2025-06-20 14:25:07 +00:00
|
|
|
|
2025-06-20 15:36:44 +00:00
|
|
|
<div className="space-y-2">
|
|
|
|
<Label htmlFor="code-editor">代码模板内容</Label>
|
|
|
|
<div className="border rounded-md h-[500px]">
|
|
|
|
<CoreEditor
|
|
|
|
language={codeTemplate.language}
|
|
|
|
value={codeTemplate.content}
|
|
|
|
path={`/${problemId}.${codeTemplate.language}`}
|
|
|
|
onChange={(value) =>
|
|
|
|
setCodeTemplate({ ...codeTemplate, content: value || "" })
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</CardContent>
|
|
|
|
</Card>
|
|
|
|
</ScrollArea>
|
|
|
|
</PanelLayout>
|
2025-06-16 10:37:25 +00:00
|
|
|
);
|
2025-06-17 07:24:43 +00:00
|
|
|
}
|