子组件(递归组件,无限下级):

<template>
  <div ref="rootNode" :class="[isGeneral==0?rootClassNode:[isGeneral==1?firstClassNode:generalClassNode]]">
      <div @click.stop="toUpdateNode(treeRoot)" :class="[isGeneral==0?rootClass:[isGeneral==1?firstClass:generalClass]]" :style="{'cursor':changeFlag?'pointer':'auto'}">
        <span v-if="isGeneral<2"><img src="/static/img/test.0affb86.png" alt=""></span>
        <span >{{treeRoot.name}}</span>
        <span :class="[isGeneral<2?nomalNum:extraNum]">30人</span>
      </div>
      <div v-if="isGeneral==0" class="centerline" :style="{width:centerlineWidth+'px',marginLeft:centerlineLeft+'px'}"></div>
      <recursive-component-tree v-for="item of treeRoot.children" :key="item.id" v-if="treeRoot.children" :tree-root="item" :changeFlag="changeFlag" v-on:toChangeNode="toUpdateNode"></recursive-component-tree>
  </div>
</template>

<script>
  import $ from 'jquery'

    export default {
      name: "recursive-component-tree",
      props: {
        treeRoot:Object,
        changeFlag:Boolean
      },
      data(){
        return{
          rootClass:'rootClass',
          firstClass:'firstClass',
          generalClass:'generalClass',
          rootClassNode:'rootClassNode',
          firstClassNode:'firstClassNode',
          generalClassNode:'generalClassNode',
          nomalNum:'nomalNum',
          extraNum:'extraNum',
          centerlineWidth:0,
          centerlineLeft:0
        }
      },
      updated(){

      },
      mounted(){
        if($(this.$refs.rootNode).attr('class') == 'rootClassNode' && this.isGeneral==0){
          let firstLeft = $($(this.$refs.rootNode).children('.firstClassNode').get(0)).position().left
          let lastLeft = $(this.$refs.rootNode).children(':last-child').position().left
          this.centerlineWidth = lastLeft-firstLeft
          this.centerlineLeft = firstLeft+90
        }
      },
      computed:{
        isGeneral:function () {
          return this.treeRoot.grade;
        }
      },
      methods: {
        toUpdateNode(treeRoot) {
          if(this.changeFlag){
            this.$emit('toChangeNode', treeRoot)
          }
        }
      }
    }
</script>

<style scoped>
  img{
    width: 45px;
    height: 45px;
    border-radius: 22px;
    display: inline-block;
    vertical-align: middle;
  }
.tree{
  text-align:left;
  padding-left:20px;
}
  .rootClass{
    width:161px;
    height:72px;
    background-color:#eff8ff;
    line-height: 72px;
    border-radius: 5px;
    margin:0 auto;
    margin-bottom: 23px;
  }
  .rootClass:after{
    content: "";
    width: 1px;
    height: 23px;
    background-color: #0099ff;
    display: block;
    margin-left: 80px;
  }

  .rootClassNode{
    height: 500px;
    position:relative;
  }
  .firstClass{
    width:161px;
    height:72px;
    background-color:#eff8ff;
    line-height: 72px;
    border-radius: 5px;
    text-align: center;
  }
  .firstClassNode{
    display:inline-block;
    vertical-align:top;
    padding:0 10px;
    text-align: left;
  }
  .firstClassNode:before{
    content: "";
    width: 1px;
    height: 23px;
    background-color: #0099ff;
    display: block;
    margin-left: 80px;
  }
  .generalClass{
    font-size: 14px;
    line-height: 28px;
  }
  .generalClass:before{
    content:'\2022';
    font-size: 18px;
    color: #0099ff;
    padding: 5px;
  }
  .generalClassNode{
    padding-left: 20px;
  }
  .centerline{
    height:1px;
    background-color: #0099ff;
    margin:0 auto;
  }
  .nomalNum{
    font-size: 12px;
    color: #666666;
    display:inline-block;
  }
  .extraNum{
    padding-left:8px;
  }
  .extraNum:before{
    content:'(';
  }
  .extraNum:after{
    content:')';
  }

/*  .firstClass:after{
  display:block;clear:both;content:"";visibility:hidden;height:0
 }*/
</style>


父组件:

