/** 顾问邀请归因暂存:7 天 last-touch(与客户邀请码并列,参数名为 advisor) */ const ADVISOR_INVITE_STORAGE_KEY = 'oms_advisor_invite_v1' const ADVISOR_INVITE_TTL_MS = 7 * 24 * 60 * 60 * 1000 type AdvisorInvitePayload = { code: string ts: number } function safeParse(raw: string | null): AdvisorInvitePayload | null { if (!raw) return null try { const parsed = JSON.parse(raw) as AdvisorInvitePayload if (!parsed?.code || typeof parsed.ts !== 'number') return null return { code: String(parsed.code).trim(), ts: parsed.ts } } catch { return null } } function isExpired(ts: number, now = Date.now()): boolean { return now - ts > ADVISOR_INVITE_TTL_MS } export function stashAdvisorInvite(advisorCode?: string | null): void { const code = String(advisorCode ?? '').trim() if (!code) return const payload: AdvisorInvitePayload = { code, ts: Date.now() } const raw = JSON.stringify(payload) try { localStorage.setItem(ADVISOR_INVITE_STORAGE_KEY, raw) } catch { /* ignore */ } try { sessionStorage.setItem(ADVISOR_INVITE_STORAGE_KEY, raw) } catch { /* ignore */ } } export function readStashedAdvisorInvite(): string { const now = Date.now() const fromSession = safeParse( (() => { try { return sessionStorage.getItem(ADVISOR_INVITE_STORAGE_KEY) } catch { return null } })(), ) if (fromSession && !isExpired(fromSession.ts, now)) { return fromSession.code } const fromLocal = safeParse( (() => { try { return localStorage.getItem(ADVISOR_INVITE_STORAGE_KEY) } catch { return null } })(), ) if (fromLocal && !isExpired(fromLocal.ts, now)) { stashAdvisorInvite(fromLocal.code) return fromLocal.code } if (fromLocal || fromSession) { clearStashedAdvisorInvite() } return '' } export function clearStashedAdvisorInvite(): void { try { localStorage.removeItem(ADVISOR_INVITE_STORAGE_KEY) } catch { /* ignore */ } try { sessionStorage.removeItem(ADVISOR_INVITE_STORAGE_KEY) } catch { /* ignore */ } } /** 解析顾问邀请:query.advisor → 7 天暂存 */ export function resolveAdvisorInvite(query: Record): string { const fromQuery = String(query.advisor ?? '').trim() if (fromQuery) { stashAdvisorInvite(fromQuery) return fromQuery } return readStashedAdvisorInvite() }