天天看点

小程序的tab切换和上拉加载下拉刷新swiper swiper-item scroll-view

<view>
  <!-- 搜索框 -->
    <view class="inp-box">
        <van-search value="{{ searchVal }}" placeholder="请输入名称" use-action-slot bind:change="searchInp">
            <view style="color: #ff6700;" slot="action" bind:tap="searchClick">搜索</view>
        </van-search>
    </view>
  <!-- tab切换 -->
    <view class="node-tab">
        <view class="tab-item {{currentTab == 0 ? 'active' : ''}}" data-current="0" bindtap="changeNav">全部</view>
        <view class="tab-item {{currentTab == 1 ? 'active' : ''}}" data-current="1" bindtap="changeNav">我参与</view>
        <view class="tab-item {{currentTab == 2 ? 'active' : ''}}" data-current="2" bindtap="changeNav">我发布</view>
    </view>
    <swiper class="tab-content" current="{{currentTab}}" duration="300" bindchange="changeTab" style="height:{{winHeight}}rpx">
        <!-- 全部 -->
        <swiper-item>
            <scroll-view scroll-y="true" class="new-list-box" bindscrolltolower="allLoadMore" scroll-top='{{scrollTop}}' scroll-with-animation refresher-enabled="{{true}}" refresher-threshold="{{80}}" refresher-default-style="white" refresher-background="#ff6700" refresher-triggered="{{triggered}}" bindrefresherrefresh="onAllRefresh">
                <block wx:if="{{allTabList.length > 0}}">
                    <view class="new-list-item" wx:for="{{allTabList}}" wx:key="index">
                        <view class="item-content" data-posid="{{item.id}}" catchtap="goDetails">
                            <view class="content-left">
                                <view class="dis-flex-between">
                                    <view class="content-title">{{item.name}}</view>
                                    <view style="min-width: 130rpx;">
                                        <view class="list-tag-item">{{item.status}}</view>
                                    </view>
                                </view>
                                <view class="content-des elli_psis">{{item.remark}}</view>
                            </view>
                        </view>
                        <view class="item-tag dis-flex-between">
                            <view class="content-deadline">发起人:{{item.providerName}}</view>
                            <view class="content-deadline">总金额:{{item.amount}}</view>
                            <view class="content-deadline">共{{item.count || 0}}人参与</view>
                            <!-- participationState; //0 为不可参与,隐藏按钮,1为可以参与,2为过期或者未到期置灰 -->
                            <view wx:if="{{item.participationState === 1}}" class="content-right" data-posid="{{item.id}}" catchtap="joinTask">参与任务</view>
                            <view wx:if="{{item.participationState === 2}}" class="content-right content-right-is-no">参与任务</view>
                        </view>
                    </view>
                </block>
                <view wx:if="{{allTabList.length >= recordCount}}" class="no-data-txt" bindtap="pScrollTo">没有更多数据了</view>
            </scroll-view>
        </swiper-item>
        <!-- 我参与 -->
        <swiper-item>
            <scroll-view scroll-y="true" class="new-list-box" bindscrolltolower="allLoadMore" scroll-top='{{scrollTop}}' scroll-with-animation refresher-enabled="{{true}}" refresher-threshold="{{80}}" refresher-default-style="white" refresher-background="#ff6700" refresher-triggered="{{triggered}}" bindrefresherrefresh="onAllRefresh">
                <block wx:if="{{myAttendList.length > 0}}">
                    <view class="new-list-item" wx:for="{{myAttendList}}" wx:key="index">
                        <view class="item-content" data-posid="{{item.id}}" catchtap="toNodeDetails">
                            <view class="content-left">
                                <view class="dis-flex-between">
                                    <view class="content-title">{{item.name}}</view>
                                    <view style="min-width: 130rpx;">
                                        <view class="list-tag-item">{{item.status}}</view>
                                    </view>
                                </view>
                                <view class="content-des elli_psis">{{item.remark}}</view>
                            </view>
                        </view>
                        <view class="item-tag dis-flex-between">
                            <view class="content-deadline">发起人:{{item.providerName}}</view>
                            <view class="content-deadline">总金额:{{item.amount}}</view>
                            <view class="content-deadline">共{{item.count || 0}}人参与</view>
                        </view>
                    </view>
                </block>
                <view wx:if="{{myAttendList.length >= recordCount}}" class="no-data-txt" bindtap="pScrollTo">没有更多数据了</view>
            </scroll-view>
        </swiper-item>
        <!-- 我发布 -->
        <swiper-item>
            <scroll-view scroll-y="true" class="new-list-box" bindscrolltolower="allLoadMore" scroll-top='{{scrollTop}}' scroll-with-animation refresher-enabled="{{true}}" refresher-threshold="{{80}}" refresher-default-style="white" refresher-background="#ff6700" refresher-triggered="{{triggered}}" bindrefresherrefresh="onAllRefresh">
                <block wx:if="{{myPublishList.length > 0}}">
                    <view class="new-list-item" wx:for="{{myPublishList}}" wx:key="index">
                        <view class="item-content" data-posid="{{item.id}}" catchtap="toNodeDetails">
                            <view class="content-left">
                                <view class="dis-flex-between">
                                    <view class="content-title">{{item.name}}</view>
                                    <view style="min-width: 130rpx;">
                                        <view class="list-tag-item">{{item.status}}</view>
                                    </view>
                                </view>
                                <view class="content-des elli_psis">{{item.remark}}</view>
                            </view>
                        </view>
                        <view class="item-tag dis-flex-between">
                            <view class="content-deadline">发起人:{{item.providerName}}</view>
                            <view class="content-deadline">总金额:{{item.amount}}</view>
                            <view class="content-deadline">共{{item.count || 0}}人参与</view>
                            <view wx:if="{{item.participationState === 1}}" class="content-right" data-posid="{{item.id}}" catchtap="joinTask">参与任务</view>
                            <view wx:if="{{item.participationState === 2}}" class="content-right content-right-is-no">参与任务</view>
                        </view>
                    </view>
                </block>
                <view wx:if="{{myPublishList.length >= recordCount}}" class="no-data-txt" bindtap="pScrollTo">没有更多数据了</view>
            </scroll-view>
        </swiper-item>
    </swiper>

