REVIEW 角色管理(设置菜单权限)

This commit is contained in:
YunaiV 2023-04-01 17:45:31 +08:00
parent 70fa36a262
commit ecde723fa2
5 changed files with 176 additions and 164 deletions

View File

@ -17,7 +17,7 @@ export interface PermissionAssignRoleDataScopeReqVO {
} }
// 查询角色拥有的菜单权限 // 查询角色拥有的菜单权限
export const listRoleMenusApi = async (roleId: number) => { export const getRoleMenuList = async (roleId: number) => {
return await request.get({ url: '/system/permission/list-role-resources?roleId=' + roleId }) return await request.get({ url: '/system/permission/list-role-resources?roleId=' + roleId })
} }

View File

@ -1,152 +0,0 @@
<template>
<Dialog :title="dialogScopeTitle" v-model="dialogScopeVisible" width="800">
<el-form
ref="menuPermissionFormRef"
:model="dataScopeForm"
:inline="true"
label-width="80px"
v-loading="formLoading"
>
<el-form-item label="角色名称">
<el-tag>{{ dataScopeForm.name }}</el-tag>
</el-form-item>
<el-form-item label="角色标识">
<el-tag>{{ dataScopeForm.code }}</el-tag>
</el-form-item>
<!-- 分配角色的菜单权限对话框 -->
<el-row>
<el-col :span="24">
<el-form-item label="权限范围" style="display: flex">
<el-card class="card" shadow="never">
<template #header>
父子联动(选中父节点自动选择子节点):
<el-switch
v-model="checkStrictly"
inline-prompt
active-text="是"
inactive-text="否"
/>
全选/全不选:
<el-switch
v-model="treeNodeAll"
inline-prompt
active-text="是"
inactive-text="否"
@change="handleCheckedTreeNodeAll()"
/>
</template>
<el-tree
ref="treeRef"
node-key="id"
show-checkbox
:check-strictly="!checkStrictly"
:props="defaultProps"
:data="treeOptions"
empty-text="加载中,请稍后"
/>
</el-card>
</el-form-item> </el-col
></el-row>
</el-form>
<!-- 操作按钮 -->
<template #footer>
<div class="dialog-footer">
<el-button
:title="t('action.save')"
:loading="actionLoading"
@click="submitScope()"
type="primary"
:disabled="formLoading"
>
保存
</el-button>
<el-button
:loading="actionLoading"
:title="t('dialog.close')"
@click="dialogScopeVisible = false"
> </el-button
>
</div>
</template>
</Dialog>
</template>
<script setup lang="ts">
import * as RoleApi from '@/api/system/role'
import type { ElTree } from 'element-plus'
import type { FormExpose } from '@/components/Form'
import { handleTree, defaultProps } from '@/utils/tree'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import * as MenuApi from '@/api/system/menu'
import * as PermissionApi from '@/api/system/permission'
// ========== CRUD ==========
const actionLoading = ref(false) //
const menuPermissionFormRef = ref<FormExpose>() // Ref
const { t } = useI18n() //
const dialogScopeTitle = ref('菜单权限')
const dataScopeDictDatas = ref()
const message = useMessage() //
const actionScopeType = ref('')
//
const checkStrictly = ref(true)
const treeNodeAll = ref(false)
const dialogScopeVisible = ref(false) //
const formLoading = ref(false) // 12
const treeOptions = ref<any[]>([]) //
const treeRef = ref<InstanceType<typeof ElTree>>()
// ========== ==========
const dataScopeForm = reactive({
id: 0,
name: '',
code: '',
dataScope: 0,
checkList: []
})
/** 打开弹窗 */
const openModal = async (type: string, row: RoleApi.RoleVO) => {
dataScopeForm.id = row.id
dataScopeForm.name = row.name
dataScopeForm.code = row.code
actionScopeType.value = type
dialogScopeVisible.value = true
const menuRes = await MenuApi.getSimpleMenusList()
treeOptions.value = handleTree(menuRes)
const role = await PermissionApi.listRoleMenusApi(row.id)
if (role) {
role?.forEach((item: any) => {
unref(treeRef)?.setChecked(item, true, false)
})
}
}
//
const submitScope = async () => {
const data = ref<PermissionApi.PermissionAssignRoleMenuReqVO>({
roleId: dataScopeForm.id,
menuIds: [
...(treeRef.value!.getCheckedKeys(false) as unknown as Array<number>),
...(treeRef.value!.getHalfCheckedKeys() as unknown as Array<number>)
]
})
await PermissionApi.assignRoleMenuApi(data.value)
message.success(t('common.updateSuccess'))
dialogScopeVisible.value = false
}
// /
const handleCheckedTreeNodeAll = () => {
treeRef.value!.setCheckedNodes(treeNodeAll.value ? treeOptions.value : [])
}
const init = () => {
dataScopeDictDatas.value = getIntDictOptions(DICT_TYPE.SYSTEM_DATA_SCOPE)
}
defineExpose({ openModal }) // openModal
// ========== ==========
onMounted(() => {
init()
})
</script>

