Feat:抽奖2.0(细节调整,查漏补缺)

This commit is contained in:
linxi
2026-04-30 18:19:23 +08:00
parent c3c0483625
commit 91aad660e6
7 changed files with 130 additions and 69 deletions
+12
View File
@@ -49,6 +49,18 @@ export function getActivityWinRecord(activityId) {
return request.get('/draw/activityWinRecord', { activityId }) return request.get('/draw/activityWinRecord', { activityId })
} }
/**
* 获取最新中奖名单
* @param activityId 抽奖活动ID(可选)
*/
export function getDrawLatestWinners(activityId) {
const params = {}
if (activityId !== undefined && activityId !== null && activityId !== '') {
params.activityId = activityId
}
return request.get('/draw/latestWinners', params)
}
/** /**
* 历史抽奖活动列表 * 历史抽奖活动列表
* 用于在中奖名单页面切换历史抽奖活动 * 用于在中奖名单页面切换历史抽奖活动
+14
View File
@@ -375,6 +375,7 @@
<view <view
v-if="order.isDrawOrder > 0" v-if="order.isDrawOrder > 0"
class="bnt service" class="bnt service"
@click.stop="callMerPhone(order)"
>联系客服 >联系客服
</view> </view>
<view> <view>
@@ -1055,6 +1056,19 @@ export default {
force2Decimal(v) { force2Decimal(v) {
return this.$force2Decimal(v) return this.$force2Decimal(v)
}, },
callMerPhone(order) {
const phone = String((order && order.merPhone) || '').trim()
if (!phone) {
uni.showToast({
title: '暂无电话',
icon: 'none'
})
return
}
uni.makePhoneCall({
phoneNumber: phone
})
},
goRoom(order) { goRoom(order) {
console.log(order); console.log(order);
if (order.experienceOrderInfo) { if (order.experienceOrderInfo) {
+17 -27
View File
@@ -489,7 +489,7 @@
<template v-if="status.type == 1" > <template v-if="status.type == 1" >
<view class="v12-justify-between " style="width: 100%"> <view class="v12-justify-between " style="width: 100%">
<view class="v12-justify-between "> <view class="v12-justify-between ">
<view v-if="orderInfo.isDrawOrder > 0" class="bnt v12-dark-text v12-dark-border cancel">联系客服</view> <view v-if="orderInfo.isDrawOrder > 0" class="bnt v12-dark-text v12-dark-border cancel" @click.stop="callMerPhone">联系客服</view>
<view v-if="orderInfo.isGiftCardReceiveBlind === 0 && orderInfo.isDrawOrder === 0" class="bnt v12-dark-text v12-dark-border cancel" @click="goRoom(orderInfo)">联系商家</view> <view v-if="orderInfo.isGiftCardReceiveBlind === 0 && orderInfo.isDrawOrder === 0" class="bnt v12-dark-text v12-dark-border cancel" @click="goRoom(orderInfo)">联系商家</view>
<view v-if="orderInfo.isDrawOrder === 0" class="bnt v12-dark-text v12-dark-border cancel" @click="delayOrder">催发货</view> <view v-if="orderInfo.isDrawOrder === 0" class="bnt v12-dark-text v12-dark-border cancel" @click="delayOrder">催发货</view>
<view v-if="canShowModifyAddress(orderInfo) && orderInfo.isDrawOrder === 0" class="bnt v12-dark-text v12-dark-border cancel" @click="goAddress">修改地址</view> <view v-if="canShowModifyAddress(orderInfo) && orderInfo.isDrawOrder === 0" class="bnt v12-dark-text v12-dark-border cancel" @click="goAddress">修改地址</view>
@@ -559,7 +559,7 @@
</template> </template>
<template v-if="status.type == 4"> <template v-if="status.type == 4">
<view class="v12-justify-between " style="width: 100%"> <view class="v12-justify-between " style="width: 100%">
<view v-if="orderInfo.isDrawOrder > 0" class="bnt v12-dark-text v12-dark-border cancel" >联系客服</view> <view v-if="orderInfo.isDrawOrder > 0" class="bnt v12-dark-text v12-dark-border cancel" @click.stop="callMerPhone">联系客服</view>
<view class="bnt v12-dark-text v12-dark-border cancel" @click="delOrder">删除订单</view> <view class="bnt v12-dark-text v12-dark-border cancel" @click="delOrder">删除订单</view>
</view> </view>
<!-- <view <!-- <view
@@ -588,7 +588,7 @@
<view class="draw-ticket-close" @click="closeDrawTicketPopup">×</view> <view class="draw-ticket-close" @click="closeDrawTicketPopup">×</view>
<view class="draw-ticket-icon"> <view class="draw-ticket-icon">
<view class="ticket-icon-box"> <view class="ticket-icon-box">
<view class="ticket-icon-check"></view> <image class="ticket-icon-check" :src="webUrl + '/home/gongxi.png'" mode="widthFix"></image>
</view> </view>
</view> </view>
<view class="draw-ticket-title">支付成功</view> <view class="draw-ticket-title">支付成功</view>
@@ -970,6 +970,17 @@ export default {
url: `/pkg_common/views/room?id=${order.merId}&name=${order.merName}&params=${JSON.stringify(params)}` url: `/pkg_common/views/room?id=${order.merId}&name=${order.merName}&params=${JSON.stringify(params)}`
}) })
}, },
callMerPhone() {
const phone = String((this.orderInfo && this.orderInfo.merPhone) || '').trim()
if (!phone) {
uni.showToast({
title: '暂无商家电话',
icon: 'none'
})
return
}
this.call(phone)
},
force2Decimal(v) { force2Decimal(v) {
return this.$force2Decimal(v); return this.$force2Decimal(v);
}, },
@@ -1572,37 +1583,16 @@ export default {
} }
.ticket-icon-box { .ticket-icon-box {
width: 90rpx; width: 100rpx;
height: 70rpx; height: 70rpx;
border: 6rpx solid #111;
border-radius: 10rpx; border-radius: 10rpx;
position: relative; position: relative;
box-sizing: border-box; box-sizing: border-box;
} }
.ticket-icon-box::before {
content: '';
position: absolute;
top: -16rpx;
left: 14rpx;
width: 50rpx;
height: 12rpx;
border-top: 6rpx solid #111;
border-left: 6rpx solid #111;
border-right: 6rpx solid #111;
border-radius: 6rpx 6rpx 0 0;
background: #fff;
}
.ticket-icon-check { .ticket-icon-check {
width: 36rpx; width: 100%;
height: 18rpx; height: 100%;
border-left: 6rpx solid #c23326;
border-bottom: 6rpx solid #c23326;
transform: rotate(-45deg);
position: absolute;
left: 20rpx;
top: 14rpx;
} }
.draw-ticket-title { .draw-ticket-title {
+1
View File
@@ -2105,6 +2105,7 @@ export default {
.product-con .footer{ .product-con .footer{
height: 140rpx !important; height: 140rpx !important;
padding-bottom: 20rpx; padding-bottom: 20rpx;
z-index: 1002 !important;
} }
.product-con .product-intro .conter view { .product-con .product-intro .conter view {
width: 100% !important; width: 100% !important;
+23 -10
View File
@@ -17,7 +17,7 @@
<view class="side-entry rules" @click="openRulesModel">活动规则</view> <view class="side-entry rules" @click="openRulesModel">活动规则</view>
<view class="side-entry mine" @click="navToLog">我的抽奖码</view> <view class="side-entry mine" @click="navToLog">我的抽奖码</view>
<view class="winners-wrap" @click="navToLog"> <view class="winners-wrap">
<view class="winners-text" v-if="!winnerSortedList.length">暂时无人中奖</view> <view class="winners-text" v-if="!winnerSortedList.length">暂时无人中奖</view>
<view class="winners-text one-t" v-else-if="winnerSortedList.length === 1"> <view class="winners-text one-t" v-else-if="winnerSortedList.length === 1">
恭喜 <text class="blue">{{ winnerSortedList[0].name }}</text> 恭喜 <text class="blue">{{ winnerSortedList[0].name }}</text>
@@ -123,7 +123,7 @@
</template> </template>
<script> <script>
import { getDrawActivityInfo } from '@/api/lottery' import { getDrawActivityInfo, getDrawLatestWinners } from '@/api/lottery'
import { postCartAdd } from '@/api/store' import { postCartAdd } from '@/api/store'
import ProductWindow from '@/components/ProductWindow' import ProductWindow from '@/components/ProductWindow'
import goCartMixin from '@/mixins/goCartMixins' import goCartMixin from '@/mixins/goCartMixins'
@@ -145,6 +145,7 @@ export default {
prizePool: [], prizePool: [],
products: [] products: []
}, },
latestWinnerList: [],
activityId: 0, activityId: 0,
linkType: 1, linkType: 1,
onlyOneToAddCart: false, onlyOneToAddCart: false,
@@ -184,7 +185,7 @@ export default {
})) }))
}, },
winnerSortedList() { winnerSortedList() {
const list = this.activityInfo.winnerList || [] const list = this.latestWinnerList || []
if (!list.length) return [] if (!list.length) return []
const mapped = list.map(item => ({ const mapped = list.map(item => ({
name: item.realName || item.phone || '用户', name: item.realName || item.phone || '用户',
@@ -194,7 +195,8 @@ export default {
return mapped.sort((a, b) => this.getPeriodNoValue(b.periodNo) - this.getPeriodNoValue(a.periodNo)) return mapped.sort((a, b) => this.getPeriodNoValue(b.periodNo) - this.getPeriodNoValue(a.periodNo))
}, },
buyThresholdText() { buyThresholdText() {
return 99 const spendThreshold = this.activityInfo.spendThreshold || 0
return spendThreshold
}, },
openDateText() { openDateText() {
const target = this.getTargetDate() const target = this.getTargetDate()
@@ -223,9 +225,12 @@ export default {
}) })
return return
} }
getDrawActivityInfo(this.activityId).then(res => { Promise.all([
if (res.success) { getDrawActivityInfo(this.activityId),
const data = res.data || {} getDrawLatestWinners()
]).then(([activityRes, winnersRes]) => {
if (activityRes && activityRes.success) {
const data = activityRes.data || {}
this.activityInfo = { this.activityInfo = {
...this.activityInfo, ...this.activityInfo,
...data, ...data,
@@ -234,6 +239,11 @@ export default {
this.ready = true this.ready = true
this.startCountdown() this.startCountdown()
} }
const winnersData = winnersRes && winnersRes.data
const list = Array.isArray(winnersData)
? winnersData
: (Array.isArray(winnersData && winnersData.list) ? winnersData.list : [])
this.latestWinnerList = list
}) })
}, },
getTargetDate() { getTargetDate() {
@@ -291,9 +301,12 @@ export default {
uni.navigateTo({ url: '/pkg-video/views/county-lottery-rules' }) uni.navigateTo({ url: '/pkg-video/views/county-lottery-rules' })
}, },
navToWinners() { navToWinners() {
uni.navigateTo({ const targetDate = this.getTargetDate()
url: `/pkg-video/views/county-winners?activityId=${this.activityId}` const isNotOpened = targetDate && targetDate.getTime() > Date.now()
}) const url = isNotOpened
? '/pkg-video/views/county-winners'
: `/pkg-video/views/county-winners?activityId=${this.activityId}`
uni.navigateTo({ url })
}, },
navToLog() { navToLog() {
uni.navigateTo({ url: '/pkg-video/views/county-my-tickets' }) uni.navigateTo({ url: '/pkg-video/views/county-my-tickets' })
+2 -2
View File
@@ -288,7 +288,7 @@ export default {
this.goMyCoupons() this.goMyCoupons()
return return
} }
if (!item.sourceOrderId) { if (!item.prizeOrderId) {
uni.showToast({ uni.showToast({
title: '缺少订单号', title: '缺少订单号',
icon: 'none' icon: 'none'
@@ -296,7 +296,7 @@ export default {
return return
} }
uni.navigateTo({ uni.navigateTo({
url: `/pages/order/OrderDetails/index?id=${item.sourceOrderId}` url: `/pages/order/OrderDetails/index?id=${item.prizeOrderId}`
}) })
}, },
goBack() { goBack() {
+61 -30
View File
@@ -10,7 +10,7 @@
</view> --> </view> -->
<view class="content-wrap" v-if="loaded"> <view class="content-wrap" v-if="loaded">
<view v-if="!showHistory" class="draw-info-wrap" :style="{ backgroundImage: `url(${webUrl}/zhongjiang5.png)` }"> <view v-if="!useHistoryHeader" class="draw-info-wrap" :style="{ backgroundImage: `url(${webUrl}/zhongjiang5.png)` }">
<view class="period-side left"> <view class="period-side left">
<text class="side-text v12-font-36"></text> <text class="side-text v12-font-36"></text>
<text class="side-text v12-font-36">{{ periodLabel }}</text> <text class="side-text v12-font-36">{{ periodLabel }}</text>
@@ -74,10 +74,10 @@
</view> </view>
</view> </view>
<button v-if="!showHistory" class="my-tickets-btn" @click="handleClaimNow"> <button v-if="showClaimNowBtn" class="my-tickets-btn" @click="handleClaimNow">
<text class="btn-text">立即领取</text> <text class="btn-text">立即领取</text>
</button> </button>
<button v-if="showHistory" class="my-tickets-btn" @click="navToMyTickets"> <button v-else class="my-tickets-btn" @click="navToMyTickets">
<text class="btn-text">我的抽奖码</text> <text class="btn-text">我的抽奖码</text>
</button> </button>
<view class="claim-tip">*请在7天内领取过期失效</view> <view class="claim-tip">*请在7天内领取过期失效</view>
@@ -147,10 +147,22 @@ export default {
return this.historyList.findIndex(item => Number(item.id) === Number(this.activityId)) return this.historyList.findIndex(item => Number(item.id) === Number(this.activityId))
}, },
canSwitchPrev() { canSwitchPrev() {
return this.currentHistoryIndex > -1 && this.currentHistoryIndex < this.historyList.length - 1 if (!this.historyList.length) return false
if (this.currentHistoryIndex < 0) return true
return this.currentHistoryIndex < this.historyList.length - 1
}, },
canSwitchNext() { canSwitchNext() {
if (!this.historyList.length) return false
if (this.currentHistoryIndex < 0) return true
return this.currentHistoryIndex > 0 return this.currentHistoryIndex > 0
},
useHistoryHeader() {
return this.showHistory || this.entryWithoutActivityId
},
showClaimNowBtn() {
if (this.userWinList.length !== 1) return false
const prize = this.userWinList[0] || {}
return Number(prize.claimStatus) === 0
} }
}, },
data() { data() {
@@ -167,25 +179,24 @@ export default {
loaded: false, loaded: false,
showCouponSuccessPopup: false, showCouponSuccessPopup: false,
showHistory: false, showHistory: false,
entryWithoutActivityId: false,
historyList: [] historyList: []
} }
}, },
onLoad(options) { onLoad(options) {
this.activityId = Number(options && options.activityId) || 0 const incomingActivityId = Number(options && options.activityId) || 0
this.entryWithoutActivityId = !incomingActivityId
this.activityId = incomingActivityId
const systemInfo = uni.getSystemInfoSync() const systemInfo = uni.getSystemInfoSync()
this.statusBarHeight = systemInfo.statusBarHeight || 20 this.statusBarHeight = systemInfo.statusBarHeight || 20
this.fetchData() this.fetchData()
}, },
methods: { methods: {
async handleShowHistory() { async loadHistoryList() {
uni.showLoading({
mask: true
})
const historyRes = await getDrawHistoryActivities() const historyRes = await getDrawHistoryActivities()
const {data, success} = historyRes || {} const { data, success } = historyRes || {}
uni.hideLoading() if (!success) return []
if(!success) return const list = (data || [])
this.historyList = (data || [])
.map(item => ({ .map(item => ({
id: Number(item.id || item.activityId || item.drawActivityId || 0), id: Number(item.id || item.activityId || item.drawActivityId || 0),
periodNo: item.periodNo || '', periodNo: item.periodNo || '',
@@ -193,6 +204,16 @@ export default {
})) }))
.filter(item => item.id > 0) .filter(item => item.id > 0)
.sort((a, b) => this.getPeriodNoValue(b.periodNo) - this.getPeriodNoValue(a.periodNo)) .sort((a, b) => this.getPeriodNoValue(b.periodNo) - this.getPeriodNoValue(a.periodNo))
this.historyList = list
return list
},
async handleShowHistory() {
uni.showLoading({
mask: true
})
const list = await this.loadHistoryList()
uni.hideLoading()
if (!list.length) return
this.showHistory = true this.showHistory = true
}, },
async handleSwitchHistory(direction) { async handleSwitchHistory(direction) {
@@ -204,14 +225,9 @@ export default {
return return
} }
const currentIndex = this.currentHistoryIndex const currentIndex = this.currentHistoryIndex
if (currentIndex < 0) { const targetIndex = currentIndex < 0
uni.showToast({ ? (direction === 'prev' ? 0 : this.historyList.length - 1)
title: "当前期数不在历史列表中", : (direction === 'prev' ? currentIndex + 1 : currentIndex - 1)
icon: "none"
})
return
}
const targetIndex = direction === 'prev' ? currentIndex + 1 : currentIndex - 1
if (targetIndex < 0 || targetIndex >= this.historyList.length) return if (targetIndex < 0 || targetIndex >= this.historyList.length) return
const target = this.historyList[targetIndex] const target = this.historyList[targetIndex]
if (!target || Number(target.id) === Number(this.activityId)) return if (!target || Number(target.id) === Number(this.activityId)) return
@@ -229,6 +245,10 @@ export default {
}, },
handleClaimNow() { handleClaimNow() {
if (!this.userWinList.length) return if (!this.userWinList.length) return
if (!this.showClaimNowBtn) {
this.navToMyTickets()
return
}
if (this.userWinList.length > 1) { if (this.userWinList.length > 1) {
this.navToMyTickets() this.navToMyTickets()
@@ -308,6 +328,7 @@ export default {
prizeName: item.prizeName || item.awardName || "神秘奖品", prizeName: item.prizeName || item.awardName || "神秘奖品",
prizeDesc: item.prizeDesc || item.remark || "默认", prizeDesc: item.prizeDesc || item.remark || "默认",
ticketCode: item.ticketCode || item.code || "--", ticketCode: item.ticketCode || item.code || "--",
claimStatus: Number(item.claimStatus),
prizeType: item.prizeType, prizeType: item.prizeType,
prizeTypeName: item.prizeTypeName || item.prizeCategoryName || "", prizeTypeName: item.prizeTypeName || item.prizeCategoryName || "",
prizeImage: item.prizeImage || item.image || "" prizeImage: item.prizeImage || item.image || ""
@@ -315,24 +336,34 @@ export default {
}, },
async fetchData() { async fetchData() {
try { try {
let targetActivityId = Number(this.activityId) || 0
if (!targetActivityId) {
const historyList = await this.loadHistoryList()
this.showHistory = true
targetActivityId = (historyList[0] && Number(historyList[0].id)) || 0
if (targetActivityId) {
this.activityId = targetActivityId
}
}
const [activityRes, winnerRes, myTicketsRes] = await Promise.all([ const [activityRes, winnerRes, myTicketsRes] = await Promise.all([
this.activityId ? getDrawActivityInfo(this.activityId) : Promise.resolve(null), targetActivityId ? getDrawActivityInfo(targetActivityId) : Promise.resolve(null),
this.activityId ? getActivityWinRecord(this.activityId) : Promise.resolve(null), targetActivityId ? getActivityWinRecord(targetActivityId) : Promise.resolve(null),
getDrawMyTickets(1) getDrawMyTickets(1)
]) ])
const activityData = (activityRes && activityRes.data) || {} const activityData = (activityRes && activityRes.data) || {}
const winnerList = winnerRes.data.activityWinnerList || [] const winnerData = (winnerRes && winnerRes.data) || {}
const winnerList = winnerData.activityWinnerList || []
const myTicketList = this.normalizeListData(myTicketsRes) const myTicketList = this.normalizeListData(myTicketsRes)
const filteredMyTicketList = this.activityId const filteredMyTicketList = targetActivityId
? myTicketList.filter(item => Number(item.activityId || item.drawActivityId || 0) === this.activityId) ? myTicketList.filter(item => Number(item.activityId || item.drawActivityId || 0) === targetActivityId)
: myTicketList : myTicketList
this.drawTime = this.formatDrawTime(activityData.drawTime || activityData.openTime || "") this.drawTime = this.formatDrawTime(activityData.drawTime || activityData.openTime || "")
this.activityWinnerList = winnerList this.activityWinnerList = winnerList
this.userWinList = this.mapUserWinList(filteredMyTicketList) this.userWinList = this.mapUserWinList(filteredMyTicketList)
this.hasWon = this.userWinList.length > 0 ? 1 : 0 this.hasWon = this.userWinList.length > 0 ? 1 : 0
this.periodLabel = winnerRes.data.periodNo || "01" this.periodLabel = winnerData.periodNo || "01"
} catch (e) { } catch (e) {
uni.showToast({ uni.showToast({
title: "中奖数据加载失败", title: "中奖数据加载失败",
@@ -659,11 +690,11 @@ export default {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
border: 4rpx solid #333;
box-shadow: inset 0 -12rpx 0 #FAA100, inset 0 12rpx 0 #FAA100, inset -12rpx 0rpx 0rpx #FAA100, inset 12rpx 0rpx 0 #FAA100; box-shadow: inset 0 -12rpx 0 #FAA100, inset 0 12rpx 0 #FAA100, inset -12rpx 0rpx 0rpx #FAA100, inset 12rpx 0rpx 0 #FAA100;
transition: all 0.1s; transition: all 0.1s;
background: #FDB400; background: #FDB400;
color: #333;
&:active { &:active {
transform: translateY(4rpx); transform: translateY(4rpx);
box-shadow: inset 0 -4rpx 0 #FAA100; box-shadow: inset 0 -4rpx 0 #FAA100;
@@ -732,7 +763,7 @@ export default {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: 280rpx; /* 根据实际标题框宽度设定,让它包裹住背景图 */ width: 280rpx; /* 根据实际标题框宽度设定,让它包裹住背景图 */
height: 80rpx; height: 85rpx;
z-index: 3; z-index: 3;
/* 主背景图,层级2,盖住半圆的一部分 */ /* 主背景图,层级2,盖住半圆的一部分 */