mirror of
https://github.com/woodchen-ink/nezha-dash-v1.git
synced 2025-07-18 17:41:56 +08:00
feat: add PWA support with manifest, icons, and theme color management
This commit is contained in:
parent
b298d91aa1
commit
d4f6db436a
19
.cert/cert.pem
Normal file
19
.cert/cert.pem
Normal file
@ -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-----
|
28
.cert/key.pem
Normal file
28
.cert/key.pem
Normal file
@ -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-----
|
@ -108,6 +108,15 @@
|
|||||||
<link rel="icon" type="image/png" href="/apple-touch-icon.png" />
|
<link rel="icon" type="image/png" href="/apple-touch-icon.png" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>哪吒监控 Nezha Monitoring</title>
|
<title>哪吒监控 Nezha Monitoring</title>
|
||||||
|
|
||||||
|
<!-- PWA -->
|
||||||
|
<link rel="manifest" href="/manifest.json" />
|
||||||
|
<meta name="theme-color" content="hsl(0 0% 98%)" />
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
|
||||||
|
<meta name="apple-mobile-web-app-title" content="Nezha Monitoring" />
|
||||||
|
<link rel="apple-touch-icon" href="/android-chrome-192x192.png" />
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://fastly.jsdelivr.net/gh/lipis/flag-icons@7.0.0/css/flag-icons.min.css" />
|
<link rel="stylesheet" href="https://fastly.jsdelivr.net/gh/lipis/flag-icons@7.0.0/css/flag-icons.min.css" />
|
||||||
<link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/font-logos@1/assets/font-logos.css" />
|
<link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/font-logos@1/assets/font-logos.css" />
|
||||||
</head>
|
</head>
|
||||||
|
BIN
public/android-chrome-192x192.png
Normal file
BIN
public/android-chrome-192x192.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.7 KiB |
17
public/manifest.json
Normal file
17
public/manifest.json
Normal file
@ -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"
|
||||||
|
}
|
39
src/components/ThemeColorManager.tsx
Normal file
39
src/components/ThemeColorManager.tsx
Normal file
@ -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
|
||||||
|
}
|
@ -4,6 +4,7 @@ import ReactDOM from "react-dom/client"
|
|||||||
import { Toaster } from "sonner"
|
import { Toaster } from "sonner"
|
||||||
|
|
||||||
import App from "./App"
|
import App from "./App"
|
||||||
|
import { ThemeColorManager } from "./components/ThemeColorManager"
|
||||||
import { ThemeProvider } from "./components/ThemeProvider"
|
import { ThemeProvider } from "./components/ThemeProvider"
|
||||||
import { MotionProvider } from "./components/motion/motion-provider"
|
import { MotionProvider } from "./components/motion/motion-provider"
|
||||||
import { SortProvider } from "./context/sort-provider"
|
import { SortProvider } from "./context/sort-provider"
|
||||||
@ -18,6 +19,7 @@ const queryClient = new QueryClient()
|
|||||||
ReactDOM.createRoot(document.getElementById("root")!).render(
|
ReactDOM.createRoot(document.getElementById("root")!).render(
|
||||||
<MotionProvider>
|
<MotionProvider>
|
||||||
<ThemeProvider storageKey="vite-ui-theme">
|
<ThemeProvider storageKey="vite-ui-theme">
|
||||||
|
<ThemeColorManager />
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<WebSocketProvider url="/api/v1/ws/server">
|
<WebSocketProvider url="/api/v1/ws/server">
|
||||||
<StatusProvider>
|
<StatusProvider>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import react from "@vitejs/plugin-react-swc"
|
import react from "@vitejs/plugin-react-swc"
|
||||||
import { execSync } from "child_process"
|
import { execSync } from "child_process"
|
||||||
|
import fs from "fs"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
import { defineConfig } from "vite"
|
import { defineConfig } from "vite"
|
||||||
|
|
||||||
@ -26,6 +27,10 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
|
https: {
|
||||||
|
key: fs.readFileSync("./.cert/key.pem"),
|
||||||
|
cert: fs.readFileSync("./.cert/cert.pem"),
|
||||||
|
},
|
||||||
proxy: {
|
proxy: {
|
||||||
"/api/v1/ws/server": {
|
"/api/v1/ws/server": {
|
||||||
target: "ws://localhost:8008",
|
target: "ws://localhost:8008",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user