/** * 计价法持久化控制 * * 管理 sessionStorage 中的 skip/force 标记, * 用于控制计价法组件在清除/重建默认数据时的竞态。 */ import { readCurrentProjectId } from '@/lib/workspace' const PRICING_CLEAR_SKIP_PREFIX = 'pricing-clear-skip:' const PRICING_FORCE_DEFAULT_PREFIX = 'pricing-force-default:' export const buildProjectScopedSessionKey = (prefix: string, dbKey: string) => `${prefix}${readCurrentProjectId()}:${dbKey}` /** * 判断当前是否应跳过持久化写入 * 用于防止组件卸载时覆盖刚被清除的数据 */ export const shouldSkipPersist = (dbKey: string, paneCreatedAt: number): boolean => { const storageKey = buildProjectScopedSessionKey(PRICING_CLEAR_SKIP_PREFIX, dbKey) const raw = sessionStorage.getItem(storageKey) if (!raw) return false const now = Date.now() if (raw.includes(':')) { const [issuedRaw, untilRaw] = raw.split(':') const issuedAt = Number(issuedRaw) const skipUntil = Number(untilRaw) if (Number.isFinite(issuedAt) && Number.isFinite(skipUntil) && now <= skipUntil) { return paneCreatedAt <= issuedAt } sessionStorage.removeItem(storageKey) return false } const skipUntil = Number(raw) if (Number.isFinite(skipUntil) && now <= skipUntil) return true sessionStorage.removeItem(storageKey) return false } /** * 判断当前是否应强制加载默认数据(忽略已有持久化数据) * 读取后立即清除标记(一次性) */ export const shouldForceDefaultLoad = (dbKey: string): boolean => { const storageKey = buildProjectScopedSessionKey(PRICING_FORCE_DEFAULT_PREFIX, dbKey) const raw = sessionStorage.getItem(storageKey) if (!raw) return false const forceUntil = Number(raw) sessionStorage.removeItem(storageKey) return Number.isFinite(forceUntil) && Date.now() <= forceUntil } /** * 设置跳过持久化标记 * @param dbKey 存储键 * @param durationMs 有效时长(毫秒),默认 3000ms */ export const markSkipPersist = (dbKey: string, durationMs = 3000): void => { const storageKey = buildProjectScopedSessionKey(PRICING_CLEAR_SKIP_PREFIX, dbKey) const now = Date.now() sessionStorage.setItem(storageKey, `${now}:${now + durationMs}`) } /** * 设置强制加载默认数据标记 * @param dbKey 存储键 * @param durationMs 有效时长(毫秒),默认 3000ms */ export const markForceDefaultLoad = (dbKey: string, durationMs = 3000): void => { const storageKey = buildProjectScopedSessionKey(PRICING_FORCE_DEFAULT_PREFIX, dbKey) sessionStorage.setItem(storageKey, String(Date.now() + durationMs)) }