码桶
发现社区成员的开源项目
site.tsx2 KB
import { createContext, useContext, useEffect, useState, type ReactNode } from 'react'
interface SiteConfig {
site_name: string
site_icon: string
seo_title: string
seo_description: string
seo_keywords: string
github: string
}
const DEFAULT: SiteConfig = {
site_name: '奶狗WeBot',
site_icon: '',
seo_title: '',
seo_description: '',
seo_keywords: '',
github: 'https://github.com/naigoucn/ng-webot',
}
const SiteCtx = createContext<SiteConfig>(DEFAULT)
export function useSite() {
return useContext(SiteCtx)
}
function applyMeta(cfg: SiteConfig) {
const title = cfg.seo_title || cfg.site_name || '奶狗WeBot'
document.title = title
const setMeta = (name: string, content: string) => {
if (!content) return
let el = document.querySelector(`meta[name="${name}"]`)
if (!el) {
el = document.createElement('meta')
el.setAttribute('name', name)
document.head.appendChild(el)
}
el.setAttribute('content', content)
}
setMeta('description', cfg.seo_description)
setMeta('keywords', cfg.seo_keywords)
// 站点 icon(favicon)
if (cfg.site_icon) {
let link = document.querySelector("link[rel~='icon']") as HTMLLinkElement | null
if (!link) {
link = document.createElement('link')
link.rel = 'icon'
document.head.appendChild(link)
}
link.href = cfg.site_icon
}
}
export function SiteProvider({ children }: { children: ReactNode }) {
const [cfg, setCfg] = useState<SiteConfig>(DEFAULT)
useEffect(() => {
fetch('/api/site-config', { headers: { 'X-Requested-With': 'XMLHttpRequest' } })
.then(r => r.json())
.then(d => {
if (d?.ok && d.config) {
const c = { ...DEFAULT, ...d.config }
setCfg(c)
applyMeta(c)
}
})
.catch(() => { /* 拉取失败则用默认值 */ })
}, [])
return <SiteCtx.Provider value={cfg}>{children}</SiteCtx.Provider>
}