</view>      
let app = getApp();
let startPoint;
let tabName = ['allTabList', 'myAttendList', 'myPublishList']; // 列表名称
Page({
  onShow() {
    this.getTabBar().init();
  },
  data: {
    triggered: false,
    searchVal: '', // 搜索
    winHeight: "",// 窗口高度
    currentTab: 0, // 当前所在滑块的 index
    allTabList:[], // 全部
    myAttendList:[], // 我参与
    myPublishList:[], // 我发布
    scrollTop: 0, // 设置竖向滚动条位置
    windowHeight: '',
    windowWidth: '',
    recordCount: 0, //列表总条数
    pageNo: 1 //页码
  },
  onLoad: function(options) {
    // 计算drawer高度,占满window
    let that = this;
    //  高度自适应
    wx.getSystemInfo({
      success: function (res) {
        let clientHeight = res.windowHeight,
          clientWidth = res.windowWidth,
          rpxR = 750 / clientWidth;
        let calc = (clientHeight - 50 - 54) * rpxR - 130;
        // console.log(calc)
        that.setData({
          windowHeight:  res.windowHeight,
          windowWidth:  res.windowWidth,
          winHeight: calc
        });
      }
    });
    this._requestPageList(true);
  },
  // 参数
  _requestPageList(isLoadMore = false, callback) {
    // isLoadMore 为true是上拉加载,不需要置空数组
    if(!isLoadMore){
      this.setData({
        allTabList:[], // 全部
        myAttendList:[], // 我参与
        myPublishList:[], // 我发布
        pageNo: 1
      });
    }
    let opt = {
      name: this.data.searchVal,
      number: "", //任务编号
      searchType: this.data.currentTab == 0 ? null : this.data.currentTab * 2,  //  null 全部 2我参与的 4我发布的
    }
    this._requestPageListCom("virtualTaskList", opt, callback);
  },
  // 列表接口
  _requestPageListCom(url, params, callback) {
    let opt = Object.assign({}, params, {
      pageData: {
        pageNo: this.data.pageNo,
        pageSize: 10
      },
    })
    app.$request.post(app.$config[url], opt).then(res => {
      if (res.returnResult === 200) {
        let oldList = [];
        if(this.data.currentTab == 0){
          oldList = this.data.allTabList;
        } else if(this.data.currentTab == 1){
          oldList = this.data.myAttendList;
        } else if(this.data.currentTab == 2){
          oldList = this.data.myPublishList;
        }
        const newGoodsList = res.returnData.data
        const allData = [...oldList, ...newGoodsList]
        console.log(allData,'allData')
        let newData = {}; // 新变更数据
        for(let i in allData){
          newData[`${tabName[this.data.currentTab]}[${i}]`] = allData[i];
        }
        this.setData(newData); // 赋值列表数据
        console.log(newData,'newData')
        this.setData({
          recordCount: res.returnData.recordCount
        })
        if(callback && typeof callback === 'function'){
          callback()
        }
      }
    })
  },
  // 输入搜索 event.detail 为当前输入的值
  searchInp(e) {
    this.setData({
      searchVal: e.detail
    })
  },
  // 搜索
  searchClick(){
    this._requestPageList();
  },
  // tip: 如果在 bindchange 的事件回调函数中使用 setData 改变 current 值,则有可能导致 setData 被不停地调用,
  // 因而通常情况下请在改变 current 值前检测 source 字段来判断是否是由于用户触摸引起 event.detail = {current, source}
  // 滚动切换标签样式
  changeTab: function (e) {
    console.log(e,e.detail.current,'e') // 0 1 2 
    this.setData({
      currentTab: e.detail.current
    });
    this._requestPageList();
  },
  // 点击标题切换当前页时改变样式
  changeNav: function (e) {
    let currentIndex = e.target.dataset.current;
    if (this.data.currentTaB == currentIndex) {
      return false;
    } else {
      this.setData({
        currentTab: currentIndex
      })
    }
  },
  // 参与任务
  joinTask:function(events){
    let opt = {
      id: events.currentTarget.dataset.posid
    }
    app.$request.post(app.$config.virtualTaskCheckIn, opt).then(res => {
      if (res.returnResult === 200) {
        wx.showToast({
          title: '参与成功',
          icon: 'none',
          duration: 3000
        })
        // this._requestPageList();
      }
    })
  },
  // 详情
  goDetails:function(events){
    let meetId = events.currentTarget.dataset.posid;
    wx.navigateTo({
      url: `../../taskDes/taskDes?id=${meetId}`
    })
  },
  // 上拉加载  滚动到底部/右边时触发
  allLoadMore(e){
    let _self = this;
    if (this._allLoadMore || _self.data[tabName[this.data.currentTab]].length >= _self.data.recordCount || _self.data.recordCount === 0) return
    this._allLoadMore = true;
    this.setData({
      pageNo: ++_self.data.pageNo
    });
    this._requestPageList(true, () => {
      _self._allLoadMore = false;
    });
  },
  // 下拉刷新接口
  onAllRefresh() {
    if (this._allFreshing) return
    this._allFreshing = true
    this._requestPageList(false, () => {
      // 当处理完数据刷新后,wx.stopPullDownRefresh可以停止当前页面的下拉刷新
      this.setData({
        triggered: false
      })
      this._allFreshing = false
    });
  },
  pScrollTo(){
    // 返回顶部
    this.setData({
      scrollTop:0
    });
  }
})      
{
  "navigationBarBackgroundColor": "#ff6700",
  "navigationBarTextStyle": "white",
  "backgroundColor": "#ff6700",
  "backgroundTextStyle":"light",
  "navigationBarTitleText": "任务",
  "usingComponents": {
    "van-popup": "@vant/weapp/popup/index",
    "van-button": "@vant/weapp/button/index",
    "van-search": "@vant/weapp/search/index"
  }
}      
page{
  background-color: #f3f6fb;
}
/* .inp-box{
  padding:10rpx 20rpx 10rpx;
  box-sizing: border-box;
  position:relative;
  background-color: #ffffff;
} */
.node-tab{
  background-color: #ffffff;
  height:88rpx;
  font-size:28rpx;
  line-height: 88rpx;
  display: flex;
}
.node-tab .tab-item{
  flex:1;
  text-align: center;
  color: #666;
}
.node-tab .active{
  color: #ff6700;
  position: relative;
}
.node-tab .active::before{
  position:absolute;
  content: " ";
  bottom:10rpx;
  left: 50%;
  transform: translateX(-50%);
  width: 30rpx;
    height: 6rpx;
    background-color: #ff6700;
    border-radius: 3rpx;
}
.tab-content{
  margin-top:20rpx;
}

