mirror of
https://github.com/soybeanjs/soybean-admin.git
synced 2025-09-22 03:26:38 +08:00
feat(projects): 权限完善及权限示例页面
This commit is contained in:
parent
b9c5c34979
commit
807448aec5
4
.env
4
.env
@ -7,6 +7,8 @@ VITE_APP_TITLE=Soybean管理系统
|
||||
VITE_APP_DESC=SoybeanAdmin是一个中后台管理系统模版
|
||||
|
||||
# 权限路由模式: static | dynamic
|
||||
VITE_AUTH_ROUTE_MODE=dynamic
|
||||
VITE_AUTH_ROUTE_MODE=static
|
||||
|
||||
VITE_VISUALIZER=false
|
||||
|
||||
VITE_ROUTE_HOME_PATH=/dashboard/analysis
|
||||
|
@ -8,7 +8,7 @@ import mock from './mock';
|
||||
import visualizer from './visualizer';
|
||||
|
||||
/**
|
||||
* vite插件
|
||||
* vite插件
|
||||
* @param configEnv - 环境
|
||||
* @param srcPath - src路径
|
||||
* @param viteEnv - 环境变量配置
|
||||
|
15
components.d.ts
vendored
15
components.d.ts
vendored
@ -13,14 +13,9 @@ declare module 'vue' {
|
||||
IconAntDesignCloseOutlined: typeof import('~icons/ant-design/close-outlined')['default']
|
||||
IconAntDesignEnterOutlined: typeof import('~icons/ant-design/enter-outlined')['default']
|
||||
IconAntDesignSettingOutlined: typeof import('~icons/ant-design/setting-outlined')['default']
|
||||
IconCustomActivity: typeof import('~icons/custom/activity')['default']
|
||||
IconCustomAvatar: typeof import('~icons/custom/avatar')['default']
|
||||
IconCustomBanner: typeof import('~icons/custom/banner')['default']
|
||||
IconCustomCast: typeof import('~icons/custom/cast')['default']
|
||||
IconCustomEmptyData: typeof import('~icons/custom/empty-data')['default']
|
||||
IconCustomLogo: typeof import('~icons/custom/logo')['default']
|
||||
IconCustomLogoFill: typeof import('~icons/custom/logo-fill')['default']
|
||||
IconCustomNetworkError: typeof import('~icons/custom/network-error')['default']
|
||||
IconCustomNoPermission: typeof import('~icons/custom/no-permission')['default']
|
||||
IconCustomNotFound: typeof import('~icons/custom/not-found')['default']
|
||||
IconCustomServiceError: typeof import('~icons/custom/service-error')['default']
|
||||
@ -55,8 +50,6 @@ declare module 'vue' {
|
||||
NColorPicker: typeof import('naive-ui')['NColorPicker']
|
||||
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
||||
NDataTable: typeof import('naive-ui')['NDataTable']
|
||||
NDescriptions: typeof import('naive-ui')['NDescriptions']
|
||||
NDescriptionsItem: typeof import('naive-ui')['NDescriptionsItem']
|
||||
NDialogProvider: typeof import('naive-ui')['NDialogProvider']
|
||||
NDivider: typeof import('naive-ui')['NDivider']
|
||||
NDrawer: typeof import('naive-ui')['NDrawer']
|
||||
@ -69,26 +62,18 @@ declare module 'vue' {
|
||||
NGrid: typeof import('naive-ui')['NGrid']
|
||||
NGridItem: typeof import('naive-ui')['NGridItem']
|
||||
NInput: typeof import('naive-ui')['NInput']
|
||||
NInputGroup: typeof import('naive-ui')['NInputGroup']
|
||||
NInputNumber: typeof import('naive-ui')['NInputNumber']
|
||||
NList: typeof import('naive-ui')['NList']
|
||||
NListItem: typeof import('naive-ui')['NListItem']
|
||||
NLoadingBarProvider: typeof import('naive-ui')['NLoadingBarProvider']
|
||||
NMenu: typeof import('naive-ui')['NMenu']
|
||||
NMessageProvider: typeof import('naive-ui')['NMessageProvider']
|
||||
NModal: typeof import('naive-ui')['NModal']
|
||||
NNotificationProvider: typeof import('naive-ui')['NNotificationProvider']
|
||||
NPopover: typeof import('naive-ui')['NPopover']
|
||||
NScrollbar: typeof import('naive-ui')['NScrollbar']
|
||||
NSelect: typeof import('naive-ui')['NSelect']
|
||||
NSpace: typeof import('naive-ui')['NSpace']
|
||||
NSpin: typeof import('naive-ui')['NSpin']
|
||||
NStatistic: typeof import('naive-ui')['NStatistic']
|
||||
NSwitch: typeof import('naive-ui')['NSwitch']
|
||||
NTabPane: typeof import('naive-ui')['NTabPane']
|
||||
NTabs: typeof import('naive-ui')['NTabs']
|
||||
NTag: typeof import('naive-ui')['NTag']
|
||||
NThing: typeof import('naive-ui')['NThing']
|
||||
NTimeline: typeof import('naive-ui')['NTimeline']
|
||||
NTimelineItem: typeof import('naive-ui')['NTimelineItem']
|
||||
NTooltip: typeof import('naive-ui')['NTooltip']
|
||||
|
@ -62,7 +62,7 @@ const apis: MockMethod[] = [
|
||||
{
|
||||
url: '/mock/testToken',
|
||||
method: 'post',
|
||||
response: (option: any): Service.MockServiceResult<true | null> => {
|
||||
response: (option: Service.MockOption): Service.MockServiceResult<true | null> => {
|
||||
if (option.headers?.authorization !== token.token) {
|
||||
return {
|
||||
code: 66666,
|
||||
|
@ -231,6 +231,39 @@ const routes: AuthRoute.Route[] = [
|
||||
order: 4
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'auth-demo',
|
||||
path: '/auth-demo',
|
||||
component: 'basic',
|
||||
children: [
|
||||
{
|
||||
name: 'auth-demo_permission',
|
||||
path: '/auth-demo/permission',
|
||||
component: 'self',
|
||||
meta: {
|
||||
title: '指令和权限切换',
|
||||
requiresAuth: true,
|
||||
icon: 'ic:round-construction'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'auth-demo_super',
|
||||
path: '/auth-demo/super',
|
||||
component: 'self',
|
||||
meta: {
|
||||
title: '超级管理员可见',
|
||||
requiresAuth: true,
|
||||
permissions: ['super'],
|
||||
icon: 'ic:round-supervisor-account'
|
||||
}
|
||||
}
|
||||
],
|
||||
meta: {
|
||||
title: '权限示例',
|
||||
icon: 'ic:baseline-security',
|
||||
order: 5
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'exception',
|
||||
path: '/exception',
|
||||
@ -270,7 +303,7 @@ const routes: AuthRoute.Route[] = [
|
||||
meta: {
|
||||
title: '异常页',
|
||||
icon: 'ant-design:exception-outlined',
|
||||
order: 5
|
||||
order: 6
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -324,7 +357,7 @@ const routes: AuthRoute.Route[] = [
|
||||
meta: {
|
||||
title: '多级菜单',
|
||||
icon: 'carbon:menu',
|
||||
order: 6
|
||||
order: 7
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -337,7 +370,7 @@ const routes: AuthRoute.Route[] = [
|
||||
singleLayout: 'basic',
|
||||
permissions: ['super', 'admin', 'test'],
|
||||
icon: 'fluent:book-information-24-regular',
|
||||
order: 7
|
||||
order: 8
|
||||
}
|
||||
}
|
||||
];
|
||||
|
@ -26,7 +26,7 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@antv/g2plot": "^2.4.15",
|
||||
"@antv/g2plot": "^2.4.16",
|
||||
"@better-scroll/core": "^2.4.2",
|
||||
"@vueuse/core": "^8.3.1",
|
||||
"axios": "^0.26.1",
|
||||
@ -54,7 +54,7 @@
|
||||
"@amap/amap-jsapi-types": "^0.0.8",
|
||||
"@commitlint/cli": "^16.2.3",
|
||||
"@commitlint/config-conventional": "^16.2.1",
|
||||
"@iconify/json": "^2.1.30",
|
||||
"@iconify/json": "^2.1.31",
|
||||
"@iconify/vue": "^3.2.1",
|
||||
"@types/bmapgl": "^0.0.5",
|
||||
"@types/crypto-js": "^4.1.1",
|
||||
@ -77,7 +77,7 @@
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-vue": "^8.6.0",
|
||||
"eslint-plugin-vue": "^8.7.1",
|
||||
"husky": "^7.0.4",
|
||||
"lint-staged": "^12.4.0",
|
||||
"mockjs": "^1.1.0",
|
||||
|
@ -2,11 +2,11 @@ lockfileVersion: 5.3
|
||||
|
||||
specifiers:
|
||||
'@amap/amap-jsapi-types': ^0.0.8
|
||||
'@antv/g2plot': ^2.4.15
|
||||
'@antv/g2plot': ^2.4.16
|
||||
'@better-scroll/core': ^2.4.2
|
||||
'@commitlint/cli': ^16.2.3
|
||||
'@commitlint/config-conventional': ^16.2.1
|
||||
'@iconify/json': ^2.1.30
|
||||
'@iconify/json': ^2.1.31
|
||||
'@iconify/vue': ^3.2.1
|
||||
'@types/bmapgl': ^0.0.5
|
||||
'@types/crypto-js': ^4.1.1
|
||||
@ -35,7 +35,7 @@ specifiers:
|
||||
eslint-config-prettier: ^8.5.0
|
||||
eslint-plugin-import: ^2.26.0
|
||||
eslint-plugin-prettier: ^4.0.0
|
||||
eslint-plugin-vue: ^8.6.0
|
||||
eslint-plugin-vue: ^8.7.1
|
||||
form-data: ^4.0.0
|
||||
husky: ^7.0.4
|
||||
lint-staged: ^12.4.0
|
||||
@ -72,7 +72,7 @@ specifiers:
|
||||
xgplayer: ^2.31.6
|
||||
|
||||
dependencies:
|
||||
'@antv/g2plot': 2.4.15
|
||||
'@antv/g2plot': 2.4.16
|
||||
'@better-scroll/core': registry.nlark.com/@better-scroll/core/2.4.2
|
||||
'@vueuse/core': 8.3.1_vue@3.2.33
|
||||
axios: 0.26.1
|
||||
@ -100,7 +100,7 @@ devDependencies:
|
||||
'@amap/amap-jsapi-types': 0.0.8
|
||||
'@commitlint/cli': 16.2.3
|
||||
'@commitlint/config-conventional': 16.2.1
|
||||
'@iconify/json': 2.1.30
|
||||
'@iconify/json': 2.1.31
|
||||
'@iconify/vue': 3.2.1_vue@3.2.33
|
||||
'@types/bmapgl': 0.0.5
|
||||
'@types/crypto-js': 4.1.1
|
||||
@ -112,7 +112,7 @@ devDependencies:
|
||||
'@vitejs/plugin-vue': 2.3.1_vite@2.9.5+vue@3.2.33
|
||||
'@vitejs/plugin-vue-jsx': 1.3.10
|
||||
'@vue/eslint-config-prettier': 7.0.0_eslint@8.13.0+prettier@2.6.2
|
||||
'@vue/eslint-config-typescript': 10.0.0_a62cbc2f4797496d74696b1f6538012a
|
||||
'@vue/eslint-config-typescript': 10.0.0_72c1a3548548335704ca8b66d8a11662
|
||||
'@vue/tsconfig': 0.1.3_@types+node@17.0.25
|
||||
commitizen: 4.2.4
|
||||
cross-env: registry.nlark.com/cross-env/7.0.3
|
||||
@ -123,7 +123,7 @@ devDependencies:
|
||||
eslint-config-prettier: 8.5.0_eslint@8.13.0
|
||||
eslint-plugin-import: 2.26.0_eslint@8.13.0
|
||||
eslint-plugin-prettier: 4.0.0_1815ac95b7fb26c13c7d48a8eef62d0f
|
||||
eslint-plugin-vue: 8.6.0_eslint@8.13.0
|
||||
eslint-plugin-vue: 8.7.1_eslint@8.13.0
|
||||
husky: 7.0.4
|
||||
lint-staged: 12.4.0
|
||||
mockjs: 1.1.0
|
||||
@ -307,8 +307,8 @@ packages:
|
||||
tslib: 2.3.1
|
||||
dev: false
|
||||
|
||||
/@antv/g2plot/2.4.15:
|
||||
resolution: {integrity: sha512-VDE1w8iOCuxgWmowGIHRoDNjQ/WDD31wx/wjMaGcaV1xHFOccG+nVycPaAV21Pjb3jwzDlqAWqvwHpT1lOBKFw==}
|
||||
/@antv/g2plot/2.4.16:
|
||||
resolution: {integrity: sha512-uuO08uyN4WvHHt0f3o6qVuIrUiARhIwebFh/JvMTnWEqoH3MbVo3e6vvcLhBrqE2J+WZeQyqrtyAxl92C95wqw==}
|
||||
dependencies:
|
||||
'@antv/event-emitter': 0.1.2
|
||||
'@antv/g2': 4.1.37
|
||||
@ -887,8 +887,8 @@ packages:
|
||||
resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==}
|
||||
dev: true
|
||||
|
||||
/@iconify/json/2.1.30:
|
||||
resolution: {integrity: sha512-mxaB9gr4sSAKUq6GJdXV42YC7tkJ9WOZW6/8zGXciiA1cjLLyHe73GJl6qpnc53G8SDSSXWClQC5RHWNz/HIBQ==}
|
||||
/@iconify/json/2.1.31:
|
||||
resolution: {integrity: sha512-peG8fjKAOe8w9xMrYo0kkDdF9AcDPxz89P516TTsC3EK2MVTaRuvuXEgMG3trqfU0Hur/n6ZZ/LXGE+/qS4aFg==}
|
||||
dependencies:
|
||||
'@iconify/types': 1.1.0
|
||||
pathe: 0.2.0
|
||||
@ -1520,7 +1520,7 @@ packages:
|
||||
prettier: 2.6.2
|
||||
dev: true
|
||||
|
||||
/@vue/eslint-config-typescript/10.0.0_a62cbc2f4797496d74696b1f6538012a:
|
||||
/@vue/eslint-config-typescript/10.0.0_72c1a3548548335704ca8b66d8a11662:
|
||||
resolution: {integrity: sha512-F94cL8ug3FaYXlCfU5/wiGjk1qeadmoBpRGAOBq+qre3Smdupa59dd6ZJrsfRODpsMPyTG7330juMDsUvpZ3Rw==, registry: http://registry.npm.taobao.org/, tarball: http://registry.npm.taobao.org/@vue/eslint-config-typescript/download/@vue/eslint-config-typescript-10.0.0.tgz}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
@ -1530,7 +1530,7 @@ packages:
|
||||
'@typescript-eslint/eslint-plugin': 5.20.0_b9ac9b5656ce5dffade639fcf5e491bf
|
||||
'@typescript-eslint/parser': 5.20.0_eslint@8.13.0+typescript@4.6.3
|
||||
eslint: 8.13.0
|
||||
eslint-plugin-vue: 8.6.0_eslint@8.13.0
|
||||
eslint-plugin-vue: 8.7.1_eslint@8.13.0
|
||||
vue-eslint-parser: 8.0.1_eslint@8.13.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@ -1704,7 +1704,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
/amdefine/1.0.1:
|
||||
resolution: {integrity: sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npm.taobao.org/amdefine/-/amdefine-1.0.1.tgz}
|
||||
resolution: {integrity: sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==}
|
||||
engines: {node: '>=0.4.2'}
|
||||
dev: false
|
||||
|
||||
@ -1849,7 +1849,7 @@ packages:
|
||||
dev: true
|
||||
|
||||
/boolbase/1.0.0:
|
||||
resolution: {integrity: sha1-aN/1++YMUes3cl6p4+0xDcwed24=}
|
||||
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
|
||||
dev: true
|
||||
|
||||
/brace-expansion/1.1.11:
|
||||
@ -2283,6 +2283,12 @@ packages:
|
||||
engines: {node: '>= 6'}
|
||||
dev: true
|
||||
|
||||
/cssesc/3.0.0:
|
||||
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
|
||||
engines: {node: '>=4'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/csstype/2.6.19:
|
||||
resolution: {integrity: sha512-ZVxXaNy28/k3kJg0Fou5MiYpp88j7H9hLZp8PDC3jV0WFjfH5E9xHb56L0W59cPbKbcHXeP4qyT8PrHp8t6LcQ==}
|
||||
dev: false
|
||||
@ -2421,7 +2427,7 @@ packages:
|
||||
dev: true
|
||||
|
||||
/decamelize/1.2.0:
|
||||
resolution: {integrity: sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=}
|
||||
resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
/deep-equal/1.1.1:
|
||||
@ -2963,8 +2969,8 @@ packages:
|
||||
prettier-linter-helpers: registry.nlark.com/prettier-linter-helpers/1.0.0
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-vue/8.6.0_eslint@8.13.0:
|
||||
resolution: {integrity: sha512-abXiF2J18n/7ZPy9foSlJyouKf54IqpKlNvNmzhM93N0zs3QUxZG/oBd3tVPOJTKg7SlhBUtPxugpqzNbgGpQQ==}
|
||||
/eslint-plugin-vue/8.7.1_eslint@8.13.0:
|
||||
resolution: {integrity: sha512-28sbtm4l4cOzoO1LtzQPxfxhQABararUb1JtqusQqObJpWX2e/gmVyeYVfepizPFne0Q5cILkYGiBoV36L12Wg==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: ^6.2.0 || ^7.0.0 || ^8.0.0
|
||||
@ -2972,6 +2978,8 @@ packages:
|
||||
eslint: 8.13.0
|
||||
eslint-utils: 3.0.0_eslint@8.13.0
|
||||
natural-compare: 1.4.0
|
||||
nth-check: 2.0.1
|
||||
postcss-selector-parser: 6.0.10
|
||||
semver: 7.3.5
|
||||
vue-eslint-parser: 8.0.1_eslint@8.13.0
|
||||
transitivePeerDependencies:
|
||||
@ -3297,7 +3305,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
/fs.realpath/1.0.0:
|
||||
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npm.taobao.org/fs.realpath/-/fs.realpath-1.0.0.tgz}
|
||||
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
||||
|
||||
/fsevents/2.3.2:
|
||||
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
|
||||
@ -3585,13 +3593,13 @@ packages:
|
||||
dev: true
|
||||
|
||||
/inflight/1.0.6:
|
||||
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npm.taobao.org/inflight/-/inflight-1.0.6.tgz}
|
||||
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
|
||||
dependencies:
|
||||
once: 1.4.0
|
||||
wrappy: 1.0.2
|
||||
|
||||
/inherits/2.0.4:
|
||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==, registry: http://registry.npm.taobao.org/, tarball: http://registry.npm.taobao.org/inherits/-/inherits-2.0.4.tgz}
|
||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
||||
|
||||
/ini/1.3.8:
|
||||
resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
|
||||
@ -3647,7 +3655,6 @@ packages:
|
||||
/is-callable/1.2.4:
|
||||
resolution: {integrity: sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==}
|
||||
engines: {node: '>= 0.4'}
|
||||
dev: false
|
||||
|
||||
/is-ci/2.0.0:
|
||||
resolution: {integrity: sha1-a8YzQYGBDgS1wis9WJ/cpVAmQEw=, registry: http://registry.npm.taobao.org/, tarball: http://registry.npm.taobao.org/is-ci/download/is-ci-2.0.0.tgz}
|
||||
@ -3666,7 +3673,6 @@ packages:
|
||||
engines: {node: '>= 0.4'}
|
||||
dependencies:
|
||||
has-tostringtag: 1.0.0
|
||||
dev: false
|
||||
|
||||
/is-docker/2.2.1:
|
||||
resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==}
|
||||
@ -4130,13 +4136,8 @@ packages:
|
||||
kind-of: 6.0.3
|
||||
dev: true
|
||||
|
||||
/minimist/1.2.5:
|
||||
resolution: {integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==}
|
||||
dev: false
|
||||
|
||||
/minimist/1.2.6:
|
||||
resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==}
|
||||
dev: true
|
||||
|
||||
/mkdirp/0.5.5:
|
||||
resolution: {integrity: sha1-2Rzv1i0UNsoPQWIOJRKI1CAJne8=, registry: http://registry.npm.taobao.org/, tarball: http://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.5.tgz}
|
||||
@ -4307,7 +4308,7 @@ packages:
|
||||
dev: true
|
||||
|
||||
/once/1.4.0:
|
||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npm.taobao.org/once/-/once-1.4.0.tgz}
|
||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
||||
dependencies:
|
||||
wrappy: 1.0.2
|
||||
|
||||
@ -4455,7 +4456,7 @@ packages:
|
||||
dev: true
|
||||
|
||||
/path-is-absolute/1.0.1:
|
||||
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npm.taobao.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz}
|
||||
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
/path-key/2.0.1:
|
||||
@ -4520,6 +4521,14 @@ packages:
|
||||
vue-demi: 0.12.1_vue@3.2.33
|
||||
dev: false
|
||||
|
||||
/postcss-selector-parser/6.0.10:
|
||||
resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==}
|
||||
engines: {node: '>=4'}
|
||||
dependencies:
|
||||
cssesc: 3.0.0
|
||||
util-deprecate: 1.0.2
|
||||
dev: true
|
||||
|
||||
/postcss/8.4.12:
|
||||
resolution: {integrity: sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
@ -4778,7 +4787,7 @@ packages:
|
||||
hasBin: true
|
||||
dependencies:
|
||||
chalk: 1.1.3
|
||||
minimist: 1.2.5
|
||||
minimist: 1.2.6
|
||||
source-map-support: 0.3.3
|
||||
dev: false
|
||||
|
||||
@ -5204,7 +5213,7 @@ packages:
|
||||
has: 1.0.3
|
||||
inherits: 2.0.4
|
||||
is-regex: 1.1.4
|
||||
minimist: 1.2.5
|
||||
minimist: 1.2.6
|
||||
object-inspect: 1.11.1
|
||||
resolve: 1.20.0
|
||||
resumer: 0.0.0
|
||||
@ -5573,7 +5582,7 @@ packages:
|
||||
dev: true
|
||||
|
||||
/util-deprecate/1.0.2:
|
||||
resolution: {integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=}
|
||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||
dev: true
|
||||
|
||||
/v8-compile-cache/2.3.0:
|
||||
@ -5851,7 +5860,7 @@ packages:
|
||||
dev: true
|
||||
|
||||
/wrappy/1.0.2:
|
||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npm.taobao.org/wrappy/-/wrappy-1.0.2.tgz}
|
||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||
|
||||
/xgplayer-subtitles/1.0.22:
|
||||
resolution: {integrity: sha512-+m1fo+FFynL+2ymO4UQBUSnJAz3WuIthpJFCrKBjd+ukcLRoy3vTcsylXEOo5AZN1xT28fpHmxvZQKEIEYA+6w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npm.taobao.org/xgplayer-subtitles/-/xgplayer-subtitles-1.0.22.tgz}
|
||||
@ -6150,8 +6159,8 @@ packages:
|
||||
version: 1.2.1
|
||||
engines: {node: '>= 0.4'}
|
||||
dependencies:
|
||||
is-callable: registry.nlark.com/is-callable/1.2.4
|
||||
is-date-object: registry.nlark.com/is-date-object/1.0.5
|
||||
is-callable: 1.2.4
|
||||
is-date-object: 1.0.5
|
||||
is-symbol: registry.nlark.com/is-symbol/1.0.4
|
||||
|
||||
registry.nlark.com/escape-html/1.0.3:
|
||||
@ -6394,14 +6403,6 @@ packages:
|
||||
version: 1.2.4
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
registry.nlark.com/is-date-object/1.0.5:
|
||||
resolution: {integrity: sha1-CEHVU25yTCVZe/bqYuG9OCmN8x8=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/is-date-object/download/is-date-object-1.0.5.tgz}
|
||||
name: is-date-object
|
||||
version: 1.0.5
|
||||
engines: {node: '>= 0.4'}
|
||||
dependencies:
|
||||
has-tostringtag: 1.0.0
|
||||
|
||||
registry.nlark.com/is-docker/2.2.1:
|
||||
resolution: {integrity: sha1-M+6r4jz+hvFL3kQIoCwM+4U6zao=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/is-docker/download/is-docker-2.2.1.tgz}
|
||||
name: is-docker
|
||||
|
@ -1,9 +1,11 @@
|
||||
import type { App } from 'vue';
|
||||
import setupNetworkDirective from './network';
|
||||
import setupLoginDirective from './login';
|
||||
import setupPermissionDirective from './permission';
|
||||
|
||||
/** setup custom vue directives. - [安装自定义的vue指令] */
|
||||
export function setupDirectives(app: App) {
|
||||
setupNetworkDirective(app);
|
||||
setupLoginDirective(app);
|
||||
setupPermissionDirective(app);
|
||||
}
|
||||
|
@ -1,16 +1,28 @@
|
||||
import type { App, Directive } from 'vue';
|
||||
import { useAuthStore } from '@/store';
|
||||
import { isArray, isString } from '@/utils';
|
||||
|
||||
export default function setupLoginDirective(app: App) {
|
||||
export default function setupPermissionDirective(app: App) {
|
||||
const auth = useAuthStore();
|
||||
|
||||
const loginDirective: Directive<HTMLElement, Auth.RoleType | undefined> = {
|
||||
const permissionDirective: Directive<HTMLElement, Auth.RoleType | Auth.RoleType[]> = {
|
||||
mounted(el: HTMLElement, binding) {
|
||||
if (binding.value !== auth.userInfo.userRole) {
|
||||
const { userRole } = auth.userInfo;
|
||||
const elPermission = binding.value;
|
||||
let hasPermission = userRole === 'super';
|
||||
if (!hasPermission) {
|
||||
if (isArray(elPermission)) {
|
||||
hasPermission = (elPermission as Auth.RoleType[]).includes(userRole);
|
||||
}
|
||||
if (isString(elPermission)) {
|
||||
hasPermission = (elPermission as Auth.RoleType) === userRole;
|
||||
}
|
||||
}
|
||||
if (!hasPermission) {
|
||||
el.remove();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
app.directive('login', loginDirective);
|
||||
app.directive('permission', permissionDirective);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ export async function createDynamicRouteGuard(
|
||||
const isLogin = Boolean(getToken());
|
||||
|
||||
// 初始化权限路由
|
||||
if (!route.isInitedAuthRoute) {
|
||||
if (!route.isInitAuthRoute) {
|
||||
// 未登录情况下直接回到登录页,登录成功后再加载权限路由
|
||||
if (!isLogin) {
|
||||
if (to.name === routeName('login')) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import type { App } from 'vue';
|
||||
import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router';
|
||||
import { transformAuthRoutesToVueRoutes } from '@/utils';
|
||||
import { transformAuthRoutesToVueRoutes, transformRouteNameToRoutePath } from '@/utils';
|
||||
import { constantRoutes } from './routes';
|
||||
import { scrollBehavior } from './helpers';
|
||||
import { createRouterGuard } from './guard';
|
||||
@ -20,5 +20,10 @@ export async function setupRouter(app: App) {
|
||||
await router.isReady();
|
||||
}
|
||||
|
||||
/** 路由名称 */
|
||||
export const routeName = (key: AuthRoute.RouteKey) => key;
|
||||
/** 路由路径 */
|
||||
export const routePath = (key: Exclude<AuthRoute.RouteKey, 'not-found-page'>) => transformRouteNameToRoutePath(key);
|
||||
|
||||
export * from './routes';
|
||||
export * from './modules';
|
||||
|
@ -8,7 +8,7 @@ const about: AuthRoute.Route = {
|
||||
singleLayout: 'basic',
|
||||
permissions: ['super', 'admin', 'test'],
|
||||
icon: 'fluent:book-information-24-regular',
|
||||
order: 7
|
||||
order: 8
|
||||
}
|
||||
};
|
||||
|
||||
|
35
src/router/modules/auth-demo.ts
Normal file
35
src/router/modules/auth-demo.ts
Normal file
@ -0,0 +1,35 @@
|
||||
const authDemo: AuthRoute.Route = {
|
||||
name: 'auth-demo',
|
||||
path: '/auth-demo',
|
||||
component: 'basic',
|
||||
children: [
|
||||
{
|
||||
name: 'auth-demo_permission',
|
||||
path: '/auth-demo/permission',
|
||||
component: 'self',
|
||||
meta: {
|
||||
title: '指令和权限切换',
|
||||
requiresAuth: true,
|
||||
icon: 'ic:round-construction'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'auth-demo_super',
|
||||
path: '/auth-demo/super',
|
||||
component: 'self',
|
||||
meta: {
|
||||
title: '超级管理员可见',
|
||||
requiresAuth: true,
|
||||
permissions: ['super'],
|
||||
icon: 'ic:round-supervisor-account'
|
||||
}
|
||||
}
|
||||
],
|
||||
meta: {
|
||||
title: '权限示例',
|
||||
icon: 'ic:baseline-security',
|
||||
order: 5
|
||||
}
|
||||
};
|
||||
|
||||
export default authDemo;
|
@ -37,7 +37,7 @@ const exception: AuthRoute.Route = {
|
||||
meta: {
|
||||
title: '异常页',
|
||||
icon: 'ant-design:exception-outlined',
|
||||
order: 5
|
||||
order: 6
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -5,7 +5,7 @@ export const constantRoutes: AuthRoute.Route[] = [
|
||||
{
|
||||
name: 'root',
|
||||
path: '/',
|
||||
redirect: '/dashboard/analysis',
|
||||
redirect: import.meta.env.VITE_ROUTE_HOME_PATH,
|
||||
meta: {
|
||||
title: 'Root'
|
||||
}
|
||||
@ -64,16 +64,3 @@ export const constantRoutes: AuthRoute.Route[] = [
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
/** 路由名称 */
|
||||
export const routeName = (key: AuthRoute.RouteKey) => key;
|
||||
|
||||
/** 路由路径 */
|
||||
export function routePath(key: Exclude<AuthRoute.RouteKey, 'not-found-page'>): AuthRoute.RoutePath {
|
||||
const rootPath: AuthRoute.RoutePath = '/';
|
||||
if (key === 'root') return rootPath;
|
||||
const splitMark: AuthRoute.RouteSplitMark = '_';
|
||||
const pathSplitMark = '/';
|
||||
const path = key.split(splitMark).join(pathSplitMark);
|
||||
return (pathSplitMark + path) as AuthRoute.RoutePath;
|
||||
}
|
||||
|
@ -87,6 +87,9 @@ export const useAuthStore = defineStore('auth-store', {
|
||||
await this.loginByToken(data);
|
||||
}
|
||||
this.loginLoading = false;
|
||||
},
|
||||
updateUserRole(userRole: Auth.RoleType) {
|
||||
this.userInfo.userRole = userRole;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -7,8 +7,11 @@ import {
|
||||
transformAuthRouteToMenu,
|
||||
transformAuthRoutesToVueRoutes,
|
||||
transformAuthRoutesToSearchMenus,
|
||||
getCacheRoutes
|
||||
getCacheRoutes,
|
||||
filterAuthRoutesByUserPermission,
|
||||
transformRoutePathToRouteName
|
||||
} from '@/utils';
|
||||
import { useAuthStore } from '../auth';
|
||||
import { useTabStore } from '../tab';
|
||||
|
||||
interface RouteState {
|
||||
@ -19,7 +22,7 @@ interface RouteState {
|
||||
*/
|
||||
authRouteMode: ImportMetaEnv['VITE_AUTH_ROUTE_MODE'];
|
||||
/** 是否初始化了权限路由 */
|
||||
isInitedAuthRoute: boolean;
|
||||
isInitAuthRoute: boolean;
|
||||
/** 路由首页name(前端静态路由时生效,后端动态路由该值会被后端返回的值覆盖) */
|
||||
routeHomeName: AuthRoute.RouteKey;
|
||||
/** 菜单 */
|
||||
@ -33,8 +36,8 @@ interface RouteState {
|
||||
export const useRouteStore = defineStore('route-store', {
|
||||
state: (): RouteState => ({
|
||||
authRouteMode: import.meta.env.VITE_AUTH_ROUTE_MODE,
|
||||
isInitedAuthRoute: false,
|
||||
routeHomeName: 'dashboard_analysis',
|
||||
isInitAuthRoute: false,
|
||||
routeHomeName: transformRoutePathToRouteName(import.meta.env.VITE_ROUTE_HOME_PATH),
|
||||
menus: [],
|
||||
searchMenus: [],
|
||||
cacheRoutes: []
|
||||
@ -73,9 +76,9 @@ export const useRouteStore = defineStore('route-store', {
|
||||
* @param router - 路由实例
|
||||
*/
|
||||
async initStaticRoute(router: Router) {
|
||||
// 先根据用户权限过滤一下staticRoutes
|
||||
|
||||
this.handleAuthRoutes(staticRoutes, router);
|
||||
const auth = useAuthStore();
|
||||
const routes = filterAuthRoutesByUserPermission(staticRoutes, auth.userInfo.userRole);
|
||||
this.handleAuthRoutes(routes, router);
|
||||
},
|
||||
/**
|
||||
* 初始化权限路由
|
||||
@ -84,6 +87,7 @@ export const useRouteStore = defineStore('route-store', {
|
||||
async initAuthRoute(router: Router) {
|
||||
const { initHomeTab } = useTabStore();
|
||||
const { userId } = getUserInfo();
|
||||
|
||||
if (!userId) return;
|
||||
|
||||
const isDynamicRoute = this.authRouteMode === 'dynamic';
|
||||
@ -94,7 +98,8 @@ export const useRouteStore = defineStore('route-store', {
|
||||
}
|
||||
|
||||
initHomeTab(this.routeHomeName, router);
|
||||
this.isInitedAuthRoute = true;
|
||||
|
||||
this.isInitAuthRoute = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -21,7 +21,7 @@ export const useTabStore = defineStore('tab-store', {
|
||||
name: 'root',
|
||||
path: '/',
|
||||
meta: {
|
||||
title: 'root'
|
||||
title: 'Root'
|
||||
},
|
||||
scrollPosition: {
|
||||
left: 0,
|
||||
@ -53,7 +53,8 @@ export const useTabStore = defineStore('tab-store', {
|
||||
initHomeTab(routeHomeName: string, router: Router) {
|
||||
const routes = router.getRoutes();
|
||||
const findHome = routes.find(item => item.name === routeHomeName);
|
||||
if (findHome) {
|
||||
if (findHome && !findHome.children) {
|
||||
// 有子路由的不能作为Tab
|
||||
this.homeTab = getTabRouteByVueRoute(findHome);
|
||||
}
|
||||
},
|
||||
@ -165,16 +166,20 @@ export const useTabStore = defineStore('tab-store', {
|
||||
iniTabStore(currentRoute: RouteLocationNormalizedLoaded) {
|
||||
const theme = useThemeStore();
|
||||
|
||||
const isHome = currentRoute.path === this.homeTab.path;
|
||||
const tabs: GlobalTabRoute[] = theme.tab.isCache ? getTabRoutes() : [];
|
||||
|
||||
const hasHome = isInTabRoutes(tabs, this.homeTab.path);
|
||||
const hasCurrent = isInTabRoutes(tabs, currentRoute.path);
|
||||
if (!hasHome) {
|
||||
if (!hasHome && this.homeTab.name !== 'root') {
|
||||
tabs.unshift(this.homeTab);
|
||||
}
|
||||
|
||||
const isHome = currentRoute.path === this.homeTab.path;
|
||||
const hasCurrent = isInTabRoutes(tabs, currentRoute.path);
|
||||
if (!isHome && !hasCurrent) {
|
||||
tabs.push(getTabRouteByVueRoute(currentRoute));
|
||||
const currentTab = getTabRouteByVueRoute(currentRoute);
|
||||
tabs.push(currentTab);
|
||||
}
|
||||
|
||||
this.tabs = tabs;
|
||||
this.setActiveTab(currentRoute.path);
|
||||
}
|
||||
|
5
src/typings/env.d.ts
vendored
5
src/typings/env.d.ts
vendored
@ -27,8 +27,11 @@ interface ImportMetaEnv {
|
||||
/**
|
||||
* 权限路由模式:
|
||||
* - static - 前端声明的静态
|
||||
* - dynamic - 后端返回的动态 */
|
||||
* - dynamic - 后端返回的动态
|
||||
*/
|
||||
readonly VITE_AUTH_ROUTE_MODE: 'static' | 'dynamic';
|
||||
/** 路由首页的路径 */
|
||||
readonly VITE_ROUTE_HOME_PATH: Exclude<AuthRoute.RoutePath, '/not-found-page' | '/:pathMatch(.*)*'>;
|
||||
/** vite环境类型 */
|
||||
readonly VITE_ENV_TYPE?: EnvType;
|
||||
/** 开启请求代理 */
|
||||
|
3
src/typings/route.d.ts
vendored
3
src/typings/route.d.ts
vendored
@ -36,6 +36,9 @@ declare namespace AuthRoute {
|
||||
| 'plugin_icon'
|
||||
| 'plugin_print'
|
||||
| 'plugin_swiper'
|
||||
| 'auth-demo'
|
||||
| 'auth-demo_permission'
|
||||
| 'auth-demo_super'
|
||||
| 'exception'
|
||||
| 'exception_403'
|
||||
| 'exception_404'
|
||||
|
8
src/typings/system.d.ts
vendored
8
src/typings/system.d.ts
vendored
@ -84,6 +84,14 @@ declare namespace Service {
|
||||
/** 接口消息 */
|
||||
message: string;
|
||||
}
|
||||
|
||||
/** mock的响应option */
|
||||
interface MockOption {
|
||||
url: Record<string, any>;
|
||||
body: Record<string, any>;
|
||||
query: Record<string, any>;
|
||||
headers: Record<string, any>;
|
||||
}
|
||||
}
|
||||
|
||||
/** 主题相关类型 */
|
||||
|
@ -37,7 +37,7 @@ export function getUserInfo() {
|
||||
userId: '',
|
||||
userName: '',
|
||||
userPhone: '',
|
||||
userRole: 'test'
|
||||
userRole: 'normal'
|
||||
};
|
||||
const userInfo: Auth.UserInfo = getLocal<Auth.UserInfo>(EnumStorageKey['user-info']) || emptyInfo;
|
||||
return userInfo;
|
||||
|
@ -1,16 +1,10 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
/**
|
||||
* 根据用户权限过滤路由
|
||||
* @param routes - 权限路由
|
||||
* @param permission - 权限
|
||||
*/
|
||||
export function filterAuthRoutesByUserPermission(routes: AuthRoute.Route[], permission: Auth.RoleType) {
|
||||
const filters: AuthRoute.Route[] = [];
|
||||
|
||||
routes.forEach(route => {
|
||||
filterAuthRouteByUserPermission(route, permission);
|
||||
});
|
||||
return filters;
|
||||
return routes.map(route => filterAuthRouteByUserPermission(route, permission)).flat(1);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -19,5 +13,12 @@ export function filterAuthRoutesByUserPermission(routes: AuthRoute.Route[], perm
|
||||
* @param permission - 权限
|
||||
*/
|
||||
function filterAuthRouteByUserPermission(route: AuthRoute.Route, permission: Auth.RoleType): AuthRoute.Route[] {
|
||||
return [];
|
||||
const hasPermission =
|
||||
!route.meta.permissions || permission === 'super' || route.meta.permissions.includes(permission);
|
||||
|
||||
if (route.children) {
|
||||
const filterChildren = route.children.map(item => filterAuthRouteByUserPermission(item, permission)).flat(1);
|
||||
Object.assign(route, { children: filterChildren });
|
||||
}
|
||||
return hasPermission ? [route] : [];
|
||||
}
|
||||
|
@ -31,6 +31,34 @@ export function transformAuthRoutesToSearchMenus(routes: AuthRoute.Route[], tree
|
||||
}, treeMap);
|
||||
}
|
||||
|
||||
/** 将路由名字转换成路由路径 */
|
||||
export function transformRouteNameToRoutePath(
|
||||
name: Exclude<AuthRoute.RouteKey, 'not-found-page'>
|
||||
): AuthRoute.RoutePath {
|
||||
const rootPath: AuthRoute.RoutePath = '/';
|
||||
if (name === 'root') return rootPath;
|
||||
|
||||
const splitMark: AuthRoute.RouteSplitMark = '_';
|
||||
const pathSplitMark = '/';
|
||||
const path = name.split(splitMark).join(pathSplitMark);
|
||||
|
||||
return (pathSplitMark + path) as AuthRoute.RoutePath;
|
||||
}
|
||||
|
||||
/** 将路由路径转换成路由名字 */
|
||||
export function transformRoutePathToRouteName(
|
||||
path: Exclude<AuthRoute.RoutePath, '/not-found-page' | '/:pathMatch(.*)*'>
|
||||
): AuthRoute.RouteKey {
|
||||
if (path === '/') return 'root';
|
||||
|
||||
const pathSplitMark = '/';
|
||||
const routeSplitMark: AuthRoute.RouteSplitMark = '_';
|
||||
|
||||
const name = path.split(pathSplitMark).slice(1).join(routeSplitMark) as AuthRoute.RouteKey;
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将单个权限路由转换成vue路由
|
||||
* @param item - 单个权限路由
|
||||
|
@ -1,6 +1,7 @@
|
||||
export * from './module';
|
||||
export * from './helpers';
|
||||
export * from './cache';
|
||||
export * from './auth';
|
||||
export * from './menu';
|
||||
export * from './breadcrumb';
|
||||
export * from './tab';
|
||||
|
46
src/views/auth-demo/permission/index.vue
Normal file
46
src/views/auth-demo/permission/index.vue
Normal file
@ -0,0 +1,46 @@
|
||||
<template>
|
||||
<div class="h-full">
|
||||
<n-card title="权限指令 v-permission" class="h-full shadow-sm rounded-16px">
|
||||
<div class="pb-12px">
|
||||
<n-gradient-text type="primary" :size="20">当前用户的权限:{{ auth.userInfo.userRole }}</n-gradient-text>
|
||||
</div>
|
||||
<n-space>
|
||||
<n-button v-permission="`super`">super可见</n-button>
|
||||
<n-button v-permission="`admin`">admin可见</n-button>
|
||||
<n-button v-permission="['admin', 'test']">admin和test可见</n-button>
|
||||
</n-space>
|
||||
<div class="py-12px">
|
||||
<n-gradient-text type="primary" :size="20">切换用户权限</n-gradient-text>
|
||||
</div>
|
||||
<n-select
|
||||
:value="auth.userInfo.userRole"
|
||||
class="w-120px"
|
||||
size="small"
|
||||
:options="roleList"
|
||||
@update:value="auth.updateUserRole"
|
||||
/>
|
||||
</n-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { watch } from 'vue';
|
||||
import { useAppStore, useAuthStore } from '@/store';
|
||||
|
||||
const app = useAppStore();
|
||||
const auth = useAuthStore();
|
||||
|
||||
const roleList = [
|
||||
{ label: '超级管理员', value: 'super' },
|
||||
{ label: '管理员', value: 'admin' },
|
||||
{ label: '测试', value: 'test' }
|
||||
];
|
||||
|
||||
watch(
|
||||
() => auth.userInfo.userRole,
|
||||
async () => {
|
||||
app.reloadPage();
|
||||
}
|
||||
);
|
||||
</script>
|
||||
<style scoped></style>
|
8
src/views/auth-demo/super/index.vue
Normal file
8
src/views/auth-demo/super/index.vue
Normal file
@ -0,0 +1,8 @@
|
||||
<template>
|
||||
<div class="h-full">
|
||||
<n-card title="当前页面只有super才能看到" class="h-full shadow-sm rounded-16px"> </n-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts"></script>
|
||||
<style scoped></style>
|
Loading…
Reference in New Issue
Block a user