Skip to content

Commit ecde723

Browse files
committed
REVIEW 角色管理(设置菜单权限)
1 parent 70fa36a commit ecde723

File tree

5 files changed

+176
-164
lines changed

5 files changed

+176
-164
lines changed

src/api/system/permission/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export interface PermissionAssignRoleDataScopeReqVO {
1717
}
1818

1919
// 查询角色拥有的菜单权限
20-
export const listRoleMenusApi = async (roleId: number) => {
20+
export const getRoleMenuList = async (roleId: number) => {
2121
return await request.get({ url: '/system/permission/list-role-resources?roleId=' + roleId })
2222
}
2323

src/views/system/role/MenuPermissionForm.vue

Lines changed: 0 additions & 152 deletions
This file was deleted.
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
<template>
2+
<Dialog title="菜单权限" v-model="modelVisible">
3+
<el-form
4+
ref="formRef"
5+
:model="formData"
6+
:inline="true"
7+
label-width="80px"
8+
v-loading="formLoading"
9+
>
10+
<el-form-item label="角色名称">
11+
<el-tag>{{ formData.name }}</el-tag>
12+
</el-form-item>
13+
<el-form-item label="角色标识">
14+
<el-tag>{{ formData.code }}</el-tag>
15+
</el-form-item>
16+
<el-form-item label="菜单权限">
17+
<el-card class="cardHeight">
18+
<template #header>
19+
全选/全不选:
20+
<el-switch
21+
v-model="treeNodeAll"
22+
inline-prompt
23+
active-text=""
24+
inactive-text=""
25+
@change="handleCheckedTreeNodeAll"
26+
/>
27+
全部展开/折叠:
28+
<el-switch
29+
v-model="menuExpand"
30+
inline-prompt
31+
active-text="展开"
32+
inactive-text="折叠"
33+
@change="handleCheckedTreeExpand"
34+
/>
35+
</template>
36+
<el-tree
37+
ref="treeRef"
38+
node-key="id"
39+
show-checkbox
40+
:props="defaultProps"
41+
:data="menuOptions"
42+
empty-text="加载中,请稍候"
43+
/>
44+
</el-card>
45+
</el-form-item>
46+
</el-form>
47+
<template #footer>
48+
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
49+
<el-button @click="modelVisible = false">取 消</el-button>
50+
</template>
51+
</Dialog>
52+
</template>
53+
<script setup lang="ts">
54+
import { handleTree, defaultProps } from '@/utils/tree'
55+
import * as RoleApi from '@/api/system/role'
56+
import type { ElTree } from 'element-plus'
57+
import * as MenuApi from '@/api/system/menu'
58+
import * as PermissionApi from '@/api/system/permission'
59+
const { t } = useI18n() // 国际化
60+
const message = useMessage() // 消息弹窗
61+
62+
const modelVisible = ref(false) // 弹窗的是否展示
63+
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
64+
const formData = reactive({
65+
id: 0,
66+
name: '',
67+
code: '',
68+
menuIds: []
69+
})
70+
const formRef = ref() // 表单 Ref
71+
const menuOptions = ref<any[]>([]) // 菜单树形结构
72+
const menuExpand = ref(false) // 展开/折叠
73+
const treeRef = ref<InstanceType<typeof ElTree>>() // 树组件 Ref
74+
const treeNodeAll = ref(false) // 全选/全不选
75+
76+
/** 打开弹窗 */
77+
const open = async (row: RoleApi.RoleVO) => {
78+
modelVisible.value = true
79+
resetForm()
80+
// 加载 Menu 列表。注意,必须放在前面,不然下面 setChecked 没数据节点
81+
menuOptions.value = handleTree(await MenuApi.getSimpleMenusList())
82+
// 设置数据
83+
formData.id = row.id
84+
formData.name = row.name
85+
formData.code = row.code
86+
formLoading.value = true
87+
try {
88+
formData.value.menuIds = await PermissionApi.getRoleMenuList(row.id)
89+
// 设置选中
90+
formData.value.menuIds.forEach((menuId: number) => {
91+
treeRef.value.setChecked(menuId, true, false)
92+
})
93+
} finally {
94+
formLoading.value = false
95+
}
96+
}
97+
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
98+
99+
/** 提交表单 */
100+
const submitForm = async () => {
101+
// 校验表单
102+
if (!formRef) return
103+
const valid = await formRef.value.validate()
104+
if (!valid) return
105+
// 提交请求
106+
formLoading.value = true
107+
try {
108+
const data = {
109+
roleId: formData.id,
110+
menuIds: [
111+
...(treeRef.value.getCheckedKeys(false) as unknown as Array<number>), // 获得当前选中节点
112+
...(treeRef.value.getHalfCheckedKeys() as unknown as Array<number>) // 获得半选中的父节点
113+
]
114+
}
115+
await PermissionApi.assignRoleMenuApi(data)
116+
message.success(t('common.updateSuccess'))
117+
modelVisible.value = false
118+
} finally {
119+
formLoading.value = false
120+
}
121+
}
122+
123+
/** 重置表单 */
124+
const resetForm = () => {
125+
// 重置选项
126+
treeNodeAll.value = false
127+
menuExpand.value = false
128+
// 重置表单
129+
formData.value = {
130+
id: 0,
131+
name: '',
132+
code: '',
133+
menuIds: []
134+
}
135+
treeRef.value?.setCheckedNodes([])
136+
formRef.value?.resetFields()
137+
}
138+
139+
/** 全选/全不选 */
140+
const handleCheckedTreeNodeAll = () => {
141+
treeRef.value.setCheckedNodes(treeNodeAll.value ? menuOptions.value : [])
142+
}
143+
144+
/** 展开/折叠全部 */
145+
const handleCheckedTreeExpand = () => {
146+
const nodes = treeRef.value?.store.nodesMap
147+
for (let node in nodes) {
148+
if (nodes[node].expanded === menuExpand.value) {
149+
continue
150+
}
151+
nodes[node].expanded = menuExpand.value
152+
}
153+
}
154+
</script>
155+
<style lang="scss" scoped>
156+
.cardHeight {
157+
width: 100%;
158+
max-height: 400px;
159+
overflow-y: scroll;
160+
}
161+
</style>

src/views/system/role/index.vue

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@
108108
preIcon="ep:basketball"
109109
title="菜单权限"
110110
v-hasPermi="['system:permission:assign-role-menu']"
111-
@click="handleScope('menu', scope.row)"
111+
@click="openAssignMenuForm(scope.row)"
112112
>
113113
菜单权限
114114
</el-button>
@@ -145,18 +145,18 @@
145145
<!-- 表单弹窗:添加/修改 -->
146146
<RoleForm ref="formRef" @success="getList" />
147147
<!-- 表单弹窗:菜单权限 -->
148-
<MenuPermissionForm ref="menuPermissionFormRef" @success="getList" />
148+
<RoleAssignMenuForm ref="assignMenuFormRef" @success="getList" />
149149
<!-- 表单弹窗:数据权限 -->
150150
<DataPermissionForm ref="dataPermissionFormRef" @success="getList" />
151151
</template>
152152
<script setup lang="tsx">
153-
import * as RoleApi from '@/api/system/role'
154-
import RoleForm from './RoleForm.vue'
155-
import MenuPermissionForm from './MenuPermissionForm.vue'
156-
import DataPermissionForm from './DataPermissionForm.vue'
157153
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
158154
import { dateFormatter } from '@/utils/formatTime'
159155
import download from '@/utils/download'
156+
import * as RoleApi from '@/api/system/role'
157+
import RoleForm from './RoleForm.vue'
158+
import RoleAssignMenuForm from './RoleAssignMenuForm.vue'
159+
import DataPermissionForm from './DataPermissionForm.vue'
160160
const message = useMessage() // 消息弹窗
161161
const { t } = useI18n() // 国际化
162162
@@ -204,19 +204,23 @@ const openForm = (type: string, id?: number) => {
204204
formRef.value.open(type, id)
205205
}
206206
207-
/** 菜单权限操作 */
208-
const menuPermissionFormRef = ref()
209207
/** 数据权限操作 */
210208
const dataPermissionFormRef = ref()
211209
212210
const handleScope = async (type: string, row: RoleApi.RoleVO) => {
213211
if (type === 'menu') {
214-
menuPermissionFormRef.value.openModal(type, row)
212+
assignMenuFormRef.value.openModal(type, row)
215213
} else if (type === 'data') {
216214
dataPermissionFormRef.value.openModal(type, row)
217215
}
218216
}
219217
218+
/** 菜单权限操作 */
219+
const assignMenuFormRef = ref()
220+
const openAssignMenuForm = async (row: RoleApi.RoleVO) => {
221+
assignMenuFormRef.value.open(row)
222+
}
223+
220224
/** 删除按钮操作 */
221225
const handleDelete = async (id: number) => {
222226
try {

src/views/system/tenantPackage/TenantPackageForm.vue

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,10 @@
6464
<script setup lang="ts" name="TenantPackageForm">
6565
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
6666
import { CommonStatusEnum } from '@/utils/constants'
67-
import { defaultProps } from '@/utils/tree'
67+
import { defaultProps, handleTree } from '@/utils/tree'
6868
import * as TenantPackageApi from '@/api/system/tenantPackage'
6969
import * as MenuApi from '@/api/system/menu'
7070
import { ElTree } from 'element-plus'
71-
import { handleTree } from '@/utils/tree'
7271
const { t } = useI18n() // 国际化
7372
const message = useMessage() // 消息弹窗
7473

0 commit comments

Comments
 (0)