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" (手机横竖屏自适应)