跳到主要内容

状态管理

概述

项目使用 Pinia 作为状态管理方案,全局仅定义了一个 Store 实例 useStore(对应 store/index.ts),集中管理用户信息、登录状态、IM 连接、字典数据等全局状态。

Store 定义

import { defineStore } from 'pinia'

export const useStore = defineStore('main', {
state: () => ({ ... }),
actions: { ... },
persist: {
enabled: true,
strategies: [{ key: 'live-mall', storage: window?.localStorage, paths: [...] }]
}
})

State 字段说明

用户与认证

字段类型说明
userIUserInfo当前登录用户信息
isLoginboolean登录状态,基于 StorageKeyEnum.TOKEN 初始化
openIdstring微信 openId,小程序登录后保存
phoneVisibleboolean个人信息中手机号是否完全可见
walletIdnumber当前用户钱包 ID

系统与平台

字段类型说明
isIosAppboolean是否为 iOS App 环境
isAppPlusboolean是否为 App 环境(Android 或 iOS)
isWeixinboolean是否在微信小程序环境
sysInfoUniApp.GetSystemInfoResult系统信息(屏幕尺寸、安全区域等)
appPermissionMapRecord<PermissionType, boolean>App 权限授权状态映射
appPermissionIdsRecord<PermissionType, number>App 权限状态码(1=已授权,-1=已拒绝)

业务数据

字段类型说明
pageTabIndexnumber当前 Tab 页索引
tabbarListITabbarItem[]动态 Tabbar 列表(根据平台动态生成)
cityDataListICityData[]城市三级联动数据
museumitemIMuseumItem当前博物馆详情(跨页面共享)
dictMapRecord<string, IDictItem[]>字典数据缓存
isLiveVisibleboolean直播模块是否可见
recommendSwitchboolean推送功能是否开启

IM 即时通讯

字段类型说明
isIMLoginbooleanIM 是否已登录
chatany腾讯云 IM SDK 实例
csUrlstring客服页面 URL
imSDKAppIdnumberIM SDK AppID
imSecretKeystringIM 密钥
tcPlayerLicenseUrlstringH5 直播播放器授权地址

Actions 说明

登录与令牌

async setToken(token = '', refreshToken = '', openId = '') {
if (token === '') {
// 清除登录状态:移除 Storage 中的 Token、清空用户信息
this.isLogin = false
this.user = <IUserInfo>{}
uni.removeStorageSync(StorageKeyEnum.TOKEN)
uni.removeStorageSync(StorageKeyEnum.REFRESH_TOKEN)
} else {
// 设置登录状态:保存 Token → 拉取用户信息 → 登录 IM
this.isLogin = true
uni.setStorageSync(StorageKeyEnum.TOKEN, token)
uni.setStorageSync(StorageKeyEnum.REFRESH_TOKEN, refreshToken)
this.user = await getUserInfoApi()
await useIM().login()
}
}

关键点setToken 不仅管理本地存储,还串联了用户信息拉取和 IM 登录流程。

Tab 管理

// 通过索引设置当前 Tab
setPageTabIndex(index: number)

// 通过 Tab 类型设置(自动处理小程序无直播 Tab 的情况)
setPageTabByType(type: TabbarTypeEnum)

TabbarTypeEnum 包含:HOMEMALLLIVEMUSEUMMINE

字典数据

// 支持批量设置和单个设置
setDictMap(key: string | Record<string, IDictItem[]>, data?: IDictItem[])

IM 配置

setIMSettings(settings: IDictItem[]) {
// 从字典数据中提取 im_sdk_app_id、im_secret_key、v_cube_license
this.imSDKAppId = Number(appIdStr)
this.imSecretKey = secretKey
this.tcPlayerLicenseUrl = license
}

持久化策略

Store 通过 pinia-plugin-persist 插件实现数据持久化,存储键为 live-mall,使用 localStorage

persist: {
enabled: true,
strategies: [{
key: 'live-mall',
storage: window?.localStorage,
paths: [
'sysInfo', // 系统信息
'appPermissionMap', // 权限映射
'appPermissionIds', // 权限状态码
'user', // 用户信息
'museumitem', // 博物馆详情
'cityDataList', // 城市数据
'openId', // 微信 openId
'phoneVisible', // 手机号可见性
'recommendSwitch', // 推送开关
'walletId', // 钱包 ID
'dictMap', // 字典缓存
]
}]
}

注意:以下字段不持久化(每次启动重新获取):

  • isLogin — 基于 Token 是否存在重新计算
  • isIMLogin / chat — IM 状态需重新初始化
  • pageTabIndex / tabbarList — 每次启动动态生成
  • isLiveVisible / showOneClickLogin — 临时 UI 状态

本地存储键枚举

除 Pinia 持久化外,项目还通过 StorageKeyEnum 管理独立的本地存储:

用途
TOKEN访问令牌
REFRESH_TOKEN刷新令牌
NETWORK_ALLOWED_IN_IOSiOS 首次启动网络权限标识
INVOICE_TITLE_INFO发票抬头信息(列表页→详情页传递)
LIVE_LIST直播列表缓存
PROD_ORDER_INFO商品订单信息
LIVE_PLAYBACK_DETAIL直播回放详情

使用示例

// 在组件中使用
import useStore from '@/store'

const store = useStore()

// 读取状态
console.log(store.user.nickname)
console.log(store.isLogin)

// 修改状态
store.setUserInfo(newUser)
store.setPageTabByType(TabbarTypeEnum.MALL)
store.setDictMap('promotion_product_scope', dictList)

// 登录流程
await store.setToken(accessToken, refreshToken, openId)

// 登出
store.setToken() // 传空参数,自动清除所有登录相关状态