diff --git a/backend/agent/basicAgent.go b/backend/agent/basicAgent.go index e319a86..4e96fba 100644 --- a/backend/agent/basicAgent.go +++ b/backend/agent/basicAgent.go @@ -100,6 +100,8 @@ func CallWithAgentDefined[T any](llm llms.Model, ctx context.Context, topic stri "用户正在学习Go语言和React框架,你是用户的助手。\n"+prompt, ) + fmt.Printf("Raw output: %v\n\n", responseString) + if err != nil { log.Fatal(err) } diff --git a/backend/handlers/agent.go b/backend/handlers/agent.go index cee35ba..d14e2c9 100644 --- a/backend/handlers/agent.go +++ b/backend/handlers/agent.go @@ -33,8 +33,8 @@ func GetQuiz(llm llms.Model, ctx context.Context, topic string) (response respon return } -func GetScenario(llm llms.Model, ctx context.Context, topic string) (response response_struct.Scenario) { +func GetScenario(llm llms.Model, ctx context.Context, topic string) (response response_struct.ScenarioResponse) { file := files[3] - response = agent.CallWithAgentDefined(llm, ctx, topic, file, response_struct.Scenario{}) + response = agent.CallWithAgentDefined(llm, ctx, topic, file, response_struct.ScenarioResponse{}) return } diff --git a/backend/response_struct/response_test.go b/backend/response_struct/response_test.go index a129ff7..e43152f 100644 --- a/backend/response_struct/response_test.go +++ b/backend/response_struct/response_test.go @@ -40,7 +40,7 @@ func TestQuiz(t *testing.T) { } func TestScenario(t *testing.T) { - definedScenario, err := outputparser.NewDefined(Scenario{}) + definedScenario, err := outputparser.NewDefined(ScenarioResponse{}) if err != nil { t.Fatalf("%v", err) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 414f0cd..20d9c9b 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -4,6 +4,7 @@ import Card from "./components/Card"; import Guodegang from "./components/Guodegang"; import Quiz from "./components/Quiz"; import Topic from "./components/Topic"; +import Scenario from "./components/Scenario"; /* eslint-disable @typescript-eslint/no-explicit-any */ function App() { @@ -17,18 +18,24 @@ function App() { const [quizData, setQuizData]: any = useState(null); const [quizLoading, setQuizLoading] = useState(false); const [quizError, setQuizError] = useState(null); + const [scenarioData, setScenarioData]: any = useState(null); + const [scenarioLoading, setScenarioLoading] = useState(false); + const [scenarioError, setScenarioError] = useState(null); const fetchData = async (topicToFetch: string) => { setCardLoading(true); setGuodegangLoading(true); setQuizLoading(true); + setScenarioLoading(true); setCardError(null); setGuodegangError(null); setQuizError(null); + setScenarioError(null); const cardUrl = `http://localhost:8080/card/${encodeURIComponent(topicToFetch)}`; const guodegangUrl = `http://localhost:8080/guodegang/${encodeURIComponent(topicToFetch)}`; const quizUrl = `http://localhost:8080/quiz/${encodeURIComponent(topicToFetch)}`; + const scenarioUrl = `http://localhost:8080/scenario/${encodeURIComponent(topicToFetch)}`; const abortController = new AbortController(); const timeoutId = setTimeout(() => abortController.abort(), 300000); @@ -75,7 +82,21 @@ function App() { } }; - Promise.allSettled([fetchCard(), fetchGuodegang(), fetchQuiz()]).finally(() => { + const fetchScenario = async () => { + try { + const response = await fetch(scenarioUrl, { signal: abortController.signal }); + if (!response.ok) throw new Error(`Scenario API failed: ${response.status}`); + const result = await response.json(); + setScenarioData(result.message); + } catch (error) { + console.error("Error fetching scenario data:", error); + setScenarioError("Failed to load scenario data"); + } finally { + setScenarioLoading(false); + } + }; + + Promise.allSettled([fetchCard(), fetchGuodegang(), fetchQuiz(), fetchScenario()]).finally(() => { clearTimeout(timeoutId); }); }; @@ -90,11 +111,12 @@ function App() { const cardLoaded = !cardLoading && !!cardData; const guodegangLoaded = !guodegangLoading && !!guodegangData; const quizLoaded = !quizLoading && !!quizData; + const scenarioLoaded = !scenarioLoading && !!scenarioData; const progress = (() => { if (!topic) return 0; - const loadedCount = [cardLoaded, guodegangLoaded, quizLoaded].filter(Boolean).length; - return Math.round((loadedCount / 3) * 100); + const loadedCount = [cardLoaded, guodegangLoaded, quizLoaded, scenarioLoaded].filter(Boolean).length; + return Math.round((loadedCount / 4) * 100); })(); return ( @@ -130,6 +152,11 @@ function App() { 📝 测验问答 + + + + 💡 工程场景 + @@ -141,6 +168,9 @@ function App() { + + + diff --git a/frontend/src/components/Scenario.tsx b/frontend/src/components/Scenario.tsx new file mode 100644 index 0000000..000d0f2 --- /dev/null +++ b/frontend/src/components/Scenario.tsx @@ -0,0 +1,198 @@ +import { useState } from "react"; +import { Card, Chip } from "@heroui/react"; + +interface Scenario { + name: string; + background: string; + solution: string; + code_example: string; + core_problem_solved: string; + key_considerations: string[]; +} + +interface ScenarioData { + scenarios: Scenario[]; +} + +interface Props { + topic: string; + data: ScenarioData | null; + loading: boolean; + error: string | null; +} + +export default function Scenario({ topic, data, loading, error }: Props) { + const [expandedIndex, setExpandedIndex] = useState(null); + + const toggleScenario = (index: number) => { + setExpandedIndex(expandedIndex === index ? null : index); + }; + + if (loading) { + return ( +
+ +
Loading...
+
+
+ ); + } + + if (error) { + return ( +
+ +
{error}
+
+
+ ); + } + + if (!topic || !data || data.scenarios.length === 0) { + return ( +
+ +
+ 💡 +
+
+
🌟
+
工程应用场景
+
输入主题后,这里将展示相关的工程应用场景和最佳实践
+
+
+
+ ); + } + + return ( +
+ +
+ 💡 +
+ +
+
+ + {topic} - 工程场景 + +
+

+ 以下是该知识点的实际工程应用场景,帮助你理解如何在真实项目中使用 +

+
+ +
+ {data.scenarios.map((scenario, index) => { + const isExpanded = expandedIndex === index; + return ( +
+ + +
+
+
+

+ 📋 + 问题背景 +

+

+ {scenario.background} +

+
+ +
+

+ 💡 + 解决方案 +

+

+ {scenario.solution} +

+
+ +
+

+ 💻 + 代码示例 +

+
+
+                            {scenario.code_example}
+                          
+
+
+ +
+

+ 🎯 + 核心问题解决 +

+

+ {scenario.core_problem_solved} +

+
+ +
+

+ ⚠️ + 注意事项与最佳实践 +

+
    + {scenario.key_considerations.map((consideration, considerationIndex) => ( +
  • + + • + + + {consideration} + +
  • + ))} +
+
+
+
+
+ ); + })} +
+
+
+
+ ); +}