add: 补充部分文档,修复鉴权bug

This commit is contained in:
ray_wuhao 2023-06-19 17:48:21 +08:00
parent d1cb4ddb41
commit 54d370c7a0
10 changed files with 108 additions and 48 deletions

View File

@ -44,7 +44,7 @@ export const SETUP_ROUTER_GUARD = true
* , meta hidden
* mete hidden false
*/
export const WHITE_ROUTES = ['login', 'error-page', 'doc']
export const WHITE_ROUTES = ['RLogin', 'ErrorPage', 'RayTemplateDoc']
/**
*

View File

@ -18,19 +18,43 @@
import { useAxiosInterceptor, axiosCanceler } from '@/axios/helper/interceptor'
import { appendRequestHeaders } from '@/axios/helper/axiosCopilot'
import { APP_CATCH_KEY } from '@/appConfig/appConfig'
import { getCache } from '@/utils/cache'
import type { RequestInterceptorConfig, ImplementFunction } from '@/axios/type'
const { setImplementQueue } = useAxiosInterceptor()
/**
*
* token token key value
*
*
*
* request instance ,
*/
const requestHeaderToken = (ins: RequestInterceptorConfig, mode: string) => {
const token = getCache(APP_CATCH_KEY.token)
if (ins.url) {
// TODO: 根据 url 不同是否设置 token
}
return {
key: 'X-TOKEN',
value: token,
}
}
/** 注入请求头信息 */
const injectRequestHeaders: ImplementFunction<RequestInterceptorConfig> = (
ins,
mode,
) => {
appendRequestHeaders(ins, [
requestHeaderToken(ins, mode),
{
key: 'X-TOKEN',
value: 'token',
key: 'Demo-Header-Key',
value: 'Demo Header Value',
},
])
}

View File

@ -0,0 +1,9 @@
## 描述
> 该组件包存放依赖系统数据的公共组件。
## 约束
- 该组件包仅存放与系统数据有绑定、关联的组件,纯组件或纯 UI 组件应放置于外层包中
- 以 `App` 开头标记组件是系统组件
- 组件应该尽量避免与其他系统组件有关联性

View File

