feat(抽奖活动页): 对接接口

This commit is contained in:
hzj 2025-10-22 19:39:28 +08:00
parent edf03650bd
commit caef58fa15
2 changed files with 332 additions and 71 deletions

106
src/api/lottery.js Normal file
View File

@ -0,0 +1,106 @@
import { get, post } from '../utils/http.js'
// 获取排行榜
export const ranklist = async (applicationId) => {
try {
const response = await get(`/activity/lottery/rank-list`)
return response
} catch (error) {
console.error('Failed to fetch get rank list:', error)
console.error('error:' + error.response.errorMsg)
throw error
}
}
// 获取有效活动
export const validActivity = async () => {
try {
const response = await get(`/activity/lottery/valid-activity`)
return response
} catch (error) {
console.error('Failed to fetch get valid activity:', error)
console.error('error:' + error.response.errorMsg)
throw error
}
}
// 获取活动详情
export const activityDetail = async (activityCode) => {
try {
const response = await get(`/activity/lottery/detail/${activityCode}`)
return response
} catch (error) {
console.error('Failed to fetch get activity detail:', error)
console.error('error:' + error.response.errorMsg)
throw error
}
}
// 获取剩余中奖券
export const myTickets = async () => {
try {
const response = await get(`/activity/lottery/my-ticket-count`)
return response
} catch (error) {
console.error('Failed to fetch get my tickets:', error)
console.error('error:' + error.response.errorMsg)
throw error
}
}
// 执行单次抽奖
export const onceDraw = async (data) => {
try {
const response = await post('/activity/lottery/draw', data)
return response
} catch (error) {
console.error('Failed to fetch once draw:', error)
throw error
}
}
// 执行连抽
export const multiDraw = async (data) => {
try {
const response = await post('/activity/lottery/multi-draw', data)
return response
} catch (error) {
console.error('Failed to fetch multiply draw:', error)
throw error
}
}
// 获取中奖记录
export const drawRecords = async () => {
try {
const response = await get(`/activity/lottery/my-records`)
return response
} catch (error) {
console.error('Failed to fetch get draw records:', error)
console.error('error:' + error.response.errorMsg)
throw error
}
}
// 获取任务列表
export const ActTaskList = async () => {
try {
const response = await get(`/spins/task/list`)
return response
} catch (error) {
console.error('Failed to fetch get tickets:', error)
console.error('error:' + error.response.errorMsg)
throw error
}
}
// 领取任务奖励
export const receiveTickets = async (data) => {
try {
const response = await post('/spins/task/receive/reward', data)
return response
} catch (error) {
console.error('Failed to fetch receive reward:', error)
throw error
}
}

View File

