微信小程序树状多选弹出框

前言

根据单位项目的需要,需要开发一个树状的部门人物选择,无限层级的。查看了半天发现小程序官方是没有相关组件的,只好自己写一个自定义组件了。
在网上找了好久,找到了两个感觉能用的,给了我很多启发。
微信小程序-树形菜单替代方案
微信小程序:树形菜单
但是两个代码都不全,所以自己结合两位前辈整合了一份自己的。

qq录屏20200915150020000000-000019(2).gif

话不多说了,上代码吧。
checkbox-view.wxml

选择人员


    
    
        
            取消
            确定
           
        
      
        
          
          {{ rootText }} 
        
        
          
          {{ current.DEPT_NAME }}
        
      
      
        
          
            
              
                {{item.REAL_NAME}}
              
            
          
        
        
          
            {{ item.DEPT_NAME }}
            
          
        
      
        
    

checkbox-view.js

Component({
  properties:{
    list: {
      type: Array,
      value :[],
      observer() {
        this.init();
      }
    },
    rootText:{
      type: String,
      value : 'root'
    },
    title: {
      type: String,
      value: 'key'
    },
    children:{
      type: String,
      value: 'children'
    },
    content:{
      type: String,
      value: 'userlist'
    },
    selected:{
      type: Array,
      value: []
    }
  },
  data:{
    showPicker: false,
        firstShow: false,
    outlist: [],
    path: [],
    current: {},
    isRoot: true,
    selected: []
  },
  methods:{
    // 展示picker
        showPicker() {
            if (!this.data.firstShow) {
                this.setData({
                    firstShow: true
                })
            }
            this.setData({
                showPicker: true,
      })
    },
    // 隐藏picker
        hidePicker() {
            this.setData({
                showPicker: false
            })
        },
        // 取消按钮事件
        cancal() {
            this.hidePicker();
    },
    // 确定按钮事件
        sure() {
            this.hidePicker();
            this.triggerEvent('click', {
                selected: this.data.selected
      });
      // this.triggerEvent('click', { value: user });
        },
    init(){
      this.data.selected = this.properties.selected;
      this.toRoot();
    },
    toRoot(){
      // console.log(this.properties.list)
      this.properties.list.forEach((item)=>{
        item.itemShow='';
        item.itemTrans='';
      })
      this.setData({
        outlist: this.properties.list,
        current:{},
        isRoot: true,
        path:[]
      })
    },
    intoNextPath(e){
      var caninto = e.currentTarget.dataset.caninto;
      // console.log(e.currentTarget.dataset)
      if(!caninto){
        return
      }
      var item = e.currentTarget.dataset.item;
      var index = e.currentTarget.dataset.index;
      var path = this.data.path;
      path.push(index);
      item = this.initUser(item)
      this.setData({
        path: path,
        current: item,
        outlist: item[this.properties.children],
        isRoot: false
      });
      this.scrollTop();
    },
    backLastPath(e){
      var path = this.data.path;
      var floor = path.length;
      if (floor <= 1){
        this.toRoot()
      }else{
        path.pop();
        console.log('back:' + path)
        var list = this.properties.list;
        var item = {};
        path.forEach((index) =>{
          item = list[index];
          list = item[this.properties.children]
        })
        var isRoot = false;
        if (this.data.path.length <= 0){
          isRoot = true;
        }
        // console.log(item)
        item = this.initUser(item);
        this.setData({
          path: path,
          current: item,
          outlist: list,
          isRoot: isRoot
        })
      }
      this.scrollTop();
    },
    openContent(e){
      var index = e.currentTarget.dataset.index;
      var itemShow = this.data.outlist[index].itemShow
      if (itemShow == null || itemShow == ''){
        this.setData({
          ['outlist[' + index + '].itemShow']: 'item-show',
          ['outlist[' + index + '].itemTrans']:'item-trans90'
        })
      }else{
        this.setData({
          ['outlist[' + index + '].itemShow']: '',
          ['outlist[' + index + '].itemTrans']: ''
        })
      }
    },
    checkboxChange(e) {
      let checkarr = this.data.selected
      const items = this.data.current
      const values = e.detail.value
      for (let i = 0, lenI = items.userlist.length; i < lenI; ++i) {
        items.userlist[i].checked = false
        if(checkarr.indexOf(items.userlist[i].USER_NAME) > -1) {
          checkarr.splice(checkarr.indexOf(items.userlist[i].USER_NAME), 1)
        }
        for (let j = 0, lenJ = values.length; j < lenJ; ++j) {
          if (items.userlist[i].USER_NAME === values[j]) {
            items.userlist[i].checked = true
            if(!checkarr.includes(values[j])) {
              checkarr.push(values[j])
            }
            break
          }
        }
      }
      // console.log(checkarr)
      this.setData({
        current: items,
        selected: checkarr
      })
    },
    initUser(dept){
      // console.log(dept)
      var selected = this.data.selected;
      var userlist = dept.userlist;
      userlist.forEach((user) => {
        user.checked = false;
        for(let j = 0, lenJ = selected.length; j < lenJ; ++j) {
          if (selected[j] == user.USER_NAME) {
            user.checked = true;
          }
        }
      })
      dept.userlist = userlist
      return dept
    },
    scrollTop(){
      setTimeout(function () {
        wx.pageScrollTo({
          scrollTop: 0,
          duration: 300
        })
      }.bind(this), 200)
    }
  }
})

