zdtap-uniapp-main/components/ActivityItem.vue

331 lines
8.1 KiB
Vue
Raw Permalink 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="activity-item flex" v-if="isActivityVisible" @click="handleClick">
<view class="store-tag" v-if="item.activityType === 1">指定门店</view>
<view class="left">
<image :src="item.brandLogo" class="brand-logo"></image>
<view class="status-content">
<text v-if="activityState === 'recruiting' && item.remainingDays > 0" class="status-label">招募剩余天数</text>
<text v-else-if="activityState === 'recruiting' && item.remainingDays <= 0" class="status-label">活动招募已结束</text>
<text v-else-if="activityState === 'inProgress'" class="status-label">距离达成还剩</text>
<view class="status-box">
<template v-if="activityState === 'recruiting' && item.remainingDays > 0">
<view class="days-left">
<text class="days-num">{{item.remainingDays}}</text>
<text class="days-unit"></text>
</view>
</template>
<template v-else-if="activityState === 'recruiting' && item.remainingDays <= 0">
<view class="status-text">
<view class="end-date">{{formatDate(item.endDate)}}</view>
<view>已结束</view>
</view>
</template>
<template v-else-if="activityState === 'inProgress'">
<view v-if="item.remainingBeerCount > 0" class="beer-count">
<text class="count-num">{{item.remainingBeerCount}}</text>
<text class="count-unit"></text>
</view>
</template>
<template v-else-if="activityState === 'completed'">
<view class="status-text">
{{!item.barAwardStatus ? '待兑付' : '已完成'}}
</view>
</template>
</view>
</view>
</view>
<view class="right">
<view class="title">{{ item.breweryName }}</view>
<view class="sub">时间首次扫码开始累计 <text class="highlight">{{item.duration}}天内</text></view>
<view class="sub">目标{{item.beerScope === 0 ? '品牌全系' : '以下'}}酒款累积扫码 <text class="highlight">{{ item.activityTarget}}</text></view>
<scroll-view v-if="item.beers" scroll-x="true" class="scroll-img" enhanced show-scrollbar="false">
<view class="beer-box" v-for="(beer, beerIndex) in item.beers" :key="beerIndex" @click.stop="handleReview(beer)">
<image v-if="beer.cover" :src="beer.cover" class="cover" mode="aspectFit"></image>
</view>
</scroll-view>
<view class="reward-info">
<text v-if="item.activityRewardType == 2 || (item.activityRewardType == 1 && item.activityRewardGoods)" class="zeng"></text>
<text v-if="item.activityRewardType == 1 && item.activityRewardGoods" class="reward-text">{{item.activityRewardGoods.goodsName}} {{item.activityRewardGoods.specs}} 奖励数量{{item.activityRewardCount}}</text>
<text v-if="item.activityRewardType == 2" class="reward-text">品牌啤酒币 奖励数量 {{item.activityRewardCount}}</text>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'activity-item',
props: {
item: {
type: Object,
required: true
}
},
created() {
console.log('ActivityItem created', this.item)
},
mounted() {
console.log('ActivityItem mounted', this.item)
},
computed: {
// 判断活动是否可显示
isActivityVisible() {
// 获取用户所在城市
const userCity = uni.getStorageSync('userCity');
// 未登录用户或未设置城市的用户,只显示全国活动
if (!userCity) {
return this.item.city === '全国';
}
// 已登录用户,显示全国活动和所在城市的活动
return this.item.city === '全国' || this.item.city === userCity;
},
activityState() {
if (this.item.activityStatus === 1) {
return 'recruiting';
} else if (this.item.activityStatus === 2) {
return 'inProgress';
} else if (this.item.activityStatus === 3) {
return 'completed';
}
return '';
}
},
methods: {
handleClick() {
console.log('ActivityItem clicked', this.item)
this.$emit('click', this.item)
},
handleReview(beer) {
console.log('ActivityItem review clicked', beer)
this.$emit('review', beer)
},
formatDate(dateString) {
if (!dateString) return '';
const date = new Date(dateString);
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
return `${year}-${month}-${day}`;
}
}
}
</script>
<style lang="scss" scoped>
/* 活动项容器样式 */
.activity-item {
position: relative;
width: 702rpx;
margin-bottom: 48rpx;
transition: transform 0.2s ease;
&:active {
transform: scale(0.98);
}
.store-tag {
position: absolute;
top: 24rpx;
right: 24rpx;
font-size: 20rpx;
color: #FFFFFF;
background-color: #D42E78;
padding: 6rpx 16rpx;
border-radius: 8rpx;
z-index: 2;
box-shadow: 0 2rpx 6rpx rgba(212, 46, 120, 0.3);
}
.right {
width: 702rpx;
min-height: 428rpx;
background: #FFFFFF;
border-radius: 20rpx;
padding: 24rpx 32rpx 24rpx 200rpx;
box-sizing: border-box;
box-shadow: 0 8rpx 16rpx rgba(0, 0, 0, 0.08);
position: relative;
z-index: 1;
border: 1px solid #EFEDE9;
.title {
font-size: 36rpx;
font-weight: bold;
line-height: 48rpx;
color: #0B0E26;
margin-bottom: 16rpx;
}
.sub {
font-size: 28rpx;
font-weight: 500;
line-height: 44rpx;
color: #0B0E26;
margin-bottom: 16rpx;
.highlight {
color: #D42E78;
font-weight: bold;
}
}
.scroll-img {
width: 100%;
display: flex;
flex-direction: row;
white-space: nowrap;
height: 200rpx;
margin-bottom: 16rpx;
overflow-x: auto;
padding: 4rpx 0;
.beer-box {
width: 120rpx;
height: 170rpx;
background: #FFFFFF;
margin-right: 8rpx;
box-sizing: border-box;
display: inline-flex;
align-items: center;
justify-content: center;
transition: transform 0.2s;
border-radius: 12rpx;
overflow: hidden;
position: relative;
&:active {
transform: scale(0.95);
}
.cover {
width: 100%;
height: 100%;
border-radius: 12rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
object-fit: contain;
}
}
}
.reward-info {
display: flex;
align-items: center;
margin-top: 8rpx;
}
.zeng {
font-size: 22rpx;
font-weight: bold;
line-height: normal;
text-align: center;
color: #0B0E26;
padding: 8rpx 16rpx;
border-radius: 10rpx;
background: #FEE034;
margin-right: 20rpx;
box-shadow: 0 2rpx 4rpx rgba(254, 224, 52, 0.3);
}
.reward-text {
color: #0B0E26;
font-size: 26rpx;
line-height: 36rpx;
}
}
.left {
position: absolute;
left: 0;
top: -12rpx;
height: calc(100% + 24rpx);
width: 180rpx;
padding: 40rpx 24rpx;
background: #FFFFFF;
border-radius: 20rpx;
box-sizing: border-box;
border: 1px solid #EFEDE9;
z-index: 3;
box-shadow: 0rpx 1rpx 3rpx 0rpx rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
align-items: center;
.brand-logo {
width: 132rpx;
height: 132rpx;
border-radius: 6rpx;
margin-bottom: 40rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.status-content {
display: flex;
flex-direction: column;
align-items: center;
.status-label {
color: #606060;
font-size: 24rpx;
font-weight: bold;
white-space: nowrap;
margin-bottom: 46rpx;
}
.status-box {
text-align: center;
.days-left {
display: flex;
align-items: baseline;
justify-content: center;
.days-num {
font-size: 72rpx;
color: #D42E78;
font-weight: bold;
line-height: 1;
}
.days-unit {
font-size: 24rpx;
color: #606060;
margin-left: 4rpx;
}
}
.beer-count {
display: flex;
align-items: baseline;
justify-content: center;
.count-num {
font-size: 48rpx;
color: #19367A;
font-weight: bold;
line-height: 1;
}
.count-unit {
font-size: 24rpx;
color: #606060;
margin-left: 4rpx;
}
}
.status-text {
font-size: 28rpx;
color: #19367A;
font-weight: bold;
.end-date {
font-size: 20rpx;
color: #606060;
font-weight: normal;
margin-bottom: 24rpx;
}
}
}
}
}
}
</style>