diff --git a/.cert/cert.pem b/.cert/cert.pem new file mode 100644 index 0000000..22a7231 --- /dev/null +++ b/.cert/cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDCTCCAfGgAwIBAgIUQxY5HJAktPoEWU9osMraUrm/DEAwDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI1MDIxMzAzMTA0MVoXDTI2MDIx +MzAzMTA0MVowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAraDt2UXkzKLRskNtVDo1iXe1tBTYTAFtl+m7JOvdYdmS +oenV3Cn/8Cd8JuusQVl9jovcMFb3pwrQzodSQ9oN70B/MSqA/Pjgpji+uu4Hjcas +VhaAHregBsV8ULl+OikPPFWcGKRZMtRyta3Sy/2E5Y44wr8vdERKDl/6ydDVioe5 +dQQS+klyzamy9ayQj8fpSTR96H+WpDd6gGuDf+XlrqlnrgatiUIJiDkeJPCIUNJi +VSw8lq3KO8O4K376smCAdngdyYg+q/Sk2r5MnHi9VqNknwmos06yPk6vTWIpZ+mK +bz9W2HW4sukU0nwRXP0p29SKoW5ZKPvrLvfNDp0P3QIDAQABo1MwUTAdBgNVHQ4E +FgQUYSHtj6LjfaQ0BmuCdlHf/EXKm5AwHwYDVR0jBBgwFoAUYSHtj6LjfaQ0BmuC +dlHf/EXKm5AwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAQnM/ +MIYunEp8ITMtllILW9TJhZVertfuux4S1rgRZ3VADmHgHftCgUKpm4kh8w2gEZ0M +DXTmnIwqaBa+lpiCcALECUQ1L2jPcwCYowmEfnKLF6Ob3Tnznz0eqr8TnvuKCX4c +ehSlfqOcUn8rveLDX91j+FJ+LSggf/kYjhE0ACtZHJyEM9csWu5chu8cCjpq5pn/ +ahiPw5eUnxsyBWdqlkMvY+lofH7SaunXrbLcIDg67wMl0FpZ39z/UAhIVNiyUIDe +k7pNzRu99r5hIqdyfx5zULG2mzJCSsJj63t4BeDwr6u+zXSlyVMqh5cXj9mk4LJ6 +DhJlnudcCV5t/RGyOw== +-----END CERTIFICATE----- diff --git a/.cert/key.pem b/.cert/key.pem new file mode 100644 index 0000000..53b20f4 --- /dev/null +++ b/.cert/key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCtoO3ZReTMotGy +Q21UOjWJd7W0FNhMAW2X6bsk691h2ZKh6dXcKf/wJ3wm66xBWX2Oi9wwVvenCtDO +h1JD2g3vQH8xKoD8+OCmOL667geNxqxWFoAet6AGxXxQuX46KQ88VZwYpFky1HK1 +rdLL/YTljjjCvy90REoOX/rJ0NWKh7l1BBL6SXLNqbL1rJCPx+lJNH3of5akN3qA +a4N/5eWuqWeuBq2JQgmIOR4k8IhQ0mJVLDyWrco7w7grfvqyYIB2eB3JiD6r9KTa +vkyceL1Wo2SfCaizTrI+Tq9NYiln6YpvP1bYdbiy6RTSfBFc/Snb1Iqhblko++su +980OnQ/dAgMBAAECggEAI/6N+GI9N7AUVUaVqmWj1iL/Q/0jRwRvxhOyFIoiG6gp +dg/+IhWB5bUlz4LBc8270fqME+hfkF1VYs9aXk8c3unJxHVJhsgIeGUgoyt33Owg +K3ugJV4PWoAD0M9Xi/KZojokMVaW2EsDGcdWgSwGKjmk6jiMu6dxi8/Zc4+ryTsY +3+KMUocFyqMfYK1/sYSTPzlPWcCGMuaO36Df++cAzKLlqHRh7BLgSiCXBrV8ITFf +LTkQFDf/c+yVC6mJG/GXzqdKXS3OT97sW34tdmQPNhReCSkSEDVQt+tnFa5be1R2 +18mODkaSv4DxnMXnlfexon/pGuXukgrMTZQXq2+pIQKBgQDaNvBmJrSCU9NSDNSj +I0yTX8DUzEv1bxErbfptSlSoUcEIPcLsxt+xZFVfU8IcMvQ43gHSsRquCfZsUZ0r +/ZIfJ7pWTqbxd/EybsMiC2ZSS8NdVX3MJhKinrZXMTRAA8l5a4AFr2YKMtNqQpGY +xWu8TS7PR8N9B6vZqGC9hhID4QKBgQDLsZLrezomWTthFAOfACj/ebIEyZ30YVNw +7IaaVTkeWtYGJXasMrts1+n15dPwR6a18c65hSywJKsCEYD6z/uXxaoX1bK32oLw +49thMw+qSilA1jMQ/XQxx9TFsmrCvwSm5xIjSV+0pD1sApiivGQAU+2oHZeEwLue +v51JxnaLfQKBgQDVYUWgThbTHk8U+7DuObVGoyp3q7JXNJ1wf2GTf0zbLt54RZSX +Xj0dRMRqrAey9Wx1MzpLIZ26M8nAz+nGO3Woe3utq8l5c9TqgP7VCpqqvKU0XkXd +3Bj65gHdryKtukZIMgOFC6fXLy4mySOAZQRdpIeybzVMzLSR6SF4EmMJYQKBgGtz +xVlLrCVGtThE4pQh9X6vp+U2poigPvA3FdqcUoFc0cJ0SOIV8SE91UHOd7stURhx +8ueTBTv2W++/ZBbrWIF72HqyVJEASErjKHtiAEWI0bJOTKoNyhnonKmdsQwC0GVr +R/otXrtgWLZ9uB9A2lAB9kDVO3TgZxkbY9HjS+3RAoGBAKVKcJFErNZhQxCx5ll3 +u9wtE7duiVcS3jZhFa7tvcSc4O5+ahEQG/gy2M6kgqB/f3nMH6Rd9wsTzwPp1uZz +qiumr3ZOvpTWuLiIMQi3sE9pBGz7p+ZTeP8Z0Wez98v9MVmgsCsPqDOpa1JhnJIq +2AgG3D/RUJylOPYnMq8vdAyx +-----END PRIVATE KEY----- diff --git a/index.html b/index.html index f2114e7..e87d011 100644 --- a/index.html +++ b/index.html @@ -108,6 +108,15 @@ 哪吒监控 Nezha Monitoring + + + + + + + + + diff --git a/public/android-chrome-192x192.png b/public/android-chrome-192x192.png new file mode 100644 index 0000000..0e09ce1 Binary files /dev/null and b/public/android-chrome-192x192.png differ diff --git a/public/manifest.json b/public/manifest.json new file mode 100644 index 0000000..3e749eb --- /dev/null +++ b/public/manifest.json @@ -0,0 +1,17 @@ +{ + "name": "Nezha Monitoring", + "short_name": "Nezha Monitoring", + "icons": [ + { + "src": "/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "any maskable" + } + ], + "theme_color": "hsl(0 0% 98%)", + "background_color": "hsl(0 0% 98%)", + "start_url": "/", + "display": "standalone", + "orientation": "portrait" +} diff --git a/src/components/ThemeColorManager.tsx b/src/components/ThemeColorManager.tsx new file mode 100644 index 0000000..36e2f67 --- /dev/null +++ b/src/components/ThemeColorManager.tsx @@ -0,0 +1,39 @@ +"use client" + +import { useTheme } from "@/hooks/use-theme" +import { useEffect } from "react" + +export function ThemeColorManager() { + const { theme } = useTheme() + + useEffect(() => { + const updateThemeColor = () => { + const currentTheme = theme + const meta = document.querySelector('meta[name="theme-color"]') + + if (!meta) { + const newMeta = document.createElement("meta") + newMeta.name = "theme-color" + document.head.appendChild(newMeta) + } + + const themeColor = + currentTheme === "dark" + ? "hsl(30 15% 8%)" // 深色模式背景色 + : "hsl(0 0% 98%)" // 浅色模式背景色 + + document.querySelector('meta[name="theme-color"]')?.setAttribute("content", themeColor) + } + + // Update on mount and theme change + updateThemeColor() + + // Listen for system theme changes + const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)") + mediaQuery.addEventListener("change", updateThemeColor) + + return () => mediaQuery.removeEventListener("change", updateThemeColor) + }, [theme]) + + return null +} diff --git a/src/main.tsx b/src/main.tsx index 1be15b4..a8048c8 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -4,6 +4,7 @@ import ReactDOM from "react-dom/client" import { Toaster } from "sonner" import App from "./App" +import { ThemeColorManager } from "./components/ThemeColorManager" import { ThemeProvider } from "./components/ThemeProvider" import { MotionProvider } from "./components/motion/motion-provider" import { SortProvider } from "./context/sort-provider" @@ -18,6 +19,7 @@ const queryClient = new QueryClient() ReactDOM.createRoot(document.getElementById("root")!).render( + diff --git a/vite.config.ts b/vite.config.ts index e9011f8..d17ebb5 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,5 +1,6 @@ import react from "@vitejs/plugin-react-swc" import { execSync } from "child_process" +import fs from "fs" import path from "path" import { defineConfig } from "vite" @@ -26,6 +27,10 @@ export default defineConfig({ }, }, server: { + https: { + key: fs.readFileSync("./.cert/key.pem"), + cert: fs.readFileSync("./.cert/cert.pem"), + }, proxy: { "/api/v1/ws/server": { target: "ws://localhost:8008",