.no-data{
  text-align: center;
  box-sizing: border-box;
  padding-top:230rpx;
  color: #999999;
}

/* 更新样式 */
.node-tab {
  position: relative;
}
.new-list-box {
  height: 100%;
} 
.new-list-item {
  box-sizing:border-box;
  /* height:260rpx; */
  position: relative;
  background-color: #fff;
  margin-bottom: 20rpx;
  padding: 20rpx 30rpx 0;
}

.new-list-item:last-child {
  margin-bottom: 0;
}

.new-list-item view {
  box-sizing: border-box;
}

.item-content {
  display: flex;
  justify-content: space-between;
  border-bottom: 1rpx solid #eaeaea;
  align-items: center;
  position: relative;
}

.content-left {
  width: 100%;
  padding-bottom: 30rpx;
}

.content-left .content-title {
  font-size: 32rpx;
  color: #333;
}

.content-left .content-des {
  font-size: 28rpx;
  color: #666;
  margin-top: 10rpx;
}

.content-deadline {
  font-size: 24rpx;
  color: #999;
}

.content-right {
  width: 130rpx;
  flex-shrink: 0;
  height: 48rpx;
  border: 1rpx solid #ff6700;
  color: #ff6700;
  border-radius: 8rpx;
  font-size: 24rpx;
  text-align: center;
  line-height: 48rpx;
}

