refactor: replace Vuex with Pinia

This commit is contained in:
Aqr-K
2025-02-24 19:26:56 +08:00
parent 87239994ae
commit 721d4f7685
23 changed files with 269 additions and 222 deletions
+9 -5
View File
@@ -1,6 +1,6 @@
import axios from 'axios' import axios from 'axios'
import router from '@/router' import router from '@/router'
import store from '@/store' import { useAuthStore } from '@/stores'
// 创建axios实例 // 创建axios实例
const api = axios.create({ const api = axios.create({
@@ -9,10 +9,12 @@ const api = axios.create({
// 添加请求拦截器 // 添加请求拦截器
api.interceptors.request.use(config => { api.interceptors.request.use(config => {
// 认证 Store
const authStore = useAuthStore()
// 在请求头中添加token // 在请求头中添加token
const token = store.state.auth.token if (authStore.token) {
if (token) config.headers.Authorization = `Bearer ${token}` config.headers.Authorization = `Bearer ${authStore.token}`
}
return config return config
}) })
@@ -26,8 +28,10 @@ api.interceptors.response.use(
// 请求超时 // 请求超时
return Promise.reject(new Error(error)) return Promise.reject(new Error(error))
} else if (error.response.status === 403) { } else if (error.response.status === 403) {
// 认证 Store
const authStore = useAuthStore()
// 清除登录状态信息 // 清除登录状态信息
store.dispatch('auth/logout') authStore.logout()
// token验证失败,跳转到登录页面 // token验证失败,跳转到登录页面
router.push('/login') router.push('/login')
} }
+4 -2
View File
@@ -11,6 +11,7 @@ import noImage from '@images/no-image.jpeg'
import tmdbImage from '@images/logos/tmdb.png' import tmdbImage from '@images/logos/tmdb.png'
import doubanImage from '@images/logos/douban-black.png' import doubanImage from '@images/logos/douban-black.png'
import bangumiImage from '@images/logos/bangumi.png' import bangumiImage from '@images/logos/bangumi.png'
import { useUserStore } from '@/stores'
// 输入参数 // 输入参数
const props = defineProps({ const props = defineProps({
@@ -22,7 +23,8 @@ const props = defineProps({
// 从 provide 中获取全局设置 // 从 provide 中获取全局设置
const globalSettings: any = inject('globalSettings') const globalSettings: any = inject('globalSettings')
const store = useStore() // 用户 Store
const userStore = useUserStore()
// 提示框 // 提示框
const $toast = useToast() const $toast = useToast()
@@ -340,7 +342,7 @@ async function getMediaSeasons() {
// 查询订阅弹窗规则 // 查询订阅弹窗规则
async function queryDefaultSubscribeConfig() { async function queryDefaultSubscribeConfig() {
// 非管理员不显示 // 非管理员不显示
if (!store.state.auth.superUser) return false if (!userStore.superUser) return false
try { try {
let subscribe_config_url = '' let subscribe_config_url = ''
if (props.media?.type === '电影') subscribe_config_url = 'system/setting/DefaultMovieSubscribeConfig' if (props.media?.type === '电影') subscribe_config_url = 'system/setting/DefaultMovieSubscribeConfig'
+4 -11
View File
@@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import api from '@/api' import api from '@/api'
import { Subscribe, User } from '@/api/types' import { Subscribe, User } from '@/api/types'
import store from '@/store' import { useUserStore } from '@/stores'
import avatar1 from '@images/avatars/avatar-1.png' import avatar1 from '@images/avatars/avatar-1.png'
import { useToast } from 'vue-toast-notification' import { useToast } from 'vue-toast-notification'
import { useConfirm } from 'vuetify-use-dialog' import { useConfirm } from 'vuetify-use-dialog'
@@ -22,10 +22,10 @@ const props = defineProps({
}) })
// 当前用户的ID // 当前用户的ID
const currentLoginUserId = computed(() => store.state.auth.userID) const currentLoginUserId = computed(() => useUserStore().userID)
// 当前用户是否是管理员 // 当前用户是否是管理员
const currentUserIsSuperuser = computed(() => store.state.auth.superUser) const currentUserIsSuperuser = computed(() => useUserStore().superUser)
// 定义触发的自定义事件 // 定义触发的自定义事件
const emit = defineEmits(['remove', 'save']) const emit = defineEmits(['remove', 'save'])
@@ -161,14 +161,7 @@ onMounted(() => {
</VList> </VList>
</VCardText> </VCardText>
<VCardText class="flex flex-row justify-center"> <VCardText class="flex flex-row justify-center">
<VBtn <VBtn v-if="currentUserIsSuperuser" color="primary" class="me-4" @click="editUser"> 编辑 </VBtn>
v-if="currentUserIsSuperuser"
color="primary"
class="me-4"
@click="editUser"
>
编辑
</VBtn>
<VBtn <VBtn
v-if="currentUserIsSuperuser && props.user.id != currentLoginUserId" v-if="currentUserIsSuperuser && props.user.id != currentLoginUserId"
color="error" color="error"
+9 -4
View File
@@ -5,7 +5,7 @@ import { doneNProgress, startNProgress } from '@/api/nprogress'
import api from '@/api' import api from '@/api'
import { useDisplay } from 'vuetify' import { useDisplay } from 'vuetify'
import avatar1 from '@images/avatars/avatar-1.png' import avatar1 from '@images/avatars/avatar-1.png'
import store from '@/store' import { useUserStore } from '@/stores'
// 显示器宽度 // 显示器宽度
const display = useDisplay() const display = useDisplay()
@@ -23,8 +23,11 @@ const props = defineProps({
oper: String, oper: String,
}) })
// 用户 Store
const userStore = useUserStore()
// 当前登录用户名称 // 当前登录用户名称
const currentLoginUser = store.state.auth.userName const currentLoginUser = userStore.userName
// 用户名 // 用户名
const userName = ref('') const userName = ref('')
@@ -199,13 +202,15 @@ async function updateUser() {
if (oldUserName !== currentUserName.value) { if (oldUserName !== currentUserName.value) {
$toast.success(`${oldUserName}】更名【${currentUserName.value}】, 更新成功!`) $toast.success(`${oldUserName}】更名【${currentUserName.value}】, 更新成功!`)
// 如果是当前登录用户,更新当前用户名称显示 // 如果是当前登录用户,更新当前用户名称显示
if (isCurrentUser.value) store.commit('auth/setUserName', currentUserName.value) if (isCurrentUser.value) {
userStore.setUserName(currentUserName.value)
}
} else { } else {
$toast.success(`${userForm.value?.name}】更新成功!`) $toast.success(`${userForm.value?.name}】更新成功!`)
} }
// 更新本地头像显示 // 更新本地头像显示
if (oldAvatar !== currentAvatar.value && isCurrentUser.value) { if (oldAvatar !== currentAvatar.value && isCurrentUser.value) {
store.commit('auth/setAvatar', currentAvatar.value) userStore.setAvatar(currentAvatar.value)
} }
emit('save') emit('save')
} else { } else {
+5 -2
View File
@@ -8,7 +8,7 @@ import UserNofification from '@/layouts/components/UserNotification.vue'
import SearchBar from '@/layouts/components/SearchBar.vue' import SearchBar from '@/layouts/components/SearchBar.vue'
import ShortcutBar from '@/layouts/components/ShortcutBar.vue' import ShortcutBar from '@/layouts/components/ShortcutBar.vue'
import UserProfile from '@/layouts/components/UserProfile.vue' import UserProfile from '@/layouts/components/UserProfile.vue'
import store from '@/store' import { useUserStore } from '@/stores'
import { SystemNavMenus } from '@/router/menu' import { SystemNavMenus } from '@/router/menu'
import { NavMenu } from '@/@layouts/types' import { NavMenu } from '@/@layouts/types'
import { useDisplay } from 'vuetify' import { useDisplay } from 'vuetify'
@@ -16,8 +16,11 @@ import { useDisplay } from 'vuetify'
const display = useDisplay() const display = useDisplay()
const appMode = inject('pwaMode') const appMode = inject('pwaMode')
// 用户 Store
const userStore = useUserStore()
// 是否超级用户 // 是否超级用户
let superUser = store.state.auth.superUser let superUser = userStore.superUser
// 开始菜单项 // 开始菜单项
const startMenus = ref<NavMenu[]>([]) const startMenus = ref<NavMenu[]>([])
+11 -9
View File
@@ -1,5 +1,4 @@
<script setup lang="ts"> <script setup lang="ts">
import { useStore } from 'vuex'
import { useConfirm } from 'vuetify-use-dialog' import { useConfirm } from 'vuetify-use-dialog'
import { useToast } from 'vue-toast-notification' import { useToast } from 'vue-toast-notification'
import router from '@/router' import router from '@/router'
@@ -7,9 +6,12 @@ import avatar1 from '@images/avatars/avatar-1.png'
import api from '@/api' import api from '@/api'
import ProgressDialog from '@/components/dialog/ProgressDialog.vue' import ProgressDialog from '@/components/dialog/ProgressDialog.vue'
import UserAuthDialog from '@/components/dialog/UserAuthDialog.vue' import UserAuthDialog from '@/components/dialog/UserAuthDialog.vue'
import { useAuthStore, useUserStore } from '@/stores'
// Vuex Store // 认证 Store
const store = useStore() const authStore = useAuthStore()
// 用户 Store
const userStore = useUserStore()
// 确认框 // 确认框
const createConfirm = useConfirm() const createConfirm = useConfirm()
@@ -29,7 +31,7 @@ const restartDialog = ref(false)
// 执行注销操作 // 执行注销操作
function logout() { function logout() {
// 清除登录状态信息 // 清除登录状态信息
store.dispatch('auth/logout') authStore.logout()
// 重定向到登录页面或其他适当的页面 // 重定向到登录页面或其他适当的页面
router.push('/login') router.push('/login')
} }
@@ -74,11 +76,11 @@ function siteAuthDone() {
logout() logout()
} }
// 从Vuex Store中获取信息 // 从用户 Store中获取信息
const superUser = computed(() => store.state.auth.superUser) const superUser = computed(() => userStore.superUser)
const userName = computed(() => store.state.auth.userName) const userName = computed(() => userStore.userName)
const avatar = computed(() => store.state.auth.avatar || avatar1) const avatar = computed(() => userStore.avatar || avatar1)
const userLevel = computed(() => store.state.auth.level) const userLevel = computed(() => userStore.level)
</script> </script>
<template> <template>
+7 -6
View File
@@ -8,7 +8,7 @@ import '@/plugins/webfontloader'
import { createApp } from 'vue' import { createApp } from 'vue'
import vuetify from '@/plugins/vuetify' import vuetify from '@/plugins/vuetify'
import router from '@/router' import router from '@/router'
import store from '@/store' import pinia from '@/stores/index'
// 3. 全局组件 // 3. 全局组件
import App from '@/App.vue' import App from '@/App.vue'
@@ -65,10 +65,13 @@ async function initializeApp() {
// 注册全局组件 // 注册全局组件
initializeApp().then(() => { initializeApp().then(() => {
// 优先注册框架 // 1. 注册 UI 框架
app.use(vuetify) app.use(vuetify)
// 注册全局组件 // 2. 注册状态管理与路由
app.use(pinia).use(router)
// 3. 注册全局组件
app app
.component('VAceEditor', VAceEditor) .component('VAceEditor', VAceEditor)
.component('VApexChart', VueApexCharts) .component('VApexChart', VueApexCharts)
@@ -84,10 +87,8 @@ initializeApp().then(() => {
.component('VCronField', CronField) .component('VCronField', CronField)
.component('VPathField', PathField) .component('VPathField', PathField)
// 注册插件 // 4. 注册其他插件
app app
.use(router)
.use(store)
.use(PerfectScrollbarPlugin) .use(PerfectScrollbarPlugin)
.use(ToastPlugin, { .use(ToastPlugin, {
position: 'bottom-right', position: 'bottom-right',
+3 -3
View File
@@ -1,11 +1,11 @@
<script setup lang="ts"> <script setup lang="ts">
import { NavMenu } from '@/@layouts/types' import { NavMenu } from '@/@layouts/types'
import { SystemNavMenus } from '@/router/menu' import { SystemNavMenus } from '@/router/menu'
import store from '@/store' import { useUserStore } from '@/stores'
import draggable from 'vuedraggable' import draggable from 'vuedraggable'
// 从Vuex Store中获取superuser信息 // 从 Store 中获取superuser信息
const superUser = store.state.auth.superUser const superUser = useUserStore().superUser
// APP图标顺序 // APP图标顺序
const appOrder = ref<string[]>([]) const appOrder = ref<string[]>([])
+3 -3
View File
@@ -3,7 +3,7 @@ import draggable from 'vuedraggable'
import api from '@/api' import api from '@/api'
import { isNullOrEmptyObject } from '@/@core/utils' import { isNullOrEmptyObject } from '@/@core/utils'
import { DashboardItem } from '@/api/types' import { DashboardItem } from '@/api/types'
import store from '@/store' import { useUserStore } from '@/stores'
import DashboardElement from '@/components/misc/DashboardElement.vue' import DashboardElement from '@/components/misc/DashboardElement.vue'
import { useDisplay } from 'vuetify' import { useDisplay } from 'vuetify'
@@ -11,8 +11,8 @@ import { useDisplay } from 'vuetify'
const display = useDisplay() const display = useDisplay()
const appMode = inject('pwaMode') && display.mdAndDown.value const appMode = inject('pwaMode') && display.mdAndDown.value
// 从Vuex Store中获取superuser信息 // 从用户 Store 中获取superuser信息
const superUser = store.state.auth.superUser const superUser = useUserStore().superUser
// 是否拉升高度 // 是否拉升高度
const isElevated = ref(true) const isElevated = ref(true)
+27 -29
View File
@@ -1,7 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { debounce } from 'lodash' import { debounce } from 'lodash'
import { VForm } from 'vuetify/components/VForm' import { VForm } from 'vuetify/components/VForm'
import { useStore } from 'vuex' import { useAuthStore, useUserStore } from '@/stores'
import { authState, userState } from '@/stores/types'
import { requiredValidator } from '@/@validators' import { requiredValidator } from '@/@validators'
import api from '@/api' import api from '@/api'
import router from '@/router' import router from '@/router'
@@ -11,10 +12,12 @@ import { checkPrefersColorSchemeIsDark } from '@/@core/utils'
import { urlBase64ToUint8Array } from '@/@core/utils/navigator' import { urlBase64ToUint8Array } from '@/@core/utils/navigator'
import { saveLocalTheme } from '@/@core/utils/theme' import { saveLocalTheme } from '@/@core/utils/theme'
// 主题
const { global: globalTheme } = useTheme() const { global: globalTheme } = useTheme()
// 认证 Store
// Vuex Store const authStore = useAuthStore()
const store = useStore() //用户 Store
const userStore = useUserStore()
// 表单 // 表单
const form = ref({ const form = ref({
@@ -119,7 +122,7 @@ async function afterLogin(superuser: boolean) {
// 生效主题配置 // 生效主题配置
await setTheme() await setTheme()
// 跳转到首页或回原始页面 // 跳转到首页或回原始页面
router.push(store.state.auth.originalPath ?? '/') router.push(authStore.originalPath ?? '/')
// 订阅推送通知 // 订阅推送通知
if (superuser) await subscribeForPushNotifications() if (superuser) await subscribeForPushNotifications()
} }
@@ -147,30 +150,25 @@ function login() {
}, },
}) })
.then((response: any) => { .then((response: any) => {
// 获取token const authPayLoad: authState = {
const token = response.access_token token: response.access_token,
const superUser = response.super_user remember: form.value.remember,
const userID = response.user_id }
const userName = response.user_name
const avatar = response.avatar
const level = response.level
const remember = form.value.remember
const permissions = response.permissions
// 更新token和remember状态到Vuex Store const userPayload: userState = {
store.dispatch('auth/login', { superUser: response.super_user,
token, userID: response.user_id,
remember, userName: response.user_name,
superUser, avatar: response.avatar,
userID, level: response.level,
userName, permissions: response.permissions,
avatar, }
level,
permissions, authStore.login(authPayLoad)
}) userStore.loginUser(userPayload)
// 登录后处理 // 登录后处理
afterLogin(superUser) afterLogin(userPayload.superUser)
}) })
.catch((error: any) => { .catch((error: any) => {
// 登录失败,显示错误提示 // 登录失败,显示错误提示
@@ -191,9 +189,9 @@ function startBackgroundRotation() {
// 自动登录 // 自动登录
onMounted(async () => { onMounted(async () => {
// 从Vuex Store中获取token和remember状态 // 获取token和remember状态
const token = store.state.auth.token const token = authStore.token
const remember = store.state.auth.remember const remember = authStore.remember
// 如果token存在,且保持登录状态为true,则跳转到首页 // 如果token存在,且保持登录状态为true,则跳转到首页
if (token && remember) { if (token && remember) {
+5 -3
View File
@@ -1,6 +1,6 @@
import { createRouter, createWebHashHistory } from 'vue-router' import { createRouter, createWebHashHistory } from 'vue-router'
import { configureNProgress } from '@/api/nprogress' import { configureNProgress } from '@/api/nprogress'
import store from '@/store' import { useAuthStore } from '@/stores'
// Nprogress // Nprogress
configureNProgress() configureNProgress()
@@ -215,9 +215,11 @@ function abortAllControllers() {
// 路由导航守卫 // 路由导航守卫
router.beforeEach((to: any, from: any, next: any) => { router.beforeEach((to: any, from: any, next: any) => {
// 认证 Store
const authStore = useAuthStore()
// 总是记录非login路由 // 总是记录非login路由
if (to.fullPath != '/login') store.state.auth.originalPath = to.fullPath if (to.fullPath != '/login') authStore.originalPath = to.fullPath
const isAuthenticated = store.state.auth.token !== null const isAuthenticated = authStore.token !== null
if (to.meta.requiresAuth && !isAuthenticated) { if (to.meta.requiresAuth && !isAuthenticated) {
next('/login') next('/login')
} else { } else {
-96
View File
@@ -1,96 +0,0 @@
import type { Module } from 'vuex'
// 定义状态类型
interface AuthState {
token: string | null
remember: boolean
superUser: boolean
userID: number
userName: string
avatar: string
originalPath: string | null
level: number
permissions: { [key: string]: any }
}
// 定义根状态类型
interface RootState {
auth: AuthState
}
// 用户信息模块
const authModule: Module<AuthState, RootState> = {
namespaced: true,
state: {
token: null, // 用户令牌
remember: false, // 记住我
superUser: false, // 超级管理员
userID: 999, // 用户ID
userName: '', // 用户名
avatar: '', // 头像
originalPath: null, // 原始路径
level: 1, // 用户认证等级 1-未认证 2-已认证
permissions: {},
},
mutations: {
setToken(state, token: string) {
state.token = token
},
clearToken(state) {
state.token = null
},
setRemember(state, remember: boolean) {
state.remember = remember
},
setSuperUser(state, superUser: boolean) {
state.superUser = superUser
},
setUserID(state, userID: number) {
state.userID = userID
},
setUserName(state, userName: string) {
state.userName = userName
},
setAvatar(state, avatar: string) {
state.avatar = avatar
},
setOriginalPath(state, originalPath: string) {
state.originalPath = originalPath
},
setLevel(state, level: number) {
state.level = level
},
setPermissions(state, permissions: object) {
state.permissions = permissions
},
},
actions: {
login({ commit }, { token, remember, superUser, userID, userName, avatar, level, permissions }) {
commit('setToken', token)
commit('setRemember', remember)
commit('setSuperUser', superUser)
commit('setUserID', userID)
commit('setUserName', userName)
commit('setAvatar', avatar)
commit('setLevel', level)
commit('setPermissions', permissions)
},
logout({ commit }) {
commit('clearToken')
commit('setOriginalPath', null)
},
},
getters: {
getToken: state => state.token,
getRemember: state => state.remember,
getSuperUser: state => state.superUser,
getUserID: state => state.userID,
getUserName: state => state.userName,
getAvatar: state => state.avatar,
getOriginalPath: state => state.originalPath,
getLevel: state => state.level,
getPermissions: state => state.permissions,
},
}
export default authModule
-19
View File
@@ -1,19 +0,0 @@
import { createStore } from 'vuex'
import createPersistedState from 'vuex-persistedstate'
import authModule from './auth'
const store = createStore({
modules: {
// 用户认证store
auth: authModule,
},
plugins: [
createPersistedState({
// 配置持久化存储的选项
storage: window.localStorage, // 使用 localStorage 存储状态
key: 'moviepilot', // 存储的键名
}),
],
})
export default store
+42
View File
@@ -0,0 +1,42 @@
import { defineStore } from 'pinia'
import type { authState } from '@/stores/types'
export const useAuthStore = defineStore('auth', {
state: (): authState => ({
token: null,
remember: false,
originalPath: null,
}),
// 全局持久化
persist: true,
actions: {
setToken(token: string | null) {
this.token = token
},
clearToken() {
this.token = null
},
setRemember(remember: boolean) {
this.remember = remember
},
setOriginalPath(originalPath: string | null) {
this.originalPath = originalPath
},
login(payload: authState) {
this.setToken(payload.token)
this.setRemember(payload.remember)
},
logout() {
this.clearToken()
this.setOriginalPath(null)
},
},
getters: {
getToken: state => state.token,
getRemember: state => state.remember,
getOriginalPath: state => state.originalPath,
},
})
+16
View File
@@ -0,0 +1,16 @@
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
// 创建 Pinia 实例
const pinia = createPinia()
// 使用持久化插件
pinia.use(piniaPluginPersistedstate)
export default pinia
// 所有的 store
import { useAuthStore } from './auth'
import { useUserStore } from './user'
export { useAuthStore, useUserStore }
+23
View File
@@ -0,0 +1,23 @@
export interface authState {
// 用户令牌
token: string | null
// 记住我
remember: boolean
// 原始路径
originalPath?: string | null
}
export interface userState {
// 是否属于超级管理员
superUser: boolean
// 用户ID
userID: number
// 用户名
userName: string
// 头像
avatar: string
// 用户认证等级 1-未认证 2-已认证
level: number
// 权限
permissions: { [key: string]: any }
}
+62
View File
@@ -0,0 +1,62 @@
import { defineStore } from 'pinia'
import type { userState } from '@/stores/types'
export const useUserStore = defineStore('user', {
state: (): userState => ({
superUser: false,
userID: -1,
userName: '',
avatar: '',
level: 1,
permissions: {},
}),
// 全局持久化
persist: true,
actions: {
setSuperUser(superUser: boolean) {
this.superUser = superUser
},
setUserID(userID: number) {
this.userID = userID
},
setUserName(userName: string) {
this.userName = userName
},
setAvatar(avatar: string) {
this.avatar = avatar
},
setLevel(level: number) {
this.level = level
},
setPermissions(permissions: object) {
this.permissions = permissions
},
loginUser(payload: userState) {
this.setSuperUser(payload.superUser)
this.setUserID(payload.userID)
this.setUserName(payload.userName)
this.setAvatar(payload.avatar)
this.setLevel(payload.level)
this.setPermissions(payload.permissions)
},
reset() {
this.setSuperUser(false)
this.setUserID(-1)
this.setUserName('')
this.setAvatar('')
this.setLevel(1)
this.setPermissions({})
},
},
getters: {
getSuperUser: state => state.superUser,
getUserID: state => state.userID,
getUserName: state => state.userName,
getAvatar: state => state.avatar,
getLevel: state => state.level,
getPermissions: state => state.permissions,
},
})
@@ -2,12 +2,13 @@
import { useTheme } from 'vuetify' import { useTheme } from 'vuetify'
import api from '@/api' import api from '@/api'
import { hexToRgb } from '@layouts/utils' import { hexToRgb } from '@layouts/utils'
import { useUserStore } from '@/stores'
const vuetifyTheme = useTheme() const vuetifyTheme = useTheme()
// 从Vuex Store中获取信息 // 用户 Store
const store = useStore() const userStore = useUserStore()
const superUser = store.state.auth.superUser const superUser = userStore.superUser
const options = controlledComputed( const options = controlledComputed(
() => vuetifyTheme.name.value, () => vuetifyTheme.name.value,
+4 -2
View File
@@ -10,6 +10,7 @@ import { formatSeason } from '@/@core/utils/formatters'
import router from '@/router' import router from '@/router'
import SubscribeEditDialog from '@/components/dialog/SubscribeEditDialog.vue' import SubscribeEditDialog from '@/components/dialog/SubscribeEditDialog.vue'
import { isNullOrEmptyObject } from '@/@core/utils' import { isNullOrEmptyObject } from '@/@core/utils'
import { useUserStore } from '@/stores'
// 输入参数 // 输入参数
const mediaProps = defineProps({ const mediaProps = defineProps({
@@ -22,7 +23,8 @@ const mediaProps = defineProps({
// 从 provide 中获取全局设置 // 从 provide 中获取全局设置
const globalSettings: any = inject('globalSettings') const globalSettings: any = inject('globalSettings')
const store = useStore() // 用户 Store
const userStore = useUserStore()
// 提示框 // 提示框
const $toast = useToast() const $toast = useToast()
@@ -466,7 +468,7 @@ async function handlePlay() {
async function queryDefaultSubscribeConfig() { async function queryDefaultSubscribeConfig() {
// 非管理员不显示 // 非管理员不显示
if (!store.state.auth.superUser) return false if (!userStore.superUser) return false
try { try {
let subscribe_config_url = '' let subscribe_config_url = ''
if (mediaProps.type === '电影') subscribe_config_url = 'system/setting/DefaultMovieSubscribeConfig' if (mediaProps.type === '电影') subscribe_config_url = 'system/setting/DefaultMovieSubscribeConfig'
+7 -4
View File
@@ -4,13 +4,16 @@ import api from '@/api'
import type { DownloadingInfo } from '@/api/types' import type { DownloadingInfo } from '@/api/types'
import NoDataFound from '@/components/NoDataFound.vue' import NoDataFound from '@/components/NoDataFound.vue'
import DownloadingCard from '@/components/cards/DownloadingCard.vue' import DownloadingCard from '@/components/cards/DownloadingCard.vue'
import store from '@/store' import { useUserStore } from '@/stores'
// 定义输入参数 // 定义输入参数
const props = defineProps<{ const props = defineProps<{
name: string name: string
}>() }>()
// 用户 Store
const userStore = useUserStore()
// 定时器 // 定时器
let refreshTimer: NodeJS.Timeout | null = null let refreshTimer: NodeJS.Timeout | null = null
@@ -42,9 +45,9 @@ function onRefresh() {
// 过滤数据,管理员用户显示全部,非管理员只显示自己的订阅 // 过滤数据,管理员用户显示全部,非管理员只显示自己的订阅
const filteredDataList = computed(() => { const filteredDataList = computed(() => {
// 从Vuex Store中获取用户信息 // 从 Store 中获取用户信息
const superUser = store.state.auth.superUser const superUser = userStore.superUser
const userName = store.state.auth.userName const userName = userStore.userName
if (superUser) return dataList.value if (superUser) return dataList.value
else return dataList.value.filter(data => data.userid === userName || data.username === userName) else return dataList.value.filter(data => data.userid === userName || data.username === userName)
}) })
+9 -6
View File
@@ -6,13 +6,16 @@ import NoDataFound from '@/components/NoDataFound.vue'
import SubscribeCard from '@/components/cards/SubscribeCard.vue' import SubscribeCard from '@/components/cards/SubscribeCard.vue'
import SubscribeEditDialog from '@/components/dialog/SubscribeEditDialog.vue' import SubscribeEditDialog from '@/components/dialog/SubscribeEditDialog.vue'
import SubscribeHistoryDialog from '@/components/dialog/SubscribeHistoryDialog.vue' import SubscribeHistoryDialog from '@/components/dialog/SubscribeHistoryDialog.vue'
import store from '@/store' import { useUserStore } from '@/stores'
import { useDisplay } from 'vuetify' import { useDisplay } from 'vuetify'
// APP // APP
const display = useDisplay() const display = useDisplay()
const appMode = inject('pwaMode') && display.mdAndDown.value const appMode = inject('pwaMode') && display.mdAndDown.value
// 用户 Store
const userStore = useUserStore()
// 输入参数 // 输入参数
const props = defineProps({ const props = defineProps({
type: String, type: String,
@@ -46,9 +49,9 @@ const displayList = ref<Subscribe[]>([])
// 监听dataList变化,同步更新displayList // 监听dataList变化,同步更新displayList
watch(dataList, () => { watch(dataList, () => {
// 从Vuex Store中获取用户信息 // 从 Store 中获取用户信息
const superUser = store.state.auth.superUser const superUser = userStore.superUser
const userName = store.state.auth.userName const userName = userStore.userName
if (superUser) displayList.value = dataList.value.filter(data => data.type === props.type) if (superUser) displayList.value = dataList.value.filter(data => data.type === props.type)
else displayList.value = dataList.value.filter(data => data.type === props.type && data.username === userName) else displayList.value = dataList.value.filter(data => data.type === props.type && data.username === userName)
// 排序 // 排序
@@ -163,7 +166,7 @@ onActivated(async () => {
<!-- 底部操作按钮 --> <!-- 底部操作按钮 -->
<div v-if="isRefreshed"> <div v-if="isRefreshed">
<VFab <VFab
v-if="store.state.auth.superUser" v-if="userStore.superUser"
icon="mdi-clipboard-edit" icon="mdi-clipboard-edit"
location="bottom" location="bottom"
size="x-large" size="x-large"
@@ -174,7 +177,7 @@ onActivated(async () => {
:class="{ 'mb-12': appMode }" :class="{ 'mb-12': appMode }"
/> />
<VFab <VFab
v-if="store.state.auth.superUser" v-if="userStore.superUser"
icon="mdi-history" icon="mdi-history"
color="info" color="info"
location="bottom" location="bottom"
+6 -3
View File
@@ -3,16 +3,19 @@ import api from '@/api'
import type { Plugin, Site, Subscribe } from '@/api/types' import type { Plugin, Site, Subscribe } from '@/api/types'
import { SystemNavMenus, SettingTabs } from '@/router/menu' import { SystemNavMenus, SettingTabs } from '@/router/menu'
import { NavMenu } from '@/@layouts/types' import { NavMenu } from '@/@layouts/types'
import store from '@/store' import { useUserStore } from '@/stores'
// 路由 // 路由
const router = useRouter() const router = useRouter()
// 用户 Store
const userStore = useUserStore()
// 超级用户 // 超级用户
const superUser = store.state.auth.superUser const superUser = userStore.superUser
// 当前用户名 // 当前用户名
const userName = store.state.auth.userName const userName = userStore.userName
// 定义事件 // 定义事件
const emit = defineEmits(['close']) const emit = defineEmits(['close'])
+9 -12
View File
@@ -6,7 +6,7 @@ import api from '@/api'
import type { User } from '@/api/types' import type { User } from '@/api/types'
import avatar1 from '@images/avatars/avatar-1.png' import avatar1 from '@images/avatars/avatar-1.png'
import { useDisplay } from 'vuetify' import { useDisplay } from 'vuetify'
import store from '@/store' import { useUserStore } from '@/stores'
// 显示器宽度 // 显示器宽度
const display = useDisplay() const display = useDisplay()
@@ -16,6 +16,9 @@ const isConfirmPasswordVisible = ref(false)
const newPassword = ref('') const newPassword = ref('')
const confirmPassword = ref('') const confirmPassword = ref('')
// 用户 Store
const userStore = useUserStore()
// 提示框 // 提示框
const $toast = useToast() const $toast = useToast()
@@ -53,13 +56,7 @@ const accountInfo = ref<User>({
avatar: '', avatar: '',
is_otp: false, is_otp: false,
permissions: {}, permissions: {},
settings: { settings: {},
wechat_userid: null,
telegram_userid: null,
slack_userid: null,
vocechat_userid: null,
synologychat_userid: null,
},
}) })
// 二维码信息 // 二维码信息
@@ -149,13 +146,13 @@ async function saveAccountInfo() {
if (oldUserName !== currentUserName.value) { if (oldUserName !== currentUserName.value) {
$toast.success(`${oldUserName}】更名【${currentUserName.value}】,用户信息保存成功!`) $toast.success(`${oldUserName}】更名【${currentUserName.value}】,用户信息保存成功!`)
// 更新本地用户名显示 // 更新本地用户名显示
store.commit('auth/setUserName', currentUserName.value) userStore.setUserName(currentUserName.value)
} else { } else {
$toast.success('用户信息保存成功!') $toast.success('用户信息保存成功!')
} }
// 更新本地头像显示 // 更新本地头像显示
if (oldAvatar !== currentAvatar.value) { if (oldAvatar !== currentAvatar.value) {
store.commit('auth/setAvatar', currentAvatar.value) userStore.setAvatar(currentAvatar.value)
} }
} else { } else {
if (oldAvatar !== currentAvatar.value) { if (oldAvatar !== currentAvatar.value) {
@@ -238,9 +235,9 @@ onMounted(() => {
// 监听 localStorage 中的用户头像变化 // 监听 localStorage 中的用户头像变化
watch( watch(
() => store.state.auth.avatar, () => userStore.avatar,
() => { () => {
currentAvatar.value = store.state.auth.avatar currentAvatar.value = userStore.avatar
}, },
) )
</script> </script>