微信小程序 商品报价表格 兼容PC端、手机端

1.固定表头、表格行高由内容撑开

2.图片自适应居中、图片预览

3.筛选条件置顶、显示所选的筛选分类

4.触底加载下一页

5.表格文字可复制

6.支持手机横屏、竖屏切换。横屏时隐藏底部 tabbar 导航栏

兼容电脑、手机端,文字是可以复制的,模拟器上可能看不出效果,但是在手机端长按文字可以选择复制、电脑端使用鼠标选中快捷键复制!

上效果图

wxml

<view class="containers">
  <view class="head" catchtouchmove='catchTouchMove' style="width: {{isWindows?'980px':'100%'}};">
    <view class="head__search" wx:if="{{filtrate_show}}">
      <view class="search__left">
        <text class="iconfont icon-sousuo"></text>
        <input class="search__input" confirm-type="search" type="text" bindinput="bindKeyInput" bindconfirm='searchClick' placeholder="请输入内容" />
        <view class="search__btn" bindtap="searchClick">搜索</view>
      </view>
      <!-- <view class="search__right" bindtap="xingshiClick">
      <block wx:if="{{layout_type}}">
        <view>收起筛选<text class="iconfont icon-weibiaoti33"></text></view>
      </block>
      <block wx:else>
        <view>展开筛选<text class="iconfont icon-xia"></text></view>
      </block>
    </view> -->
    </view>
    <view class="head__filtrate" wx:if="{{filtrate_show}}">
      <block wx:for="{{cate_list}}" wx:for-index="i" wx:key="i">
        <scroll-view scroll-x="true" class="filtrate__item">
          <view class="filtrate__item__row">
            <block wx:for="{{item.cate_two}}" wx:for-item="items" wx:key="index">
              <view class="filtrate__item__title {{item.index == items.id ? 'disabled':''}}" bindtap="geshitap" data-item="{{items}}" data-index="{{i}}">
                {{items.cate_name}}
              </view>
            </block>
          </view>
        </scroll-view>
      </block>
    </view>
    <view class="open__filtrate" catchtouchmove="catchTouchMove">
      <view class="open__filtrate_btn" bindtap="openFiltrate" wx:if="{{!filtrate_show}}">展开筛选<text class="iconfont icon-xia"></text></view>
      <view class="open__filtrate_btn" bindtap="openFiltrate" wx:else>收起筛选<text class="iconfont icon-weibiaoti33"></text></view>
      <view class="selected__type" wx:if="{{filtrateList!=''}}">所选分类:
        <block wx:for="{{filtrateList}}" wx:key="index"><text>{{item.cate_name}}</text></block>
      </view>
    </view>
  </view>
  <view class='centre__container'>
    <view class='table' style="margin-top: {{filtrate_show?headHeight+'px':'30px'}};">
      <view class='table__thead' style="top: {{filtrate_show?headHeight+'px':'30px'}};">
        <view class="th" style='width:70px;'>序号</view>
        <view class='th' style='width:150px;'>图片</view>
        <view class='th' style='width:70px;'>型号</view>
        <view class='th' style='width:70px;'>颜色</view>
        <view class='th' style='width:100px;'>色号</view>
        <view class='th' style='width:70px;'>规格</view>
        <view class='th' style='width:150px;'>尺寸</view>
        <view class='th' style='width:70px;'>件数</view>
        <view class='th' style='width:70px;'>价格</view>
        <view class='th' style='width:150px;'>备注</view>
      </view>
      <block wx:for="{{list}}" wx:key="index">
        <view class='table__tbody'>
          <view class='td' style='width:70px;font-weight: bold;'>{{index+1}}</view>
          <view class="td" style='width:150px;'>
            <image src="{{item.image}}" mode="aspectFit" bindtap="imgClick" data-index="{{index}}" lazy-load style="height: 120px;margin: auto;"></image>
          </view>
          <view class="td" style='width:70px;'>{{item.param_model}}</view>
          <view class="td" style='width:70px;'>{{item.param_color}}</view>
          <view class="td" style='width:100px;'>{{item.param_color_num}}</view>
          <view class="td max__td">
            <view wx:for="{{item.param_sku}}" wx:for-item="item2" wx:for-index="index2" wx:key="index2" class="max__td__row">
              <view class="max__td__row__item" style="width: 70px;">{{item2.sku}}</view>
              <view class="max__td__row__item" style='width:150px;'>{{item2.size}}</view>
              <view class="max__td__row__item" style="width: 70px;">{{item2.num}}</view>
              <view class="max__td__row__item" style="width: 69px;font-weight: bold;">{{item2.price}}</view>
            </view>
          </view>
          <view class='td' style='width:150px;'>{{item.param_custom_remark == null?"":item.param_custom_remark}}</view>
        </view>
      </block>
    </view>
  </view>
  <view class='mask' hidden='{{!filtrate_show}}' catchtouchmove='catchTouchMove' bindtap='close'></view>
</view>

<block wx:if="{{isPhone}}">
  <phoneNumber isPhone='{{isPhone}}'></phoneNumber>
</block>
<block wx:if="{{!iShidden}}">
  <authorize bind:onLoadFun='onLoadFun' iShidden="{{iShidden}}" isAuto="{{isAuto}}"></authorize>
</block>

wxss 样式这里统一使用 px  因为rpx可以根据屏幕宽度进行自适应,电脑端字体会变大、表格行高也会因为窗口大而变大等等...这样就做不到兼容电脑端了,所以不用rpx,直接用px写死

page {
  width: 100%;
  height: 100%;
  white-space: nowrap;
  overflow: scroll;
  box-sizing: border-box;
  font-size: 14.5px;
  font-family: '宋体';
}

.containers {
  width: 980px;
  height: auto;
  margin: 0 auto;
  background-color: #fff;
}

.head {
  width: 100%;
  padding: 0 10px; 
  position: fixed;
  top: 0;
  z-index: 99;
  background-color: #fff;
  overflow: hidden;
}

/* search */
.head__search {
  /* width: 980px; */
  width: 100%;
  height: auto;
  padding: 10px 0px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.search__left {
  /* width: 600px; */
  flex: 1;
  height: 30px;
  position: relative;
  vertical-align: middle;
  border-radius: 15px;
  padding-left: 25px;
  display: flex;
  align-items: center;
  border: 1px solid #ccc;
}

.search__left text {
  font-size: 16px;
  position: absolute;
  top: 6.5px;
  left: 15px;
}

.search__input {
  padding-left: 12.5px;
  /* width: 500px; */
  flex: 1;
}

.search__btn {
  width: 100px;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  text-align: center;
  border-radius: 0px 15px 15px 0px;
  color: #555;
  background-color: #eee;
  border-left: 1px solid #ccc;
}

@media (max-width: 430px) {
  /* 仅在 480px 或更宽的屏幕上生效的样式规则 */
  .search__btn {
    width: 60px;
  }
}

.search__right {
  display: flex;
  align-items: center;
  flex-direction: column;
  justify-content: center;
  text-align: center;
  width: 83px;
  height: 25px;
  border: 1px solid #e8e8e8;
  background-color: #f5f5f5;
  color: #6b6b6b;
  cursor: pointer;
}

/* filtrate */
.head__filtrate {
  /* width: 100%; */
  height: auto;
  overflow: hidden;
}

.filtrate__item {
  padding-bottom: 10px;
}

.filtrate__item__row {
  display: flex;
  align-items: center;
  /* flex-wrap: wrap; */
}

.filtrate__item__title {
  padding: 0 10px;
  height: 30px;
  line-height: 30px;
  white-space: nowrap;
  font-size: 13px;
  font-family: PingFang;
  font-weight: 500;
  color: #010000;
  border-radius: 15px;
}

.filtrate__item__row .disabled {
  background-color: #F0F1F3;
  font-weight: 800;
}

/* open__filtrate */
.open__filtrate {
  width: 980px;
  height: 30px;
  font-size: 12px;
  padding: 0 30px;
  display: flex;
  align-items: center;
}

.open__filtrate_btn {
  width: 85px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  background-color: #f8f8f8;
  border: 1px solid #f8f8f8;
}

.selected__type {
  margin-left: 20px;
}

.selected__type text{
  margin-right: 10px;
}

/* centre */
.centre__container {
  width: 100%;
  height: 100%;
  display: flex;
  background-color: white;
}

.table {
  margin: 0 auto;
  display: inline-flex;
  flex-direction: column;
  border: 1px solid rgba(218, 217, 217, 1);
  border-bottom: 0;
}

.table__thead {
  width: 100%;
  height: 40px;
  border-top: 1px solid rgba(218, 217, 217, 1);
  border-width: thin;
  display: inline-flex;
  position: -webkit-sticky;
  position: sticky;
  top: 50px;
  z-index: 87;
}

.th,
.td {
  width: 200px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background-color: #FFFF00;
  border-right: 1px solid rgba(218, 217, 217, 1);
  border-bottom: 1px solid rgba(218, 217, 217, 1);
  border-width: thin;
  font-weight: bold;
}

.table__tbody {
  width: 100%;
  display: inline-flex;
  flex-direction: row;
  border-bottom: 1px solid rgba(218, 217, 217, 1);
}

.td {
  background: white;
  min-height: 90px;
  font-weight: normal;
  text-align: center;
  word-wrap: break-word;
  word-break: break-all;
  white-space: pre-line;
  /* 文字可复制 */
  user-select: text;
  -moz-user-select: text;
  -webkit-user-select: text;
  -ms-user-select: text;
}

.max__td {
  width: 360px;
}

.max__td__row {
  width: 100%;
  display: flex;
  border-bottom: 1px solid rgba(218, 217, 217, 1);
  flex-basis: auto;
  flex-grow: 1;
  -webkit-flex-grow: 1;
}

.max__td__row:last-child {
  border-bottom: none;
}

.max__td__row__item {
  width: 200.5px;
  border-right: 1px solid rgba(218, 217, 217, 1);
  border-width: thin;
  min-height: 30px;
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
}

.max__td__row__item:last-child {
  border-right: none;
}

.mask {
  width: 100%;
  height: 100%;
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 98;
}
/* ----end */

js 处理逻辑

// 导入接口
import { getIndexData, cateIndex, goodsList } from '../../api/api.js';

Page({

  /**
   * 页面的初始数据
   */
  data: {
    cate_list: [],
    list: [],
    inputValue: '',
    ids: '',
    page: 1,
    loading: true,
    up_show: false,
    layout_type: true,
    userInfo: "",
    iShidden: true,
    isAuto: false,
    isPhone: false, 
    inter: '',
    headHeight:0,
    filtrate_show: false,
    isWindows: false,
    filtrateList:[],
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    //获取系统信息
    wx.getSystemInfo({
      success: (res) => {
      if(res.platform == "windows") {
        this.setData({
          isWindows: true
        })
      }
      }
    })

    //请求筛选列表
    cateIndex().then(res => {
      if (res.status == 200) {
        let all = {
          cate_name: "全部",
          id: 0,
        }
        res.data.forEach((e) => {
          e.index = 0;
          e.cate_two = [all, ...e.cate_two];
        })
        this.setData({
          cate_list: res.data
        })
      }
    })

    //请求商品列表
    this.dataGoods();
  },

  //商品列表
  dataGoods() {
    let data = {
      cate_ids: this.data.ids,
      page: this.data.page,
      keywords: this.data.inputValue,
    }
    getIndexData(data).then(res => {
      if (res.status == 200) {
        if (res.data.length != 0) {
          this.setData({
            list: [...this.data.list, ...res.data]
          })
        } else {
          this.setData({
            loading: false
          })
        }
      }
    })
  },

    // 键盘输入时触发事件 
    bindKeyInput: function (e) {
      this.setData({
        inputValue: e.detail.value
      })
    },

    //搜索按钮点击 or 点击键盘搜索按钮时触发
    searchClick() {
      let result = this.islogin();
      if(result){
        this.setData({
          page: 1,
          list: [],
          loading: true
        })
        this.dataGoods();
      }
    },

  //收起 | 展开筛选
  xingshiClick() {
    this.setData({
      layout_type: !this.data.layout_type,
    })
    wx.pageScrollTo({
      scrollTop: 0,
      duration: 0
    })
  },

  // 点击分类筛选
  geshitap(e) {
    let result = this.islogin();
    if(result){
      let dataset = e.currentTarget.dataset;
      var listIndex = "cate_list[" + dataset.index + "].index";
      this.setData({
        [listIndex]: dataset.item.id,
        page: 1,
        list: [],
        loading: true
      })
      let ids = [];
      this.data.cate_list.forEach(item => {
        if (item.index != 0) {
          ids.push(item.index)
        }
      })
      this.setData({
        ids: ids.join(','),
      })

      // 处理所选的分类
      let newlist = []
      newlist.push({id:dataset.index,cate_name:dataset.item.cate_name})
      if(this.data.filtrateList.length==0){
        //console.log('--空数组,直接赋值')
        this.setData({
          filtrateList: newlist,
        })
      } else {
        //console.log('--非空数组,合并数组')
         let isRow = false;
         let index = 0;
        for(var k = 0;k<this.data.filtrateList.length;k++){
          if(dataset.index==this.data.filtrateList[k].id){
            //console.log('循环判断用户点击的是否是同一行')
            isRow = true
            index = k
          }
        }

        if(isRow){
          //console.log('点击的是同一行,替换')
          let list = this.data.filtrateList
          list[index].cate_name = dataset.item.cate_name
          this.setData({
            filtrateList: list
          })
        } else {
          //console.log('点击的不是同一行,合并');
          this.setData({
            filtrateList: this.data.filtrateList.concat(newlist)
          })    
        }
      }
      //console.log(this.data.filtrateList);
      this.dataGoods();
      }
  },


  //点击图片预览事件
  imgClick(e){
    let result = this.islogin();
    if(result){
      let index = e.currentTarget.dataset.index;
      let list = this.data.list;
      // wx.previewImage({
      //   current: list[index].image, 
      //   urls: list[index].slider_image,
      //   success: function(res) {}
      // })

      //查看图片要添加记录,所以请求一次接口
      goodsList(list[index].id).then(res => {
        if (res.status == 200) {
          wx.previewImage({
            current: res.data.storeInfo.image, 
            urls: res.data.storeInfo.slider_image,
            success: function(res) {}
          })
        } 
      })

    }
  },

  //用户是否登录、封装为公共函数
  islogin() {
    let userInfo = wx.getStorageSync('USERINFO');
    if (!userInfo) {
      this.setData({
        iShidden: false,
      });      
      return false
    }

    if (!userInfo.phone) {
      this.setData({
        isPhone: true,
      });
      return false
    }

    return true
  },

  /**
   * 
   * 生命周期函数--监听屏幕滚动
   */
  onPageScroll (e) {
    // if(e.scrollTop > 0 ) {
    //   this.setData({
    //     filtrate_show: false,
    //   });
    // }
  },

  // 展开筛选
  openFiltrate () {
    this.setData({
      filtrate_show: !this.data.filtrate_show,
    })
    let query = wx.createSelectorQuery();
    query.select('.head').boundingClientRect(rect=>{
      //console.log('head的高度是',rect.height)
      this.setData({
        headHeight: rect.height
      })
    }).exec();
  },    

  //关闭蒙版
  close() {
     this.openFiltrate()
  },

  //禁止滑动
  catchTouchMove(){
    return false;
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {
    // wx.hideHomeButton();
  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {

  },

  /**
   * 
   * 生命周期函数--监听屏幕旋转事件
   */
  onResize:function(res) {
    console.log('屏幕方向旋转',res.deviceOrientation)
    if(res.deviceOrientation == 'landscape'){
      wx.hideTabBar();
    }else{
      wx.showTabBar();
    }
  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {
      
  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {
    if (this.data.loading) {
      let page = this.data.page + 1;
      this.setData({
        page: page
      })
      this.dataGoods();
    }
  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {

  }
})

然后配置单页面的json文件  注意不是app.json !  "pageOrientation": "auto" (手机横竖屏自适应) 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值