Merge pull request #303 from Aqr-K/build/reduce-size

This commit is contained in:
jxxghp
2025-02-25 06:57:48 +08:00
committed by GitHub
36 changed files with 685 additions and 284 deletions

View File

@@ -1,6 +1,6 @@
import axios from 'axios'
import router from '@/router'
import store from '@/store'
import { useAuthStore } from '@/stores'
// 创建axios实例
const api = axios.create({
@@ -9,10 +9,12 @@ const api = axios.create({
// 添加请求拦截器
api.interceptors.request.use(config => {
// 认证 Store
const authStore = useAuthStore()
// 在请求头中添加token
const token = store.state.auth.token
if (token) config.headers.Authorization = `Bearer ${token}`
if (authStore.token) {
config.headers.Authorization = `Bearer ${authStore.token}`
}
return config
})
@@ -26,8 +28,10 @@ api.interceptors.response.use(
// 请求超时
return Promise.reject(new Error(error))
} else if (error.response.status === 403) {
// 认证 Store
const authStore = useAuthStore()
// 清除登录状态信息
store.dispatch('auth/logout')
authStore.logout()
// token验证失败跳转到登录页面
router.push('/login')
}

View File

@@ -2,7 +2,7 @@
import { CustomRule } from '@/api/types'
import { useToast } from 'vue-toast-notification'
import filter_svg from '@images/svg/filter.svg'
import { cloneDeep } from 'lodash'
import { cloneDeep } from 'lodash-es'
import { innerFilterRules } from '@/api/constants'
// 输入参数

View File

@@ -6,7 +6,7 @@ import { useToast } from 'vue-toast-notification'
import type { DownloaderInfo } from '@/api/types'
import qbittorrent_image from '@images/logos/qbittorrent.png'
import transmission_image from '@images/logos/transmission.png'
import { cloneDeep } from 'lodash'
import { cloneDeep } from 'lodash-es'
// 定义输入
const props = defineProps({
@@ -104,7 +104,7 @@ function saveDownloaderInfo() {
props.downloaders.forEach(item => {
if (item.default && item !== props.downloader) {
item.default = false
$toast.info(`${item.name}存在默认下载器,已替换成【${downloaderInfo.value.name}`)
$toast.info(`存在默认下载器${item.name}】,已替换成【${downloaderInfo.value.name}`)
}
})
}

View File

@@ -1,7 +1,7 @@
<script lang="ts" setup>
import { innerFilterRules } from '@/api/constants'
import { CustomRule } from '@/api/types'
import { cloneDeep } from 'lodash'
import { cloneDeep } from 'lodash-es'
// 输入参数
const props = defineProps({

View File

@@ -6,7 +6,7 @@ import FilterRuleCard from '@/components/cards/FilterRuleCard.vue'
import { useToast } from 'vue-toast-notification'
import ImportCodeDialog from '@/components/dialog/ImportCodeDialog.vue'
import filter_group_svg from '@images/svg/filter-group.svg'
import { cloneDeep } from 'lodash'
import { cloneDeep } from 'lodash-es'
// 输入参数
const props = defineProps({

View File

@@ -11,6 +11,7 @@ import noImage from '@images/no-image.jpeg'
import tmdbImage from '@images/logos/tmdb.png'
import doubanImage from '@images/logos/douban-black.png'
import bangumiImage from '@images/logos/bangumi.png'
import { useUserStore } from '@/stores'
// 输入参数
const props = defineProps({
@@ -22,7 +23,8 @@ const props = defineProps({
// 从 provide 中获取全局设置
const globalSettings: any = inject('globalSettings')
const store = useStore()
// 用户 Store
const userStore = useUserStore()
// 提示框
const $toast = useToast()
@@ -340,7 +342,7 @@ async function getMediaSeasons() {
// 查询订阅弹窗规则
async function queryDefaultSubscribeConfig() {
// 非管理员不显示
if (!store.state.auth.superUser) return false
if (!userStore.superUser) return false
try {
let subscribe_config_url = ''
if (props.media?.type === '电影') subscribe_config_url = 'system/setting/DefaultMovieSubscribeConfig'

View File

@@ -5,7 +5,7 @@ import emby_image from '@images/logos/emby.png'
import jellyfin_image from '@images/logos/jellyfin.png'
import plex_image from '@images/logos/plex.png'
import api from '@/api'
import { cloneDeep } from 'lodash'
import { cloneDeep } from 'lodash-es'
// 定义输入
const props = defineProps({

View File

@@ -7,7 +7,7 @@ import synologychat_image from '@images/logos/synologychat.png'
import slack_image from '@images/logos/slack.webp'
import chrome_image from '@images/logos/chrome.png'
import { useToast } from 'vue-toast-notification'
import { cloneDeep } from 'lodash'
import { cloneDeep } from 'lodash-es'
// 定义输入
const props = defineProps({

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import api from '@/api'
import { Subscribe, User } from '@/api/types'
import store from '@/store'
import { useUserStore } from '@/stores'
import avatar1 from '@images/avatars/avatar-1.png'
import { useToast } from 'vue-toast-notification'
import { useConfirm } from 'vuetify-use-dialog'
@@ -22,10 +22,10 @@ const props = defineProps({
})
// 当前用户的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'])
@@ -161,14 +161,7 @@ onMounted(() => {
</VList>
</VCardText>
<VCardText class="flex flex-row justify-center">
<VBtn
v-if="currentUserIsSuperuser"
color="primary"
class="me-4"
@click="editUser"
>
编辑
</VBtn>
<VBtn v-if="currentUserIsSuperuser" color="primary" class="me-4" @click="editUser"> 编辑 </VBtn>
<VBtn
v-if="currentUserIsSuperuser && props.user.id != currentLoginUserId"
color="error"

View File

@@ -5,7 +5,7 @@ import { doneNProgress, startNProgress } from '@/api/nprogress'
import api from '@/api'
import { useDisplay } from 'vuetify'
import avatar1 from '@images/avatars/avatar-1.png'
import store from '@/store'
import { useUserStore } from '@/stores'
// 显示器宽度
const display = useDisplay()
@@ -23,8 +23,11 @@ const props = defineProps({
oper: String,
})
// 用户 Store
const userStore = useUserStore()
// 当前登录用户名称
const currentLoginUser = store.state.auth.userName
const currentLoginUser = userStore.userName
// 用户名
const userName = ref('')
@@ -199,13 +202,15 @@ async function updateUser() {
if (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 {
$toast.success(`${userForm.value?.name}】更新成功!`)
}
// 更新本地头像显示
if (oldAvatar !== currentAvatar.value && isCurrentUser.value) {
store.commit('auth/setAvatar', currentAvatar.value)
userStore.setAvatar(currentAvatar.value)
}
emit('save')
} else {

View File

@@ -8,7 +8,7 @@ import UserNofification from '@/layouts/components/UserNotification.vue'
import SearchBar from '@/layouts/components/SearchBar.vue'
import ShortcutBar from '@/layouts/components/ShortcutBar.vue'
import UserProfile from '@/layouts/components/UserProfile.vue'
import store from '@/store'
import { useUserStore } from '@/stores'
import { SystemNavMenus } from '@/router/menu'
import { NavMenu } from '@/@layouts/types'
import { useDisplay } from 'vuetify'
@@ -16,8 +16,11 @@ import { useDisplay } from 'vuetify'
const display = useDisplay()
const appMode = inject('pwaMode')
// 用户 Store
const userStore = useUserStore()
// 是否超级用户
let superUser = store.state.auth.superUser
let superUser = userStore.superUser
// 开始菜单项
const startMenus = ref<NavMenu[]>([])

View File

@@ -1,5 +1,4 @@
<script setup lang="ts">
import { useStore } from 'vuex'
import { useConfirm } from 'vuetify-use-dialog'
import { useToast } from 'vue-toast-notification'
import router from '@/router'
@@ -7,9 +6,12 @@ import avatar1 from '@images/avatars/avatar-1.png'
import api from '@/api'
import ProgressDialog from '@/components/dialog/ProgressDialog.vue'
import UserAuthDialog from '@/components/dialog/UserAuthDialog.vue'
import { useAuthStore, useUserStore } from '@/stores'
// Vuex Store
const store = useStore()
// 认证 Store
const authStore = useAuthStore()
// 用户 Store
const userStore = useUserStore()
// 确认框
const createConfirm = useConfirm()
@@ -29,7 +31,7 @@ const restartDialog = ref(false)
// 执行注销操作
function logout() {
// 清除登录状态信息
store.dispatch('auth/logout')
authStore.logout()
// 重定向到登录页面或其他适当的页面
router.push('/login')
}
@@ -74,11 +76,11 @@ function siteAuthDone() {
logout()
}
// 从Vuex Store中获取信息
const superUser = computed(() => store.state.auth.superUser)
const userName = computed(() => store.state.auth.userName)
const avatar = computed(() => store.state.auth.avatar || avatar1)
const userLevel = computed(() => store.state.auth.level)
// 从用户 Store中获取信息
const superUser = computed(() => userStore.superUser)
const userName = computed(() => userStore.userName)
const avatar = computed(() => userStore.avatar || avatar1)
const userLevel = computed(() => userStore.level)
</script>
<template>

View File

@@ -8,7 +8,7 @@ import '@/plugins/webfontloader'
import { createApp } from 'vue'
import vuetify from '@/plugins/vuetify'
import router from '@/router'
import store from '@/store'
import pinia from '@/stores/index'
// 3. 全局组件
import App from '@/App.vue'
@@ -65,10 +65,13 @@ async function initializeApp() {
// 注册全局组件
initializeApp().then(() => {
// 优先注册框架
// 1. 注册 UI 框架
app.use(vuetify)
// 注册全局组件
// 2. 注册状态管理与路由
app.use(pinia).use(router)
// 3. 注册全局组件
app
.component('VAceEditor', VAceEditor)
.component('VApexChart', VueApexCharts)
@@ -84,10 +87,8 @@ initializeApp().then(() => {
.component('VCronField', CronField)
.component('VPathField', PathField)
// 注册插件
// 4. 注册其他插件
app
.use(router)
.use(store)
.use(PerfectScrollbarPlugin)
.use(ToastPlugin, {
position: 'bottom-right',

View File

@@ -1,11 +1,11 @@
<script setup lang="ts">
import { NavMenu } from '@/@layouts/types'
import { SystemNavMenus } from '@/router/menu'
import store from '@/store'
import { useUserStore } from '@/stores'
import draggable from 'vuedraggable'
// 从Vuex Store中获取superuser信息
const superUser = store.state.auth.superUser
// 从 Store 中获取superuser信息
const superUser = useUserStore().superUser
// APP图标顺序
const appOrder = ref<string[]>([])

View File

@@ -3,7 +3,7 @@ import draggable from 'vuedraggable'
import api from '@/api'
import { isNullOrEmptyObject } from '@/@core/utils'
import { DashboardItem } from '@/api/types'
import store from '@/store'
import { useUserStore } from '@/stores'
import DashboardElement from '@/components/misc/DashboardElement.vue'
import { useDisplay } from 'vuetify'
@@ -11,8 +11,8 @@ import { useDisplay } from 'vuetify'
const display = useDisplay()
const appMode = inject('pwaMode') && display.mdAndDown.value
// 从Vuex Store中获取superuser信息
const superUser = store.state.auth.superUser
// 从用户 Store 中获取superuser信息
const superUser = useUserStore().superUser
// 是否拉升高度
const isElevated = ref(true)

View File

@@ -1,7 +1,8 @@
<script setup lang="ts">
import { debounce } from 'lodash'
import { debounce } from 'lodash-es'
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 api from '@/api'
import router from '@/router'
@@ -11,10 +12,12 @@ import { checkPrefersColorSchemeIsDark } from '@/@core/utils'
import { urlBase64ToUint8Array } from '@/@core/utils/navigator'
import { saveLocalTheme } from '@/@core/utils/theme'
// 主题
const { global: globalTheme } = useTheme()
// Vuex Store
const store = useStore()
// 认证 Store
const authStore = useAuthStore()
//用户 Store
const userStore = useUserStore()
// 表单
const form = ref({
@@ -119,7 +122,7 @@ async function afterLogin(superuser: boolean) {
// 生效主题配置
await setTheme()
// 跳转到首页或回原始页面
router.push(store.state.auth.originalPath ?? '/')
router.push(authStore.originalPath ?? '/')
// 订阅推送通知
if (superuser) await subscribeForPushNotifications()
}
@@ -147,30 +150,25 @@ function login() {
},
})
.then((response: any) => {
// 获取token
const token = response.access_token
const superUser = response.super_user
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
const authPayLoad: authState = {
token: response.access_token,
remember: form.value.remember,
}
// 更新token和remember状态到Vuex Store
store.dispatch('auth/login', {
token,
remember,
superUser,
userID,
userName,
avatar,
level,
permissions,
})
const userPayload: userState = {
superUser: response.super_user,
userID: response.user_id,
userName: response.user_name,
avatar: response.avatar,
level: response.level,
permissions: response.permissions,
}
authStore.login(authPayLoad)
userStore.loginUser(userPayload)
// 登录后处理
afterLogin(superUser)
afterLogin(userPayload.superUser)
})
.catch((error: any) => {
// 登录失败,显示错误提示
@@ -191,9 +189,9 @@ function startBackgroundRotation() {
// 自动登录
onMounted(async () => {
// 从Vuex Store中获取token和remember状态
const token = store.state.auth.token
const remember = store.state.auth.remember
// 获取token和remember状态
const token = authStore.token
const remember = authStore.remember
// 如果token存在且保持登录状态为true则跳转到首页
if (token && remember) {

View File

@@ -1,6 +1,6 @@
import { createRouter, createWebHashHistory } from 'vue-router'
import { configureNProgress } from '@/api/nprogress'
import store from '@/store'
import { useAuthStore } from '@/stores'
// Nprogress
configureNProgress()
@@ -223,9 +223,11 @@ function abortAllControllers() {
// 路由导航守卫
router.beforeEach((to: any, from: any, next: any) => {
// 认证 Store
const authStore = useAuthStore()
// 总是记录非login路由
if (to.fullPath != '/login') store.state.auth.originalPath = to.fullPath
const isAuthenticated = store.state.auth.token !== null
if (to.fullPath != '/login') authStore.originalPath = to.fullPath
const isAuthenticated = authStore.token !== null
if (to.meta.requiresAuth && !isAuthenticated) {
next('/login')
} else {

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

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
src/stores/auth.ts Normal file
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
src/stores/index.ts Normal file
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
src/stores/types.ts Normal file
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
src/stores/user.ts Normal file
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,
},
})

View File

@@ -2,12 +2,13 @@
import { useTheme } from 'vuetify'
import api from '@/api'
import { hexToRgb } from '@layouts/utils'
import { useUserStore } from '@/stores'
const vuetifyTheme = useTheme()
// 从Vuex Store中获取信息
const store = useStore()
const superUser = store.state.auth.superUser
// 用户 Store
const userStore = useUserStore()
const superUser = userStore.superUser
const options = controlledComputed(
() => vuetifyTheme.name.value,

View File

@@ -2,7 +2,7 @@
import { DiscoverSource } from '@/api/types'
import MediaCardListView from '@/views/discover/MediaCardListView.vue'
import FormRender from '@/components/render/FormRender.vue'
import { cloneDeep, isNull } from 'lodash'
import { cloneDeep } from 'lodash-es'
// 输入参数
const props = defineProps<{

View File

@@ -10,6 +10,7 @@ import { formatSeason } from '@/@core/utils/formatters'
import router from '@/router'
import SubscribeEditDialog from '@/components/dialog/SubscribeEditDialog.vue'
import { isNullOrEmptyObject } from '@/@core/utils'
import { useUserStore } from '@/stores'
// 输入参数
const mediaProps = defineProps({
@@ -22,7 +23,8 @@ const mediaProps = defineProps({
// 从 provide 中获取全局设置
const globalSettings: any = inject('globalSettings')
const store = useStore()
// 用户 Store
const userStore = useUserStore()
// 提示框
const $toast = useToast()
@@ -466,7 +468,7 @@ async function handlePlay() {
async function queryDefaultSubscribeConfig() {
// 非管理员不显示
if (!store.state.auth.superUser) return false
if (!userStore.superUser) return false
try {
let subscribe_config_url = ''
if (mediaProps.type === '电影') subscribe_config_url = 'system/setting/DefaultMovieSubscribeConfig'

View File

@@ -4,13 +4,16 @@ import api from '@/api'
import type { DownloadingInfo } from '@/api/types'
import NoDataFound from '@/components/NoDataFound.vue'
import DownloadingCard from '@/components/cards/DownloadingCard.vue'
import store from '@/store'
import { useUserStore } from '@/stores'
// 定义输入参数
const props = defineProps<{
name: string
}>()
// 用户 Store
const userStore = useUserStore()
// 定时器
let refreshTimer: NodeJS.Timeout | null = null
@@ -42,9 +45,9 @@ function onRefresh() {
// 过滤数据,管理员用户显示全部,非管理员只显示自己的订阅
const filteredDataList = computed(() => {
// 从Vuex Store中获取用户信息
const superUser = store.state.auth.superUser
const userName = store.state.auth.userName
// 从 Store 中获取用户信息
const superUser = userStore.superUser
const userName = userStore.userName
if (superUser) return dataList.value
else return dataList.value.filter(data => data.userid === userName || data.username === userName)
})

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { debounce } from 'lodash'
import { debounce } from 'lodash-es'
import { useToast } from 'vue-toast-notification'
import api from '@/api'
import type { TransferHistory } from '@/api/types'

View File

@@ -6,13 +6,16 @@ import NoDataFound from '@/components/NoDataFound.vue'
import SubscribeCard from '@/components/cards/SubscribeCard.vue'
import SubscribeEditDialog from '@/components/dialog/SubscribeEditDialog.vue'
import SubscribeHistoryDialog from '@/components/dialog/SubscribeHistoryDialog.vue'
import store from '@/store'
import { useUserStore } from '@/stores'
import { useDisplay } from 'vuetify'
// APP
const display = useDisplay()
const appMode = inject('pwaMode') && display.mdAndDown.value
// 用户 Store
const userStore = useUserStore()
// 输入参数
const props = defineProps({
type: String,
@@ -46,9 +49,9 @@ const displayList = ref<Subscribe[]>([])
// 监听dataList变化同步更新displayList
watch(dataList, () => {
// 从Vuex Store中获取用户信息
const superUser = store.state.auth.superUser
const userName = store.state.auth.userName
// 从 Store 中获取用户信息
const superUser = userStore.superUser
const userName = userStore.userName
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)
// 排序
@@ -163,7 +166,7 @@ onActivated(async () => {
<!-- 底部操作按钮 -->
<div v-if="isRefreshed">
<VFab
v-if="store.state.auth.superUser"
v-if="userStore.superUser"
icon="mdi-clipboard-edit"
location="bottom"
size="x-large"
@@ -174,7 +177,7 @@ onActivated(async () => {
:class="{ 'mb-12': appMode }"
/>
<VFab
v-if="store.state.auth.superUser"
v-if="userStore.superUser"
icon="mdi-history"
color="info"
location="bottom"

View File

@@ -3,16 +3,19 @@ import api from '@/api'
import type { Plugin, Site, Subscribe } from '@/api/types'
import { SystemNavMenus, SettingTabs } from '@/router/menu'
import { NavMenu } from '@/@layouts/types'
import store from '@/store'
import { useUserStore } from '@/stores'
// 路由
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'])

View File

@@ -1,5 +1,5 @@
<script lang="ts" setup>
import _ from 'lodash'
import { cloneDeepWith } from 'lodash-es'
import type { Context } from '@/api/types'
import TorrentCard from '@/components/cards/TorrentCard.vue'
@@ -259,7 +259,7 @@ function filterData() {
)
})
if (matchData.length > 0) {
const firstData = _.cloneDeepWith(matchData[0]) as SearchTorrent
const firstData = cloneDeepWith(matchData[0]) as SearchTorrent
if (matchData.length > 1) firstData.more = matchData.slice(1)
// 显示前20个4行左右。

View File

@@ -6,7 +6,7 @@ import api from '@/api'
import type { User } from '@/api/types'
import avatar1 from '@images/avatars/avatar-1.png'
import { useDisplay } from 'vuetify'
import store from '@/store'
import { useUserStore } from '@/stores'
// 显示器宽度
const display = useDisplay()
@@ -16,6 +16,9 @@ const isConfirmPasswordVisible = ref(false)
const newPassword = ref('')
const confirmPassword = ref('')
// 用户 Store
const userStore = useUserStore()
// 提示框
const $toast = useToast()
@@ -53,13 +56,7 @@ const accountInfo = ref<User>({
avatar: '',
is_otp: false,
permissions: {},
settings: {
wechat_userid: null,
telegram_userid: null,
slack_userid: null,
vocechat_userid: null,
synologychat_userid: null,
},
settings: {},
})
// 二维码信息
@@ -149,13 +146,13 @@ async function saveAccountInfo() {
if (oldUserName !== currentUserName.value) {
$toast.success(`${oldUserName}】更名【${currentUserName.value}】,用户信息保存成功!`)
// 更新本地用户名显示
store.commit('auth/setUserName', currentUserName.value)
userStore.setUserName(currentUserName.value)
} else {
$toast.success('用户信息保存成功!')
}
// 更新本地头像显示
if (oldAvatar !== currentAvatar.value) {
store.commit('auth/setAvatar', currentAvatar.value)
userStore.setAvatar(currentAvatar.value)
}
} else {
if (oldAvatar !== currentAvatar.value) {
@@ -238,9 +235,9 @@ onMounted(() => {
// 监听 localStorage 中的用户头像变化
watch(
() => store.state.auth.avatar,
() => userStore.avatar,
() => {
currentAvatar.value = store.state.auth.avatar
currentAvatar.value = userStore.avatar
},
)
</script>