Skip to content

Commit 70fa36a

Browse files
YunaiVgitee-org
authored andcommitted
!85 【REVIEW】Vue3 管理后台:[系统管理 -> 角色管理] 使用 Element Plus 原生实现
Merge pull request !85 from Chika/dev
2 parents 8810cb9 + 20b3eac commit 70fa36a

File tree

3 files changed

+203
-69
lines changed

3 files changed

+203
-69
lines changed
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
<template>
2+
<Dialog :title="dialogScopeTitle" v-model="dialogScopeVisible" width="800">
3+
<el-form
4+
ref="dataPermissionFormRef"
5+
:model="dataScopeForm"
6+
:inline="true"
7+
label-width="80px"
8+
v-loading="formLoading"
9+
>
10+
<el-form-item label="角色名称">
11+
<el-tag>{{ dataScopeForm.name }}</el-tag>
12+
</el-form-item>
13+
<el-form-item label="角色标识">
14+
<el-tag>{{ dataScopeForm.code }}</el-tag>
15+
</el-form-item>
16+
<!-- 分配角色的数据权限对话框 -->
17+
<el-form-item label="权限范围">
18+
<el-select v-model="dataScopeForm.dataScope">
19+
<el-option
20+
v-for="item in dataScopeDictDatas"
21+
:key="item.value"
22+
:label="item.label"
23+
:value="item.value"
24+
/>
25+
</el-select>
26+
</el-form-item>
27+
</el-form>
28+
<!-- 分配角色的菜单权限对话框 -->
29+
<el-row>
30+
<el-col :span="24">
31+
<el-form-item
32+
label="权限范围"
33+
v-if="
34+
actionScopeType === 'menu' ||
35+
dataScopeForm.dataScope === SystemDataScopeEnum.DEPT_CUSTOM
36+
"
37+
style="display: flex"
38+
>
39+
<el-card class="card" shadow="never">
40+
<template #header>
41+
父子联动(选中父节点,自动选择子节点):
42+
<el-switch
43+
v-model="checkStrictly"
44+
inline-prompt
45+
active-text=""
46+
inactive-text=""
47+
/>
48+
全选/全不选:
49+
<el-switch
50+
v-model="treeNodeAll"
51+
inline-prompt
52+
active-text=""
53+
inactive-text=""
54+
@change="handleCheckedTreeNodeAll()"
55+
/>
56+
</template>
57+
<el-tree
58+
ref="treeRef"
59+
node-key="id"
60+
show-checkbox
61+
:check-strictly="!checkStrictly"
62+
:props="defaultProps"
63+
:data="treeOptions"
64+
empty-text="加载中,请稍后"
65+
/>
66+
</el-card>
67+
</el-form-item> </el-col
68+
></el-row>
69+
70+
<!-- 操作按钮 -->
71+
<template #footer>
72+
<div class="dialog-footer">
73+
<el-button
74+
:title="t('action.save')"
75+
:loading="actionLoading"
76+
@click="submitScope()"
77+
type="primary"
78+
:disabled="formLoading"
79+
>
80+
保存
81+
</el-button>
82+
<el-button
83+
:loading="actionLoading"
84+
:title="t('dialog.close')"
85+
@click="dialogScopeVisible = false"
86+
>取 消</el-button
87+
>
88+
</div>
89+
</template>
90+
</Dialog>
91+
</template>
92+
93+
<script setup lang="ts">
94+
import * as RoleApi from '@/api/system/role'
95+
import type { ElTree } from 'element-plus'
96+
import type { FormExpose } from '@/components/Form'
97+
import { handleTree, defaultProps } from '@/utils/tree'
98+
import { SystemDataScopeEnum } from '@/utils/constants'
99+
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
100+
import * as DeptApi from '@/api/system/dept'
101+
import * as PermissionApi from '@/api/system/permission'
102+
// ========== CRUD 相关 ==========
103+
const actionLoading = ref(false) // 遮罩层
104+
const dataPermissionFormRef = ref<FormExpose>() // 表单 Ref
105+
const { t } = useI18n() // 国际化
106+
const dialogScopeTitle = ref('菜单权限')
107+
const dataScopeDictDatas = ref()
108+
const message = useMessage() // 消息弹窗
109+
const actionScopeType = ref('')
110+
// 选项
111+
const treeNodeAll = ref(false)
112+
const checkStrictly = ref(true)
113+
const dialogScopeVisible = ref(false) // 弹窗的是否展示
114+
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
115+
const treeOptions = ref<any[]>([]) // 菜单树形结构
116+
const treeRef = ref<InstanceType<typeof ElTree>>()
117+
// ========== 数据权限 ==========
118+
const dataScopeForm = reactive({
119+
id: 0,
120+
name: '',
121+
code: '',
122+
dataScope: 0,
123+
checkList: []
124+
})
125+
126+
/** 打开弹窗 */
127+
const openModal = async (type: string, row: RoleApi.RoleVO) => {
128+
dataScopeForm.id = row.id
129+
dataScopeForm.name = row.name
130+
dataScopeForm.code = row.code
131+
actionScopeType.value = type
132+
dialogScopeVisible.value = true
133+
const deptRes = await DeptApi.getSimpleDeptList()
134+
treeOptions.value = handleTree(deptRes)
135+
const role = await RoleApi.getRole(row.id)
136+
dataScopeForm.dataScope = role.dataScope
137+
if (role.dataScopeDeptIds) {
138+
role.dataScopeDeptIds?.forEach((item: any) => {
139+
unref(treeRef)?.setChecked(item, true, false)
140+
})
141+
}
142+
}
143+
144+
// 保存权限
145+
const submitScope = async () => {
146+
const data = ref<PermissionApi.PermissionAssignRoleDataScopeReqVO>({
147+
roleId: dataScopeForm.id,
148+
dataScope: dataScopeForm.dataScope,
149+
dataScopeDeptIds:
150+
dataScopeForm.dataScope !== SystemDataScopeEnum.DEPT_CUSTOM
151+
? []
152+
: (treeRef.value!.getCheckedKeys(false) as unknown as Array<number>)
153+
})
154+
await PermissionApi.assignRoleDataScopeApi(data.value)
155+
156+
message.success(t('common.updateSuccess'))
157+
dialogScopeVisible.value = false
158+
}
159+
160+
// 全选/全不选
161+
const handleCheckedTreeNodeAll = () => {
162+
treeRef.value!.setCheckedNodes(treeNodeAll.value ? treeOptions.value : [])
163+
}
164+
165+
const init = () => {
166+
dataScopeDictDatas.value = getIntDictOptions(DICT_TYPE.SYSTEM_DATA_SCOPE)
167+
}
168+
169+
defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗
170+
// ========== 初始化 ==========
171+
onMounted(() => {
172+
init()
173+
})
174+
</script>

