码桶

发现社区成员的开源项目

奶狗 /

ng-webot

公开
main
ng-webot/web/src/lib/site.tsx
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>
}