@ -24,42 +24,23 @@ import { getCache, setCache } from '@/utils/cache'
import { useSignin } from '@/store'
import { APP_CATCH_KEY, ROOT_ROUTE } from '@/appConfig/appConfig'
import { redirectRouterToDashboard } from '@/router/helper/routerCopilot'
import { validRole, validMenuItemShow } from '@/router/helper/routerCopilot'
import type { Router, NavigationGuardNext } from 'vue-router'
import type {
Router,
NavigationGuardNext,
RouteLocationNormalized,
} from 'vue-router'
export const permissionRouter = (router: Router) => {
const { beforeEach } = router
const { path } = ROOT_ROUTE
beforeEach((to, from, next) => {
const token = getCache(APP_CATCH_KEY.token)
const route = getCache('menuKey')
const { signinCallback } = storeToRefs(useSignin())
const role = computed(() => signinCallback.value.role)
const { meta } = to
/**
*
* , ( dashboard)
* 使,
*/
const hasRole = () => {
/** 如果未设置权限则默认无需鉴权 */
if (meta.role) {
/** 空权限列表默认无需鉴权 */
if (meta.role.length === 0) {
return true
} else {
return meta.role.includes(role.value)
}
} else {
return true
}
}
if (token !== 'no') {
if (hasRole()) {
if (validMenuItemShow(to as unknown as IMenuOptions)) {
if (to.path === '/' || from.path === '/login') {
if (route !== 'no') {
next(route)

View File

@ -23,6 +23,7 @@ import { ROOT_ROUTE } from '@/appConfig/appConfig'
import { setCache } from '@/utils/cache'
import type { Router } from 'vue-router'
import type { AppRouteMeta } from '@/router/type'
/**
*
@ -31,17 +32,23 @@ import type { Router } from 'vue-router'
*
* ,
*/
export const validRole = (option: IMenuOptions) => {
export const validRole = (meta: AppRouteMeta) => {
const { signinCallback } = storeToRefs(useSignin())
const role = computed(() => signinCallback.value.role)
const { meta } = option
const { role: metaRole } = meta
if (SUPER_ADMIN?.length && SUPER_ADMIN.includes(role.value)) {
return true
} else {
if (meta?.role) {
return meta.role.includes(role.value)
// 如果 role 为 undefind 或者空数组, 则认为该路由不做权限过滤
if (!metaRole || !metaRole?.length) {
return true
}
// 判断是否含有该权限
if (metaRole) {
return metaRole.includes(role.value)
}
return true
@ -63,7 +70,7 @@ export const validMenuItemShow = (option: IMenuOptions) => {
meta?.hidden === undefined || meta?.hidden === false ? false : meta?.hidden
// 如果是超级管理员(预设为 admin), 则根据其菜单栏(hidden)字段判断是否显示
if (validRole(option)) {
if (validRole(meta)) {
return true && !hidden
} else {
// 如果为基础路由, 不进行鉴权则根据其菜单栏(hidden)字段判断是否显示
@ -71,9 +78,14 @@ export const validMenuItemShow = (option: IMenuOptions) => {
return true && !hidden
}
// 如果 role 为 undefind 或者空数组, 则认为该路由不做权限过滤
if (!meta?.role || !meta.role?.length) {
return true && !hidden
}
// 判断权限是否匹配和菜单栏(hidden)字段判断是否显示
if (meta?.role) {
return validRole(option) && !hidden
if (meta?.role && meta.role.length) {
return validRole(meta) && !hidden
}
return true && !hidden
@ -127,7 +139,8 @@ export const redirectRouterToDashboard = (isReplace = true) => {
const { push, replace } = router
const { path } = ROOT_ROUTE
isReplace ? push(path) : replace(path)
setCache('menuKey', path)
console.log('path', path)
isReplace ? push(path) : replace(path)
}

View File

@ -11,6 +11,7 @@ const axios: AppRouteRecordRaw = {
icon: 'axios',
order: 3,
keepAlive: true,
hidden: false,
},
}

29
src/store/README.md Normal file
View File

@ -0,0 +1,29 @@
## 描述
> pinia store 仓库包。存放全局公共状态。
## 约束
- 状态管理器应该按照其用途进行分包(见名知意)
- 包名以用途名命名
- 默认以 index.ts 作为入口其余的辅助函数、类型分别在该文件夹下进行补充type.ts、helper.ts。。。
- 仓库使用 `piniaPluginPersistedstate` 作为中间件,用于缓存仓库数据避免刷新丢失(但是该方法有缺陷,不能缓存函数)
- 默认不全部缓存参数,如果需要缓存参数,需要在 `defineStore` 第三个参数配置 `persist` 属性
- `defineStore` 第一个参数必须全局唯一
- 缓存插件 key 应该按照 `piniaXXXStore` 格式命名XXX 表示该包名称)
```ts
export const useDemoStore = defineStore('demo', () => {}, {
persist: {
key: 'piniaDemoStore',
paths: ['demoState'],
storage: sessionStorage | localStorage,
},
})
```
- 最后在 index.ts 中暴露使用
```ts
export { useDemo } from './modules/demo/index'
```

View File

@ -14,6 +14,7 @@
import { MENU_COLLAPSED_CONFIG, ROOT_ROUTE } from '@/appConfig/appConfig'
import RayIcon from '@/components/RayIcon/index'
import { validteValueType } from '@/utils/hook'
import { getCache, setCache } from '@/utils/cache'
import type { VNode } from 'vue'
@ -156,3 +157,12 @@ export const hasMenuIcon = (option: IMenuOptions) => {
return () => icon
}
/** 获取缓存的 menu key, 如果未获取到则使用 ROOTROUTE path 当作默认激活路由菜单 */
export const getCatchMenuKey = () => {
const { path: rootPath } = ROOT_ROUTE
const cacheMenuKey: MenuKey =
getCache('menuKey') === 'no' ? rootPath : getCache('menuKey')
return cacheMenuKey
}

View File

@ -23,7 +23,6 @@
*/
import { NEllipsis } from 'naive-ui'
import RayIcon from '@/components/RayIcon/index'
import { getCache, setCache } from '@/utils/cache'
import { validMenuItemShow } from '@/router/helper/routerCopilot'
@ -32,9 +31,9 @@ import {
matchMenuOption,
updateDocumentTitle,
hasMenuIcon,
getCatchMenuKey,
} from './helper'
import { useI18n } from '@/locales/useI18n'
import { MENU_COLLAPSED_CONFIG, ROOT_ROUTE } from '@/appConfig/appConfig'
import routeModules from '@/router/routeModules'
import { useKeepAlive } from '@/store'
import { useVueRouter } from '@/router/helper/useVueRouter'
@ -50,13 +49,8 @@ export const useMenu = defineStore(
const { t } = useI18n()
const { setKeepAliveInclude } = useKeepAlive()
const { path: rootPath } = ROOT_ROUTE
const cacheMenuKey =
getCache('menuKey') === 'no' ? rootPath : getCache('menuKey')
const menuState = reactive({
menuKey: cacheMenuKey as MenuKey, // 当前菜单 `key`
menuKey: getCatchMenuKey(), // 当前菜单 `key`
options: [] as IMenuOptions[], // 菜单列表
collapsed: false, // 是否折叠菜单
menuTagOptions: [] as MenuTagOptions[], // tag 标签菜单
@ -196,7 +190,7 @@ export const useMenu = defineStore(
icon: hasMenuIcon(option),
})
if (option.path === cacheMenuKey) {
if (option.path === getCatchMenuKey()) {
/** 设置菜单标签 */
setMenuTagOptions(attr)
/** 设置浏览器标题 */

View File

@ -21,7 +21,6 @@
import { isEmpty } from 'lodash-es'
import { removeCache } from '@/utils/cache'
import { useMenu } from '@/store'
import type {
SigninForm,