789 lines
17 KiB
Vue
Raw Normal View History

<template>
<view class="page">
<!-- <view style="position: fixed;left:0px;z-index: 100;" :style="{'top': statusBaeHeight + 58 + 'px'}">
<view class="search-box" style="background: #F2F2F2;">
<input type="text" disabled placeholder="搜索酒款/酒厂" @click="toSearch">
</view>
</view> -->
<view v-if="showJoinImg && bannerJoin" class="join-box" @click="toJoin">
<image :src="bannerJoin.bannerUrl" class="img" mode="aspectFill" :lazy-load="true"></image>
</view>
<!-- 轮播 -->
<swiper v-else class="join-box" circular :autoplay="true" :indicator-dots="true">
<swiper-item v-for="(item,index) in homeBanner" :key="index">
<image :src="item.bannerUrl" class="img" mode="aspectFill" :lazy-load="true"></image>
</swiper-item>
</swiper>
<!-- 快捷导航 -->
<view class="bg-white"
style="border-radius: 30rpx 30rpx 12rpx 12rpx;padding-top:8rpx;position: relative;margin-top:-20rpx">
<view class="search-box hover-effect" @click="toSearch">
<view class="search-input">
<text class="cuIcon-search" style="font-size: 40rpx;color: #A2A2A2;margin-right: 24rpx;"></text>
<text style="color: #A2A2A2;">搜索酒款名称品牌名称啤酒风格</text>
</view>
<view class="searchs">
<uni-icons type="search" size="30" color="#fff"></uni-icons>
</view>
</view>
<view class="flex justify-between bg-white" style="padding: 20rpx 36rpx;">
<view class="nav-item hover-effect" v-for="(item, index) in navItems" :key="index" @click="toGo(index + 1)">
<view class="flex justify-center align-center img-box">
<image :src="'/static/nav-' + (index + 1) + '.png'" style="width: 48rpx;height: 48rpx;" :lazy-load="true"></image>
</view>
<text class="text-bold">{{item}}</text>
</view>
</view>
</view>
<!-- <commonTitle title="热门活动招募"></commonTitle> -->
<view class="section-title">
<text>热门活动招募</text>
</view>
<!-- 活动列表容器 -->
<view class="list-container">
<scroll-view
scroll-y="true"
@scrolltolower="changePage"
:scroll-anchoring="true"
>
<view class="activity-list" style="margin-top: 16rpx;">
<activity-item
v-for="(item, index) in featurePageList"
:key="index"
:item="item"
@click="handleActivityClick"
@review="toReview"
/>
</view>
<view v-if="featurePageList.length > 0" class="more-btn-box" @click="moreHotActivity">
<view class="more-btn">更多热门活动招募</view>
</view>
</scroll-view>
</view>
<!-- <view class="weixin-box zixuns">
<text>入驻助理在线服务1对1咨询使用指南~</text>
<view class="btn" @click="toAddAiad">立即添加</view>
</view> -->
<!-- <view class="weixin-box zixuns">
<text>账户正在审核中请稍等~</text>
<view class="btn" @click="toAddAiad">立即添加</view>
</view> -->
<loginPopup ref="loginRef" @loginSuccess="loginSuccess"></loginPopup>
<!-- 开屏广告 -->
<uni-popup ref="ADRef" type="center" :is-mask-click="false" maskBackgroundColor="rgba(0,0,0,0.7)" @change="handlePopupChange">
<view class="ad-container">
<swiper class="ad-swiper"
:circular="false"
:autoplay="false"
:duration="300"
:indicator-dots="true"
:indicator-color="'rgba(255,255,255,0.3)'"
:indicator-active-color="'#FFFFFF'"
@change="handleAdSwiperChange">
<swiper-item v-for="(item,index) in ADList"
:key="index"
class="ad-swiper-item"
:class="{'active': currentAdIndex === index}"
@click="handleAD(item)">
<view class="ad-image-container">
<image :src="item.bannerUrl"
class="ad-image"
mode="aspectFill"
:lazy-load="true">
</image>
</view>
</swiper-item>
</swiper>
<view class="ad-close" @click="closeAd">
<text class="cuIcon-roundclose"></text>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
import {
getBannerList,
getActivities
} from '@/api/bar.js'
import {
listFeaturePage
} from '@/api/platform.js'
import loginPopup from '@/components/loginPopup.vue';
import rowBeer from '@/components/rowBeer.vue'
import ActivityItem from '@/components/ActivityItem.vue'
export default {
components: {
loginPopup,
rowBeer,
ActivityItem
},
data() {
return {
statusBaeHeight: 0,
curTag: 0,
ADList: [], // 广告弹窗
bannerJoin: null, // 认证门店banner
showJoinImg: false, // 是否显示认证门店图片
userInfo: null,
featurePageList: [], // 活动列表
homeBanner: [], //首页banner
keyword: '',
pageNum: 1,
pageSize: 10,
total: 0,
loading: false,
finished: false,
navItems: ['新酒上市', '生成酒单', '酒币换购', '关注厂牌'],
currentAdIndex: 0, // 当前广告索引
};
},
created() {
console.log('Index page created')
},
mounted() {
console.log('Index page mounted')
},
onReady() {
console.log('Index page ready')
// 确保数据已加载
if (this.featurePageList.length === 0) {
this.getActivityList()
}
},
watch: {
featurePageList: {
handler(newVal) {
console.log('featurePageList changed', newVal)
},
deep: true
}
},
onLoad() {
// setTimeout(() => {
// uni.setNavigationBarColor({
// frontColor: '#ffffff',
// backgroundColor: '#FFFFFF',
// animation: {
// duration: 400,
// timingFunc: 'easeIn'
// }
// })
// }, 500)
this.statusBaeHeight = uni.getWindowInfo.statusBarHeight
this.getBannerListFun() // 广告轮播图
uni.showShareMenu({
menus: ['shareAppMessage', 'shareTimeline']
})
// 禁用页面下拉刷新
uni.stopPullDownRefresh()
},
onShow() {
const newUserInfo = uni.getStorageSync('userInfo')
// 只在用户信息发生变化时更新状态
if (JSON.stringify(newUserInfo) !== JSON.stringify(this.userInfo)) {
this.userInfo = newUserInfo
this.showJoinImg = !this.userInfo || this.userInfo.userType === '09'
// 只在用户状态变化时重新加载数据
this.resetAndLoadData()
}
},
methods: {
loginSuccess() {
this.userInfo = uni.getStorageSync('userInfo')
this.showJoinImg = !this.userInfo || this.userInfo.userType === '09'
this.resetAndLoadData()
},
// 重置数据并重新加载
resetAndLoadData() {
this.pageNum = 1
this.featurePageList = []
this.finished = false
this.getActivityList()
},
// 获取活动列表
async getActivityList() {
if (this.loading || this.finished) return
this.loading = true
try {
const res = await getActivities({
pageNum: this.pageNum,
pageSize: this.pageSize,
keyword: this.keyword
})
if (res.rows && res.rows.length > 0) {
if (this.pageNum === 1) {
this.featurePageList = res.rows
} else {
this.featurePageList = [...this.featurePageList, ...res.rows]
}
this.total = res.total
this.pageNum++
// 判断是否加载完成
if (this.featurePageList.length >= this.total) {
this.finished = true
}
} else {
this.finished = true
}
} catch (error) {
console.error('获取活动列表失败:', error)
uni.showToast({
title: '加载失败',
icon: 'none'
})
} finally {
this.loading = false
}
},
// 加载更多
changePage() {
if (!this.loading && !this.finished) {
this.getActivityList()
}
},
// 更多热门活动
moreHotActivity() {
uni.navigateTo({
url: '/pages/activityList/activityList'
})
},
// 处理活动点击
handleActivityClick(item) {
uni.navigateTo({
url: `/pages/activityList/details?id=${item.id}`
})
},
// 跳转酒评页
toReview(it) {
uni.navigateTo({
url: "/pages/index/review?beerId=" + it.id
})
},
// 查询广告弹窗 banner列表
getBannerListFun() {
this.ADList = []
this.homeBanner = []
this.bannerJoin = null
getBannerList().then(res => {
res.data.forEach(it => {
if (it.bannerType == 'homeAD') { // 开屏广告
this.ADList.push(it)
} else if (it.bannerType == 'homeJoin') { // 认证门店
this.bannerJoin = it
} else if (it.bannerType == 'homeBanner') { // 首页banner
this.homeBanner.push(it)
}
})
let showHomeAD = uni.getStorageSync('showHomeAD')
if (!showHomeAD) {
this.$refs.ADRef.open()
}
})
},
// 关闭广告
closeAd() {
uni.setStorageSync('showHomeAD', true)
uni.setTabBarStyle({
backgroundColor: '#ffffff'
})
this.$refs.ADRef.close()
},
handleAD(item) {
this.closeAd()
if (item.bannerLink) {
uni.navigateTo({
url: item.bannerLink,
})
}
},
// 立即认证门店
toJoin() {
if (!this.bannerJoin) return
uni.navigateTo({
url: this.bannerJoin.bannerLink,
})
},
// 搜索
toSearch() {
uni.navigateTo({
url: '/pagesActivity/homeSearch'
})
},
// 导航跳转
toGo(index) {
switch(index) {
case 1: // 新酒上市
uni.navigateTo({
url: '/pages/index/newBeer'
})
break;
case 2: // 生成酒单
uni.navigateTo({
url: '/pages/index/featureInfo'
})
break;
case 3: // 酒币换购
uni.navigateTo({
url: '/pagesCoin/beerCoin'
})
break;
case 4: // 关注厂牌
uni.navigateTo({
url: '/pages/index/myJoin'
})
break;
}
},
// 处理广告轮播切换
handleAdSwiperChange(e) {
this.currentAdIndex = e.detail.current
},
// 处理弹窗状态变化
handlePopupChange(e) {
if (!e.show) {
this.closeAd()
}
}
}
}
</script>
<style lang="scss" scoped>
/deep/.uni-popup {
z-index: 1025;
}
.page {
background: #F9F9F9;
min-height: 100vh;
display: flex;
flex-direction: column;
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", Roboto, "Segoe UI", "Microsoft YaHei", sans-serif;
.join-box {
width: 100%;
height: 562rpx;
background: #f5f5f5;
position: relative;
overflow: hidden;
.img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
}
.search-box {
border-radius: 24rpx;
width: 700rpx;
height: 80rpx;
background-color: #F9F9F9;
display: flex;
align-items: center;
padding: 32rpx 0;
margin: 26rpx auto;
box-sizing: border-box;
box-shadow: 0rpx 1rpx 3rpx 0rpx rgba(0, 0, 0, 0.1);
.search-input {
flex: 1;
display: flex;
align-items: center;
padding: 0 24rpx;
}
.searchs{
background: #D42E78;
width: 80rpx;
height: 80rpx;
border-radius: 0 24rpx 24rpx 0;
display: flex;
justify-content: center;
align-items: center;
box-shadow: 0rpx 1rpx 3rpx 0rpx rgba(0, 0, 0, 0.1);
}
}
.section-title {
margin: 46rpx 24rpx 32rpx 24rpx;
font-size: 40rpx;
font-weight: bold;
color: #030303;
}
.list-container {
flex: 1;
display: flex;
flex-direction: column;
min-height: 200rpx;
position: relative;
z-index: 0;
scroll-view {
flex: 1;
}
.activity-list {
padding: 0 32rpx;
opacity: 1;
transition: opacity 0.3s ease;
&.loading {
opacity: 0.6;
}
}
.more-btn-box {
width: 92%;
height: 88rpx;
margin: 32rpx auto;
background: linear-gradient(135deg, #19367A, #2C4C99);
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4rpx 16rpx rgba(25, 54, 122, 0.2);
transition: all 0.3s ease;
&:active {
transform: scale(0.98);
box-shadow: 0 2rpx 8rpx rgba(25, 54, 122, 0.1);
}
.more-btn {
font-size: 28rpx;
font-weight: 600;
letter-spacing: 2rpx;
color: #FFFFFF;
}
}
}
.join-box {
// margin: 20rpx 0;
// border-radius: 30rpx;
box-sizing: border-box;
// border: 1.5px solid #F2F2F2;
// padding: 34rpx 26rpx;
// height: 450rpx;
// height: 1130rpx;
height: 562rpx;
display: flex;
flex-direction: column;
justify-content: space-around;
.btn {
width: 582rpx;
height: 68rpx;
border-radius: 24rpx;
text-align: center;
line-height: 68rpx;
margin: 0 auto;
background: #D42E78;
}
.img {
width: 100%;
height: 100%;
}
}
.swiper {
margin-bottom: 20rpx;
height: 400rpx;
}
// 快捷导航
.nav-item {
text-align: center;
color: #0B0E26;
.img-box {
width: 146rpx;
height: 146rpx;
background: #F9F9F9;
border-radius: 50%;
margin-bottom: 18rpx;
box-shadow: 0rpx 1rpx 3rpx 0rpx rgba(0, 0, 0, 0.1);
}
}
.quickNav-box {
border-radius: 20rpx;
background: #FFFFFF;
width: 100%;
padding: 32rpx 24rpx;
height: 490rpx;
box-sizing: border-box;
.left {
height: 416rpx;
width: 352rpx;
// width: 47%;
border-radius: 20rpx;
margin-right: 22rpx;
}
.right {
height: 196rpx;
// width: 326rpx;
width: 100%;
margin-bottom: 22rpx;
border-radius: 20rpx;
}
}
.goods-box {
border-radius: 30rpx;
background: rgba(255, 255, 255, 0.2);
box-sizing: border-box;
border: 1px solid #F2F2F2;
box-shadow: 0px 5.47px 43.78px 0px rgba(0, 0, 0, 0.05);
display: flex;
padding: 16rpx 32rpx;
margin: 20rpx 32rpx 0;
.cover {
width: 208rpx;
height: 300rpx;
border-radius: 30rpx;
margin-right: 14rpx;
}
}
.tag {
background-color: transparent;
border-radius: 12rpx;
padding: 12rpx 20rpx;
border: 1px solid #9D9D9D;
;
margin-right: 24rpx;
margin-bottom: 50rpx;
}
.active-tag {
background-color: #FEE034;
font-weight: bold;
border: 1px solid #FEE034;
}
.title-box {
padding: 24rpx 32rpx;
margin-bottom: 28rpx;
box-sizing: border-box;
.title {
font-size: 32rpx;
font-weight: bold;
color: #1E2019;
line-height: 130%;
}
.sub {
font-size: 20rpx;
color: #9D9D9D;
}
}
.zixuns {
padding: 0 34rpx 0 20rpx;
background: rgba(0, 0, 0, 0.6);
}
.bg-white {
background: #FFFFFF;
border-radius: 30rpx 30rpx 12rpx 12rpx;
padding-top: 8rpx;
position: relative;
transform: translateY(-20rpx);
z-index: 1;
.search-box {
margin: 24rpx 32rpx;
}
}
.activity-item {
display: block;
}
.hover-effect {
transition: all 0.2s ease;
&:active {
transform: scale(0.96);
opacity: 0.8;
}
}
.search-box {
// ... existing code ...
&:active {
transform: scale(0.98);
opacity: 0.9;
}
}
.nav-item {
// ... existing code ...
&:active {
transform: scale(0.95);
opacity: 0.8;
}
}
.more-btn-box {
// ... existing code ...
&:active {
transform: scale(0.98);
opacity: 0.9;
}
}
.activity-item {
// ... existing code ...
&:active {
transform: scale(0.98);
opacity: 0.9;
}
}
// 添加图片加载优化相关样式
.img {
width: 100%;
height: 100%;
will-change: transform;
backface-visibility: hidden;
transform: translateZ(0);
}
// 添加骨架屏样式
.skeleton {
background: linear-gradient(90deg, #f2f2f2 25%, #e6e6e6 37%, #f2f2f2 63%);
background-size: 400% 100%;
animation: skeleton-loading 1.4s ease infinite;
}
@keyframes skeleton-loading {
0% {
background-position: 100% 50%;
}
100% {
background-position: 0 50%;
}
}
.ad-container {
position: relative;
width: 750rpx;
height: 70vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
animation: fadeIn 0.3s ease;
padding: 0 40rpx;
box-sizing: border-box;
}
.ad-swiper {
width: 100%;
height: 85%;
overflow: visible;
}
.ad-swiper-item {
box-sizing: border-box;
transition: all 0.3s ease;
transform: scale(0.85);
opacity: 0.6;
&.active {
transform: scale(1);
opacity: 1;
}
}
.ad-image-container {
width: 100%;
height: 100%;
position: relative;
border-radius: 30rpx;
overflow: hidden;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.15);
}
.ad-image {
width: 100%;
height: 100%;
border-radius: 30rpx;
will-change: transform;
backface-visibility: hidden;
transform: translateZ(0);
}
.ad-close {
margin-top: 40rpx;
width: 72rpx;
height: 72rpx;
display: flex;
justify-content: center;
align-items: center;
background: rgba(255, 255, 255, 0.15);
border-radius: 50%;
backdrop-filter: blur(10px);
transition: all 0.3s ease;
.cuIcon-roundclose {
font-size: 44rpx;
color: #FFFFFF;
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.2);
}
&:active {
transform: scale(0.9);
opacity: 0.8;
background: rgba(255, 255, 255, 0.25);
}
}
/deep/ .uni-swiper-dots {
bottom: -20rpx !important;
.uni-swiper-dot {
width: 12rpx !important;
height: 12rpx !important;
border-radius: 6rpx !important;
margin: 0 6rpx !important;
transition: all 0.3s ease !important;
background: rgba(255, 255, 255, 0.3) !important;
&.uni-swiper-dot-active {
width: 28rpx !important;
background-color: #FFFFFF !important;
box-shadow: 0 2rpx 8rpx rgba(255, 255, 255, 0.3);
}
}
}
// 添加过渡效果
.fade-enter-active, .fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
</style>