UNPKG

@tianyio/quality-helper

Version:

A comprehensive quality helper tool for project scaffolding and management

288 lines (247 loc) 7.84 kB
import { ref, computed } from 'vue' import { defineStore, acceptHMRUpdate } from 'pinia' // 用户信息接口 interface UserInfo { id: string username: string email: string avatar?: string role: 'admin' | 'user' | 'guest' preferences: { theme: 'light' | 'dark' | 'auto' language: string notifications: boolean autoSave: boolean } lastLoginTime?: string } // 用户设置接口 interface UserSettings { sidebarCollapsed: boolean pageSize: number defaultView: 'grid' | 'list' shortcuts: Record<string, string> } /** * 用户 Store - 数据持久化案例 * 演示 Pinia 3.0.3 的持久化功能和最佳实践 */ export const useUserStore = defineStore( 'user', () => { // 状态定义 const userInfo = ref<UserInfo | null>(null) const isLoggedIn = ref(false) const token = ref<string | null>(null) const settings = ref<UserSettings>({ sidebarCollapsed: false, pageSize: 20, defaultView: 'grid', shortcuts: {}, }) const loginHistory = ref<string[]>([]) const sessionStartTime = ref<string | null>(null) // 计算属性 const isAdmin = computed(() => userInfo.value?.role === 'admin') const displayName = computed(() => { if (!userInfo.value) return 'Guest' return userInfo.value.username || userInfo.value.email.split('@')[0] }) const avatarUrl = computed(() => { if (userInfo.value?.avatar) return userInfo.value.avatar // 生成默认头像 URL const email = userInfo.value?.email ?? 'guest@example.com' return `https://www.gravatar.com/avatar/${btoa(email)}?d=identicon&s=64` }) const sessionDuration = computed(() => { if (!sessionStartTime.value) return 0 return Date.now() - new Date(sessionStartTime.value).getTime() }) // 登录方法 async function login(credentials: { username: string; password: string }): Promise<boolean> { try { // 模拟 API 调用 await new Promise(resolve => setTimeout(resolve, 1000)) // 模拟登录成功 const mockUser: UserInfo = { id: '1', username: credentials.username, email: `${credentials.username}@example.com`, role: credentials.username === 'admin' ? 'admin' : 'user', preferences: { theme: 'light', language: 'zh-CN', notifications: true, autoSave: true, }, lastLoginTime: new Date().toISOString(), } const mockToken = `token_${Date.now()}_${Math.random().toString(36).substr(2, 9)}` // 更新状态 userInfo.value = mockUser token.value = mockToken isLoggedIn.value = true sessionStartTime.value = new Date().toISOString() // 记录登录历史 loginHistory.value.unshift(mockUser.lastLoginTime!) if (loginHistory.value.length > 10) { loginHistory.value = loginHistory.value.slice(0, 10) } if (import.meta.env.DEV) { console.log('👤 User logged in:', mockUser) } return true } catch (error) { console.error('Login failed:', error) return false } } // 登出方法 function logout() { userInfo.value = null token.value = null isLoggedIn.value = false sessionStartTime.value = null if (import.meta.env.DEV) { console.log('👋 User logged out') } } // 更新用户信息 function updateUserInfo(updates: Partial<UserInfo>) { if (!userInfo.value) { throw new Error('No user logged in') } userInfo.value = { ...userInfo.value, ...updates } if (import.meta.env.DEV) { console.log('📝 User info updated:', updates) } } // 更新用户偏好设置 function updatePreferences(preferences: Partial<UserInfo['preferences']>) { if (!userInfo.value) { throw new Error('No user logged in') } userInfo.value.preferences = { ...userInfo.value.preferences, ...preferences } if (import.meta.env.DEV) { console.log('⚙️ User preferences updated:', preferences) } } // 更新用户设置 function updateSettings(newSettings: Partial<UserSettings>) { settings.value = { ...settings.value, ...newSettings } if (import.meta.env.DEV) { console.log('🔧 User settings updated:', newSettings) } } // 切换侧边栏状态 function toggleSidebar() { settings.value.sidebarCollapsed = !settings.value.sidebarCollapsed } // 添加快捷键 function addShortcut(key: string, action: string) { settings.value.shortcuts[key] = action } // 移除快捷键 function removeShortcut(key: string) { delete settings.value.shortcuts[key] } // 切换主题 function toggleTheme() { if (!userInfo.value) return const themes: Array<UserInfo['preferences']['theme']> = ['light', 'dark', 'auto'] const currentIndex = themes.indexOf(userInfo.value.preferences.theme) const nextIndex = (currentIndex + 1) % themes.length updatePreferences({ theme: themes[nextIndex] }) } // 检查权限 function hasPermission(permission: string): boolean { if (!userInfo.value) return false // 简单的权限检查逻辑 if (userInfo.value.role === 'admin') return true if (userInfo.value.role === 'guest') return false // 用户权限检查逻辑 const userPermissions = ['read', 'write'] return userPermissions.includes(permission) } // 刷新 token async function refreshToken(): Promise<boolean> { if (!token.value) return false try { // 模拟 API 调用 await new Promise(resolve => setTimeout(resolve, 500)) const newToken = `token_${Date.now()}_${Math.random().toString(36).substr(2, 9)}` token.value = newToken if (import.meta.env.DEV) { console.log('🔄 Token refreshed') } return true } catch (error) { console.error('Token refresh failed:', error) logout() // 刷新失败时登出 return false } } // 清除登录历史 function clearLoginHistory() { loginHistory.value = [] } // 导出状态 function exportUserData() { return { userInfo: userInfo.value, settings: settings.value, loginHistory: loginHistory.value, sessionStartTime: sessionStartTime.value, } } // 导入状态 function importUserData(data: ReturnType<typeof exportUserData>) { if (data.userInfo) userInfo.value = data.userInfo if (data.settings) settings.value = data.settings if (data.loginHistory) loginHistory.value = data.loginHistory if (data.sessionStartTime) sessionStartTime.value = data.sessionStartTime } return { // 状态 userInfo, isLoggedIn, token, settings, loginHistory, sessionStartTime, // 计算属性 isAdmin, displayName, avatarUrl, sessionDuration, // 方法 login, logout, updateUserInfo, updatePreferences, updateSettings, toggleSidebar, addShortcut, removeShortcut, toggleTheme, hasPermission, refreshToken, clearLoginHistory, exportUserData, importUserData, } }, { // 启用数据持久化 persist: { key: 'user-store', storage: localStorage, // 只持久化部分字段,敏感信息如 token 不持久化 paths: ['userInfo', 'settings', 'loginHistory'], }, } ) // HMR 支持 if (import.meta.hot) { import.meta.hot.accept(acceptHMRUpdate(useUserStore, import.meta.hot)) }