优化pagetype列表页缓存机制
This commit is contained in:
parent
e57ee5189d
commit
589640baa7
@ -291,46 +291,125 @@ const cardBadges = computed(() => {
|
|||||||
const metaFields = ref<any[]>([])
|
const metaFields = ref<any[]>([])
|
||||||
const linkTitleCache = ref<Record<string, string>>({})
|
const linkTitleCache = ref<Record<string, string>>({})
|
||||||
const pageTypeConfigCache = ref<Record<string, any>>({})
|
const pageTypeConfigCache = ref<Record<string, any>>({})
|
||||||
|
const cacheAccessOrder = ref<string[]>([]) // 记录访问顺序,用于LRU
|
||||||
let saveCacheTimer: ReturnType<typeof setTimeout> | null = null
|
let saveCacheTimer: ReturnType<typeof setTimeout> | null = null
|
||||||
|
const CACHE_EXPIRY_DAYS = 7 // 缓存过期天数
|
||||||
|
const MAX_CACHE_SIZE = 500 // 最大缓存条目数
|
||||||
|
|
||||||
// 从localStorage恢复缓存(避免刷新时抖动)
|
// 从localStorage恢复缓存(避免刷新时抖动)
|
||||||
function loadCacheFromStorage() {
|
function loadCacheFromStorage() {
|
||||||
try {
|
try {
|
||||||
const cached = localStorage.getItem(`linkTitleCache:${entity.value}`)
|
const cached = localStorage.getItem('linkTitleCache')
|
||||||
if (cached) {
|
if (cached) {
|
||||||
const parsed = JSON.parse(cached)
|
const parsed = JSON.parse(cached)
|
||||||
// 合并到当前缓存,但不覆盖已有值
|
const { data, timestamp } = parsed
|
||||||
Object.keys(parsed).forEach(key => {
|
|
||||||
if (!linkTitleCache.value[key]) {
|
// 检查是否过期
|
||||||
linkTitleCache.value[key] = parsed[key]
|
const now = Date.now()
|
||||||
}
|
const expiryTime = CACHE_EXPIRY_DAYS * 24 * 60 * 60 * 1000
|
||||||
})
|
if (timestamp && now - timestamp < expiryTime && data) {
|
||||||
|
// 合并到当前缓存,但不覆盖已有值
|
||||||
|
Object.keys(data).forEach(key => {
|
||||||
|
if (!linkTitleCache.value[key]) {
|
||||||
|
linkTitleCache.value[key] = data[key]
|
||||||
|
// 恢复访问顺序
|
||||||
|
if (!cacheAccessOrder.value.includes(key)) {
|
||||||
|
cacheAccessOrder.value.push(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载缓存失败:', error)
|
console.error('加载缓存失败:', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存缓存到localStorage(带防抖,避免频繁写入)
|
// 更新缓存并记录访问顺序(LRU策略)
|
||||||
|
function updateCacheWithLRU(key: string, value: string) {
|
||||||
|
// 如果已存在,更新访问顺序
|
||||||
|
if (linkTitleCache.value[key]) {
|
||||||
|
const index = cacheAccessOrder.value.indexOf(key)
|
||||||
|
if (index > -1) {
|
||||||
|
cacheAccessOrder.value.splice(index, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果缓存已满,移除最久未使用的
|
||||||
|
if (cacheAccessOrder.value.length >= MAX_CACHE_SIZE && !linkTitleCache.value[key]) {
|
||||||
|
const oldestKey = cacheAccessOrder.value.shift()
|
||||||
|
if (oldestKey) {
|
||||||
|
delete linkTitleCache.value[oldestKey]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加/更新缓存
|
||||||
|
linkTitleCache.value[key] = value
|
||||||
|
cacheAccessOrder.value.push(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存缓存到localStorage(带防抖,页面关闭时立即保存)
|
||||||
function saveCacheToStorage() {
|
function saveCacheToStorage() {
|
||||||
if (saveCacheTimer) {
|
if (saveCacheTimer) {
|
||||||
clearTimeout(saveCacheTimer)
|
clearTimeout(saveCacheTimer)
|
||||||
}
|
}
|
||||||
saveCacheTimer = setTimeout(() => {
|
saveCacheTimer = setTimeout(() => {
|
||||||
try {
|
saveCacheImmediately()
|
||||||
// 限制缓存大小,只保存最近1000个条目
|
}, 500) // 减少防抖时间到500ms,更快响应
|
||||||
const cacheEntries = Object.entries(linkTitleCache.value)
|
}
|
||||||
if (cacheEntries.length > 1000) {
|
|
||||||
// 只保留最新的1000个
|
// 立即保存缓存(用于页面关闭时)
|
||||||
const recentEntries = cacheEntries.slice(-1000)
|
function saveCacheImmediately() {
|
||||||
linkTitleCache.value = Object.fromEntries(recentEntries)
|
if (saveCacheTimer) {
|
||||||
|
clearTimeout(saveCacheTimer)
|
||||||
|
saveCacheTimer = null
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 按访问顺序限制缓存大小
|
||||||
|
if (cacheAccessOrder.value.length > MAX_CACHE_SIZE) {
|
||||||
|
const toRemove = cacheAccessOrder.value.slice(0, cacheAccessOrder.value.length - MAX_CACHE_SIZE)
|
||||||
|
toRemove.forEach(key => {
|
||||||
|
delete linkTitleCache.value[key]
|
||||||
|
})
|
||||||
|
cacheAccessOrder.value = cacheAccessOrder.value.slice(-MAX_CACHE_SIZE)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存带时间戳的缓存
|
||||||
|
localStorage.setItem('linkTitleCache', JSON.stringify({
|
||||||
|
data: linkTitleCache.value,
|
||||||
|
timestamp: Date.now()
|
||||||
|
}))
|
||||||
|
} catch (error) {
|
||||||
|
// 如果存储空间不足,清理旧缓存
|
||||||
|
if (error instanceof DOMException && error.code === 22) {
|
||||||
|
try {
|
||||||
|
localStorage.removeItem('linkTitleCache')
|
||||||
|
// 重试保存,只保存最近100个
|
||||||
|
const recentKeys = cacheAccessOrder.value.slice(-100)
|
||||||
|
const recentCache: Record<string, string> = {}
|
||||||
|
recentKeys.forEach(key => {
|
||||||
|
recentCache[key] = linkTitleCache.value[key]
|
||||||
|
})
|
||||||
|
localStorage.setItem('linkTitleCache', JSON.stringify({
|
||||||
|
data: recentCache,
|
||||||
|
timestamp: Date.now()
|
||||||
|
}))
|
||||||
|
linkTitleCache.value = recentCache
|
||||||
|
cacheAccessOrder.value = recentKeys
|
||||||
|
} catch (e) {
|
||||||
|
console.error('保存缓存失败:', e)
|
||||||
}
|
}
|
||||||
localStorage.setItem(`linkTitleCache:${entity.value}`, JSON.stringify(linkTitleCache.value))
|
} else {
|
||||||
} catch (error) {
|
|
||||||
console.error('保存缓存失败:', error)
|
console.error('保存缓存失败:', error)
|
||||||
}
|
}
|
||||||
saveCacheTimer = null
|
}
|
||||||
}, 1000) // 1秒防抖
|
}
|
||||||
|
|
||||||
|
// 页面关闭时立即保存缓存
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
window.addEventListener('beforeunload', saveCacheImmediately)
|
||||||
|
window.addEventListener('pagehide', saveCacheImmediately)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadMeta() {
|
async function loadMeta() {
|
||||||
@ -410,7 +489,7 @@ async function preloadLinkTitles() {
|
|||||||
recordNames.forEach(name => {
|
recordNames.forEach(name => {
|
||||||
const cacheKey = `${pagetype}_${name}`
|
const cacheKey = `${pagetype}_${name}`
|
||||||
if (!linkTitleCache.value[cacheKey]) {
|
if (!linkTitleCache.value[cacheKey]) {
|
||||||
linkTitleCache.value[cacheKey] = name
|
updateCacheWithLRU(cacheKey, name)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@ -438,20 +517,20 @@ async function preloadLinkTitles() {
|
|||||||
withCredentials: true
|
withCredentials: true
|
||||||
})
|
})
|
||||||
|
|
||||||
// 缓存结果
|
// 缓存结果(使用LRU策略)
|
||||||
const records = result.data?.data || []
|
const records = result.data?.data || []
|
||||||
records.forEach((record: any) => {
|
records.forEach((record: any) => {
|
||||||
const name = record.name
|
const name = record.name
|
||||||
const titleValue = record[titleField] || name
|
const titleValue = record[titleField] || name
|
||||||
const cacheKey = `${pagetype}_${name}`
|
const cacheKey = `${pagetype}_${name}`
|
||||||
linkTitleCache.value[cacheKey] = titleValue
|
updateCacheWithLRU(cacheKey, titleValue)
|
||||||
})
|
})
|
||||||
|
|
||||||
// 对于API未返回的记录,缓存原值(可能是已删除的记录)
|
// 对于API未返回的记录,缓存原值(可能是已删除的记录)
|
||||||
namesToLoad.forEach(name => {
|
namesToLoad.forEach(name => {
|
||||||
const cacheKey = `${pagetype}_${name}`
|
const cacheKey = `${pagetype}_${name}`
|
||||||
if (!linkTitleCache.value[cacheKey]) {
|
if (!linkTitleCache.value[cacheKey]) {
|
||||||
linkTitleCache.value[cacheKey] = name
|
updateCacheWithLRU(cacheKey, name)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -463,7 +542,7 @@ async function preloadLinkTitles() {
|
|||||||
namesToLoad.forEach(name => {
|
namesToLoad.forEach(name => {
|
||||||
const cacheKey = `${pagetype}_${name}`
|
const cacheKey = `${pagetype}_${name}`
|
||||||
if (!linkTitleCache.value[cacheKey]) {
|
if (!linkTitleCache.value[cacheKey]) {
|
||||||
linkTitleCache.value[cacheKey] = name
|
updateCacheWithLRU(cacheKey, name)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user