优化pinia持久化

This commit is contained in:
2026-01-15 09:51:59 +08:00
parent bb1ed16d8b
commit ab737f8a75
9 changed files with 239 additions and 155 deletions
+11 -1
View File
@@ -1,4 +1,14 @@
<script setup></script>
<script setup>
import { onMounted } from 'vue'
import { useI18nStore } from './stores/modules/i18n'
import i18n from './i18n'
onMounted(() => {
// 从持久化的 store 中读取语言设置并同步到 i18n
const i18nStore = useI18nStore()
i18n.global.locale.value = i18nStore.currentLocale
})
</script>
<template>
<router-view />
+47 -3
View File
@@ -1,7 +1,51 @@
export default {
app_title: 'vueadmin',
APP_NAME: 'vueadmin',
DASHBOARD_URL: '/home',
baseURL: '',
// 白名单路由(不需要登录即可访问)
whiteList: ['/login', '/register', '/reset-password']
whiteList: ['/login', '/register', '/reset-password'],
//版本号
APP_VER: "1.6.6",
//内核版本号
CORE_VER: "1.6.6",
//接口地址
API_URL: "http://localhost:8000/admin/",
//请求超时
TIMEOUT: 50000,
//TokenName
TOKEN_NAME: "authorization",
//Token前缀,注意最后有个空格,如不需要需设置空字符串
TOKEN_PREFIX: "Bearer ",
//追加其他头
HEADERS: {},
//请求是否开启缓存
REQUEST_CACHE: false,
//语言
LANG: "zh-cn",
//是否加密localStorage, 为空不加密
//支持多种加密方式: 'AES', 'BASE64', 'DES'
LS_ENCRYPTION: "",
//localStorage加密秘钥,位数建议填写8的倍数
LS_ENCRYPTION_key: "2XNN4K8LC0ELVWN4",
//localStorage加密模式,AES支持: 'ECB', 'CBC', 'CTR', 'OFB', 'CFB'
LS_ENCRYPTION_mode: "ECB",
//localStorage加密填充方式,AES支持: 'Pkcs7', 'ZeroPadding', 'Iso10126', 'Iso97971'
LS_ENCRYPTION_padding: "Pkcs7",
//localStorage默认过期时间(单位:小时),0表示永不过期
LS_DEFAULT_EXPIRE: 720, // 30天
//DES加密秘钥,必须是8字节
LS_DES_key: "12345678",
}
-5
View File
@@ -6,7 +6,6 @@ import App from './App.vue'
import router from './router'
import pinia from './stores'
import i18n from './i18n'
import { useI18nStore } from './stores/modules/i18n'
const app = createApp(App)
@@ -15,8 +14,4 @@ app.use(router)
app.use(pinia)
app.use(i18n)
// 初始化 i18n store,从 localStorage 读取保存的语言设置
const i18nStore = useI18nStore()
i18nStore.initLocale()
app.mount('#app')
+4
View File
@@ -1,5 +1,9 @@
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
const pinia = createPinia()
// 注册持久化插件
pinia.use(piniaPluginPersistedstate)
export default pinia
+26 -25
View File
@@ -1,34 +1,35 @@
import { defineStore } from 'pinia'
import i18n from '@/i18n'
export const useI18nStore = defineStore('i18n', {
state: () => ({
currentLocale: 'zh-CN',
availableLocales: [
{ label: '简体中文', value: 'zh-CN' },
{ label: 'English', value: 'en-US' }
]
}),
export const useI18nStore = defineStore(
'i18n',
{
state: () => ({
currentLocale: 'zh-CN',
availableLocales: [
{ label: '简体中文', value: 'zh-CN' },
{ label: 'English', value: 'en-US' }
]
}),
getters: {
localeLabel: (state) => {
const locale = state.availableLocales.find((item) => item.value === state.currentLocale)
return locale ? locale.label : ''
}
},
actions: {
setLocale(locale) {
this.currentLocale = locale
i18n.global.locale.value = locale
localStorage.setItem('locale', locale)
getters: {
localeLabel: (state) => {
const locale = state.availableLocales.find((item) => item.value === state.currentLocale)
return locale ? locale.label : ''
}
},
initLocale() {
const savedLocale = localStorage.getItem('locale')
if (savedLocale && this.availableLocales.some((item) => item.value === savedLocale)) {
this.setLocale(savedLocale)
actions: {
setLocale(locale) {
this.currentLocale = locale
i18n.global.locale.value = locale
}
},
persist: {
key: 'i18n-store',
storage: localStorage,
pick: ['currentLocale']
}
}
})
)
+57 -47
View File
@@ -1,57 +1,67 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useLayoutStore = defineStore('layout', () => {
// 布局模式:'sidebar', 'top-nav', 'sidebar-top', 'classic'
const layoutMode = ref('sidebar')
export const useLayoutStore = defineStore(
'layout',
() => {
// 布局模式:'sidebar', 'top-nav', 'sidebar-top', 'classic'
const layoutMode = ref('sidebar')
// 侧边栏折叠状态
const sidebarCollapsed = ref(false)
// 侧边栏折叠状态
const sidebarCollapsed = ref(false)
// 视图标签页(用于记录页面滚动位置)
const viewTags = ref([])
// 视图标签页(用于记录页面滚动位置)
const viewTags = ref([])
// 切换侧边栏折叠
const toggleSidebar = () => {
sidebarCollapsed.value = !sidebarCollapsed.value
}
// 切换侧边栏折叠
const toggleSidebar = () => {
sidebarCollapsed.value = !sidebarCollapsed.value
}
// 设置布局模式
const setLayoutMode = (mode) => {
layoutMode.value = mode
}
// 设置布局模式
const setLayoutMode = (mode) => {
layoutMode.value = mode
}
// 更新视图标签
const updateViewTags = (tag) => {
const index = viewTags.value.findIndex((item) => item.fullPath === tag.fullPath)
if (index !== -1) {
viewTags.value[index] = tag
} else {
viewTags.value.push(tag)
// 更新视图标签
const updateViewTags = (tag) => {
const index = viewTags.value.findIndex((item) => item.fullPath === tag.fullPath)
if (index !== -1) {
viewTags.value[index] = tag
} else {
viewTags.value.push(tag)
}
}
// 移除视图标签
const removeViewTags = (fullPath) => {
const index = viewTags.value.findIndex((item) => item.fullPath === fullPath)
if (index !== -1) {
viewTags.value.splice(index, 1)
}
}
// 清空视图标签
const clearViewTags = () => {
viewTags.value = []
}
return {
layoutMode,
sidebarCollapsed,
viewTags,
toggleSidebar,
setLayoutMode,
updateViewTags,
removeViewTags,
clearViewTags,
}
},
{
persist: {
key: 'layout-store',
storage: localStorage,
pick: ['layoutMode', 'sidebarCollapsed']
}
}
// 移除视图标签
const removeViewTags = (fullPath) => {
const index = viewTags.value.findIndex((item) => item.fullPath === fullPath)
if (index !== -1) {
viewTags.value.splice(index, 1)
}
}
// 清空视图标签
const clearViewTags = () => {
viewTags.value = []
}
return {
layoutMode,
sidebarCollapsed,
viewTags,
toggleSidebar,
setLayoutMode,
updateViewTags,
removeViewTags,
clearViewTags,
}
})
)
+75 -74
View File
@@ -2,79 +2,80 @@ import { ref } from 'vue'
import { defineStore } from 'pinia'
import { resetRouter } from '../../router'
export const useUserStore = defineStore('user', () => {
const token = ref(localStorage.getItem('token') || '')
const refreshToken = ref(localStorage.getItem('refreshToken') || '')
const userInfo = ref(JSON.parse(localStorage.getItem('userInfo') || 'null'))
const menu = ref(JSON.parse(localStorage.getItem('MENU') || '[]'))
export const useUserStore = defineStore(
'user',
() => {
const token = ref('')
const refreshToken = ref('')
const userInfo = ref(null)
const menu = ref([])
// 设置 token
function setToken(newToken) {
token.value = newToken
localStorage.setItem('token', newToken)
// 设置 token
function setToken(newToken) {
token.value = newToken
}
// 设置 refresh token
function setRefreshToken(newRefreshToken) {
refreshToken.value = newRefreshToken
}
// 设置用户信息
function setUserInfo(info) {
userInfo.value = info
}
// 设置菜单
function setMenu(newMenu) {
menu.value = newMenu
}
// 获取菜单
function getMenu() {
return menu.value
}
// 清除菜单
function clearMenu() {
menu.value = []
}
// 登出
function logout() {
token.value = ''
refreshToken.value = ''
userInfo.value = null
menu.value = []
// 重置路由
resetRouter()
}
// 检查是否已登录
function isLoggedIn() {
return !!token.value
}
return {
token,
refreshToken,
userInfo,
menu,
setToken,
setRefreshToken,
setUserInfo,
setMenu,
getMenu,
clearMenu,
logout,
isLoggedIn,
}
},
{
persist: {
key: 'user-store',
storage: localStorage,
pick: ['token', 'refreshToken', 'userInfo', 'menu']
}
}
// 设置 refresh token
function setRefreshToken(newRefreshToken) {
refreshToken.value = newRefreshToken
localStorage.setItem('refreshToken', newRefreshToken)
}
// 设置用户信息
function setUserInfo(info) {
userInfo.value = info
localStorage.setItem('userInfo', JSON.stringify(info))
}
// 设置菜单
function setMenu(newMenu) {
menu.value = newMenu
localStorage.setItem('MENU', JSON.stringify(newMenu))
}
// 获取菜单
function getMenu() {
return menu.value
}
// 清除菜单
function clearMenu() {
menu.value = []
localStorage.removeItem('MENU')
}
// 登出
function logout() {
token.value = ''
refreshToken.value = ''
userInfo.value = null
menu.value = []
localStorage.removeItem('token')
localStorage.removeItem('refreshToken')
localStorage.removeItem('userInfo')
localStorage.removeItem('MENU')
// 重置路由
resetRouter()
}
// 检查是否已登录
function isLoggedIn() {
return !!token.value
}
return {
token,
refreshToken,
userInfo,
menu,
setToken,
setRefreshToken,
setUserInfo,
setMenu,
getMenu,
clearMenu,
logout,
isLoggedIn,
}
})
)