View File

@ -0,0 +1,161 @@
<template>
<Dialog title="菜单权限" v-model="modelVisible">
<el-form
ref="formRef"
:model="formData"
:inline="true"
label-width="80px"
v-loading="formLoading"
>
<el-form-item label="角色名称">
<el-tag>{{ formData.name }}</el-tag>
</el-form-item>
<el-form-item label="角色标识">
<el-tag>{{ formData.code }}</el-tag>
</el-form-item>
<el-form-item label="菜单权限">
<el-card class="cardHeight">
<template #header>
全选/全不选:
<el-switch
v-model="treeNodeAll"
inline-prompt
active-text="是"
inactive-text="否"
@change="handleCheckedTreeNodeAll"
/>
全部展开/折叠:
<el-switch
v-model="menuExpand"
inline-prompt
active-text="展开"
inactive-text="折叠"
@change="handleCheckedTreeExpand"
/>
</template>
<el-tree
ref="treeRef"
node-key="id"
show-checkbox
:props="defaultProps"
:data="menuOptions"
empty-text="加载中,请稍候"
/>
</el-card>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="modelVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { handleTree, defaultProps } from '@/utils/tree'
import * as RoleApi from '@/api/system/role'
import type { ElTree } from 'element-plus'
import * as MenuApi from '@/api/system/menu'
import * as PermissionApi from '@/api/system/permission'
const { t } = useI18n() //
const message = useMessage() //
const modelVisible = ref(false) //
const formLoading = ref(false) // 12
const formData = reactive({
id: 0,
name: '',
code: '',
menuIds: []
})
const formRef = ref() // Ref
const menuOptions = ref<any[]>([]) //
const menuExpand = ref(false) // /
const treeRef = ref<InstanceType<typeof ElTree>>() // Ref
const treeNodeAll = ref(false) // /
/** 打开弹窗 */
const open = async (row: RoleApi.RoleVO) => {
modelVisible.value = true
resetForm()
// Menu setChecked
menuOptions.value = handleTree(await MenuApi.getSimpleMenusList())
//
formData.id = row.id
formData.name = row.name
formData.code = row.code
formLoading.value = true
try {
formData.value.menuIds = await PermissionApi.getRoleMenuList(row.id)
//
formData.value.menuIds.forEach((menuId: number) => {
treeRef.value.setChecked(menuId, true, false)
})
} finally {
formLoading.value = false
}
}
defineExpose({ open }) // open
/** 提交表单 */
const submitForm = async () => {
//
if (!formRef) return
const valid = await formRef.value.validate()
if (!valid) return
//
formLoading.value = true
try {
const data = {
roleId: formData.id,
menuIds: [
...(treeRef.value.getCheckedKeys(false) as unknown as Array<number>), //
...(treeRef.value.getHalfCheckedKeys() as unknown as Array<number>) //
]
}
await PermissionApi.assignRoleMenuApi(data)
message.success(t('common.updateSuccess'))
modelVisible.value = false
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
//
treeNodeAll.value = false
menuExpand.value = false
//
formData.value = {
id: 0,
name: '',
code: '',
menuIds: []
}
treeRef.value?.setCheckedNodes([])
formRef.value?.resetFields()
}
/** 全选/全不选 */
const handleCheckedTreeNodeAll = () => {
treeRef.value.setCheckedNodes(treeNodeAll.value ? menuOptions.value : [])
}
/** 展开/折叠全部 */
const handleCheckedTreeExpand = () => {
const nodes = treeRef.value?.store.nodesMap
for (let node in nodes) {
if (nodes[node].expanded === menuExpand.value) {
continue
}
nodes[node].expanded = menuExpand.value
}
}
</script>
<style lang="scss" scoped>
.cardHeight {
width: 100%;
max-height: 400px;
overflow-y: scroll;
}
</style>

View File

@ -108,7 +108,7 @@
preIcon="ep:basketball" preIcon="ep:basketball"
title="菜单权限" title="菜单权限"
v-hasPermi="['system:permission:assign-role-menu']" v-hasPermi="['system:permission:assign-role-menu']"
@click="handleScope('menu', scope.row)" @click="openAssignMenuForm(scope.row)"
> >
菜单权限 菜单权限
</el-button> </el-button>
@ -145,18 +145,18 @@
<!-- 表单弹窗添加/修改 --> <!-- 表单弹窗添加/修改 -->
<RoleForm ref="formRef" @success="getList" /> <RoleForm ref="formRef" @success="getList" />
<!-- 表单弹窗菜单权限 --> <!-- 表单弹窗菜单权限 -->
<MenuPermissionForm ref="menuPermissionFormRef" @success="getList" /> <RoleAssignMenuForm ref="assignMenuFormRef" @success="getList" />
<!-- 表单弹窗数据权限 --> <!-- 表单弹窗数据权限 -->
<DataPermissionForm ref="dataPermissionFormRef" @success="getList" /> <DataPermissionForm ref="dataPermissionFormRef" @success="getList" />
</template> </template>
<script setup lang="tsx"> <script setup lang="tsx">
import * as RoleApi from '@/api/system/role'
import RoleForm from './RoleForm.vue'
import MenuPermissionForm from './MenuPermissionForm.vue'
import DataPermissionForm from './DataPermissionForm.vue'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime' import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download' import download from '@/utils/download'
import * as RoleApi from '@/api/system/role'
import RoleForm from './RoleForm.vue'
import RoleAssignMenuForm from './RoleAssignMenuForm.vue'
import DataPermissionForm from './DataPermissionForm.vue'
const message = useMessage() // const message = useMessage() //
const { t } = useI18n() // const { t } = useI18n() //
@ -204,19 +204,23 @@ const openForm = (type: string, id?: number) => {
formRef.value.open(type, id) formRef.value.open(type, id)
} }
/** 菜单权限操作 */
const menuPermissionFormRef = ref()
/** 数据权限操作 */ /** 数据权限操作 */
const dataPermissionFormRef = ref() const dataPermissionFormRef = ref()
const handleScope = async (type: string, row: RoleApi.RoleVO) => { const handleScope = async (type: string, row: RoleApi.RoleVO) => {
if (type === 'menu') { if (type === 'menu') {
menuPermissionFormRef.value.openModal(type, row) assignMenuFormRef.value.openModal(type, row)
} else if (type === 'data') { } else if (type === 'data') {
dataPermissionFormRef.value.openModal(type, row) dataPermissionFormRef.value.openModal(type, row)
} }
} }
/** 菜单权限操作 */
const assignMenuFormRef = ref()
const openAssignMenuForm = async (row: RoleApi.RoleVO) => {
assignMenuFormRef.value.open(row)
}
/** 删除按钮操作 */ /** 删除按钮操作 */
const handleDelete = async (id: number) => { const handleDelete = async (id: number) => {
try { try {

View File

@ -64,11 +64,10 @@
<script setup lang="ts" name="TenantPackageForm"> <script setup lang="ts" name="TenantPackageForm">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { CommonStatusEnum } from '@/utils/constants' import { CommonStatusEnum } from '@/utils/constants'
import { defaultProps } from '@/utils/tree' import { defaultProps, handleTree } from '@/utils/tree'
import * as TenantPackageApi from '@/api/system/tenantPackage' import * as TenantPackageApi from '@/api/system/tenantPackage'
import * as MenuApi from '@/api/system/menu' import * as MenuApi from '@/api/system/menu'
import { ElTree } from 'element-plus' import { ElTree } from 'element-plus'
import { handleTree } from '@/utils/tree'
const { t } = useI18n() // const { t } = useI18n() //
const message = useMessage() // const message = useMessage() //