fix: 修复系统设置的动态注入问题
- 创建 useSiteSettings composable 在应用启动时加载系统设置 - 从 window.__SITE_CONFIG__(后端注入)和 localStorage 初始化设置 - 修复 favicon 更新逻辑,正确移除旧 favicon 并添加新的 - 在路由守卫中设置页面标题,格式为 '页面名 - 网站名' - 简化 admin.vue 和 admin-sidebar 组件,使用统一的设置管理 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
import { reactive } from 'vue'
|
||||
import { getFileUrl } from '@/utils/config'
|
||||
|
||||
interface SiteSettings {
|
||||
siteName: string
|
||||
siteDescription: string
|
||||
siteLogo: string
|
||||
siteFavicon: string
|
||||
logoLight: string
|
||||
logoDark: string
|
||||
loaded: boolean
|
||||
}
|
||||
|
||||
const siteSettings = reactive<SiteSettings>({
|
||||
siteName: '',
|
||||
siteDescription: '',
|
||||
siteLogo: '',
|
||||
siteFavicon: '',
|
||||
logoLight: '',
|
||||
logoDark: '',
|
||||
loaded: false,
|
||||
})
|
||||
|
||||
function updateFavicon(favicon: string) {
|
||||
if (!favicon)
|
||||
return
|
||||
|
||||
const head = document.getElementsByTagName('head')[0]
|
||||
|
||||
// 移除旧的 favicon
|
||||
const existingLinks = head.querySelectorAll('link[rel*="icon"]')
|
||||
existingLinks.forEach((link) => link.remove())
|
||||
|
||||
// 添加新的 favicon
|
||||
const link = document.createElement('link')
|
||||
link.type = 'image/x-icon'
|
||||
link.rel = 'shortcut icon'
|
||||
link.href = getFileUrl(favicon)
|
||||
head.appendChild(link)
|
||||
|
||||
// 同时添加 icon 类型的 link
|
||||
const linkIcon = document.createElement('link')
|
||||
linkIcon.type = 'image/x-icon'
|
||||
linkIcon.rel = 'icon'
|
||||
linkIcon.href = getFileUrl(favicon)
|
||||
head.appendChild(linkIcon)
|
||||
}
|
||||
|
||||
function updateTitle(title?: string) {
|
||||
if (title) {
|
||||
document.title = title
|
||||
} else if (siteSettings.siteName) {
|
||||
document.title = siteSettings.siteName
|
||||
}
|
||||
}
|
||||
|
||||
function applySettings(settings: Partial<SiteSettings>) {
|
||||
if (settings.siteName) {
|
||||
siteSettings.siteName = settings.siteName
|
||||
updateTitle(settings.siteName)
|
||||
}
|
||||
if (settings.siteDescription) {
|
||||
siteSettings.siteDescription = settings.siteDescription
|
||||
}
|
||||
if (settings.siteLogo) {
|
||||
siteSettings.siteLogo = settings.siteLogo
|
||||
}
|
||||
if (settings.siteFavicon) {
|
||||
siteSettings.siteFavicon = settings.siteFavicon
|
||||
updateFavicon(settings.siteFavicon)
|
||||
}
|
||||
if (settings.logoLight) {
|
||||
siteSettings.logoLight = settings.logoLight
|
||||
}
|
||||
if (settings.logoDark) {
|
||||
siteSettings.logoDark = settings.logoDark
|
||||
}
|
||||
siteSettings.loaded = true
|
||||
}
|
||||
|
||||
// 从 window.__SITE_CONFIG__ 获取初始配置(由后端注入)
|
||||
function initFromServerConfig() {
|
||||
const config = (window as any).__SITE_CONFIG__
|
||||
if (config) {
|
||||
applySettings({
|
||||
siteName: config.siteName || '',
|
||||
siteDescription: config.siteDescription || '',
|
||||
siteLogo: config.logoLight || config.logoDark || '',
|
||||
logoLight: config.logoLight || '',
|
||||
logoDark: config.logoDark || '',
|
||||
favicon: config.favicon || '',
|
||||
})
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 从 localStorage 获取缓存的设置
|
||||
function initFromLocalStorage() {
|
||||
const storedSettings = localStorage.getItem('systemSettings')
|
||||
if (storedSettings) {
|
||||
try {
|
||||
const parsed = JSON.parse(storedSettings)
|
||||
applySettings({
|
||||
siteName: parsed.site_name || '',
|
||||
siteDescription: parsed.site_description || '',
|
||||
siteLogo: parsed.site_logo || '',
|
||||
siteFavicon: parsed.site_favicon || '',
|
||||
})
|
||||
return true
|
||||
}
|
||||
catch (e) {
|
||||
console.error('Failed to parse systemSettings from localStorage', e)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 从 API 获取最新设置
|
||||
async function fetchSettings() {
|
||||
try {
|
||||
const response = await fetch('/api/v1/dev/system-settings', {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${localStorage.getItem('token')}`,
|
||||
},
|
||||
})
|
||||
const data = await response.json()
|
||||
if (data.code === 200 && data.data) {
|
||||
const settings = {
|
||||
site_name: data.data.site_name || '',
|
||||
site_description: data.data.site_description || '',
|
||||
site_logo: data.data.site_logo || '',
|
||||
site_favicon: data.data.site_favicon || '',
|
||||
}
|
||||
localStorage.setItem('systemSettings', JSON.stringify(settings))
|
||||
applySettings({
|
||||
siteName: settings.site_name,
|
||||
siteDescription: settings.site_description,
|
||||
siteLogo: settings.site_logo,
|
||||
siteFavicon: settings.site_favicon,
|
||||
})
|
||||
// 触发事件通知其他组件
|
||||
window.dispatchEvent(new CustomEvent('system-settings-changed', { detail: settings }))
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Failed to fetch system settings:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化系统设置(在应用启动时调用)
|
||||
async function initSiteSettings() {
|
||||
// 优先从后端注入的配置获取
|
||||
const hasServerConfig = initFromServerConfig()
|
||||
|
||||
// 然后从 localStorage 获取缓存
|
||||
const hasLocalConfig = initFromLocalStorage()
|
||||
|
||||
// 如果都没有,尝试从 API 获取
|
||||
if (!hasServerConfig && !hasLocalConfig) {
|
||||
await fetchSettings()
|
||||
}
|
||||
|
||||
// 监听设置变化
|
||||
window.addEventListener('system-settings-changed', ((event: CustomEvent) => {
|
||||
applySettings({
|
||||
siteName: event.detail.site_name,
|
||||
siteDescription: event.detail.site_description,
|
||||
siteLogo: event.detail.site_logo,
|
||||
siteFavicon: event.detail.site_favicon,
|
||||
})
|
||||
}) as EventListener)
|
||||
}
|
||||
|
||||
// 获取带页面标题的完整标题
|
||||
function getPageTitle(pageTitle?: string): string {
|
||||
if (pageTitle && siteSettings.siteName) {
|
||||
return `${pageTitle} - ${siteSettings.siteName}`
|
||||
}
|
||||
if (siteSettings.siteName) {
|
||||
return siteSettings.siteName
|
||||
}
|
||||
return pageTitle || ''
|
||||
}
|
||||
|
||||
export function useSiteSettings() {
|
||||
return {
|
||||
siteSettings,
|
||||
initSiteSettings,
|
||||
updateTitle,
|
||||
getPageTitle,
|
||||
fetchSettings,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user