1
0
mirror of https://github.com/zclzone/vue-naive-admin.git synced 2026-01-22 15:40:21 +08:00

fix: 解决vite5循环引用导致热更新失效问题

This commit is contained in:
zclzone
2024-01-06 18:47:40 +08:00
parent c4fd0459ab
commit 2c9604a829
14 changed files with 351 additions and 317 deletions

View File

@@ -62,7 +62,8 @@ function open(options) {
async function setCurrentRole() {
try {
okLoading.value = true
await userStore.switchCurrentRole(roleCode.value)
const { data } = await api.switchCurrentRole(roleCode.value)
await authStore.switchCurrentRole(data)
okLoading.value = false
$message.success('切换成功')
modalRef.value?.handleOk()

View File

@@ -0,0 +1,40 @@
export const basicRoutes = [
{
name: 'Login',
path: '/login',
component: () => import('@/views/login/index.vue'),
meta: {
title: '登录页',
layout: 'empty',
},
},
{
name: 'Home',
path: '/',
component: () => import('@/views/home/index.vue'),
meta: {
title: '首页',
},
},
{
name: '404',
path: '/404',
component: () => import('@/views/error-page/404.vue'),
meta: {
title: '页面飞走了',
layout: 'empty',
},
},
{
name: '403',
path: '/403',
component: () => import('@/views/error-page/403.vue'),
meta: {
title: '没有权限',
layout: 'empty',
},
},
]

View File

@@ -9,47 +9,8 @@
import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'
import { setupRouterGuards } from './guards'
import { useAuthStore, usePermissionStore, useUserStore } from '@/store'
export const basicRoutes = [
{
name: 'Login',
path: '/login',
component: () => import('@/views/login/index.vue'),
meta: {
title: '登录页',
layout: 'empty',
},
},
{
name: 'Home',
path: '/',
component: () => import('@/views/home/index.vue'),
meta: {
title: '首页',
},
},
{
name: '404',
path: '/404',
component: () => import('@/views/error-page/404.vue'),
meta: {
title: '页面飞走了',
layout: 'empty',
},
},
{
name: '403',
path: '/403',
component: () => import('@/views/error-page/403.vue'),
meta: {
title: '没有权限',
layout: 'empty',
},
},
]
import { getPermissions, getUserInfo } from '@/store/helper'
import { basicRoutes } from './basic-routes'
export const router = createRouter({
history:
@@ -74,32 +35,21 @@ export async function initUserAndPermissions() {
const authStore = useAuthStore()
if (!authStore.accessToken) {
authStore.toLogin()
const route = unref(router.currentRoute)
if (route.path !== '/login') {
router.replace({
path: '/login',
query: route.query,
})
}
return
}
await Promise.all([userStore.getUserInfo(), permissionStore.initPermissions()])
const [user, permissions] = await Promise.all([getUserInfo(), getPermissions()])
userStore.setUser(user)
permissionStore.setPermissions(permissions)
const routeComponents = import.meta.glob('@/views/**/*.vue')
permissionStore.accessRoutes.forEach((route) => {
route.component = routeComponents[route.component] || undefined
!router.hasRoute(route.name) && router.addRoute(route)
})
}
export async function resetRouter() {
const basicRouteNames = getRouteNames(basicRoutes)
router.getRoutes().forEach((route) => {
const name = route.name
if (!basicRouteNames.includes(name)) {
router.removeRoute(name)
}
})
}
export function getRouteNames(routes) {
const names = []
for (const route of routes) {
names.push(route.name)
if (route.children?.length) {
names.push(...getRouteNames(route.children))
}
}
return names
}

29
src/store/helper.js Normal file
View File

@@ -0,0 +1,29 @@
import { basePermissions } from '@/settings'
import api from '@/api'
export async function getUserInfo() {
const res = await api.getUser()
const { id, username, profile, roles, currentRole } = res.data || {}
return {
id,
username,
avatar: profile?.avatar,
nickName: profile?.nickName,
gender: profile?.gender,
address: profile?.address,
email: profile?.email,
roles,
currentRole,
}
}
export async function getPermissions() {
let asyncPermissions = []
try {
const res = await api.getRolePermissions()
asyncPermissions = res?.data || []
} catch (error) {
console.error(error)
}
return basePermissions.concat(asyncPermissions)
}

View File

@@ -7,8 +7,7 @@
**********************************/
import { defineStore } from 'pinia'
import { useUserStore, usePermissionStore, useTabStore } from '@/store'
import { resetRouter, router } from '@/router'
import { useUserStore, usePermissionStore, useTabStore, useRouterStore } from '@/store'
export const useAuthStore = defineStore('auth', {
state: () => ({
@@ -22,24 +21,30 @@ export const useAuthStore = defineStore('auth', {
this.$reset()
},
toLogin() {
const currentRoute = unref(router.currentRoute)
const { router, route } = useRouterStore()
router.replace({
path: '/login',
query: currentRoute.query,
query: route.query,
})
},
async switchCurrentRole(data) {
this.resetLoginState()
await nextTick()
this.setToken(data)
},
resetLoginState() {
const { resetUser } = useUserStore()
const { resetPermission } = usePermissionStore()
const { resetRouter } = useRouterStore()
const { resetPermission, accessRoutes } = usePermissionStore()
const { resetTabs } = useTabStore()
// 重置路由
resetRouter(accessRoutes)
// 重置用户
resetUser()
// 重置权限
resetPermission()
// 重置Tabs
resetTabs()
// 重置路由
resetRouter()
// 重置token
this.resetToken()
},

View File

@@ -3,3 +3,4 @@ export * from './auth'
export * from './permission'
export * from './tab'
export * from './user'
export * from './router'

View File

@@ -7,27 +7,16 @@
**********************************/
import { defineStore } from 'pinia'
import { isExternal } from '@/utils'
import { basePermissions } from '@/settings'
import api from '@/api'
const routeComponents = import.meta.glob('@/views/**/*.vue')
export const usePermissionStore = defineStore('permission', {
state: () => ({
menus: [],
accessRoutes: [],
asyncPermissions: [],
permissions: [],
menus: [],
}),
getters: {
permissions() {
return basePermissions.concat(this.asyncPermissions)
},
},
actions: {
async initPermissions() {
const { data } = (await api.getRolePermissions()) || []
this.asyncPermissions = data
setPermissions(permissions) {
this.permissions = permissions
this.menus = this.permissions
.filter((item) => item.type === 'MENU')
.map((item) => this.getMenuItem(item))
@@ -36,7 +25,7 @@ export const usePermissionStore = defineStore('permission', {
},
getMenuItem(item, parent) {
const route = this.generateRoute(item, item.show ? null : parent?.key)
if (item.enable && route.path && !isExternal(route.path)) this.accessRoutes.push(route)
if (item.enable && route.path && !route.path.startsWith('http')) this.accessRoutes.push(route)
if (!item.show) return null
const menuItem = {
label: route.meta.title,
@@ -60,7 +49,7 @@ export const usePermissionStore = defineStore('permission', {
name: item.code,
path: item.path,
redirect: item.redirect,
component: routeComponents[item.component] || undefined,
component: item.component,
meta: {
icon: item.icon,
title: item.name,

View File

@@ -0,0 +1,26 @@
/**********************************
* @Author: Ronnie Zhang
* @LastEditor: Ronnie Zhang
* @LastEditTime: 2024/01/06 17:18:40
* @Email: zclzone@outlook.com
* Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
**********************************/
import { defineStore } from 'pinia'
export const useRouterStore = defineStore('router', () => {
const router = useRouter()
const route = useRoute()
function resetRouter(accessRoutes) {
accessRoutes.forEach((item) => {
router.hasRoute(item.name) && router.removeRoute(item.name)
})
}
return {
router,
route,
resetRouter,
}
})

View File

@@ -7,7 +7,7 @@
**********************************/
import { defineStore } from 'pinia'
import { router } from '@/router'
import { useRouterStore } from './router'
export const useTabStore = defineStore('tab', {
state: () => ({
@@ -55,13 +55,13 @@ export const useTabStore = defineStore('tab', {
async removeTab(path) {
this.setTabs(this.tabs.filter((tab) => tab.path !== path))
if (path === this.activeTab) {
router.push(this.tabs[this.tabs.length - 1].path)
useRouterStore().router?.push(this.tabs[this.tabs.length - 1].path)
}
},
removeOther(curPath = this.activeTab) {
this.setTabs(this.tabs.filter((tab) => tab.path === curPath))
if (curPath !== this.activeTab) {
router.push(this.tabs[this.tabs.length - 1].path)
useRouterStore().router?.push(this.tabs[this.tabs.length - 1].path)
}
},
removeLeft(curPath) {
@@ -69,7 +69,7 @@ export const useTabStore = defineStore('tab', {
const filterTabs = this.tabs.filter((item, index) => index >= curIndex)
this.setTabs(filterTabs)
if (!filterTabs.find((item) => item.path === this.activeTab)) {
router.push(filterTabs[filterTabs.length - 1].path)
useRouterStore().router?.push(filterTabs[filterTabs.length - 1].path)
}
},
removeRight(curPath) {
@@ -77,7 +77,7 @@ export const useTabStore = defineStore('tab', {
const filterTabs = this.tabs.filter((item, index) => index <= curIndex)
this.setTabs(filterTabs)
if (!filterTabs.find((item) => item.path === this.activeTab.value)) {
router.push(filterTabs[filterTabs.length - 1].path)
useRouterStore().router?.push(filterTabs[filterTabs.length - 1].path)
}
},
resetTabs() {

View File

@@ -7,8 +7,6 @@
**********************************/
import { defineStore } from 'pinia'
import api from '@/api'
import { useAuthStore } from '@/store'
export const useUserStore = defineStore('user', {
state: () => ({
@@ -35,32 +33,8 @@ export const useUserStore = defineStore('user', {
},
},
actions: {
async getUserInfo() {
try {
const res = await api.getUser()
const { id, username, profile, roles, currentRole } = res.data || {}
this.userInfo = {
id,
username,
avatar: profile?.avatar,
nickName: profile?.nickName,
gender: profile?.gender,
address: profile?.address,
email: profile?.email,
roles,
currentRole,
}
return Promise.resolve(res.data)
} catch (error) {
return Promise.reject(error)
}
},
async switchCurrentRole(roleCode) {
const { data } = await api.switchCurrentRole(roleCode)
const authStore = useAuthStore()
authStore.resetLoginState()
await nextTick()
authStore.setToken(data)
setUser(user) {
this.userInfo = user
},
resetUser() {
this.$reset()

View File

@@ -9,7 +9,7 @@
import * as NaiveUI from 'naive-ui'
import { isNullOrUndef } from '@/utils'
import { useAppStore } from '@/store/modules/app'
import { useAppStore } from '@/store'
export function setupMessage(NMessage) {
class Message {

View File

@@ -100,9 +100,10 @@
import { MeModal } from '@/components'
import { useForm, useModal } from '@/composables'
import { useUserStore } from '@/store'
import { getUserInfo } from '@/store/helper'
import api from './api'
const userStore = useUserStore()
const userStore = useUserStore()
const required = {
required: true,
message: '此为必填项',
@@ -116,7 +117,7 @@ async function handlePwdSave() {
await pwdValidation()
await api.changePassword(pwdForm.value)
$message.success('密码修改成功')
userStore.getUserInfo()
refreshUserInfo()
}
const newAvatar = ref(userStore.avatar)
@@ -128,7 +129,7 @@ async function handleAvatarSave() {
}
await api.updateProfile({ id: userStore.userId, avatar: newAvatar.value })
$message.success('头像修改成功')
userStore.getUserInfo()
refreshUserInfo()
}
const genders = [
@@ -148,6 +149,11 @@ async function handleProfileSave() {
await profileValidation()
await api.updateProfile(profileForm.value)
$message.success('资料修改成功')
userStore.getUserInfo()
refreshUserInfo()
}
async function refreshUserInfo() {
const user = await getUserInfo()
userStore.setUser(user)
}
</script>