From 9b231cc5e548dcb9d4bbd0a1cd853112a95e874c Mon Sep 17 00:00:00 2001 From: cfngc4594 Date: Fri, 20 Jun 2025 23:36:44 +0800 Subject: [PATCH] refactor(creater): wrap Panel with PanelLayout and ScrollArea --- src/components/creater/edit-code-panel.tsx | 99 ++++---- .../creater/edit-description-panel.tsx | 225 +++++++++--------- src/components/creater/edit-detail-panel.tsx | 171 ++++++------- .../creater/edit-solution-panel.tsx | 224 ++++++++--------- .../creater/edit-testcase-panel.tsx | 179 +++++++------- .../admin/ui/views/problem-edit-view.tsx | 2 +- src/stores/flexlayout.ts | 14 +- 7 files changed, 480 insertions(+), 434 deletions(-) diff --git a/src/components/creater/edit-code-panel.tsx b/src/components/creater/edit-code-panel.tsx index b151d54..581a497 100644 --- a/src/components/creater/edit-code-panel.tsx +++ b/src/components/creater/edit-code-panel.tsx @@ -1,14 +1,16 @@ "use client"; -import React, { useEffect, useState } from "react"; -import { getProblemData } from "@/app/actions/getProblem"; -import { updateProblemTemplate } from "@/components/creater/problem-maintain"; -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"; -import { Language } from "@/generated/client"; import { toast } from "sonner"; +import { Label } from "@/components/ui/label"; +import { Language } from "@/generated/client"; +import { Button } from "@/components/ui/button"; +import React, { useEffect, useState } from "react"; +import { CoreEditor } from "@/components/core-editor"; +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"; interface Template { language: string; @@ -67,45 +69,50 @@ export default function EditCodePanel({ problemId }: EditCodePanelProps) { }; return ( - - - 代码模板 - - -
-
- - -
- -
- -
- - setCodeTemplate({ ...codeTemplate, content: value || "" }) - } - /> + + + + +
+ 代码模板 +
-
+ + +
+
+ + +
- -
-
- +
+ +
+ + setCodeTemplate({ ...codeTemplate, content: value || "" }) + } + /> +
+
+
+ + + + ); } diff --git a/src/components/creater/edit-description-panel.tsx b/src/components/creater/edit-description-panel.tsx index 1ff7456..94a93ad 100644 --- a/src/components/creater/edit-description-panel.tsx +++ b/src/components/creater/edit-description-panel.tsx @@ -1,22 +1,24 @@ "use client"; -import React, { useEffect, useState } from "react"; +import { toast } from "sonner"; +import { Locale } from "@/generated/client"; 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 { CoreEditor } from "@/components/core-editor"; -import MdxPreview from "@/components/mdx-preview"; -import { getProblemData } from "@/app/actions/getProblem"; -import { getProblemLocales } from "@/app/actions/getProblemLocales"; -import { Accordion } from "@/components/ui/accordion"; -import { VideoEmbed } from "@/components/content/video-embed"; -import { toast } from "sonner"; import { updateProblemDescription, updateProblemTitle, } from "@/components/creater/problem-maintain"; -import { Locale } from "@/generated/client"; +import { Button } from "@/components/ui/button"; +import MdxPreview from "@/components/mdx-preview"; +import React, { useEffect, useState } from "react"; +import { Accordion } from "@/components/ui/accordion"; +import { CoreEditor } from "@/components/core-editor"; +import { ScrollArea } from "@/components/ui/scroll-area"; +import { getProblemData } from "@/app/actions/getProblem"; +import { VideoEmbed } from "@/components/content/video-embed"; +import { getProblemLocales } from "@/app/actions/getProblemLocales"; +import { PanelLayout } from "@/features/problems/layouts/panel-layout"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; export default function EditDescriptionPanel({ problemId, @@ -102,107 +104,114 @@ export default function EditDescriptionPanel({ }; return ( - - - 题目描述 - - - {/* 语言切换 */} -
- -
- - setCustomLocale(e.target.value)} - /> - -
-
+ + + + + 题目描述 + + + {/* 语言切换 */} +
+ +
+ + setCustomLocale(e.target.value)} + /> + +
+
- {/* 标题输入 */} -
- - - setDescription({ ...description, title: e.target.value }) - } - placeholder="输入题目标题" - /> -
- - {/* 编辑/预览切换 */} -
- - - -
- - {/* 编辑/预览区域 */} -
- {(viewMode === "edit" || viewMode === "compare") && ( -
- - setDescription({ ...description, content: newVal || "" }) + {/* 标题输入 */} +
+ + + setDescription({ ...description, title: e.target.value }) } - language="markdown" - className="absolute inset-0 rounded-md border border-input" + placeholder="输入题目标题" />
- )} - {viewMode !== "edit" && ( -
- -
- )} -
- - - + {/* 编辑/预览切换 */} +
+
+ + + +
+
+ +
+
+ + {/* 编辑/预览区域 */} +
+ {(viewMode === "edit" || viewMode === "compare") && ( +
+ + setDescription({ ...description, content: newVal || "" }) + } + language="markdown" + className="absolute inset-0 rounded-md border border-input" + /> +
+ )} + {viewMode !== "edit" && ( +
+ +
+ )} +
+ + + + ); } diff --git a/src/components/creater/edit-detail-panel.tsx b/src/components/creater/edit-detail-panel.tsx index b044d28..1021364 100644 --- a/src/components/creater/edit-detail-panel.tsx +++ b/src/components/creater/edit-detail-panel.tsx @@ -1,14 +1,16 @@ "use client"; -import React, { useState, useEffect } from "react"; +import { toast } from "sonner"; 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 { getProblemData } from "@/app/actions/getProblem"; -import { toast } from "sonner"; -import { updateProblemDetail } from "@/components/creater/problem-maintain"; import { Difficulty } from "@/generated/client"; +import React, { useState, useEffect } from "react"; +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 { updateProblemDetail } from "@/components/creater/problem-maintain"; export default function EditDetailPanel({ problemId }: { problemId: string }) { const [problemDetails, setProblemDetails] = useState({ @@ -77,84 +79,91 @@ export default function EditDetailPanel({ problemId }: { problemId: string }) { }; return ( - - - 题目详情 - - -
-
-
- - handleNumberInputChange(e, "displayId")} - placeholder="输入显示ID" - /> + + + + +
+ 题目详情 +
-
- - -
-
+ + +
+
+
+ + handleNumberInputChange(e, "displayId")} + placeholder="输入显示ID" + /> +
+
+ + +
+
-
-
- - handleNumberInputChange(e, "timeLimit")} - placeholder="输入时间限制" - /> -
-
- - handleNumberInputChange(e, "memoryLimit")} - placeholder="输入内存限制" - /> -
-
+
+
+ + handleNumberInputChange(e, "timeLimit")} + placeholder="输入时间限制" + /> +
+
+ + handleNumberInputChange(e, "memoryLimit")} + placeholder="输入内存限制" + /> +
+
-
- - setProblemDetails({ - ...problemDetails, - isPublished: e.target.checked, - }) - } - className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 focus:ring-2" - /> - -
- - -
-
- +
+
+ + setProblemDetails({ + ...problemDetails, + isPublished: e.target.checked, + }) + } + className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 focus:ring-2" + /> + +
+
+
+ + + + ); } diff --git a/src/components/creater/edit-solution-panel.tsx b/src/components/creater/edit-solution-panel.tsx index 4d92f00..1236e74 100644 --- a/src/components/creater/edit-solution-panel.tsx +++ b/src/components/creater/edit-solution-panel.tsx @@ -1,19 +1,21 @@ "use client"; -import React, { useEffect, useState } from "react"; +import { toast } from "sonner"; +import { Locale } from "@/generated/client"; 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 { CoreEditor } from "@/components/core-editor"; import MdxPreview from "@/components/mdx-preview"; -import { getProblemData } from "@/app/actions/getProblem"; -import { getProblemLocales } from "@/app/actions/getProblemLocales"; +import React, { useEffect, useState } from "react"; import { Accordion } from "@/components/ui/accordion"; +import { CoreEditor } from "@/components/core-editor"; +import { ScrollArea } from "@/components/ui/scroll-area"; +import { getProblemData } from "@/app/actions/getProblem"; import { VideoEmbed } from "@/components/content/video-embed"; -import { toast } from "sonner"; +import { getProblemLocales } from "@/app/actions/getProblemLocales"; +import { PanelLayout } from "@/features/problems/layouts/panel-layout"; import { updateProblemSolution } from "@/components/creater/problem-maintain"; -import { Locale } from "@/generated/client"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; export default function EditSolutionPanel({ problemId, @@ -93,112 +95,116 @@ export default function EditSolutionPanel({ }; return ( - - - 题目解析 - - - {/* 语言切换 */} -
- -
- - setCustomLocale(e.target.value)} - /> - -
-
+ + + + + 题目解析 + + + {/* 语言切换 */} +
+ +
+ + setCustomLocale(e.target.value)} + /> + +
+
- {/* 标题输入 (仅展示) */} -
- - - setSolution({ ...solution, title: e.target.value }) - } - placeholder="输入题解标题" - disabled - /> -
- - {/* 编辑/预览切换 */} -
- - - -
- - {/* 编辑/预览区域 */} -
- {(viewMode === "edit" || viewMode === "compare") && ( -
- - setSolution({ ...solution, content: val || "" }) + {/* 标题输入 (仅展示) */} +
+ + + setSolution({ ...solution, title: e.target.value }) } - language="markdown" - className="absolute inset-0 rounded-md border border-input" + placeholder="输入题解标题" + disabled />
- )} - {viewMode !== "edit" && ( -
- -
- )} -
- - - + {/* 编辑/预览切换 */} +
+ + + +
+ + {/* 编辑/预览区域 */} +
+ {(viewMode === "edit" || viewMode === "compare") && ( +
+ + setSolution({ ...solution, content: val || "" }) + } + language="markdown" + className="absolute inset-0 rounded-md border border-input" + /> +
+ )} + {viewMode !== "edit" && ( +
+ +
+ )} +
+ + + + + + ); } diff --git a/src/components/creater/edit-testcase-panel.tsx b/src/components/creater/edit-testcase-panel.tsx index 24f75d1..a534260 100644 --- a/src/components/creater/edit-testcase-panel.tsx +++ b/src/components/creater/edit-testcase-panel.tsx @@ -1,18 +1,20 @@ "use client"; -import React, { useState, useEffect } from "react"; -import { generateAITestcase } from "@/app/actions/ai-testcase"; -import { getProblemData } from "@/app/actions/getProblem"; +import { toast } from "sonner"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; 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"; +import React, { useState, useEffect } from "react"; +import { ScrollArea } from "@/components/ui/scroll-area"; +import { getProblemData } from "@/app/actions/getProblem"; +import { generateAITestcase } from "@/app/actions/ai-testcase"; +import { Card, CardContent, CardHeader } from "@/components/ui/card"; +import { PanelLayout } from "@/features/problems/layouts/panel-layout"; interface Testcase { id: string; @@ -182,82 +184,95 @@ export default function EditTestcasePanel({ }; 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 && ( - - )} -
- ))}
-
- ))} - - + + + {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 && ( + + )} +
+ ))} +
+
+ ))} +
+ + + ); } diff --git a/src/features/admin/ui/views/problem-edit-view.tsx b/src/features/admin/ui/views/problem-edit-view.tsx index add476f..57e17a3 100644 --- a/src/features/admin/ui/views/problem-edit-view.tsx +++ b/src/features/admin/ui/views/problem-edit-view.tsx @@ -11,9 +11,9 @@ interface ProblemEditViewProps { export const ProblemEditView = ({ problemId }: ProblemEditViewProps) => { const components: Record = { + detail: , description: , solution: , - detail: , code: , testcase: , }; diff --git a/src/stores/flexlayout.ts b/src/stores/flexlayout.ts index 439013f..35c360e 100644 --- a/src/stores/flexlayout.ts +++ b/src/stores/flexlayout.ts @@ -144,6 +144,13 @@ const initialProblemEditFlexLayoutJsonModel: IJsonModel = { id: "1", weight: 50, children: [ + { + type: "tab", + id: "detail", + name: "Details", + component: "detail", + enableClose: false, + }, { type: "tab", id: "description", @@ -158,13 +165,6 @@ const initialProblemEditFlexLayoutJsonModel: IJsonModel = { component: "solution", enableClose: false, }, - { - type: "tab", - id: "detail", - name: "Details", - component: "detail", - enableClose: false, - }, ], }, {