feat: UI permission instruction (#3010)

This commit is contained in:
shaohuzhang1 2025-04-28 10:20:40 +08:00 committed by GitHub
parent c79479d80b
commit 99fd32897c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 96 additions and 10 deletions

View File

@ -0,0 +1,27 @@
import type { App } from 'vue'
import { hasPermission } from '@/utils/permission'
const display = async (el: any, binding: any) => {
const has = hasPermission(
binding.value?.permission || binding.value,
binding.value?.compare || 'OR',
)
if (!has) {
el.style.display = 'none'
} else {
delete el.style.display
}
}
export default {
install: (app: App) => {
app.directive('hasPermission', {
async created(el: any, binding: any) {
display(el, binding)
},
async beforeUpdate(el: any, binding: any) {
display(el, binding)
},
})
},
}

View File

@ -0,0 +1,14 @@
import type { App } from 'vue'
const directives = import.meta.glob('./*.ts', { eager: true })
const install = (app: App) => {
Object.keys(directives)
.filter((key: string) => {
return !key.endsWith('index.ts')
})
.forEach((key: string) => {
const directive: any = directives[key]
app.use(directive.default)
})
}
export default { install }

View File

@ -10,6 +10,7 @@ import App from './App.vue'
import router from '@/router' import router from '@/router'
import i18n from '@/locales' import i18n from '@/locales'
import Components from '@/components' import Components from '@/components'
import directives from '@/directives'
const app = createApp(App) const app = createApp(App)
app.use(createPinia()) app.use(createPinia())
for (const [key, component] of Object.entries(ElementPlusIcons)) { for (const [key, component] of Object.entries(ElementPlusIcons)) {
@ -18,11 +19,12 @@ for (const [key, component] of Object.entries(ElementPlusIcons)) {
const locale_map: any = { const locale_map: any = {
'zh-CN': zhCn, 'zh-CN': zhCn,
'zh-Hant': zhTW, 'zh-Hant': zhTW,
'en-US': enUs 'en-US': enUs,
} }
app.use(ElementPlus, { app.use(ElementPlus, {
locale: locale_map[localStorage.getItem('MaxKB-locale') || navigator.language || 'en-US'] locale: locale_map[localStorage.getItem('MaxKB-locale') || navigator.language || 'en-US'],
}) })
app.use(directives)
app.use(router) app.use(router)
app.use(i18n) app.use(i18n)
app.use(Components) app.use(Components)

View File

@ -36,8 +36,8 @@ const useLoginStore = defineStore('user', {
return !this.themeInfo?.theme || this.themeInfo?.theme === '#3370FF' return !this.themeInfo?.theme || this.themeInfo?.theme === '#3370FF'
}, },
async profile() { async profile() {
return UserApi.getUserProfile().then((ok: { data: User }) => { return UserApi.getUserProfile().then((ok) => {
this.userInfo = ok.data this.userInfo = ok
useLocalStorage<string>(localeConfigKey, 'en-US').value = useLocalStorage<string>(localeConfigKey, 'en-US').value =
ok.data?.language || this.getLanguage() ok.data?.language || this.getLanguage()
// return this.asyncGetProfile() // return this.asyncGetProfile()
@ -72,7 +72,7 @@ const useLoginStore = defineStore('user', {
? [...this.userInfo?.permissions, 'x-pack'] ? [...this.userInfo?.permissions, 'x-pack']
: this.userInfo?.permissions : this.userInfo?.permissions
} else { } else {
return [] return this.userInfo?.permissions
} }
}, },
getRole() { getRole() {

View File

@ -0,0 +1,7 @@
import { Permission } from '@/utils/permission/type'
const PermissionConst = {
USER_READ: new Permission('USER:READ'),
USER_CREATE: new Permission('USER:CREATE'),
KNOWLEDGE_READ: new Permission('KNOWLEDGE:READ'),
}
export default PermissionConst

View File

@ -1,4 +1,4 @@
import useStore from '@/stores'; import useStore from '@/stores'
import { Role, Permission, ComplexPermission } from '@/utils/permission/type' import { Role, Permission, ComplexPermission } from '@/utils/permission/type'
/** /**
* *
@ -6,7 +6,7 @@ import { Role, Permission, ComplexPermission } from '@/utils/permission/type'
* @returns True false * @returns True false
*/ */
const hasPermissionChild = (permission: Role | string | Permission | ComplexPermission) => { const hasPermissionChild = (permission: Role | string | Permission | ComplexPermission) => {
const { user } = useStore(); const { user } = useStore()
const permissions = user.getPermissions() const permissions = user.getPermissions()
const role = user.getRole() const role = user.getRole()
if (!permission) { if (!permission) {
@ -43,7 +43,7 @@ export const hasPermission = (
| string | string
| Permission | Permission
| ComplexPermission, | ComplexPermission,
compare: 'OR' | 'AND' compare: 'OR' | 'AND',
): boolean => { ): boolean => {
if (permission instanceof Array) { if (permission instanceof Array) {
return compare === 'OR' return compare === 'OR'

View File

@ -17,6 +17,24 @@ export class Permission {
constructor(permission: string) { constructor(permission: string) {
this.permission = permission this.permission = permission
} }
/**
*
* @param workspace_id id
* @returns
*/
getWorkspacePermission(workspace_id: string) {
return `${this.permission}:/WORKSPACE/${workspace_id}`
}
/**
*
* @param workspace_id id
* @param resource
* @param resource_id id
* @returns
*/
getWorkspaceResourcePermission(workspace_id: string, resource: string, resource_id: string) {
return `${this.permission}:/WORKSPACE/${workspace_id}/${resource}/${resource_id}`
}
} }
/** /**
* *

View File

@ -1,3 +1,21 @@
<script setup lang="ts"></script> <script setup lang="ts">
import PermissionConst from '@/utils/permission/data'
</script>
<template>首页</template> <template>
首页
<div v-hasPermission="PermissionConst.USER_READ.getWorkspacePermission('default')">
default工作空间用户只读
</div>
<div v-hasPermission="PermissionConst.USER_READ.getWorkspacePermission('default1')">
default1工作空间用户只读
</div>
<div v-hasPermission="PermissionConst.USER_READ">用户只读</div>
<div
v-hasPermission="
PermissionConst.KNOWLEDGE_READ.getWorkspaceResourcePermission('default', 'KNOWLEDGE', 'xxx')
"
>
default工作空间的知识库xxx权限
</div>
</template>