From 6b84a5ed982a50236368c3a30591be35b0cc6dd4 Mon Sep 17 00:00:00 2001 From: join_zhong Date: Thu, 16 Oct 2025 23:25:17 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E8=B7=AF=E7=94=B1=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 创建 router.js 统一管理路由配置 - App.jsx 重构为使用 RouterProvider - 创建 pages 目录结构: - Layout.jsx: 主布局组件,包含 header 和 footer - Home.jsx: 首页实验列表(原 App.jsx 内容) - ExperimentDetail.jsx: 实验详情页,展示完整实验信息 - NotFound.jsx: 404 页面 - 实现页面导航功能: - 点击实验项目可跳转到详情页 - 详情页支持返回列表 - 完善的错误处理和 404 页面 - 实验详情页功能: - 展示实验目标、步骤、注意事项 - 实验信息卡片(时长、难度、类型) - 交互式按钮(开始实验、下载资料) - 所有代码通过 ESLint 检查 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/App.jsx | 116 +------------------- src/pages/ExperimentDetail.jsx | 190 +++++++++++++++++++++++++++++++++ src/pages/Home.jsx | 107 +++++++++++++++++++ src/pages/Layout.jsx | 30 ++++++ src/pages/NotFound.jsx | 37 +++++++ src/router.js | 33 ++++++ 6 files changed, 400 insertions(+), 113 deletions(-) create mode 100644 src/pages/ExperimentDetail.jsx create mode 100644 src/pages/Home.jsx create mode 100644 src/pages/Layout.jsx create mode 100644 src/pages/NotFound.jsx create mode 100644 src/router.js diff --git a/src/App.jsx b/src/App.jsx index 05638e3..e521be4 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,118 +1,8 @@ -import { useState, useEffect } from 'react'; -import { - DndContext, - closestCenter, - KeyboardSensor, - PointerSensor, - useSensor, - useSensors, -} from '@dnd-kit/core'; -import { - arrayMove, - SortableContext, - sortableKeyboardCoordinates, - verticalListSortingStrategy, -} from '@dnd-kit/sortable'; -import { DraggableItem } from './components/DraggableItem'; -import { Cpu } from 'lucide-react'; -import { - defaultExperiments, - loadExperimentsFromStorage, - saveExperimentsToStorage, -} from './data/experiments'; +import { RouterProvider } from 'react-router-dom'; +import router from './router'; function App() { - // 从 localStorage 加载数据,如果没有则使用默认数据 - const [experiments, setExperiments] = useState(() => { - return loadExperimentsFromStorage() || defaultExperiments; - }); - - // 当实验数据变化时,保存到 localStorage - useEffect(() => { - saveExperimentsToStorage(experiments); - }, [experiments]); - - const sensors = useSensors( - useSensor(PointerSensor), - useSensor(KeyboardSensor, { - coordinateGetter: sortableKeyboardCoordinates, - }) - ); - - function handleDragEnd(event) { - const { active, over } = event; - - if (over && active.id !== over.id) { - setExperiments((items) => { - const oldIndex = items.findIndex((item) => item.id === active.id); - const newIndex = items.findIndex((item) => item.id === over.id); - return arrayMove(items, oldIndex, newIndex); - }); - } - } - - return ( -
-
-
-
- -

- 传感器及检测技术 -

-
-

实验课件交互式平台

-
- -
-
-

- 实验项目列表 -

-

- 拖动实验项目可以调整顺序,规划您的学习路径 -

- - - - {experiments.map((experiment, index) => { - const Icon = experiment.icon; - return ( - -
-
- -
-
-

- {index + 1}. {experiment.name} -

-

- {experiment.description} -

-
-
-
- ); - })} -
-
-
- -
-

使用现代化技术构建 • React + Vite + Tailwind CSS

-
-
-
-
- ); + return ; } export default App; diff --git a/src/pages/ExperimentDetail.jsx b/src/pages/ExperimentDetail.jsx new file mode 100644 index 0000000..3dccd5c --- /dev/null +++ b/src/pages/ExperimentDetail.jsx @@ -0,0 +1,190 @@ +import { useParams, useNavigate, Link } from 'react-router-dom'; +import { ArrowLeft, BookOpen, Target, Clock, FileText } from 'lucide-react'; +import { defaultExperiments } from '../data/experiments'; + +export default function ExperimentDetail() { + const { id } = useParams(); + const navigate = useNavigate(); + + const experiment = defaultExperiments.find((exp) => exp.id === id); + + if (!experiment) { + return ( +
+
+

实验不存在

+

抱歉,未找到该实验项目。

+ + + 返回首页 + +
+
+ ); + } + + const Icon = experiment.icon; + + return ( +
+ + +
+ {/* 实验头部 */} +
+
+
+ +
+
+

{experiment.name}

+

{experiment.description}

+
+
+
+ + {/* 实验内容 */} +
+ {/* 实验信息卡片 */} +
+
+
+ +

实验时长

+
+

约 2-3 小时

+
+ +
+
+ +

难度等级

+
+

中级

+
+ +
+
+ +

实验类型

+
+

综合实验

+
+
+ + {/* 实验目标 */} +
+
+ +

实验目标

+
+
    +
  • + • + 理解传感器的基本工作原理和测量特性 +
  • +
  • + • + 掌握传感器的校准和标定方法 +
  • +
  • + • + 学习数据采集和处理的基本技术 +
  • +
  • + • + 分析实验结果并撰写实验报告 +
  • +
+
+ + {/* 实验步骤 */} +
+
+ +

实验步骤

+
+
+
+

+ 步骤 1: 实验准备 +

+

+ 检查实验设备和仪器,确保传感器连接正确,熟悉实验操作流程。 +

+
+ +
+

+ 步骤 2: 传感器校准 +

+

+ 使用标准信号源对传感器进行校准,记录校准数据并绘制校准曲线。 +

+
+ +
+

+ 步骤 3: 数据采集 +

+

+ 按照实验要求进行数据采集,注意记录环境条件和测量参数。 +

+
+ +
+

+ 步骤 4: 数据分析 +

+

+ 对采集的数据进行处理和分析,计算传感器的性能参数。 +

+
+ +
+

+ 步骤 5: 撰写报告 +

+

+ 整理实验数据和分析结果,撰写完整的实验报告。 +

+
+
+
+ + {/* 注意事项 */} +
+

注意事项

+
+
    +
  • • 实验前请仔细阅读实验指导书和安全操作规程
  • +
  • • 注意保护传感器,避免过载和损坏
  • +
  • • 数据记录要准确完整,便于后续分析
  • +
  • • 实验结束后及时整理设备和清理实验台
  • +
+
+
+ + {/* 操作按钮 */} +
+ + +
+
+
+
+ ); +} diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx new file mode 100644 index 0000000..090a29e --- /dev/null +++ b/src/pages/Home.jsx @@ -0,0 +1,107 @@ +import { useState, useEffect } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { + DndContext, + closestCenter, + KeyboardSensor, + PointerSensor, + useSensor, + useSensors, +} from '@dnd-kit/core'; +import { + arrayMove, + SortableContext, + sortableKeyboardCoordinates, + verticalListSortingStrategy, +} from '@dnd-kit/sortable'; +import { DraggableItem } from '../components/DraggableItem'; +import { + defaultExperiments, + loadExperimentsFromStorage, + saveExperimentsToStorage, +} from '../data/experiments'; + +export default function Home() { + const navigate = useNavigate(); + + // 从 localStorage 加载数据,如果没有则使用默认数据 + const [experiments, setExperiments] = useState(() => { + return loadExperimentsFromStorage() || defaultExperiments; + }); + + // 当实验数据变化时,保存到 localStorage + useEffect(() => { + saveExperimentsToStorage(experiments); + }, [experiments]); + + const sensors = useSensors( + useSensor(PointerSensor), + useSensor(KeyboardSensor, { + coordinateGetter: sortableKeyboardCoordinates, + }) + ); + + function handleDragEnd(event) { + const { active, over } = event; + + if (over && active.id !== over.id) { + setExperiments((items) => { + const oldIndex = items.findIndex((item) => item.id === active.id); + const newIndex = items.findIndex((item) => item.id === over.id); + return arrayMove(items, oldIndex, newIndex); + }); + } + } + + function handleExperimentClick(id) { + navigate(`/experiment/${id}`); + } + + return ( +
+
+

+ 实验项目列表 +

+

+ 拖动实验项目可以调整顺序,规划您的学习路径。点击项目查看详情。 +

+ + + + {experiments.map((experiment, index) => { + const Icon = experiment.icon; + return ( + +
handleExperimentClick(experiment.id)} + > +
+ +
+
+

+ {index + 1}. {experiment.name} +

+

+ {experiment.description} +

+
+
+
+ ); + })} +
+
+
+
+ ); +} diff --git a/src/pages/Layout.jsx b/src/pages/Layout.jsx new file mode 100644 index 0000000..c4a5c3f --- /dev/null +++ b/src/pages/Layout.jsx @@ -0,0 +1,30 @@ +import { Outlet, Link } from 'react-router-dom'; +import { Cpu } from 'lucide-react'; + +export default function Layout() { + return ( +
+
+
+ +
+ +

+ 传感器及检测技术 +

+
+ +

实验课件交互式平台

+
+ +
+ +
+ +
+

使用现代化技术构建 • React + Vite + Tailwind CSS

+
+
+
+ ); +} diff --git a/src/pages/NotFound.jsx b/src/pages/NotFound.jsx new file mode 100644 index 0000000..987f7e1 --- /dev/null +++ b/src/pages/NotFound.jsx @@ -0,0 +1,37 @@ +import { Link } from 'react-router-dom'; +import { Home, ArrowLeft } from 'lucide-react'; + +export default function NotFound() { + return ( +
+
+
+

404

+

+ 页面未找到 +

+

+ 抱歉,您访问的页面不存在或已被移除。 +

+
+ +
+ + + 返回首页 + + +
+
+
+ ); +} diff --git a/src/router.js b/src/router.js new file mode 100644 index 0000000..a94110f --- /dev/null +++ b/src/router.js @@ -0,0 +1,33 @@ +import { createBrowserRouter } from 'react-router-dom'; +import Layout from './pages/Layout'; +import Home from './pages/Home'; +import ExperimentDetail from './pages/ExperimentDetail'; +import NotFound from './pages/NotFound'; + +/** + * 应用路由配置 + * 使用 React Router v7 的 createBrowserRouter + */ +const router = createBrowserRouter([ + { + path: '/', + element: , + errorElement: , + children: [ + { + index: true, + element: , + }, + { + path: 'experiment/:id', + element: , + }, + ], + }, + { + path: '*', + element: , + }, +]); + +export default router;