Skip to content

Commit 72c2214

Browse files
committed
feat: 角色权限设置
1 parent 59a42d1 commit 72c2214

File tree

5 files changed

+325
-8
lines changed

5 files changed

+325
-8
lines changed

src/api/tableExample.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,44 @@ export const getRoleColumns = () => {
4343
/** 创建角色 */
4444
export const createRole = (data?: object) => {
4545
// return http.request<Result>("get", apiUrl("rbac/menus/"));
46-
return http.request<postResult>("post", `api/roles/`, {
46+
return http.request<postResult>("post", "/api/roles/", {
4747
data
4848
});
4949
};
5050

5151
/** 修改角色 */
5252
export const updateRole = (id: number, data?: object) => {
5353
// return http.request<Result>("get", apiUrl("rbac/menus/"));
54-
return http.request<postResult>("patch", `api/roles/${id}/`, {
54+
return http.request<postResult>("patch", `/api/roles/${id}/`, {
5555
data
5656
});
5757
};
5858

5959
export const deleteRole = (id: number) => {
6060
return http.request<postResult>("delete", `api/roles/${id}/`, {});
6161
}
62+
63+
/** 菜单树状数据 */
64+
export const treeMenu = () => {
65+
// return http.request<Result>("get", apiUrl("rbac/menus/"));
66+
return http.request<postArrayResult>("get", "/api/menus/tree/", {});
67+
};
68+
69+
export const getRolePermission = (id: number) => {
70+
return http.request<postResult>(
71+
"get",
72+
`/api/roles/${id}/get-permissions/`,
73+
{}
74+
);
75+
};
76+
77+
export const setRolePermission = (id: number, data?: Array<number>) => {
78+
// return http.request<Result>("get", apiUrl("rbac/menus/"));
79+
return http.request<postResult>(
80+
"post",
81+
`/api/roles/${id}/set-permissions/`,
82+
{
83+
data
84+
}
85+
);
86+
};

src/views/system/role/index.vue

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ const {
2121
dataList,
2222
tablePagination,
2323
onSearch,
24-
openDialog
24+
openDialog,
25+
setPermissionDialog
2526
} = useTable();
2627
2728
const deleteData = (rowId: number) => {
@@ -83,6 +84,16 @@ const deleteData = (rowId: number) => {
8384
>
8485
修改
8586
</el-button>
87+
<el-button
88+
class="reset-margin"
89+
link
90+
type="primary"
91+
:size="size"
92+
:icon="useRenderIcon(EditPen)"
93+
@click="setPermissionDialog(row)"
94+
>
95+
权限
96+
</el-button>
8697
<el-popconfirm
8798
:title="`是否确认删除编号为${row.code}的这条数据`"
8899
@confirm="deleteData(row.id)"

src/views/system/role/permForm.vue

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
<script setup lang="ts">
2+
import { ref } from "vue";
3+
import { transformI18n } from "@/plugins/i18n";
4+
import ElTreeLine from "@/components/ReTreeLine";
5+
import { getRolePermission, treeMenu } from "@/api/tableExample";
6+
import { message } from "@/utils/message";
7+
import { PermDialogProps } from "./utils/types";
8+
9+
const loading = ref(true);
10+
11+
const props = withDefaults(defineProps<PermDialogProps>(), {
12+
formInline: () => ({
13+
id: null,
14+
permissions: []
15+
})
16+
});
17+
const newFormInline = ref(props.formInline);
18+
19+
// 获取菜单树状数据
20+
const menuTree = ref([]);
21+
function getMenuTree() {
22+
treeMenu()
23+
.then(res => {
24+
menuTree.value = res.data;
25+
})
26+
.catch(error => {
27+
message(`${error.data.ret}: ${error.data.msg}\n菜单数据获取失败`, {
28+
type: "error"
29+
});
30+
});
31+
loading.value = false;
32+
}
33+
34+
// 获取角色拥有的菜单权限
35+
getRolePermission(newFormInline.value.id)
36+
.then(res => {
37+
newFormInline.value.permissions = res.data.permissions;
38+
getMenuTree();
39+
})
40+
.catch(error => {
41+
message(`${error.data.ret}: ${error.data.msg}\n角色权限获取失败`, {
42+
type: "error"
43+
});
44+
});
45+
46+
const ruleFormRef = ref();
47+
function getRef() {
48+
return ruleFormRef.value;
49+
}
50+
defineExpose({ getRef });
51+
52+
const dataProps = {
53+
value: "id",
54+
children: "children",
55+
disabled: "disabled"
56+
};
57+
58+
const treeRef = ref();
59+
const swCheckAll = ref(false);
60+
const swExpandTree = ref(true);
61+
// const swLinkage = ref(false);
62+
63+
function removePermission(permId) {
64+
const delIndex = newFormInline.value.permissions.indexOf(permId);
65+
if (delIndex >= 0) {
66+
newFormInline.value.permissions.splice(delIndex, 1);
67+
}
68+
}
69+
70+
function setPermission(permId) {
71+
if (!newFormInline.value.permissions.includes(permId)) {
72+
newFormInline.value.permissions.push(permId);
73+
}
74+
}
75+
76+
/*菜单权限树节点选中变化时*/
77+
function menuCheckChange(obj, isChecked) {
78+
const permId = obj.id;
79+
80+
// 菜单上下级之间联动时半选中的父节点视为选择
81+
// const halfCheckedMenuIds = treeRef.value.getHalfCheckedKeys();
82+
// if (!isChecked && halfCheckedMenuIds.includes(permId)) {
83+
// isChecked = true;
84+
// }
85+
if (isChecked) {
86+
setPermission(permId);
87+
if (obj.parentId) {
88+
const parentNode = treeRef.value.store.nodesMap[obj.parentId];
89+
if (!parentNode.checked) {
90+
parentNode.checked = true;
91+
}
92+
}
93+
} else {
94+
removePermission(permId);
95+
// 按钮
96+
obj.buttons.forEach(button => {
97+
removePermission(button.id);
98+
});
99+
obj.children.forEach(child => {
100+
const childNode = treeRef.value.store.nodesMap[child.id];
101+
if (childNode.checked) {
102+
childNode.checked = false;
103+
}
104+
});
105+
}
106+
}
107+
108+
/*菜单权限树展开/折叠*/
109+
function expandTree(isExpand) {
110+
const nodes = treeRef.value.store.nodesMap;
111+
for (const node in nodes) {
112+
nodes[node].expanded = isExpand;
113+
}
114+
}
115+
116+
/*菜单权限树全选/不选*/
117+
function checkAllTree(isCheckedAll) {
118+
const nodes = treeRef.value.store.nodesMap;
119+
for (const node in nodes) {
120+
if (!nodes[node].data.disabled) {
121+
if (nodes[node].checked != isCheckedAll) {
122+
nodes[node].checked = isCheckedAll;
123+
}
124+
const nodeButtons = nodes[node].data.buttons;
125+
for (const index in nodeButtons) {
126+
if (isCheckedAll && !nodeButtons[index].disabled) {
127+
setPermission(nodeButtons[index].id);
128+
} else {
129+
removePermission(nodeButtons[index].id);
130+
}
131+
}
132+
}
133+
}
134+
}
135+
136+
function buttonCheckChange(isChecked, nodeData: any) {
137+
// 按钮勾选时自动勾选按钮所属菜单
138+
const menuId = nodeData.id;
139+
const node = treeRef.value.store.nodesMap[menuId];
140+
if (isChecked && !node.checked) {
141+
node.checked = true;
142+
// setPermission(menuId);
143+
}
144+
}
145+
</script>
146+
147+
<template>
148+
<el-form
149+
ref="ruleFormRef"
150+
:model="newFormInline"
151+
label-width="82px"
152+
v-loading="loading"
153+
>
154+
<el-col class="mb-[20px]">
155+
<el-row>
156+
<el-col :span="6">
157+
<el-switch
158+
v-model="swCheckAll"
159+
active-text="全选/不选"
160+
@change="checkAllTree"
161+
/>
162+
</el-col>
163+
<el-col :span="6">
164+
<el-switch
165+
v-model="swExpandTree"
166+
active-text="展开/折叠"
167+
@change="expandTree"
168+
/>
169+
</el-col>
170+
<!-- <el-col :span="6">-->
171+
<!-- <el-switch v-model="swLinkage" active-text="父子联动" />-->
172+
<!-- </el-col>-->
173+
</el-row>
174+
<el-card shadow="never">
175+
<div class="max-h-[550px] overflow-y-auto">
176+
<el-tree
177+
ref="treeRef"
178+
:data="menuTree"
179+
:props="dataProps"
180+
show-checkbox
181+
check-strictly
182+
node-key="id"
183+
:render-after-expand="false"
184+
:indent="30"
185+
:default-checked-keys="newFormInline.permissions"
186+
default-expand-all
187+
@check-change="menuCheckChange"
188+
>
189+
<template v-slot:default="{ node, data }">
190+
<el-tree-line :node="node" :showLabelLine="true">
191+
<template v-slot:node-label>
192+
<span class="text-sm">
193+
{{ transformI18n(node.label) }}
194+
</span>
195+
<div class="demo-button-style" style="margin-left: 20px">
196+
<el-checkbox-group
197+
v-model="newFormInline.permissions"
198+
size="small"
199+
>
200+
<el-checkbox-button
201+
v-for="button in data.buttons"
202+
:value="button.id"
203+
:key="button.id"
204+
:disabled="button.disabled"
205+
@change="checked => buttonCheckChange(checked, data)"
206+
>{{ transformI18n(button.meta.title) }}
207+
</el-checkbox-button>
208+
</el-checkbox-group>
209+
</div>
210+
</template>
211+
</el-tree-line>
212+
</template>
213+
</el-tree>
214+
</div>
215+
</el-card>
216+
</el-col>
217+
</el-form>
218+
</template>

src/views/system/role/utils/hook.tsx

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import { h, ref } from "vue";
2-
import { createRole, getRoleList, updateRole } from "@/api/tableExample";
2+
import { createRole, getRoleList, updateRole, setRolePermission } from "@/api/tableExample";
33
// import { useUserStoreHook } from "@/store/modules/user";
44
import { onStatusChange, usePublicHooks } from "@/utils/common";
55
import { useTableBase } from "@/utils/tableHook";
66
import { addDialog } from "@/components/ReDialog/index";
77
import { deviceDetection } from "@pureadmin/utils";
88
import { message } from "@/utils/message";
9-
import type { FormItemProps } from "./types";
9+
10+
import type { FormItemProps, PermDialogItemProps } from "./types";
1011
import editForm from "../form.vue";
12+
import permForm from "../permForm.vue";
1113

1214
export function useTable() {
1315
const switchLoadMap = ref({});
@@ -47,7 +49,8 @@ export function useTable() {
4749
{
4850
label: "操作",
4951
fixed: "right",
50-
slot: "operation"
52+
slot: "operation",
53+
minWidth: 120
5154
}
5255
];
5356

@@ -104,6 +107,49 @@ export function useTable() {
104107
});
105108
}
106109

110+
async function setPermissionDialog(row: FormItemProps) {
111+
// const menuTree = await getMenuTree();
112+
// const rolePermis: any = await getRolePerms(row.id);
113+
addDialog({
114+
title: "权限设置",
115+
props: {
116+
formInline: {
117+
id: row?.id ?? null,
118+
permissions: []
119+
}
120+
},
121+
hideFooter: row.is_super_role,
122+
width: "40%",
123+
draggable: true,
124+
fullscreenIcon: true,
125+
closeOnClickModal: false,
126+
sureBtnLoading: true,
127+
contentRenderer: () => h(permForm, { ref: formRef, formInline: null }),
128+
beforeSure: (done, { options, index, closeLoading }) => {
129+
const FormRef = formRef.value.getRef();
130+
const curData = options.props.formInline as PermDialogItemProps;
131+
function chores() {
132+
message("权限设置成功", {
133+
type: "success"
134+
});
135+
done(); // 关闭弹框
136+
onSearch(); // 刷新表格数据
137+
}
138+
FormRef.validate((isValid: boolean) => {
139+
if (isValid) {
140+
setRolePermission(row.id, curData.permissions).then(res => {
141+
if (res.ret == 200 || res.ret == 201) {
142+
chores();
143+
}
144+
}).catch(() => {
145+
closeLoading();
146+
});
147+
}
148+
});
149+
}
150+
});
151+
}
152+
107153
const {
108154
tableLoading,
109155
tableColumns,
@@ -121,6 +167,7 @@ export function useTable() {
121167
dataList,
122168
tablePagination,
123169
onSearch,
124-
openDialog
170+
openDialog,
171+
setPermissionDialog
125172
};
126173
}

0 commit comments

Comments
 (0)