<template>
   <div class="all">
     <vDialog v-show="showDialog" :dialog-option="dialogOption" ref="dialog"></vDialog>
     <headTop :isActive_2="isActive_2">
   </headTop>
        <div class="organization-main">
          <div class="menuLeft">
           <menuLeft :isActive_9="isActive_9"></menuLeft>
          </div>
             <div class='organization-index'>
                <div class='organization-index-top'>
                  <div class='main-top-title'>
                      <img class='main-top-title-img' src='../../assets/roundedRectangle.png'/>
                      <div class='main-top-title-text'>组织结构</div>
                  </div>
                  <div class='main-top-change' @click="toEditStructure()">
                      <img src='../../assets/informationEdit.png'/>
                      <div class='main-top-change-text' >{{changeOrSave}}</div>
                  </div>
                </div>
               <div style="overflow: scroll;white-space:nowrap">
                 <RecursiveComponentTree :tree-root="organizationTree" v-if="updateRoot" :changeFlag="childrenFlag" v-on:toChangeNode="handleChangeNode"></RecursiveComponentTree>

                 <div class='modal-total' v-if="showModal" v-on:click="hideModal()"></div>
                 <!--修改模态框-->
                 <div class="modal" v-if="showModal">
                   <div class='modal-top'>
                     <div class="modal-top-button" v-on:click="hideModal()"></div>
                     <div class='modal-top-right'>
                       <div class='modal-top-right-wrong'></div>
                     </div>
                   </div>
                   <div class="modal-buttons">
                     <div class="modal-updateNode"><span class="modal-NodeName">修改部门名:</span><input type="text" v-model="changeName" /></div>
                     <div class='modal-add-button' @click="showNewNode()" >添加子部门</div>
                     <div class='modal-sub-button' @click="subSelfNode()">删除当前部门</div>
                   </div>
                   <div class='modal-four'>
                     <div class='modal-four-button' @click="submitChange()">确定</div>
                     <div class='modal-four-button' @click="hideModal()">取消</div>
                   </div>
                 </div>
                 <div class="modal-newNode" v-if="showNodeModal">
                   <div class="modal-newNode-top">
                   <div style="display: inline-block;"><span class="modal-newNode-name">新建部门名:</span></div>
                   <div style="display: inline-block;"><input class="modal-newNode-input" type="text" v-model="newNodeName"></div>
                   </div>
                   <div class="modal-newNode-buttons"><button class="modal-newNode-button" @click="addChildNode()">确定</button></div>
                   <div class="modal-newNode-buttons"><button class="modal-newNode-button" @click="hideNodeModal()">取消</button></div>
                 </div>
               </div>
              </div>
        </div>

       <footBottom>
   </footBottom>
   </div>
</template>

<script>
  import headTop from '../../components/header/header.vue'
  import menuLeft from '../../components/enterpriseSetting/enterpriseSetting'
  import footBottom from '../../components/footer/footer.vue'
  import RecursiveComponentTree from '../../components/utils/RecursiveComponentTree'
  import vDialog from '../../components/utils/commonModalTen.vue'
  import $ from 'jquery'

  export default{
    data(){
      return{
        departLength:0,
        fullWidth:0,
        leftWidth:0,
        botWidth:0,
        isActive_9:true,
        isActive_2:true,
        childrenFlag:false,
        changeOrSave:'编辑',
        showModal:false,
        showNodeModal:false,
        showDialog:false,
        master:0,
        dialogOption:[
          {
            title:'',
            text:'',
            happiness:'',
            sad:'',
            department:null
          }
        ],
        newNodeName:'',
        changeName:'',
        treeNode:Object,
        updateRoot:true,
        toList:Object,
        organizationTree:{}
/*        organizationTree:{
          id:1,
          name:'CEO',
          super_id:0,
          grade:'0',
          children:[
            {
              id:11,
              name:'部门1',
              super_id:1,
              grade:'1',
              children:[
                {
                  id:111,
                  name:'部门1-1',
                  grade:'2',
                  super_id:11,
                  children:[
                    {
                      id:1111,
                      name:'部门1-1-1',
                      grade:'3',
                      super_id:111,
                      children:[]
                    }
                  ]
                }
              ]
            },
            {
              id:12,
              name:'部门2',
              grade:'1',
              super_id:1,
              children:[
                {
                  id:121,
                  name:'部门2-1',
                  super_id:12,
                  grade:'2',
                  children:[
                    {
                      id:1211,
                      name:'部门2-1-1',
                      super_id:121,
                      grade:'3',
                      children:[
                        {
                          id:12111,
                          name:'部门2-1-1-1',
                          super_id:1211,
                          grade:'4',
                          children:[]
                        }
                      ]
                    },
                    {
                      id:1212,
                      name:'部门2-1-2',
                      super_id:121,
                      grade:'3',
                      children:[]
                    }
                  ]
                },
                {
                  id:122,
                  name:'部门2-2',
                  super_id:12,
                  grade:'2',
                  children:[]
                }
              ]
            },
            {
              id:13,
              name:'部门3',
              super_id:1,
              grade:'1',
              children:[
                {
                  id:131,
                  name:'部门3-1',
                  super_id:13,
                  grade:'2',
                  children:[]
                }
              ]
            }
          ]
        }*/

      }

    },
    mounted(){
      this.initDate()
/*      window.onbeforeunload = function(event) {
        return "确定退出吗";
      }*/
    },
    created(){

    },

    components: {
      headTop,
      menuLeft,
      footBottom,
      vDialog,
      RecursiveComponentTree
    },
    computed: {

      TreetoList(){
        let listData = [];
        transferTreeData(JSON.parse(JSON.stringify([this.organizationTree])))
        function transferTreeData (sourceData) {
          sourceData.forEach( function(node, nodeIndex) {
            if(node.children.length > 0)
              transferTreeData(node.children)
            listData.push(node)
          })
        }
        return listData;
      },
      ListtoTree() {
        let list = JSON.parse(JSON.stringify(this.toList))
        //let list = this.toList
        let myId = 'id'
        let pId = 'super_id'


        function exists(list, parentId) {  //判断是否有父亲
          for (var i = 0; i < list.length; i++) {
            if (list[i][myId] == parentId) return true
          }
          return false
        }

        var nodes = [];
        for (var i = 0; i < list.length; i++) {
          var row = list[i]
          if (!exists(list, row[pId])) {
            nodes.push(row)
          }
        }

        var toDo = [];
        for (var i = 0; i < nodes.length; i++) {
          toDo.push(nodes[i]);
        }
        while (toDo.length) {
          var node = toDo.shift()
          for (var i = 0; i < list.length; i++) {
            var row = list[i]
            if (row[pId] == node[myId]) {
              if (node.children) {
                node.children.push(row)
              } else {
                node.children = [row]
              }
              row.children = []
              toDo.push(row);
            }
          }
        }

          if(!('children' in nodes[0])){
              nodes[0].children = []
          }
        return nodes;
      }
    },
    methods: {
      initDate(){
        let that = this
        $.ajax({
          type:'POST',
          url:global.urlPath+'getAllDepartments',
          data:{
            enterpriseId:sessionStorage.getItem("enterpriseId")
          },
          success:function(data){
            let result=$.parseJSON(data)
            that.organizationTree = result.departments[0]
          },
          error:function(e){
          }
        })

        $.ajax({
          type:'POST',
          url:global.urlPath+'getDepartmentMaster',
          data:{
            enterpriseId:sessionStorage.getItem("enterpriseId")
          },
          success:function(data){
            let result=$.parseJSON(data)
            that.master = result.master
          }
        })
      },
      toEditStructure(){
        this.childrenFlag = !this.childrenFlag
        this.childrenFlag?this.changeOrSave = '退出编辑':this.changeOrSave = '编辑'
      },
      handleChangeNode(Nodedata){
        //console.log(Nodedata)
        this.showModal = true
        this.toList = JSON.parse(JSON.stringify(this.TreetoList))
        this.toList.forEach(function(Listnode){
          delete Listnode.children
        })
        this.treeNode = this.toList.find((e)=>e.id === Nodedata.id)
        this.changeName = this.treeNode.name
      },
      hideModal(){
        this.showModal=false
      },
      hideNodeModal(){
        this.showNodeModal=false
      },
      submitChange(){
        for(let i=0;i<this.toList.length;i++){
          if(this.toList[i] === this.treeNode){
            this.$set(this.toList[i], 'name', this.changeName)
            let that = this
            $.ajax({
              type:'POST',
              url:global.urlPath+'updateDepartmentName',
              data:{
                id:that.toList[i].id,
                name:this.changeName
              },
              success:function(data){
                let result=$.parseJSON(data)
                console.log(result)
              },
              error:function(e){
              }
            })
          }
        }
        //TODO 修改名称
        this.organizationTree = JSON.parse(JSON.stringify(this.ListtoTree[0]))
        this.hideModal()
      },
      showNewNode(){
        this.showNodeModal=true
        this.showModal=false
      },
      addChildNode(){
        if(this.master == 0){
            this.dialogOption[0].text = '请为当前部门添加职位'
            this.dialogOption[0].happiness = false
            this.dialogOption[0].sad = false
            this.dialogOption[0].departmentId = this.treeNode.id
            this.showDialog = true
        }else {
          for (let i = 0; i < this.toList.length; i++) {
            if (this.toList[i] === this.treeNode) {
              let newNode = {
                id: null,
                name: this.newNodeName,
                grade: this.treeNode.grade + 1,
                enterprise_id: sessionStorage.getItem("enterpriseId"),
                super_id: this.treeNode.id
              }
              let that = this
              /*            $.ajax({
              type:'POST',
              url:global.urlPath+'insertDepartment',
              async: false,
              data:newNode,
              success:function(data){
                let result=$.parseJSON(data)
                newNode.id = result.departmentId
                delete newNode.enterprise_id
              },
              error:function(e){
              }
            })*/
              that.toList.push(newNode)
              //this.$router.push('/addNewOffer')
              this.hideNodeModal()
              //TODO 添加孩子节点
              that.dialogOption[0].text = '请为新部门添加职位'
              that.dialogOption[0].happiness = false
              that.dialogOption[0].sad = false
              that.dialogOption[0].department = newNode
              that.showDialog = true
            }
          }
          this.organizationTree = JSON.parse(JSON.stringify(this.ListtoTree[0]))
          this.hideModal()
        }
      },
      subSelfNode(){
        let subList = [];
        if(this.treeNode.id != 1){
          subList.push(this.treeNode.id)
        }else{
          this.dialogOption[0].text = '根节点不可以删除'
          this.dialogOption[0].happiness = false
          this.dialogOption[0].sad = true
          this.dialogOption[0].department = null
          this.showDialog = true
          return false
        }
        subNode(this.toList,this.treeNode.id)
        function subNode(Node,id){
          for(let i=0;i<Node.length;i++){
            if(Node[i].super_id == id){
              let superId = Node[i].id
              subNode(Node,superId)
              //Node.splice(i,1)
              subList.push(Node[i].id)
            }
          }
        }

        for(let i=0;i<subList.length;i++){
          for(let j=0;j<this.toList.length;j++){
            if(this.toList[j].id === subList[i]){
              this.toList.splice(j,1)
            }
          }
        }
        //TODO 删除
        let ids="";
        for(let i=0;i<subList.length;i++){
          if(i==0){
            ids=subList[i];
          }else{
            ids += ','+subList[i];
          }
        }

        let that = this
        $.ajax({
          type:'POST',
          url:global.urlPath+'deleteDepartment',
          data:{
            ids:ids
          },
          success:function(data){
            let result=$.parseJSON(data)

          },
          error:function(e){
          }
        })

        this.organizationTree = JSON.parse(JSON.stringify(this.ListtoTree[0]))
        this.hideModal()
      }
    },
    watch:{
      organizationTree:{
        handler: function(curVal,oldVal) {
          this.updateRoot = false
          let _this = this
          setTimeout(function (){
            _this.updateRoot = true
          }, 10)
        },
        deep:true  //深度watch
      }
    }
  }
</script>

<style scoped>
.all{
	 position: relative;
      min-height:100%;
      padding-bottom: 200px;
}
.organization-main:after,.organization-index-top:after{
  display:block;clear:both;content:"";visibility:hidden;height:0
}
.organization-main{
	 width:1200px;
    margin:130px auto 70px;
    font-size:14px;
    /*display:flex;*/
    /*flex-direction:row;*/
    font-size:14px;
    text-align:center;
}
.menuLeft{
  float:left;
}
.organization-index{
	background-color:#ffffff;
	width:969px;
  height:650px;
	border-radius:5px;
  padding-bottom:20px;
  margin-left:20px;
  float:right;
}
.organization-index-top{
  /*display:flex;*/
  /*flex-direction:row;*/
}
.main-top-title{
  padding-left:20px;
  padding-top:20px;
  /*width:1050px;*/
  height:100px;
  text-align: left;
  float:left;
  /*display:flex;*/
  /*flex-direction:row;*/
}
.main-top-title-img{
  width:17px;
  height:22px;
  display:inline-block;
  vertical-align: middle;
}
.main-top-title-text{
  padding-left:5px;
  font-weight:600;
  font-size:16px;
  color:#333333;
  vertical-align: middle;
  display:inline-block;
}
.main-top-change{
 padding-top:20px;
  width:150px;
  float:right;
  /*display:flex;*/
  /*flex-direction:row;*/
  font-size:14px;
  color:#0099ff;
  cursor: pointer;
}
.main-top-change img{
  width:20px;
  height:20px;
  display:inline-block;
  vertical-align: middle;
}
.main-top-change-text{
  padding-left:10px;
  display:inline-block;
  vertical-align: middle;
}
.organization-area{
  /*width:969px;*/
  padding-left:40px;
  padding-top:20px;
  padding-right:20px;
  /*overflow-x: scroll;*/
  /*overflow-y:hidden;*/
  white-space: nowrap;
  height:480px;
  scrollbar-face-color: #20a774;
  scrollbar-shadow-color: #20a774;
  scrollbar-track-color: #ccc;
  scrollbar-arrow-color: #ddd;
}
::-webkit-scrollbar-thumb{
   background-color:#018EE8;
   height:50px;
   outline-offset:-2px;
   outline:8px solid #fff;
   -webkit-border-radius:4px;

}
::-webkit-scrollbar-track-piece{
  background-color:#fff;
  -webkit-border-radius:0;
  }
