Files
geg-gas-web/src/views/system/role/components/RoleAuthModal.vue

602 lines
21 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>
<BasicModal
wrapClassName="autherizeDialog"
v-bind="$attrs"
@register="registerRoleAuthModal"
:title="t('功能授权')"
destroy-on-close
@ok="handleSubmit"
:width=modalLength()
>
<template #title>
<div>功能授权<span style="color:red">注意修改角色权限后需要手动点击登出角色用户按钮或用户重新登录后才会生效</span></div>
</template>
<a-row :gutter="[16, 16]" class="h-full">
<a-col :span=spanLength() v-if="typeKey==4||typeKey==0">
<div class="text-base border-l-6 border-[#5e95ff] pl-3 h-5 leading-5 mb-3 ml-2">{{
t('系统功能')
}}</div>
<div class="treebox">
<BasicTree
:treeData="treeData"
checkable
ref="treeRef"
@check="handleTreeSelect"
:fieldNames="{ title: 'title', key: 'id' }"
>
<template #title="{ title, systemName, parentId }">
<div v-if="parentId == 0">{{ title }} {{ systemName }}</div>
<div v-else>{{ title }}</div>
</template>
</BasicTree>
</div>
</a-col>
<a-col :span=spanLength() v-if="typeKey==4||typeKey==1">
<div class="text-base border-l-6 border-[#5e95ff] pl-3 h-5 leading-5 mb-3 ml-2">{{
t('按钮权限')
}}</div>
<div class="treebox">
<BasicTree
:treeData="buttonSelectData"
checkable
ref="ButtonRef"
@check="handleButtonSelect"
:fieldNames="{ title: 'title', key: 'id' }"
/>
</div>
</a-col>
<a-col :span=spanLength() v-if="typeKey==4||typeKey==2">
<div class="text-base border-l-6 border-[#5e95ff] pl-3 h-5 leading-5 mb-3 ml-2">{{
t('字段权限')
}}</div>
<div class="treebox">
<BasicTree
:treeData="columnSelectData"
checkable
ref="ColumnRef"
@check="handleColumnSelect"
:fieldNames="{ title: 'title', key: 'id' }"
/>
</div>
</a-col>
<a-col :span=spanLength() v-if="typeKey==4||typeKey==3">
<div class="text-base border-l-6 border-[#5e95ff] pl-3 h-5 leading-5 mb-3 ml-2">{{
t('表单权限')
}}</div>
<div class="treebox">
<BasicTree
:treeData="fieldSelectData"
checkable
ref="FieldRef"
@check="handleFieldSelect"
:fieldNames="{ title: 'title', key: 'id' }"
/>
</div>
</a-col>
</a-row>
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, ref, unref, nextTick } from 'vue';
import { getMenuSimpleTree } from '/@/api/system/menu';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { TreeItem, BasicTree, TreeActionType } from '/@/components/Tree';
import { getRoleAuth, RoleSetAuth } from '/@/api/system/role';
import { useMessage } from '/@/hooks/web/useMessage';
import { getMenuButtonList, getMenuColumnList, getMenuFieldList } from '/@/api/system/menuButton';
import { cloneDeep } from 'lodash-es';
import { useI18n } from '/@/hooks/web/useI18n';
export default defineComponent({
name: 'SelectUserModal',
components: { BasicModal, BasicTree },
emits: ['success', 'register'],
setup(_, { emit }) {
const { notification } = useMessage();
const { t } = useI18n();
const treeRef = ref<Nullable<TreeActionType>>(null);
const ButtonRef = ref<Nullable<TreeActionType>>(null);
const ColumnRef = ref<Nullable<TreeActionType>>(null);
const FieldRef = ref<Nullable<TreeActionType>>(null);
const treeData = ref<TreeItem[]>([]);
const buttonData = ref<TreeItem[]>([]);
const columnData = ref<TreeItem[]>([]);
const fieldData = ref<TreeItem[]>([]);
const buttonSelectData = ref<TreeItem[]>([]);
const columnSelectData = ref<TreeItem[]>([]);
const fieldSelectData = ref<TreeItem[]>([]);
const btnKeys = ref<string[]>([]);
const colKeys = ref<string[]>([]);
const menuKeys = ref<string[]>([]);
const fieldKeys = ref<string[]>([]);
const btnFilterKeys = ref<string[]>([]);
const colFilterKeys = ref<string[]>([]);
const fieldFilterKeys = ref<string[]>([]);
const rowId = ref('');
const typeKey = ref(4);
function getTree(tree) {
if (!tree) {
return null;
}
return tree;
}
function spanLength() {
if (typeKey.value == 4) {
return "6";
} else {
return "24";
}
}
function modalLength() {
if (typeKey.value == 4) {
return "90%";
} else {
return "40%";
}
}
const [registerRoleAuthModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
setModalProps({ confirmLoading: false });
rowId.value = data.id;
typeKey.value = data.key;
treeData.value = await getMenuSimpleTree();
buttonData.value = await getMenuButtonList();
columnData.value = await getMenuColumnList();
fieldData.value = await getMenuFieldList();
const authList = await getRoleAuth(rowId.value);
menuKeys.value = authList.menuIds || [];
btnKeys.value = authList.buttonIds || [];
colKeys.value = authList.columnIds || [];
fieldKeys.value = authList.formIds || [];
let menuCheckedKey = [];
let btnCheckedKey = [];
let colCheckedKey = [];
let fieldCheckedKey = [];
if (typeKey.value == 4) {
menuKeys.value.forEach((o) => {
getParentKeys(menuCheckedKey, treeData.value, o);
});
menuKeys.value = menuCheckedKey;
getTree(unref(treeRef)).setCheckedKeys(authList.menuIds);
initTree(menuCheckedKey);
let lostBtnKey = [];
btnKeys.value.forEach((o) => {
// getParentKeys(btnCheckedKey, buttonSelectData.value, o, lostBtnKey);
getParentKeysAndLost(btnCheckedKey, buttonSelectData.value, o, lostBtnKey);
});
if (lostBtnKey) {
let menuIds = [];
buttonData.value.forEach((but) => {
if (lostBtnKey.includes(but.id)) {
menuIds.push(but.menuId);
}
});
menuIds.forEach((key) => {
getParentKeys(btnCheckedKey, treeData.value, key);
});
findMenuTree(buttonSelectData.value, treeData.value, btnCheckedKey, 'button');
}
btnKeys.value = Array.from(new Set([...btnKeys.value, ...btnCheckedKey]));
let lostColKey = [];
colKeys.value.forEach((o) => {
// getParentKeys(colCheckedKey, columnSelectData.value, o);
getParentKeysAndLost(colCheckedKey, columnSelectData.value, o, lostColKey);
});
if (lostColKey) {
let menuIds = [];
columnData.value.forEach((but) => {
if (lostColKey.includes(but.id)) {
menuIds.push(but.menuId);
}
});
menuIds.forEach((key) => {
getParentKeys(colCheckedKey, treeData.value, key);
});
findMenuTree(columnSelectData.value, treeData.value, colCheckedKey, 'column');
}
colKeys.value = Array.from(new Set([...colKeys.value, ...colCheckedKey]));
let lostFieldKey = [];
fieldKeys.value.forEach((o) => {
// getParentKeys(fieldCheckedKey, fieldSelectData.value, o);
getParentKeysAndLost(fieldCheckedKey, fieldSelectData.value, o, lostFieldKey);
});
if (lostFieldKey) {
let menuIds = [];
columnData.value.forEach((but) => {
if (lostFieldKey.includes(but.id)) {
menuIds.push(but.menuId);
}
});
menuIds.forEach((key) => {
getParentKeys(fieldCheckedKey, treeData.value, key);
});
findMenuTree(fieldSelectData.value, treeData.value, fieldCheckedKey, 'field');
}
fieldKeys.value = Array.from(new Set([...fieldKeys.value, ...fieldCheckedKey]));
nextTick(() => {
getTree(unref(ButtonRef))?.setCheckedKeys(authList.buttonIds);
getTree(unref(ColumnRef))?.setCheckedKeys(authList.columnIds);
getTree(unref(FieldRef))?.setCheckedKeys(authList.formIds);
getTree(unref(ButtonRef)).expandAll(true);
getTree(unref(ColumnRef)).expandAll(true);
getTree(unref(FieldRef)).expandAll(true);
});
getTree(unref(treeRef)).expandAll(true);
} else {
if (typeKey.value == 0) {
menuKeys.value.forEach((o) => {
getParentKeys(menuCheckedKey, treeData.value, o);
});
menuKeys.value = menuCheckedKey;
getTree(unref(treeRef)).setCheckedKeys(authList.menuIds);
getTree(unref(treeRef)).expandAll(true);
}
const fullMenuKey = [];
getFullMenu(fullMenuKey, treeData.value);
initTree(fullMenuKey);
if (typeKey.value == 1) {
btnKeys.value.forEach((o) => {
getParentKeys(btnCheckedKey, buttonData.value, o);
});
btnKeys.value = btnCheckedKey;
getTree(unref(ButtonRef))?.setCheckedKeys(authList.buttonIds);
getTree(unref(ButtonRef)).expandAll(true);
}
else if (typeKey.value == 2) {
colKeys.value.forEach((o) => {
getParentKeys(colCheckedKey, columnData.value, o);
});
colKeys.value = colCheckedKey;
nextTick(() => {
getTree(unref(ColumnRef))?.setCheckedKeys(authList.columnIds);
getTree(unref(ColumnRef)).expandAll(true);
});
}
else if (typeKey.value == 3) {
fieldKeys.value.forEach((o) => {
getParentKeys(fieldCheckedKey, fieldData.value, o);
});
fieldKeys.value = fieldCheckedKey;
nextTick(() => {
getTree(unref(FieldRef))?.setCheckedKeys(authList.formIds);
getTree(unref(FieldRef)).expandAll(true);
});
}
}
});
async function handleSubmit() {
try {
setModalProps({ confirmLoading: true });
//由于树组件的原因,提交之前先过滤一遍,没有选中的不提交
// btnKeys.value = getTree(unref(ButtonRef)).getCheckedKeys();
// colKeys.value = getTree(unref(ColumnRef)).getCheckedKeys();
// fieldKeys.value = getTree(unref(FieldRef)).getCheckedKeys();
// 过滤无效的权限 ID
btnKeys.value = btnKeys.value.filter((o) => btnFilterKeys.value.includes(o));
colKeys.value = colKeys.value.filter((o) => colFilterKeys.value.includes(o));
fieldKeys.value = fieldKeys.value.filter((o) => fieldFilterKeys.value.includes(o));
// btnKeys.value = btnKeys.value.filter((o) => {
// return btnFilterKeys.value.includes(o);
// });
// colKeys.value = colKeys.value.filter((o) => {
// return colFilterKeys.value.includes(o);
// });
// fieldKeys.value = fieldKeys.value.filter((o) => {
// return fieldFilterKeys.value.includes(o);
// });
// 提交更新后的权限数据
await RoleSetAuth({
id: rowId.value,
type: typeKey.value == 4?NaN:typeKey.value,
menuIds: menuKeys.value,
buttonIds: btnKeys.value,
columnIds: colKeys.value,
formIds: fieldKeys.value,
});
notification.success({
message: t('提示'),
description: t('功能授权更新成功'),
}); //提示消息
closeModal();
emit('success');
} catch (error) {
setModalProps({ confirmLoading: false });
}
}
function handleButtonSelect(keys, e) {
btnKeys.value = [...e.halfCheckedKeys, ...keys];
}
function handleColumnSelect(keys, e) {
colKeys.value = [...e.halfCheckedKeys, ...keys];
}
function handleFieldSelect(keys, e) {
fieldKeys.value = [...e.halfCheckedKeys, ...keys];
}
function handleTreeSelect(keys, e) {
//keys 所有全选中的key
//e.halfCheckedKeys 所有半选中的
//如果没有半选 就证明全部全选 直接使用keys
//如果有半选需要 使用keys + e.halfCheckedKeys
const menuSelect: string[] = [...e.halfCheckedKeys, ...keys];
//选择菜单的时候。对应后面的button column field 只进行增量添加
incrementTree(menuSelect);
menuKeys.value = menuSelect;
}
function initTree(menuSelect) {
buttonSelectData.value = [];
columnSelectData.value = [];
fieldSelectData.value = [];
btnFilterKeys.value = [];
colFilterKeys.value = [];
fieldFilterKeys.value = [];
findMenuTree(buttonSelectData.value, treeData.value, menuSelect, 'button');
findMenuTree(columnSelectData.value, treeData.value, menuSelect, 'column');
findMenuTree(fieldSelectData.value, treeData.value, menuSelect, 'field');
getTree(unref(ButtonRef))?.setExpandedKeys(menuSelect);
getTree(unref(ColumnRef))?.setExpandedKeys(menuSelect);
getTree(unref(FieldRef))?.setExpandedKeys(menuSelect);
}
function incrementTree(addMenuSelect) {
btnFilterKeys.value = [];
colFilterKeys.value = [];
fieldFilterKeys.value = [];
// 使用 Set 合并已选中和新增选中的菜单,避免重复
const allMenuKeys = new Set([...menuKeys.value, ...addMenuSelect]);
// 确保未选中菜单的子节点不会丢失
findMenuTree(buttonSelectData.value, treeData.value, Array.from(allMenuKeys), 'button');
findMenuTree(columnSelectData.value, treeData.value, Array.from(allMenuKeys), 'column');
findMenuTree(fieldSelectData.value, treeData.value, Array.from(allMenuKeys), 'field');
// 更新按钮、字段、表单的选中状态
btnKeys.value = Array.from(new Set([...btnKeys.value, ...addMenuSelect]));
colKeys.value = Array.from(new Set([...colKeys.value, ...addMenuSelect]));
fieldKeys.value = Array.from(new Set([...fieldKeys.value, ...addMenuSelect]));
// 扩展树的展开状态
getTree(unref(ButtonRef))?.setExpandedKeys(Array.from(allMenuKeys));
getTree(unref(ColumnRef))?.setExpandedKeys(Array.from(allMenuKeys));
getTree(unref(FieldRef))?.setExpandedKeys(Array.from(allMenuKeys));
}
function getParentKeys(checkedKey, arr, keys) {
for (let i = 0; i < arr.length; i++) {
let o = arr[i];
if (o.id == keys) {
checkedKey.push(o.id);
if (o.parentId > 0 && !checkedKey.includes(o.parentId)) {
checkedKey.push(o.parentId);
}
}
if (o.children?.length > 0) {
getParentKeys(checkedKey, o.children, keys);
}
}
}
// keys获取对应的菜单 返回给chackedKey如果该keys 不在原先过滤后的数组arr中的话把keys 记录lostKey抛出给外面二次处理减少全数据过滤的内存处理
function getParentKeysAndLost(checkedKey, arr, keys, lostKey) {
for (let i = 0; i < arr.length; i++) {
let o = arr[i];
if (o.id == keys) {
checkedKey.push(o.id);
if (o.parentId > 0 && !checkedKey.includes(o.parentId)) {
checkedKey.push(o.parentId);
}
}
if (o.children?.length > 0) {
getParentKeys(checkedKey, o.children, keys);
}
}
if (!checkedKey.includes(keys)) {
lostKey.push(keys);
}
}
function findMenuTree(menuSelectTree, treeData, keys, type) {
for (let i = 0; i < treeData.length; i++) {
let o = cloneDeep(treeData[i]);
if (keys.includes(o.id)) {
let hadData = false;
let index = 0;
for (let j = 0; j < menuSelectTree.length; j++) {
if (menuSelectTree[j].id == o.id) {
hadData = true;
index = j;
break;
}
}
if (!hadData) {
o.children = [];
menuSelectTree.push(o);
} else {
o = menuSelectTree[index];
}
if (treeData[i].children?.length > 0) {
findMenuTree(o.children, treeData[i].children, keys, type);
} else {
let list =
type == 'button'
? buttonData.value
: type == 'column'
? columnData.value
: fieldData.value;
o.children = getAuthData(list, o.id, type);
}
}
}
}
function getFullMenu(menuKeys, treeData) {
for (let i = 0; i < treeData.length; i++) {
let o = cloneDeep(treeData[i]);
menuKeys.push(o.id);
if (treeData[i].children?.length > 0) {
getFullMenu(menuKeys, treeData[i].children)
}
}
}
function getAuthData(list, id, type) {
let arr: TreeItem[] = [];
arr = list.filter((o) => {
return o.menuId == id;
});
arr.forEach((o) => {
o.parentId = o.menuId;
if (type == 'button') {
btnFilterKeys.value.push(o.id);
} else if (type == 'column') {
colFilterKeys.value.push(o.id);
} else {
if (o.children && o.children.length > 0) {
o.children?.forEach((k) => {
fieldFilterKeys.value.push(k.id);
});
}
fieldFilterKeys.value.push(o.id);
}
});
return arr;
}
// function findMenuTree(menuTree, menuSelectTree, keys) {
// let selected: any = {};
// menuTree.forEach((key) => {
// //找到node对象
// if (keys.includes(key.id)) {
// console.log(key, 'kkkkkkkkkk');
// selected = cloneDeep(key);
// if (key.children?.length > 0) {
// selected.children = [];
// findMenuTree(key.children, selected.children, keys);
// }
// }
// });
// // let obj = menuSelectTree.find((o) => {
// // return o.id == selected.id;
// // });
// // if (!obj) {
// // menuSelectTree.push(selected);
// // } else {
// // obj.children = obj.children.concat(selected.children);
// // }
// checkChild(menuSelectTree, selected);
// }
// function checkChild(menuTree, selected) {
// menuTree.forEach((o) => {
// if (o.id == selected.parentId) {
// o.children = o.children.concat(selected.children);
// checkChild(o.children, selected);
// } else {
// menuTree.push(selected);
// }
// });
// }
//将按钮塞入到菜单树
// function menuInsertButton(menuTree, buttonList) {
// menuTree.forEach((menu) => {
// const thisMenuButton = buttonList.filter((btn) => btn.menuId === menu.id);
// if (menu.children && menu.children.length > 0) {
// menuInsertButton(menu.children, buttonList);
// }
// // console.log('thisMenuButton', thisMenuButton);
// menu.children = menu.children?.concat(thisMenuButton);
// });
// }
return {
registerRoleAuthModal,
handleSubmit,
handleTreeSelect,
handleButtonSelect,
handleColumnSelect,
handleFieldSelect,
menuKeys,
treeData,
treeRef,
ButtonRef,
FieldRef,
ColumnRef,
buttonSelectData,
columnSelectData,
fieldSelectData,
t,
typeKey,
spanLength,
modalLength,
};
},
});
</script>
<style lang="less">
.autherizeDialog {
.ant-modal {
top: 20px;
height: calc(100% - 40px) !important;
.ant-modal-content {
height: 100%;
.ant-modal-body {
height: calc(100% - 120px) !important;
.scrollbar__view {
height: 100%;
& > div {
height: 100%;
max-height: none !important;
.ant-col {
height: 100%;
.treebox {
height: calc(100% - 42px);
overflow: auto;
padding-right: 15px;
margin-bottom: 10px;
border-right: solid 1px #ccc;
.vben-tree {
height: auto;
}
}
}
}
}
}
}
}
}
</style>