HTML:
<!-- menu.wxml -->
<view>
<!-- mainBox -->
<view class="mainBox">
<!-- menuMain -->
<view class="menuMain">
<!-- left -->
<scroll-view style="height:{{height}}px" class="menuTabs" scroll-with-animation="true" scroll-y="true">
<view>
<view class="menu-item" wx:for="{{menuTabs}}" wx:key="index" data-id="tab{{index}}" bindtap="clickMenu" class="menu-item {{currentLeftSelect == 'tab'+index ? 'active': ''}}" >
<text>{{item.title}}</text>
<view class="rmdBtn" wx:if="{{item.rmdFlag==1}}">推荐</view>
</view>
</view>
</scroll-view>
<!-- left end -->
<!-- right -->
<scroll-view class="menuScroll" style="height:{{height}}px" scroll-y="true" bindscroll="handleScroll" scroll-into-view="{{toView}}" scroll-with-animation="true">
<!-- <view wx:for="{{menuList}}" wx:key="index" id="tab{{index}}" class="menuItem {{top>130 ? 'topnav' : ''}}"> -->
<view class="menu-list" wx:for="{{menuList}}" wx:for-item="list" wx:key="index" id="tab{{index}}" style="{{index == (menuList.length - 1) ? 'margin-bottom: 1000rpx':'' }}">
<view>
<!-- menuTitle -->
<view class="menuTitle">
<text>{{list.productType}}</text>
<view class="line"></view>
</view>
<!-- menuTitle end -->
</view>
<!-- menuList -->
<view class="list-item" wx:for="{{list.products}}" wx:key="key" data-titel="{{list.productType}}" data-item="{{item}}" bindtap="getMenuDetail">
<view class="caffeeInfo">
<!-- 售罄遮罩 -->
<image class="outOfStock" wx:if="{{item.soldOutFlag=='1'}}" src="https://cofeplus.oss-cn-beijing.aliyuncs.com/applets/images/menu_outOfStock.png"></image>
<!-- 售罄遮罩 end -->
<image class="caffeeImg" src="{{item.littleImg}}"></image>
<view class="infoDetail">
<view class="nameBox">
<text class="caffeeName">{{item.productName}}</text>
<text class="discount" wx:if="{{item.hotFlag==1}}">热销</text>
</view>
<text class="englishName">{{item.englishName}}</text>
<view class="origin specs">规格:<rich-text nodes="{{item.composition}}"></rich-text></view>
<!-- <text class="origin">规格:{{item.composition}}</text> -->
<view class="priceBox">
<text class="price">¥<text style="{{item.isProduct == 1?'color: #727171':''}}">{{item.sellingPrice}}</text></text>
<text class="originPrice" wx:if="{{item.sellingPrice!=item.originalPrice}}">¥{{item.originalPrice}}</text>
</view>
</view>
</view>
<!-- 未售罄加号 -->
<view class="addBtn" wx:if="{{item.soldOutFlag=='0' && item.isProduct == 0}}">
<image class="addImg" src="https://cofeplus.oss-cn-beijing.aliyuncs.com/applets/images/menu_add2.png"></image>
</view>
<!-- 未售罄加号 end -->
<!-- 已售罄加号 - 非商品 -->
<view class="addBtn" wx:if="{{item.soldOutFlag=='1' || item.isProduct == 1}}">
<image class="addImg" src="https://cofeplus.oss-cn-beijing.aliyuncs.com/applets/images/menu_noAdd.png"></image>
</view>
<!-- 已售罄加号 - 非商品 end -->
</view>
<!-- menuList end -->
</view>
</scroll-view>
<!-- right end -->
</view>
<!-- menuMain end -->
</view>
<!-- mainBox end -->
</view>
css:
/* pages/menu/menu.wxss */
/*
mainbox
*/
.mainBox {
width: 100%;
}
/*
swiper
*/
swiper {
width: 100%;
display: flex;
height: 138rpx;
}
.slide-image {
width: 100%;
height: 100%;
}
/*
menuMain
*/
.menuMain {
width: 100%;
height: 100%;
display: flex;
flex-flow: row;
position: absolute;
background-color: #fff;
}
.menuTabs {
width: 25%;
height: 100%;
background: #f5f5f5;
overflow: hidden;
}
.menu-item {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
background: #f5f5f5;
height: 30rpx;
font-size: 28rpx;
color: #666;
padding: 30rpx 0;
position: relative;
}
.menu-item text{
text-align: center;
}
.active {
background: #fff;
/* font-weight: bold; */
color: #00c8c8;
/* border-left: 2px solid #27b8b8; */
/* border-bottom-right-radius: 30rpx; */
}
.active+.menu-item{
border-top-right-radius: 24rpx;
}
.menuList {
width: 75%;
background: #fff;
padding: 20rpx 0;
}
.menuList:last-child {
margin-bottom: 380rpx;
}
.menuScroll {
width: 100%;
height: 100%;
padding: 10rpx 0 0;
}
.menuItem:last-child{
margin-bottom: 40rpx;
}
.menuTitle {
width: 100%;
font-size: 22rpx;
color: #666;
display: flex;
justify-content: space-between;
align-items: center;
margin-left: 20rpx;
margin-bottom: 40rpx;
/* margin-top: 20rpx; */
}
.line {
width: 82%;
height: 1rpx;
border-bottom: 1rpx solid #eee;
}
.list-item {
margin-left: 20rpx;
margin-top: 20rpx;
margin-right: 20rpx;
display: flex;
justify-content: space-between;
border-bottom: 1rpx solid #b9f0f0;
padding-bottom: 20rpx;
}
.menu-list .list-item:last-child{
border-bottom: 0;
}
/* .list-item:last-child {
border: none;
} */
.caffeeImg {
width: 140rpx;
height: 140rpx;
}
.addBtn {
position: relative;
min-width: 60rpx;
}
.addImg {
width: 45rpx;
height: 45rpx;
position: absolute;
bottom: 0;
right: 10rpx;
}
.caffeeName {
/* font-size: 26rpx; */
color: #00c8c8;
/* font-weight: bold; */
vertical-align: middle;
}
.englishName, .origin {
font-size: 24rpx;
color: #898989;
}
.origin{
margin: 4rpx 0 25rpx;
}
.price {
/* font-size: 28rpx; */
color: #727171;
/* font-weight: bold; */
}
.price text{
font-size: 40rpx;
color: #00c8c8;
}
.discount {
font-size: 16rpx;
color: #fff;
background: #f5a622;
border-radius: 6rpx;
padding: 6rpx;
margin-left: 10rpx;
vertical-align: middle;
}
.nameBox {
line-height: 30rpx;
margin-bottom: 12rpx;
}
.caffeeInfo {
display: flex;
flex-flow: row;
}
.infoDetail {
display: flex;
flex:1;
flex-flow: column;
margin-left: 16rpx;
justify-content: center;
}
.infoDetail text:first-child {
margin-bottom: 6rpx;
}
.infoDetail text:last-child {
margin-top: 12rpx;
}
.outOfStock {
position: absolute;
width: 140rpx;
height: 140rpx;
}
.originPrice{
color: #999;
font-size: 24rpx;
text-decoration: line-through;
margin-left: 8rpx;
}
.rmdBtn{
position: absolute;
top:0;
right:0;
background: #f5a622;
color: #fff;
font-size: 18rpx;
padding:0 10rpx;
}
.specs{
display: flex;
/* align-items: center; */
flex-wrap: wrap;
}
.specs rich-text{
display: inline-block;
flex: 1;
padding: 0;
}```
js:
// pages/menu/menu.js
const lang = require("../../utils/language.js");
const app = getApp();
const c_url = getApp().globalData.c_apiRoot;
// 右侧每一类的 bar 的高度(固定)
const RIGHT_BAR_HEIGHT = 23;
// 右侧每个子类的高度(固定)
const RIGHT_ITEM_HEIGHT = 70;
// 左侧每个类的高度(固定)
const LEFT_ITEM_HEIGHT = 45
Page({
/**
* 页面的初始数据
*/
data: {
// menuTabs
current: "tab1",
menuTabs: [],
// menuList
menuList: [
{
productType: "经典咖啡",
products:[
{
composition: "浓缩咖啡,水",
epId: 163,
hotFlag: 1,
isProduct: 0,
littleImg: "https://cofeplus.oss-cn-beijing.aliyuncs.com/product/meishikafei.jpg",
originalPrice: 10.9,
productCode: "test0116100003",
productName: "美式咖啡",
sellingPrice: 10.9,
soldOutFlag: 0,
},
{
composition: "浓缩咖啡,牛奶",
epId: 168,
hotFlag: 0,
isProduct: 0,
littleImg: "https://cofeplus.oss-cn-beijing.aliyuncs.com/product/natiekafei.jpg",
originalPrice: 14.9,
productCode: "test0116100001",
productName: "美式拿铁",
sellingPrice: 14.9,
soldOutFlag: 0,
},
],
rmdFlag: 0
},
{
productType: "各国特色",
products:[
{
composition: "浓缩咖啡,水",
epId: 163,
hotFlag: 1,
isProduct: 0,
littleImg: "https://cofeplus.oss-cn-beijing.aliyuncs.com/product/meishikafei.jpg",
originalPrice: 10.9,
productCode: "test0116100003",
productName: "美式咖啡",
sellingPrice: 10.9,
soldOutFlag: 0,
},
{
composition: "浓缩咖啡,牛奶",
epId: 168,
hotFlag: 0,
isProduct: 0,
littleImg: "https://cofeplus.oss-cn-beijing.aliyuncs.com/product/natiekafei.jpg",
originalPrice: 14.9,
productCode: "test0116100001",
productName: "美式拿铁",
sellingPrice: 14.9,
soldOutFlag: 0,
},
],
rmdFlag: 0
}
],
currentLeftSelect:'tab0',
// 锚点
toView: 'tab0',
curId: 'tab0',
//记录scroll-view滚动过程中距离顶部的高度
distance: 0,
currentLeft: 0, //左侧选中的下标
// 屏幕高度
height: "",
// 当前页
curPage: 1,
heightArr:[],
lastActive:'',
eachRightItemToTop: [],
},
onLoad: function () {
var that = this;
wx.getSystemInfo({
success: function (res) {
that.setData({
height: res.windowHeight-69
})
},
})
},
onShow: function () {
this.getMenus();
},
/**
* 获取每个右侧的 bar 到顶部的距离,
* 用来做后面的计算。
*/
getEachRightItemToTop: function (data) {
var obj = {};
var totop = 0;
// 循环来计算每个子类到顶部的高度
obj['tab0'] = totop
for (let i = 1; i < data.length+1; i++) {
var elemId = 'tab' + i
// obj[elemId] = totop
if (i != 0) {
totop += (RIGHT_BAR_HEIGHT + data[i - 1].products.length * RIGHT_ITEM_HEIGHT)
}
// 这个的目的是 例如有两类,最后需要 0-1 1-2 2-3 的数据,所以需要一个不存在的 'last' 项,此项即为第一类加上第二类的高度。
var lastIndex = data.length;
console.log(lastIndex, totop)
obj[lastIndex == i ? 'last' : elemId] = totop
}
console.log(obj)
return obj
},
// 锚点
clickMenu: function (e) {
this.setData({
toView: e.currentTarget.dataset.id,
currentLeftSelect: e.currentTarget.dataset.id
})
},
// scroll
handleScroll: function (e) {
// console.log(this.data.eachRightItemToTop)
for (let i = 0; i < this.data.menuList.length; i++) {
var elemId = 'tab' + i
let left = this.data.eachRightItemToTop[elemId]
// console.log(left)
let right = this.data.eachRightItemToTop[this.data.menuList[i + 1] ? ('tab' + (i+1)) : 'last']
if (e.detail.scrollTop < right && e.detail.scrollTop >= left) {
this.setData({
currentLeftSelect: elemId,
leftToTop: LEFT_ITEM_HEIGHT * i
})
}
}
// console.log(this.data.constants)
// console.log(this.data.eachRightItemToTop)
},
// 菜单详情
getMenuDetail: function (e) {
console.log(e)
},
// 获取商品列表
getMenus: function () {
var that = this;
var data = {
eqNumber: wx.getStorageSync('eqNumber'),
language: wx.getStorageSync('lan'),
pageNum: this.data.curPage,
pageSize: 500
};
app.httpPost(c_url + 'v1/get_products', data, (res) => {
var tempTabs = [];
res.data.forEach(function (item, index) {
tempTabs.push({
'title': item.productType,
'rmdFlag': item.rmdFlag
});
});
that.setData({
menuList: res.data,
menuTabs: tempTabs,
eachRightItemToTop: that.getEachRightItemToTop(res.data)
});
// this.getHeight()
}, (errRes) => {
app.errorMsg(errRes.data.msg);
});
},
})