Files
xdd-uniapp-new/pkg-video/views/county-lottery.vue
T

786 lines
20 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="county-lottery-page">
<view class="banner-wrapper">
<view class="top-banner" :style="topBannerStyle">
<view class="banner-content">
<view class="banner-date">开奖时间{{ openDateText }}</view>
<view class="banner-countdown">
<text class="text">距离开奖还有</text>
<text class="num">{{ countdownData.day }}</text>
<text class="text"></text>
<text class="num">{{ countdownData.time }}</text>
</view>
</view>
</view>
</view>
<view class="side-entry rules" @click="openRulesModel">活动规则</view>
<view class="side-entry mine" @click="navToLog">我的抽奖码</view>
<view class="winners-wrap" @click="navToLog">
<view class="winners-text" v-if="!winnerSortedList.length">暂时无人中奖</view>
<view class="winners-text one-t" v-else-if="winnerSortedList.length === 1">
恭喜 <text class="blue">{{ winnerSortedList[0].name }}</text>
在第 <text class="blue">{{ winnerSortedList[0].periodNo }}</text> 期抽奖活动中获得
<text class="red">{{ winnerSortedList[0].prizeName }}</text>
</view>
<swiper
v-else
class="winner-swiper"
vertical
circular
autoplay
:interval="3000"
:duration="500"
>
<swiper-item v-for="(winner, index) in winnerSortedList" :key="index">
<view class="winners-text one-t">
恭喜 <text class="blue">{{ winner.name }}</text>
在第 <text class="blue">{{ winner.periodNo }}</text> 期抽奖活动中获得
<text class="red">{{ winner.prizeName }}</text>
</view>
</swiper-item>
</swiper>
<view class="winners-btn" @click="navToWinners">查看全部 <text class="arrow"></text></view>
</view>
<view class="pool-wrap">
<view class="pool-header">
<view class="pool-title">奖品池 <text class="sub">/ prize pool</text></view>
<view class="pool-desc">实付满{{ buyThresholdText }}元即可获得抽奖码定时统一开奖</view>
</view>
<view class="pool-body">
<swiper
class="pool-swiper"
:autoplay="prizeList.length > 3"
:circular="prizeList.length > 3"
:interval="3000"
:duration="500"
:display-multiple-items="prizeList.length >= 3 ? 3 : prizeList.length"
v-if="prizeList.length"
>
<swiper-item v-for="(prize, gIndex) in prizeList" :key="gIndex">
<view class="pool-list-group">
<view
class="pool-item"
style="margin: 0 auto;"
>
<view class="item-inner">
<view class="item-dashed">
<image class="pool-image" :src="prize.prizeImage" mode="aspectFit" />
</view>
</view>
<image class="prize-tag" :src="prize.levelIcon" v-if="prize.levelIcon" mode="aspectFit" />
<view class="pool-name one-t">{{ prize.prizeName }}</view>
</view>
</view>
</swiper-item>
</swiper>
</view>
</view>
<view class="goods-section">
<view class="goods-header-box">
<view class="goods-title-pill">
<text class="dot">·</text> 活动商品 <text class="dot">·</text>
<view class="triangle"></view>
</view>
<view class="goods-sub">—— 购买即得抽奖码 ——</view>
</view>
<view class="goods-list">
<view
v-for="(item, index) in activityGoodsList"
:key="index"
class="goods-item"
>
<image class="goods-image" :src="item.image" mode="aspectFill" @click="goGoodsDetail(item)" />
<view class="goods-name more-t">{{ item.name }}</view>
<view class="goods-bottom">
<text class="goods-price">¥{{ item.price }}</text>
<view class="goods-cart" @click.stop="openGoodsSku(item)">购</view>
</view>
</view>
</view>
</view>
<ProductWindow
ref="attrWindow"
:attr="attr"
:cartNum="cart_num"
:showOk="true"
okText="立即下单"
@changeFun="changeFun"
@ok="submitFromSku()"
/>
</view>
</template>
<script>
import { getDrawActivityInfo } from '@/api/lottery'
import { postCartAdd } from '@/api/store'
import ProductWindow from '@/components/ProductWindow'
import goCartMixin from '@/mixins/goCartMixins'
import { pageListenMixins } from '@/mixins/pageListenMixins'
export default {
name: 'CountyLotteryPage',
components: {
ProductWindow
},
mixins: [pageListenMixins, goCartMixin],
data() {
return {
ready: false,
activityInfo: {
drawImage: '',
drawTime: '',
winnerList: [],
prizePool: [],
products: []
},
activityId: 0,
linkType: 1,
onlyOneToAddCart: false,
statusBarHeight: 20,
countdownData: {
day: '--',
time: '--:--:--'
},
countdownTimer: null
}
},
computed: {
topBannerStyle() {
const drawImage = String(this.activityInfo.drawImage || '').trim()
if (!drawImage) return ''
return `background-image:url(${drawImage});background-size:100% 100%;background-repeat:no-repeat;background-position:center top;`
},
prizeList() {
return this.activityInfo.prizePool || []
},
activityGoodsList() {
const list = this.activityInfo.products || []
if (list.length > 0) {
return list.map(item => ({
id: item.productId || item.id || 0,
image: item.productImage || item.image || item.pic || '',
name: item.productName || item.name || item.prizeName || '',
price: item.productPrice || item.price || item.salePrice || 0
}))
}
return this.prizeList.map(item => ({
id: item.productId || 0,
image: item.prizeImage || '',
name: item.prizeName || '',
price: item.productPrice || item.price || 0
}))
},
winnerSortedList() {
const list = this.activityInfo.winnerList || []
if (!list.length) return []
const mapped = list.map(item => ({
name: item.realName || item.phone || '用户',
periodNo: item.periodNo || '-',
prizeName: item.prizeName || '神秘奖品'
}))
return mapped.sort((a, b) => this.getPeriodNoValue(b.periodNo) - this.getPeriodNoValue(a.periodNo))
},
buyThresholdText() {
return 99
},
openDateText() {
const target = this.getTargetDate()
if (!target) return '--'
const year = target.getFullYear()
const month = String(target.getMonth() + 1).padStart(2, '0')
const day = String(target.getDate()).padStart(2, '0')
return `${year}年${month}月${day}日`
}
},
onLoad(options) {
this.linkType = Number(options.linkType) || 1
this.activityId = Number(options.activityId || options.areaId) || 0
this.statusBarHeight = uni.getSystemInfoSync().statusBarHeight || 20
this.init()
},
onUnload() {
this.clearCountdownTimer()
},
methods: {
init() {
if (!this.activityId) {
uni.showToast({
title: '缺少活动ID',
icon: 'none'
})
return
}
getDrawActivityInfo(this.activityId).then(res => {
if (res.success) {
const data = res.data || {}
this.activityInfo = {
...this.activityInfo,
...data,
drawImage: data.drawImage || ''
}
this.ready = true
this.startCountdown()
}
})
},
getTargetDate() {
const targetTime = this.activityInfo.drawTime || ''
if (!targetTime) return null
const date = new Date(String(targetTime).replace(/-/g, '/'))
if (Number.isNaN(date.getTime())) return null
return date
},
startCountdown() {
this.clearCountdownTimer()
const calc = () => {
const target = this.getTargetDate()
if (!target) {
this.countdownData = { day: '--', time: '--:--:--' }
return
}
let diff = target.getTime() - Date.now()
if (diff <= 0) {
this.countdownData = { day: '00', time: '00:00:00' }
return
}
const day = Math.floor(diff / (24 * 60 * 60 * 1000))
diff -= day * 24 * 60 * 60 * 1000
const hour = Math.floor(diff / (60 * 60 * 1000))
diff -= hour * 60 * 60 * 1000
const minute = Math.floor(diff / (60 * 1000))
diff -= minute * 60 * 1000
const second = Math.floor(diff / 1000)
const dd = String(day).padStart(2, '0')
const hh = String(hour).padStart(2, '0')
const mm = String(minute).padStart(2, '0')
const ss = String(second).padStart(2, '0')
this.countdownData = {
day: dd,
time: `${hh}:${mm}:${ss}`
}
}
calc()
this.countdownTimer = setInterval(calc, 1000)
},
clearCountdownTimer() {
if (this.countdownTimer) {
clearInterval(this.countdownTimer)
this.countdownTimer = null
}
},
getPeriodNoValue(periodNo) {
const text = String(periodNo || '')
const match = text.match(/\d+/g)
if (!match || !match.length) return 0
return Number(match.join('')) || 0
},
openRulesModel() {
uni.navigateTo({ url: '/pkg-video/views/county-lottery-rules' })
},
navToWinners() {
uni.navigateTo({
url: `/pkg-video/views/county-winners?activityId=${this.activityId}`
})
},
navToLog() {
uni.navigateTo({ url: '/pkg-video/views/county-my-tickets' })
},
goBack() {
if (getCurrentPages().length > 1) {
uni.navigateBack()
return
}
uni.switchTab({
url: '/pages/home/index'
})
},
goGoodsDetail(item) {
if (!item.id) return
uni.navigateTo({ url: `/pages/shop/GoodsCon/index?id=${item.id}&from=countyLottery&activityId=${this.activityId}` })
},
openGoodsSku(item) {
if (!item.id) return
this.addToCart(item)
},
submitFromSku() {
const productSelect = this.getAttrItemData(this.attrValue)
const currentSelect = productSelect || this.attr.productSelect || {}
const stock = Number(currentSelect.stock || 0)
const hasNo = (this.attr.productAttr.length && !productSelect && this.isOpen) || stock <= 0
if (hasNo) {
uni.showToast({
title: '产品库存不足,请选择其他商品',
icon: 'none',
duration: 3000
})
return
}
const q = {
productId: this.m_id,
cartNum: Number(currentSelect.cart_num || 1),
new: 1,
uniqueId: currentSelect.unique || ''
}
if (this.activityId) {
q.drawActivityId = Number(this.activityId)
}
postCartAdd(q).then(res => {
this.isOpen = false
this.attr.cartAttr = false
this.$set(this.attr.productSelect, 'cart_num', 1)
this.cart_num = 1
const cartId = (res.data && res.data.cartId) || ''
if (!cartId) return
uni.navigateTo({
url: `/pages/order/OrderSubmission/index?id=${cartId}`
})
})
}
}
}
</script>
<style scoped lang="less">
.county-lottery-page {
min-height: 100vh;
background-color: #f5f5f5;
padding-bottom: 40rpx;
}
.custom-header {
position: fixed;
left: 0;
top: 0;
width: 100%;
z-index: 30;
background: rgba(255, 255, 255, 0);
}
.custom-header-inner {
height: 88rpx;
display: flex;
align-items: center;
padding: 0 24rpx;
}
.header-back {
width: 64rpx;
height: 64rpx;
border-radius: 50%;
background: rgba(0, 0, 0, .35);
display: flex;
align-items: center;
justify-content: center;
}
.header-back-icon {
color: #fff;
font-size: 56rpx;
line-height: 1;
margin-top: -6rpx;
}
.banner-wrapper {
position: relative;
background: #f5f5f5;
padding-bottom: 30rpx;
}
.banner-red-curve {
background: #cb302c;
height: 40rpx;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
border-bottom-left-radius: 60rpx;
border-bottom-right-radius: 60rpx;
z-index: 1;
}
.top-banner {
background-color: #ffb611;
background-size: 100% 100%;
background-repeat: no-repeat;
height: 640rpx;
position: relative;
border-bottom-left-radius: 40rpx;
border-bottom-right-radius: 40rpx;
z-index: 2;
}
.banner-content {
position: absolute;
bottom: 40rpx;
left: 0;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
.banner-date {
position: relative;
background: #3b7cf6;
color: #fff;
border: 4rpx solid #fff;
border-radius: 40rpx;
padding: 6rpx 30rpx;
font-size: 28rpx;
margin-bottom: 24rpx;
&::after {
content: '';
position: absolute;
bottom: -14rpx;
left: 50%;
transform: translateX(-50%);
border-width: 14rpx 14rpx 0;
border-style: solid;
border-color: #fff transparent transparent transparent;
}
&::before {
content: '';
position: absolute;
bottom: -8rpx;
left: 50%;
transform: translateX(-50%);
border-width: 10rpx 10rpx 0;
border-style: solid;
border-color: #3b7cf6 transparent transparent transparent;
z-index: 1;
}
}
.banner-countdown {
background: #cb302c;
color: #fff;
border: 6rpx solid #fff;
border-radius: 60rpx;
padding: 10rpx 40rpx;
display: flex;
align-items: baseline;
box-shadow: inset 0 0 0 6rpx rgba(0, 0, 0, 0.1);
.text {
font-size: 32rpx;
}
.num {
font-size: 48rpx;
font-weight: bold;
margin: 0 10rpx;
}
}
.side-entry {
position: fixed;
right: 0;
background: #fff;
color: #333;
font-size: 24rpx;
width: 44rpx;
padding: 24rpx 0;
text-align: center;
border-radius: 24rpx 0 0 24rpx;
z-index: 10;
writing-mode: vertical-rl;
letter-spacing: 6rpx;
font-weight: bold;
box-shadow: -2rpx 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.side-entry.rules {
top: 60rpx;
}
.side-entry.mine {
top: 260rpx;
}
.winners-wrap {
margin: 0 24rpx;
background: #fff;
border-radius: 40rpx;
padding: 10rpx 10rpx 10rpx 30rpx;
display: flex;
align-items: center;
justify-content: space-between;
border: 2rpx solid #333;
.winners-text {
font-size: 24rpx;
color: #333;
flex: 1;
.blue {
color: #3b7cf6;
}
.red {
color: #cb302c;
}
}
.winner-swiper {
flex: 1;
height: 36rpx;
margin-right: 8rpx;
}
.winners-btn {
background: #3b7cf6;
color: #fff;
font-size: 24rpx;
padding: 8rpx 20rpx;
border-radius: 30rpx;
display: flex;
align-items: center;
white-space: nowrap;
margin-left: 16rpx;
.arrow {
margin-left: 4rpx;
font-size: 22rpx;
}
}
}
.pool-wrap {
margin: 24rpx;
background: #cb302c;
border-radius: 24rpx;
overflow: hidden;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
.pool-header {
display: flex;
align-items: stretch;
.pool-title {
background: #ffb611;
color: #333;
font-weight: bold;
font-size: 34rpx;
padding: 10rpx 24rpx;
border-radius: 40rpx;
margin: 20rpx 30rpx 20rpx 20rpx;
display: flex;
align-items: baseline;
.sub {
font-size: 20rpx;
font-weight: bold;
margin-left: 8rpx;
}
}
.pool-desc {
font-size: 24rpx;
color: #666;
flex: 1;
background: #fff;
display: flex;
align-items: center;
padding: 0 20rpx 0 30rpx;
border-bottom-left-radius: 40rpx;
}
}
.pool-body {
padding: 30rpx 0 40rpx 20rpx;
}
.pool-swiper {
height: 250rpx;
width: 100%;
}
.pool-list-group {
display: flex;
flex-wrap: nowrap;
}
.pool-item {
width: 220rpx;
margin-right: 32rpx;
position: relative;
flex-shrink: 0;
.item-inner {
background: #fff;
border-radius: 16rpx 48rpx 16rpx 16rpx;
padding: 12rpx;
height: 220rpx;
box-sizing: border-box;
border: 2rpx solid #ffb611;
box-shadow: 10rpx 10rpx 0 #ffb611;
.item-dashed {
border: 2rpx dashed #ccc;
border-radius: 8rpx 36rpx 8rpx 8rpx;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
.pool-image {
width: 150rpx;
height: 150rpx;
}
}
}
.prize-tag {
position: absolute;
left: -10rpx;
bottom: 20rpx;
width: 76rpx;
height: 76rpx;
z-index: 2;
}
.pool-name {
position: absolute;
bottom: -16rpx;
left: 50%;
transform: translateX(-50%);
background: #fff;
color: #cb302c;
font-size: 22rpx;
font-weight: bold;
padding: 6rpx 24rpx;
border-radius: 30rpx;
white-space: nowrap;
z-index: 3;
border: 2rpx solid #ffb611;
max-width: 95%;
text-align: center;
}
}
}
.goods-section {
margin: 60rpx 24rpx 24rpx;
background: #fff;
border-radius: 24rpx;
position: relative;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
.goods-header-box {
background: #cb302c;
border-radius: 24rpx 24rpx 0 0;
padding: 50rpx 0 20rpx;
display: flex;
flex-direction: column;
align-items: center;
position: relative;
.goods-title-pill {
position: absolute;
top: -24rpx;
left: 50%;
transform: translateX(-50%);
background: #ffb611;
color: #333;
font-size: 32rpx;
font-weight: bold;
padding: 8rpx 40rpx;
border-radius: 40rpx;
border: 6rpx solid #fff;
display: flex;
align-items: center;
white-space: nowrap;
.dot {
margin: 0 8rpx;
}
.triangle {
position: absolute;
bottom: -16rpx;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 0;
border-left: 12rpx solid transparent;
border-right: 12rpx solid transparent;
border-top: 12rpx solid #ffb611;
}
}
.goods-sub {
color: #fff;
font-size: 24rpx;
font-weight: 500;
}
}
.goods-list {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding: 24rpx;
}
.goods-item {
width: 316rpx;
background: #fff;
margin-bottom: 30rpx;
.goods-image {
width: 100%;
height: 316rpx;
background: #f8f8f8;
border-radius: 16rpx;
}
.goods-name {
font-size: 26rpx;
color: #333;
line-height: 1.4;
margin: 16rpx 0;
height: 72rpx;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.goods-bottom {
display: flex;
align-items: center;
justify-content: space-between;
.goods-price {
color: #cb302c;
font-size: 32rpx;
font-weight: bold;
}
.goods-cart {
width: 48rpx;
height: 48rpx;
background-color: #cb302c;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M7 18c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2zM1 2v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.42c-.14 0-.25-.11-.25-.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3.58-6.49c.08-.14.12-.31.12-.48 0-.55-.45-1-1-1H5.21l-.94-2H1zm16 16c-1.1 0-1.99.9-1.99 2s.89 2 1.99 2 2-.9 2-2-.9-2-2-2z'/%3E%3C/svg%3E");
background-size: 28rpx 28rpx;
background-repeat: no-repeat;
background-position: center;
color: transparent;
}
}
}
}
</style>