Commit da34143e by 赖慧粮

feat(mini): 抽奖工具封装 & ui更新 & mini版本

parent c6e0e16b

630 KB | W: | H:

8.57 KB | W: | H:

assets/images/lottery/gift.png
assets/images/lottery/gift.png
assets/images/lottery/gift.png
assets/images/lottery/gift.png
  • 2-up
  • Swipe
  • Onion skin

2.15 KB | W: | H:

7.19 KB | W: | H:

assets/images/lottery/prize.png
assets/images/lottery/prize.png
assets/images/lottery/prize.png
assets/images/lottery/prize.png
  • 2-up
  • Swipe
  • Onion skin

31 KB | W: | H:

7.71 KB | W: | H:

assets/images/lottery/winning_bg.png
assets/images/lottery/winning_bg.png
assets/images/lottery/winning_bg.png
assets/images/lottery/winning_bg.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -13,21 +13,18 @@ import { mapActions } from 'vuex'
export default {
name: 'BindPhoneDialog',
props: {
isShow: {
value: {
type: Boolean,
default: false
}
},
data() {
return {}
},
computed: {
visible: {
get () {
return this.isShow
return this.value
},
set (val) {
this.$emit('changeVisible', val)
this.$emit('input', val)
}
}
},
......
<template>
<van-popup class="winners-popup" closeable v-model="visible" position="left">
<van-popup v-model="visible" class="winners-popup" closeable position="left">
<div class="winners-popup__container">
<div class="winners-popup__container__head">中奖名单</div>
<div class="winners-popup__container__content">
<div class="winners-popup__container__content__list">
<div class="item" v-for="(item, index) in winnersList" :key="index">
<div v-for="(item, index) in winnersList" :key="index" class="item">
<span class="item__prize">{{ item.userNick }}获得{{ item.prizeName }}</span>
</div>
<div class="winners-popup__container__content__list__no-data" v-if="winnersList.length === 0">暂无数据</div>
<div v-if="winnersList.length === 0" class="winners-popup__container__content__list__no-data">暂无数据</div>
</div>
</div>
</div>
......@@ -20,7 +20,7 @@ import { getWinnersList } from '@/api/modules/lottery'
export default {
name: 'WinnersPopup',
props: {
isShow: {
value: {
type: Boolean,
default: false
}
......@@ -33,10 +33,10 @@ export default {
computed: {
visible: {
get () {
return this.isShow
return this.value
},
set (val) {
this.$emit('changeVisible', val)
this.$emit('input', val)
}
}
},
......
<template>
<section v-if="isShowBanner" class="banner">
<a class="banner__wrap" target="_blank" :href="bannerLink">
<div class="banner__wrap__content" :style="`background-image:url('${bannerImg}')`"></div>
<div class="banner__content" :style="`background-image:url('${bannerImg}')`"></div>
</a>
</section>
</template>
......@@ -38,16 +38,22 @@ export default {
width: 100%;
display: flex;
&__wrap {
display: block;
width: 100%;
height: 0;
padding-top: 115 / 330 * 100%;
position: relative;
}
&__content {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
&__content {
width: 100%;
height: 100%;
border-radius: 4px;
background-size: cover;
background-position: center;
font-size: 0;
}
border-radius: 4px;
background-size: cover;
background-position: center;
font-size: 0;
}
}
</style>
......@@ -2,9 +2,7 @@
<section v-if="'startTime' in lotteryInfo" class="countdown-bar">
<div class="countdown-bar__status">
<template v-if="parseInt(status, 10) !== LOTTERY_STATUS.end">
<div class="countdown-bar__status__text">
{{ LOTTERY_STATUS_TXT[parseInt(status, 10)].actionLabel }}倒计时:
</div>
<div class="countdown-bar__text">{{ LOTTERY_STATUS_TXT[parseInt(status, 10)].actionLabel }}倒计时:</div>
<van-count-down millisecond :time="time">
<template #default="timeData">
<span v-if="timeData.days" class="time-item">
......@@ -13,15 +11,15 @@
</span>
<span class="time-item">
{{ timeData.hours | formatNum }}
<span></span>
<span>:</span>
</span>
<span class="time-item">
{{ timeData.minutes | formatNum }}
<span></span>
<span>:</span>
</span>
<span class="time-item">
{{ timeData.seconds | formatNum }}
<span></span>
<!-- <span>:</span> -->
</span>
</template>
</van-count-down>
......@@ -82,28 +80,37 @@ export default {
<style lang="less" scoped>
.countdown-bar {
width: 100%;
background: url('~@/assets/images/lottery/lottery_instant_contdown_bg.png');
background-size: contain;
background-repeat: no-repeat;
background-position: center;
height: auto;
display: flex;
justify-content: center;
align-items: center;
&__status {
transform: translateY(-4px);
font-size: 14px;
padding: 0 24px;
height: 29px;
line-height: 29px;
border-radius: 50px;
background-color: rgba(3, 2, 2, 0.4);
border: 2px solid rgba(255, 144, 110, 0.4);
font-size: 13px;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
color: #ff2b00;
font-weight: 600;
color: #fff;
font-weight: 400;
/deep/ .van-count-down {
color: #ff2b00;
color: #fff;
height: 28px;
line-height: 28px;
.time-item {
font-weight: 600;
font-size: 13px;
font-weight: 400;
}
}
&__text {
font-weight: 600;
}
}
&__text {
font-size: 13px;
font-weight: 400;
}
}
</style>
<template>
<div class="introduction">
<div class="introduction__sec-title"></div>
<div class="introduction__wrap">
<div class="introduction__title">活动介绍</div>
<p class="introduction__intro">{{ lotteryInfo.intro }}</p>
<template v-if="!!lotteryInfo.isShowPrize">
<div class="introduction__title">活动奖品</div>
<div class="introduction__prize">
<ul class="introduction__list" :class="{ 'introduction__list--center': lotteryInfo.prizeConfigs.length < 3 }">
<li v-for="(item, index) in lotteryInfo.prizeConfigs" :key="index">
<img v-lazy="item.icon || img" class="introduction__item-img" alt />
<p v-if="item.prizeAlias" class="introduction__item-level">{{ item.prizeAlias }}</p>
<p class="introduction__item-name">{{ item.name }}</p>
</li>
</ul>
</div>
</template>
<div class="introduction__content">
<p class="introduction__intro">{{ lotteryInfo.intro }}</p>
<template v-if="!!lotteryInfo.isShowPrize">
<div class="introduction__title">本场活动奖品:</div>
<div class="introduction__prize">
<ul
class="introduction__list"
:class="{ 'introduction__list--center': lotteryInfo.prizeConfigs.length < 3 }"
>
<li v-for="(item, index) in lotteryInfo.prizeConfigs" :key="index">
<img v-lazy="item.icon || img" class="introduction__item-img" alt />
<p v-if="item.prizeAlias" class="introduction__item-level">{{ item.prizeAlias }}</p>
<p class="introduction__item-name">{{ item.name }}</p>
</li>
</ul>
</div>
</template>
</div>
</div>
</div>
</template>
......@@ -39,32 +44,45 @@ export default {
<style lang="less" scoped>
.introduction {
width: 100%;
background-color: #ff8e5e;
border-radius: 6px;
padding: 8px;
position: relative;
padding-top: 44px;
&__sec-title {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 72px;
background: url('~@/assets/images/lottery/intro_title.png');
background-repeat: no-repeat;
background-position: center;
background-size: cover;
}
&__wrap {
width: 100%;
height: 100%;
border-radius: 6px;
background-color: #fcf7d5;
background-color: #f6d2b6;
padding: 6px;
}
&__content {
width: 100%;
height: 100%;
padding: 6px 12px;
border-radius: 6px;
background-color: #f8e0cb;
font-size: 12px;
color: #fc5147;
}
&__title {
font-size: 14px;
font-weight: 600;
text-align: center;
height: 20px;
line-height: 20px;
margin: 8px 0;
padding: 20px 14px 14px;
color: #79420c;
}
&__intro {
font-size: 14px;
padding: 5px;
font-size: 12px;
line-height: 18px;
white-space: pre-line;
}
&__title {
margin: 14px 0 10px;
}
&__prize {
width: 100%;
}
......
<template>
<van-popup v-model="visible" class="introduction-popup">
<div class="introduction-popup__main">
<div class="introduction-popup__sec-title">活动介绍</div>
<div class="introduction-popup__wrap">
<div class="introduction-popup__content">
<p class="introduction-popup__intro">{{ lotteryInfo.intro }}</p>
<template v-if="!!lotteryInfo.isShowPrize">
<div class="introduction-popup__title">本场活动奖品:</div>
<div class="introduction-popup__prize">
<ul
class="introduction-popup__list"
:class="{ 'introduction-popup__list--center': lotteryInfo.prizeConfigs.length < 3 }"
>
<li v-for="(item, index) in lotteryInfo.prizeConfigs" :key="index">
<img v-lazy="item.icon || img" class="introduction-popup__item-img" alt />
<p v-if="item.prizeAlias" class="introduction-popup__item-level">{{ item.prizeAlias }}</p>
<p class="introduction-popup__item-name">{{ item.name }}</p>
</li>
</ul>
</div>
</template>
</div>
</div>
<div class="introduction-popup__back" @click="visible = false">返回活动</div>
</div>
</van-popup>
</template>
<script>
import { mapGetters } from 'vuex'
import img from '@/assets/images/lottery/gift.png'
export default {
name: 'Introduction',
props: {
value: {
type: Boolean,
default: false
}
},
data() {
return {
img
}
},
computed: {
...mapGetters({ lotteryInfo: 'lottery/lotteryInfo' }),
visible: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
}
}
}
</script>
<style lang="less" scoped>
.introduction-popup {
width: 100%;
height: 100%;
background-image: url('~@/assets/images/lottery/index_bg.png');
background-size: 100% 100%;
background-position: top center;
background-repeat: no-repeat;
&__main {
width: 100%;
border-radius: 6px;
padding: 13px;
position: relative;
padding-top: 44px;
}
&__back {
position: absolute;
top: 10px;
right: 5px;
background-color: #ffd440;
border: 2px solid #e28a00;
color: #9c5c00;
font-size: 12px;
writing-mode: vertical-lr;
padding: 5px 3px;
border-radius: 6px;
}
&__sec-title {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 72px;
padding-top: 22px;
text-align: center;
font-size: 15px;
font-weight: 500;
color: #fff;
}
&__wrap {
width: 100%;
height: 100%;
border-radius: 6px;
background-color: #f6d2b6;
padding: 6px;
}
&__content {
width: 100%;
height: 100%;
border-radius: 6px;
background-color: #f8e0cb;
font-size: 12px;
padding: 20px 14px 14px;
color: #79420c;
}
&__intro {
font-size: 12px;
line-height: 18px;
white-space: pre-line;
}
&__title {
margin: 14px 0 10px;
}
&__prize {
width: 100%;
}
&__list {
display: flex;
flex-wrap: wrap;
width: 100%;
&--center {
justify-content: center;
}
> li {
text-align: center;
width: 33.3333%;
padding: 6px;
}
}
&__item-img {
display: block;
width: 68px;
height: 68px;
margin: 0 auto;
}
&__item-level {
font-size: 14px;
height: 18px;
line-height: 18px;
margin: 5px 0 0;
}
&__item-name {
font-size: 12px;
margin: 5px 0 0;
line-height: 14px;
}
}
</style>
......@@ -35,7 +35,7 @@ import { NUMBER_LIST } from '@/utils/constant'
export default {
name: 'RecordPopup',
props: {
isShow: {
value: {
type: Boolean,
default: false
}
......@@ -54,10 +54,10 @@ export default {
}),
visible: {
get() {
return this.isShow
return this.value
},
set(val) {
this.$emit('changeVisible', val)
this.$emit('input', val)
}
}
},
......
<template>
<div class="records" :class="{ 'records--button-center': !isShowWinnersList }">
<van-button round color="#FDF3AB" @click="openRecord">我的抽奖记录</van-button>
<RecordPopup :is-show="isShowRecordPopup" @changeVisible="changeIsShowRecord"></RecordPopup>
<van-button v-if="isShowWinnersList" round color="#FDF3AB" @click="changeIsShowWinners(true)">中奖名单</van-button>
<WinnersPopup
v-if="isShowWinnersList"
:is-show="isShowWinnersPopup"
@changeVisible="changeIsShowWinners"
></WinnersPopup>
<div class="records">
<div class="records__layouts">
<div class="records__entry" @click="openRecord">
<div class="records__entry-wrap">
<p>抽奖</p>
<p>记录</p>
</div>
</div>
<div v-if="isShowWinnersList" class="records__entry records__entry--winners" @click="openRecordPopup('winners')">
<div class="records__entry-wrap">
<p>中奖</p>
<p>名单</p>
</div>
</div>
</div>
<RecordsPupup v-model="isShowRecordsPopup" :active-tab="activeTab" :is-show-winners-list="isShowWinnersList"></RecordsPupup>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
import RecordPopup from '@/components/Lottery/Instant/RecordPopup'
import WinnersPopup from '@/components/Common/WinnersPopup'
import RecordsPupup from '@/components/Lottery/Instant/RecordsPupup'
export default {
name: 'Records',
components: {
RecordPopup,
WinnersPopup
RecordsPupup
},
data() {
return {
isShowRecordPopup: false, // 是否显示我的抽奖记录
isShowWinnersPopup: false // 是否显示中奖名单
isShowRecordsPopup: false,
activeTab: 'personal'
}
},
computed: {
......@@ -47,14 +52,12 @@ export default {
}
})
} else {
this.changeIsShowRecord(true)
this.openRecordPopup('personal')
}
},
changeIsShowRecord(val) {
this.isShowRecordPopup = val
},
changeIsShowWinners(val) {
this.isShowWinnersPopup = val
openRecordPopup(type){
this.activeTab = type
this.isShowRecordsPopup = true
}
}
}
......@@ -62,16 +65,30 @@ export default {
<style lang="less" scoped>
.records {
display: flex;
justify-content: space-between;
width: 100%;
&--button-center {
&__layouts {
position: fixed;
z-index: 5;
right: 10px;
bottom: 40px;
}
&__entry {
width: 47px;
height: 47px;
background-color: #fff;
box-shadow: 0px 1px 3px 0px rgba(170, 80, 40, 0.35);
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
&--winners {
margin-top: 18px;
}
}
/deep/ .van-button {
height: 100%;
.van-button__content {
color: #fc5147;
&__entry-wrap {
> p {
font-size: 13px;
font-weight: 500;
color: #804e26;
}
}
}
......
<template>
<van-popup v-model="visible" class="records-popup" closeable swipeable close-icon="close">
<van-tabs v-model="active" class="records-popup__tabs" :line-width="16" @change="onChange">
<van-tab title="抽奖记录" name="personal">
<div class="records-popup__personal-record">
<div class="records-popup__record-content">
<div class="records-popup__phone">
领奖手机号:
<span v-if="isBindPhone">{{ userInfo.phone }}</span>
<span v-else class="records-popup__bind-phone" @click="bindMobile">绑定手机号</span>
</div>
<ul v-if="Object.keys(recordList).length !== 0" class="records-popup__record-list">
<li v-for="(session, key, index) in recordList" :key="index">
<div v-for="(item, itemIndex) in session" :key="itemIndex" class="records-popup__session-info">
<div class="records-popup__info-wrap">
<div v-if="session.length > 1" class="records-popup__session">
{{ NUMBER_LIST[index + 1] }}场次
</div>
<div class="records-popup__time">
<span>{{ (item.drawTime * 1000) | formatDate('MM-DD HH:mm:ss') }}</span>
</div>
</div>
<div class="records-popup__prize-name">{{ item.prizeName }}</div>
</div>
</li>
</ul>
<div v-if="Object.keys(recordList).length === 0" class="records-popup__no-data">暂无记录</div>
</div>
</div>
</van-tab>
<van-tab v-if="isShowWinnersList" title="中奖名单" name="winners">
<div class="records-popup__winners-record">
<div class="records-popup__record-content">
<div class="records-popup__winners-list">
<div v-for="(item, index) in winnersList" :key="index" class="records-popup__item">
{{ item.userNick }} 获得 <span class="records-popup__prize-name">{{ item.prizeName }}</span>
</div>
<div v-if="winnersList.length === 0" class="records-popup__no-data">暂无数据</div>
</div>
</div>
</div>
</van-tab>
</van-tabs>
</van-popup>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
import { getLotteryRecordList, getWinnersList } from '@/api/modules/lottery'
import { NUMBER_LIST } from '@/utils/constant'
export default {
name: 'RecordsPupup',
props: {
value: {
type: Boolean,
default: false
},
isShowWinnersList: {
type: Boolean,
default: false
},
activeTab: {
type: String,
default: 'personal'
}
},
data() {
return {
NUMBER_LIST,
recordList: {},
winnersList: [],
active: ''
}
},
computed: {
...mapGetters({
uin: 'users/uin',
userInfo: 'users/userInfo',
isBindPhone: 'users/isBindPhone'
}),
visible: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
}
},
watch: {
visible: {
handler(val) {
if (val) {
this.active = this.activeTab
this.dataInit()
}
},
immediate: true
}
},
methods: {
...mapActions({ jumpToBinding: 'users/jumpToBinding' }),
dataInit() {
if (this.active === 'personal') {
getLotteryRecordList({
id: this.$route.query.id,
uin: this.uin,
playId: this.$route.query.sessionId
}).then(res => {
const { code, errorCode, errorMessage, data } = res
if (code === 200 && errorCode === 0) {
this.recordList = data
} else {
this.$toast(errorMessage)
}
})
}
if (this.active === 'winners') {
getWinnersList({
id: this.$route.query.id,
uin: this.$route.query.uin
}).then(res => {
const { code, errorCode, errorMessage, data } = res
if (code === 200 && errorCode === 0) {
this.winnersList = data
} else {
this.$toast(errorMessage)
}
})
}
},
onChange() {
if (!Object.keys(this.recordList).length || !this.winnersList.length) {
this.dataInit()
}
},
bindMobile() {
this.$toast({
message: '正在为您转跳,请完成绑定手机操作',
duration: 1500,
onClose: () => {
this.jumpToBinding()
}
})
}
}
}
</script>
<style lang='less' scoped>
.records-popup {
width: 258px;
height: 291px;
background: #ffe9d8;
border-radius: 15px;
overflow: visible;
font-size: 12px;
/deep/ .van-popup__close-icon {
right: -22px;
top: -20px;
font-size: 22px;
color: #fff;
}
&__tabs {
padding: 8px 0 0;
height: 100%;
overflow: hidden;
display: flex;
flex-direction: column;
::v-deep .van-tabs__wrap {
display: flex;
justify-content: center;
height: 34px;
}
::v-deep .van-tabs__nav {
background-color: transparent;
justify-content: center;
width: 160px;
.van-tab--active {
.van-tab__text {
color: #333;
font-weight: 500;
font-size: 14px;
}
}
}
::v-deep .van-tabs__line {
background-color: #f57641;
border-radius: 1px;
}
::v-deep .van-tabs__content {
flex: 1;
overflow: hidden;
.van-tab__pane {
width: 100%;
height: 100%;
padding: 15px 0;
}
}
}
&__personal-record {
width: 100%;
height: 100%;
overflow: hidden auto;
padding: 0 15px;
}
&__phone {
color: #666;
margin-bottom: 12px;
}
&__bind-phone {
color: #f57641;
}
&__record-list {
li {
margin-bottom: 15px;
&:last-child {
margin-bottom: 0;
}
}
}
&__session-info {
display: flex;
flex-direction: column;
&:last-child {
.records-popup__prize-name {
margin-bottom: 0;
}
}
}
&__info-wrap {
display: flex;
align-items: center;
}
&__session {
margin-left: 5px;
font-size: 13px;
color: #333;
}
&__time {
color: #666;
}
&__prize-name {
margin: 8px 0 15px;
color: #666;
}
&__item {
margin-bottom: 8px;
}
&__winners-record {
width: 100%;
height: 100%;
overflow: hidden auto;
padding: 0 15px;
.records-popup__prize-name {
color: #f57641;
}
}
&__no-data {
color: #999;
text-align: center;
padding-top: 40px;
}
}
</style>
<template>
<van-popup class="win-popup" v-model="visible" closeable close-icon="close" :style="{ background: 'transparent' }">
<van-popup v-model="visible" class="win-popup" closeable close-icon="close" :style="{ background: 'transparent' }">
<div class="win-popup__container">
<div class="win-popup__container__wrap">
<div class="win-popup__container__wrap__title">
<template v-if="info.id !== 0">恭喜获得</template>
</div>
<div class="win-popup__container__wrap__content">
<div class="win-popup__container__wrap__content__box">
<!-- :class="{'win-popup__container__wrap__content__box--no': info.id === 0}" -->
<div class="win-popup__container__wrap__content__box__title">
<template v-if="info.id !== 0">{{ info.name }}</template>
<template v-if="info.id === 0">谢谢参与</template>
<div class="win-popup__wrap">
<div class="win-popup__content">
<div v-if="isWin" class="win-popup__win-info">
<div class="win-popup__title">恭喜获得</div>
<div class="win-popup__prize-img">
<img src="@/assets/images/lottery/gift.png" alt="" />
</div>
<div
class="win-popup__container__wrap__content__box__win-msg"
:class="{ 'win-popup__container__wrap__content__box__win-msg--no': info.id === 0 }"
>
<template v-if="info.id !== 0">
已成功获取{{ info.name }}
<p>根据活动说明进行领取</p>
</template>
<template v-if="info.id === 0">谢谢参与,再接再厉</template>
<div class="win-popup__prize-name">
{{ info.name }}
</div>
</div>
<van-button class="win-popup__container__wrap__content__sure" color="#F5E952" round @click="know"
<div v-else class="win-popup__thanks">谢谢参与,再接再厉</div>
</div>
<div class="win-popup__footer">
<van-button class="win-popup__sure" color="linear-gradient(to right, #ffde9d, #ffdbb3)" round @click="know"
>我知道了</van-button
>
<template v-if="isWin">
<p class="win-popup__win-msg">根据活动说明进行领取</p>
</template>
</div>
</div>
</div>
......@@ -35,11 +30,9 @@
<script>
export default {
name: 'WinPopup',
data() {
return {}
},
components: {},
props: {
isShow: {
value: {
type: Boolean,
default: false
},
......@@ -50,15 +43,17 @@ export default {
},
computed: {
visible: {
get: function () {
return this.isShow
get() {
return this.value
},
set: function (val) {
this.$emit('changeVisible', val)
set(val) {
this.$emit('input', val)
}
},
isWin() {
return !!+this.info.id
}
},
components: {},
methods: {
know() {
this.$emit('winCallback')
......@@ -71,15 +66,13 @@ export default {
@containerWidth: 326px;
@wrapWidth: 275px;
@wrapHeight: 292px;
@bulinbulinWidth: @containerWidth;
@bulinbulinHeight: 136px;
.win-popup {
overflow: visible;
/deep/ .van-popup__close-icon {
right: 52px;
top: -8px;
font-size: 38px;
top: -16px;
font-size: 22px;
color: #fff;
}
&__container {
......@@ -87,105 +80,90 @@ export default {
height: 100%;
position: relative;
width: @containerWidth;
&::after {
content: '';
position: absolute;
width: @bulinbulinWidth;
height: @bulinbulinHeight;
top: 40px;
left: 0;
background-image: url('~@/assets/images/lottery/bulinbulin.png');
background-size: cover;
background-repeat: no-repeat;
}
&__wrap {
margin: 0 auto;
width: 184px;
height: 211px;
overflow: hidden;
background-image: url('~@/assets/images/lottery/winning_bg.png');
background-size: cover;
background-repeat: no-repeat;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
&__content {
color: #fff;
font-size: 16px;
flex: 1;
width: 100%;
overflow: hidden
}
&__win-info {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
}
&__title {
width: 100%;
text-align: center;
color: #fff;
font-weight: 500;
font-size: 16px;
height: 18px;
margin: 13px 0 7px;
}
&__prize-img {
img {
display: block;
width: 65px;
}
&__wrap {
margin: 0 auto;
width: 275px;
height: 292px;
padding: 10px;
border-radius: 10px;
overflow: hidden;
background-image: url('~@/assets/images/lottery/winning_bg.png');
background-size: cover;
background-repeat: no-repeat;
&__title {
padding: 0 42px;
width: 100%;
text-align: center;
color: #fc5147;
font-weight: 700;
font-size: 16px;
height: 18px;
text-indent: 12px;
margin: 45px 0 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
&__content {
color: #fc575a;
font-size: 16px;
&__box {
margin-top: 5px;
text-align: center;
color: #fc575a;
font-size: 28px;
text-indent: 12px;
font-weight: 700;
&__title {
height: 52px;
line-height: 28px;
width: 60%;
margin: 0 auto;
// 两行隐藏
word-break: break-all;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
overflow: hidden;
/*! autoprefixer: off */
-webkit-box-orient: vertical;
}
&__win-msg {
padding: 0 20px;
margin-top: 48px;
font-size: 20px;
color: #fff;
text-indent: 10px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
&--no {
margin-top: 70px;
}
> p {
color: #fe9746;
font-size: 12px;
height: 26px;
line-height: 26px;
}
}
}
&__sure {
width: 45%;
height: 38px;
line-height: 38px;
border: 0;
outline: none;
position: absolute;
bottom: 28px;
left: 50%;
transform: translateX(-50%);
/deep/ .van-button__text {
font-size: 16px;
color: #fc5147;
font-weight: 700;
}
}
}
}
&__prize-name {
width: 100%;
padding: 0 10px;
font-size: 13px;
color: #fff;
margin-top: 11px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
text-align: center;
}
&__thanks {
padding-top: 24px;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
&__footer {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: 65px;
}
&__sure {
width: 126px;
height: 33px;
line-height: 33px;
border: 0;
outline: none;
/deep/ .van-button__text {
font-size: 13px;
color: #fb1f34;
font-weight: 500;
}
}
&__win-msg {
margin: 13px 0 20px;
font-size: 12px;
color: #fff;
}
}
</style>
......@@ -25,7 +25,7 @@
点击绑定手机号
<i class="iconfont icon-zhankai"></i>
</a>
<span v-if="lotteryInfo.showResult" class="blue-text win-list" @click="$emit('openWiner', true)">
<span v-if="lotteryInfo.showResult" class="blue-text win-list" @click="$emit('openWiner')">
查看中奖名单
<i class="iconfont icon-zhankai"></i>
</span>
......@@ -34,7 +34,7 @@
<template v-if="isLogin && lotteryInfo.isDraw && !lotteryInfo.isWin">
<div class="win-result-box">
<p class="win-result">很遗憾,您没有中奖</p>
<span v-if="lotteryInfo.showResult" class="blue-text win-list" @click="$emit('openWiner', true)">
<span v-if="lotteryInfo.showResult" class="blue-text win-list" @click="$emit('openWiner')">
查看中奖名单
<i class="iconfont icon-zhankai"></i>
</span>
......
......@@ -9,9 +9,9 @@
</p>
</div>
<TimingStatus class="timing-status-box"></TimingStatus>
<JoinButton class="join-button-box" @lottery="lotteryCallback" @openWiner="changeIsShowWinner"></JoinButton>
<JoinButton class="join-button-box" @lottery="lotteryCallback" @openWiner="isShowWinner = true"></JoinButton>
<BackButton v-if="backUrl" class="back-box" :url="backUrl"></BackButton>
<WinnersPopup :is-show="isShowWinner" @changeVisible="changeIsShowWinner"></WinnersPopup>
<WinnersPopup v-model="isShowWinner"></WinnersPopup>
</section>
</template>
<script>
......@@ -65,9 +65,6 @@ export default {
},
methods: {
...mapActions({ jumpToLogin: 'users/jumpToLogin', updateInfo: 'lottery/updateInfo' }),
changeIsShowWinner(val) {
this.isShowWinner = val
},
// 抽奖回调
lotteryCallback() {
// 抽奖点击事件
......
......@@ -8,7 +8,7 @@ export default {
goDomain: '//golivec.guangdianyun.tv/v1',
privateDomain: '//privateapi.guangdianyun.tv/v1',
activityDomain: '//activity.guangdianyun.tv/v1',
defBanner: `${process.env.OSS_DOMAIN}/common/img/lottery_banner_default.png`,
defBanner: `${process.env.OSS_DOMAIN}/common/img/lottery_banner_default_v2.png`,
defShareImg: `${protocol || 'https:'}${process.env.OSS_DOMAIN}/common/img/lottery.png`, // 必须带协议头,否则微信分享配置时无法生效
env: process.env.X_CA_STAGE,
private: process.env.private,
......
......@@ -48,6 +48,7 @@
"alife-logger": "1.8.6",
"core-js": "^3.15.1",
"dayjs": "^1.10.6",
"lotteries": "^1.1.0",
"normalize.css": "^8.0.1",
"nuxt": "^2.15.7",
"qrcode": "^1.4.4",
......
<template>
<div class="session-list">
<ul class="session-list__wrapper">
<li
v-for="(item, index) in sessionList"
:key="index"
v-lazy:background-image="bannerImg(item.banner)"
@click="jumpToLottery(item.id)"
>
<div class="session-list__status" :class="`session-list__status--${getStatus(item).value}`">
{{ getStatus(item).label }}
</div>
<div class="session-list__time">
{{ index + 1 }}场:
{{ (item.startTime * 1000) | formatDate('MM/DD HH:mm') }}
~
{{ (item.endTime * 1000) | formatDate('MM/DD HH:mm') }}
<li v-for="(item, index) in sessionList" :key="index" @click="jumpToLottery(item.id)">
<div v-lazy:background-image="bannerImg(item.banner)" class="session-list__item-wrap">
<div class="session-list__status" :class="`session-list__status--${getStatus(item).className}`">
{{ getStatus(item).label }}
</div>
<div class="session-list__time">
{{ index + 1 }}场:
{{ (item.startTime * 1000) | formatDate('MM/DD HH:mm') }}
{{ (item.endTime * 1000) | formatDate('MM/DD HH:mm') }}
</div>
</div>
</li>
</ul>
......@@ -23,6 +20,7 @@
<script>
import { mapGetters, mapActions } from 'vuex'
import { LOTTERY_STATUS, LOTTERY_STATUS_TXT } from '@/utils/constant'
import CONFIG from '@/config'
import Bus from '@/utils/Bus'
import UserAgents from '@/utils/UserAgents'
......@@ -82,12 +80,12 @@ export default {
getStatus(item) {
const { nowTime } = this
if (nowTime < item.startTime * 1000) {
return { label: '未开始', value: 'teaser' }
return LOTTERY_STATUS_TXT[LOTTERY_STATUS.teaser]
}
if (nowTime > item.endTime * 1000) {
return { label: '已结束', value: 'end' }
return LOTTERY_STATUS_TXT[LOTTERY_STATUS.end]
}
return { label: '进行中', value: 'start' }
return LOTTERY_STATUS_TXT[LOTTERY_STATUS.start]
},
bannerImg(url) {
const img = url || CONFIG.defBanner
......@@ -115,44 +113,53 @@ export default {
.session-list {
width: 100%;
height: 100%;
background-color: #fff;
&__wrapper {
width: 100%;
height: 100%;
padding: 15px;
overflow: hidden auto;
padding: 22px;
li {
width: 100%;
height: 150px;
border-radius: 6px;
background-size: cover;
background-position: center;
font-size: 0;
margin-top: 15px;
height: 0px;
position: relative;
font-size: 0;
margin-top: 20px;
padding-top: 115 / 330 * 100%;
&:first-child {
margin-top: 0px;
}
}
}
&__item-wrap {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
background-size: cover;
background-position: center;
border-radius: 10px;
}
&__status {
position: absolute;
top: 10px;
left: 6px;
min-width: 72px;
height: 24px;
line-height: 24px;
border-radius: 12px;
height: 20px;
line-height: 20px;
border-radius: 5px;
background: rgba(0, 0, 0, 0.2);
text-align: center;
font-size: 12px;
padding: 0 5px;
&--teaser {
color: #ffaa00;
color: #fffeab;
}
&--start {
color: #6abf47;
color: #58d719;
}
&--end {
color: #dfdfdf;
color: #ffffff;
}
}
&__time {
......@@ -163,9 +170,8 @@ export default {
height: 32px;
line-height: 32px;
border-radius: 0 0 6px 6px;
background: rgba(0, 0, 0, 0.2);
color: #fff;
padding: 0 12px;
padding: 0 17px;
font-size: 14px;
}
}
......
<template>
<section class="lottery-box">
<component
:is="lotteryComponents[parseInt(lotteryInfo.type, 10)]"
v-if="'type' in lotteryInfo && lotteryInfo.type"
></component>
<Loading v-model="isLoading" class="lottery-box__loading"></Loading>
</section>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
import { LOTTERY_TYPE } from '@/utils/constant'
import Bus from '@/utils/Bus'
import UserAgents from '@/utils/UserAgents'
import CONFIG from '@/config'
export default {
components: {
Loading: () => import('@/components/Loading')
},
data() {
return {
isLoading: true,
lotteryComponents: {
[LOTTERY_TYPE.instant]: () => import('@/components/Lottery/Instant/MiniMain'),
[LOTTERY_TYPE.timing]: () => import('@/components/Lottery/Timing/Main')
},
id: this.$route.query.id || null, // 接收抽奖id
sessionId: this.$route.query.sessionId || null // 接收抽奖场次id
// sid: this.$route.query.sid || null, // 引用id
// stype: this.$route.query.stype || null, // 引用类型
}
},
computed: {
...mapGetters({
isLogin: 'users/isLogin',
uin: 'users/uin',
lotteryInfo: 'lottery/lotteryInfo'
})
},
created() {
this.dataInit()
},
destroyed() {
Bus.$off('LotteryInfoUpdate')
Bus.$off('LotteryStateUpdate')
},
methods: {
...mapActions({
getLotteryDetail: 'lottery/getLotteryDetail',
updateInfo: 'lottery/updateInfo',
getUerInfo: 'users/getUerInfo',
postInfo: 'users/postInfo'
}),
// 页面进入初始化
dataInit() {
const { id, sessionId: playId, uin } = this.$route.query
// 拉取场次内基础信息
this.getLotteryDetail({ id, playId, uin })
.then(() => {
this.isLoading = false
// 微信分享
if (UserAgents.isWx && process.client) {
const { lotteryInfo } = this
const wxShare = require('@/utils/wxShare').default
wxShare.init(
{
link: window.location.href,
title: lotteryInfo?.shareTitle || lotteryInfo?.title || '抽奖',
desc: lotteryInfo?.intro || window.location.href,
imgUrl: CONFIG.defShareImg
},
{ uin }
)
}
})
.catch(() => {
this.isLoading = false
})
// 初始化事件中心
this.eventHubInit()
},
// 事件中心
eventHubInit() {
// 数据更新
Bus.$on('LotteryInfoUpdate', data => {
const { id } = data
const { uin, id: currentId, sessionId: currentPlayId } = this
if (parseInt(id, 10) === parseInt(currentId, 10)) {
this.getLotteryDetail({ id, playId: currentPlayId, uin })
}
})
// 抽奖开始与结束
Bus.$on('LotteryStateUpdate', data => {
const { id, playId } = data
const { sessionId: currentPlayId, id: currentId } = this
if (parseInt(id, 10) === parseInt(currentId, 10) && parseInt(playId, 10) === parseInt(currentPlayId, 10)) {
const { status, startTime, endTime, userTimes } = data
// 状态
this.updateInfo({
status
})
// 开始时间结束时间
this.updateInfo({
startTime,
endTime
})
// 剩余抽奖次数
if (this.isLogin) {
this.updateInfo({
userTimes
})
}
}
})
}
}
}
</script>
<style lang="less" scoped>
.lottery-box {
overflow: hidden;
margin: 0 auto;
height: 100%;
}
</style>
<template>
<div class="session-list">
<ul class="session-list__wrapper">
<li v-for="(item, index) in sessionList" :key="index" @click="jumpToLottery(item.id)">
<div v-lazy:background-image="bannerImg(item.banner)" class="session-list__item-wrap">
<div class="session-list__status" :class="`session-list__status--${getStatus(item).className}`">
{{ getStatus(item).label }}
</div>
<div class="session-list__time">
{{ index + 1 }}场:
{{ (item.startTime * 1000) | formatDate('MM/DD HH:mm') }}
{{ (item.endTime * 1000) | formatDate('MM/DD HH:mm') }}
</div>
</div>
</li>
</ul>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
import { LOTTERY_STATUS, LOTTERY_STATUS_TXT } from '@/utils/constant'
import CONFIG from '@/config'
import Bus from '@/utils/Bus'
export default {
name: 'List',
data() {
return {
nowTime: new Date().getTime()
}
},
computed: {
...mapGetters({ sessionList: 'lottery/sessionList' })
},
mounted() {
// 初始化事件中心
this.eventHubInit()
this.dataInit()
},
destroyed() {
Bus.$off('LotteryInfoUpdate')
},
methods: {
...mapActions({
getSessionList: 'lottery/getSessionList'
}),
dataInit() {
const { id, uin } = this.$route.query
this.getSessionList({ id, uin })
.then(res => {
// 判断是否自动进入抽奖页
if (res.data.playConfig.length < 2) {
this.$router.replace({
path: '/mini/index',
query: { ...this.$route.query, sessionId: res.data.playConfig[0].id }
})
}
})
.catch(() => {
this.$root.context.error({ statusCode: 504, message: '网络请求超时,请刷新重试' })
})
},
getStatus(item) {
const { nowTime } = this
if (nowTime < item.startTime * 1000) {
return LOTTERY_STATUS_TXT[LOTTERY_STATUS.teaser]
}
if (nowTime > item.endTime * 1000) {
return LOTTERY_STATUS_TXT[LOTTERY_STATUS.end]
}
return LOTTERY_STATUS_TXT[LOTTERY_STATUS.start]
},
bannerImg(url) {
const img = url || CONFIG.defBanner
return `${img}${CONFIG.ossImageServe}`
},
jumpToLottery(sessionId) {
const params = new URLSearchParams({ ...this.$route.query, sessionId }).toString()
window.location.href = `${window.location.origin}/lottery/mini/index?${params}`
},
eventHubInit() {
// 数据更新
Bus.$on('LotteryInfoUpdate', data => {
const { id } = data
const { uin, id: currentId } = this.$route.query
if (parseInt(id, 10) === parseInt(currentId, 10)) {
this.getSessionList({ id, uin })
}
})
}
}
}
</script>
<style lang="less" scoped>
.session-list {
width: 100%;
height: 100%;
background-color: #fff;
&__wrapper {
width: 100%;
height: 100%;
overflow: hidden auto;
padding: 22px;
li {
width: 100%;
height: 0px;
position: relative;
font-size: 0;
margin-top: 20px;
padding-top: 115 / 330 * 100%;
&:first-child {
margin-top: 0px;
}
}
}
&__item-wrap {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
background-size: cover;
background-position: center;
border-radius: 10px;
}
&__status {
position: absolute;
top: 10px;
left: 6px;
height: 20px;
line-height: 20px;
border-radius: 5px;
background: rgba(0, 0, 0, 0.2);
text-align: center;
font-size: 12px;
padding: 0 5px;
&--teaser {
color: #fffeab;
}
&--start {
color: #58d719;
}
&--end {
color: #ffffff;
}
}
&__time {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 32px;
line-height: 32px;
border-radius: 0 0 6px 6px;
color: #fff;
padding: 0 17px;
font-size: 14px;
}
}
</style>
......@@ -11,21 +11,14 @@ export default function ({ store, app, redirect }) {
}
store.commit('users/SET_UIN', uin)
if (to.path === '/list' && !id) {
if (['/list', '/index', '/message', '/winners'].includes(to.path) && !id) {
app.context.error({ statusCode: 450, message: 'Incomplete route, parameter: ID not found' })
}
if ((to.path === '/index' || to.path === '/message') && !id) {
app.context.error({ statusCode: 450, message: 'Incomplete route, parameter: ID not found' })
}
if ((to.path === '/index' || to.path === '/message') && !sessionId) {
if (['/index', '/message'].includes(to.path) && !sessionId) {
app.context.error({ statusCode: 450, message: 'Incomplete route, parameter: found:sessionId not found' })
}
if (to.path === '/winners' && !id) {
app.context.error({ statusCode: 450, message: 'Incomplete route, parameter: ID not found' })
}
next()
})
}
......@@ -17,7 +17,9 @@ import {
NoticeBar,
NavBar,
Icon,
PullRefresh
PullRefresh,
Tab,
Tabs
} from 'vant'
import errorImg from '@/assets/images/lazyLoad/error.png'
import loadingImg from '@/assets/images/lazyLoad/loading.png'
......@@ -75,3 +77,7 @@ Vue.use(Icon)
/* 下拉刷新 */
Vue.use(PullRefresh)
/* 标签页 */
Vue.use(Tab);
Vue.use(Tabs);
......@@ -5749,6 +5749,14 @@ lodash@^4.15.0, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
lotteries@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/lotteries/-/lotteries-1.1.0.tgz#b73df0baceeba41f622a4388facbe0a13b357e86"
integrity sha512-Ja+y+2HSOWU+/l7Aobt9xfpaRAj4rIHCJwesJ4qUZgS2NHMpSJ9rvWtMFrl/NeBkSYx1DPfj9WFZHIScvITmzQ==
dependencies:
core-js "^3.6.5"
vue "^2.6.11"
lower-case@^1.1.1:
version "1.1.4"
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment