Feat:抽奖2.0(部分接口未调通)
This commit is contained in:
@@ -0,0 +1,550 @@
|
||||
<template>
|
||||
<view class="county-my-tickets-page">
|
||||
<view class="custom-header" :style="{ paddingTop: `${statusBarHeight}px` }">
|
||||
<view class="header-inner">
|
||||
<view class="header-back" @click="goBack">
|
||||
<text class="header-back-icon">‹</text>
|
||||
</view>
|
||||
<view class="header-title">我的抽奖码</view>
|
||||
<view class="header-right">
|
||||
<view class="right-dot"></view>
|
||||
<view class="right-ring"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="tabs">
|
||||
<view
|
||||
v-for="tab in tabs"
|
||||
:key="tab.key"
|
||||
class="tab-item"
|
||||
:class="{ active: activeTab === tab.key }"
|
||||
@click="onChangeTab(tab.key)"
|
||||
>
|
||||
{{ tab.label }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<scroll-view class="page-body" scroll-y :style="{ paddingTop: `calc(${statusBarHeight}px + 168rpx)` }">
|
||||
<view class="tip-bar" v-if="summaryText">
|
||||
<view class="tip-text one-t">{{ summaryText }}</view>
|
||||
<view class="tip-btn" @click="goWinnersPage">查看全部 <text class="icon-expand">⤢</text></view>
|
||||
</view>
|
||||
|
||||
<view class="ticket-list" v-if="displayList.length">
|
||||
<view class="ticket-card" v-for="item in displayList" :key="item.id">
|
||||
<view class="ticket-head">
|
||||
<view class="ticket-code">
|
||||
<text class="code-icon">🎟</text>
|
||||
<text class="code-label">抽奖码:</text>
|
||||
<text class="code-value">{{ item.ticketCode || '--' }}</text>
|
||||
</view>
|
||||
<view class="ticket-status" :class="[ `status-${item.status}`, item.status === 0 ? 'status-pill' : '', item.status === 1 && item.claimStatus === 1 ? 'status-claimed' : '' ]">{{ getStatusText(item) }}</view>
|
||||
</view>
|
||||
|
||||
<view class="ticket-info-row">
|
||||
<text class="label">来源订单</text>
|
||||
<text class="value">{{ item.sourceOrderId || '--' }}</text>
|
||||
</view>
|
||||
<view class="ticket-info-row">
|
||||
<text class="label">开奖时间</text>
|
||||
<text class="value">{{ formatDrawTime(item.drawTime) }}</text>
|
||||
</view>
|
||||
|
||||
<view class="prize-box" v-if="showPrize(item)">
|
||||
恭喜获得:{{ item.prizeName || '神秘奖品' }}
|
||||
</view>
|
||||
|
||||
<view class="ticket-footer" v-if="item.status === 1">
|
||||
<template v-if="item.claimStatus === 0">
|
||||
<view class="footer-note">注意:请在7天内领取,过期不予发放</view>
|
||||
<view class="footer-btn btn-claim" @click="onClaim(item)">立 即 领 取</view>
|
||||
</template>
|
||||
<template v-else-if="item.claimStatus === 1">
|
||||
<view class="footer-note done">奖品已领取</view>
|
||||
<view class="footer-btn btn-order" @click="goOrder(item)">查看订单</view>
|
||||
</template>
|
||||
</view>
|
||||
|
||||
<view class="invalid-reason" v-if="item.status === -1">
|
||||
失效原因:{{ getInvalidReason(item) }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="empty-wrap" v-else>
|
||||
<view class="empty-text">{{ loading ? '加载中...' : '暂无抽奖码记录' }}</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import { getDrawMyTickets } from '@/api/lottery'
|
||||
|
||||
export default {
|
||||
name: 'CountyMyTicketsPage',
|
||||
data() {
|
||||
return {
|
||||
statusBarHeight: 20,
|
||||
loading: false,
|
||||
activeTab: 'all',
|
||||
activityId: 1,
|
||||
tabs: [
|
||||
{ key: 'all', label: '全部' },
|
||||
{ key: 'wait', label: '待开奖' },
|
||||
{ key: 'opened', label: '已开奖' },
|
||||
{ key: 'invalid', label: '已失效' }
|
||||
],
|
||||
list: [],
|
||||
openedList: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
displayList() {
|
||||
return this.activeTab === 'opened' ? this.openedList : this.list
|
||||
},
|
||||
summaryText() {
|
||||
return `恭喜海*在第01期抽奖活动中获得 iPhone17 pro 手机`
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
if (options && options.activityId) {
|
||||
this.activityId = Number(options.activityId) || 1
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
this.statusBarHeight = uni.getSystemInfoSync().statusBarHeight || 20
|
||||
this.fetchList()
|
||||
},
|
||||
methods: {
|
||||
mapTabToStatus(tab) {
|
||||
const map = {
|
||||
wait: 0,
|
||||
invalid: -1
|
||||
}
|
||||
return map[tab]
|
||||
},
|
||||
onChangeTab(tab) {
|
||||
if (this.activeTab === tab) return
|
||||
this.activeTab = tab
|
||||
this.fetchList()
|
||||
},
|
||||
goWinnersPage() {
|
||||
uni.navigateTo({
|
||||
url: `/pkg-video/views/county-winners?activityId=${this.activityId}`
|
||||
})
|
||||
},
|
||||
fetchList() {
|
||||
this.loading = true
|
||||
|
||||
// 使用模拟数据以匹配设计图所有状态
|
||||
setTimeout(() => {
|
||||
const mockData = [
|
||||
{
|
||||
id: 1,
|
||||
ticketCode: 'A8F92E',
|
||||
status: 0,
|
||||
sourceOrderId: '12345678910',
|
||||
drawTime: '2026-05-30 10:00:00',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
ticketCode: 'A8F92E',
|
||||
status: 1,
|
||||
claimStatus: 0,
|
||||
sourceOrderId: '12345678910',
|
||||
drawTime: '2026-05-30 10:00:00',
|
||||
prizeName: '一等奖ipone17 pro max手机'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
ticketCode: 'A8F92E',
|
||||
status: 1,
|
||||
claimStatus: 1,
|
||||
sourceOrderId: '12345678910',
|
||||
drawTime: '2026-05-30 10:00:00',
|
||||
prizeName: '一等奖ipone17 pro max手机'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
ticketCode: 'A8F92E',
|
||||
status: -1,
|
||||
claimStatus: 0,
|
||||
sourceOrderId: '12345678910',
|
||||
drawTime: '2026-05-30 10:00:00',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
ticketCode: 'A8F92E',
|
||||
status: -1,
|
||||
claimStatus: -1,
|
||||
sourceOrderId: '12345678910',
|
||||
drawTime: '2026-05-30 10:00:00',
|
||||
prizeName: '一等奖ipone17 pro max手机'
|
||||
}
|
||||
];
|
||||
|
||||
let filteredData = mockData;
|
||||
if (this.activeTab === 'wait') {
|
||||
filteredData = mockData.filter(item => item.status === 0);
|
||||
} else if (this.activeTab === 'opened') {
|
||||
filteredData = mockData.filter(item => item.status === 1 || item.status === 2);
|
||||
} else if (this.activeTab === 'invalid') {
|
||||
filteredData = mockData.filter(item => item.status === -1);
|
||||
}
|
||||
|
||||
this.list = filteredData;
|
||||
this.openedList = mockData.filter(item => item.status === 1 || item.status === 2);
|
||||
this.loading = false;
|
||||
}, 300);
|
||||
},
|
||||
getStatusText(item) {
|
||||
const status = Number(item.status)
|
||||
if (status === 0) return '等待开奖'
|
||||
if (status === 1) return item.claimStatus === 1 ? '已领取' : '已开奖'
|
||||
if (status === 2) return '已开奖'
|
||||
if (status === -1) return '已失效'
|
||||
return '--'
|
||||
},
|
||||
showPrize(item) {
|
||||
return [1, 2, -1].includes(Number(item.status)) && !!item.prizeName
|
||||
},
|
||||
getInvalidReason(item) {
|
||||
if (Number(item.claimStatus) === -1) return '奖品过期未领取'
|
||||
return '订单取消'
|
||||
},
|
||||
formatDrawTime(time) {
|
||||
if (!time) return '--'
|
||||
const date = new Date(String(time).replace(/-/g, '/'))
|
||||
if (Number.isNaN(date.getTime())) return time
|
||||
const y = date.getFullYear()
|
||||
const m = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const d = String(date.getDate()).padStart(2, '0')
|
||||
const hh = String(date.getHours()).padStart(2, '0')
|
||||
const mm = String(date.getMinutes()).padStart(2, '0')
|
||||
return `${y}年${m}月${d}日 ${hh}:${mm}`
|
||||
},
|
||||
onClaim(item) {
|
||||
if (!item.id) return
|
||||
uni.navigateTo({
|
||||
url: `/pages/order/OrderSubmission/index?lotteryRecordId=${item.id}`
|
||||
})
|
||||
},
|
||||
goOrder(item) {
|
||||
if (!item.sourceOrderId) {
|
||||
uni.showToast({
|
||||
title: '缺少订单号',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: `/pages/order/OrderDetails/index?id=${item.sourceOrderId}`
|
||||
})
|
||||
},
|
||||
goBack() {
|
||||
if (getCurrentPages().length > 1) {
|
||||
uni.navigateBack()
|
||||
return
|
||||
}
|
||||
uni.switchTab({
|
||||
url: '/pages/home/index'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.county-my-tickets-page {
|
||||
min-height: 100vh;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.custom-header {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
z-index: 20;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.header-inner {
|
||||
height: 88rpx;
|
||||
padding: 0 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header-back {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
border-radius: 8rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.header-back-icon {
|
||||
font-size: 60rpx;
|
||||
color: #111;
|
||||
line-height: 1;
|
||||
margin-top: -4rpx;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
margin-left: 56rpx;
|
||||
font-size: 34rpx;
|
||||
color: #333;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
width: 88rpx;
|
||||
height: 44rpx;
|
||||
border-radius: 24rpx;
|
||||
border: 2rpx solid #d8d8d8;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.right-dot {
|
||||
width: 8rpx;
|
||||
height: 8rpx;
|
||||
border-radius: 50%;
|
||||
background: #111;
|
||||
margin-right: 14rpx;
|
||||
}
|
||||
|
||||
.right-ring {
|
||||
width: 18rpx;
|
||||
height: 18rpx;
|
||||
border-radius: 50%;
|
||||
border: 2rpx solid #111;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
height: 80rpx;
|
||||
padding: 0 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
margin-right: 20rpx;
|
||||
padding: 8rpx 24rpx;
|
||||
border-radius: 30rpx;
|
||||
color: #666;
|
||||
font-size: 26rpx;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.tab-item.active {
|
||||
color: #BD3124;
|
||||
background: rgba(220,60,53,0.39);
|
||||
}
|
||||
|
||||
.page-body {
|
||||
box-sizing: border-box;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.tip-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10rpx 24rpx;
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
background: #fff;
|
||||
border-radius: 160rpx;
|
||||
margin: 0 20rpx;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
flex: 1;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.tip-btn {
|
||||
background: #FCF9EA;
|
||||
padding: 6rpx 16rpx;
|
||||
border-radius: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 22rpx;
|
||||
color: #333;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.icon-expand {
|
||||
font-size: 20rpx;
|
||||
margin-left: 4rpx;
|
||||
}
|
||||
|
||||
.ticket-list {
|
||||
padding-top: 10rpx;
|
||||
padding-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.ticket-card {
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
margin: 0 24rpx 20rpx;
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.ticket-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-bottom: 20rpx;
|
||||
border-bottom: 2rpx dashed #eee;
|
||||
margin-bottom: 20rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.ticket-code {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.code-icon {
|
||||
margin-right: 8rpx;
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.code-label {
|
||||
font-size: 32rpx;
|
||||
font-weight: 700;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
|
||||
.code-value {
|
||||
font-size: 34rpx;
|
||||
font-weight: 700;
|
||||
letter-spacing: 1rpx;
|
||||
}
|
||||
|
||||
.ticket-status {
|
||||
font-size: 26rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.status-pill {
|
||||
background: #BD3124;
|
||||
color: #fff;
|
||||
padding: 4rpx 16rpx;
|
||||
border-radius: 20rpx 0 0 20rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: normal;
|
||||
position: absolute;
|
||||
right: -24rpx;
|
||||
}
|
||||
|
||||
.status-0 {
|
||||
/* handled by pill */
|
||||
}
|
||||
|
||||
.status-1,
|
||||
.status-2 {
|
||||
color: #BD3124;
|
||||
}
|
||||
|
||||
.status-claimed {
|
||||
color: #999 !important;
|
||||
}
|
||||
|
||||
.status--1 {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.ticket-info-row {
|
||||
margin-top: 14rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.ticket-info-row .label {
|
||||
color: #999;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.ticket-info-row .value {
|
||||
color: #333;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.prize-box {
|
||||
margin-top: 24rpx;
|
||||
border: 2rpx solid #BD3124;
|
||||
border-radius: 40rpx;
|
||||
color: #BD3124;
|
||||
font-size: 30rpx;
|
||||
text-align: center;
|
||||
padding: 16rpx 0;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.ticket-footer {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.footer-note {
|
||||
flex: 1;
|
||||
color: #BD3124;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
|
||||
.footer-note.done {
|
||||
color: #BD3124;
|
||||
}
|
||||
|
||||
.footer-btn {
|
||||
width: 170rpx;
|
||||
height: 54rpx;
|
||||
border-radius: 30rpx;
|
||||
color: #fff;
|
||||
font-size: 26rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.btn-claim {
|
||||
background: #BD3124;
|
||||
}
|
||||
|
||||
.btn-order {
|
||||
background: #BD3124;
|
||||
}
|
||||
|
||||
.invalid-reason {
|
||||
margin-top: 14rpx;
|
||||
font-size: 24rpx;
|
||||
color: #BD3124;
|
||||
}
|
||||
|
||||
.empty-wrap {
|
||||
padding-top: 120rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user