93 lines
2.8 KiB
React
93 lines
2.8 KiB
React
import React from 'react'
|
|
import ReactDOM from 'react-dom/client'
|
|
import App from './App.jsx'
|
|
import './index.css'
|
|
|
|
// Preline UI JavaScript
|
|
import 'preline'
|
|
|
|
import { generateShades } from './utils/colorPalette.js'
|
|
|
|
const API_BASE_URL = 'http://129.211.173.87:8889/api'
|
|
const SHADE_STOPS = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950]
|
|
|
|
/**
|
|
* 从后端加载配色配置并注入 CSS 变量
|
|
* 这个请求在登录前也能访问,确保访客和管理员都能看到统一主题
|
|
*/
|
|
async function loadThemeColors() {
|
|
try {
|
|
const res = await fetch(`${API_BASE_URL}/settings/public`, {
|
|
method: 'GET',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
})
|
|
if (!res.ok) return
|
|
const data = await res.json()
|
|
let colors = data.theme_colors || {}
|
|
if (typeof colors === 'string') {
|
|
try {
|
|
colors = JSON.parse(colors)
|
|
} catch (e) {
|
|
colors = {}
|
|
}
|
|
}
|
|
const root = document.documentElement
|
|
|
|
const shades = colors.shades || {}
|
|
const primaryFallback = shades[500] || colors.primary
|
|
const hoverFallback = shades[600] || colors['primary-hover'] || primaryFallback
|
|
const lightFallback = shades[100] || colors['primary-light'] || primaryFallback
|
|
|
|
// 语义变量(色阶优先)
|
|
if (primaryFallback) root.style.setProperty('--color-primary', primaryFallback)
|
|
if (hoverFallback) root.style.setProperty('--color-primary-hover', hoverFallback)
|
|
if (lightFallback) root.style.setProperty('--color-primary-light', lightFallback)
|
|
|
|
const mapping = {
|
|
secondary: '--color-secondary',
|
|
bg: '--color-bg',
|
|
text: '--color-text',
|
|
sidebar: '--color-sidebar',
|
|
'sidebar-active': '--color-sidebar-active',
|
|
card: '--color-card',
|
|
border: '--color-border',
|
|
'text-secondary': '--color-text-secondary',
|
|
}
|
|
|
|
Object.entries(mapping).forEach(([key, cssVar]) => {
|
|
if (colors[key]) {
|
|
root.style.setProperty(cssVar, colors[key])
|
|
}
|
|
})
|
|
|
|
// Primary 色阶 (50-950)
|
|
if (shades && Object.keys(shades).length > 0) {
|
|
SHADE_STOPS.forEach(stop => {
|
|
if (shades[stop]) {
|
|
root.style.setProperty(`--color-primary-${stop}`, shades[stop])
|
|
}
|
|
})
|
|
}
|
|
|
|
// Secondary 色阶 (50-950)
|
|
if (colors.secondary) {
|
|
const secShades = generateShades(colors.secondary)
|
|
SHADE_STOPS.forEach(stop => {
|
|
root.style.setProperty(`--color-secondary-${stop}`, secShades[stop])
|
|
})
|
|
}
|
|
} catch (e) {
|
|
// 静默失败,使用默认 CSS 变量值
|
|
console.warn('加载主题配色失败,使用默认值', e)
|
|
}
|
|
}
|
|
|
|
// 先加载主题,再渲染应用
|
|
loadThemeColors().then(() => {
|
|
ReactDOM.createRoot(document.getElementById('root')).render(
|
|
<React.StrictMode>
|
|
<App />
|
|
</React.StrictMode>,
|
|
)
|
|
})
|