Files

306 lines
6.9 KiB
Plaintext

<template>
<view class="page">
<scroll-view direction="vertical" :show-scrollbar="false" style="flex:1;">
<!-- 顶部金币信息 -->
<view class="top-card">
<view class="coin-row">
<uni-icons type="wallet-filled" size="28" color="#FFD700"></uni-icons>
<text class="coin-num">{{ coins }}</text>
<text class="coin-label">我的金币</text>
</view>
<view class="free-tip">
今日免费抽奖剩余 <text class="free-num">{{ freeLeft }}</text> 次(每次消耗 {{ cost }} 金币)
</view>
</view>
<!-- 奖品展示 -->
<view class="section-title">奖品池</view>
<view class="prize-grid">
<view v-for="(p, idx) in prizes" :key="idx" class="prize-item">
<view class="prize-icon">
<uni-icons :type="prizeIcon(p.type)" size="30"
:color="p.type == 1 ? '#FF9500' : (p.type == 2 ? '#FF2D55' : '#999')"></uni-icons>
</view>
<text class="prize-name">{{ p.name }}</text>
<text class="prize-sub" v-if="p.type == 1">{{ p.value }} 金币</text>
<text class="prize-sub" v-else-if="p.type == 2">实物</text>
<text class="prize-sub" v-else>谢谢参与</text>
</view>
</view>
<!-- 抽奖按钮 -->
<view class="draw-btn" :class="{ disabled: drawing }" @click="onDraw">
<text v-if="!drawing">{{ freeLeft > 0 ? '免费抽奖' : ('抽一次(' + cost + '金币)') }}</text>
<text v-else>抽奖中...</text>
</view>
<text class="draw-hint">每日 {{ freeDaily }} 次免费机会,点击即抽</text>
</scroll-view>
<!-- 结果弹窗 -->
<view v-if="showResult" class="mask" @click="showResult = false">
<view class="result-card" @click.stop>
<uni-icons :type="resultIcon" size="56"
:color="resultType == 1 ? '#FF9500' : (resultType == 2 ? '#FF2D55' : '#bbb')"></uni-icons>
<text class="result-title">{{ resultPrize }}</text>
<text class="result-sub" v-if="resultType == 1">+{{ resultValue }} 金币已到账</text>
<view class="result-btn" @click="showResult = false">
<text>开心收下</text>
</view>
</view>
</view>
</view>
</template>
<script setup lang="uts">
import Api from '@/common/api-service.uts'
const BASE = 'https://dev.xixingwl.cn'
type IPrize = {
id : number
name : string
type : number
value : number
probability : number
}
const coins = ref<number>(0)
const cost = ref<number>(10)
const freeDaily = ref<number>(1)
const freeLeft = ref<number>(0)
const prizes = reactive<IPrize[]>([])
const drawing = ref<boolean>(false)
const showResult = ref<boolean>(false)
const resultPrize = ref<string>('')
const resultType = ref<number>(3)
const resultValue = ref<number>(0)
const resultIcon = computed<string>(() => {
if (resultType.value == 1) return 'wallet-filled'
if (resultType.value == 2) return 'gift-filled'
return 'close'
})
function prizeIcon(type : number) : string {
if (type == 1) return 'wallet-filled'
if (type == 2) return 'gift-filled'
return 'more'
}
function loadConfig() {
Api.lottery.config()
.then((res : UTSJSONObject) => {
coins.value = (res.get('coins') as number) ?? 0
cost.value = (res.get('cost') as number) ?? 10
freeDaily.value = (res.get('free_daily') as number) ?? 1
freeLeft.value = (res.get('free_left') as number) ?? 0
const list = (res.get('prizes') as Array<IPrize>) ?? []
prizes.splice(0, prizes.length)
list.forEach((p : IPrize) => prizes.push(p))
})
.catch(() => {
uni.showToast({ title: '配置加载失败', icon: 'none' })
})
}
function onDraw() {
if (drawing.value) return
if (freeLeft.value <= 0 && coins.value < cost.value) {
uni.showToast({ title: '金币不足', icon: 'none' })
return
}
drawing.value = true
Api.lottery.draw()
.then((res : UTSJSONObject) => {
resultPrize.value = (res.get('prize') as string) ?? '谢谢参与'
resultType.value = (res.get('prize_type') as number) ?? 3
resultValue.value = (res.get('prize_value') as number) ?? 0
coins.value = (res.get('coins_left') as number) ?? coins.value
showResult.value = true
loadConfig()
})
.catch((e : any) => {
uni.showToast({ title: (e && e.message) ? e.message : '抽奖失败', icon: 'none' })
})
.finally(() => {
drawing.value = false
})
}
onMounted(() => { loadConfig() })
onShow(() => { loadConfig() })
</script>
<style lang="scss">
.page {
flex: 1;
background-color: #f7f7f7;
}
.top-card {
margin: 24rpx 30rpx;
padding: 40rpx;
background: linear-gradient(135deg, #6A5ACD 0%, #FF6B6B 100%);
border-radius: 20rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.coin-row {
display: flex;
flex-flow: row nowrap;
align-items: baseline;
}
.coin-num {
font-size: 56rpx;
font-weight: bold;
color: #fff;
margin: 0 12rpx;
}
.coin-label {
font-size: 26rpx;
color: #ffe;
}
.free-tip {
margin-top: 16rpx;
font-size: 24rpx;
color: #fff;
}
.free-num {
font-weight: bold;
color: #FFD700;
}
.section-title {
font-size: 28rpx;
color: #999;
margin: 10rpx 30rpx 16rpx;
}
.prize-grid {
display: flex;
flex-flow: row wrap;
margin: 0 30rpx;
background-color: #fff;
border-radius: 20rpx;
padding: 20rpx 0;
}
.prize-item {
width: 33.33%;
display: flex;
flex-direction: column;
align-items: center;
padding: 20rpx 0;
}
.prize-icon {
width: 96rpx;
height: 96rpx;
border-radius: 48rpx;
background-color: #f7f7f7;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 12rpx;
}
.prize-name {
font-size: 26rpx;
color: #333;
font-weight: 500;
}
.prize-sub {
font-size: 22rpx;
color: #999;
margin-top: 4rpx;
}
.draw-btn {
margin: 40rpx 60rpx 0;
height: 96rpx;
border-radius: 48rpx;
background: linear-gradient(135deg, #FF6B6B 0%, #FF8E53 100%);
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 10rpx 30rpx rgba(255, 107, 107, 0.3);
}
.draw-btn.disabled {
opacity: 0.6;
}
.draw-btn text {
color: #fff;
font-size: 32rpx;
font-weight: bold;
}
.draw-hint {
display: block;
text-align: center;
font-size: 22rpx;
color: #bbb;
margin: 16rpx 0 60rpx;
}
.mask {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 999;
}
.result-card {
width: 560rpx;
background-color: #fff;
border-radius: 24rpx;
padding: 60rpx 40rpx 40rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.result-title {
font-size: 36rpx;
font-weight: bold;
color: #333;
margin-top: 24rpx;
}
.result-sub {
font-size: 26rpx;
color: #FF9500;
margin-top: 12rpx;
}
.result-btn {
margin-top: 40rpx;
width: 100%;
height: 80rpx;
border-radius: 40rpx;
background: linear-gradient(135deg, #FF6B6B 0%, #FF8E53 100%);
display: flex;
align-items: center;
justify-content: center;
}
.result-btn text {
color: #fff;
font-size: 30rpx;
}
</style>