<template> 
 | 
  <div class="role-container"> 
 | 
    <div class="role-tree-left flex-col"> 
 | 
      <div class="title"><i class="el-icon-user"></i>角色列表</div> 
 | 
      <el-scrollbar class="el-role-list"> 
 | 
        <el-tree 
 | 
          :data="tree" 
 | 
          @node-click="nodeClick" 
 | 
          node-key="id" 
 | 
          :default-expanded-keys="openKeys" 
 | 
          :expand-on-click-node="false" 
 | 
          style="padding: 5px 0; margin-right: 2px" 
 | 
        > 
 | 
          <template #default="{ data }"> 
 | 
            <div class="action-group"> 
 | 
              <div class="action-text"> 
 | 
                {{ data.roleName }} 
 | 
              </div> 
 | 
            </div> 
 | 
          </template> 
 | 
        </el-tree> 
 | 
      </el-scrollbar> 
 | 
    </div> 
 | 
    <div class="role-tree-right flex-col"> 
 | 
      <div class="title"> 
 | 
        <div><i class="el-icon-folder-opened"></i>菜单权限</div> 
 | 
        <el-button type="primary" @click="save">保存</el-button> 
 | 
      </div> 
 | 
      <el-scrollbar class="el-role-list"> 
 | 
        <el-tree 
 | 
          @check-change="leftCheckChange" 
 | 
          @check="nodeCheck" 
 | 
          :data="roleTree" 
 | 
          :show-checkbox="false" 
 | 
          style="padding: 15px" 
 | 
          node-key="id" 
 | 
          default-expand-all 
 | 
          :expand-on-click-node="false" 
 | 
        > 
 | 
          <template #default="{ data }"> 
 | 
            <div class="action-group"> 
 | 
              <div 
 | 
                class="action-text" 
 | 
                :style="{ width: (4 - data.lv) * 18 + 150 + 'px' }" 
 | 
              > 
 | 
                <el-checkbox v-model="data.leftCk" @change="allChange(data)">{{ 
 | 
                  // data.text + (data.isApp ? "(app)" : "") 
 | 
                  data.text  
 | 
                }}</el-checkbox> 
 | 
              </div> 
 | 
              <div class="action-item"> 
 | 
                <el-checkbox 
 | 
                  v-for="(item, index) in data.actions" 
 | 
                  :key="index" 
 | 
                  v-model="item.checked" 
 | 
                  @change="actionChange(data, item.checked)" 
 | 
                  >{{ item.text }}</el-checkbox 
 | 
                > 
 | 
              </div> 
 | 
            </div> 
 | 
          </template> 
 | 
        </el-tree> 
 | 
      </el-scrollbar> 
 | 
    </div> 
 | 
  </div> 
 | 
</template> 
 | 
  
 | 
<script> 
 | 
import { defineComponent, ref, reactive, getCurrentInstance } from "vue"; 
 | 
import http from "@/../src/api/http.js"; 
 | 
