diff --git a/src/frontend/package.json b/src/frontend/package.json
index 391129e..2a32a7b 100644
--- a/src/frontend/package.json
+++ b/src/frontend/package.json
@@ -12,9 +12,11 @@
"@testing-library/user-event": "^13.5.0",
"axios": "^1.9.0",
"framer-motion": "^12.14.0",
+ "next-themes": "^0.4.6",
"prettierrc": "0.0.0-5",
"react": "^19.1.0",
"react-dom": "^19.1.0",
+ "react-icons": "^5.5.0",
"react-router-dom": "^7.6.1",
"react-scripts": "^5.0.1",
"recharts": "^2.15.3",
diff --git a/src/frontend/pnpm-lock.yaml b/src/frontend/pnpm-lock.yaml
index 174c7a0..1473485 100644
--- a/src/frontend/pnpm-lock.yaml
+++ b/src/frontend/pnpm-lock.yaml
@@ -35,6 +35,9 @@ importers:
framer-motion:
specifier: ^12.14.0
version: 12.15.0(@emotion/is-prop-valid@1.3.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ next-themes:
+ specifier: ^0.4.6
+ version: 0.4.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
prettierrc:
specifier: 0.0.0-5
version: 0.0.0-5(prettier@1.19.1)
@@ -44,6 +47,9 @@ importers:
react-dom:
specifier: ^19.1.0
version: 19.1.0(react@19.1.0)
+ react-icons:
+ specifier: ^5.5.0
+ version: 5.5.0(react@19.1.0)
react-router-dom:
specifier: ^7.6.1
version: 7.6.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
@@ -4438,6 +4444,12 @@ packages:
neo-async@2.6.2:
resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
+ next-themes@0.4.6:
+ resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==}
+ peerDependencies:
+ react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc
+
no-case@3.0.4:
resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==}
@@ -5271,6 +5283,11 @@ packages:
react-error-overlay@6.1.0:
resolution: {integrity: sha512-SN/U6Ytxf1QGkw/9ve5Y+NxBbZM6Ht95tuXNMKs8EJyFa/Vy/+Co3stop3KBHARfn/giv+Lj1uUnTfOJ3moFEQ==}
+ react-icons@5.5.0:
+ resolution: {integrity: sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==}
+ peerDependencies:
+ react: '*'
+
react-is@16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
@@ -12021,6 +12038,11 @@ snapshots:
neo-async@2.6.2: {}
+ next-themes@0.4.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
+ dependencies:
+ react: 19.1.0
+ react-dom: 19.1.0(react@19.1.0)
+
no-case@3.0.4:
dependencies:
lower-case: 2.0.2
@@ -12881,6 +12903,10 @@ snapshots:
react-error-overlay@6.1.0: {}
+ react-icons@5.5.0(react@19.1.0):
+ dependencies:
+ react: 19.1.0
+
react-is@16.13.1: {}
react-is@17.0.2: {}
diff --git a/src/frontend/src/App.jsx b/src/frontend/src/App.jsx
index b9bcde6..2aa2790 100644
--- a/src/frontend/src/App.jsx
+++ b/src/frontend/src/App.jsx
@@ -1,17 +1,20 @@
import React from 'react';
-import { Routes, Route } from 'react-router-dom';
-import Dashboard from './pages/Dashboard';
-import Configuration from './pages/Configuration';
-import Header from './components/Header';
+//import { Button, HStack } from '@chakra-ui/react';
+//import { Routes, Route } from 'react-router-dom';
+//import Dashboard from './pages/Dashboard';
+//import Configuration from './pages/Configuration';
+//import Header from './components/Header';
+//import { Box, Button } from '@chakra-ui/react';
-const App = () => (
+const App = () => (//待扩展
<>
-
-
- } />
- } />
-
>
);
+/**备用
+ *
+ * } />
+ * } />
+ *
+ */
export default App;
\ No newline at end of file
diff --git a/src/frontend/src/components/ui/color-mode.jsx b/src/frontend/src/components/ui/color-mode.jsx
new file mode 100644
index 0000000..b2d1cd6
--- /dev/null
+++ b/src/frontend/src/components/ui/color-mode.jsx
@@ -0,0 +1,90 @@
+'use client'
+
+import { ClientOnly, IconButton, Skeleton, Span } from '@chakra-ui/react'
+import { ThemeProvider, useTheme } from 'next-themes'
+
+import * as React from 'react'
+import { LuMoon, LuSun } from 'react-icons/lu'
+
+export function ColorModeProvider(props) {
+ return (
+
+ )
+}
+
+export function useColorMode() {
+ const { resolvedTheme, setTheme, forcedTheme } = useTheme()
+ const colorMode = forcedTheme || resolvedTheme
+ const toggleColorMode = () => {
+ setTheme(resolvedTheme === 'dark' ? 'light' : 'dark')
+ }
+ return {
+ colorMode: colorMode,
+ setColorMode: setTheme,
+ toggleColorMode,
+ }
+}
+
+export function useColorModeValue(light, dark) {
+ const { colorMode } = useColorMode()
+ return colorMode === 'dark' ? dark : light
+}
+
+export function ColorModeIcon() {
+ const { colorMode } = useColorMode()
+ return colorMode === 'dark' ? :
+}
+
+export const ColorModeButton = React.forwardRef(
+ function ColorModeButton(props, ref) {
+ const { toggleColorMode } = useColorMode()
+ return (
+ }>
+
+
+
+
+ )
+ },
+)
+
+export const LightMode = React.forwardRef(function LightMode(props, ref) {
+ return (
+
+ )
+})
+
+export const DarkMode = React.forwardRef(function DarkMode(props, ref) {
+ return (
+
+ )
+})
diff --git a/src/frontend/src/components/ui/provider.jsx b/src/frontend/src/components/ui/provider.jsx
new file mode 100644
index 0000000..80e3e01
--- /dev/null
+++ b/src/frontend/src/components/ui/provider.jsx
@@ -0,0 +1,12 @@
+'use client'
+
+import { ChakraProvider, defaultSystem } from '@chakra-ui/react'
+import { ColorModeProvider } from './color-mode'
+
+export function Provider(props) {
+ return (
+
+
+
+ )
+}
diff --git a/src/frontend/src/components/ui/toaster.jsx b/src/frontend/src/components/ui/toaster.jsx
new file mode 100644
index 0000000..6af2b70
--- /dev/null
+++ b/src/frontend/src/components/ui/toaster.jsx
@@ -0,0 +1,43 @@
+'use client'
+
+import {
+ Toaster as ChakraToaster,
+ Portal,
+ Spinner,
+ Stack,
+ Toast,
+ createToaster,
+} from '@chakra-ui/react'
+
+export const toaster = createToaster({
+ placement: 'bottom-end',
+ pauseOnPageIdle: true,
+})
+
+export const Toaster = () => {
+ return (
+
+
+ {(toast) => (
+
+ {toast.type === 'loading' ? (
+
+ ) : (
+
+ )}
+
+ {toast.title && {toast.title}}
+ {toast.description && (
+ {toast.description}
+ )}
+
+ {toast.action && (
+ {toast.action.label}
+ )}
+ {toast.closable && }
+
+ )}
+
+
+ )
+}
diff --git a/src/frontend/src/components/ui/tooltip.jsx b/src/frontend/src/components/ui/tooltip.jsx
new file mode 100644
index 0000000..ab225cc
--- /dev/null
+++ b/src/frontend/src/components/ui/tooltip.jsx
@@ -0,0 +1,35 @@
+import { Tooltip as ChakraTooltip, Portal } from '@chakra-ui/react'
+import * as React from 'react'
+
+export const Tooltip = React.forwardRef(function Tooltip(props, ref) {
+ const {
+ showArrow,
+ children,
+ disabled,
+ portalled = true,
+ content,
+ contentProps,
+ portalRef,
+ ...rest
+ } = props
+
+ if (disabled) return children
+
+ return (
+
+ {children}
+
+
+
+ {showArrow && (
+
+
+
+ )}
+ {content}
+
+
+
+
+ )
+})
diff --git a/src/frontend/src/index.js b/src/frontend/src/index.js
index 97f201d..5ac5ed0 100644
--- a/src/frontend/src/index.js
+++ b/src/frontend/src/index.js
@@ -1,14 +1,14 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
-import {ChakraProvider} from '@chakra-ui/react';
import { BrowserRouter } from 'react-router-dom';
+import {Provider} from './components/ui/provider'
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
-
+
-
+
)