.content-right-is-no {
  opacity: 0.8;
  border-color: #999;
  color: #999;
}

.item-tag {
  padding: 10rpx 0 10rpx;
  font-size: 24rpx;
}

.list-tag-item {
  padding: 5rpx 12rpx;
  text-align: center;
  background-color: #e5efff;
  border-radius: 4rpx;
  margin-right: 10rpx;
  color: #ff6700;
  border-radius: 8rpx;
  margin-bottom: 10rpx;
  font-size: 24rpx;
}

.content-right.bg-green {
  background-color:#e6ffca;
  border-color: #e6ffca;
  color:#ff6700;
  margin-right: 20rpx;
}

.exchange-btn{
  text-align: center;
  margin: 10px 0 0;
}

.dialog-box{
  font-size: 28rpx;
  padding: 30rpx 30rpx 0;
}

.textarea_css{
  margin-top: 15rpx;
  color: #333;
  height: 160px;
  border: 1px solid #999;
  border-radius: 6rpx;
  padding: 20rpx;
}      
/**app.wxss**/
.container {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  padding: 200rpx 0;
  box-sizing: border-box;
} 

.elli_psis{
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
}

.dis-flex-between{
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.dis-flex-center{
  display: flex;
  justify-content: center;
  align-items: center;
}

.dis-flex-start{
  display: flex;
  justify-content: center;
}

.dis-flex-items{
  display: flex;
  align-items: center;
}

.dis-flex-column{
  display: flex;
  flex-direction:column;
  justify-content: center;
}

.no-data-txt{
  color: #ff6700;
  font-size: 12px;
  text-align: center;
  margin: 10px 0;
}