851 lines
19 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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 commonTitle from '@/components/commonTitle.vue'
import loginPopup from '@/components/loginPopup.vue';
import rowBeer from '@/components/rowBeer.vue'
import ActivityItem from '@/components/ActivityItem.vue'
export default {
components: {
commonTitle,
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')
if (this.userInfo == null || this.userInfo.userType == '09') { // 没登录或者没认证门店
console.log('登录')
this.showJoinImg = true
} else {
this.showJoinImg = false
}
},
// 重置并加载数据
resetAndLoadData() {
this.pageNum = 1
this.finished = false
this.featurePageList = []
this.getActivityList()
},
// 获取活动列表
async getActivityList() {
if (this.loading || this.finished) return
try {
this.loading = true
const res = await getActivities({
pageNum: this.pageNum,
pageSize: this.pageSize
})
if (res.code === 200) {
const { rows, total } = res
// 处理数据,计算剩余天数和状态
const processedRows = this.processActivityData(rows)
// 更新列表数据
if (this.pageNum === 1) {
this.featurePageList = processedRows
} else {
this.featurePageList = [...this.featurePageList, ...processedRows]
}
this.total = total
this.finished = this.featurePageList.length >= total
this.pageNum++
}
} catch (error) {
console.error('获取活动列表失败:', error)
} finally {
this.loading = false
}
},
// 处理活动数据
processActivityData(rows) {
return rows.map(it => {
// 计算剩余天数
const targetDate = new Date(it.endDate)
const currentDate = new Date()
const timeDiff = targetDate.getTime() - currentDate.getTime()
const remainingDays = Math.ceil(timeDiff / (1000 * 3600 * 24))
// 设置活动状态
let activityState = 'recruiting'
if (remainingDays <= 0) {
activityState = 'completed'
} else if (it.activityStatus === 2) {
activityState = 'in_progress'
} else if (it.activityStatus === 3) {
activityState = 'completed'
}
return {
...it,
remainingDays,
activityState,
remainingBeerCount: it.remainingBeerCount || 0,
barAwardStatus: it.barAwardStatus || 0
}
})
},
// 修改页面加载更多方法
async changePage() {
if (!this.finished) {
await this.getActivityList()
}
},
handleActivityClick(item) {
console.log('handleActivityClick called', item)
uni.navigateTo({
url: "/pagesActivity/activityDetail?id=" + item.id
})
},
handlePopupChange(e) {
if (e && e.detail) {
this.currentAdIndex = e.detail.current;
}
},
handleAdSwiperChange(e) {
if (e && e.detail) {
this.currentAdIndex = e.detail.current;
}
},
toAddAiad() {
uni.navigateTo({
url: '/pagesMy/addAiad'
})
},
// 搜索
toSearch() {
uni.navigateTo({
url: '/pagesActivity/homeSearch',
success: () => {
uni.$emit('openKeyboard')
}
})
},
changeTag(index) {
this.curTag = index
},
// 查询广告弹窗 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)
}
})
// 检查是否需要显示开屏广告
this.checkShowAD()
})
},
// 检查是否需要显示开屏广告
checkShowAD() {
if (this.ADList.length === 0) return
const currentSession = uni.getStorageSync('currentSession')
const newSession = Date.now()
// 每次打开小程序都显示广告
if (!currentSession || currentSession !== newSession) {
this.$refs.ADRef.open()
// 记录本次会话时间
uni.setStorageSync('currentSession', newSession)
}
},
// 关闭广告
closeAd() {
this.$refs.ADRef.close()
},
handleAD(item) {
this.closeAd()
if (item.bannerLink) {
uni.navigateTo({
url: item.bannerLink,
})
}
},
// 跳转专辑页
toFeaturePage(item) {
uni.navigateTo({
url: `/pages/index/featureInfo?id=${item.id}`
})
},
// 查询专辑页列表
getFeaturePageListFun() {
listFeaturePage().then(res => {
this.featurePageList = res.data
})
},
// 跳转酒评页
toReview(it) {
uni.navigateTo({
url: "/pages/index/review?beerId=" + it.id
})
},
toGo(key) {
switch (key) {
case 1: // 新酒上市
uni.navigateTo({
url: "/pages/index/newBeer"
})
break;
case 2: // 生成酒单
uni.navigateTo({
url: "/pagesActivity/winelist"
})
break;
case 3: //酒币换购
uni.navigateTo({
url: "/pagesCoin/beerCoin"
})
break;
case 4: // 关注酒厂
uni.navigateTo({
url: '/pagesMy/myAttention'
})
break;
}
},
// 更多热门活动
moreHotActivity() {
uni.navigateTo({
url: "/pages/activityList/activityList"
})
},
search() {
// 实现搜索逻辑
console.log('搜索关键词:', this.keyword);
},
changeSearch() {
// 实现搜索逻辑
console.log('搜索关键词:', this.keyword);
},
}
}
</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>