微信小程序 列表多选 下拉分页 滑动切换分类

1、卡片列表

2、分页(下拉页面加载分页数据)

3、分类(页面间互不干扰,数据也不干扰)

4、左右滑动可切换分类

5、列表搜索

6、单选模式(默认单选模式,即点击卡片,回写所选数据)

7、多选模式(实现微信聊天多选效果)

  • 长按列表或点击多选,进入多选模式;
  • 切换分类或搜索则退出多选模式
  • 点击确定按钮,回写所选数据
  • 指定数据不可勾选
  • 点击复选框和卡片,实现相同效果(冒泡问题坑死人T_T,checkbox的点击事件优先级太高了,只能选后再重置)
  • 复选框改成圆形样式

        

 

JS:

const app = getApp();
Page({
  data: {
    pageSize: 10, //每页查询大小
    currPage: 1, //当前页码
    searchParam: '',
    warehouseName: null,


    nav: { //滚动导航
      list: [{
          name: '本部门仓',
          id: 0,
          currPage: 1,
          wareList: [],
          type: 'self'
        },
        {
          name: '总仓/子仓',
          id: 1,
          currPage: 1,
          wareList: [],
          type: 'total'
        },
        {
          name: '其他部门仓',
          id: 2,
          currPage: 1,
          wareList: [],
          type: 'other'
        }
      ],
      active: 0, //当前选中的导航下标
      left: 0, //滚动值
      width: 130,
      offsetLeft: 0,

      todoTipNum: 0,
    },

    curUsername: '',
    scrollHeight: 0,

    navtop: 97,
    reduceHeight: 80,


    showRadio: false,
    showRadioText: '多选',
    choseNames: [], //选中的名字列表
  },

  onLoad: function (options) {
    var that = this;
    if (options.warehouseName != null && options.warehouseName != undefined && options.warehouseName != '') {
      that.setData({
        warehouseName: options.warehouseName
      });
    }
    if (options.isall != null && options.isall == "1") {
      // 其他入库
      that.setData({
        [`nav.list`]: [{
          name: '无',
          id: 0,
          currPage: 1,
          wareList: []
        }],
        navtop: 57,
        reduceHeight: 70
      });
    }
    wx.getSystemInfo({
      success: function (res) {
        //console.log('系统信息:', res);
        that.setData({
          windowWidth: res.windowWidth,
          [`nav.width`]: res.windowWidth / 3
        })
      }
    });

    that.getTaskList(1, 1);

    let res = wx.getSystemInfoSync();
    that.setData({
      scrollHeight: res.windowHeight - that.data.reduceHeight
    });
  },

  onShow: function () {},

  //点击导航 - 选中监听
  select: function (e) {
    this.changetab(e.currentTarget.dataset.idx);
  },

  //滚动页面,切换导航
  bindchange(e) {
    this.changetab(e.detail.current);
  },

  changetab: function (idx) {
    let _this = this,
      nav = this.data.nav,
      // idx = e.currentTarget.dataset.idx,
      windowWidth = this.data.windowWidth,
      width = windowWidth / 3,
      offsetLeft = this.data.nav.offsetLeft;
    
    _this.cancelRadio();
    if (offsetLeft < windowWidth) {
      // nav.left = width - windowWidth + offsetLeft;
      nav.offsetLeft = width * idx;
    } else {
      nav.offsetLeft = width * idx - windowWidth;
    }
    nav.active = idx;
    _this.setData({
      nav: nav,
    })
  },

  /**
   * 查询
   */
  onSearch: function () {
    var that = this;
    that.cancelRadio();
    that.getTaskList(1, 1);
  },


  getTaskList: function (isfirst, notshowtip) {
    var that = this;
    if (isfirst == 1) {
      that.data.nav.list.forEach((val, key) => {
        that.setData({
          [`nav.list[${key}].currPage`]: 1
        });
      })
      that.data.nav.list.forEach((val, key) => {
        let notshow = key == 0 ? 1 : -1;
        that.getTaskListByType(isfirst, notshow, key);
      })
    } else {
      that.getTaskListByType(isfirst, notshowtip, that.data.nav.active);
    }
  },

  /**
   * 列表
   */
  getTaskListByType: function (isfirst, notshowtip, querytab) {
    var that = this;
    var preList = that.data.nav.list[querytab].wareList;
    if (isfirst == 1) {
      preList = [];
      that.setData({
        [`nav.list[${querytab}].wareList`]: []
      });
    }
    if (notshowtip !== -1) {
      wx.showLoading({
        title: '查询中,请稍候',
        mask: true
      })
    }
    let param = {
      page: that.data.nav.list[querytab].currPage + '',
      size: that.data.pageSize + '',
      orgname: app.globalData.comName,
      username: app.globalData.userName,
    }
    if (that.data.searchParam != null && that.data.searchParam.length > 0) {
      param.name = that.data.searchParam;
    }
    if (!app.util.Empty(that.data.nav.list[querytab].type)) {
      param.type = that.data.nav.list[querytab].type;
    }

    app.globalData.$wsdl.ncWsdl('XXXXXXX', 'xxxxx', param).then(res => {
      // console.log('xxxxx 返回', res);

      if (notshowtip !== -1) {
        wx.hideLoading();
      }
      if (res.code == '1' && res.data) {
        if (res.data.length < that.data.pageSize) { // 分页结束
          // 停止上拉查询
          that.setData({
            [`nav.list[${querytab}].stopQuery`]: 1,
          });
          if (res.data.length == 0) {
            // 恢复页码
            let cp = that.data.nav.list[querytab].currPage;
            if (cp > 1) {
              --cp;
              that.setData({
                [`nav.list[${querytab}].currPage`]: cp
              });
            }
            return;
          }
        }

        var tempItems = [];
        res.data.forEach((val, key) => {
          if (val.materialtype == '' || val.materialtype == '暂无' || val.materialtype == '无') {
            val.materialtype = null;
          }
          tempItems.push(val);
        })

        that.setData({
          [`nav.list[${querytab}].wareList`]: preList.concat(app.globalData.$wsdl.oa2wx(tempItems, {
            pk_material: 'wareid',
            materialname: 'warename',
            code: 'warecode',
            materialtype: 'model',
            materialspec: 'specification',
            whname: 'from',
            nonhandnum: 'sum',
            jldw: 'unit',
            racks: 'location'
          })),
        });

        //分页加载后会删掉已选,此处重新设置已选项
        that.data.nav.list.forEach((pval, pkey) => {
          pval.wareList.forEach((val, key) => {
            val.checked=val.realchecked;
            that.setData({
              [`nav.list[${pkey}].wareList[${key}]`]: val,
            });
          })
        });
      } else {
        wx.showToast({
          title: '物料列表接口调用失败:' + res.msg,
          icon: 'none',
          duration: 3000
        })
      }
    })
  },

  /**
   * 查询框输入事件监听
   * @param {*} e 
   */
  onSearchParamInput(e) {
    this.setData({
      searchParam: e.detail.value
    })
  },

  // 点击键盘上的搜索
  bindconfirm: function (e) {
    var that = this;
    that.onSearch();
  },

  /**
   * 查询框输入事件监听
   * @param {*} e 
   */
  onSearchParamInput(e) {
    this.setData({
      searchParam: e.detail.value
    })
  },

  selware: function (e) {
    var that = this;
    let item = e.currentTarget.dataset.item;
    let pass = true;
    if (this.data.warehouseName != null && this.data.warehouseName !== item.from) {
      wx.showToast({
        title: '已选定仓库,不可选其它仓库物料',
        icon: 'none',
        duration: 1500,
        mask: true
      })
      pass = false;
    } else if (item.sum == 0) {
      wx.showToast({
        title: '当前库存为0',
        icon: 'none',
        duration: 1500,
        mask: true
      })
      pass = false;
    }
    if (!pass) {
      if (!that.data.showRadio) {
        return;
      } else {
        if (e.fromcheck == 1) {
          that.data.nav.list.forEach((pval, pkey) => {
            pval.wareList.forEach((val, key) => {
              if (val.wareid == item.wareid) {
                val.realchecked = false;
                val.checked = false;
                that.setData({
                  [`nav.list[${pkey}].wareList[${key}]`]: val
                });
              }
            })
          });
        }
        return;
      }
    }
    if (that.data.showRadio) { //多选时
      that.triggerCheckboxChange(item);
    } else {
      that.backEmit([item]);
    }
  },

  loadMore: function () {
    var that = this;
    if (that.data.nav.list[that.data.nav.active].stopQuery == 1) {
      return;
    }

    var page = that.data.nav.list[that.data.nav.active].currPage + 1;
    this.setData({
      [`nav.list[${that.data.nav.active}].currPage`]: page,
    });
    this.getTaskList();
  },
  
  //标签长按事件逻辑
  longPress: function (e) { 
    var that = this;
    if (!that.data.showRadio) {
      that.showCheckRadio();
    }
  },

  //取消多选模式
  cancelRadio: function (e) { 
    var that = this;
    if (that.data.showRadio) {
      that.showCheckRadio();
    }
  },
  

  /**
   * 重置
   */
  resetCheckRadio: function () {
    var that = this;
    that.data.nav.list.forEach((pval, pkey) => {
      pval.wareList.forEach((val, key) => {
        // if (pval.realchecked) {
          val.checked = false;
          val.realchecked = false;
          that.setData({
            [`nav.list[${pkey}].wareList[${key}]`]: val,
          });
        // }
      })
    });
    that.setData({
      choseNames:[]
    });
  },

  triggerCheckboxChange: function(item) {
    var that = this;

    that.data.nav.list.forEach((pval, pkey) => {
      pval.wareList.forEach((val, key) => {
        if (val.wareid == item.wareid) {
          val.realchecked=!val.checked;
          val.checked=!val.checked;
          that.setData({
            [`nav.list[${pkey}].wareList[${key}]`]: val
          });
        }
      })
    });

    // 有则删除,无则添加
    let newChoseNames=that.data.choseNames;
    let index = newChoseNames.indexOf(item.wareid);
    if(index>-1){
      newChoseNames.splice(index, 1);
    } else {
      newChoseNames.push(item.wareid);
    }
    this.setData({
      choseNames: newChoseNames, //单个选中的值
    });
  },

  // 单选
  changeRadio: function (e) {
    var that = this;
    console.log(e.detail.value);
    this.setData({
      choseNames: e.detail.value, //单个选中的值
    });
    var values = e.detail.value;
    that.data.nav.list.forEach((pval, pkey) => {
      pval.wareList.forEach((val, key) => {
        var itemCheck = false;
        for (var i = 0; i < values.length; i++) {
          if (val.wareid == values[i]) {
            itemCheck = true;
            break
          }
        }
        that.setData({
          [`nav.list[${pkey}].wareList[${key}].realchecked`]: itemCheck
        });
      })
    });
  },

  /**
   * 多选按钮点击
   * @param {} params 
   */
  showCheckRadio: function (params) {
    var that = this;
    if (that.data.showRadio) {
      that.setData({
        showRadio: false,
        showRadioText: '多选'
      });
      that.resetCheckRadio();
    } else {
      that.setData({
        showRadio: true,
        showRadioText: '取消'
      });
    }
  },


  // 多选确定
  comfirmsel(e) {
    var that = this;
    let selItems = [];
    if (that.data.choseNames.length === 0) {
      return wx.showToast({
        title: '请选择',
        icon: 'none'
      })
    }

    that.data.nav.list[that.data.nav.active].wareList.forEach((val, key) => {
      for (var i = 0; i < that.data.choseNames.length; i++) {
        if (val.wareid == that.data.choseNames[i]) {
          selItems.push(val);
          break
        }
      }
    })
    that.backEmit(selItems);
  },

  backEmit : function(selItems){
    //返回并回写上一页面
    let pages = getCurrentPages();
    let prePage = pages[pages.length - 2];
    prePage.emit(selItems)
    wx.navigateBack({
      delta: 1
    })
  },

  bindcheck : function(e){
    e.fromcheck=1;
    this.selware(e)
  },
})

