Files
yunxinwei-vue/src/views/system/role/components/role-auth.vue
2023-08-04 13:32:43 +08:00

160 lines
3.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- 角色权限分配弹窗 -->
<template>
<ele-modal
:width="460"
title="分配权限"
:visible="visible"
:confirm-loading="loading"
@update:visible="updateVisible"
@ok="save"
>
<a-spin :spinning="authLoading">
<div style="height: 60vh" class="ele-scrollbar-hover">
<a-tree
:checkable="true"
:show-icon="true"
:tree-data="(authData as any)"
v-model:expandedKeys="expandKeys"
v-model:checkedKeys="checkedKeys"
>
<template #icon="{ menuIcon }">
<component v-if="menuIcon" :is="menuIcon" />
</template>
</a-tree>
</div>
</a-spin>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, watch, nextTick } from 'vue';
import { message } from 'ant-design-vue/es';
import { toTreeData, eachTreeData } from 'ele-admin-pro/es';
import { listRoleMenus, updateRoleMenus } from '@/api/system/role';
import type { Role } from '@/api/system/role/model';
import type { Menu } from '@/api/system/menu/model';
const emit = defineEmits<{
(e: 'update:visible', visible: boolean): void;
}>();
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 当前角色数据
data?: Role | null;
}>();
// 权限数据
const authData = ref<Menu[]>([]);
// 权限数据请求状态
const authLoading = ref(false);
// 提交状态
const loading = ref(false);
// 角色权限展开的keys
const expandKeys = ref<number[]>([]);
// 角色权限选中的keys
const checkedKeys = ref<number[]>([]);
/* 查询权限数据 */
const query = () => {
authData.value = [];
expandKeys.value = [];
checkedKeys.value = [];
if (!props.data) {
return;
}
authLoading.value = true;
listRoleMenus(props.data.roleId)
.then((data) => {
authLoading.value = false;
// 转成树形结构的数据
authData.value = toTreeData({
data: data?.map((d) => ({
...d,
key: d.menuId,
icon: undefined,
menuIcon: d.icon
})),
idField: 'menuId',
parentIdField: 'parentId',
addParentIds: true,
parentIds: []
});
// 全部默认展开以及回显选中的数据
nextTick(() => {
const eks: number[] = [];
const cks: number[] = [];
eachTreeData(authData.value, (d) => {
if (d.key) {
if (d.children?.length) {
eks.push(d.key);
} else if (d.checked) {
cks.push(d.key);
}
}
});
expandKeys.value = eks;
checkedKeys.value = cks;
});
})
.catch((e) => {
authLoading.value = false;
message.error(e.message);
});
};
/* 保存权限分配 */
const save = () => {
loading.value = true;
// 获取选中的id包含所有半选的父级的id
const ids = new Set<number>();
eachTreeData(authData.value, (d) => {
if (d.key && checkedKeys.value.some((c) => c === d.key)) {
ids.add(d.key);
if (d.parentIds) {
d.parentIds.forEach((id: number) => {
ids.add(id);
});
}
}
});
updateRoleMenus(props.data?.roleId, Array.from(ids))
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
};
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
watch(
() => props.visible,
(visible) => {
if (visible) {
query();
}
}
);
</script>
<script lang="ts">
import * as MenuIcons from '@/layout/menu-icons';
export default {
components: MenuIcons
};
</script>