|
@@ -1,35 +1,48 @@
|
|
|
<template>
|
|
|
<div class="system-edit-role-container">
|
|
|
- <el-dialog title="权限配置" v-model="state.isShowDialog" draggable @opened="opened">
|
|
|
- <div class="custom-tree-node-container">
|
|
|
- <el-table :data="state.menuTableData" stripe row-key="permissionCode" border :expand-row-keys="state.expandRowKeys">
|
|
|
- <el-table-column width="180" label="菜单">
|
|
|
- <template #default="scope">
|
|
|
- <el-checkbox
|
|
|
- v-if="scope.row.children"
|
|
|
- :indeterminate="scope.row.indeterminate"
|
|
|
- v-model="scope.row.checked"
|
|
|
- @change="changeRowSelect(scope.row)"
|
|
|
- >{{ scope.row.pageName }}</el-checkbox
|
|
|
- >
|
|
|
- <el-checkbox v-else v-model="scope.row.checked" @change="changeRowSelect(scope.row)">{{ scope.row.pageName }}</el-checkbox>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column prop="children" label="按钮">
|
|
|
- <template #default="scope">
|
|
|
- <el-checkbox-group v-model="state.systemButtonArr" @change="handleCheckedBtnChange">
|
|
|
- <el-checkbox v-for="item in scope.row.buttonArr" :key="item.id" :label="item.permissionCode"
|
|
|
- ><span v-if="showSetting">{{ item.permissionCode }}-{{ item.btnName }}</span>
|
|
|
- <span v-else>{{ item.btnName }}</span>
|
|
|
- </el-checkbox>
|
|
|
- </el-checkbox-group>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- </el-table>
|
|
|
+ <el-dialog :title="`【${state.rowName}】权限配置`" v-model="state.isShowDialog" draggable @opened="opened">
|
|
|
+ <div class="custom-tree-node-container" v-loading="state.loading">
|
|
|
+ <el-row :gutter="10">
|
|
|
+ <el-col :xs="24" :sm="8" :md="8" :lg="8" :xl="8">
|
|
|
+ 展开/折叠:<el-switch
|
|
|
+ v-model="state.menuExpand"
|
|
|
+ @change="handleCheckedTreeExpand"
|
|
|
+ inline-prompt
|
|
|
+ active-text="折叠"
|
|
|
+ inactive-text="展开"
|
|
|
+ ></el-switch>
|
|
|
+ </el-col>
|
|
|
+ <el-col :xs="24" :sm="8" :md="8" :lg="8" :xl="8">
|
|
|
+ 全选/全不选:<el-switch
|
|
|
+ v-model="state.menuNodeAll"
|
|
|
+ @change="handleCheckedTreeNodeAll"
|
|
|
+ inline-prompt
|
|
|
+ active-text="全选"
|
|
|
+ inactive-text="全不选"
|
|
|
+ ></el-switch>
|
|
|
+ </el-col>
|
|
|
+ <el-col :xs="24" :sm="8" :md="8" :lg="8" :xl="8">
|
|
|
+ 父子联动:<el-switch
|
|
|
+ v-model="state.menuCheckStrictly"
|
|
|
+ @change="handleCheckedTreeConnect"
|
|
|
+ inline-prompt
|
|
|
+ active-text="联动"
|
|
|
+ inactive-text="不联动"
|
|
|
+ ></el-switch>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-tree
|
|
|
+ class="tree-border mt20"
|
|
|
+ :data="state.menuTableData"
|
|
|
+ show-checkbox
|
|
|
+ ref="menuRef"
|
|
|
+ node-key="permissionCode"
|
|
|
+ :check-strictly="!state.menuCheckStrictly"
|
|
|
+ :props="{ label: 'pageName', children: 'children', class: customNodeClass }"
|
|
|
+ ></el-tree>
|
|
|
</div>
|
|
|
<template #footer>
|
|
|
<span class="dialog-footer">
|
|
|
- <el-button class="default-button"><el-checkbox v-model="state.checkedAll" @change="changeAllSelect">全选</el-checkbox></el-button>
|
|
|
<el-button @click="onCancel" class="default-button">取 消</el-button>
|
|
|
<el-button type="primary" @click="onSubmit">确 定</el-button>
|
|
|
</span>
|
|
@@ -39,7 +52,7 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts" name="systemEditRole">
|
|
|
-import { reactive, onMounted, computed } from 'vue';
|
|
|
+import { reactive, onMounted, ref } from 'vue';
|
|
|
import { ElMessage } from 'element-plus';
|
|
|
import { auth } from '/@/utils/authFunction';
|
|
|
import { getMenuList } from '/@/api/system/menu';
|
|
@@ -47,66 +60,70 @@ import { getRolePower, setRolePower } from '/@/api/system/roles';
|
|
|
|
|
|
// 定义子组件向父组件传值/事件
|
|
|
const emit = defineEmits(['updateList']);
|
|
|
+interface Tree {
|
|
|
+ id: number;
|
|
|
+ label: string;
|
|
|
+ isPenultimate?: boolean;
|
|
|
+ menuType?: number;
|
|
|
+ children?: Tree[];
|
|
|
+}
|
|
|
|
|
|
// 定义变量内容
|
|
|
const state = reactive<any>({
|
|
|
isShowDialog: false,
|
|
|
- menuTableData: <any>[],
|
|
|
- systemMenuArr: <any>[],
|
|
|
- systemButtonArr: <any>[],
|
|
|
+ menuTableData: <any>[], //所有菜单按钮
|
|
|
+ systemMenuArr: <any>[], // 选中的菜单
|
|
|
currentRow: {},
|
|
|
- checkedAll: false,
|
|
|
expandRowKeys: [],
|
|
|
+ rowName: '',
|
|
|
+ menuExpand: false,
|
|
|
+ menuNodeAll: false,
|
|
|
+ menuCheckStrictly: true,
|
|
|
+ loading: false,
|
|
|
});
|
|
|
+const menuRef = ref();
|
|
|
+const customNodeClass = (data: Tree) => {
|
|
|
+ if (data.menuType === 2) {
|
|
|
+ return 'is-penultimate';
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+};
|
|
|
// 打开弹窗
|
|
|
const openDialog = (row: any) => {
|
|
|
state.currentRow = row;
|
|
|
state.systemMenuArr = <any>[];
|
|
|
- state.systemButtonArr = <any>[];
|
|
|
- const loop = (data: any) => {
|
|
|
- data.forEach((item: any) => {
|
|
|
- item.checked = false;
|
|
|
- if (item.children && item.children.length) {
|
|
|
- loop(item.children);
|
|
|
- }
|
|
|
- });
|
|
|
- };
|
|
|
- loop(state.menuTableData);
|
|
|
+ state.menuExpand = false;
|
|
|
+ state.menuNodeAll = false;
|
|
|
+ state.rowName = row.displayName;
|
|
|
+ state.loading = true;
|
|
|
+ state.isShowDialog = true;
|
|
|
+};
|
|
|
+// 树形扁平化
|
|
|
+const treeFlat = (source: any[]) => {
|
|
|
+ let res: any = [];
|
|
|
+ source.forEach((el) => {
|
|
|
+ res.push(el);
|
|
|
+ el.children && res.push(...treeFlat(el.children));
|
|
|
+ });
|
|
|
+ return res;
|
|
|
+};
|
|
|
+
|
|
|
+const opened = () => {
|
|
|
if (!auth('100205')) ElMessage.error('抱歉,您没有获取角色权限的权限!');
|
|
|
else {
|
|
|
- getRolePower({ roleid: row.id }).then((res: any) => {
|
|
|
- state.systemMenuArr = res.result?.systemMenuArr ?? [];
|
|
|
- state.systemButtonArr = res.result?.systemButtonArr ?? [];
|
|
|
- const loop = (data: any) => {
|
|
|
- data.forEach((item: any) => {
|
|
|
- for (let i of state.systemMenuArr) {
|
|
|
- if (item.permissionCode === i) {
|
|
|
- item.checked = true;
|
|
|
- if (item.children && item.children.length) {
|
|
|
- loop(item.children);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- };
|
|
|
- loop(state.menuTableData);
|
|
|
- state.expandRowKeys = state.systemMenuArr;
|
|
|
- state.isShowDialog = true;
|
|
|
- });
|
|
|
+ getRolePower({ roleid: state.currentRow.id })
|
|
|
+ .then((res: any) => {
|
|
|
+ const arr: any[] = res.result?.systemMenuArr ?? [];
|
|
|
+ menuRef.value.setCheckedKeys(arr);
|
|
|
+ const arr1 = treeFlat(state.menuTableData);
|
|
|
+ if (arr.length === arr1.length) state.menuNodeAll = true;
|
|
|
+ state.loading = false;
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ state.loading = false;
|
|
|
+ });
|
|
|
}
|
|
|
};
|
|
|
-// 检查是否全选
|
|
|
-const opened = () => {
|
|
|
- const loopMenu = (data: any) => {
|
|
|
- return data.every((item: any) => {
|
|
|
- if (item.children && item.children.length) {
|
|
|
- loopMenu(item.children);
|
|
|
- }
|
|
|
- return item.checked;
|
|
|
- });
|
|
|
- };
|
|
|
- state.checkedAll = loopMenu(state.menuTableData);
|
|
|
-};
|
|
|
// 关闭弹窗
|
|
|
const closeDialog = () => {
|
|
|
state.isShowDialog = false;
|
|
@@ -121,172 +138,26 @@ const getMenuListApi = () => {
|
|
|
state.menuTableData = res?.result ?? [];
|
|
|
});
|
|
|
};
|
|
|
-// 开发环境不显示设置
|
|
|
-const showSetting = computed(() => {
|
|
|
- return import.meta.env.VITE_MODE_NAME === 'development';
|
|
|
-});
|
|
|
-
|
|
|
-// 选择表格(全选)
|
|
|
-const changeAllSelect = (val: any) => {
|
|
|
- const loop = (data: any) => {
|
|
|
- data.forEach((item: any) => {
|
|
|
- item.checked = val;
|
|
|
- if ('indeterminate' in item) {
|
|
|
- item.indeterminate = false;
|
|
|
- }
|
|
|
- if (item.buttonArr && item.buttonArr.length) {
|
|
|
- item.buttonArr.forEach((item: any) => {
|
|
|
- if (val) {
|
|
|
- state.systemButtonArr.push(item.permissionCode);
|
|
|
- } else {
|
|
|
- for (let i in state.systemButtonArr) {
|
|
|
- if (state.systemButtonArr[i] === item.permissionCode) {
|
|
|
- state.systemButtonArr.splice(i, 1);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- state.systemButtonArr = Array.from(new Set(state.systemButtonArr));
|
|
|
- if (item.children && item.children.length) {
|
|
|
- loop(item.children);
|
|
|
- }
|
|
|
- });
|
|
|
- };
|
|
|
- loop(state.menuTableData);
|
|
|
-};
|
|
|
-const find = (v: any, list: any[]) => {
|
|
|
- let data;
|
|
|
- (list || []).map((i) => {
|
|
|
- if (i.id === v) {
|
|
|
- data = i;
|
|
|
- } else {
|
|
|
- const children = find(v, i.children);
|
|
|
- if (children) {
|
|
|
- data = children;
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- return data;
|
|
|
-};
|
|
|
-// 选择表格(表格行选择)
|
|
|
-const changeRowSelect = (val: any) => {
|
|
|
- const loopBtn = (data: any, checked = val.checked) => {
|
|
|
- data.forEach((item: any) => {
|
|
|
- if (checked) {
|
|
|
- state.systemButtonArr.push(item.permissionCode);
|
|
|
- } else {
|
|
|
- for (let i in state.systemButtonArr) {
|
|
|
- if (state.systemButtonArr[i] === item.permissionCode) {
|
|
|
- state.systemButtonArr.splice(i, 1);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if (item.buttonArr && item.buttonArr.length) {
|
|
|
- loopBtn(item.buttonArr);
|
|
|
- }
|
|
|
- });
|
|
|
- };
|
|
|
- const loop = (data: any) => {
|
|
|
- data.forEach((item: any) => {
|
|
|
- item.checked = val.checked;
|
|
|
- if (item.children && item.children.length) {
|
|
|
- loop(item.children);
|
|
|
- }
|
|
|
- if (item.buttonArr && item.buttonArr.length) {
|
|
|
- loopBtn(item.buttonArr);
|
|
|
- }
|
|
|
- });
|
|
|
- };
|
|
|
- state.systemButtonArr = Array.from(new Set(state.systemButtonArr));
|
|
|
- if (val.buttonArr && val.buttonArr.length) {
|
|
|
- loopBtn(val.buttonArr);
|
|
|
- }
|
|
|
- if (val.children && val.children.length) {
|
|
|
- loop(val.children);
|
|
|
- if ('indeterminate' in val) {
|
|
|
- val.indeterminate = false;
|
|
|
- }
|
|
|
- } else {
|
|
|
- let checkedLeg = 0;
|
|
|
- const loop = (data: any) => {
|
|
|
- data.forEach((item: any) => {
|
|
|
- if (item.id === val.parentId) {
|
|
|
- // 获取当前父级下子级选中条数
|
|
|
- const leg = item.children.length;
|
|
|
- checkedLeg = item.children.filter((ss: any) => ss.checked).length;
|
|
|
- // 根据条数改变父级的indeterminate和checked
|
|
|
- if (checkedLeg === 0) {
|
|
|
- item.indeterminate = false;
|
|
|
- item.checked = false;
|
|
|
- } else if (checkedLeg < leg) {
|
|
|
- item.indeterminate = true;
|
|
|
- item.checked = false;
|
|
|
- } else if (checkedLeg === leg) {
|
|
|
- item.indeterminate = false;
|
|
|
- item.checked = true;
|
|
|
- }
|
|
|
-
|
|
|
- const currentI: any = find(item.parentId, state.menuTableData);
|
|
|
- if (currentI) {
|
|
|
- let checkedLeg1 = 0;
|
|
|
- const leg1 = currentI.children.length;
|
|
|
- checkedLeg1 = item.children.filter((ss: any) => ss.checked).length;
|
|
|
- // 根据条数改变父级的indeterminate和checked
|
|
|
- if (checkedLeg1 === 0) {
|
|
|
- currentI.indeterminate = false;
|
|
|
- } else if (checkedLeg < leg1) {
|
|
|
- currentI.indeterminate = true;
|
|
|
- } else if (checkedLeg === leg1) {
|
|
|
- currentI.indeterminate = false;
|
|
|
- }
|
|
|
- }
|
|
|
- return;
|
|
|
- }
|
|
|
- if (item.children && item.children.length) {
|
|
|
- loop(item.children);
|
|
|
- }
|
|
|
- });
|
|
|
- };
|
|
|
- loop(state.menuTableData);
|
|
|
+/** 树权限(展开/折叠)*/
|
|
|
+const handleCheckedTreeExpand = (value: boolean) => {
|
|
|
+ for (let i = 0; i < state.menuTableData.length; i++) {
|
|
|
+ menuRef.value.store.nodesMap[state.menuTableData[i].permissionCode].expanded = value;
|
|
|
}
|
|
|
- // 判断是否全部选择了,改变全选框的样式
|
|
|
- let flag = true;
|
|
|
- state.menuTableData.some((item: any) => {
|
|
|
- if (!item.checked) {
|
|
|
- flag = false;
|
|
|
- return;
|
|
|
- }
|
|
|
- });
|
|
|
- state.checkedAll = flag;
|
|
|
};
|
|
|
-// 选择按钮
|
|
|
-const handleCheckedBtnChange = (value: string[]) => {
|
|
|
- state.systemButtonArr = value;
|
|
|
+/** 树权限(全选/全不选) */
|
|
|
+const handleCheckedTreeNodeAll = (value: boolean) => {
|
|
|
+ menuRef.value.setCheckedNodes(value ? state.menuTableData : []);
|
|
|
};
|
|
|
-// 点击提交选中的表格
|
|
|
-const handleSelectTable = () => {
|
|
|
- let selectedCodes = <any>[];
|
|
|
- const loop = (data: any) => {
|
|
|
- data.forEach((item: any) => {
|
|
|
- if (item.checked || item.indeterminate) {
|
|
|
- selectedCodes.push(item.permissionCode);
|
|
|
- if (item.children) {
|
|
|
- loop(item.children);
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- };
|
|
|
- loop(state.menuTableData);
|
|
|
- return selectedCodes;
|
|
|
+/** 树权限(父子联动) */
|
|
|
+const handleCheckedTreeConnect = (value: boolean) => {
|
|
|
+ state.menuCheckStrictly = value ? true : false;
|
|
|
};
|
|
|
// 保存
|
|
|
const onSubmit = () => {
|
|
|
let req = {
|
|
|
roleId: state.currentRow.id,
|
|
|
roleCode: state.currentRow.name,
|
|
|
- systemMenuArr: handleSelectTable(),
|
|
|
- systemButtonArr: state.systemButtonArr,
|
|
|
+ systemMenuArr: menuRef.value.getCheckedKeys(),
|
|
|
};
|
|
|
setRolePower(req)
|
|
|
.then(() => {
|
|
@@ -318,4 +189,17 @@ defineExpose({
|
|
|
box-sizing: border-box;
|
|
|
align-items: center;
|
|
|
}
|
|
|
+.tree-border {
|
|
|
+ border: var(--el-border);
|
|
|
+ border-radius: var(--el-border-radius-base);
|
|
|
+ padding: 15px;
|
|
|
+}
|
|
|
+:deep(.el-tree-node.is-expanded.is-penultimate > .el-tree-node__children) {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ flex-wrap: wrap;
|
|
|
+}
|
|
|
+:deep(.is-penultimate > .el-tree-node__children > div) {
|
|
|
+ width: 25%;
|
|
|
+}
|
|
|
</style>
|