WXML:

<!-- <view> -->
<view class="cu-bar bg-white search " style="height: 100rpx;width: 100%;position: fixed;top: 0;z-index: 998;padding-bottom: 10px;">
  <view class="search-form round">
    <text class="cuIcon-search"></text>
    <input value="{{ searchParam }}" confirm-type="search" bindconfirm="bindconfirm" bindinput="onSearchParamInput" placeholder="搜索添加物料" type="text">
    </input>
    <button class="cu-btn  cu-btn-lamp icon shadow" style='width:15vw;background-color: #4BCCB9;color: white;' bindtap="onSearch">查询</button>
  </view>
</view>

<view class="top_nav" wx:if="{{nav.list.length==3}}">
  <!-- <view class="numtip" wx:if="{{todoTipNum!=0}}">{{todoTipNum}}</view> -->
  <view class="scroll_item scroll_item{{index}} {{nav.active == index ? 'active' : ''}}" data-idx="{{index}}" wx:for="{{nav.list}}" wx:key="id" bindtap='select' style="width: 100%;text-align: center;">
    {{item.name}}
  </view>
  <view class="sub" style="width:{{nav.width}}px; left:{{nav.offsetLeft}}px;">
    <view style="background-color: #4BCCB9;margin: 0 20px;height: 100%;">
    </view>
  </view>
</view>

<view class="content" style="height:100%;font-family: '微软雅黑';top:{{navtop}}px">
  <swiper current="{{nav.active}}" style='height:100%' bindchange="bindchange">
    <swiper-item wx:for="{{nav.list}}" item-id="{{item.id}}" wx:key="id">
      <scroll-view scroll-y="true" style="height:{{scrollHeight}}px;" bindscrolltolower="loadMore">
        <!-- <view catchtap="donothing"> -->
        <checkbox-group data-itemid="{{item.wareid}}" style="{{showRadio?'display: block;':''}}">
          <view wx:for-items='{{item.wareList}}' bindlongpress="longPress" wx:for-index="index" wx:key="index" data-item="{{item}}" data-id='{{item.wareid}}' data-index="{{index}}" bindtap="selware" class="cu-card dynamic" style="padding: 10rpx 20rpx 8rpx 20rpx;display: flex;">
            <view wx:if="{{showRadio}}" style="height: 180rpx;display: flex;align-items: center;padding-right: 10rpx;">
              <checkbox value="{{item.wareid}}" checked="{{item.checked}}" data-item="{{item}}" catchtap="bindcheck"></checkbox>
            </view>
            <view data-item="{{item}}" style="width: 100%;border-radius: 20rpx;padding: 24rpx;padding-bottom: 14rpx;display: flex;{{(warehouseName !==null&&warehouseName !== item.from)||item.sum==0?'background-color: #ddd;color: #999':'background-color: white;color: black'}}">
              <view style="width: 100%;">
                <view style="font-size: 16px;font-weight: bold;margin-bottom: 10rpx;">
                  <!-- {{item.name!==null&&item.name!=='undefined'?item.name+' ':''}} -->
                  编号:{{item.warecode}}
                </view>
                <view style="font-size: 15px;margin-bottom: 10rpx;">
                  物品:{{item.warename}} {{item.model!=null?item.model:''}} {{item.specification!=null?item.specification:''}}
                </view>
                <view style="font-size: 15px;margin-bottom: 10rpx;">
                  库存:{{item.from}}({{item.location}}) {{item.sum}}{{item.unit}}
                </view>
              </view>
            </view>
          </view>

        </checkbox-group>
        <!-- </view> -->
      </scroll-view>
    </swiper-item>
  </swiper>
</view>

<button wx:if="{{showRadio}}" class="round shadow cu-btn" bindtap='comfirmsel' style="background-color: #4BCCB9;color: white;width: 100px;position: fixed;bottom: 15px;right: {{showRadio?'30vw':'6vw'}};z-index: 999;font-weight: 500;font-size: 16px;">确定{{choseNames.length>0?('('+choseNames.length+')'):''}}</button>
<button class=" round shadow cu-btn" bindtap='showCheckRadio' style="background-color: {{showRadio?'#aaa':'#4BCCB9'}};color: {{showRadio?'#fff':'#fff'}};width: 90px;position: fixed;bottom: 15px;right: 5vw;z-index: 999;font-weight: 500;font-size: 16px;"><text decode="true">&nbsp;{{showRadioText}}</text> </button>

WXSS:

.top_nav {
  width: 100%;
  height: 82rpx;
  line-height: 80rpx;
  border-bottom: 1px olid #ddd;
  background-color: #FFF;
  position: fixed;
  top: 50px;
  left: 0;
  z-index: 999;
  display: flex;
  justify-content: space-around;
}

.top_nav .scroll_list {
  height: 82rpx;
  white-space: nowrap;
}

.top_nav .scroll_item {
  display: inline-block;
  padding: 0 10px;
  font-size: 14px;
  vertical-align: top;
}

