Skip to content

Commit 9a9598b

Browse files
author
sunss
committed
feat: 调整权限逻辑,补充v-role指令
1 parent d32087c commit 9a9598b

File tree

7 files changed

+175
-13
lines changed

7 files changed

+175
-13
lines changed

src/components/Table/index.vue

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
>
4444
<a @click.prevent="() => {}" :type="action.type">{{ action.label }}</a>
4545
</a-popconfirm>
46+
<span v-else-if="!action.permission">——</span>
4647
<!-- 按钮 -->
4748
<a v-else @click="action?.onClick(record)" :type="action.type">{{ action.label }}</a>
4849
<!-- 分割线 -->
@@ -58,6 +59,7 @@
5859
import { usePagination } from 'vue-request';
5960
import { formatToDate, formatToDateTime } from '/@/utils/dateUtil';
6061
import { usePermission } from '/@/hooks/usePermission';
62+
import { useRole } from '/@/hooks/useRole';
6163
6264
// const req = () => new Promise((resolve) => resolve({ total: 0, list: [] }));
6365
@@ -77,6 +79,7 @@
7779
// emits: ['onSearch'],
7880
setup(props) {
7981
const { hasPermission } = usePermission();
82+
const { hasRole } = useRole();
8083
const {
8184
data: dataSource,
8285
run,
@@ -120,17 +123,20 @@
120123
121124
// action 操作列
122125
const getActions = computed(() => {
123-
return (toRaw(props.actions) || [])
124-
.filter((action) => hasPermission(action.auth))
125-
.map((action) => {
126-
const { popConfirm } = action;
127-
return {
128-
type: 'link',
129-
...action,
130-
...(popConfirm || {}),
131-
enable: !!popConfirm,
132-
};
133-
});
126+
return (
127+
(toRaw(props.actions) || [])
128+
// .filter((action) => hasPermission(action.auth))
129+
.map((action) => {
130+
const { popConfirm } = action;
131+
return {
132+
type: 'link',
133+
...action,
134+
...(popConfirm || {}),
135+
enable: !!popConfirm,
136+
permission: hasPermission(action.auth) && hasRole(action.role),
137+
};
138+
})
139+
);
134140
});
135141
136142
// filter

src/components/TableFilter/index.vue

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
<a-row type="flex">
55
<a-col v-if="button" flex="100px">
66
<span class="text" v-if="button.type === 'text'">{{ button.label }}</span>
7-
<a-button v-else v-bind="button" v-auth="button.auth" @click="button?.onClick">{{
7+
<!-- <a-button v-else v-bind="button" v-auth="button.auth" @click="button?.onClick">{{
8+
button.label
9+
}}</a-button> -->
10+
<a-button v-if="getButton.permission" v-bind="button" @click="button?.onClick">{{
811
button.label
912
}}</a-button>
1013
</a-col>
@@ -47,11 +50,17 @@
4750
</a-card>
4851
</template>
4952
<script lang="ts">
53+
import { usePermission } from '/@/hooks/usePermission';
54+
import { useRole } from '/@/hooks/useRole';
55+
5056
export default defineComponent({
5157
props: ['hiddenFilter', 'button', 'items', 'model'],
5258
emits: ['onSearch'],
5359
5460
setup(props, { emit }) {
61+
const { hasPermission } = usePermission();
62+
const { hasRole } = useRole();
63+
5564
const formModel = reactive(props.model || {});
5665
5766
const getItems = computed(() => {
@@ -78,10 +87,19 @@
7887
}
7988
});
8089
90+
const getButton = computed(() => {
91+
const plainObj = toRaw(props.button) || {};
92+
return {
93+
...plainObj,
94+
permission: hasPermission(plainObj.auth) && hasRole(plainObj.role),
95+
};
96+
});
97+
8198
return {
8299
formModel,
83100
getItems,
84101
hasHidden,
102+
getButton,
85103
handleSubmit,
86104
};
87105
},

src/directives/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
*/
44
import type { App } from 'vue';
55
import { setupPermissionDirective } from './permission';
6+
import { setupRoleDirective } from './role';
67

78
export function setupGlobDirectives(app: App) {
89
setupPermissionDirective(app);
10+
setupRoleDirective(app);
911
}

src/directives/role.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* Global authority directive
3+
* 角色控制: 银行 0 / 监管 1
4+
* @Example v-role="role"
5+
*/
6+
import type { App, Directive, DirectiveBinding } from 'vue';
7+
import { useRole } from '/@/hooks/useRole';
8+
import intersection from 'lodash-es/intersection';
9+
10+
// 操作按钮无权限时,替换展示内容
11+
function replaceHtml(parentNode: HTMLElement | null) {
12+
if (!parentNode) return;
13+
14+
const child = document.createElement('span');
15+
// 只过滤 Table里的操作按钮
16+
const classNames = ['ant-space-item', 'ant-table-row-cell-break-word'];
17+
const parentNodeText =
18+
intersection(classNames, parentNode?.className?.split(' ')).length > 0 ? '——' : '';
19+
// console.dir(parentNode);
20+
child.innerHTML = parentNodeText;
21+
child.style.color = 'rgba(0,0,0,.08)';
22+
parentNode?.appendChild(child);
23+
}
24+
25+
function isAuth(el: Element, binding: any) {
26+
const { hasRole } = useRole();
27+
const value = binding.value;
28+
// 过滤 undefined、null
29+
if (value == null) return;
30+
// 权限验证
31+
32+
if (!hasRole(value)) {
33+
const parentNode = el.parentNode;
34+
el.parentNode?.removeChild(el);
35+
replaceHtml(parentNode as any);
36+
}
37+
}
38+
39+
const mounted = (el: Element, binding: DirectiveBinding<any>) => {
40+
isAuth(el, binding);
41+
};
42+
43+
const authDirective: Directive = {
44+
mounted,
45+
};
46+
47+
export function setupRoleDirective(app: App) {
48+
app.directive('role', authDirective);
49+
}
50+
51+
export default authDirective;

src/hooks/useRole.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* @name useRole
3+
* @description 处理角色权限
4+
*/
5+
6+
import { usePermissioStore } from '/@/store/modules/permission';
7+
8+
export function useRole() {
9+
const permissioStore = usePermissioStore();
10+
11+
function hasRole(value?: string | string[], def = true): boolean {
12+
if (value == null) {
13+
return def;
14+
}
15+
16+
if (typeof value === 'boolean') {
17+
return value;
18+
}
19+
20+
if (typeof value === 'number') {
21+
return permissioStore.getRole === value;
22+
}
23+
return def;
24+
}
25+
26+
return { hasRole };
27+
}

src/store/modules/permission.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ interface PermissioState {
1010
isAdmin: 0 | 1; // 是否为管理员
1111
auths: string[]; // 当前用户权限
1212
modules: string[]; // 模块权限
13+
role: 0 | 1;
1314
}
1415

1516
export const usePermissioStore = defineStore({
@@ -23,11 +24,16 @@ export const usePermissioStore = defineStore({
2324
auths: [],
2425
// modules
2526
modules: [],
27+
// role 0-银行 1-银保监
28+
role: 0,
2629
}),
2730
getters: {
2831
getAuths(): string[] {
2932
return this.auths;
3033
},
34+
getRole(): 0 | 1 {
35+
return this.role;
36+
},
3137
getModules(): string[] {
3238
return this.modules;
3339
},
@@ -52,6 +58,7 @@ export const usePermissioStore = defineStore({
5258
this.isAdmin = 0;
5359
this.auths = [];
5460
this.modules = [];
61+
this.role = 0;
5562
},
5663

5764
/**
@@ -88,6 +95,36 @@ export const usePermissioStore = defineStore({
8895

8996
return routes;
9097
},
98+
99+
// /**
100+
// * @name buildRoutesAction
101+
// * @description: 获取路由
102+
// */
103+
// buildRoutesAction(): RouteRecordRaw[] {
104+
// // this.isGetUserInfo = true;
105+
// this.setIsGetUserInfo(true);
106+
107+
// // 404 路由一定要放在 权限路由后面
108+
// let routes: RouteRecordRaw[] = [...constantRoutes, ...accessRoutes, ...publicRoutes];
109+
110+
// // 1. 角色权限过滤:0-银行 1-银保监
111+
// let filterRoutes = filterRouteByRole(cloneDeep(accessRoutes), this.role);
112+
// // let filterRoutes = routes;
113+
114+
// // 2. 菜单权限过滤:
115+
// // 管理员直接跳过
116+
// if (this.getIsAdmin === 0) {
117+
// const filterRoutesByAuth = filterAsyncRoutes(cloneDeep(filterRoutes), this.modules);
118+
// filterRoutes = filterRoutesByAuth;
119+
// }
120+
121+
// // 普通用户
122+
// // 1. 方案一:过滤每个路由模块涉及的接口权限,判断是否展示该路由
123+
// // 2. 方案二:直接检索接口权限列表是否包含该路由模块,不做细分,axios同一拦截
124+
// routes = [...constantRoutes, ...filterRoutes, ...publicRoutes];
125+
126+
// return routes;
127+
// },
91128
},
92129
});
93130

src/utils/permission.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export const filterModuleByAuths = (auths: string[]): string[] => {
2222
// 不需要权限过滤的 白名单
2323
export const WhiteList = ['/v1/user/login', '/v1/user/permission', '/v1/account/info'];
2424

25-
type IAuth = { auth?: string[] };
25+
type IAuth = { auth?: string[]; role?: number };
2626

2727
export const filterAsyncRoutes = (routes: RouteRecordRaw[], roles: string[]): RouteRecordRaw[] => {
2828
const res: RouteRecordRaw[] = [];
@@ -44,3 +44,24 @@ export const filterAsyncRoutes = (routes: RouteRecordRaw[], roles: string[]): Ro
4444
});
4545
return res;
4646
};
47+
48+
export const filterRouteByRole = (routes: RouteRecordRaw[], ROLE: number) => {
49+
const filterChildrenByRole = (currentRoutes: RouteRecordRaw[]): RouteRecordRaw[] => {
50+
const result: RouteRecordRaw[] = [];
51+
52+
currentRoutes.forEach((route) => {
53+
const { role } = (route.meta as IAuth) || {};
54+
55+
if (role == undefined || role == ROLE) {
56+
if (route.children) {
57+
route.children = filterChildrenByRole(route.children);
58+
}
59+
result.push(route);
60+
}
61+
});
62+
63+
return result;
64+
};
65+
66+
return filterChildrenByRole(routes);
67+
};

0 commit comments

Comments
 (0)