update: 角色管理-权限分配组件

This commit is contained in:
easy 2023-02-06 18:11:54 +08:00
parent 3d22650763
commit a7772d55b5
4 changed files with 344 additions and 32 deletions

View File

@ -6,10 +6,14 @@ export const getRoleList_api = (data: any): Promise<any> => server.post(`/role/_
export const delRole_api = (id: string): Promise<any> => server.remove(`/role/${id}`);
// 保存角色
export const saveRole_api = (data: any): Promise<any> => server.post(`/role`, data);
// 更新角色信息
export const updateRole_api = (data: any): Promise<any> => server.patch(`/role`, data);
// 获取角色详细信息
export const getRoleDetails_api = (id: string): Promise<any> => server.get(`/role/${id}`);
// 获取角色对应的权限树
export const getPrimissTree_api = (id: string): Promise<any> => server.get(`/menu/role/${id}/_grant/tree`);
// 更新角色对应的权限树
export const updatePrimissTree_api = (id: string, data:object): Promise<any> => server.put(`/menu/role/${id}/_grant`,data);
// 获取用户列表

View File

@ -26,7 +26,7 @@
<a-card>
<h5>权限分配</h5>
<PermissTree />
<PermissTree v-model:select-items="form.menus" />
<a-button
type="primary"
@ -39,12 +39,17 @@
</template>
<script setup lang="ts" name="RolePermiss">
import { FormInstance } from 'ant-design-vue';
import { FormInstance, message } from 'ant-design-vue';
import PermissTree from '../components/PermissTree.vue';
import { getRoleDetails_api } from '@/api/system/role';
import {
getRoleDetails_api,
updateRole_api,
updatePrimissTree_api,
} from '@/api/system/role';
const route = useRoute();
const router = useRouter();
const roleId = route.params.id as string;
//
@ -55,6 +60,7 @@ const form = reactive({
name: '',
description: '',
},
menus: [],
getForm: () => {
getRoleDetails_api(roleId).then((resp) => {
if (resp.status) {
@ -62,7 +68,15 @@ const form = reactive({
}
});
},
clickSave: () => {},
clickSave: () => {
const updateRole = updateRole_api(form.data);
const updateTree = updatePrimissTree_api(roleId, { menu: form.menus });
Promise.all([updateRole, updateTree]).then((resp) => {
message.success('操作成功');
router.push('/system/Role');
});
},
});
form.getForm();

View File

@ -1,64 +1,343 @@
<template>
<div class="permiss-tree-container">
<a-table :data-source="dataSource">
<a-table-column key="menu" data-index="menu">
<template #title><span style="">菜单权限</span></template>
</a-table-column>
<a-table-column key="action" title="操作权限" data-index="action" />
<a-table-column key="data" data-index="data">
<template #title>
<a-table
:columns="columns"
:data-source="tableData"
:pagination="false"
:rowKey="'id'"
>
<!-- 自定义表头 -->
<template #headerCell="{ column }">
<div v-if="column.key === 'menu'">
<a-checkbox
v-model:checked="selectedAll"
:indeterminate="indeterminate"
@change="selectAllChange"
>菜单权限</a-checkbox
>
</div>
<div v-else-if="column.key === 'data'">
<span style="">数据权限</span>
<a-checkbox v-model:checked="checked">批量设置</a-checkbox>
<a-checkbox
v-model:checked="bulkShow"
@change="bulkValue = ''"
>批量设置</a-checkbox
>
<a-select
v-show="checked"
v-model:value="selectValue"
v-show="bulkShow"
v-model:value="bulkValue"
:size="'middle'"
style="width: 200px"
:options="options"
:options="bulkOptions"
@change="bulkChange"
></a-select>
</template>
</a-table-column>
</div>
<div v-else>
<span>{{ column.title }}</span>
</div>
</template>
<!-- 自定义表格内容 -->
<template #bodyCell="{ column, record }">
<div v-if="column.key === 'menu'">
<a-checkbox
v-model:checked="record.granted"
:indeterminate="record.indeterminate"
@change="menuChange(record)"
>{{ record.name }}</a-checkbox
>
</div>
<div v-else-if="column.key === 'action'">
<div v-if="record.buttons && record.buttons.length > 0">
<a-checkbox
v-for="button in record.buttons"
v-model:checked="button.granted"
@change="actionChange(record)"
>{{ button.name }}</a-checkbox
>
</div>
</div>
<div v-else-if="column.key === 'data'">
<span v-if="record.accessSupport === undefined">
不支持数据权限配置默认可查看全部数据
</span>
<div v-else-if="record.accessSupport.value === 'support'">
<a-radio-group v-model:value="record.selectAccesses">
<a-radio
:value="asset.supportId"
v-for="asset in record.assetAccesses"
>{{ asset.name }}</a-radio
>
</a-radio-group>
</div>
<span
v-else-if="
record.accessSupport.value === 'indirect' ||
record.accessSupport.value === 'unsupported'
"
>{{ record.accessDescription }}</span
>
</div>
</template>
</a-table>
</div>
</template>
<script setup lang="ts">
import { cloneDeep } from 'lodash-es';
import { getPrimissTree_api } from '@/api/system/role';
const emits = defineEmits(['update:selectItems']);
const route = useRoute();
const props = defineProps({
selectItems: Array,
});
const dataSource = ref([]);
const checked = ref<boolean>(false);
const options = [
const columns = [
{
title: '菜单权限',
dataIndex: 'menu',
key: 'menu',
width: '260px',
},
{
title: '操作权限',
dataIndex: 'action',
key: 'action',
width: '260px',
},
{
title: '数据权限',
dataIndex: 'data',
key: 'data',
width: '50%',
},
];
const tableData = ref<tableItemType[]>([]);
// -
const selectedAll = ref<boolean>(false);
const indeterminate = ref<boolean>(false);
const selectAllChange = () => {
flatTableData.forEach((item) => {
item.granted = selectedAll.value;
item.buttons?.forEach((button) => {
button.granted = selectedAll.value;
});
});
indeterminate.value = false;
};
// -
const bulkShow = ref<boolean>(false);
const bulkOptions = [
{
label: '全部数据',
value: '1',
value: 'ignore',
},
{
label: '所在组织及下级组织',
value: '2',
value: 'org-include-children',
},
{
label: '所在组织',
value: '3',
value: 'org',
},
{
label: '自己创建的',
value: '4',
value: 'creator',
},
];
const selectValue = ref<string>('');
const getAllPermiss = () => {
const id = route.params.id as string;
getPrimissTree_api(id).then((resp) => {
console.log(resp);
const bulkValue = ref<string>('');
const bulkChange = () => {
if (!bulkValue) return;
flatTableData.forEach((item) => {
if (item.accessSupport && item.accessSupport.value === 'support') {
item.selectAccesses = bulkValue.value;
}
});
};
// ------------------------------
const flatTableData: tableItemType[] = []; // -- 便
getAllPermiss();
const init = () => {
getAllPermiss();
watch(tableData, () => {
const selected = cloneDeep(flatTableData).filter((item) => (item.granted || item.indeterminate) && !item.parentId);
selected.forEach((item) => {
if (
item.accessSupport &&
item.accessSupport.value === 'support' &&
item.selectAccesses
) {
item.selectAccesses = bulkValue.value;
item.assetAccesses?.forEach((asset) => {
if (asset.supportId === item.selectAccesses) {
asset.granted = true;
} else {
asset.granted = false;
}
});
delete item.selectAccesses;
}
delete item.indeterminate
});
emits(
'update:selectItems',
selected,
);
});
};
init();
function getAllPermiss() {
const id = route.params.id as string;
getPrimissTree_api(id).then((resp) => {
tableData.value = resp.result;
treeToSimple(resp.result); //
const selectList = flatTableData.filter((item) => item.granted); //
emits('update:selectItems', selectList); //
// /
if (selectList.length === flatTableData.length) {
selectedAll.value = true;
indeterminate.value = false;
} else if (selectList.length > 0) {
indeterminate.value = true;
selectedAll.value = false;
}
});
}
/**
* 菜单权限改变事件
* @param row 触发的项
* @param setButtonBool 是否改变对应的操作权限
*/
function menuChange(
row: tableItemType,
setButtonBool: boolean = true,
): undefined {
if (setButtonBool) {
if (row.buttons && row.buttons.length > 0)
row.buttons.forEach((button) => {
button.granted = row.granted;
});
row.children && setChildrenChecked(row.children, row.granted);
}
//
const selectList = flatTableData.filter((item) => item.granted); //
if (row.parentId) {
// //
const parent = flatTableData.find(
(item) => item.id === row.parentId,
) as tableItemType;
const selectLen = parent.children?.filter((item) => item.granted)
.length as number; //
if (selectLen === parent.children?.length) {
parent.granted = true;
parent.indeterminate = false;
} else if (selectLen > 0) {
parent.granted = false;
parent.indeterminate = true;
} else {
parent.granted = false;
parent.indeterminate = false;
}
if (parent.parentId) {
return menuChange(parent, false);
}
}
//
if (selectList.length === flatTableData.length) {
selectedAll.value = true;
indeterminate.value = false;
} else if (selectList.length > 0) {
indeterminate.value = true;
selectedAll.value = false;
} else {
selectedAll.value = false;
indeterminate.value = false;
}
emits('update:selectItems', selectList); //
}
/**
* 操作权限改变事件
* @param row 触发的项
*/
function actionChange(row: tableItemType) {
const selectLen = row.buttons?.filter((item) => item.granted)
.length as number;
if (selectLen === row.buttons?.length) {
row.granted = true;
row.indeterminate = false;
} else if (selectLen > 0) {
row.granted = false;
row.indeterminate = true;
} else {
row.granted = false;
row.indeterminate = false;
}
menuChange(row, false);
}
/**
* 将树形结构的表格数据拍扁为一个普通数组
* @param treeData
*/
function treeToSimple(treeData: tableItemType[]) {
treeData.forEach((item) => {
if (item.accessSupport && item.accessSupport.value === 'support') {
const select =
item.assetAccesses?.find((assetItem) => assetItem.granted) ||
{};
item.selectAccesses = select.supportId || '';
}
flatTableData.push(item);
item.children && treeToSimple(item.children);
});
}
/**
* 设置子节点的状态
* @param childrens
* @param value
*/
function setChildrenChecked(childrens: tableItemType[], value: boolean) {
if (childrens.length < 1) return;
childrens.forEach((item) => {
item.granted = value;
if (item.buttons && item.buttons.length > 0)
item.buttons.forEach((button) => {
button.granted = value;
});
item.children && setChildrenChecked(item.children, value);
});
}
type buttonItemType = {
supportId: string;
name: string;
granted: boolean;
};
type tableItemType = {
id: string;
granted: boolean;
name: string;
indeterminate?: boolean;
parentId?: string;
children?: tableItemType[];
accessSupport?: any;
buttons?: buttonItemType[];
accessDescription?: string;
selectAccesses?: string;
assetAccesses?: any[];
};
</script>
<style lang="less" scoped>

View File

@ -15,4 +15,19 @@ const route = useRoute();
const activeKey = ref('1');
</script>
<style lang="less" scoped></style>
<style lang="less" scoped>
.details-container {
:deep(.ant-tabs-nav-wrap) {
background-color: #fff;
padding: 24px 0 0 24px;
}
.role-permiss-container {
padding: 24px;
}
}
</style>