.top_nav .scroll_item.active {
  color: #4BCCB9;
}

.top_nav .sub {
  /* width: 56rpx; */
  height: 4rpx;
  position: absolute;
  top: 78rpx;
  transition: left .5s;
}

/* .content{margin-top: 84rpx; line-height: 80rpx; font-size: 28rpx;width: 100%;} */
.content {
  position: fixed;
  top: 183rpx;
  font-size: 28rpx;
  width: 100%;
}

/* .swiper_box{ border: 1px solid red;height: 90%;margin: 0 20rpx;} */

.map_container {
  height: 40vh;
  width: 100vw;
}

.map {
  height: 100%;
  width: 100%;
}

.weui-cell__hd {
  font-size: 0
}

.weui-cell__hd image {
  margin-right: 16px;
  vertical-align: middle;
  width: 20px;
  height: 20px
}

.minicell {
  padding: 30rpx 16rpx;
}

.text_too_long {
  width: 500rpx;
  word-break: break-all;
}

.text_too_long480 {
  width: 480rpx;
  word-break: break-all;
  font-size: 15px;
}

.numtip {

  background-color: red;
  position: absolute;
  top: 0p;
  left: 160rpx;
  width: fit-content;
  height: 36rpx;
  border-radius: 2em;
  display: flex;
  justify-content: center;
  align-items: center;
  color: white;
  font-size: 12px;

  padding: 0 12rpx;
}

.btnview {
  position: fixed;
  bottom: 0;
  height: 100rpx;
  line-height: 100rpx;
  background-color: white;
  width: 100%;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 999;
}

.newbtn {
  width: 90%;
  border-radius: 50px;
  height: 70rpx;
  line-height: 70rpx;
  background-color: #4BCCB9;
  color: white;
}



checkbox .wx-checkbox-input {
  width: 46rpx;
  height: 46rpx;
  border-radius: 50%;
}

/*checkbox选中后样式  */
checkbox .wx-checkbox-input.wx-checkbox-input-checked {
  background: #fed6e3;
}

/*checkbox选中后图标样式  */
checkbox .wx-checkbox-input.wx-checkbox-input-checked::before {
  width: 40rpx;
  height: 40rpx;
  line-height: 28rpx;
  text-align: center;
  font-size: 18rpx;
  color: #fff;
  background: transparent;
  transform: translate(-50%, -50%) scale(1);
  -webkit-transform: translate(-50%, -50%) scale(1);
}

样式引用:

         GitHub - weilanwl/coloruicss: 鲜亮的高饱和色彩,专注视觉的小程序组件库

如果我的文章帮助到了你,点赞,评论,关注下吧

谢谢,欢迎多多交流!

——tanly

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值