添加路由权限,添加meta配置属性

This commit is contained in:
ray_wuhao 2023-01-28 16:51:15 +08:00
parent 93aca4cf6b
commit 59aaa82e0d
13 changed files with 228 additions and 60 deletions

View File

@ -1,7 +1,7 @@
{ {
"name": "ray-template", "name": "ray-template",
"private": true, "private": true,
"version": "3.0.7", "version": "3.0.8",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

View File

@ -19,8 +19,9 @@ import SettingDrawer from './components/SettingDrawer/index'
import { useSetting } from '@/store' import { useSetting } from '@/store'
import { useLanguageOptions } from '@/language/index' import { useLanguageOptions } from '@/language/index'
import { useAvatarOptions } from './hook' import { useAvatarOptions } from './hook'
import { removeCache, getCache } from '@/utils/cache' import { getCache } from '@/utils/cache'
import screenfull from 'screenfull' import screenfull from 'screenfull'
import { logout } from '@/utils/user'
import type { IconEventMapOptions, IconEventMap } from './type' import type { IconEventMapOptions, IconEventMap } from './type'
@ -110,9 +111,7 @@ const SiderBar = defineComponent({
positiveText: '确定', positiveText: '确定',
negativeText: '不确定', negativeText: '不确定',
onPositiveClick: () => { onPositiveClick: () => {
window.$message.info('账号退出中...') logout()
removeCache('all-sessionStorage')
setTimeout(() => window.location.reload(), 300)
}, },
}) })
} else { } else {

48
src/router/basic.ts Normal file
View File

@ -0,0 +1,48 @@
/**
*
* @author Ray <https://github.com/XiaoDaiGua-Ray>
*
* @date 2023-01-28
*
* @workspace ray-template
*
* @remark
*/
/**
*
* ,
*
* , includes
*
* , meta ,
*
* meta
*/
import { useSignin } from '@/store'
const BASIC_ROUTER = ['login', 'error-page', 'doc']
const BASE_ROLES = ['admin']
export const validRole = (options: IMenuOptions) => {
const { role } = storeToRefs(useSignin())
const { meta, name } = options
const hidden =
meta?.hidden === undefined || meta?.hidden === false ? meta?.hidden : true
if (BASE_ROLES.includes(role.value)) {
return true && hidden
} else {
if (BASIC_ROUTER.includes(name)) {
return true && hidden
}
if (meta?.role) {
return meta.role.includes(role.value) && hidden
}
return true && hidden
}
}

View File

@ -2,6 +2,8 @@ import { createRouter, createWebHashHistory } from 'vue-router'
import { constantRoutes } from './routes' import { constantRoutes } from './routes'
import { getCache, setCache } from '@/utils/cache' import { getCache, setCache } from '@/utils/cache'
import { permissionRouter as _permissionRouter } from './permission'
import type { App } from 'vue' import type { App } from 'vue'
export const router = createRouter({ export const router = createRouter({
@ -10,6 +12,8 @@ export const router = createRouter({
scrollBehavior: () => ({ left: 0, top: 0 }), scrollBehavior: () => ({ left: 0, top: 0 }),
}) })
export const permissionRouter = () => _permissionRouter(router)
// setup router // setup router
export const setupRouter = (app: App<Element>) => { export const setupRouter = (app: App<Element>) => {
app.use(router) app.use(router)
@ -17,8 +21,7 @@ export const setupRouter = (app: App<Element>) => {
/** /**
* *
* `naive-ui` * @remark
* 使,
*/ */
export const setupRouterLoadingBar = () => { export const setupRouterLoadingBar = () => {
router.beforeEach(() => { router.beforeEach(() => {
@ -33,34 +36,3 @@ export const setupRouterLoadingBar = () => {
window?.$loadingBar?.error() window?.$loadingBar?.error()
}) })
} }
/**
*
*
*/
export const permissionRouter = () => {
router.beforeEach((to, from, next) => {
const token = getCache('token')
const route = getCache('menuKey')
if (token !== 'no') {
if (to.path === '/' || from.path === '/login') {
if (route !== 'no') {
next(route)
} else {
next('/dashboard')
setCache('menuKey', '/dashboard')
}
} else {
next()
}
} else {
if (to.path === '/' || from.path === '/login') {
next()
} else {
next('/')
}
}
})
}

View File

@ -5,5 +5,6 @@ export default {
meta: { meta: {
i18nKey: 'scrollReveal', i18nKey: 'scrollReveal',
icon: 'scroll_reveal', icon: 'scroll_reveal',
hidden: false,
}, },
} }

56
src/router/permission.ts Normal file
View File

@ -0,0 +1,56 @@
/**
*
* @author Ray <https://github.com/XiaoDaiGua-Ray>
*
* @date 2023-01-28
*
* @workspace ray-template
*
* @remark
*/
/**
*
* ,
*
* meta role BASIC_ROUTER
*
* meta role
*
* ,
*
* , ,
*/
import { getCache, setCache } from '@/utils/cache'
import type { Router } from 'vue-router'
export const permissionRouter = (router: Router) => {
const { beforeEach } = router
beforeEach((to, from, next) => {
const token = getCache('token')
const route = getCache('menuKey')
if (token !== 'no') {
if (to.path === '/' || from.path === '/login') {
if (route !== 'no') {
next(route)
} else {
next('/dashboard')
setCache('menuKey', '/dashboard')
}
} else {
next()
}
} else {
if (to.path === '/' || from.path === '/login') {
next()
} else {
next('/')
}
}
})
}

View File

@ -4,6 +4,7 @@ import type { App } from 'vue'
export { useSetting } from './modules/setting' // import { useSetting } from '@/store' 即可使用 export { useSetting } from './modules/setting' // import { useSetting } from '@/store' 即可使用
export { useMenu } from './modules/menu' export { useMenu } from './modules/menu'
export { useSignin } from './modules/signin'
const store = createPinia() const store = createPinia()

View File

@ -2,9 +2,10 @@ import { NEllipsis } from 'naive-ui'
import RayIcon from '@/components/RayIcon/index' import RayIcon from '@/components/RayIcon/index'
import { getCache, setCache } from '@/utils/cache' import { getCache, setCache } from '@/utils/cache'
import { validRole } from '@/router/basic'
import type { MenuOption } from 'naive-ui' import type { MenuOption } from 'naive-ui'
import type { RouteRecordRaw, RouteMeta } from 'vue-router' import type { RouteMeta } from 'vue-router'
export const useMenu = defineStore('menu', () => { export const useMenu = defineStore('menu', () => {
const router = useRouter() const router = useRouter()
@ -51,6 +52,7 @@ export const useMenu = defineStore('menu', () => {
menuState.menuKey = key menuState.menuKey = key
router.push(`${item.path}`) router.push(`${item.path}`)
setCache('menuKey', key) setCache('menuKey', key)
} }
} }
@ -81,55 +83,56 @@ export const useMenu = defineStore('menu', () => {
/** /**
* *
* * @remark ,
* * @remark ,
*/ */
const setupAppRoutes = () => { const setupAppRoutes = () => {
const layout = router.getRoutes().find((route) => route.name === 'layout') const layout = router.getRoutes().find((route) => route.name === 'layout')
const resolveRoutes = (routes: RouteRecordRaw[], index: number) => { const resolveRoutes = (routes: IMenuOptions[], index: number) => {
return routes.map((curr) => { return routes.map((curr) => {
if (curr.children?.length) { if (curr.children?.length) {
curr.children = resolveRoutes( curr.children = resolveRoutes(curr.children, index++)
curr.children as RouteRecordRaw[],
index++,
)
} }
const { meta } = curr
const route = { const route = {
...curr, ...curr,
key: curr.path, key: curr.path,
label: () => label: () =>
h(NEllipsis, null, { h(NEllipsis, null, {
default: () => t(`GlobalMenuOptions.${curr!.meta!.i18nKey}`), default: () => t(`GlobalMenuOptions.${meta!.i18nKey}`),
}), }),
} }
const expandIcon = { const expandIcon = {
icon: () => icon: () =>
h( h(
RayIcon, RayIcon,
{ {
name: curr?.meta?.icon as string, name: meta!.icon as string,
size: 20, size: 20,
}, },
{}, {},
), ),
} }
const attr = curr.meta?.icon const attr: IMenuOptions = meta?.icon
? Object.assign({}, route, expandIcon) ? Object.assign({}, route, expandIcon)
: route : route
// 初始化 `menu tag`
if (curr.path === cacheMenuKey) { if (curr.path === cacheMenuKey) {
menuState.menuTagOptions.push(attr) menuState.menuTagOptions.push(attr)
} }
attr.show = validRole(curr)
return attr return attr
}) })
} }
menuState.options = resolveRoutes(layout?.children as RouteRecordRaw[], 0) menuState.options = resolveRoutes(layout?.children as IMenuOptions[], 0)
} }
/** /**

View File

@ -0,0 +1,63 @@
/**
*
* @author Ray <https://github.com/XiaoDaiGua-Ray>
*
* @date 2023-01-28
*
* @workspace ray-template
*
* @remark
*/
/**
*
* 便, pinia
*
* 可以存储: 头像, ,
*
* ,
*/
import { isEmpty } from 'lodash-es'
import { logout } from '@/utils/user'
export interface SigninForm extends IUnknownObjectKey {
name: string
pwd: string
}
export const useSignin = defineStore(
'signin',
() => {
const state = reactive({
role: '',
})
/**
*
* @param signinForm
* @returns
*
* @remark 0: 登陆成功, 1: 登陆失败
*/
const signin = (signinForm: SigninForm) => {
if (!isEmpty(signinForm)) {
state.role = 'admin'
return 0
} else {
return 1
}
}
return {
...toRefs(state),
signin,
}
},
{
persist: {
key: 'piniaSigninStore',
},
},
)

View File

@ -1,14 +1,18 @@
export {} export {}
import type { RouteRecordRaw } from 'vue-router' import type { RouteRecordRaw, RouteMeta } from 'vue-router'
import type { MenuOption } from 'naive-ui' import type { MenuOption } from 'naive-ui'
import type { VNode } from 'vue' import type { VNode } from 'vue'
declare global { declare global {
declare interface IMenuOptions extends MenuOption, RouteRecordRaw { declare interface IMenuOptions extends RouteRecordRaw, MenuOption {
name: string
key: string | number key: string | number
path: string path: string
label: string | Function label: string | Function
show?: boolean
children?: IMenuOptions[]
meta?: RouteMeta
} }
declare interface TagMenuOptions extends IMenuOptions {} declare interface TagMenuOptions extends IMenuOptions {}

13
src/utils/user.ts Normal file
View File

@ -0,0 +1,13 @@
import { removeCache } from '@/utils/cache'
/**
*
* @remark 退 localStorage
*/
export const logout = () => {
window.$message.info('账号退出中...')
removeCache('all-sessionStorage')
setTimeout(() => window.location.reload(), 300)
}

View File

@ -1,6 +1,7 @@
import { NForm, NFormItem, NInput, NButton } from 'naive-ui' import { NForm, NFormItem, NInput, NButton } from 'naive-ui'
import { setCache } from '@/utils/cache' import { setCache } from '@/utils/cache'
import { useSpin } from '@/spin' import { useSpin } from '@/spin'
import { useSignin } from '@/store'
import type { FormInst } from 'naive-ui' import type { FormInst } from 'naive-ui'
@ -8,6 +9,9 @@ const Signin = defineComponent({
name: 'Signin', name: 'Signin',
setup() { setup() {
const { t } = useI18n() const { t } = useI18n()
const signinStore = useSignin()
const { signin } = signinStore
const useSigninForm = () => ({ const useSigninForm = () => ({
name: 'ray', name: 'ray',
@ -35,16 +39,18 @@ const Signin = defineComponent({
if (!valid) { if (!valid) {
useSpin(true) useSpin(true)
setTimeout(() => { if (signin(signinForm.value) === 0) {
router.push('/dashboard') setTimeout(() => {
router.push('/dashboard')
useSpin(false) useSpin(false)
window.$message.success(`欢迎${signinForm.value.name}登陆~`) window.$message.success(`欢迎${signinForm.value.name}登陆~`)
setCache('token', 'tokenValue') setCache('token', 'tokenValue')
setCache('person', signinForm.value) setCache('person', signinForm.value)
}, 2 * 1000) }, 2 * 1000)
}
} else { } else {
window.$message.error('不可以这样哟, 不可以哟') window.$message.error('不可以这样哟, 不可以哟')
} }

2
src/vite-env.d.ts vendored
View File

@ -15,6 +15,8 @@ declare module 'vue-router' {
i18nKey: string i18nKey: string
icon?: string icon?: string
windowOpen?: string windowOpen?: string
role?: string[]
hidden?: boolean
} }
} }