export default defineComponent({ 
 | 
  setup() { 
 | 
    const selectId = ref(-1); 
 | 
    const checked = ref(false); 
 | 
    const tree = reactive([]); 
 | 
    const list = reactive([]); 
 | 
    const roles = reactive([]); 
 | 
    const roleList = reactive([]); 
 | 
    const roleTree = reactive([]); 
 | 
    const openKeys = reactive([]); 
 | 
  
 | 
    const leftCheckChange = (node, selected) => { 
 | 
      node.actions.forEach((x, index) => { 
 | 
        x.checked = selected; 
 | 
      }); 
 | 
    }; 
 | 
    const nodeCheck = (node, data) => { 
 | 
      let rootData = roleList.find((x) => { 
 | 
        return x.id === node.pid; 
 | 
      }); 
 | 
      if (rootData && rootData.actions.length) { 
 | 
        rootData.actions[0].checked = 
 | 
          node.actions.some((x) => { 
 | 
            return x.checked; 
 | 
          }) || 
 | 
          data.halfCheckedNodes.some((x) => { 
 | 
            return x.id === node.pid; 
 | 
          }); 
 | 
      } 
 | 
    }; 
 | 
  
 | 
    const allChange = (data) => { 
 | 
      data.actions.forEach((item) => { 
 | 
        item.checked = data.leftCk; 
 | 
      }); 
 | 
      if (!data.children) { 
 | 
        return; 
 | 
      } 
 | 
      setChildrenChecked(data, data.leftCk); 
 | 
    }; 
 | 
    const setChildrenChecked = (data, ck) => { 
 | 
      data.children.forEach((item) => { 
 | 
        item.leftCk = ck; 
 | 
        item.actions.forEach((c) => { 
 | 
          c.checked = ck; 
 | 
        }); 
 | 
        if (item.children) { 
 | 
          setChildrenChecked(item, ck); 
 | 
        } 
 | 
      }); 
 | 
    }; 
 | 
    const actionChange = (data, ck) => { 
 | 
      ck = 
 | 
        data.actions.filter((x) => { 
 | 
          return x.checked; 
 | 
        }).length == data.actions.length; 
 | 
      data.leftCk = ck; 
 | 
    }; 
 | 
  
 | 
    const load = () => { 
 | 
      const url = "api/Sys_Role/getUserChildRoles"; 
 | 
      http.post(url, {}, true).then((result) => { 
 | 
         
 | 
        if (!result.status) return; 
 | 
        list.splice(0); 
 | 
        list.push(...result.data); 
 | 
        list.forEach((x) => { 
 | 
          if (x.parentId == 0) { 
 | 
            x.lv = 1; 
 | 
            x.children = []; 
 | 
            tree.push(x); 
 | 
            getTree(x.id, x); 
 | 
          } 
 | 
        }); 
 | 
        openKeys.push(tree[0].id); 
 | 
        selectId.value = openKeys[0]; 
 | 
      }); 
 | 
    }; 
 | 
    const getTree = (id, data) => { 
 | 
      list.forEach((x) => { 
 | 
        if (x.parentId == id) { 
 | 
          x.lv = data.lv + 1; 
 | 
          if (!data.children) data.children = []; 
 | 
          data.children.push(x); 
 | 
          getTree(x.id, x); 
 | 
        } 
 | 
      }); 
 | 
    }; 
 | 
    const nodeClick = (node, selected) => { 
 | 
      selectId.value = node.id; 
 | 
      getUserRole(node); 
 | 
    }; 
 | 
    const getUserRole = (item) => { 
 | 
      selectId.value = item.id; 
 | 
      roleList.forEach((x) => { 
 | 
        x.actions.forEach((a) => { 
 | 
          a.checked = false; 
 | 
        }); 
 | 
      }); 
 | 
      let url = `/api/Sys_Role/getUserTreePermission?roleId=${item.id}`; 
 | 
      http.post(url, {}, true).then((result) => { 
 | 
        if (!result.status) return; 
 | 
        result.data.forEach((item) => { 
 | 
          if (item.actions.length == 0) return; 
 | 
          let sourceItem = roleList.find((f) => f.id == item.id); 
 | 
          if (!sourceItem) return; 
 | 
          item.actions.forEach((actions) => { 
 | 
            sourceItem.actions.forEach((soure) => { 
 | 
              if (soure.value == actions.value) { 
 | 
                soure.checked = true; 
 | 
              } 
 | 
            }); 
 | 
          }); 
 | 
        }); 
 | 
      }); 
 | 
    }; 
 | 
  
 | 
    const getRoleTree = (id, data, isRootId) => { 
 | 
      roleList.forEach((x) => { 
 | 
        if (x.pid == id) { 
 | 
          x.lv = data.lv + 1; 
 | 
          if (isRootId) { 
 | 
            x.rootId = id; 
 | 
          } 
 | 
          if (!data.children) data.children = []; 
 | 
          data.children.push(x); 
 | 
          getRoleTree(x.id, x, isRootId); 
 | 
        } 
 | 
      }); 
 | 
    }; 
 | 
  
 | 
    const getCurrentTreePermission = () => { 
 | 
      let url = "/api/Sys_Role/getCurrentTreePermission"; 
 | 
      http.post(url, {}, true).then((result) => { 
 | 
        if (!result.status) return; 
 | 
        roleList.splice(0); 
 | 
        roles.splice(0); 
 | 
        roleList.push(...result.data.tree); 
 | 
        roles.push(...result.data.roles); 
 | 
        roleList.forEach((x) => { 
 | 
          if (x.pid == 0) { 
 | 
            x.lv = 1; 
 | 
            x.children = []; 
 | 
            roleTree.push(x); 
 | 
            getRoleTree(x.id, x); 
 | 
          } 
 | 
        }); 
 | 
      }); 
 | 
    }; 
 | 
    let $message = 
 | 
      getCurrentInstance().appContext.config.globalProperties.$message; 
 | 
    const save = () => { 
 | 
      if (selectId.value <= 0) { 
 | 
        return $message.error("请选择角色!"); 
 | 
      } 
 | 
      let userPermissions = []; 
 | 
      roleList.forEach((x) => { 
 | 
        let checkedPermission = x.actions.filter((f) => { 
 | 
          return f.checked; 
 | 
        }); 
 | 
        if (checkedPermission.length > 0) { 
 | 
          let actions = checkedPermission.map((m) => { 
 | 
            return { text: m.text, value: m.value }; 
 | 
          }); 
 | 
          userPermissions.push({ 
 | 
            id: x.id, 
 | 
            actions: actions, 
 | 
          }); 
 | 
        } 
 | 
      }); 
 | 
      let url = `api/Sys_Role/SavePermission?roleId=${selectId.value}`; 
 | 
      http.post(url, userPermissions, true).then((result) => { 
 | 
        $message[result.status ? "success" : "error"](result.message); 
 | 
      }); 
 | 
    }; 
 | 
  
 | 
    load(); 
 | 
    getCurrentTreePermission(); 
 | 
    return { 
 | 
      list, 
 | 
      nodeClick, 
 | 
      checked, 
 | 
      tree, 
 | 
      selectId, 
 | 
      openKeys, 
 | 
      getUserRole, 
 | 
      roles, 
 | 
      roleList, 
 | 
      getCurrentTreePermission, 
 | 
      leftCheckChange, 
 | 
      nodeCheck, 
 | 
      roleTree, 
 | 
      allChange, 
 | 
      actionChange, 
 | 
      save, 
 | 
    }; 
 | 
  }, 
 | 
}); 
 | 
