feat(admin): 补全平台任务观测 + 空间管理 + 基建加 MinIO/实时探针 #2

Merged
Blizzard merged 3 commits from feat/site into main 2026-07-18 09:46:30 +00:00
2 changed files with 3 additions and 85 deletions
Showing only changes of commit 197531ea33 - Show all commits
@@ -1,34 +1,17 @@
import { useState } from 'react' import { useState } from 'react'
import { Link, NavLink } from 'react-router-dom' import { Link, NavLink } from 'react-router-dom'
import { Menu, Moon, Sun, X } from 'lucide-react' import { Menu, X } from 'lucide-react'
import { useTheme } from '@/components/theme-provider'
import { LogoMark } from '@/components/logo' import { LogoMark } from '@/components/logo'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
// 官网默认浅色,不搬深浅切换(ThemeProvider 未挂载)。
const NAV_ITEMS = [ const NAV_ITEMS = [
{ label: '产品', to: '/', end: true }, { label: '产品', to: '/', end: true },
{ label: '功能', to: '/#features' }, { label: '功能', to: '/#features' },
{ label: '架构', to: '/#architecture' }, { label: '架构', to: '/#architecture' },
] ]
function ThemeToggle() {
const { resolved, setTheme } = useTheme()
return (
<button
type="button"
aria-label={resolved === 'dark' ? '切换到浅色主题' : '切换到深色主题'}
onClick={() => setTheme(resolved === 'dark' ? 'light' : 'dark')}
className="flex size-8 items-center justify-center rounded-full border border-hairline-strong text-ink-2 transition-colors hover:border-accent hover:text-accent-ink"
>
{resolved === 'dark' ? (
<Sun className="size-4" />
) : (
<Moon className="size-4" />
)}
</button>
)
}
export function SiteHeader() { export function SiteHeader() {
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
@@ -70,7 +53,6 @@ export function SiteHeader() {
<nav className="hidden items-center gap-7 md:flex"> <nav className="hidden items-center gap-7 md:flex">
{links} {links}
<ThemeToggle />
<Link <Link
to="/download" to="/download"
className="rounded-[7px] bg-accent px-4 py-1.5 text-[13px] font-medium text-ground transition-opacity hover:opacity-90" className="rounded-[7px] bg-accent px-4 py-1.5 text-[13px] font-medium text-ground transition-opacity hover:opacity-90"
@@ -80,7 +62,6 @@ export function SiteHeader() {
</nav> </nav>
<div className="flex items-center gap-3 md:hidden"> <div className="flex items-center gap-3 md:hidden">
<ThemeToggle />
<button <button
type="button" type="button"
aria-label={open ? '关闭菜单' : '打开菜单'} aria-label={open ? '关闭菜单' : '打开菜单'}
@@ -1,63 +0,0 @@
import {
createContext,
useContext,
useEffect,
useState,
type ReactNode,
} from 'react'
type Theme = 'light' | 'dark' | 'system'
interface ThemeContextValue {
theme: Theme
resolved: 'light' | 'dark'
setTheme: (t: Theme) => void
}
const ThemeContext = createContext<ThemeContextValue | null>(null)
const STORAGE_KEY = 'sundynix-theme'
function systemTheme(): 'light' | 'dark' {
return window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light'
}
export function ThemeProvider({ children }: { children: ReactNode }) {
const [theme, setThemeState] = useState<Theme>(
() => (localStorage.getItem(STORAGE_KEY) as Theme) ?? 'system',
)
const [resolved, setResolved] = useState<'light' | 'dark'>(() =>
theme === 'system' ? systemTheme() : theme,
)
useEffect(() => {
const apply = () => {
const r = theme === 'system' ? systemTheme() : theme
setResolved(r)
document.documentElement.classList.toggle('dark', r === 'dark')
}
apply()
const mq = window.matchMedia('(prefers-color-scheme: dark)')
mq.addEventListener('change', apply)
return () => mq.removeEventListener('change', apply)
}, [theme])
const setTheme = (t: Theme) => {
localStorage.setItem(STORAGE_KEY, t)
setThemeState(t)
}
return (
<ThemeContext.Provider value={{ theme, resolved, setTheme }}>
{children}
</ThemeContext.Provider>
)
}
export function useTheme() {
const ctx = useContext(ThemeContext)
if (!ctx) throw new Error('useTheme must be used within ThemeProvider')
return ctx
}