<template> <view style="height: 100%;"> <!-- perspective: 1000; --> <scroll-view v-if="typeList=='classify'" class="scroll-view goods-list" :scroll-top="scrollTop" @scroll="handleScroll" scroll-y="true" :lower-threshold="lowerThreshold" @scrolltolower="handleScrolltolower" @touchstart="handleTouchStart" @touchmove.stop.prevent="handleTouchMove" @touchend="handleTouchEnd"> <!-- @touchmove.stop.prevent @touch.stop --> <view class="scroll-content1" :style="[scrollContentStyle]"> <!-- 下拉 --> <view class="pull-down-view"> <view class="refresh-view"> <text :class="' pull-down-text icon-ymt '+(refreshStatus == 'soon'?' to-blod-down ':refreshStatus == 'sure'?' to-blod-up ':' ') ">{{ refreshText[refreshStatus] }}</text> </view> </view> <view class="scroll-list"> <view class="right-content-actual pr bs" :style="'padding-bottom:'+paddBottom+'px;'"> <view v-if="(propData || null) != null && propData.length > 0" class="oh"> <view v-for="(item, index) in propData" :key="index"> <view @click="goGoodsDetail(item.id)" class="goods-item bs"> <image :src="imageUrl+item.listImg" mode="aspectFill" class="goods-img bs"></image> <view class="goods-detail"> <view class="goods-title"> <view class="goods-text">{{item.name}}</view> <!-- <view v-if="(item.simple_desc || null) != null" class="goods-desc">{{item.simple_desc}}</view> --> <view class="goods-desc">{{item.listDescribe || ''}}</view> </view> <view class="goods-item-bottom"> <view class="goods-price"> <view class="new-price">¥{{item.price}}</view> <view class="old-price">¥{{item.originalPrice}}</view> </view> <view class="goods-num"> <view class="icon cart cart-class" @click.stop="cartIconChoose(item.id)"> </view> </view> </view> </view> </view> </view> </view> </view> </view> <!-- 空 --> <view class=" empty-content" v-if="propData.length == 0"> <image class="empty-text" mode="widthFix" :src="imagewxUrl+imgadres"></image> <!-- <text class="empty-text">{{ emptyText }}</text> --> </view> <!-- 底部上滑 --> <view class="pull-up-view"> <view class="load-view"> <view class="loading-animation" v-if="loadStatus == 'loading'"></view> <text :class="' loading-text icon-ymt '+(loadStatus == 'soon'?' to-blod-up ':loadStatus == 'sure'?' to-blod-down ':' ') ">{{ loadText[loadStatus] }}</text> </view> </view> </view> </scroll-view> <!--search-List --> <scroll-view v-if="typeList=='goodsSearch'" scroll-y="true" class="ht-auto goods-list" @scroll="handleScroll" :scroll-top="scrollTop" @scrolltolower="scroll_lower" lower-threshold="30"> <!-- <view class="right-content-actual pr bs" :style="'padding-bottom:'+paddBottom+'px;'"> --> <view v-if="(propData || null) != null && propData.length > 0"> <view v-for="(item, index) in propData" :key="index"> <view @click="goGoodsDetail(item.id)" class="goods-item bs"> <image :src="imageUrl+item.listImg" mode="aspectFill" class="goods-img bs"></image> <view class="goods-detail"> <view class="goods-title"> <view class="goods-text">{{item.name}}</view> <!-- <view v-if="(item.simple_desc || null) != null" class="goods-desc">{{item.simple_desc}}</view> --> <view class="goods-desc">{{item.listDescribe || ''}}</view> </view> <view class="goods-item-bottom"> <view class="goods-price"> <view class="new-price">¥{{item.price}}</view> <view class="old-price">¥{{item.originalPrice}}</view> </view> <view class="goods-num"> <view class="icon cart cart-class" @click.stop="cartIconChoose(item.id)"> </view> </view> </view> </view> </view> </view> <noMore :bgColor="'#ffffff'"></noMore> </view> <!-- 空 --> <view class=" empty-content" v-else> <image class="empty-text" mode="widthFix" :src="imagewxUrl+imgadres"></image> <!-- <text class="empty-text">{{ emptyText }}</text> --> </view> <!-- </view> --> </scroll-view> <!-- 购物车 --> <view :class="' gouwuche searchCart ' " @click.prevent="goCart"> <!-- cartNum --> <uniBadge class="uni-badge-left-margin badgeClass" max-num="99" :text="cartNum+''" type="warning" size="small" /> <view class="icon cart font40"> </view> </view> <!-- 选择类别 --> <wybPopup ref="popup" zIndex="999" type="bottom" height="500" width="500" :scrollY="true" radius="6" :showCloseIcon="true"> <cart-choose @refreshCartNum="refreshCartNum" :specificationList="specificationList" @close="close"> </cart-choose> </wybPopup> </view> </template> <script> import noMore from '@/components/no-more/no-more.vue' import wybPopup from '@/components/wyb-popup/wyb-popup.vue' import cartChoose from '@/components/cart-choose/cart-choose.vue' import { findGoodsSkuByGoodsId, getShoppingCartList } from '@/Utils/physicalObject.js' import uniBadge from '@/components/uni-badge/components/uni-badge/uni-badge.vue' const app = getApp(); export default { data() { return { cartNum: 0, imageUrl: app.globalData.imgUrl, //图片地址 imagewxUrl: app.globalData.imageWxImg, imgadres: 'goods_default_pages.png', scrollTop: 0, currentScrollTop: 0, // start refresherThreshold: 50, lowerThreshold: 50, pullingDown: false, // 是否正在下拉 pullDownHeight: 0, // 下拉高度 pullDownTimeStamp: 0, // 下拉时的时间戳 pullingUp: false, // 是否正在上拉 pullUpHeight: 0, // 上拉高度 pullUpTimeStamp: 0, // 上拉时的时间戳 maxDistance: 100, touchDirection: '', list: [], emptyText: "暂无数据", loadStatus: 'soon', loadText: { loading: '加载中~', nomore: '', soon: '上滑查看下一分类', sure: '释放查看下一分类', }, refreshStatus: 'soon', refreshText: { soon: '下滑查看上一分类', sure: '释放查看上一分类', nomore: '没有更多啦~', refreshing: '正在刷新中~' }, //end specificationList: [], } }, created() { this.refreshCartNum(); }, mounted() { this.handleInit(); }, props: { propData: { type: Array, default () { return [] } }, paddBottom: { type: Number, default: 0, }, pageData: { type: Object, default() { return { pageStart: 1, pageNum: 0, allData: 0 } } }, selectObject: { type: Object, default(){ return { selectIndex: 0, length: 0 } } }, typeList: { type: String, default: "classify" }, }, watch: { selectObject: { handler(n, o) { if (n.selectIndex == n.length - 1) { this.loadStatus = "nomore" } else { this.loadStatus = "soon" } if (n.selectIndex == 0) { this.refreshStatus = "nomore" } else { this.refreshStatus = "soon" } }, deep: true, // 深度监听 immediate: true, // 初始化监听 }, }, computed: { scrollContentStyle() { const style = {}; const { pullDownHeight, pullingDown, pullUpHeight, pullingUp } = this; style.transform = pullingDown && !pullingUp ? `translateY(${pullDownHeight}px)` : `translateY(0px)`; style.transition = pullingDown && !pullingUp ? `transform .1s linear` : `transform 0.3s cubic-bezier(0.19,1.64,0.42,0.72)`; return style; }, }, components: { wybPopup, cartChoose, noMore, uniBadge }, methods: { goCart() { uni.navigateTo({ url: "/physical-merchants/classify/cart/cart" }) }, // 刷新购物车数量 refreshCartNum() { this.scrollTop = this.currentScrollTop; getShoppingCartList().then(res => { if (res.return_code == '000000') { this.cartNum = res.return_data.length; } else { uni.showToast({ title: res.return_msg, icon: 'none', duration: 2000 }) } }) }, //查看商品详情 goGoodsDetail(id) { uni.navigateTo({ url: '/physical-merchants/classify/goodsDetail/goodsDetail?goodsId=' + id }) }, // 购物车商品图标点击 cartIconChoose(id) { this.specificationList = []; let params = { goodsId: id }; // console.log(params) findGoodsSkuByGoodsId(params).then(res => { if (res.return_code == '000000') { if (res.return_data && res.return_data.length > 0) { this.specificationList = res.return_data; this.$refs.popup.show(); // console.log(this.specificationList) } else { this.specificationList = []; } } else { uni.showToast({ title: res.return_msg, icon: 'none', duration: 2000 }) } }) }, //popup关闭选择方法 close() { this.$refs.popup.hide(); }, scroll_lower() { this.$emit("loadData") }, //start // 下滑触底后 数据加载 loadData() { this.waiting = true; this.$emit('loadData', res => { this.waiting = false; this.list = res.list; this.total = res.total; this.currentPage++; this.handleComputeData(); }); }, // 计算数据 handleComputeData() { const len = this.list.length; const total = this.total; if (len >= this.total) { this.loadStatus = 'soon'; } else if (len < this.total) { this.loadStatus = 'loading'; } }, // 下滑触底事件 handleScrolltolower(e) { this.$emit('scrolltolower', e); if (this.loadStatus == 'nomore' || this.waiting) return; this.loadData(); }, // 滚动事件 handleScroll(e) { this.currentScrollTop = e.detail.scrollTop; // this.$emit('scroll', e); }, // 触摸按下处理 handleTouchStart(e) { this.pullingDown = true; this.currentTouchStartY = e.touches[0].clientY; }, // 触摸按下滑动处理 handleTouchMove(e) { // 顶部下滑 if (e.touches[0].clientY >= this.currentTouchStartY) { this.pullingUp = false; this.touchDirection = 'top'; const currentTouchMoveY = e.touches[0].clientY; let movingDistance = (currentTouchMoveY - this.currentTouchStartY); if (this.selectObject.selectIndex == 0) { this.refreshStatus = 'nomore' } else if (movingDistance > this.refresherThreshold) { this.refreshStatus = 'sure'; // 释放 } else { this.refreshStatus = 'soon'; // 划 } let computeDistance = movingDistance; if (computeDistance > this.maxDistance) { computeDistance = this.maxDistance; } this.pullDownHeight = computeDistance; } else { this.pullingUp = true; this.pullingDown = false; // 底部上滑 this.touchDirection = 'bottom'; const currentTouchMoveY = e.touches[0].clientY; let movingDistance = (this.currentTouchStartY - currentTouchMoveY); if (this.selectObject.selectIndex == this.selectObject.length - 1) { this.loadStatus = 'nomore'; } else if (movingDistance >= this.lowerThreshold) { this.loadStatus = 'sure'; //释放 } else { this.loadStatus = 'soon'; //划 } let computeDistance = movingDistance; if (computeDistance > this.maxDistance) { computeDistance = this.maxDistance; } this.pullUpHeight = computeDistance; } }, // 触摸松开处理 handleTouchEnd(e) { // 顶部下滑 if (this.touchDirection == 'top') { if (this.pullDownHeight >= this.refresherThreshold && this.selectObject.selectIndex > 0) { this.$emit("switchCategory", "prev") } // 底部上滑 } else if (this.touchDirection == 'bottom') { if (this.pullUpHeight >= this.lowerThreshold && this.selectObject.selectIndex < (this.selectObject .length - 1)) { this.$emit("switchCategory", "next") } } this.pullDownHeight = 0; this.pullUpHeight = 0; this.pullingDown = false; this.pullingUp = false; }, // 初始化 handleInit() { this.currentPage = this.page; this.currentSize = this.size; // console.log() // this.computedHeight(); }, // end } } </script> <style lang="scss" scoped> // 购物车 .gouwuche { position: absolute; bottom: 10px; right: 25px; width: 35px; height: 35px; color: #3DA7E7 !important; .font40 { font-size: 35px !important; color: #F0AD4E; } } .searchCart { bottom: 27px !important; right: 30px !important; } .badgeClass { position: absolute; top: -5px; right: -10px; } // .br { border: 1px solid #ffffff; } .bs { box-sizing: border-box; } .goods-list .goods-item { display: flex; align-items: center; width: 100%; height: 240rpx; /* margin-bottom: 20rpx; */ color: #333333; padding: 0 20rpx 10rpx; border-bottom: 1px solid #F6F6F6; } .goods-list { background-color: #ffffff; } .goods-list .goods-img { /* width: 190rpx; */ height: 100% !important; width: 200rpx; padding: 10rpx; } .goods-list .goods-detail { width: calc(100% - 190rpx); height: 100%; } .goods-title { width: 100%; padding: 0 10rpx 0 0; height: 140rpx; } .goods-title .goods-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; height: 50rpx; line-height: 50rpx; font-size: 30rpx; padding: 20rpx 0 10rpx; } .goods-title .goods-desc { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; height: 40rpx; line-height: 40rpx; font-size: 24rpx; color: #999999; } .goods-item-bottom { display: flex; justify-content: space-between; align-items: flex-end; } .goods-item-bottom .goods-price { font-family: Arial; padding-left: 20rpx; } .goods-item-bottom .new-price { color: #3DA7E7; font-weight: bold; font-size: 18px; } .goods-item-bottom .old-price { font-size: 24rpx; color: #D6D6D6; font-weight: bold; text-decoration: line-through; } .goods-item-bottom .goods-num { height: 80rpx; } .goods-item-bottom .cart-class { width: 80rpx; height: 80rpx; line-height: 80rpx; color: #3DA7E7; text-align: center; font-size: 50rpx; } /* gundong */ // 空 .empty-content { height: calc(100% - 20px); display: flex; align-items: center; flex-direction: column; justify-content: center; .empty-image { width: 100%; } .empty-text { width: 80%; display: block; color: #606266; margin-top: 40rpx; margin-bottom: 20rpx; } } .scroll-view { height: 100%; .scroll-content1 { width: 100%; padding-bottom: 40px; // position: relative; // height: inherit; .empty-view { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; } .pull-down-view { width: 100%; top: 0; left: 0; padding: 30rpx 0; display: flex; position: absolute; align-items: center; flex-direction: column; justify-content: center; transform: translateY(-100%); .refresh-view { display: flex; align-items: center; flex-direction: column; .loading-animation { width: 50rpx; height: 50rpx; } .pull-down-text { color: #606266; font-size: 24rpx; margin-top: 10rpx; } } } .scroll-list { display: flex; flex-direction: column; } .loading-view { width: 100%; height: 100%; display: flex; align-items: center; flex-direction: column; justify-content: center; .loading-animation { width: 40rpx; height: 40rpx; } .loading-text { color: #606266; font-size: 24rpx; margin-top: 10rpx; } } .pull-up-view { width: 100%; // padding: 15rpx 0; height: 20px; display: flex; align-items: center; justify-content: center; .load-view { display: flex; align-items: center; .loading-text { color: #606266; font-size: 24rpx; margin-left: 20rpx; } } } .loading-animation { position: relative; &::after, &::before { left: 0; width: 100%; position: absolute; border: 0 solid currentColor; background-color: #b7b7b7; } &::after { content: ''; top: -25%; z-index: 1; height: 100%; border-radius: 10%; animation: spin 0.6s -0.1s linear infinite; } &::before { content: ''; bottom: -9%; height: 10%; background: #000; border-radius: 50%; opacity: 0.2; animation: shadow 0.6s -0.1s linear infinite; } @keyframes spin { 17% { border-bottom-right-radius: 10%; } 25% { transform: translateY(25%) rotate(22.5deg); } 50% { border-bottom-right-radius: 100%; transform: translateY(50%) scale(1, 0.9) rotate(45deg); } 75% { transform: translateY(25%) rotate(67.5deg); } 100% { transform: translateY(0) rotate(90deg); } } @keyframes shadow { 50% { transform: scale(1.25, 1); } } } } } </style>