src/views/system/role/MenuPermissionForm.vue

Lines changed: 17 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,10 @@
1313
<el-form-item label="角色标识">
1414
<el-tag>{{ dataScopeForm.code }}</el-tag>
1515
</el-form-item>
16-
<!-- 分配角色的数据权限对话框 -->
17-
<el-form-item label="权限范围" v-if="actionScopeType === 'data'">
18-
<el-select v-model="dataScopeForm.dataScope">
19-
<el-option
20-
v-for="item in dataScopeDictDatas"
21-
:key="item.value"
22-
:label="item.label"
23-
:value="item.value"
24-
/>
25-
</el-select>
26-
</el-form-item>
2716
<!-- 分配角色的菜单权限对话框 -->
2817
<el-row>
2918
<el-col :span="24">
30-
<el-form-item
31-
label="权限范围"
32-
v-if="
33-
actionScopeType === 'menu' ||
34-
dataScopeForm.dataScope === SystemDataScopeEnum.DEPT_CUSTOM
35-
"
36-
style="display: flex"
37-
>
19+
<el-form-item label="权限范围" style="display: flex">
3820
<el-card class="card" shadow="never">
3921
<template #header>
4022
父子联动(选中父节点,自动选择子节点):
@@ -94,10 +76,8 @@ import * as RoleApi from '@/api/system/role'
9476
import type { ElTree } from 'element-plus'
9577
import type { FormExpose } from '@/components/Form'
9678
import { handleTree, defaultProps } from '@/utils/tree'
97-
import { SystemDataScopeEnum } from '@/utils/constants'
9879
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
9980
import * as MenuApi from '@/api/system/menu'
100-
import * as DeptApi from '@/api/system/dept'
10181
import * as PermissionApi from '@/api/system/permission'
10282
// ========== CRUD 相关 ==========
10383
const actionLoading = ref(false) // 遮罩层
@@ -130,50 +110,27 @@ const openModal = async (type: string, row: RoleApi.RoleVO) => {
130110
dataScopeForm.code = row.code
131111
actionScopeType.value = type
132112
dialogScopeVisible.value = true
133-
if (type === 'menu') {
134-
const menuRes = await MenuApi.getSimpleMenusList()
135-
treeOptions.value = handleTree(menuRes)
136-
const role = await PermissionApi.listRoleMenusApi(row.id)
137-
if (role) {
138-
role?.forEach((item: any) => {
139-
unref(treeRef)?.setChecked(item, true, false)
140-
})
141-
}
142-
} else if (type === 'data') {
143-
const deptRes = await DeptApi.getSimpleDeptList()
144-
treeOptions.value = handleTree(deptRes)
145-
const role = await RoleApi.getRole(row.id)
146-
dataScopeForm.dataScope = role.dataScope
147-
if (role.dataScopeDeptIds) {
148-
role.dataScopeDeptIds?.forEach((item: any) => {
149-
unref(treeRef)?.setChecked(item, true, false)
150-
})
151-
}
113+
const menuRes = await MenuApi.getSimpleMenusList()
114+
treeOptions.value = handleTree(menuRes)
115+
const role = await PermissionApi.listRoleMenusApi(row.id)
116+
if (role) {
117+
role?.forEach((item: any) => {
118+
unref(treeRef)?.setChecked(item, true, false)
119+
})
152120
}
153121
}
154122
155123
// 保存权限
156124
const submitScope = async () => {
157-
if ('data' === actionScopeType.value) {
158-
const data = ref<PermissionApi.PermissionAssignRoleDataScopeReqVO>({
159-
roleId: dataScopeForm.id,
160-
dataScope: dataScopeForm.dataScope,
161-
dataScopeDeptIds:
162-
dataScopeForm.dataScope !== SystemDataScopeEnum.DEPT_CUSTOM
163-
? []
164-
: (treeRef.value!.getCheckedKeys(false) as unknown as Array<number>)
165-
})
166-
await PermissionApi.assignRoleDataScopeApi(data.value)
167-
} else if ('menu' === actionScopeType.value) {
168-
const data = ref<PermissionApi.PermissionAssignRoleMenuReqVO>({
169-
roleId: dataScopeForm.id,
170-
menuIds: [
171-
...(treeRef.value!.getCheckedKeys(false) as unknown as Array<number>),
172-
...(treeRef.value!.getHalfCheckedKeys() as unknown as Array<number>)
173-
]
174-
})
175-
await PermissionApi.assignRoleMenuApi(data.value)
176-
}
125+
const data = ref<PermissionApi.PermissionAssignRoleMenuReqVO>({
126+
roleId: dataScopeForm.id,
127+
menuIds: [
128+
...(treeRef.value!.getCheckedKeys(false) as unknown as Array<number>),
129+
...(treeRef.value!.getHalfCheckedKeys() as unknown as Array<number>)
130+
]
131+
})
132+
await PermissionApi.assignRoleMenuApi(data.value)
133+
177134
message.success(t('common.updateSuccess'))
178135
dialogScopeVisible.value = false
179136
}
@@ -193,10 +150,3 @@ onMounted(() => {
193150
init()
194151
})
195152
</script>
196-
<style scoped>
197-
.card {
198-
width: 100%;
199-
max-height: 400px;
200-
overflow-y: scroll;
201-
}
202-
</style>

src/views/system/role/index.vue

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,14 @@
146146
<RoleForm ref="formRef" @success="getList" />
147147
<!-- 表单弹窗:菜单权限 -->
148148
<MenuPermissionForm ref="menuPermissionFormRef" @success="getList" />
149+
<!-- 表单弹窗:数据权限 -->
150+
<DataPermissionForm ref="dataPermissionFormRef" @success="getList" />
149151
</template>
150152
<script setup lang="tsx">
151153
import * as RoleApi from '@/api/system/role'
152154
import RoleForm from './RoleForm.vue'
153155
import MenuPermissionForm from './MenuPermissionForm.vue'
156+
import DataPermissionForm from './DataPermissionForm.vue'
154157
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
155158
import { dateFormatter } from '@/utils/formatTime'
156159
import download from '@/utils/download'
@@ -201,10 +204,17 @@ const openForm = (type: string, id?: number) => {
201204
formRef.value.open(type, id)
202205
}
203206
204-
/** 数据权限操作 */
207+
/** 菜单权限操作 */
205208
const menuPermissionFormRef = ref()
209+
/** 数据权限操作 */
210+
const dataPermissionFormRef = ref()
211+
206212
const handleScope = async (type: string, row: RoleApi.RoleVO) => {
207-
menuPermissionFormRef.value.openModal(type, row)
213+
if (type === 'menu') {
214+
menuPermissionFormRef.value.openModal(type, row)
215+
} else if (type === 'data') {
216+
dataPermissionFormRef.value.openModal(type, row)
217+
}
208218
}
209219
210220
/** 删除按钮操作 */

0 commit comments

Comments
 (0)