feat(frontend): 完善角色管理功能
- 添加 PermissionButton.vue 权限按钮组件 - 添加 PermissionDialog.vue 权限对话框组件 - 添加 role.ts 角色管理服务 - 添加 RoleManagementView.vue 角色管理页面 - 更新路由配置添加角色管理页面 - 更新 App.vue 添加角色管理菜单入口 - 修复 TypeScript 类型定义问题 - 前端编译验证通过
This commit is contained in:
89
frontend/admin/src/components/PermissionButton.vue
Normal file
89
frontend/admin/src/components/PermissionButton.vue
Normal file
@@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<component
|
||||
:is="tag"
|
||||
v-bind="bindProps"
|
||||
:class="buttonClass"
|
||||
:disabled="disabled || !hasPermission"
|
||||
@click="handleClick"
|
||||
>
|
||||
<slot />
|
||||
</component>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { usePermission } from '../composables/usePermission'
|
||||
import type { Permission } from '../auth/roles'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
/** 所需权限 */
|
||||
permission: Permission
|
||||
/** 标签类型 */
|
||||
tag?: string
|
||||
/** 按钮类型 */
|
||||
type?: 'button' | 'submit' | 'reset'
|
||||
/** 禁用状态 */
|
||||
disabled?: boolean
|
||||
/** 是否显示为按钮 */
|
||||
asButton?: boolean
|
||||
/** 按钮变体 */
|
||||
variant?: 'primary' | 'secondary' | 'danger'
|
||||
/** 权限不足时隐藏 */
|
||||
hideWhenNoPermission?: boolean
|
||||
}>(), {
|
||||
tag: 'button',
|
||||
type: 'button',
|
||||
disabled: false,
|
||||
asButton: true,
|
||||
variant: 'primary',
|
||||
hideWhenNoPermission: false
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
click: [event: MouseEvent]
|
||||
}>()
|
||||
|
||||
const { hasPermission } = usePermission()
|
||||
|
||||
const buttonClass = computed(() => {
|
||||
if (!props.asButton || !hasPermission(props.permission)) {
|
||||
return ''
|
||||
}
|
||||
|
||||
const baseClass = 'mos-btn'
|
||||
const variantClass = props.variant === 'primary' ? 'mos-btn-accent' :
|
||||
props.variant === 'danger' ? 'mos-btn-danger' : 'mos-btn-secondary'
|
||||
|
||||
return `${baseClass} ${variantClass}`
|
||||
})
|
||||
|
||||
const bindProps = computed(() => {
|
||||
const result: Record<string, unknown> = {}
|
||||
|
||||
if (props.tag === 'button') {
|
||||
result.type = props.type
|
||||
}
|
||||
|
||||
if (!props.asButton) {
|
||||
return result
|
||||
}
|
||||
|
||||
if (!hasPermission(props.permission)) {
|
||||
if (props.hideWhenNoPermission) {
|
||||
return { style: 'display: none' }
|
||||
}
|
||||
result.style = 'opacity: 0.5; pointer-events: none'
|
||||
}
|
||||
|
||||
return result
|
||||
})
|
||||
|
||||
const handleClick = (event: MouseEvent) => {
|
||||
if (!hasPermission(props.permission)) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
return
|
||||
}
|
||||
emit('click', event)
|
||||
}
|
||||
</script>
|
||||
68
frontend/admin/src/components/PermissionDialog.vue
Normal file
68
frontend/admin/src/components/PermissionDialog.vue
Normal file
@@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="visible"
|
||||
:title="title"
|
||||
:width="width"
|
||||
:close-on-click-modal="false"
|
||||
@close="handleClose"
|
||||
>
|
||||
<slot />
|
||||
<template #footer>
|
||||
<div class="flex justify-end gap-2">
|
||||
<button class="mos-btn mos-btn-secondary" @click="handleClose">
|
||||
取消
|
||||
</button>
|
||||
<button
|
||||
class="mos-btn mos-btn-accent"
|
||||
:disabled="!hasAllPermissions(requiredPermissions)"
|
||||
@click="handleConfirm"
|
||||
>
|
||||
{{ confirmText }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { usePermission } from '../composables/usePermission'
|
||||
import type { Permission } from '../auth/roles'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
/** 弹窗标题 */
|
||||
title: string
|
||||
/** 确认按钮文字 */
|
||||
confirmText?: string
|
||||
/** 弹窗宽度 */
|
||||
width?: string | number
|
||||
/** 是否显示 */
|
||||
modelValue: boolean
|
||||
/** 所需权限列表 */
|
||||
requiredPermissions: Permission[]
|
||||
}>(), {
|
||||
confirmText: '确定',
|
||||
width: '500px'
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:modelValue': [value: boolean]
|
||||
confirm: []
|
||||
}>()
|
||||
|
||||
const { hasAllPermissions } = usePermission()
|
||||
|
||||
const visible = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (value) => emit('update:modelValue', value)
|
||||
})
|
||||
|
||||
const handleClose = () => {
|
||||
visible.value = false
|
||||
}
|
||||
|
||||
const handleConfirm = () => {
|
||||
emit('confirm')
|
||||
handleClose()
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user