@ -43,7 +43,7 @@
>
<div style="font-weight: 590">Ranking</div>
<div
v-for="value in 10"
v-for="user in ranking"
style="
border-radius: 12px;
background: rgba(255, 255, 255, 0.2);
@ -55,22 +55,26 @@
"
>
<div style="display: flex; align-items: center; gap: 4px">
<div style="font-weight: 700">999</div>
<div style="font-weight: 700">{{ user.rank }}</div>
<img
:src="''"
:src="user.avatar || ''"
alt=""
width="15%"
style="border-radius: 50%; aspect-ratio: 1/1; object-fit: cover"
@error="defaultAvatarUrl"
/>
<div style="width: 70%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis">
asdfadsfasfasfda
{{ user.nickname || '' }}
</div>
</div>
<div style="display: flex; gap: 4px">
<img src="/src/assets/icon/dollar.png" alt="" width="10vw" />
<div style="color: #2df860; font-weight: 500">99999</div>
<img
src="/src/assets/icon/dollar.png"
alt=""
style="display: block; object-fit: cover; width: 5vw"
/>
<div style="color: #2df860; font-weight: 500">{{ user.totalAmount }}</div>
</div>
</div>
</div>
@ -100,7 +104,7 @@
@click="helpShow = true"
/>
<img
:src="''"
:src="userInfo.userAvatar || ''"
alt=""
width="15%"
style="border-radius: 50%; aspect-ratio: 1/1; object-fit: cover"
@ -125,7 +129,7 @@
text-overflow: ellipsis;
"
>
Nanfangjianasdfasdfasdfasdf
{{ userInfo.userNickname || '' }}
</div>
<div style="font-weight: 600">Current amount:$1</div>
</div>
@ -152,6 +156,7 @@
<div
style="display: flex; justify-content: space-between; align-items: center"
@click="drawerShowBt('transfer')"
v-if="userIdentity.anchor"
>
<div>Transfer To Recharge Agent</div>
<img
@ -397,7 +402,7 @@
"
>
<div
v-for="(prize, index) in prizes"
v-for="(prize, index) in activity.prizeList"
style="
display: flex;
flex-direction: column;
@ -413,8 +418,8 @@
]"
:class="{ 'active-prize': activeIndex === index }"
>
<img src="/src/assets/icon/coinMore.png" alt="" width="50%" style="display: block" />
<div>{{ prize.value }}</div>
<img :src="prize.prizeImage || ''" alt="" width="50%" style="display: block" />
<div style="font-size: 0.8em">{{ prize.prizeName }}</div>
</div>
<!-- 按钮 -->
@ -515,21 +520,21 @@
<!-- 图标 -->
<div style="width: 20%">
<img
v-if="task.type === 'talk'"
v-if="task.taskType == 1"
:src="images.talking"
alt=""
width="100%"
style="display: block"
/>
<img
v-if="task.type === 'gift'"
v-if="task.taskType == 2"
:src="images.gift"
alt=""
width="100%"
style="display: block"
/>
<img
v-if="task.type === 'invite'"
v-if="task.taskType == 3"
:src="images.invite"
alt=""
width="100%"
@ -538,28 +543,39 @@
</div>
<!-- 内容 -->
<div style="width: 60%">
<div style="color: rgba(0, 0, 0, 0.8); font-weight: 590">{{ task.title }}</div>
<div>
<div v-if="task.taskType == 1" style="color: rgba(0, 0, 0, 0.8); font-weight: 590">
{{ showTarget(task) }}
</div>
<div v-else style="color: rgba(0, 0, 0, 0.8); font-weight: 590">
{{ task.taskName }}
</div>
</div>
<div style="display: flex; align-items: center; gap: 8px">
<img :src="images.ticket" alt="" width="15%" style="display: block" />
<div style="color: #2f0; font-weight: 590">*1</div>
<div style="color: #2f0; font-weight: 590">*{{ task.rewardValue }}</div>
</div>
</div>
<!-- 按钮 -->
<div style="width: 20%">
<!-- 前往任务 -->
<img
v-if="task.taskStatus == 0"
:src="images.goToTask"
alt=""
width="100%"
style="display: block"
v-if="task.done === 0"
/>
<!-- 领取抽奖券 -->
<img
v-else-if="task.taskStatus === 1"
:src="images.receive"
alt=""
width="100%"
style="display: block"
v-else-if="task.received === 0"
@click="receiveTaskReward(task.taskCode)"
/>
<!-- 已完成 -->
<img :src="images.done" alt="" width="100%" style="display: block" v-else />
</div>
</div>
@ -591,22 +607,26 @@
"
>
<div style="display: flex; align-items: center; gap: 4px">
<div style="font-weight: 700">999</div>
<div style="font-weight: 700">{{ userInfo.rank || 999 }}</div>
<img
:src="''"
:src="userInfo.userAvatar || ''"
alt=""
width="15%"
style="border-radius: 50%; aspect-ratio: 1/1; object-fit: cover"
@error="defaultAvatarUrl"
/>
<div style="width: 70%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis">
asdfadsfasfasfda
{{ userInfo.userNickname || '' }}
</div>
</div>
<div style="display: flex; gap: 4px">
<img src="/src/assets/icon/dollar.png" alt="" width="10vw" />
<div style="color: #2df860; font-weight: 500">99999</div>
<img
src="/src/assets/icon/dollar.png"
alt=""
style="display: block; object-fit: cover; width: 5vw"
/>
<div style="color: #2df860; font-weight: 500">{{ userInfo.totalAmount || 0 }}</div>
</div>
</div>
@ -650,7 +670,12 @@
/>
</div>
<!-- 奖品 -->
<img src="/src/assets/icon/coinMore.png" alt="" width="50%" style="display: block" />
<img
:src="result[resultShowIndex]?.prize?.prizeImage"
alt=""
width="50%"
style="display: block"
/>
<!-- 下一个奖品 -->
<div style="width: 8%">
<img
@ -677,7 +702,7 @@
position: relative;
"
>
You Get {{ result[resultShowIndex]?.value }}
You Get {{ result[resultShowIndex]?.prize?.prizeName }}
<div
v-if="result.length > 1"
style="
@ -744,7 +769,7 @@
class="scrollbar"
>
<div
v-for="value in 10"
v-for="(record, index) in myRecords"
style="
border-radius: 12px;
background: rgba(255, 255, 255, 0.2);
@ -759,14 +784,17 @@
>
<div style="display: flex; align-items: center; gap: 4px">
<img
src="/src/assets/icon/coin.png"
:src="record.prize.prizeImage || ''"
alt=""
style="width: 10vw; object-fit: cover; display: block; aspect-ratio: 1/1"
/>
<div style="font-weight: 590; font-size: 0.9em">100000 coins</div>
<div style="font-weight: 590; font-size: 0.9em">x1</div>
<div style="font-weight: 590; font-size: 0.9em">
{{ record.prize.prizeName }} x1
</div>
</div>
<div style="font-weight: 510; font-size: 0.8em">
{{ formatUTCCustom(record.drawTime) }}
</div>
<div style="font-weight: 510; font-size: 0.8em">2025.08.01 10:59:59</div>
</div>
</div>
</div>
@ -801,8 +829,20 @@ import {
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
import maskLayer from '@/components/MaskLayer.vue'
import { useDebounce, useThrottle } from '@/utils/useDebounce'
import { getMemberProfile } from '@/api/wallet'
import { formatUTCCustom } from '@/utils/utcFormat.js'
import { getMemberProfile, getUserIdentity } from '@/api/wallet'
import { useRouter } from 'vue-router'
import {
ranklist, //
validActivity, //
activityDetail, //
myTickets, //
onceDraw, //
multiDraw, //
drawRecords, //
ActTaskList, //
receiveTickets, //
} from '@/api/lottery'
import Barrage from '@/components/Lottery/Barrage.vue'
const router = useRouter()
@ -825,23 +865,23 @@ const barrageList = ref([
{ text: 'Junge withdrew $10', type: 'doller' },
])
//
const activity = ref({})
// (8)
const prizes = ref([
{ value: '奖品1' },
{ value: '奖品2' },
{ value: '奖品3' },
{ value: '奖品4' },
{ value: '奖品5' },
{ value: '奖品6' },
{ value: '奖品7' },
{ value: '奖品8' },
])
const prizes = ref([])
const userInfo = ref({}) //
const userIdentity = ref({}) //
const ranking = ref([]) //
const activeIndex = ref(-1) //
const isRolling = ref(false) //
const rollTimes = ref(11) //
const rollTimes = ref(0) //
const result = ref([]) //
const resultShowIndex = ref(0)
const myRecords = ref([]) //
const isInAppEnvironment = ref(false) // APP
@ -882,18 +922,17 @@ const handleBt = (type) => {
selectedCoin.value = null //
}
const taskList = ref([
{ type: 'talk', title: 'On the mic(0/15mins)', done: 1, received: 1, num: 1 },
{ type: 'talk', title: 'On the mic(0/30mins)', done: 1, received: 0, num: 1 },
{ type: 'talk', title: 'On the mic(0/1hours)', done: 0, received: 0, num: 1 },
{ type: 'talk', title: 'On the mic(0/2hours)', done: 0, received: 0, num: 1 },
{ type: 'gift', title: 'Send a gift', done: 1, received: 1, num: 1 },
{ type: 'gift', title: 'Send three gifts', done: 0, received: 0, num: 1 },
{ type: 'gift', title: 'Send ten gifts', done: 0, received: 0, num: 1 },
{ type: 'gift', title: 'Send fifteen gifts', done: 0, received: 0, num: 1 },
{ type: 'invite', title: 'Invite a user', done: 1, received: 1, num: 1 },
{ type: 'invite', title: 'Invite three users', done: 0, received: 0, num: 1 },
])
const taskList = ref([])
//
const showTarget = (task) => {
let timeType = task.targetValue < 60
let currentValue = timeType ? task.currentValue : task.currentValue / 60
let targetValue = timeType ? task.targetValue : task.targetValue / 60
let timeUnit = timeType ? 'mins' : 'hours'
return `On the mic(${currentValue}/${targetValue}${timeUnit})`
}
//
const selectedPayee = ref({
@ -928,6 +967,7 @@ const selectCoin = (coin) => {
}
}
//
const transfer = async () => {
if (!selectedCoin.value) {
showError('Please select an amount first')
@ -986,6 +1026,7 @@ const transfer = async () => {
}
}
//
const closedPopup = () => {
resultShow.value = false
helpShow.value = false
@ -994,12 +1035,14 @@ const closedPopup = () => {
resultShowIndex.value = 0
}
//
const defaultAvatarUrl = (e) => {
console.log('头像资源出错')
e.target.onerror = null //
e.target.src = new URL('/src/assets/images/WeeklyStar/defaultAvatar.png', import.meta.url).href
}
//
const getGridPosition = (index) => {
//
const positions = [
@ -1015,11 +1058,9 @@ const getGridPosition = (index) => {
return positions[index]
}
//
//
const startLottery = (resultIndex) => {
return new Promise((resolve) => {
if (isRolling.value) return //
isRolling.value = true
activeIndex.value = -1
let speed = 200 //
@ -1031,8 +1072,6 @@ const startLottery = (resultIndex) => {
activeIndex.value = (activeIndex.value + 1) % prizes.value.length
if (activeIndex.value === resultIndex && speed > 200) {
isRolling.value = false
setTimeout(() => {
resolve() //
}, 500)
@ -1063,18 +1102,61 @@ const startLottery = (resultIndex) => {
//
const sweepstakes = async (consecutive) => {
if (isRolling.value) return //
//
if (rollTimes.value >= consecutive) {
//
for (let i = 0; i < consecutive; i++) {
const item = { value: `奖品${Math.floor(Math.random() * 8) + 1}` } //
const index = prizes.value.findIndex((prizes) => prizes.value === item.value) //
console.log('index:', index)
await startLottery(index)
result.value.push(item)
isRolling.value = true
let data = {
activityId: activity.value.activity.id,
drawCount: consecutive,
}
rollTimes.value -= consecutive
//
if (consecutive == 1) {
const resOnceDraw = await onceDraw(data)
if (resOnceDraw.status && resOnceDraw.body) {
const resItem = resOnceDraw.body //
const index = activity.value.prizeList.findIndex(
(prize) => prize.prizeName == resItem?.prize.prizeName
) //
console.log('index:', index)
await startLottery(index)
result.value.push(resItem)
}
}
//
else {
const resMultiDraw = await multiDraw(data)
if (resMultiDraw.status && resMultiDraw.body) {
const resDrawList = resMultiDraw.body //
for (let i = 0; i < resDrawList.results.length; i++) {
const resItem = resDrawList.results[i]
const index = activity.value.prizeList.findIndex(
(prize) => prize.prizeName == resItem?.prize.prizeName
) //
console.log('index:', index)
await startLottery(index)
result.value.push(resItem)
}
}
}
getTickets() //
resultShow.value = true
isRolling.value = false
}
}
//
const getUserInfo = async () => {
if (Object.keys(userInfo.value).length === 0) {
const resUserInfo = await getMemberProfile()
if (resUserInfo.status && resUserInfo.body) {
userInfo.value =
userInfo.value == {} ? resUserInfo.body : Object.assign(userInfo.value, resUserInfo.body)
}
}
const resIdentity = await getUserIdentity()
if (resIdentity.status && resIdentity.body) {
userIdentity.value = resIdentity.body
}
}
@ -1093,7 +1175,7 @@ const connectToApp = async () => {
console.groupEnd()
//
// getUserInfo()
getUserInfo()
return { success: true, environment: 'browser' }
}
@ -1113,7 +1195,7 @@ const connectToApp = async () => {
console.groupEnd()
//
// getUserInfo()
getUserInfo()
return { success: true, environment: 'app', fromCache: true }
}
@ -1127,7 +1209,7 @@ const connectToApp = async () => {
console.groupEnd()
//
// getUserInfo()
getUserInfo()
return { success: true, environment: 'app', fromCache: true }
}
@ -1178,7 +1260,7 @@ const connectToApp = async () => {
console.groupEnd()
//
// getUserInfo()
getUserInfo()
return connectionResult
} catch (error) {
@ -1200,9 +1282,82 @@ const connectToApp = async () => {
}
}
//
const getRanking = async () => {
const resRanking = await ranklist()
if (resRanking.status && resRanking.body) {
ranking.value = resRanking.body
//
const myInfo = ranking.value.find((item) => item.account === userInfo.value.account)
if (myInfo) {
userInfo.value = userInfo.value == {} ? myInfo : Object.assign(userInfo.value, myInfo)
}
} else {
ranking.value = {}
}
}
//
const getActivityDetail = async () => {
const resvalidActivity = await validActivity() //
console.log('id:', resvalidActivity.body?.id)
console.log('id2:', JSON.stringify(resvalidActivity.body))
if (resvalidActivity.body?.activityCode) {
const resDetail = await activityDetail(resvalidActivity.body?.activityCode)
if (resDetail.status && resDetail.body) {
activity.value = resDetail.body
} else {
activity.value = {}
}
}
}
//
const getTickets = async () => {
const resTickets = await myTickets()
if (resTickets.status && resTickets.body) {
rollTimes.value = resTickets.body
} else {
rollTimes.value = 0
}
}
//
const getTaskList = async () => {
const resTaskList = await ActTaskList()
if (resTaskList.status && resTaskList.body) {
taskList.value = resTaskList.body
}
}
//
const getDrawRecords = async () => {
const resDrawRecords = await drawRecords()
if (resDrawRecords.status && resDrawRecords.body) {
myRecords.value = resDrawRecords.body?.records || []
}
}
//
const receiveTaskReward = async (code) => {
let data = {
taskCode: code,
}
const resReceive = await receiveTickets(data)
if (resReceive.status && resReceive.body) {
getTaskList() //
}
}
onMounted(() => {
connectToApp()
isInAppEnvironment.value = isInApp()
getRanking() //
getActivityDetail() //
getDrawRecords() //
getTickets() //
getTaskList() //
})
</script>