diff --git a/backend/response_struct/allstruct.go b/backend/response_struct/allstruct.go deleted file mode 100644 index a9c0038..0000000 --- a/backend/response_struct/allstruct.go +++ /dev/null @@ -1,9 +0,0 @@ -package response_struct - -type AllStruct struct { - CardStruct Card `json:"card"` - GuodegangStruct Guodegang `json:"guodegang"` - MermaidStruct Mermaid `json:"mermaid"` - QuizStruct Quiz `json:"quiz"` - ScenarioStruct Scenario `json:"scenario"` -} \ No newline at end of file diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index c1436ad..cee9c19 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,18 +1,45 @@ +import { useState, useEffect } from "react"; +import { ProgressBar, Label } from "@heroui/react"; import Card from "./components/Card"; import Guodegang from "./components/Guodegang"; -import { Surface } from "@heroui/react"; +import Topic from "./components/Topic"; function App() { + const [topic, setTopic] = useState(''); + const [cardLoaded, setCardLoaded] = useState(false); + const [guodegangLoaded, setGuodegangLoaded] = useState(false); + + useEffect(() => { + setCardLoaded(false); + setGuodegangLoaded(false); + }, [topic]); + + const progress = (() => { + if (!topic) return 0; + if (cardLoaded && guodegangLoaded) return 100; + if (cardLoaded || guodegangLoaded) return 50; + return 10; + })(); + return ( - <> - - - - - +
+ + {topic && ( +
+ + + + + + + +
+ )} +
+ + +
+
); } diff --git a/frontend/src/components/Card.tsx b/frontend/src/components/Card.tsx index 8e1b415..87a4e2e 100644 --- a/frontend/src/components/Card.tsx +++ b/frontend/src/components/Card.tsx @@ -51,14 +51,20 @@ interface CardData { interface Props { topic: string; + onLoaded?: (loaded: boolean) => void; } -export default function Default({ topic }: Props) { +export default function Default({ topic, onLoaded }: Props) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { + if (!topic) { + onLoaded?.(false); + setLoading(false); + return; + } const fetchData = async () => { try { const response = await fetch( @@ -75,10 +81,12 @@ export default function Default({ topic }: Props) { setError("Failed to load data. Please try again."); } finally { setLoading(false); + onLoaded?.(true); } }; + setLoading(true); fetchData(); - }, [topic]); + }, [topic, onLoaded]); if (loading) { return ( @@ -100,6 +108,23 @@ export default function Default({ topic }: Props) { ); } + if (!topic || !data) { + return ( +
+ +
+ 🧐 +
+
+
📚
+
学习卡片组件
+
输入主题后,这里将展示相关的核心知识点、常见误解和最佳实践
+
+
+
+ ); + } + return (
diff --git a/frontend/src/components/Guodegang.tsx b/frontend/src/components/Guodegang.tsx index 4a8d9fe..07c102d 100644 --- a/frontend/src/components/Guodegang.tsx +++ b/frontend/src/components/Guodegang.tsx @@ -8,14 +8,20 @@ interface GuodegangData { interface Props { topic: string; + onLoaded?: (loaded: boolean) => void; } -export default function Guodegang({ topic }: Props) { +export default function Guodegang({ topic, onLoaded }: Props) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { + if (!topic) { + onLoaded?.(false); + setLoading(false); + return; + } const fetchData = async () => { try { const response = await fetch( @@ -32,10 +38,12 @@ export default function Guodegang({ topic }: Props) { setError("Failed to load data. Please try again."); } finally { setLoading(false); + onLoaded?.(true); } }; + setLoading(true); fetchData(); - }, [topic]); + }, [topic, onLoaded]); if (loading) { return ( @@ -57,6 +65,23 @@ export default function Guodegang({ topic }: Props) { ); } + if (!topic || !data) { + return ( +
+ +
+ 🎤 +
+
+
🎭
+
德云社风格讲解
+
输入主题后,这里将用相声的生动语言为您讲解知识点
+
+
+
+ ); + } + return (
diff --git a/frontend/src/components/Topic.tsx b/frontend/src/components/Topic.tsx new file mode 100644 index 0000000..8204db8 --- /dev/null +++ b/frontend/src/components/Topic.tsx @@ -0,0 +1,42 @@ +import { Input, Button } from '@heroui/react'; +import { useState } from 'react'; + +interface Props { + onTopicSubmit: (topic: string) => void; +} + +export default function Default({ onTopicSubmit }: Props) { + const [value, setValue] = useState(''); + + const handleSubmit = () => { + if (value.trim()) { + onTopicSubmit(value); + } + }; + + const handleKeyPress = (e: React.KeyboardEvent) => { + if (e.key === 'Enter') { + handleSubmit(); + } + }; + + return ( +
+ setValue(e.target.value)} + onKeyPress={handleKeyPress} + /> + +
+ ); +} \ No newline at end of file