123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- <template>
- <div class="system-edit-role-container">
- <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="12" :md="12" :lg="12" :xl="12">
- 展开/折叠:<el-switch
- v-model="state.menuExpand"
- @change="handleCheckedTreeExpand"
- inline-prompt
- active-text="折叠"
- inactive-text="展开"
- ></el-switch>
- </el-col>
- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
- 全选/全不选:<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="不联动"
- disabled
- ></el-switch>
- </el-col> -->
- </el-row>
- <el-tree
- class="tree-border mt20"
- :data="state.menuTableData"
- show-checkbox
- ref="menuRef"
- node-key="permissionCode"
- check-on-click-node
- :expand-on-click-node="false"
- :check-strictly="!state.menuCheckStrictly"
- :props="{ label: 'pageName', children: 'children', class: customNodeClass }"
- >
- <template #default="{ data }">
- <span>{{ data.pageName }}</span>
- </template>
- </el-tree>
- </div>
- <template #footer>
- <span class="dialog-footer">
- <el-button @click="onCancel" class="default-button">取 消</el-button>
- <el-button type="primary" @click="onSubmit">确 定</el-button>
- </span>
- </template>
- </el-dialog>
- </div>
- </template>
- <script setup lang="ts" name="systemEditRole">
- import { reactive, onMounted, ref } from 'vue';
- import { ElMessage } from 'element-plus';
- import { auth } from '/@/utils/authFunction';
- import { getMenuList } from '/@/api/system/menu';
- import { getRolePower, setRolePower } from '/@/api/system/roles';
- // 定义子组件向父组件传值/事件
- const emit = defineEmits(['updateList']);
- interface Tree {
- id: number;
- label: string;
- isPenultimate?: boolean;
- expanded: boolean;
- menuType?: number;
- children?: Tree[];
- }
- // 定义变量内容
- const state = reactive<any>({
- isShowDialog: false,
- menuTableData: <any>[], //所有菜单按钮
- systemMenuArr: <any>[], // 选中的菜单
- currentRow: {},
- expandRowKeys: [],
- rowName: '',
- menuExpand: false, // 展开
- menuNodeAll: false, // 全选
- menuCheckStrictly: false, // 是否联动
- 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.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('system:role:detail')) ElMessage.error('抱歉,您没有权限获取当前角色权限!');
- else {
- getRolePower({ roleid: state.currentRow.id })
- .then((res: any) => {
- let arr: string[] = res.result?.systemMenuArr ?? [];
- arr = arr.map((v: any) => v.code);
- 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 closeDialog = () => {
- state.isShowDialog = false;
- };
- // 取消
- const onCancel = () => {
- closeDialog();
- };
- let newArr: string[] = [];
- // 获取所有code
- const getCode = (arr: any) => {
- if (!arr) return [];
- arr.forEach((v: any) => {
- newArr.push(v.permissionCode);
- if (v.children?.length) {
- getCode(v.children);
- }
- });
- return newArr;
- };
- // 获取所有菜单
- const getMenuListApi = () => {
- getMenuList().then((res: any) => {
- state.menuTableData = res?.result ?? [];
- });
- };
- /** 树权限(展开/折叠)*/
- const handleCheckedTreeExpand = (value: boolean) => {
- for (let i = 0; i < state.menuTableData.length; i++) {
- menuRef.value.store.nodesMap[state.menuTableData[i].permissionCode].expanded = value;
- }
- // expandNodes(menuRef.value.root, value);
- };
- // 遍历树形数据,设置每一项的expanded属性,实现展开收起
- // const expandNodes = (node: any, value: boolean) => {
- // node.expanded = value;
- // for (let i = 0; i < node.childNodes.length; i++) {
- // node.childNodes[i].expanded = value;
- // if (node.childNodes[i].childNodes.length > 0) {
- // expandNodes(node.childNodes[i], value);
- // }
- // }
- // };
- /** 树权限(全选/全不选) */
- const handleCheckedTreeNodeAll = (value: boolean) => {
- menuRef.value.setCheckedKeys(value ? getCode(state.menuTableData) : []);
- };
- /** 树权限(父子联动) */
- // const handleCheckedTreeConnect = (value: boolean) => {
- // state.menuCheckStrictly = value ? true : false;
- // };
- // 保存
- const onSubmit = () => {
- let systemMenuArr = <any>[];
- systemMenuArr = menuRef.value.getCheckedNodes();
- systemMenuArr = systemMenuArr.map((v: any) => {
- return {
- code: v.permissionCode,
- type: v.menuType,
- };
- });
- let req = {
- roleId: state.currentRow.id,
- roleCode: state.currentRow.name,
- systemMenuArr: systemMenuArr,
- };
- setRolePower(req)
- .then(() => {
- ElMessage({
- message: '操作成功',
- type: 'success',
- });
- closeDialog();
- emit('updateList');
- })
- .catch(() => {
- // 新增失败
- closeDialog();
- });
- };
- onMounted(() => {
- getMenuListApi();
- });
- // 暴露变量
- defineExpose({
- openDialog,
- closeDialog,
- });
- </script>
- <style scoped lang="scss">
- :deep(.el-table td.el-table__cell div.cell) {
- display: flex;
- 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>
|