::-webkit-scrollbar{
  width:8px;
  height:8px;
  }
::-webkit-scrollbar-thumb:hover{
  background-color:#FB4446;
  height:50px;
  -webkit-border-radius:4px;
  }
.organization-area-top-out{
 color:#ffffff;
 /*displaY:flex;*/
 /*flex-direction:row;*/
}
.organization-area-top-left{
  color:#ffffff;
  display:inline-block;
}
.organization-area-top{
  /*dispaly:flex;*/
  /*flex-direction:column;*/
  margin: 0 auto;
  display:block;
  width:161px;
}
.organization-area-top-leader{
  width:161px;
  height:72px;
  background-color:#eff8ff;
  color:#333333;
  /*display:flex;*/
  /*flex-direction:row;*/
  line-height:72px;
  border-radius:5px;
}
.organization-area-top-leader img{
  width:45px;
  height:45px;
  margin-top:15px;
  margin-left:10px;
  border-radius:22px;
  display: inline-block;
}
.organization-area-top-leader-name{
  font-size:16px;
  margin-left:10px;
  display: inline-block;
  vertical-align: top;
}
.organization-area-top-leader-count{
  font-size:12px;
  color:#666666;
  margin-left:10px;
  display: inline-block;
  vertical-align: top;
}
.organization-area-top-leader-line{
  width:1px;
  height:23px;
  background-color:#0099ff;
  margin-left:80px;
}
.organization-area-middle{
  min-width:1px;
  height:1px;
  background-color:#0099ff;
  margin: 0 auto;
}
.organization-area-bot{
 white-space:nowrap;

}
.organization-area-bot-index{
  /*width:161px;*/
  vertical-align: top;
  margin-right:20px;
  display:inline-block;
}
.organization-area-bot-line{
  width:1px;
  height:29px;
  margin-left:80px;
  background-color:#0099ff;
}
.organization-area-bot-depart{
  /*width:161px;*/
  height:72px;
  line-height:72px;
  color:#333333;
  background-color:#eff8ff;
  /*display:flex;*/
  /*flex-direction:row;*/
  margin-right:20px;
  border-radius:5px;
}
.organization-area-bot-depart img{
    width:45px;
  height:45px;
  border-radius:22px;
  margin-top:15px;
  margin-left:10px;
  display: inline-block;
}
.organization-area-bot-depart-name{
  font-size:16px;
  margin-left:10px;
  display: inline-block;
  vertical-align:top;
}
.organization-area-bot-depart-count{
  font-size:12px;
  color:#666666;
  margin-right:10px;
  display: inline-block;
  vertical-align:top;
}
.organization-area-bot-depart-position{
  /*width:161px;*/
  /*display:flex;*/
  /*flex-direction:row;*/
  color:#333333;
  font-size:14px;
  white-space:nowrap;
  margin-top:5px;
  margin-bottom:5px;
}
.organization-area-bot-depart-position-little{
  width:5px;
  height:5px;
  border-radius:2.5px;
  background-color:#0099ff;
  margin-top:10px;
  margin-left:5px;
  display:inline-block;
}
.organization-area-bot-depart-position-name{
  margin-left:5px;
  display:inline-block;
}
.organization-area-bot-depart-position-count{
  margin-left:5px;
  display:inline-block;
}
.modal-newNode{
  width:300px;
  height:150px;
  position:absolute;
  left:45%;
  top:20%;
  background-color:#ffffff;
  text-align: center;
  z-index:1000;
}
.modal-newNode-top{
  margin-top:30px;
}
.modal-newNode-name{
  width: 60px;
  height: 36px;
  line-height: 36px;
}
.modal-newNode-input{
  background-color: #edf6fc;
  border-radius: 18px;
  width: 160px;
  height: 32px;
  padding: 0px 10px;
  line-height: 36px;
  border: 1px solid #a4dbff;
  outline: 0 none !important;
}
.modal-newNode-buttons{
  display:inline-block;
}
.modal-newNode-button{
  width: 60px;
  height: 32px;
  display: inline-block;
  font-size: 14px;
  color: #0099ff;
  border: 1px solid #0099ff;
  border-radius: 16px;
  background-color: #fff;
  text-align: center;
  margin: 0px 20px;
  margin-top: 30px;
  cursor: pointer;
}
.modal-total{
  width: 100%;
  height: 100%;
  position: fixed;
  top: 0;
  left: 0;
  background: #000;
  z-index: 90;
  opacity: 0.2;
}
.modal{
  width:400px;
  height:300px;
  background-color:#ffffff;
  z-index:999;
  position:absolute;
  left:45%;
  top:20%;
  text-align: center;
}
.modal-top {
  width: 10px;
  height: 10px;
  margin-top: 18px;
  margin-left: 365px;
}
.modal-top-button{
  width: 22px;
  height: 22px;
  position: absolute;
  top: 8px;
  right: 9px;
  cursor: pointer;
  z-index: 1;
}
.modal-four{
  margin-top:50px;
}
.modal-add-button{
  width:160px;
  height:32px;
  margin: 0 auto;
  margin-top: 30px;
  font-size:14px;
  color:#0099ff;
  border:1px solid #0099ff;
  border-radius:16px;
  text-align:center;
  padding-top:5px;
  cursor: pointer;
}
.modal-sub-button{
  width:160px;
  height:32px;
  margin: 0 auto;
  margin-top: 30px;
  font-size:14px;
  color:#0099ff;
  border:1px solid #0099ff;
  border-radius:16px;
  text-align:center;
  padding-top:5px;
  cursor: pointer;
}
.modal-four-button{
  width:60px;
  height:32px;
  display:inline-block;
  font-size:14px;
  color:#0099ff;
  border:1px solid #0099ff;
  border-radius:16px;
  text-align:center;
  padding-top:5px;
  margin:0px 20px;
  cursor: pointer;
}
.modal-updateNode{
  text-align: left;
  padding-left: 37px;
  margin-top: 10px;
}
.modal-updateNode input{
  background-color:#edf6fc;
  border-radius:18px;
  width:160px;
  height:32px;
  padding:0px 10px;
  line-height:36px;
  border:1px solid #a4dbff;
  outline: 0 none !important;
}
.modal-NodeName{
  width:60px;
  height:36px;
  line-height:36px;
}
.modal-top-right-wrong{
  width: 30px;
  height:2px;
  background: #868686;
  transform: rotate(45deg);
}
.modal-top-right-wrong:after{
  content:'';
  display:block;
  width: 30px;
  height:2px;
  background: #868686;
  transform: rotate(-90deg);
}
</style>


Logo

前往低代码交流专区

更多推荐