el-select与el-tree的联动,切换勾选保存回显功能(全部代码)

 

<template>
  <div class="system-role-dialog-container">
    <el-dialog draggable :title="title" v-model="isShowDialog" width="30%">
      <el-form :model="menuRoleForm" label-width="100px">
        <el-row :gutter="35">
          <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
            <el-form-item label="应用名称 :">
              <el-select v-model="menuRoleForm.appList">
                <el-option v-for="item in menuOptions" :key="item.label" :label="item.label" :value="item.value" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
            <el-form-item label="菜单权限 :">
              <!-- 遍历展示所有菜单 -->
              <div v-for="(item, index) in treeMenu.appList" :key="index">
                <div v-if="item.appCode">
                  <el-tree :data="allTreeData[item.appCode]" ref="treeEle" :label="'title'" node-key="id"
                    :code="item.appCode" :props="treeProps" :current-node-key="currentKey"
                    :default-checked-keys="selectedNode[item.appCode]" @check="changeCheck"
                    v-show="menuRoleForm.appList === item.appCode" show-checkbox>
                  </el-tree>
                </div>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="onCancel" size="default">取 消</el-button>
          <el-button type="primary" @click="onSubmit" size="default">确定</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>
<script setup lang="ts" name="systemRoleDialog">
import { ref, onMounted } from 'vue';
import { ElMessage } from 'element-plus'
import { tmRoleApi } from '/@/api/user';
const getRoleOwnMenu = tmRoleApi().getRoleOwnMenu
const postRoleMenuList = tmRoleApi().postRoleMenuList
const props = defineProps(['menuList'])
// 定义子组件向父组件传值/事件
const emit = defineEmits(['refresh'])
// 定义变量内容
const defaultCheckedKeys = ref<number[]>([]); // 默认选中的节点id数组
const isShowDialog = ref(false)
const title = ref()
let menuOptions: any = ref([])
const dataTree = ref() // 获取菜单结构数据
let selectedIds = ref()  // 保存选中的id数组
let treeMenu = ref()

const currentKey = ref('')
// 整理根据菜单划分所有列表
const allTreeData = ref<{ [key: string]: any }>({})
const treeProps = ref({
  label: 'title'
})

interface menuRoleForm {
  appList: string,
  menuTree: any,
}
const menuRoleForm = ref<menuRoleForm>({
  appList: '',
  menuTree: [],// 保存选中节点的id的数组
})

// 关闭弹窗
const closeDialog = () => {
  isShowDialog.value = false;
  selectedNode.value = {}
};

// 储存选中的菜单
const selectedNode = ref<{ [key: string]: any }>({})
console.log(selectedNode, 'selectedNodeselectedNode');
// 取消
const onCancel = () => {
  closeDialog();
};

// 打开弹窗
const openDialog = async (row: any) => {
  selectedNode.value = {}
  defaultCheckedKeys.value = [] //每次进来回显置空
  selectedIds.value = row.id
  const resValue = await getRoleOwnMenu(row.id) //根据id获取已授权菜单
  treeMenu.value = props.menuList //获取全部菜单列表
  // 根据应用列表 添加
  for (let i = 0; i < props.menuList.appList.length; i++) {
    // 根据应用 区分所有应用下的树列表,并生成角色权限树
    let item = props.menuList.appList[i]
    if (item.appCode) {
      selectedNode.value[item.appCode] = []
      allTreeData.value[item.appCode] = props.menuList.menuTree.filter((m: any) => m.appCode === item.appCode)
    }
  }
  // 储存已获取的菜单
  for (let i = 0; i < resValue.length; i++) {
    let item = resValue[i]
    if (item.appCode) {
      selectedNode.value[item.appCode].push(...filterSelectedNodes(props.menuList, item.menuIdList))
    }
  }
  function filterSelectedNodes(tree: any, idList: any) {
    function findObjectById(data: any, targetId: any) {
      for (const node of data) {
        if (node.id === targetId) {
          return node;
        }

        if (node.children && node.children.length > 0) {
          const foundInChildren: any = findObjectById(node.children, targetId);
          if (foundInChildren) {
            return foundInChildren;
          }
        }
      }

      return null;
    }
    function processArrayB(arrayA: any, arrayB: any) {
      const newArrayB = [...arrayB];
      arrayB.forEach((id: any) => {
        const foundObject = findObjectById(arrayA, id);

        if (foundObject && foundObject.children && foundObject.children.length > 0) {
          const childrenIds = foundObject.children.map((child: any) => child.id);

          if (!childrenIds.every((childId: any) => newArrayB.includes(childId))) {
            const index = newArrayB.indexOf(id);
            if (index !== -1) {
              newArrayB.splice(index, 1);
            }
          }
        }
      });

      return newArrayB;
    }
    return processArrayB(tree.menuTree, idList)
  }

  menuOptions.value.length = 0
  // 应用列表
  props.menuList.appList.map((item: any) => {
    if (item.appCode) {
      menuOptions.value.push({
        label: item.appName,
        value: item.appCode
      })
    }
  })
  menuRoleForm.value.appList = menuRoleForm.value.appList ? menuRoleForm.value.appList : 'busiapp'
  const appListValue = props.menuList.menuTree.filter((f: any) => f.appCode === menuRoleForm.value.appList)
  dataTree.value = appListValue
  for (let i = 0; i < resValue.length; i++) {
    defaultCheckedKeys.value.push(...resValue[i].menuIdList)
  }
  title.value = '授权菜单';
  isShowDialog.value = true;
};


// 提交
const onSubmit = async () => {
  let keys = Object.keys(selectedNode.value)
  let arr: any = []
  keys.forEach(item => arr.push(...selectedNode.value[item]))
  const params = {
    id: JSON.stringify(selectedIds.value),
    grantMenuIdList: arr,
  }
  await postRoleMenuList(params)
  await emit('refresh'); //刷新列表
  await closeDialog();
  await ElMessage({
    message: '修改成功',
    type: 'success',
  })
};
// 改变选中
const changeCheck = (val: any, checked: any) => {
  selectedNode.value[val.appCode] = [...checked.checkedKeys]
}

// 暴露变量
defineExpose({
  openDialog,
});

// 页面加载时
onMounted(() => {
});
</script>

<style scoped lang="scss">
.system-role-dialog-container {
  .menu-data-tree {
    width: 100%;
    border: 1px solid var(--el-border-color);
    border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
    padding: 5px;
  }
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值