</script> 
 | 
<style lang="less" scoped> 
 | 
.role-container { 
 | 
  position: absolute; 
 | 
  background: #f6f6f6; 
 | 
  height: 100%; 
 | 
  width: 100%; 
 | 
  padding: 10px; 
 | 
  display: flex; 
 | 
  .flex-col { 
 | 
    display: flex; 
 | 
    flex-direction: column; 
 | 
  } 
 | 
  .role-tree-left { 
 | 
    border: 1px solid #f2f2f2; 
 | 
    background: #fff; 
 | 
    width: 230px; 
 | 
    margin-right: 10px; 
 | 
    .title { 
 | 
      i { 
 | 
        margin-left: 10px; 
 | 
      } 
 | 
    } 
 | 
  } 
 | 
  .role-tree-right { 
 | 
    background: #fff; 
 | 
    border: 1px solid #f2f2f2; 
 | 
    width: 0; 
 | 
    flex: 1; 
 | 
    .title { 
 | 
      display: flex; 
 | 
      i { 
 | 
        margin-left: 10px; 
 | 
      } 
 | 
      div { 
 | 
        flex: 1; 
 | 
      } 
 | 
    } 
 | 
    .action-group { 
 | 
      display: flex; 
 | 
      // line-height: 32px; 
 | 
      justify-content: center; 
 | 
      align-items: center; 
 | 
      label { 
 | 
        float: left; 
 | 
      } 
 | 
      .action-text { 
 | 
        line-height: 33px; 
 | 
        label { 
 | 
          margin-right: 5px; 
 | 
        } 
 | 
      } 
 | 
    } 
 | 
  } 
 | 
  .title { 
 | 
    padding: 10px; 
 | 
    background: rgb(246 250 255); 
 | 
    font-weight: bold; 
 | 
    font-size: 14px; 
 | 
    letter-spacing: 2px; 
 | 
  } 
 | 
  .el-role-list { 
 | 
    flex: 1; 
 | 
    height: 0; 
 | 
    overflow-x: hidden; 
 | 
  } 
 | 
} 
 | 
.role-tree-left ::v-deep(.el-tree-node__content) { 
 | 
  cursor: pointer; 
 | 
  height: auto; 
 | 
  padding: 5px; 
 | 
  margin: 2px 10px; 
 | 
  font-size: 15px; 
 | 
} 
 | 
.role-tree-left ::v-deep(.el-tree-node__content:hover) { 
 | 
  background: #f4f4f4; 
 | 
  border-radius: 20px; 
 | 
} 
 | 
.role-tree-left ::v-deep(.is-current > .el-tree-node__content:first-child) { 
 | 
  background: #f2f2f2; 
 | 
  border-radius: 20px; 
 | 
} 
 | 
.role-tree-right ::v-deep(.el-tree-node__content) { 
 | 
  margin-bottom: 5px; 
 | 
  height: auto; 
 | 
} 
 | 
.role-tree-right ::v-deep(.el-checkbox__label) { 
 | 
  position: relative; 
 | 
  top: 2px; 
 | 
} 
 | 
</style> 
 |