checkbox-view.json

{
  "component": true,
  "usingComponents": {
    "mp-icon": "/miniprogram_npm/weui-miniprogram/icon/icon"
  }
}

checkbox-view.wxss

page {
  height: 100%;
  width: 100%;
}

.showPicker {
  width: 100%;
  height: 80rpx;
  line-height: 80rpx;
  font-size: 30rpx;
  background-color: paleturquoise;
  text-align: center;
}
.showtext{
  font-size: 32rpx;
  color: rgb(32, 154, 224);
}

.shade-container {
  position: fixed;
  height: 100%;
  width: 100%;
  top: 0;
  right: -200%;
  display: flex;
  justify-content: space-around;
  background-color: rgba(0, 0, 0, 0.5);
  transform: translateX(-200%);
  transition: all 0.5s ease;
  z-index: 9999;
}

.hide-container {
  position: fixed;
  height: 100%;
  width: 100%;
  top: 0;
  right: -200%;
  z-index: 9999;
  display: flex;
  justify-content: space-between;
  transform: translateX(100%);
  transition: all 0.5s ease-in;
}

.left-shade {
  width: 30%;
  height: 100%;
}

.right-choose {
  width: 70%;
  height: 100%;
  background-color: #fff;
  padding: 40rpx;
}

.picker-container {
  height: calc(100% - 200rpx);
  overflow-x: hidden;
  overflow-y: scroll;
}

.picker-container::-webkit-scrollbar {
  display: none;
}

.title{
  font-size: 36rpx;
  font-weight: bold;
  border-bottom: 1px solid #dddee1
}
.tran-icon{
  color: #5cadff;
}
.padder{
  padding: 10px;
}
.padder-l{
  padding-left: 10px; 
}
.padder-l-sm{
  padding-left: 5px; 
}
.padder-l-md{
  padding-left: 15rpx; 
}
.padder-r-md{
  padding-right: 15rpx; 
}
.cell-group{
  border: 0px !important;
  position: relative;
}
.left_icon{
  position: absolute;
  top: 18rpx;
  left: 0;
}
.left_text{
  margin-left: 45rpx;
}
.b-t{
  border-top: 1px solid #e9eaec!important;
}
.cell{
  padding: 20rpx 0;
  border-top: 1px solid #e9eaec;
  position: relative;
}
.cell_righticon{
  position: absolute;
  right: 15rpx;
  top: 15rpx;
}
.item-group .item:last-child{
  border: 0px !important;
}
.item{
  padding: 15px 0;
  border-bottom: 1px solid #f8f8f9 !important;
}
.item-show{
  display: block;
}
.item-trans90{
  transform:rotate(90deg);
  -ms-transform:rotate(90deg); /* Internet Explorer */
  -moz-transform:rotate(90deg); /* Firefox */
  -webkit-transform:rotate(90deg); /* Safari 和 Chrome */
  -o-transform:rotate(90deg); /* Opera */
}

.button-container {
  width: 100%;
  height: 80rpx;
  display: flex;
  justify-content: space-between;
  font-size: 24rpx;
  text-align: center;
  border-bottom: 2rpx solid #eaeaea;
}

.cancal {
  width: 100rpx;
  height: 40rpx;
  line-height: 40rpx;
  border: 2rpx solid #ddd;
  border-radius: 8rpx;
}

.sure {
  width: 100rpx;
  height: 40rpx;
  line-height: 40rpx;
  border: 2rpx solid rgb(132, 235, 132);
  border-radius: 8rpx;
}

上面就是自定义组件的代码。基本拿去改一改就能用
引用的地方
index.wxml


    
      *代打人员:
      
        
      
    
    
      
        {{retpeop}}
      
    
  

index.json

{
  "usingComponents": {
        "checkbox-view": "../../../Components/checkbox-view/checkbox-view"
    }
}

index.js

// 点击确定事件
choose(e) {
    let retpeop = this.setoptuser(this.data.peopleList, e.detail.selected)
    retpeop = retpeop.join(',')
    this.setData({
      selected: e.detail.selected,
      retpeop: retpeop
        })
  },
  setoptuser(arrData, selected) {
    let retpeop = []
    for(let i = 0; i < arrData.length; i++) {
      if(arrData[i].userlist.length > 0) {
        arrData[i].userlist.forEach((item) => {
          for(let j = 0; j < selected.length; j++) {
            if(item.USER_NAME == selected[j]) {
              retpeop.push(item.REAL_NAME)
            }
          }
        })
      }
      if(arrData[i].children) {
        this.setoptuser(arrData[i].children, selected)
      }
    }
    return retpeop
  },

数据自己去和后台要吧。我这里大概是这样的数据。


1600154583(1).jpg

好了,去试试吧。欢迎交流。

你可能感兴趣的:(微信小程序树状多选弹出框)