Files
BYW-VoiceHub/server/plugins/statistics-code.ts
T

67 lines
2.1 KiB
TypeScript

import { getSystemSettingsCached } from '~~/server/utils/system-settings-helper'
/**
* 站点统计代码注入
* 读取后台「站点配置」中保存的统计代码片段,注入服务端渲染页面(SSR)的 <head>。
* 支持任意统计平台(百度统计、51.la、Microsoft Clarity、Google Analytics 等)的 HTML/JS 片段。
* 仅在整页加载(SSR / 首次hydration)时触发,客户端路由切换不会重复执行。
*
* 采用模块级 TTL 缓存复用统一设置读取封装(getSystemSettingsCached),
* 避免在渲染热路径上每次请求都查询数据库。
* 读取失败时按关闭降级且不写缓存,下个请求重试。
*/
const CACHE_TTL_MS = 60 * 1000 // 60 秒
let cache: {
enabled: boolean
code: string
} | null = null
let cacheFetchedAt = 0
let inFlight: Promise<{ enabled: boolean; code: string }> | null = null
async function getStatisticsCodeConfig(): Promise<{
enabled: boolean
code: string
}> {
const now = Date.now()
if (cache && now - cacheFetchedAt < CACHE_TTL_MS) {
return cache
}
if (!inFlight) {
inFlight = (async () => {
try {
const settings = await getSystemSettingsCached()
// getSystemSettingsCached 读取失败时返回 null(不抛错),按关闭降级且不写缓存,下个请求重试
if (!settings) {
return { enabled: false, code: '' }
}
cache = {
enabled: !!settings.statisticsCodeEnabled,
code: settings.statisticsCode || ''
}
cacheFetchedAt = Date.now()
return cache
} finally {
inFlight = null
}
})()
}
return inFlight
}
export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook('render:html', async (html: { head: string[] }) => {
try {
const { enabled, code } = await getStatisticsCodeConfig()
if (enabled && code.trim() && Array.isArray(html.head)) {
html.head.push(code)
}
} catch (error) {
// 注入失败不影响页面渲染
console.error('[StatisticsCode] 注入统计代码失败:', error)
}
})
})