From 19824e08777e03aad39d4c27a04bd72016aa8236 Mon Sep 17 00:00:00 2001 From: fly6516 Date: Tue, 17 Jun 2025 15:24:43 +0800 Subject: [PATCH] =?UTF-8?q?feat(problem-editor):=20add=20feature=20to=20pr?= =?UTF-8?q?eload=20problem=20information=20if=20there=20already=20has=20ha?= =?UTF-8?q?d=20data=20in=20database=20-=20=E6=B7=BB=E5=8A=A0=E4=BA=86?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E9=A2=84=E5=8A=A0=E8=BD=BD=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E9=80=9A=E8=BF=87=20getProblemData=20API=20=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E9=A2=98=E7=9B=AE=E4=BF=A1=E6=81=AF=20-=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E4=BA=86=E5=90=84=E4=B8=AA=E7=BC=96=E8=BE=91=E9=9D=A2?= =?UTF-8?q?=E6=9D=BF=E7=9A=84=E5=AE=9E=E7=8E=B0=EF=BC=8C=E6=8F=90=E9=AB=98?= =?UTF-8?q?=E4=BA=86=E4=BB=A3=E7=A0=81=E5=A4=8D=E7=94=A8=E6=80=A7=E5=92=8C?= =?UTF-8?q?=E5=8F=AF=E7=BB=B4=E6=8A=A4=E6=80=A7-=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E4=BA=86=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=8C=E6=94=AF=E6=8C=81=E5=A4=9A=E8=BE=93?= =?UTF-8?q?=E5=85=A5=E5=8F=82=E6=95=B0=E7=9A=84=E7=AE=A1=E7=90=86=20-=20?= =?UTF-8?q?=E6=94=B9=E8=BF=9B=E4=BA=86=E9=A2=98=E8=A7=A3=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E9=9D=A2=E6=9D=BF=EF=BC=8C=E5=A2=9E=E5=8A=A0=E4=BA=86=E9=A2=84?= =?UTF-8?q?=E8=A7=88=E5=92=8C=E5=AF=B9=E6=AF=94=E5=8A=9F=E8=83=BD=20-=20?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=E4=BA=86=E8=A1=A8=E5=8D=95=E5=85=83=E7=B4=A0?= =?UTF-8?q?=E7=9A=84=E6=A0=B7=E5=BC=8F=E5=92=8C=E4=BA=A4=E4=BA=92=E6=96=B9?= =?UTF-8?q?=E5=BC=8F=EF=BC=8C=E6=8F=90=E5=8D=87=E4=BA=86=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E4=BD=93=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../(app)/problem-editor/[problemId]/page.tsx | 10 +- src/app/actions/getProblem.ts | 27 +- src/components/creater/edit-code-panel.tsx | 173 ++++++----- .../creater/edit-description-panel.tsx | 162 ++++++----- src/components/creater/edit-detail-panel.tsx | 185 ++++++++---- .../creater/edit-solution-panel.tsx | 153 +++++----- .../creater/edit-testcase-panel.tsx | 269 +++++++++++------- 7 files changed, 590 insertions(+), 389 deletions(-) diff --git a/src/app/(app)/problem-editor/[problemId]/page.tsx b/src/app/(app)/problem-editor/[problemId]/page.tsx index 6047c80..3e2be4c 100644 --- a/src/app/(app)/problem-editor/[problemId]/page.tsx +++ b/src/app/(app)/problem-editor/[problemId]/page.tsx @@ -1,11 +1,11 @@ "use client"; import { ProblemFlexLayout } from '@/features/problems/components/problem-flexlayout'; -import { EditDescriptionPanel } from '@/components/creater/edit-description-panel'; -import { EditSolutionPanel } from '@/components/creater/edit-solution-panel'; -import { EditTestcasePanel } from '@/components/creater/edit-testcase-panel'; -import { EditDetailPanel } from '@/components/creater/edit-detail-panel'; -import { EditCodePanel } from '@/components/creater/edit-code-panel'; +import EditDescriptionPanel from '@/components/creater/edit-description-panel'; +import EditSolutionPanel from '@/components/creater/edit-solution-panel'; +import EditTestcasePanel from '@/components/creater/edit-testcase-panel'; +import EditDetailPanel from '@/components/creater/edit-detail-panel'; +import EditCodePanel from '@/components/creater/edit-code-panel'; import { updateProblem } from '@/app/actions/updateProblem'; interface ProblemEditorPageProps { diff --git a/src/app/actions/getProblem.ts b/src/app/actions/getProblem.ts index 223f2eb..271e1fe 100644 --- a/src/app/actions/getProblem.ts +++ b/src/app/actions/getProblem.ts @@ -2,25 +2,18 @@ 'use server'; import prisma from '@/lib/prisma'; -import { Locale } from '@/generated/client'; import { serialize } from 'next-mdx-remote/serialize'; -export async function getProblemData(problemId: string, locale?: string) { - const selectedLocale = locale as Locale; - +export async function getProblemData(problemId: string) { const problem = await prisma.problem.findUnique({ where: { id: problemId }, include: { + localizations: true, templates: true, testcases: { include: { inputs: true } - }, - localizations: { - where: { - locale: selectedLocale, - }, - }, - }, + } + } }); if (!problem) { @@ -32,7 +25,9 @@ export async function getProblemData(problemId: string, locale?: string) { const rawDescription = getContent('DESCRIPTION'); + // MDX序列化,给客户端渲染用 const mdxDescription = await serialize(rawDescription, { + // 可以根据需要添加MDX插件配置 parseFrontmatter: false, }); @@ -45,19 +40,19 @@ export async function getProblemData(problemId: string, locale?: string) { memoryLimit: problem.memoryLimit, title: getContent('TITLE'), description: rawDescription, - mdxDescription, + mdxDescription, // 新增序列化后的字段 solution: getContent('SOLUTION'), templates: problem.templates.map(t => ({ language: t.language, - content: t.content, + content: t.content })), testcases: problem.testcases.map(tc => ({ id: tc.id, expectedOutput: tc.expectedOutput, inputs: tc.inputs.map(input => ({ name: input.name, - value: input.value, - })), - })), + value: input.value + })) + })) }; } diff --git a/src/components/creater/edit-code-panel.tsx b/src/components/creater/edit-code-panel.tsx index faeacfe..5479e92 100644 --- a/src/components/creater/edit-code-panel.tsx +++ b/src/components/creater/edit-code-panel.tsx @@ -1,84 +1,121 @@ -"use client"; +'use client'; -import { useState } from "react"; -import { Label } from "@/components/ui/label"; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; -import { Button } from "@/components/ui/button"; +import { useEffect, useState } from 'react'; +import { getProblemData } from '@/app/actions/getProblem'; +import { Label } from '@/components/ui/label'; +import { Button } from '@/components/ui/button'; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { CoreEditor } from "@/components/core-editor"; interface Template { - id: string; language: string; - code: string; + content: string; } interface EditCodePanelProps { problemId: string; - onUpdate?: (data: { - content: string; - language: 'c' | 'cpp'; // 移除可选标记 - }) => void; + onUpdate?: (data: Template) => Promise<{ success: boolean }>; } -export const EditCodePanel = ({ - problemId, -}: EditCodePanelProps) => { - const [language, setLanguage] = useState("typescript"); - const [templates, setTemplates] = useState([ - { - id: "1", - language: "typescript", - code: `// TypeScript模板示例\nfunction twoSum(nums: number[], target: number): number[] {\n const map = new Map();\n for (let i = 0; i < nums.length; i++) {\n const complement = target - nums[i];\n if (map.has(complement)) {\n return [map.get(complement), i];\n }\n map.set(nums[i], i);\n }\n return [];\n}` - }, - { - id: "2", - language: "python", - code: "# Python模板示例\ndef two_sum(nums, target):\n num_dict = {}\n for i, num in enumerate(nums):\n complement = target - num\n if complement in num_dict:\n return [num_dict[complement], i]\n num_dict[num] = i\n return []" - } - ]); - - const currentTemplate = templates.find(t => t.language === language) || templates[0]; +// 模拟保存函数 +async function saveTemplate(data: Template): Promise<{ success: boolean }> { + try { + console.log('保存模板数据:', data); + await new Promise(resolve => setTimeout(resolve, 500)); + return { success: true }; + } catch { + return { success: false }; + } +} - const handleCodeChange = (value: string | undefined) => { - if (!value) return; - - setTemplates(templates.map(t => - t.language === language - ? { ...t, code: value } - : t - )); +export default function EditCodePanel({ problemId, onUpdate = saveTemplate }: EditCodePanelProps) { + const [codeTemplate, setCodeTemplate] = useState