mirror of
https://github.com/massbug/judge4c.git
synced 2025-05-17 23:12:23 +00:00
refactor(components): 重构 AI优化编辑器组件
-集成问题状态管理,使用 useProblem 钩子 - 添加语言服务器连接功能 - 优化代码编辑器配置和功能 - 保留原有 AI 优化功能
This commit is contained in:
parent
a559734c30
commit
027f0fa4e9
@ -1,11 +1,20 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useCallback } from "react";
|
import { useState } from "react";
|
||||||
import { DiffEditor } from "@monaco-editor/react";
|
import { DiffEditor } from "@monaco-editor/react";
|
||||||
import { optimizeCode } from "@/actions/ai-improve";
|
import { optimizeCode } from "@/actions/ai-improve";
|
||||||
import { OptimizeCodeInput } from "@/types/ai-improve";
|
import { OptimizeCodeInput } from "@/types/ai-improve";
|
||||||
import { Loading } from "@/components/loading";
|
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
|
import { highlighter } from "@/lib/shiki";
|
||||||
|
import type { editor } from "monaco-editor";
|
||||||
|
import { Loading } from "@/components/loading";
|
||||||
|
import { shikiToMonaco } from "@shikijs/monaco";
|
||||||
|
import { useProblem } from "@/hooks/use-problem";
|
||||||
|
import type { Monaco } from "@monaco-editor/react";
|
||||||
|
import { useCallback, useEffect, useRef } from "react";
|
||||||
|
import { connectToLanguageServer } from "@/lib/language-server";
|
||||||
|
import type { MonacoLanguageClient } from "monaco-languageclient";
|
||||||
|
import { DefaultEditorOptionConfig } from "@/config/editor-option";
|
||||||
|
|
||||||
// 动态导入Monaco Editor
|
// 动态导入Monaco Editor
|
||||||
const Editor = dynamic(
|
const Editor = dynamic(
|
||||||
@ -59,20 +68,102 @@ export function AIProblemEditor({
|
|||||||
problemId?: string;
|
problemId?: string;
|
||||||
onCodeChange?: (code: string) => void;
|
onCodeChange?: (code: string) => void;
|
||||||
}) {
|
}) {
|
||||||
|
const {
|
||||||
|
editor,
|
||||||
|
setEditor,
|
||||||
|
setMarkers,
|
||||||
|
setWebSocket,
|
||||||
|
currentLang,
|
||||||
|
currentPath,
|
||||||
|
currentTheme,
|
||||||
|
currentValue,
|
||||||
|
changeValue,
|
||||||
|
currentEditorLanguageConfig,
|
||||||
|
currentLanguageServerConfig,
|
||||||
|
} = useProblem();
|
||||||
|
|
||||||
|
const monacoLanguageClientRef = useRef<MonacoLanguageClient | null>(null);
|
||||||
|
|
||||||
|
// 保持原有AI优化的状态
|
||||||
const [showDiff, setShowDiff] = useState(false);
|
const [showDiff, setShowDiff] = useState(false);
|
||||||
const [optimizedCode, setOptimizedCode] = useState("");
|
const [optimizedCode, setOptimizedCode] = useState("");
|
||||||
const [isOptimizing, setIsOptimizing] = useState(false);
|
const [isOptimizing, setIsOptimizing] = useState(false);
|
||||||
const [currentCode, setCurrentCode] = useState(initialCode);
|
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
|
||||||
|
// 重用useProblem的状态管理
|
||||||
|
const currentCode = currentValue || initialCode;
|
||||||
|
|
||||||
const handleCodeChange = useCallback((value: string | undefined) => {
|
const handleCodeChange = useCallback((value: string | undefined) => {
|
||||||
if (value !== undefined) {
|
if (value !== undefined) {
|
||||||
setCurrentCode(value);
|
changeValue(value);
|
||||||
if (onCodeChange) {
|
if (onCodeChange) {
|
||||||
onCodeChange(value);
|
onCodeChange(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [onCodeChange]);
|
}, [onCodeChange, changeValue]);
|
||||||
|
|
||||||
|
// 保持原有LSP连接逻辑
|
||||||
|
const connectLSP = useCallback(async () => {
|
||||||
|
if (!(currentLang && editor)) return;
|
||||||
|
|
||||||
|
if (monacoLanguageClientRef.current) {
|
||||||
|
monacoLanguageClientRef.current.stop();
|
||||||
|
monacoLanguageClientRef.current = null;
|
||||||
|
setWebSocket(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!currentEditorLanguageConfig || !currentLanguageServerConfig) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { client: monacoLanguageClient, webSocket } = await connectToLanguageServer(
|
||||||
|
currentEditorLanguageConfig,
|
||||||
|
currentLanguageServerConfig
|
||||||
|
);
|
||||||
|
monacoLanguageClientRef.current = monacoLanguageClient;
|
||||||
|
setWebSocket(webSocket);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to connect to LSP:", error);
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
currentEditorLanguageConfig,
|
||||||
|
currentLang,
|
||||||
|
currentLanguageServerConfig,
|
||||||
|
editor,
|
||||||
|
setWebSocket,
|
||||||
|
]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
connectLSP();
|
||||||
|
}, [connectLSP]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
if (monacoLanguageClientRef.current) {
|
||||||
|
monacoLanguageClientRef.current.stop();
|
||||||
|
monacoLanguageClientRef.current = null;
|
||||||
|
setWebSocket(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [setWebSocket]);
|
||||||
|
|
||||||
|
const handleEditorWillMount = useCallback((monaco: Monaco) => {
|
||||||
|
shikiToMonaco(highlighter, monaco);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleOnMount = useCallback(
|
||||||
|
async (editor: editor.IStandaloneCodeEditor) => {
|
||||||
|
setEditor(editor);
|
||||||
|
await connectLSP();
|
||||||
|
},
|
||||||
|
[setEditor, connectLSP]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleEditorValidation = useCallback(
|
||||||
|
(markers: editor.IMarker[]) => {
|
||||||
|
setMarkers(markers);
|
||||||
|
},
|
||||||
|
[setMarkers]
|
||||||
|
);
|
||||||
|
|
||||||
const handleOptimizeCode = useCallback(async () => {
|
const handleOptimizeCode = useCallback(async () => {
|
||||||
if (!currentCode || !problemId) return;
|
if (!currentCode || !problemId) return;
|
||||||
@ -99,6 +190,7 @@ export function AIProblemEditor({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col h-full w-full">
|
<div className="flex flex-col h-full w-full">
|
||||||
|
{/* 保持原有AI优化按钮 */}
|
||||||
<div className="flex justify-between items-center p-4">
|
<div className="flex justify-between items-center p-4">
|
||||||
<button
|
<button
|
||||||
onClick={handleOptimizeCode}
|
onClick={handleOptimizeCode}
|
||||||
@ -129,8 +221,8 @@ export function AIProblemEditor({
|
|||||||
<DiffEditor
|
<DiffEditor
|
||||||
original={currentCode}
|
original={currentCode}
|
||||||
modified={optimizedCode}
|
modified={optimizedCode}
|
||||||
language="typescript"
|
language={currentLang}
|
||||||
theme="vs-dark"
|
theme={currentTheme}
|
||||||
className="h-full w-full"
|
className="h-full w-full"
|
||||||
options={{
|
options={{
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
@ -139,14 +231,16 @@ export function AIProblemEditor({
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Editor
|
<Editor
|
||||||
language="typescript"
|
language={currentLang}
|
||||||
theme="vs-dark"
|
theme={currentTheme}
|
||||||
|
path={currentPath}
|
||||||
value={currentCode}
|
value={currentCode}
|
||||||
|
beforeMount={handleEditorWillMount}
|
||||||
|
onMount={handleOnMount}
|
||||||
onChange={handleCodeChange}
|
onChange={handleCodeChange}
|
||||||
options={{
|
onValidate={handleEditorValidation}
|
||||||
scrollBeyondLastLine: false,
|
options={DefaultEditorOptionConfig}
|
||||||
fontSize: 14
|
loading={<Loading />}
|
||||||
}}
|
|
||||||
className="h-full w-full"
|
className="h-full w-full"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
Loading…
Reference in New Issue
Block a user