topfans/frontend/utils/getStoredUser.js
zerosaturation 83999995f5 refactor(frontend): consolidate user storage read via getStoredUser helper
uni.getStorageSync('user') 在 key 从未写过的 UniApp 平台下默认返回 ""(空串)
而非 null/undefined,旧式 `JSON.parse(uni.getStorageSync('user')) || {}` 在
parse 阶段直接抛 `SyntaxError: Unexpected end of JSON input`,导致 quickLogin
setup 崩溃,并触发 Vue 二次告警 `Invalid vnode type: undefined`。

新增 utils/getStoredUser.js 单点封装,统一处理:
  - 空值/损坏 JSON 兜底(返回 null,不抛)
  - 与 store/modules/user.js 初始化块同源守卫
  - 失败 warn 级别日志,不影响业务

替换全库 16 处不安全 `JSON.parse(userStr)` 调用:
  composables/useLaserMint.js                  composables/useShare.js
  utils/guideConfig.js                         utils/preloadApi/core.js
  pages/castlove/lenticular/lenticular-result.vue
  pages/support-activity/index.vue             pages/support-activity/components/{TopRanking,ActionBar}.vue
  pages/components/{Header,ShareModal,ShareReportButtons}.vue
  pages/tasks/{GuideModal,daily-tasks}.vue
  pages/asset-detail/asset-detail.vue          pages/exhibition/exhibition.vue
  pages/profile/profile.vue                    pages/login/quickLogin.vue(原崩点)

净 -18 行,17 文件改动 + 1 文件新增。后续如需支持多 key(如 'adminUser'),
把 getStoredUser 扩成泛型 getStoredJSON(key) 即可。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 17:16:49 +08:00

44 lines
2.1 KiB
JavaScript

// frontend/utils/getStoredUser.js
// 安全读取 uni.getStorageSync('user') 并 JSON.parse —— 单点封装,消除全库 ~20 处
// 重复且不安全的 `JSON.parse(userStr)` 裸调用。
//
// 已知坑(踩过 2 次,均以红色 stack trace 形式出现):
// 1. `uni.getStorageSync('user')` 在 key 从未写过的 UniApp 平台下默认返回 ""
// (空串)而不是 null/undefined,旧式 `JSON.parse(getStorageSync('user')) || {}`
// 会在 parse 阶段直接抛 `SyntaxError: Unexpected end of JSON input`,setup 崩溃 →
// Vue 触发 `[Vue warn]: Invalid vnode type when creating vnode: undefined`
// 二次告警(同一个根因)。最低成本修复是 `|| '{}'` 兜底,但仍无法防 JSON 损坏场景。
// 2. 上线后曾遇到"token 有效但 user 缓存被清"的中间态
// (升级包 / 跨设备 tab 登出 / 部分页面单独清缓存),彼时 setup 抛错导致整页白屏。
//
// 使用规范:
// import { getStoredUser } from '@/utils/getStoredUser'
// const user = getStoredUser() // 失败返回 null
// const user = getStoredUser() || {} // 失败降级为空对象
// const uid = getStoredUser()?.uid // 失败时为 undefined
//
// 与 store/modules/user.js 初始化块保持同源语义;后续如需支持多 key (e.g. 'adminUser')
// 再扩成泛型 getStoredJSON(key) 即可。
/**
* 安全读取本地缓存中的 user(JSON) 并解析为对象。
*
* 失败场景(return null):
* - 'user' key 不存在 → uni.getStorageSync 返回 "" 或 undefined
* - 'user' 缓存损坏 / 不是合法 JSON → JSON.parse 抛错
* - 'user' 是合法 JSON 但解析后是 null(如 'null' 字符串)→ 兜底返回 null
*
* @returns {object|null} 解析成功返回 user 对象;失败返回 null
*/
export function getStoredUser() {
const userStr = uni.getStorageSync('user');
if (!userStr) return null;
try {
return JSON.parse(userStr) || null;
} catch (e) {
// warn 级别即可,不要 error —— 这是可预期的 cache miss / 损坏,不是真错
console.warn('[getStoredUser] failed to parse user storage:', e?.message || e);
return null;
}
}