1029 lines
27 KiB
Vue
1029 lines
27 KiB
Vue
<template>
|
||
<view class="scan-result">
|
||
<!-- 已失效状态 -->
|
||
<template v-if="errorType === 'expired' || info.qrcode.qrcodeStatus == 2">
|
||
<view class="scan-result__header">
|
||
<image src="/static/information.svg" class="scan-result__icon"></image>
|
||
<text class="scan-result__title">该二维码无法领取品牌返利</text>
|
||
<text class="scan-result__desc">失效原因:{{ info.qrcode.remark}}</text>
|
||
</view>
|
||
|
||
<view class="scan-result__content">
|
||
<view class="scan-result__section">
|
||
<text class="scan-result__section-title">商品详细</text>
|
||
<view class="product-card" v-if="beer">
|
||
<view class="product-card__image">
|
||
<image :src="beer.cover" mode="aspectFill"></image>
|
||
</view>
|
||
<view class="product-card__info">
|
||
<text class="product-card__name">{{ beer.beerName }}</text>
|
||
<text class="product-card__brand">{{ beer.brandName }}</text>
|
||
<view class="product-card__detail">
|
||
<text class="product-card__label">生产日期:</text>
|
||
<text class="product-card__value">{{ beer.launchDate }}</text>
|
||
</view>
|
||
<view class="product-card__detail">
|
||
<text class="product-card__label">净含量:</text>
|
||
<text class="product-card__value">{{ beer.netContent }}</text>
|
||
</view>
|
||
<view class="product-card__rating">
|
||
<view class="rating-stars">
|
||
<text class="cuIcon-favorfill"></text>
|
||
<text class="rating-value">{{ beer.beerOverallRating }}</text>
|
||
</view>
|
||
<text class="rating-count">{{ beer.beerReviewsCount }} 条评论</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="scan-result__footer">
|
||
<button class="scan-result__btn scan-result__btn--back" @click="back">
|
||
<image src="/static/undo.svg"></image>
|
||
<text>返回</text>
|
||
</button>
|
||
<button class="scan-result__btn scan-result__btn--share" @click="share">
|
||
<image src="/static/send-2.svg"></image>
|
||
<text>分享上新</text>
|
||
</button>
|
||
</view>
|
||
</template>
|
||
|
||
<!-- 领取成功状态 - 刚刚领取成功 -->
|
||
<template v-if="info.qrcode.qrcodeStatus == 1 && isJustReceived">
|
||
<view class="scan-result__header scan-result__header--success">
|
||
<image src="/static/tick-circle.svg" class="scan-result__icon"></image>
|
||
<text class="scan-result__title">领取成功!</text>
|
||
</view>
|
||
|
||
<view class="scan-result__content">
|
||
<view class="scan-result__section">
|
||
<text class="scan-result__section-title">商品详细</text>
|
||
<view class="product-card" v-if="beer">
|
||
<view class="product-card__image">
|
||
<image :src="beer.cover" mode="aspectFill"></image>
|
||
</view>
|
||
<view class="product-card__info">
|
||
<text class="product-card__name">{{ beer.beerName }}</text>
|
||
<text class="product-card__brand">{{ beer.brandName }}</text>
|
||
<view class="product-card__detail">
|
||
<text class="product-card__label">生产日期:</text>
|
||
<text class="product-card__value">{{ beer.launchDate }}</text>
|
||
</view>
|
||
<view class="product-card__detail">
|
||
<text class="product-card__label">净含量:</text>
|
||
<text class="product-card__value">{{ beer.netContent }}</text>
|
||
</view>
|
||
<view class="product-card__rating">
|
||
<view class="rating-stars">
|
||
<text class="cuIcon-favorfill"></text>
|
||
<text class="rating-value">{{ beer.beerOverallRating }}</text>
|
||
</view>
|
||
<text class="rating-count">{{ beer.beerReviewsCount }} 条评论</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="scan-result__section">
|
||
<text class="scan-result__section-title">品牌福利</text>
|
||
<view class="benefit-card">
|
||
<view class="benefit-card__title">{{ beer.scanCoinCount}}枚({{beer.brandName}})品牌啤酒币已到账</view>
|
||
<text class="benefit-card__subtitle">品牌啤酒币可用于兑换好礼</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="scan-result__footer">
|
||
<button class="scan-result__btn scan-result__btn--back" @click="toWinelist">
|
||
<image src="@/static/document.png"></image>
|
||
<text>生成酒单</text>
|
||
</button>
|
||
<button class="scan-result__btn scan-result__btn--share" @click="share">
|
||
<image src="/static/send-2.svg"></image>
|
||
<text>分享上新</text>
|
||
</button>
|
||
</view>
|
||
</template>
|
||
|
||
<!-- 再次扫码已领取的商品 -->
|
||
<template v-if="info.qrcode.qrcodeStatus == 1 && !isJustReceived">
|
||
<view class="scan-result__header">
|
||
<image src="/static/information.svg" class="scan-result__icon"></image>
|
||
<text class="scan-result__title">该桶产品已于 {{ info.qrcode.verifyTime }} 扫码领取成功</text>
|
||
</view>
|
||
|
||
<view class="scan-result__content">
|
||
<view class="scan-result__section">
|
||
<text class="scan-result__section-title">商品详细</text>
|
||
<view class="product-card" v-if="beer">
|
||
<view class="product-card__image">
|
||
<image :src="beer.cover" mode="aspectFill"></image>
|
||
</view>
|
||
<view class="product-card__info">
|
||
<text class="product-card__name">{{ beer.beerName }}</text>
|
||
<text class="product-card__brand">{{ beer.brandName }}</text>
|
||
<view class="product-card__detail">
|
||
<text class="product-card__label">生产日期:</text>
|
||
<text class="product-card__value">{{ beer.launchDate }}</text>
|
||
</view>
|
||
<view class="product-card__detail">
|
||
<text class="product-card__label">净含量:</text>
|
||
<text class="product-card__value">{{ beer.netContent }}</text>
|
||
</view>
|
||
<view class="product-card__rating">
|
||
<view class="rating-stars">
|
||
<text class="cuIcon-favorfill"></text>
|
||
<text class="rating-value">{{ beer.beerOverallRating }}</text>
|
||
</view>
|
||
<text class="rating-count">{{ beer.beerReviewsCount }} 条评论</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="scan-result__footer">
|
||
<button class="scan-result__btn scan-result__btn--back" @click="toWinelist">
|
||
<image src="@/static/document.png"></image>
|
||
<text>生成酒单</text>
|
||
</button>
|
||
<button class="scan-result__btn scan-result__btn--share" @click="share">
|
||
<image src="/static/send-2.svg"></image>
|
||
<text>分享上新</text>
|
||
</button>
|
||
</view>
|
||
</template>
|
||
|
||
<!-- 待领取状态 -->
|
||
<template v-if="info.qrcode.qrcodeStatus == 0">
|
||
<view class="scan-result__content">
|
||
<view class="scan-result__section">
|
||
<text class="scan-result__section-title">商品详细</text>
|
||
<view class="product-card" v-if="beer">
|
||
<view class="product-card__image">
|
||
<image :src="beer.cover" mode="aspectFill"></image>
|
||
</view>
|
||
<view class="product-card__info">
|
||
<text class="product-card__name">{{ beer.beerName }}</text>
|
||
<text class="product-card__brand">{{ beer.brandName }}</text>
|
||
<view class="product-card__detail">
|
||
<text class="product-card__label">生产日期:</text>
|
||
<text class="product-card__value">{{ beer.launchDate }}</text>
|
||
</view>
|
||
<view class="product-card__detail">
|
||
<text class="product-card__label">净含量:</text>
|
||
<text class="product-card__value">{{ beer.netContent }}</text>
|
||
</view>
|
||
<view class="product-card__rating">
|
||
<view class="rating-stars">
|
||
<text class="cuIcon-favorfill"></text>
|
||
<text class="rating-value">{{ beer.beerOverallRating }}</text>
|
||
</view>
|
||
<text class="rating-count">{{ beer.beerReviewsCount }} 条评论</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="scan-result__section">
|
||
<text class="scan-result__section-title">品牌福利</text>
|
||
<view class="benefit-card">
|
||
<view class="benefit-card__title">可获得 {{ beer.scanCoinCount }}枚{{beer.brandName}}品牌啤酒币</view>
|
||
<text class="benefit-card__subtitle">品牌啤酒币可用于兑换好礼</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="activity-notice" v-if="activitySum > 1">
|
||
<image src="/static/warning.svg" mode="aspectFit"></image>
|
||
<text>该产品有多个进行中活动重叠,请选择要计入的活动</text>
|
||
</view>
|
||
|
||
<view class="scan-result__section" v-if="activity && activity.length > 0">
|
||
<text class="scan-result__section-title">品牌活动</text>
|
||
<view class="activity-list">
|
||
<view
|
||
class="activity-item"
|
||
v-for="(item, index) in activity"
|
||
:key="index"
|
||
:class="{'activity-item--selected': activityId === item.id}"
|
||
@click="selectPPF(item)"
|
||
>
|
||
<!-- <view class="activity-item__header">
|
||
<text class="activity-item__title">{{ item.breweryName }}</text>
|
||
</view> -->
|
||
<view class="activity-item__tag-container">
|
||
<text class="activity-item__tag activity-item__tag--store" v-if="item.activityType === 1">指定门店</text>
|
||
<text class="activity-item__tag activity-item__tag--new" v-if="item.activityType === 2">招募活动</text>
|
||
</view>
|
||
<view class="activity-item__content">
|
||
<view class="activity-item__progress">
|
||
<text>距离累计目标达成还剩</text>
|
||
<text class="activity-item__remaining-count">{{item.remainingBeerCount}}桶</text>
|
||
</view>
|
||
<view class="activity-item__time">
|
||
<text>时间:首次扫码开始累计</text>
|
||
<text class="activity-item__duration">{{item.duration}}天内</text>
|
||
</view>
|
||
<view class="activity-item__deadline" v-if="item.remainingDays">
|
||
<text>活动截止还剩</text>
|
||
<text class="activity-item__remaining-days">{{item.remainingDays}}天</text>
|
||
</view>
|
||
<view class="activity-item__target">
|
||
<text>目标:{{item.beerScope === 0 ? '品牌全系' : '以下'}}酒款累积扫码 ≥ </text>
|
||
<text class="activity-item__count">{{ item.activityTarget}}桶</text>
|
||
</view>
|
||
<scroll-view v-if="item.beers && item.beers.length > 0"
|
||
scroll-x="true"
|
||
class="activity-item__beers"
|
||
enhanced
|
||
show-scrollbar="false"
|
||
>
|
||
<view
|
||
class="activity-item__beer"
|
||
v-for="(beer, beerIndex) in item.beers"
|
||
:key="beerIndex"
|
||
>
|
||
<image v-if="beer.cover" :src="beer.cover" mode="aspectFit"></image>
|
||
</view>
|
||
</scroll-view>
|
||
<view class="activity-item__reward">
|
||
<text class="activity-item__reward-tag">赠</text>
|
||
<view class="activity-item__reward-content" v-if="item.activityRewardType == 1 && item.activityRewardGoods">
|
||
<image
|
||
v-if="item.activityRewardGoods.cover"
|
||
:src="item.activityRewardGoods.cover"
|
||
class="activity-item__reward-image"
|
||
mode="aspectFit"
|
||
></image>
|
||
<view class="activity-item__reward-info">
|
||
<text class="activity-item__reward-name">{{item.activityRewardGoods.goodsName}}</text>
|
||
<text class="activity-item__reward-specs">规格:{{item.activityRewardGoods.specs}}</text>
|
||
<text class="activity-item__reward-count">数量:{{item.activityRewardCount}}份</text>
|
||
</view>
|
||
</view>
|
||
<view class="activity-item__reward-content" v-if="item.activityRewardType == 2">
|
||
<image
|
||
src="/static/coin.png"
|
||
class="activity-item__reward-image"
|
||
mode="aspectFit"
|
||
></image>
|
||
<view class="activity-item__reward-info">
|
||
<text class="activity-item__reward-name">品牌啤酒币</text>
|
||
<text class="activity-item__reward-count">数量:{{item.activityRewardCount}}枚</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="scan-result__section" v-if="platformActivity && platformActivity.length > 0">
|
||
<text class="scan-result__section-title">平台活动</text>
|
||
<view class="activity-list">
|
||
<view
|
||
class="activity-item"
|
||
v-for="(item, index) in platformActivity"
|
||
:key="index"
|
||
:class="{'activity-item--selected': platformActivityId === item.id}"
|
||
@click="selectPlatform(item)"
|
||
>
|
||
<view class="activity-item__header">
|
||
<text class="activity-item__title">{{ item.activityName }}</text>
|
||
</view>
|
||
<view class="activity-item__tag-container">
|
||
<text class="activity-item__tag activity-item__tag--store" v-if="item.activityType === 1">指定门店</text>
|
||
<text class="activity-item__tag activity-item__tag--new" v-if="item.activityType === 2">招募活动</text>
|
||
</view>
|
||
<view class="activity-item__content">
|
||
<view class="activity-item__progress">
|
||
<text>距离达成还剩</text>
|
||
<text class="activity-item__remaining-count">{{item.remainingBeerCount}}桶</text>
|
||
</view>
|
||
<view class="activity-item__time">
|
||
<text>时间:首次扫码开始累计</text>
|
||
<text class="activity-item__duration">{{item.duration}}天内</text>
|
||
</view>
|
||
<view class="activity-item__deadline" v-if="item.remainingDays">
|
||
<text>活动截止还剩</text>
|
||
<text class="activity-item__remaining-days">{{item.remainingDays}}天</text>
|
||
</view>
|
||
<view class="activity-item__target">
|
||
<text>目标:{{item.beerScope === 0 ? '品牌全系' : '以下'}}酒款累积扫码 ≥ </text>
|
||
<text class="activity-item__count">{{ item.activityTarget}}桶</text>
|
||
</view>
|
||
<view class="activity-item__reward">
|
||
<text class="activity-item__reward-tag">赠</text>
|
||
<view class="activity-item__reward-content" v-if="item.activityRewardType == 1 && item.activityRewardGoods">
|
||
<image
|
||
v-if="item.activityRewardGoods.cover"
|
||
:src="item.activityRewardGoods.cover"
|
||
class="activity-item__reward-image"
|
||
mode="aspectFit"
|
||
></image>
|
||
<view class="activity-item__reward-info">
|
||
<text class="activity-item__reward-name">{{item.activityRewardGoods.goodsName}}</text>
|
||
<text class="activity-item__reward-specs">规格:{{item.activityRewardGoods.specs}}</text>
|
||
<text class="activity-item__reward-count">数量:{{item.activityRewardCount}}份</text>
|
||
</view>
|
||
</view>
|
||
<view class="activity-item__reward-content" v-if="item.activityRewardType == 2">
|
||
<image
|
||
src="/static/coin.png"
|
||
class="activity-item__reward-image"
|
||
mode="aspectFit"
|
||
></image>
|
||
<view class="activity-item__reward-info">
|
||
<text class="activity-item__reward-name">品牌啤酒币</text>
|
||
<text class="activity-item__reward-count">数量:{{item.activityRewardCount}}枚</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="scan-result__footer">
|
||
<button class="scan-result__btn scan-result__btn--back" @click="back">
|
||
<image src="/static/undo.svg"></image>
|
||
<text>回头再说</text>
|
||
</button>
|
||
<button class="scan-result__btn scan-result__btn--share" @click="showConfirmPopup">
|
||
<image src="/static/send-2.svg"></image>
|
||
<text>立即领取</text>
|
||
</button>
|
||
</view>
|
||
|
||
<!-- 确认弹窗 -->
|
||
<uni-popup ref="confirmPopup" type="dialog">
|
||
<uni-popup-dialog
|
||
type="info"
|
||
title="领取确认"
|
||
content="每款酒品仅可领取一次,领取后将获得相应的品牌福利,是否确认领取?"
|
||
:before-close="true"
|
||
@confirm="confirmReceive"
|
||
@close="closePopup"
|
||
></uni-popup-dialog>
|
||
</uni-popup>
|
||
</template>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import {
|
||
consumeCode,
|
||
getQrcodeInfo
|
||
} from '@/api/bar.js'
|
||
import BeerCard from '@/components/BeerCard.vue'
|
||
|
||
export default {
|
||
components: {
|
||
BeerCard
|
||
},
|
||
data() {
|
||
return {
|
||
showError: false,
|
||
info: {
|
||
qrcode: {
|
||
qrcodeStatus: null, // 0: 待领取, 1: 领取成功, 2: 已失效, 3: 转为赠品
|
||
},
|
||
},
|
||
activity: [], // 活动列表
|
||
platformActivity: [], // 平台活动
|
||
activityList: [],
|
||
activitySum: 0, // 活动数量
|
||
beer: null,
|
||
result: null, // 扫码结果 code
|
||
activityId: null, // 活动id
|
||
platformActivityId: null, // 平台活动id
|
||
latitude: null,
|
||
longitude: null,
|
||
errorType: null, // 错误类型: location-位置错误, expired-已失效
|
||
isJustReceived: false, // 是否刚刚领取成功
|
||
};
|
||
},
|
||
onLoad({
|
||
result,
|
||
latitude,
|
||
longitude
|
||
}) {
|
||
this.result = result
|
||
this.latitude = latitude
|
||
this.longitude = longitude
|
||
this.isJustReceived = false // 重置领取状态
|
||
// 查询二维码信息
|
||
this.getQrcodeInfoFun(result)
|
||
},
|
||
methods: {
|
||
// 查询二维码信息
|
||
getQrcodeInfoFun(code) {
|
||
getQrcodeInfo({
|
||
code,
|
||
latitude: this.latitude,
|
||
longitude: this.longitude
|
||
}).then(res => {
|
||
console.log(res.data)
|
||
this.showError = false // 重置错误状态
|
||
this.errorType = null // 重置错误类型
|
||
this.info = res.data
|
||
this.beer = res.data.beer
|
||
this.activity = res.data.activity || []
|
||
this.platformActivity = res.data.platformActivity || []
|
||
this.activitySum = 0 // 重置活动数量
|
||
if (this.activity && this.activity.length > 0) {
|
||
this.activitySum += this.activity.length
|
||
this.activityId = this.activity[0].id
|
||
}
|
||
if (this.platformActivity && this.platformActivity.length > 0) {
|
||
this.activitySum += this.platformActivity.length
|
||
this.platformActivityId = this.platformActivity[0].id
|
||
}
|
||
}).catch(err => {
|
||
console.error('获取二维码信息失败:', err)
|
||
this.showError = true
|
||
if (err.code === 500 && err.msg === '请在酒吧附近100米范围内扫码') {
|
||
this.errorType = 'location'
|
||
} else if (err.code === 500 && err.msg.includes('已失效')) {
|
||
this.errorType = 'expired'
|
||
} else {
|
||
this.errorType = 'expired'
|
||
uni.showToast({
|
||
title: err.msg || '获取信息失败',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
})
|
||
},
|
||
// 显示确认弹窗
|
||
showConfirmPopup() {
|
||
this.$refs.confirmPopup.open();
|
||
},
|
||
|
||
// 关闭弹窗
|
||
closePopup() {
|
||
this.$refs.confirmPopup.close();
|
||
},
|
||
|
||
// 确认领取
|
||
confirmReceive() {
|
||
this.handleReceive();
|
||
this.closePopup();
|
||
},
|
||
// 立即领取
|
||
handleReceive() {
|
||
const data = {
|
||
code: this.result,
|
||
latitude: this.latitude,
|
||
longitude: this.longitude
|
||
}
|
||
if (this.activityId) {
|
||
data.activityId = this.activityId
|
||
}
|
||
if (this.platformActivityId) {
|
||
data.platformActivityId = this.platformActivityId
|
||
}
|
||
|
||
// 显示加载提示
|
||
uni.showLoading({
|
||
title: '领取中...',
|
||
mask: true
|
||
})
|
||
|
||
consumeCode(data).then(res => {
|
||
console.log('领取响应:', res)
|
||
// 验证响应数据
|
||
if (res.code === 200 && res.data) {
|
||
uni.hideLoading()
|
||
uni.showToast({
|
||
title: '领取成功',
|
||
icon: 'success'
|
||
})
|
||
// 设置刚刚领取成功状态
|
||
this.isJustReceived = true
|
||
// 延迟刷新数据,确保后端数据已更新
|
||
setTimeout(() => {
|
||
this.getQrcodeInfoFun(this.result)
|
||
}, 1000)
|
||
} else {
|
||
throw new Error('领取失败:响应数据异常')
|
||
}
|
||
}).catch(err => {
|
||
console.error('领取失败:', err)
|
||
uni.hideLoading()
|
||
|
||
if (err.code === 500 && err.msg === '请在酒吧附近100米范围内扫码') {
|
||
this.showError = true
|
||
this.errorType = 'location'
|
||
} else if (err.code === 500 && err.msg.includes('reward_sn')) {
|
||
uni.showToast({
|
||
title: '系统维护中,请稍后再试',
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
} else if (err.code === 500 && err.msg.includes('已领取')) {
|
||
uni.showToast({
|
||
title: '该酒品已领取过,请勿重复领取',
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
} else {
|
||
uni.showToast({
|
||
title: err.msg || '领取失败,请重试',
|
||
icon: 'none',
|
||
duration: 2000
|
||
})
|
||
}
|
||
})
|
||
},
|
||
back() {
|
||
if (this.info.qrcode.qrcodeStatus == 1) {
|
||
// 领取成功时返回首页
|
||
uni.switchTab({
|
||
url: '/pages/index/index'
|
||
})
|
||
} else {
|
||
// 其他情况正常返回上一页
|
||
uni.navigateBack()
|
||
}
|
||
},
|
||
// 选择品牌方活动
|
||
selectPPF(item) {
|
||
this.activityId = item.id
|
||
},
|
||
// 选择平台活动
|
||
selectPlatform(item) {
|
||
this.platformActivityId = item.id
|
||
},
|
||
// 生成酒单
|
||
toWinelist() {
|
||
uni.navigateTo({
|
||
url: '/pagesActivity/winelist?beerId=' + this.beer.id
|
||
})
|
||
},
|
||
share() {
|
||
uni.downloadFile({
|
||
url: this.beer.cover,
|
||
success: (res) => {
|
||
console.log(res)
|
||
// #ifdef MP-WEIXIN
|
||
uni.showShareImageMenu({
|
||
provider: 'weixin',
|
||
path: res.tempFilePath,
|
||
shareType: 0,
|
||
success: (res) => {
|
||
console.log(res)
|
||
},
|
||
fail: (err) => {
|
||
console.log(err)
|
||
}
|
||
})
|
||
// #endif
|
||
}
|
||
})
|
||
},
|
||
formatTime(timestamp) {
|
||
const date = new Date(timestamp);
|
||
return date.toLocaleString();
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.scan-result {
|
||
min-height: 100vh;
|
||
background: #F5F7FA;
|
||
padding: 32rpx 26rpx 160rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
box-sizing: border-box;
|
||
position: relative;
|
||
|
||
&__header {
|
||
text-align: center;
|
||
margin-bottom: 40rpx;
|
||
padding-top: 40rpx;
|
||
|
||
&--success {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 20rpx;
|
||
}
|
||
}
|
||
|
||
&__icon {
|
||
width: 120rpx;
|
||
height: 120rpx;
|
||
margin-bottom: 24rpx;
|
||
}
|
||
|
||
&__title {
|
||
display: block;
|
||
font-size: 32rpx;
|
||
color: #333;
|
||
font-weight: 500;
|
||
margin-bottom: 16rpx;
|
||
}
|
||
|
||
&__desc {
|
||
display: block;
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
}
|
||
|
||
&__content {
|
||
flex: 1;
|
||
overflow-y: auto;
|
||
-webkit-overflow-scrolling: touch;
|
||
}
|
||
|
||
&__section {
|
||
background: #FFF;
|
||
border-radius: 16rpx;
|
||
padding: 24rpx;
|
||
margin-bottom: 24rpx;
|
||
}
|
||
|
||
&__section-title {
|
||
font-size: 32rpx;
|
||
font-weight: 500;
|
||
color: #333;
|
||
margin-bottom: 24rpx;
|
||
display: block;
|
||
position: relative;
|
||
padding-left: 24rpx;
|
||
|
||
&::before {
|
||
content: '';
|
||
position: absolute;
|
||
left: 0;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
width: 6rpx;
|
||
height: 32rpx;
|
||
background: linear-gradient(180deg, #D42E78 0%, #19367A 100%);
|
||
border-radius: 3rpx;
|
||
}
|
||
}
|
||
|
||
&__footer {
|
||
margin-top: auto;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
gap: 24rpx;
|
||
padding: 24rpx 32rpx env(safe-area-inset-bottom);
|
||
background: #fff;
|
||
position: fixed;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.1);
|
||
z-index: 99;
|
||
}
|
||
|
||
&__btn {
|
||
flex: 1;
|
||
height: 88rpx;
|
||
border-radius: 44rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 28rpx;
|
||
border: none;
|
||
padding: 0;
|
||
|
||
image {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
margin-right: 8rpx;
|
||
}
|
||
|
||
&--back {
|
||
background: #F7F8FA;
|
||
color: #4E63E0;
|
||
}
|
||
|
||
&--share {
|
||
background: #19367A;
|
||
color: #FFF;
|
||
}
|
||
|
||
&:active {
|
||
transform: scale(0.98);
|
||
opacity: 0.9;
|
||
}
|
||
}
|
||
}
|
||
|
||
.product-card {
|
||
display: flex;
|
||
gap: 24rpx;
|
||
|
||
&__image {
|
||
width: 200rpx;
|
||
height: 280rpx;
|
||
border-radius: 12rpx;
|
||
overflow: hidden;
|
||
|
||
image {
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: cover;
|
||
}
|
||
}
|
||
|
||
&__info {
|
||
flex: 1;
|
||
}
|
||
|
||
&__name {
|
||
font-size: 32rpx;
|
||
font-weight: 500;
|
||
color: #333;
|
||
margin-bottom: 8rpx;
|
||
display: block;
|
||
}
|
||
|
||
&__brand {
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
margin-bottom: 16rpx;
|
||
display: block;
|
||
}
|
||
|
||
&__detail {
|
||
display: flex;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
&__label {
|
||
font-size: 26rpx;
|
||
color: #999;
|
||
}
|
||
|
||
&__value {
|
||
font-size: 26rpx;
|
||
color: #333;
|
||
}
|
||
|
||
&__rating {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-top: 16rpx;
|
||
|
||
.rating-stars {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-right: 16rpx;
|
||
|
||
.cuIcon-favorfill {
|
||
color: #FFBC11;
|
||
margin-right: 4rpx;
|
||
}
|
||
|
||
.rating-value {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
}
|
||
}
|
||
|
||
.rating-count {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
}
|
||
}
|
||
}
|
||
|
||
.benefit-card {
|
||
background: #FFF;
|
||
padding: 24rpx;
|
||
border-radius: 16rpx;
|
||
|
||
&__title {
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
color: #3D3D3D;
|
||
margin-bottom: 12rpx;
|
||
display: block;
|
||
}
|
||
|
||
&__subtitle {
|
||
font-size: 24rpx;
|
||
color: rgba(151, 151, 151, 0.75);
|
||
font-weight: 400;
|
||
}
|
||
}
|
||
|
||
.activity-notice {
|
||
display: flex;
|
||
align-items: center;
|
||
background: #FFF9E6;
|
||
padding: 20rpx 24rpx;
|
||
border-radius: 12rpx;
|
||
margin-bottom: 24rpx;
|
||
|
||
image {
|
||
width: 32rpx;
|
||
height: 32rpx;
|
||
margin-right: 12rpx;
|
||
}
|
||
|
||
text {
|
||
font-size: 26rpx;
|
||
color: #FF9900;
|
||
}
|
||
}
|
||
|
||
.activity-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 24rpx;
|
||
}
|
||
|
||
.activity-item {
|
||
background: #FFFFFF;
|
||
border-radius: 20rpx;
|
||
padding: 32rpx;
|
||
border: 1px solid #EFEDE9;
|
||
box-shadow: 0 8rpx 16rpx rgba(0, 0, 0, 0.08);
|
||
transition: all 0.3s;
|
||
position: relative;
|
||
|
||
&--selected {
|
||
border-color: #19367A;
|
||
background: rgba(25, 54, 122, 0.05);
|
||
}
|
||
|
||
&__header {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
&__title {
|
||
font-size: 36rpx;
|
||
font-weight: bold;
|
||
color: #0B0E26;
|
||
}
|
||
|
||
&__tag-container {
|
||
position: absolute;
|
||
top: 32rpx;
|
||
left: 32rpx;
|
||
display: flex;
|
||
gap: 8rpx;
|
||
z-index: 1;
|
||
}
|
||
|
||
&__tag {
|
||
font-size: 20rpx;
|
||
color: #FFFFFF;
|
||
padding: 6rpx 16rpx;
|
||
border-radius: 8rpx;
|
||
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.3);
|
||
|
||
&--store {
|
||
background-color: #D42E78;
|
||
}
|
||
|
||
&--new {
|
||
background-color: #19367A;
|
||
}
|
||
|
||
&--limited {
|
||
background-color: #FF6B35;
|
||
}
|
||
}
|
||
|
||
&__content {
|
||
padding-top: 48rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 20rpx;
|
||
}
|
||
|
||
&__progress {
|
||
font-size: 28rpx;
|
||
font-weight: 500;
|
||
color: #0B0E26;
|
||
line-height: 44rpx;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
&__time, &__target {
|
||
font-size: 28rpx;
|
||
font-weight: 500;
|
||
color: #0B0E26;
|
||
line-height: 44rpx;
|
||
}
|
||
|
||
&__duration, &__count {
|
||
color: #D42E78;
|
||
font-weight: bold;
|
||
}
|
||
|
||
&__beers {
|
||
width: 100%;
|
||
display: flex;
|
||
flex-direction: row;
|
||
white-space: nowrap;
|
||
height: 200rpx;
|
||
margin: 4rpx 0 24rpx;
|
||
overflow-x: auto;
|
||
}
|
||
|
||
&__beer {
|
||
width: 120rpx;
|
||
height: 170rpx;
|
||
background: #FFFFFF;
|
||
margin-right: 8rpx;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border-radius: 12rpx;
|
||
overflow: hidden;
|
||
|
||
image {
|
||
width: 100%;
|
||
height: 100%;
|
||
border-radius: 12rpx;
|
||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||
object-fit: contain;
|
||
}
|
||
}
|
||
|
||
&__deadline {
|
||
font-size: 28rpx;
|
||
font-weight: 500;
|
||
color: #0B0E26;
|
||
line-height: 44rpx;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
&__remaining-days {
|
||
color: #FF6B35;
|
||
font-weight: bold;
|
||
}
|
||
|
||
&__remaining-count {
|
||
color: #19367A;
|
||
font-weight: bold;
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
&__reward {
|
||
background: #F7F8FA;
|
||
border-radius: 16rpx;
|
||
padding: 24rpx;
|
||
margin-top: 20rpx;
|
||
}
|
||
|
||
&__reward-content {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 20rpx;
|
||
margin-top: 16rpx;
|
||
}
|
||
|
||
&__reward-image {
|
||
width: 120rpx;
|
||
height: 120rpx;
|
||
border-radius: 12rpx;
|
||
background: #FFFFFF;
|
||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
&__reward-info {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8rpx;
|
||
}
|
||
|
||
&__reward-name {
|
||
font-size: 28rpx;
|
||
font-weight: 500;
|
||
color: #0B0E26;
|
||
}
|
||
|
||
&__reward-specs {
|
||
font-size: 24rpx;
|
||
color: #666666;
|
||
}
|
||
|
||
&__reward-count {
|
||
font-size: 24rpx;
|
||
color: #D42E78;
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
</style> |