// app/composables/useArticleNavContext.js // 维护文章列表上下文(顺序、当前位置)供详情页/抽屉使用 import { computed } from 'vue' const STORAGE_KEY = 'article:list:context' function useStorage () { if (process.server) return null return window.sessionStorage } function readPersisted () { try { const store = useStorage() if (!store) return null const raw = store.getItem(STORAGE_KEY) if (!raw) return null return JSON.parse(raw) } catch (err) { console.warn('[ArticleNav] read persist failed', err) return null } } function writePersisted (payload) { try { const store = useStorage() if (!store) return store.setItem(STORAGE_KEY, JSON.stringify(payload)) } catch (err) { console.warn('[ArticleNav] write persist failed', err) } } function uniqSlugs (slugs = []) { const seen = new Set() const res = [] for (const s of slugs) { if (!s || seen.has(s)) continue seen.add(s) res.push(s) } return res } export function useArticleNavContext () { const state = useState('article:nav', () => { // SSR 时返回空状态,客户端会在下面恢复 if (process.server) { return { listId: '', slugs: [], current: '' } } // 客户端首次初始化时从 sessionStorage 恢复 return readPersisted() || { listId: '', slugs: [], current: '' } }) // 客户端挂载时,确保从 sessionStorage 恢复状态 if (process.client) { const persisted = readPersisted() if (persisted && persisted.slugs && persisted.slugs.length > 0) { // 如果 sessionStorage 中有数据,但 state 是空的,则恢复 if (!state.value.slugs || state.value.slugs.length === 0) { console.log('[ArticleNav] 从 sessionStorage 恢复导航上下文:', persisted) state.value = persisted } } } const index = computed(() => { if (!state.value.current) return -1 return state.value.slugs.findIndex((s) => s === state.value.current) }) const prevSlug = computed(() => { const i = index.value return i > 0 ? state.value.slugs[i - 1] : '' }) const nextSlug = computed(() => { const i = index.value return i >= 0 && i < state.value.slugs.length - 1 ? state.value.slugs[i + 1] : '' }) const hasNav = computed(() => Boolean(state.value.slugs.length)) function setList (listId, slugs) { if (!Array.isArray(slugs)) return state.value.listId = listId || '' state.value.slugs = uniqSlugs(slugs.filter(Boolean)) writePersisted(state.value) } function setCurrent (slug) { const s = slug || '' state.value.current = s if (s && !state.value.slugs.includes(s)) { state.value.slugs = uniqSlugs([...(state.value.slugs || []), s]) } writePersisted(state.value) } return { state, index, prevSlug, nextSlug, hasNav, setList, setCurrent } }