|
@@ -1,162 +1,168 @@
|
|
|
-//管理用户信息、登录状态、角色权限等
|
|
|
+// stores/user.ts - 管理用户信息、登录状态、角色权限等
|
|
|
import { defineStore } from 'pinia'
|
|
|
import Taro from '@tarojs/taro'
|
|
|
-import { userAPI } from '@/services/api/user'
|
|
|
-import { ref } from 'vue'
|
|
|
+import { userAPI, type UserInfo} from '@/services/api/user'
|
|
|
+import { ref, computed } from 'vue'
|
|
|
|
|
|
export type UserRole = 'player' | 'hoster'
|
|
|
|
|
|
-// 定义API返回类型接口
|
|
|
-interface OpenIdResult {
|
|
|
- openid: string;
|
|
|
- [key: string]: any;
|
|
|
-}
|
|
|
-
|
|
|
-interface UserState {
|
|
|
- role: UserRole
|
|
|
- nickname: string
|
|
|
- avatar: string
|
|
|
- openid: string
|
|
|
- roomId: string | null
|
|
|
- currentGameId: string | null
|
|
|
- isRegistered: boolean
|
|
|
- currentRoom: string | null
|
|
|
-}
|
|
|
-
|
|
|
export const useUserStore = defineStore('user', () => {
|
|
|
+ // 基本状态
|
|
|
const openid = ref('')
|
|
|
const nickname = ref('')
|
|
|
const avatar = ref('')
|
|
|
- const role = ref<'player' | 'hoster'>('player')
|
|
|
+ const role = ref<UserRole>('player')
|
|
|
const isRegistered = ref(false)
|
|
|
const currentRoom = ref<string | null>(null)
|
|
|
const currentGameId = ref<string | null>(null)
|
|
|
+ const loading = ref(false)
|
|
|
+ const error = ref<string | null>(null)
|
|
|
+
|
|
|
+ // 计算属性
|
|
|
+ const userInfo = computed<UserInfo>(() => ({
|
|
|
+ openid: openid.value,
|
|
|
+ nickname: nickname.value,
|
|
|
+ avatar: avatar.value,
|
|
|
+ role: role.value
|
|
|
+ }))
|
|
|
+
|
|
|
+ // 保存用户状态到本地存储
|
|
|
+ function saveUserToStorage() {
|
|
|
+ const userData = {
|
|
|
+ openid: openid.value,
|
|
|
+ nickname: nickname.value,
|
|
|
+ avatar: avatar.value,
|
|
|
+ role: role.value,
|
|
|
+ currentRoom: currentRoom.value,
|
|
|
+ isRegistered: isRegistered.value,
|
|
|
+ }
|
|
|
+
|
|
|
+ Taro.setStorageSync('userInfo', JSON.stringify(userData))
|
|
|
+ return userData
|
|
|
+ }
|
|
|
+
|
|
|
+ // 从本地存储加载用户状态
|
|
|
+ function loadUserFromStorage(): boolean {
|
|
|
+ try {
|
|
|
+ const userInfo = Taro.getStorageSync('userInfo')
|
|
|
+ if (!userInfo) return false
|
|
|
+
|
|
|
+ const data = JSON.parse(userInfo)
|
|
|
+ openid.value = data.openid || ''
|
|
|
+ nickname.value = data.nickname || ''
|
|
|
+ avatar.value = data.avatar || ''
|
|
|
+ role.value = data.role || 'player'
|
|
|
+ isRegistered.value = !!data.isRegistered
|
|
|
+ currentRoom.value = data.currentRoom || null
|
|
|
+
|
|
|
+ return true
|
|
|
+ } catch (error) {
|
|
|
+ console.error('加载用户信息失败:', error)
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
// 初始化用户信息
|
|
|
async function initUser() {
|
|
|
- // 从本地存储加载用户信息
|
|
|
- const userInfo = Taro.getStorageSync('userInfo')
|
|
|
- if (userInfo) {
|
|
|
- try {
|
|
|
- const info = JSON.parse(userInfo)
|
|
|
- openid.value = info.openid || ''
|
|
|
- nickname.value = info.nickname || ''
|
|
|
- avatar.value = info.avatar || ''
|
|
|
- role.value = info.role || 'player'
|
|
|
- isRegistered.value = !!info.nickname && !!info.openid
|
|
|
-
|
|
|
- // 如果有房间ID,恢复
|
|
|
- if (info.currentRoom) {
|
|
|
- currentRoom.value = info.currentRoom
|
|
|
- }
|
|
|
-
|
|
|
+ loading.value = true
|
|
|
+ error.value = null
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 1. 尝试从本地存储加载
|
|
|
+ const localDataLoaded = loadUserFromStorage()
|
|
|
+
|
|
|
+ // 2. 如果本地有数据且已注册,直接返回成功
|
|
|
+ if (localDataLoaded && isRegistered.value) {
|
|
|
return true
|
|
|
- } catch (e) {
|
|
|
- console.error('解析用户信息失败:', e)
|
|
|
}
|
|
|
+
|
|
|
+ // 3. 如果本地有openid但未注册,保持现状
|
|
|
+ if (localDataLoaded && openid.value && !isRegistered.value) {
|
|
|
+ return true
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 否则,进行静默登录获取openid
|
|
|
+ return await silentLogin()
|
|
|
+ } catch (e) {
|
|
|
+ console.error('初始化用户失败:', e)
|
|
|
+ error.value = '初始化用户失败'
|
|
|
+ return false
|
|
|
+ } finally {
|
|
|
+ loading.value = false
|
|
|
}
|
|
|
-
|
|
|
- // 如果没有本地信息,尝试静默登录
|
|
|
- return silentLogin()
|
|
|
}
|
|
|
|
|
|
// 静默登录 - 仅获取openid
|
|
|
async function silentLogin() {
|
|
|
+ loading.value = true
|
|
|
+ error.value = null
|
|
|
+
|
|
|
try {
|
|
|
const loginRes = await Taro.login()
|
|
|
- if (loginRes.code) {
|
|
|
- // 修复: 确保返回类型正确
|
|
|
- const result = await userAPI.getOpenId(loginRes.code) as OpenIdResult
|
|
|
- if (result && result.openid) {
|
|
|
- openid.value = result.openid
|
|
|
-
|
|
|
- // 保存到本地
|
|
|
- Taro.setStorageSync('userInfo', JSON.stringify({
|
|
|
- openid: result.openid,
|
|
|
- role: role.value
|
|
|
- }))
|
|
|
-
|
|
|
- return true
|
|
|
- }
|
|
|
+ if (!loginRes.code) {
|
|
|
+ error.value = '登录失败'
|
|
|
+ return false
|
|
|
}
|
|
|
+
|
|
|
+ const result = await userAPI.getOpenId(loginRes.code)
|
|
|
+ if (!result.success || !result.data) {
|
|
|
+ error.value = result.message || '获取OpenID失败'
|
|
|
+ return false
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置openid
|
|
|
+ openid.value = result.data.openid
|
|
|
+ saveUserToStorage()
|
|
|
+ return true
|
|
|
+ } catch (e) {
|
|
|
+ console.error('静默登录失败:', e)
|
|
|
+ error.value = '静默登录失败'
|
|
|
return false
|
|
|
- } catch (error) {
|
|
|
- console.error('静默登录失败:', error)
|
|
|
- return false
|
|
|
+ } finally {
|
|
|
+ loading.value = false
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 注册用户 - 获取用户信息
|
|
|
async function registerUser() {
|
|
|
+ loading.value = true
|
|
|
+ error.value = null
|
|
|
+
|
|
|
try {
|
|
|
+ // 确保有openid
|
|
|
+ if (!openid.value) {
|
|
|
+ const loginSuccess = await silentLogin()
|
|
|
+ if (!loginSuccess) return false
|
|
|
+ }
|
|
|
+
|
|
|
// 微信环境使用getUserProfile
|
|
|
if (process.env.TARO_ENV === 'weapp') {
|
|
|
const profileRes = await Taro.getUserProfile({
|
|
|
desc: '用于完善用户资料'
|
|
|
})
|
|
|
|
|
|
- if (profileRes.userInfo) {
|
|
|
- nickname.value = profileRes.userInfo.nickName
|
|
|
- avatar.value = profileRes.userInfo.avatarUrl
|
|
|
- isRegistered.value = true
|
|
|
-
|
|
|
- // 保存到本地
|
|
|
- const userInfo = {
|
|
|
- openid: openid.value,
|
|
|
- nickname: profileRes.userInfo.nickName,
|
|
|
- avatar: profileRes.userInfo.avatarUrl,
|
|
|
- role: role.value,
|
|
|
- currentRoom: currentRoom.value
|
|
|
- }
|
|
|
- Taro.setStorageSync('userInfo', JSON.stringify(userInfo))
|
|
|
-
|
|
|
- // 同步到云端
|
|
|
- if (process.env.TARO_ENV === 'weapp' && Taro.cloud) {
|
|
|
- try {
|
|
|
- // 修复: 使用正确的云初始化检查方式
|
|
|
- // 注意: Taro.cloud.init()会返回void,不需要检查inited属性
|
|
|
- await Taro.cloud.init({
|
|
|
- env: (Taro.cloud as any).DYNAMIC_CURRENT_ENV
|
|
|
- })
|
|
|
-
|
|
|
- // 注意:云开发数据库操作
|
|
|
- const db = Taro.cloud.database()
|
|
|
- const userQuery = await db.collection('users').where({
|
|
|
- openid: openid.value
|
|
|
- }).get()
|
|
|
-
|
|
|
- // 如果用户已存在,更新信息
|
|
|
- if (userQuery.data && userQuery.data.length > 0) {
|
|
|
- // 修复: 强制类型转换
|
|
|
- const docId = userQuery.data[0]._id as string
|
|
|
- await db.collection('users').doc(docId).update({
|
|
|
- data: {
|
|
|
- nickname: nickname.value,
|
|
|
- avatar: avatar.value,
|
|
|
- updateTime: db.serverDate()
|
|
|
- }
|
|
|
- })
|
|
|
- } else {
|
|
|
- // 创建新用户
|
|
|
- await db.collection('users').add({
|
|
|
- data: {
|
|
|
- openid: openid.value,
|
|
|
- nickname: nickname.value,
|
|
|
- avatar: avatar.value,
|
|
|
- role: role.value,
|
|
|
- createTime: db.serverDate(),
|
|
|
- updateTime: db.serverDate()
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
- } catch (cloudError) {
|
|
|
- console.error('同步用户信息到云端失败:', cloudError)
|
|
|
- // 继续执行,即使云同步失败
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return true
|
|
|
+ if (!profileRes.userInfo) {
|
|
|
+ error.value = '获取用户信息失败'
|
|
|
+ return false
|
|
|
}
|
|
|
+
|
|
|
+ // 更新本地状态
|
|
|
+ nickname.value = profileRes.userInfo.nickName
|
|
|
+ avatar.value = profileRes.userInfo.avatarUrl
|
|
|
+ isRegistered.value = true
|
|
|
+
|
|
|
+ // 保存到本地存储
|
|
|
+ saveUserToStorage()
|
|
|
+
|
|
|
+ // 同步到云端 - 使用Service层处理
|
|
|
+ await userAPI.saveUserToCloud({
|
|
|
+ openid: openid.value,
|
|
|
+ nickname: nickname.value,
|
|
|
+ avatar: avatar.value,
|
|
|
+ role: role.value
|
|
|
+ })
|
|
|
+
|
|
|
+ return true
|
|
|
} else {
|
|
|
// 非微信环境模拟注册
|
|
|
nickname.value = '模拟用户_' + Date.now().toString().slice(-4)
|
|
@@ -164,62 +170,28 @@ export const useUserStore = defineStore('user', () => {
|
|
|
isRegistered.value = true
|
|
|
|
|
|
// 保存到本地
|
|
|
- const userInfo = {
|
|
|
- openid: openid.value,
|
|
|
- nickname: nickname.value,
|
|
|
- avatar: avatar.value,
|
|
|
- role: role.value,
|
|
|
- currentRoom: currentRoom.value
|
|
|
- }
|
|
|
- Taro.setStorageSync('userInfo', JSON.stringify(userInfo))
|
|
|
-
|
|
|
+ saveUserToStorage()
|
|
|
return true
|
|
|
}
|
|
|
-
|
|
|
- return false
|
|
|
- } catch (error) {
|
|
|
- console.error('用户注册失败:', error)
|
|
|
+ } catch (e) {
|
|
|
+ console.error('用户注册失败:', e)
|
|
|
+ error.value = '用户注册失败'
|
|
|
return false
|
|
|
+ } finally {
|
|
|
+ loading.value = false
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 设置用户角色
|
|
|
- function setRole(newRole: 'player' | 'hoster') {
|
|
|
+ function setRole(newRole: UserRole) {
|
|
|
role.value = newRole
|
|
|
-
|
|
|
- // 更新本地存储
|
|
|
- const userInfo = Taro.getStorageSync('userInfo')
|
|
|
- if (userInfo) {
|
|
|
- try {
|
|
|
- const info = JSON.parse(userInfo)
|
|
|
- info.role = newRole
|
|
|
- Taro.setStorageSync('userInfo', JSON.stringify(info))
|
|
|
- } catch (e) {
|
|
|
- console.error('更新用户角色失败:', e)
|
|
|
- }
|
|
|
- }
|
|
|
+ saveUserToStorage()
|
|
|
}
|
|
|
|
|
|
// 设置当前房间
|
|
|
function setCurrentRoom(roomId: string) {
|
|
|
currentRoom.value = roomId
|
|
|
-
|
|
|
- // 更新本地存储
|
|
|
- const userInfo = Taro.getStorageSync('userInfo')
|
|
|
- if (userInfo) {
|
|
|
- try {
|
|
|
- const info = JSON.parse(userInfo)
|
|
|
- info.currentRoom = roomId
|
|
|
- Taro.setStorageSync('userInfo', JSON.stringify(info))
|
|
|
- } catch (e) {
|
|
|
- console.error('更新当前房间失败:', e)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 检查是否已注册
|
|
|
- function checkIsRegistered() {
|
|
|
- return isRegistered.value
|
|
|
+ saveUserToStorage()
|
|
|
}
|
|
|
|
|
|
// 退出登录
|
|
@@ -229,84 +201,32 @@ export const useUserStore = defineStore('user', () => {
|
|
|
avatar.value = ''
|
|
|
isRegistered.value = false
|
|
|
currentRoom.value = null
|
|
|
+ currentGameId.value = null
|
|
|
|
|
|
// 清除本地存储
|
|
|
Taro.removeStorageSync('userInfo')
|
|
|
}
|
|
|
|
|
|
- // 检查用户登录状态
|
|
|
- async function checkLoginStatus() {
|
|
|
- try {
|
|
|
- // 从本地存储获取用户信息
|
|
|
- const userInfo = Taro.getStorageSync('userInfo')
|
|
|
- if (userInfo) {
|
|
|
- const info = JSON.parse(userInfo)
|
|
|
- openid.value = info.openid || ''
|
|
|
- nickname.value = info.nickname || ''
|
|
|
- avatar.value = info.avatar || ''
|
|
|
- isRegistered.value = !!info.openid && !!info.nickname
|
|
|
- return true
|
|
|
- }
|
|
|
-
|
|
|
- // 如果没有本地信息,尝试静默登录获取openid
|
|
|
- const loginRes = await Taro.login()
|
|
|
- if (loginRes.code) {
|
|
|
- // 修复: 确保返回类型正确
|
|
|
- const result = await userAPI.getOpenId(loginRes.code) as OpenIdResult
|
|
|
- if (result && result.openid) {
|
|
|
- openid.value = result.openid
|
|
|
- // 保存到本地
|
|
|
- Taro.setStorageSync('userInfo', JSON.stringify({ openid: result.openid }))
|
|
|
- return true
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return false
|
|
|
- } catch (error) {
|
|
|
- console.error('检查登录状态失败:', error)
|
|
|
- return false
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
// 设置当前游戏
|
|
|
function setCurrentGame(gameId: string | null) {
|
|
|
- currentGameId.value = gameId // 修复: 使用ref value
|
|
|
- }
|
|
|
-
|
|
|
- // 获取用户信息
|
|
|
- async function getUserInfo() {
|
|
|
- try {
|
|
|
- // 尝试从本地存储获取角色
|
|
|
- const roleValue = Taro.getStorageSync('userRole') as UserRole | ''
|
|
|
- if (roleValue) {
|
|
|
- role.value = roleValue
|
|
|
- }
|
|
|
-
|
|
|
- // 获取用户信息
|
|
|
- const userData = await userAPI.getUserInfo()
|
|
|
- if (userData) {
|
|
|
- nickname.value = userData.nickname || '游客'
|
|
|
- avatar.value = userData.avatar || ''
|
|
|
- openid.value = userData.openid || ''
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.error('获取用户信息失败:', error)
|
|
|
- }
|
|
|
+ currentGameId.value = gameId
|
|
|
}
|
|
|
|
|
|
// 重置用户角色到玩家
|
|
|
function resetToPlayer() {
|
|
|
- role.value = 'player' // 修复: 使用ref value
|
|
|
- Taro.setStorageSync('userRole', 'player')
|
|
|
+ role.value = 'player'
|
|
|
+ saveUserToStorage()
|
|
|
}
|
|
|
|
|
|
// 清除房间和游戏信息
|
|
|
function clearGameSession() {
|
|
|
- currentRoom.value = null // 修复: 使用ref value
|
|
|
- currentGameId.value = null // 修复: 使用ref value
|
|
|
+ currentRoom.value = null
|
|
|
+ currentGameId.value = null
|
|
|
+ saveUserToStorage()
|
|
|
}
|
|
|
|
|
|
return {
|
|
|
+ // 状态
|
|
|
openid,
|
|
|
nickname,
|
|
|
avatar,
|
|
@@ -314,16 +234,18 @@ export const useUserStore = defineStore('user', () => {
|
|
|
isRegistered,
|
|
|
currentRoom,
|
|
|
currentGameId,
|
|
|
+ loading,
|
|
|
+ error,
|
|
|
+ userInfo,
|
|
|
+
|
|
|
+ // 方法
|
|
|
initUser,
|
|
|
registerUser,
|
|
|
setRole,
|
|
|
setCurrentRoom,
|
|
|
- checkIsRegistered,
|
|
|
logout,
|
|
|
- checkLoginStatus,
|
|
|
setCurrentGame,
|
|
|
- getUserInfo,
|
|
|
resetToPlayer,
|
|
|
clearGameSession
|
|
|
}
|
|
|
-})
|
|
|
+})
|