首页.
This commit is contained in:
parent
7487e02a4d
commit
dc7c7cc475
|
|
@ -1,110 +1,116 @@
|
|||
<template>
|
||||
<view class="goods-item" @click="onItemClick">
|
||||
<view class="goods-image">
|
||||
<image v-if="goodsItem.imgUrl" :src="goodsItem.imgUrl" class="image" mode="aspectFill" />
|
||||
</view>
|
||||
<view class="goods-item" @click="onItemClick">
|
||||
<view class="goods-image">
|
||||
<image v-if="goodsItem.imgUrl" :src="goodsItem.imgUrl" class="image" mode="aspectFill" />
|
||||
</view>
|
||||
|
||||
<text class="goods-title myZt-500w">{{ goodsItem.title }}</text>
|
||||
<text class="goods-title myZt-500w">{{ goodsItem.title }}</text>
|
||||
|
||||
<text class="goods-status myZt-300w">现货发售中</text>
|
||||
<text class="goods-status myZt-300w">现货发售中</text>
|
||||
|
||||
<view class="goods-price">
|
||||
<text class="price-value myZt-500w">¥{{ goodsItem.price }}</text>
|
||||
<text class="price-unit myZt-500w">/ 包</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="goods-price">
|
||||
<text class="price-value myZt-500w">¥{{ goodsItem.price }}</text>
|
||||
<text class="price-unit myZt-500w">/ 包</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
/**
|
||||
* 商品项组件
|
||||
*/
|
||||
import { defineProps, defineEmits } from 'vue';
|
||||
/**
|
||||
* 商品项组件
|
||||
*/
|
||||
import {
|
||||
defineProps,
|
||||
defineEmits
|
||||
} from 'vue';
|
||||
|
||||
// 组件属性
|
||||
const props = defineProps({
|
||||
/**
|
||||
* 商品信息
|
||||
*/
|
||||
goodsItem: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: () => ({
|
||||
id: '',
|
||||
title: '',
|
||||
imgUrl: '',
|
||||
price: '0',
|
||||
type: ''
|
||||
})
|
||||
}
|
||||
});
|
||||
// 组件属性
|
||||
const props = defineProps({
|
||||
/**
|
||||
* 商品信息
|
||||
*/
|
||||
goodsItem: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: () => ({
|
||||
id: '',
|
||||
title: '',
|
||||
imgUrl: '',
|
||||
price: '0',
|
||||
type: ''
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
// 事件
|
||||
const emit = defineEmits(['click']);
|
||||
// 事件
|
||||
const emit = defineEmits(['click']);
|
||||
|
||||
/**
|
||||
* 点击商品项
|
||||
*/
|
||||
const onItemClick = () => {
|
||||
emit('click', props.goodsItem.id);
|
||||
};
|
||||
/**
|
||||
* 点击商品项
|
||||
*/
|
||||
const onItemClick = () => {
|
||||
emit('click', props.goodsItem.id);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.goods-item {
|
||||
height: 490.28rpx;
|
||||
background-color: #FEF6D6;
|
||||
border: 3rpx solid #F9D051;
|
||||
border-radius: 40rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.goods-image {
|
||||
width: 100%;
|
||||
height: 320.83rpx;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 40rpx 40rpx 0 0;
|
||||
overflow: hidden;
|
||||
|
||||
.image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-title {
|
||||
width: 280.56rpx;
|
||||
margin: 15.28rpx auto;
|
||||
font-size: 25rpx;
|
||||
color: #685952;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.goods-status {
|
||||
font-size: 19.44rpx;
|
||||
color: #FF6A6A;
|
||||
margin-left: 24.31rpx;
|
||||
}
|
||||
|
||||
.goods-price {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-left: 20.31rpx;
|
||||
|
||||
.price-value {
|
||||
font-size: 29.17rpx;
|
||||
color: #87644E;
|
||||
}
|
||||
|
||||
.price-unit {
|
||||
font-size: 19.44rpx;
|
||||
color: #87644E;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
.goods-item {
|
||||
height: 490.28rpx;
|
||||
background-color: #FEF6D6;
|
||||
border: 3rpx solid #F9D051;
|
||||
border-radius: 40rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.goods-image {
|
||||
width: 100%;
|
||||
height: 320.83rpx;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 40rpx 40rpx 0 0;
|
||||
overflow: hidden;
|
||||
|
||||
.image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-title {
|
||||
width: 280.56rpx;
|
||||
margin-top: 15.28rpx;
|
||||
margin-left: 23.61rpx;
|
||||
font-size: 25rpx;
|
||||
color: #685952;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.goods-status {
|
||||
font-size: 19.44rpx;
|
||||
color: #FF6A6A;
|
||||
margin-left: 24.31rpx;
|
||||
margin-top: 15.97rpx;
|
||||
}
|
||||
|
||||
.goods-price {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-left: 20.31rpx;
|
||||
margin-top: 18.75rpx;
|
||||
|
||||
.price-value {
|
||||
font-size: 29.17rpx;
|
||||
color: #87644E;
|
||||
}
|
||||
|
||||
.price-unit {
|
||||
font-size: 19.44rpx;
|
||||
color: #87644E;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -3,144 +3,150 @@
|
|||
<view>
|
||||
<z-paging ref="pagePaging" refresher-only @onRefresh="onRefresh" @scrolltolower="scrolltolower"
|
||||
@scroll="scroll">
|
||||
<view class="content">
|
||||
<guyu-home-search style="width: 100%;"></guyu-home-search>
|
||||
<!-- 公告 -->
|
||||
<guyu-home-notice :notice-info="homeData?.noticeInfo" />
|
||||
<!-- 轮播图 -->
|
||||
<guyu-home-swiper :advert-list="homeData?.advertList" style="width: 100%;" />
|
||||
<!-- 推荐位 -->
|
||||
<guyu-home-recommend :rec-list="homeData?.recList" style="width: 100%;" />
|
||||
|
||||
<!-- 小程序中直接修改组件style为position: sticky;无效,需要在组件外层套一层view -->
|
||||
<view class="bar-view" style="z-index:97;position: sticky;top :0;background-color: #fff;">
|
||||
<view :style="{ height: tabsBarHeight + 'px' }" class="status-bar"> </view>
|
||||
<guyu-home-tabs ref="tabs" :list="homeData?.categories" @change="tabsChange" :current="current" />
|
||||
<view class="bg"
|
||||
style="display: flex; justify-content: center; width: 100%; background-image: url('@@:static/bg.png');">
|
||||
<view class="content">
|
||||
<guyu-home-search style="width: 100%;"></guyu-home-search>
|
||||
<!-- 公告 -->
|
||||
<guyu-home-notice :notice-info="homeData?.noticeInfo" />
|
||||
<!-- 轮播图 -->
|
||||
<guyu-home-swiper :advert-list="homeData?.advertList" style="width: 100%;" />
|
||||
<!-- 推荐位 -->
|
||||
<guyu-home-recommend :rec-list="homeData?.recList" style="width: 100%;" />
|
||||
|
||||
<!-- 小程序中直接修改组件style为position: sticky;无效,需要在组件外层套一层view -->
|
||||
<view class="bar-view" style="z-index:97;position: sticky;top :0;background-color: #fff;">
|
||||
<view :style="{ height: tabsBarHeight + 'px' }" class="status-bar"> </view>
|
||||
<guyu-home-tabs ref="tabs" :list="homeData?.categories" @change="tabsChange"
|
||||
:current="current" />
|
||||
</view>
|
||||
<swiper class="swiper" :style="[{ height: swiperHeight + 'px' }]" :current="current"
|
||||
@transition="swiperTransition" @animationfinish="swiperAnimationfinish">
|
||||
<swiper-item class="swiper-item" v-for="(item, index) in homeData?.categories" :key="index">
|
||||
<guyu-home-goods-list ref="swiperList" :tabIndex="index" :currentIndex="current"
|
||||
@heightChanged="heightChanged">
|
||||
</guyu-home-goods-list>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
<swiper class="swiper" :style="[{ height: swiperHeight + 'px' }]" :current="current"
|
||||
@transition="swiperTransition" @animationfinish="swiperAnimationfinish">
|
||||
<swiper-item class="swiper-item" v-for="(item, index) in homeData?.categories" :key="index">
|
||||
<guyu-home-goods-list ref="swiperList" :tabIndex="index" :currentIndex="current"
|
||||
@heightChanged="heightChanged">
|
||||
</guyu-home-goods-list>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
|
||||
</z-paging>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import {
|
||||
homeData,
|
||||
isLoading,
|
||||
error,
|
||||
preloadHomeData,
|
||||
refreshHomeData
|
||||
} from '@/common/server/home';
|
||||
// 状态变量
|
||||
const swiperHeight = ref(0);
|
||||
const tabList = ref(['测试1', '测试2', '测试3', '测试4']);
|
||||
const current = ref(0); // tabs组件的current值,表示当前活动的tab选项
|
||||
const tabsBarHeight = ref(0);
|
||||
const statusBarHeight = ref(uni.getSystemInfoSync().statusBarHeight);
|
||||
const isQuerying = ref(false);
|
||||
import {
|
||||
ref,
|
||||
onMounted
|
||||
} from 'vue';
|
||||
import {
|
||||
homeData,
|
||||
isLoading,
|
||||
error,
|
||||
preloadHomeData,
|
||||
refreshHomeData
|
||||
} from '@/common/server/home';
|
||||
// 状态变量
|
||||
const swiperHeight = ref(0);
|
||||
const tabList = ref(['测试1', '测试2', '测试3', '测试4']);
|
||||
const current = ref(0); // tabs组件的current值,表示当前活动的tab选项
|
||||
const tabsBarHeight = ref(0);
|
||||
const statusBarHeight = ref(uni.getSystemInfoSync().statusBarHeight);
|
||||
const isQuerying = ref(false);
|
||||
|
||||
// 组件引用
|
||||
const pagePaging = ref(null);
|
||||
const tabs = ref(null);
|
||||
const swiperList = ref(null);
|
||||
// 组件引用
|
||||
const pagePaging = ref(null);
|
||||
const tabs = ref(null);
|
||||
const swiperList = ref(null);
|
||||
|
||||
onLoad(() => {
|
||||
onLoad(() => {
|
||||
|
||||
});
|
||||
// 初始化加载
|
||||
onMounted(() => {
|
||||
if (!homeData.value) preloadHomeData();
|
||||
});
|
||||
// 方法
|
||||
const scroll = (e) => {
|
||||
// #ifdef MP
|
||||
if (e.detail.scrollTop < 700 && statusBarHeight.value > 0) {
|
||||
if (isQuerying.value) {
|
||||
return;
|
||||
}
|
||||
isQuerying.value = true;
|
||||
const query = uni.createSelectorQuery();
|
||||
query.select('.bar-view').boundingClientRect(rect => {
|
||||
if (rect) {
|
||||
// 判断元素是否粘滞
|
||||
if (rect.top <= 0 && tabsBarHeight.value == 0) {
|
||||
tabsBarHeight.value = statusBarHeight.value;
|
||||
} else if (rect.top > 30 && statusBarHeight.value > 0) {
|
||||
tabsBarHeight.value = 0;
|
||||
}
|
||||
}
|
||||
isQuerying.value = false;
|
||||
}).exec();
|
||||
}
|
||||
// #endif
|
||||
};
|
||||
|
||||
// tabs通知swiper切换
|
||||
const tabsChange = (index) => {
|
||||
_setCurrent(index);
|
||||
};
|
||||
|
||||
// 下拉刷新时,通知当前显示的列表进行reload操作
|
||||
const onRefresh = () => {
|
||||
swiperList.value[current.value].reload(() => {
|
||||
//当当前显示的列表刷新结束,结束当前页面的刷新状态
|
||||
pagePaging.value.endRefresh();
|
||||
});
|
||||
};
|
||||
// 初始化加载
|
||||
onMounted(() => {
|
||||
if (!homeData.value) preloadHomeData();
|
||||
});
|
||||
// 方法
|
||||
const scroll = (e) => {
|
||||
// #ifdef MP
|
||||
if (e.detail.scrollTop < 700 && statusBarHeight.value > 0) {
|
||||
if (isQuerying.value) {
|
||||
return;
|
||||
}
|
||||
isQuerying.value = true;
|
||||
const query = uni.createSelectorQuery();
|
||||
query.select('.bar-view').boundingClientRect(rect => {
|
||||
if (rect) {
|
||||
// 判断元素是否粘滞
|
||||
if (rect.top <= 0 && tabsBarHeight.value == 0) {
|
||||
tabsBarHeight.value = statusBarHeight.value;
|
||||
} else if (rect.top > 30 && statusBarHeight.value > 0) {
|
||||
tabsBarHeight.value = 0;
|
||||
}
|
||||
}
|
||||
isQuerying.value = false;
|
||||
}).exec();
|
||||
}
|
||||
// #endif
|
||||
};
|
||||
|
||||
// 当滚动到底部时,通知当前显示的列表加载更多
|
||||
const scrolltolower = () => {
|
||||
swiperList.value[current.value].doLoadMore();
|
||||
};
|
||||
// tabs通知swiper切换
|
||||
const tabsChange = (index) => {
|
||||
_setCurrent(index);
|
||||
};
|
||||
|
||||
// swiper滑动中
|
||||
const swiperTransition = (e) => {
|
||||
tabs.value.setDx(e.detail.dx);
|
||||
};
|
||||
// 下拉刷新时,通知当前显示的列表进行reload操作
|
||||
const onRefresh = () => {
|
||||
swiperList.value[current.value].reload(() => {
|
||||
//当当前显示的列表刷新结束,结束当前页面的刷新状态
|
||||
pagePaging.value.endRefresh();
|
||||
});
|
||||
};
|
||||
|
||||
// swiper滑动结束
|
||||
const swiperAnimationfinish = (e) => {
|
||||
_setCurrent(e.detail.current);
|
||||
tabs.value.unlockDx();
|
||||
};
|
||||
// 当滚动到底部时,通知当前显示的列表加载更多
|
||||
const scrolltolower = () => {
|
||||
swiperList.value[current.value].doLoadMore();
|
||||
};
|
||||
|
||||
// 设置swiper的高度
|
||||
const heightChanged = (height) => {
|
||||
if (height === 0) {
|
||||
// 默认swiper高度为屏幕可用高度-tabsView高度-slot="top"内view的高度
|
||||
// 注意:uni.upx2px(80)不是固定的,它等于slot="top"内view的高度,如果slot="top"内view的高度不为80rpx,则需要修改这个值
|
||||
height = uni.getSystemInfoSync().windowHeight - uni.upx2px(80);
|
||||
}
|
||||
swiperHeight.value = height;
|
||||
};
|
||||
// swiper滑动中
|
||||
const swiperTransition = (e) => {
|
||||
tabs.value.setDx(e.detail.dx);
|
||||
};
|
||||
|
||||
const _setCurrent = (currentVal) => {
|
||||
if (currentVal !== current.value) {
|
||||
//切换tab时,将上一个tab的数据清空
|
||||
swiperList.value[current.value].clear();
|
||||
}
|
||||
current.value = currentVal;
|
||||
};
|
||||
// swiper滑动结束
|
||||
const swiperAnimationfinish = (e) => {
|
||||
_setCurrent(e.detail.current);
|
||||
tabs.value.unlockDx();
|
||||
};
|
||||
|
||||
// 设置swiper的高度
|
||||
const heightChanged = (height) => {
|
||||
if (height === 0) {
|
||||
// 默认swiper高度为屏幕可用高度-tabsView高度-slot="top"内view的高度
|
||||
// 注意:uni.upx2px(80)不是固定的,它等于slot="top"内view的高度,如果slot="top"内view的高度不为80rpx,则需要修改这个值
|
||||
height = uni.getSystemInfoSync().windowHeight - uni.upx2px(80);
|
||||
}
|
||||
swiperHeight.value = height;
|
||||
};
|
||||
|
||||
const _setCurrent = (currentVal) => {
|
||||
if (currentVal !== current.value) {
|
||||
//切换tab时,将上一个tab的数据清空
|
||||
swiperList.value[current.value].clear();
|
||||
}
|
||||
current.value = currentVal;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
width: 96%;
|
||||
margin-left: 2%;
|
||||
background-color: url('@@:static/bg.png');
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.content {
|
||||
width: 94%;
|
||||
}
|
||||
|
||||
.swiper {
|
||||
height: 1000px;
|
||||
}
|
||||
.swiper {
|
||||
height: 1000px;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue
Block a user