修复了抖音版本在微信中的问题
This commit is contained in:
parent
0609f5c531
commit
9d25477cd3
@ -196,6 +196,24 @@ export function joinLottery(data) {
|
||||
return authRequest({ url: '/api/app/lottery/join', method: 'POST', data })
|
||||
}
|
||||
|
||||
/**
|
||||
* 一番赏预下单接口
|
||||
* @param {Object} data - 预下单数据
|
||||
* @param {number} data.activity_id - 活动ID
|
||||
* @param {number} data.issue_id - 期数ID
|
||||
* @param {number[]} data.choices - 选择的位置数组
|
||||
* @param {number} data.coupon_id - 优惠券ID(可选)
|
||||
* @param {number} data.item_card_id - 道具卡ID(可选)
|
||||
* @param {boolean} data.use_game_pass - 是否使用次数卡(可选)
|
||||
*/
|
||||
export function createIchibanPreorder(data) {
|
||||
return authRequest({
|
||||
url: '/api/app/ichiban/preorder',
|
||||
method: 'POST',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function createWechatOrder(data) {
|
||||
return authRequest({ url: '/api/app/pay/wechat/jsapi/preorder', method: 'POST', data })
|
||||
}
|
||||
|
||||
@ -1,5 +1,12 @@
|
||||
<template>
|
||||
<view class="choice-grid-container">
|
||||
<!-- 调试信息 -->
|
||||
<view style="background: #4caf50; padding: 20rpx; margin: 10rpx;">
|
||||
<text style="color: white;">✅ YifanSelector Component Rendered!</text>
|
||||
<text style="color: white; display: block;">activityId: {{ activityId }}</text>
|
||||
<text style="color: white; display: block;">issueId: {{ issueId }}</text>
|
||||
</view>
|
||||
|
||||
<view v-if="loading" class="loading-state">加载中...</view>
|
||||
<view v-else-if="!choices || choices.length === 0" class="empty-state">暂无可选位置</view>
|
||||
|
||||
@ -49,6 +56,8 @@ import { ref, computed, onMounted, watch } from 'vue'
|
||||
import { getIssueChoices, getUserCoupons, joinLottery, createWechatOrder, getLotteryResult } from '@/api/appUser'
|
||||
import { requestLotterySubscription } from '@/utils/subscribe'
|
||||
|
||||
console.log('[YifanSelector] Script setup running!')
|
||||
|
||||
const props = defineProps({
|
||||
activityId: { type: [String, Number], required: true },
|
||||
issueId: { type: [String, Number], required: true },
|
||||
@ -95,6 +104,13 @@ watch(() => props.issueId, (newVal) => {
|
||||
loadChoices()
|
||||
selectedItems.value = []
|
||||
}
|
||||
}, { immediate: true }) // 添加 immediate 选项,确保初始化时立即执行
|
||||
|
||||
// 监听 activityId 变化,重新加载位置数据
|
||||
watch(() => props.activityId, (newVal) => {
|
||||
if (newVal && props.issueId) {
|
||||
loadChoices()
|
||||
}
|
||||
})
|
||||
|
||||
watch(() => props.disabled, (v) => {
|
||||
@ -104,15 +120,31 @@ watch(() => props.disabled, (v) => {
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
console.log('[YifanSelector] Component mounted', {
|
||||
activityId: props.activityId,
|
||||
issueId: props.issueId
|
||||
})
|
||||
if (props.issueId) {
|
||||
loadChoices()
|
||||
}
|
||||
})
|
||||
|
||||
async function loadChoices() {
|
||||
console.log('[YifanSelector] loadChoices called with:', {
|
||||
activityId: props.activityId,
|
||||
issueId: props.issueId
|
||||
})
|
||||
|
||||
if (!props.activityId || !props.issueId) {
|
||||
console.warn('[YifanSelector] Missing activityId or issueId, skipping loadChoices')
|
||||
return
|
||||
}
|
||||
|
||||
loading.value = true
|
||||
try {
|
||||
console.log('[YifanSelector] Calling getIssueChoices API...')
|
||||
const res = await getIssueChoices(props.activityId, props.issueId)
|
||||
console.log('[YifanSelector] getIssueChoices response:', res)
|
||||
|
||||
// 处理 { total_slots: 1, available: [1], claimed: [] } 这种格式
|
||||
if (res && typeof res.total_slots === 'number' && Array.isArray(res.available)) {
|
||||
@ -143,6 +175,7 @@ async function loadChoices() {
|
||||
} else {
|
||||
choices.value = []
|
||||
}
|
||||
console.log('[YifanSelector] Choices processed, total:', choices.value.length)
|
||||
} catch (error) {
|
||||
console.error('Failed to load choices:', error)
|
||||
uni.showToast({ title: '加载位置失败', icon: 'none' })
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<view class="custom-tab-bar">
|
||||
<view class="app-tab-bar-toutiao">
|
||||
<view class="tab-bar-item" @tap="switchTab('pages/index/index')">
|
||||
<image class="tab-icon" :src="selected === 0 ? '/static/tab/home_active.png' : '/static/tab/home.png'" mode="aspectFit"></image>
|
||||
<text class="tab-text" :class="{ active: selected === 0 }">首页</text>
|
||||
@ -58,7 +58,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.custom-tab-bar {
|
||||
.app-tab-bar-toutiao {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<!-- #ifndef MP-TOUTIAO -->
|
||||
<view class="custom-tab-bar">
|
||||
<view class="app-tab-bar">
|
||||
<view class="tab-bar-item" @tap="switchTab('pages/index/index')">
|
||||
<image class="tab-icon" :src="selected === 0 ? '/static/tab/home_active.png' : '/static/tab/home.png'" mode="aspectFit"></image>
|
||||
<text class="tab-text" :class="{ active: selected === 0 }">首页</text>
|
||||
@ -63,7 +63,7 @@ export default {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* #ifndef MP-TOUTIAO */
|
||||
.custom-tab-bar {
|
||||
.app-tab-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
@ -50,21 +50,32 @@
|
||||
</view>
|
||||
|
||||
<!-- 选号组件 - 隐藏内置操作栏 -->
|
||||
<view class="selector-body" v-if="activityId && currentIssueId">
|
||||
<YifanSelector
|
||||
ref="yifanSelectorRef"
|
||||
:activity-id="activityId"
|
||||
:issue-id="currentIssueId"
|
||||
:price-per-draw="Number(detail.price_draw || 0) / 100"
|
||||
:disabled="!isOrderAllowed"
|
||||
:disabled-text="orderBlockedReason"
|
||||
:hide-action-bar="true"
|
||||
@payment-success="onPaymentSuccess"
|
||||
@selection-change="onSelectionChange"
|
||||
@payment-visible-change="onPaymentVisibleChange"
|
||||
@payment-amount-change="onPaymentAmountChange"
|
||||
@payment-coupons-change="onPaymentCouponsChange"
|
||||
/>
|
||||
<view class="selector-body" v-if="shouldShowSelector">
|
||||
<!-- 直接调用choice接口加载数据 -->
|
||||
<view class="choice-container">
|
||||
<view v-if="choicesLoading" class="loading-state">正在加载位置...</view>
|
||||
<view v-else-if="choicesList.length === 0" class="empty-state">暂无可选位置</view>
|
||||
<view v-else class="choices-grid">
|
||||
<view
|
||||
v-for="(item, index) in choicesList"
|
||||
:key="item.id || index"
|
||||
class="choice-item"
|
||||
:class="{
|
||||
'is-sold': item.status === 'sold' || item.is_sold,
|
||||
'is-selected': isChoiceSelected(item),
|
||||
'is-available': !item.status || item.status === 'available'
|
||||
}"
|
||||
@tap="handleSelectChoice(item)"
|
||||
>
|
||||
<text class="choice-number">{{ item.number || item.position || index + 1 }}</text>
|
||||
<view class="choice-status">
|
||||
<text v-if="item.status === 'sold' || item.is_sold">已售</text>
|
||||
<text v-else-if="isChoiceSelected(item)">已选</text>
|
||||
<text v-else>可选</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@ -73,9 +84,6 @@
|
||||
<!-- 固定底部操作栏 -->
|
||||
<view class="float-bar" v-show="!isPaymentVisible">
|
||||
<view class="float-bar-inner">
|
||||
<view class="selection-info" v-if="selectedCount > 0">
|
||||
已选 <text class="highlight">{{ selectedCount }}</text> 个位置
|
||||
</view>
|
||||
<view class="selection-info" v-if="selectedCount > 0">
|
||||
已选 <text class="highlight">{{ selectedCount }}</text> 个位置
|
||||
</view>
|
||||
@ -151,6 +159,7 @@
|
||||
<script setup>
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { onLoad, onUnload } from '@dcloudio/uni-app'
|
||||
import { getIssueChoices, joinLottery, createWechatOrder, getLotteryResult } from '@/api/appUser'
|
||||
// 公共组件 - uni-app需要直接导入.vue文件
|
||||
import ActivityPageLayout from '@/components/activity/ActivityPageLayout.vue'
|
||||
import ActivityHeader from '@/components/activity/ActivityHeader.vue'
|
||||
@ -161,7 +170,6 @@ import RecordsList from '@/components/activity/RecordsList.vue'
|
||||
import RulesPopup from '@/components/activity/RulesPopup.vue'
|
||||
import CabinetPreviewPopup from '@/components/activity/CabinetPreviewPopup.vue'
|
||||
import FlipGrid from '@/components/FlipGrid.vue'
|
||||
import YifanSelector from '@/components/YifanSelector.vue'
|
||||
import PaymentPopup from '@/components/PaymentPopup.vue'
|
||||
import GamePassPurchasePopup from '@/components/GamePassPurchasePopup.vue'
|
||||
import { getGamePasses } from '@/api/appUser'
|
||||
@ -214,6 +222,127 @@ const paymentVisible = ref(false) // 控制支付弹窗显示
|
||||
const paymentAmount = ref('0') // 支付金额
|
||||
const paymentCoupons = ref([]) // 可用优惠券
|
||||
|
||||
// Choices 相关状态
|
||||
const choicesLoading = ref(false)
|
||||
const choicesList = ref([])
|
||||
const selectedChoices = ref([])
|
||||
|
||||
// 计算属性:判断是否应该显示选号器
|
||||
const shouldShowSelector = computed(() => {
|
||||
const result = !!(
|
||||
activityId.value &&
|
||||
currentIssueId.value &&
|
||||
detail.value?.play_type === 'ichiban'
|
||||
)
|
||||
console.log('[Yifanshang] shouldShowSelector computed:', {
|
||||
activityId: activityId.value,
|
||||
currentIssueId: currentIssueId.value,
|
||||
play_type: detail.value?.play_type,
|
||||
result
|
||||
})
|
||||
return result
|
||||
})
|
||||
|
||||
// 监控 shouldShowSelector 的变化
|
||||
watch(shouldShowSelector, (newVal, oldVal) => {
|
||||
console.log('[Yifanshang] shouldShowSelector changed:', {
|
||||
from: oldVal,
|
||||
to: newVal,
|
||||
yifanSelectorRef: yifanSelectorRef.value
|
||||
})
|
||||
if (newVal && !yifanSelectorRef.value) {
|
||||
console.warn('[Yifanshang] shouldShowSelector is true but yifanSelectorRef is null!')
|
||||
}
|
||||
})
|
||||
|
||||
// 加载choices数据
|
||||
async function loadChoices() {
|
||||
console.log('[Yifanshang] loadChoices called with:', {
|
||||
activityId: activityId.value,
|
||||
issueId: currentIssueId.value
|
||||
})
|
||||
|
||||
if (!activityId.value || !currentIssueId.value) {
|
||||
console.warn('[Yifanshang] Missing activityId or issueId')
|
||||
return
|
||||
}
|
||||
|
||||
choicesLoading.value = true
|
||||
try {
|
||||
console.log('[Yifanshang] Calling getIssueChoices API...')
|
||||
const res = await getIssueChoices(activityId.value, currentIssueId.value)
|
||||
console.log('[Yifanshang] getIssueChoices response:', res)
|
||||
|
||||
// 处理 { total_slots: 1, available: [1], claimed: [] } 这种格式
|
||||
if (res && typeof res.total_slots === 'number' && Array.isArray(res.available)) {
|
||||
const total = res.total_slots
|
||||
const list = []
|
||||
const availableSet = new Set(res.available.map(v => Number(v)))
|
||||
|
||||
for (let i = 1; i <= total; i++) {
|
||||
const isAvailable = availableSet.has(i)
|
||||
list.push({
|
||||
id: i,
|
||||
number: i,
|
||||
position: i,
|
||||
status: isAvailable ? 'available' : 'sold',
|
||||
is_sold: !isAvailable
|
||||
})
|
||||
}
|
||||
choicesList.value = list
|
||||
} else if (Array.isArray(res)) {
|
||||
choicesList.value = res
|
||||
} else if (res && Array.isArray(res.data)) {
|
||||
choicesList.value = res.data
|
||||
} else if (res && Array.isArray(res.choices)) {
|
||||
choicesList.value = res.choices
|
||||
} else {
|
||||
choicesList.value = []
|
||||
}
|
||||
|
||||
console.log('[Yifanshang] Choices loaded, total:', choicesList.value.length)
|
||||
} catch (error) {
|
||||
console.error('[Yifanshang] Failed to load choices:', error)
|
||||
uni.showToast({ title: '加载位置失败', icon: 'none' })
|
||||
choicesList.value = []
|
||||
} finally {
|
||||
choicesLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 判断某个choice是否被选中
|
||||
function isChoiceSelected(item) {
|
||||
return selectedChoices.value.some(i => i.id === item.id || (i.position && i.position === item.position))
|
||||
}
|
||||
|
||||
// 处理选择choice
|
||||
function handleSelectChoice(item) {
|
||||
if (!isOrderAllowed.value) {
|
||||
uni.showToast({ title: orderBlockedReason.value, icon: 'none' })
|
||||
return
|
||||
}
|
||||
if (item.status === 'sold' || item.is_sold) {
|
||||
return
|
||||
}
|
||||
|
||||
const index = selectedChoices.value.findIndex(i => i.id === item.id || (i.position && i.position === item.position))
|
||||
if (index > -1) {
|
||||
selectedChoices.value.splice(index, 1)
|
||||
} else {
|
||||
selectedChoices.value.push(item)
|
||||
}
|
||||
|
||||
console.log('[Yifanshang] Selected choices:', selectedChoices.value.length)
|
||||
selectedCount.value = selectedChoices.value.length
|
||||
}
|
||||
|
||||
// 监听 shouldShowSelector 变化,加载choices
|
||||
watch(shouldShowSelector, (newVal) => {
|
||||
if (newVal && (choicesList.value.length === 0 || !choicesList.value)) {
|
||||
loadChoices()
|
||||
}
|
||||
})
|
||||
|
||||
// 接收选中变化事件
|
||||
function onSelectionChange(items) {
|
||||
selectedCount.value = Array.isArray(items) ? items.length : 0
|
||||
@ -235,39 +364,241 @@ function onPaymentCouponsChange(coupons) {
|
||||
paymentCoupons.value = coupons
|
||||
}
|
||||
|
||||
// 支付确认处理(委托给 YifanSelector)
|
||||
// 支付确认处理
|
||||
async function onPaymentConfirm(paymentData) {
|
||||
if (yifanSelectorRef.value && yifanSelectorRef.value.onPaymentConfirm) {
|
||||
await yifanSelectorRef.value.onPaymentConfirm(paymentData)
|
||||
console.log('[Yifanshang] onPaymentConfirm called with:', paymentData)
|
||||
|
||||
if (selectedChoices.value.length === 0) {
|
||||
uni.showToast({ title: '请先选择位置', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
uni.showLoading({ title: '创建订单中...' })
|
||||
|
||||
// 第一步:调用 join 接口创建订单
|
||||
const joinData = {
|
||||
activity_id: Number(activityId.value),
|
||||
issue_id: Number(currentIssueId.value),
|
||||
choices: selectedChoices.value.map(c => Number(c.id || c.number)),
|
||||
coupon_id: paymentData.coupon_id || 0,
|
||||
item_card_id: paymentData.item_card_id || 0,
|
||||
use_game_pass: paymentData.use_game_pass || false
|
||||
}
|
||||
|
||||
console.log('[Yifanshang] Calling join with:', joinData)
|
||||
|
||||
const joinResult = await joinLottery(joinData)
|
||||
|
||||
console.log('[Yifanshang] Join result:', joinResult)
|
||||
|
||||
if (!joinResult.order_no) {
|
||||
throw new Error('创建订单失败:未返回订单号')
|
||||
}
|
||||
|
||||
// 第二步:使用订单号调用微信支付预下单接口
|
||||
uni.showLoading({ title: '拉起支付...' })
|
||||
|
||||
// 获取 openid
|
||||
const openid = uni.getStorageSync('openid')
|
||||
if (!openid) {
|
||||
throw new Error('缺少OpenID,请重新登录')
|
||||
}
|
||||
|
||||
const preorderData = {
|
||||
openid: openid,
|
||||
order_no: joinResult.order_no
|
||||
}
|
||||
|
||||
console.log('[Yifanshang] Calling wechat preorder with:', preorderData)
|
||||
|
||||
const paymentParams = await createWechatOrder(preorderData)
|
||||
console.log('[Yifanshang] Wechat payment params:', paymentParams)
|
||||
|
||||
uni.hideLoading()
|
||||
|
||||
// 第三步:拉起支付
|
||||
// #ifdef MP-WEIXIN
|
||||
const payResult = await uni.requestPayment({
|
||||
provider: 'wxpay',
|
||||
...paymentParams
|
||||
})
|
||||
console.log('[Yifanshang] Payment result:', payResult)
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-TOUTIAO
|
||||
const payResult = await tt.pay({
|
||||
...paymentParams
|
||||
})
|
||||
console.log('[Yifanshang] Payment result:', payResult)
|
||||
// #endif
|
||||
|
||||
// 第四步:支付成功后,查询抽奖结果
|
||||
uni.showLoading({ title: '查询结果中...' })
|
||||
|
||||
console.log('[Yifanshang] Getting lottery result with order_no:', joinResult.order_no)
|
||||
|
||||
const lotteryResult = await getLotteryResult(joinResult.order_no)
|
||||
|
||||
console.log('[Yifanshang] Lottery result:', lotteryResult)
|
||||
|
||||
uni.hideLoading()
|
||||
|
||||
// 检查状态:如果是 paid_waiting,提示用户等待系统开启
|
||||
const status = lotteryResult?.status || (lotteryResult?.result?.status) || ''
|
||||
if (status === 'paid_waiting') {
|
||||
const nextDrawTime = lotteryResult?.next_draw_time || lotteryResult?.result?.next_draw_time
|
||||
const nextTimeText = nextDrawTime ? formatDateTime(nextDrawTime) : ''
|
||||
const content = nextTimeText
|
||||
? `下单成功,等待系统自动开启本期赏品。\n预计开赏时间:${nextTimeText}`
|
||||
: '下单成功,等待系统自动开启本期赏品。'
|
||||
|
||||
uni.showModal({
|
||||
title: '下单成功',
|
||||
content,
|
||||
showCancel: false,
|
||||
success: () => {
|
||||
// 清空选择并关闭弹窗
|
||||
selectedChoices.value = []
|
||||
selectedCount.value = 0
|
||||
paymentVisible.value = false
|
||||
loadChoices()
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 抽奖成功,清空选择
|
||||
selectedChoices.value = []
|
||||
selectedCount.value = 0
|
||||
|
||||
uni.showToast({
|
||||
title: '购买成功!',
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
// 关闭支付弹窗
|
||||
paymentVisible.value = false
|
||||
|
||||
// 重新加载choices
|
||||
await loadChoices()
|
||||
|
||||
// 显示翻牌结果
|
||||
if (lotteryResult) {
|
||||
showFlip.value = true
|
||||
try { flipRef.value?.reset?.() } catch (_) {}
|
||||
|
||||
setTimeout(() => {
|
||||
// 处理不同的结果格式
|
||||
let items = []
|
||||
|
||||
if (Array.isArray(lotteryResult)) {
|
||||
items = lotteryResult.map(data => ({
|
||||
title: String(data?.title || data?.name || '未知奖励'),
|
||||
image: String(data?.image || data?.img || '')
|
||||
}))
|
||||
} else if (lotteryResult.list && Array.isArray(lotteryResult.list)) {
|
||||
items = lotteryResult.list.map(data => ({
|
||||
title: String(data?.title || data?.name || '未知奖励'),
|
||||
image: String(data?.image || data?.img || '')
|
||||
}))
|
||||
} else if (lotteryResult.rewards && Array.isArray(lotteryResult.rewards)) {
|
||||
items = lotteryResult.rewards.map(data => ({
|
||||
title: String(data?.title || data?.name || '未知奖励'),
|
||||
image: String(data?.image || data?.img || '')
|
||||
}))
|
||||
} else if (lotteryResult.data && Array.isArray(lotteryResult.data)) {
|
||||
items = lotteryResult.data.map(data => ({
|
||||
title: String(data?.title || data?.name || '未知奖励'),
|
||||
image: String(data?.image || data?.img || '')
|
||||
}))
|
||||
} else {
|
||||
// 单个结果
|
||||
items = [{
|
||||
title: String(lotteryResult?.title || lotteryResult?.name || '未知奖励'),
|
||||
image: String(lotteryResult?.image || lotteryResult?.img || '')
|
||||
}]
|
||||
}
|
||||
|
||||
console.log('[Yifanshang] Processed reward items:', items)
|
||||
flipRef.value?.revealResults?.(items)
|
||||
}, 100)
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('[Yifanshang] Payment/Join failed:', error)
|
||||
uni.hideLoading()
|
||||
|
||||
// 处理支付取消
|
||||
if (error.errMsg && error.errMsg.includes('cancel')) {
|
||||
uni.showToast({
|
||||
title: '已取消支付',
|
||||
icon: 'none'
|
||||
})
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: error.message || error.errMsg || '支付失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 支付取消处理
|
||||
function onPaymentCancel() {
|
||||
// PaymentPopup 会通过 v-model 自动更新 paymentVisible
|
||||
// watch 会监听到变化并同步给 YifanSelector
|
||||
}
|
||||
|
||||
// 监听支付弹窗状态变化,同步给 YifanSelector
|
||||
watch(paymentVisible, (newVal) => {
|
||||
// 当支付弹窗关闭时,通知 YifanSelector 更新内部状态
|
||||
if (!newVal && yifanSelectorRef.value && yifanSelectorRef.value.setPaymentVisible) {
|
||||
yifanSelectorRef.value.setPaymentVisible(false)
|
||||
}
|
||||
})
|
||||
|
||||
// 触发随机选号
|
||||
function handleRandomDraw() {
|
||||
if (yifanSelectorRef.value && yifanSelectorRef.value.handleRandomOne) {
|
||||
yifanSelectorRef.value.handleRandomOne()
|
||||
}
|
||||
console.log('[Yifanshang] Payment cancelled')
|
||||
// 支付弹窗会自动关闭
|
||||
}
|
||||
|
||||
// 触发支付
|
||||
function handlePayment() {
|
||||
if (yifanSelectorRef.value && yifanSelectorRef.value.handleBuy) {
|
||||
yifanSelectorRef.value.handleBuy()
|
||||
console.log('[Yifanshang] handlePayment called, selectedChoices:', selectedChoices.value.length)
|
||||
|
||||
if (selectedChoices.value.length === 0) {
|
||||
uni.showToast({ title: '请先选择位置', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
if (!isOrderAllowed.value) {
|
||||
uni.showToast({ title: orderBlockedReason.value, icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
// 计算支付金额
|
||||
const amount = (selectedChoices.value.length * Number(detail.value.price_draw || 0) / 100).toFixed(2)
|
||||
paymentAmount.value = amount
|
||||
|
||||
console.log('[Yifanshang] Payment amount:', amount, 'Opening payment popup...')
|
||||
|
||||
// 显示支付弹窗
|
||||
paymentVisible.value = true
|
||||
}
|
||||
|
||||
// 触发随机选号
|
||||
function handleRandomDraw() {
|
||||
console.log('[Yifanshang] handleRandomDraw called')
|
||||
|
||||
if (!isOrderAllowed.value) {
|
||||
uni.showToast({ title: orderBlockedReason.value, icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
// 随机选择一个可用位置
|
||||
const availableChoices = choicesList.value.filter(c => c.status === 'available' || !c.is_sold)
|
||||
if (availableChoices.length === 0) {
|
||||
uni.showToast({ title: '暂无可用位置', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
const randomIndex = Math.floor(Math.random() * availableChoices.length)
|
||||
const randomChoice = availableChoices[randomIndex]
|
||||
selectedChoices.value = [randomChoice]
|
||||
selectedCount.value = 1
|
||||
|
||||
console.log('[Yifanshang] Random choice selected:', randomChoice)
|
||||
|
||||
// 自动触发支付
|
||||
handlePayment()
|
||||
}
|
||||
|
||||
// ============ 次数卡逻辑 ============
|
||||
@ -418,10 +749,22 @@ onUnload(() => {
|
||||
|
||||
// 监听期切换,刷新记录
|
||||
watch(currentIssueId, (newId) => {
|
||||
console.log('[Yifanshang] currentIssueId changed:', newId, 'activityId:', activityId.value)
|
||||
if (newId && activityId.value) {
|
||||
fetchWinRecords(activityId.value, newId)
|
||||
}
|
||||
})
|
||||
|
||||
// 监听 activityId 和 currentIssueId,用于调试
|
||||
watch([activityId, currentIssueId], ([newActId, newIssueId]) => {
|
||||
console.log('[Yifanshang] Props state:', {
|
||||
activityId: newActId,
|
||||
currentIssueId: newIssueId,
|
||||
play_type: detail.value?.play_type,
|
||||
bothExist: !!(newActId && newIssueId),
|
||||
shouldShowSelector: !!(newActId && newIssueId && detail.value?.play_type === 'ichiban')
|
||||
})
|
||||
}, { immediate: true })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@ -515,6 +858,79 @@ watch(currentIssueId, (newId) => {
|
||||
margin-top: $spacing-sm;
|
||||
}
|
||||
|
||||
/* Choices 网格 */
|
||||
.choice-container {
|
||||
padding: $spacing-md;
|
||||
}
|
||||
|
||||
.loading-state,
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 40rpx;
|
||||
color: $text-tertiary;
|
||||
font-size: $font-md;
|
||||
}
|
||||
|
||||
.choices-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
gap: 16rpx;
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
|
||||
.choice-item {
|
||||
aspect-ratio: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: $bg-card;
|
||||
border-radius: $radius-md;
|
||||
border: 2rpx solid $border-color;
|
||||
transition: all 0.2s;
|
||||
position: relative;
|
||||
|
||||
&.is-available {
|
||||
background: linear-gradient(135deg, #e3f2fd, #bbdefb);
|
||||
border-color: #2196f3;
|
||||
cursor: pointer;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
}
|
||||
|
||||
&.is-sold {
|
||||
background: #f5f5f5;
|
||||
border-color: #ddd;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
&.is-selected {
|
||||
background: linear-gradient(135deg, #fff3e0, #ffe0b2);
|
||||
border-color: #ff9800;
|
||||
box-shadow: 0 0 0 4rpx rgba(255, 152, 0, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.choice-number {
|
||||
font-size: 32rpx;
|
||||
font-weight: 700;
|
||||
color: $text-main;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.choice-status {
|
||||
font-size: 20rpx;
|
||||
color: $text-tertiary;
|
||||
|
||||
text {
|
||||
padding: 4rpx 12rpx;
|
||||
border-radius: 20rpx;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
}
|
||||
|
||||
/* 入场动画 */
|
||||
.animate-enter {
|
||||
animation: slideUp 0.5s ease-out both;
|
||||
|
||||
@ -35,11 +35,14 @@ export function useActivity(activityIdRef) {
|
||||
|
||||
async function fetchDetail() {
|
||||
const id = activityIdRef?.value || activityIdRef
|
||||
console.log('[useActivity] fetchDetail called with activityId:', id)
|
||||
if (!id) return
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await getActivityDetail(id)
|
||||
detail.value = data || {}
|
||||
console.log('[useActivity] getActivityDetail response:', data)
|
||||
console.log('[useActivity] play_type:', data?.play_type)
|
||||
} catch (e) {
|
||||
console.error('fetchDetail error', e)
|
||||
detail.value = {}
|
||||
|
||||
@ -38,13 +38,21 @@ export function useIssues(activityIdRef) {
|
||||
|
||||
async function fetchIssues() {
|
||||
const id = activityIdRef?.value || activityIdRef
|
||||
if (!id) return
|
||||
console.log('[useIssues] fetchIssues called with activityId:', id)
|
||||
if (!id) {
|
||||
console.warn('[useIssues] No activityId, skipping fetchIssues')
|
||||
return
|
||||
}
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await getActivityIssues(id)
|
||||
console.log('[useIssues] getActivityIssues response:', data)
|
||||
issues.value = normalizeIssues(data)
|
||||
console.log('[useIssues] Normalized issues:', issues.value)
|
||||
const latestId = pickLatestIssueId(issues.value)
|
||||
console.log('[useIssues] Latest issue ID:', latestId)
|
||||
setSelectedById(latestId)
|
||||
console.log('[useIssues] currentIssueId after setSelectedById:', currentIssueId.value)
|
||||
} catch (e) {
|
||||
console.error('fetchIssues error', e)
|
||||
issues.value = []
|
||||
|
||||
@ -5,10 +5,10 @@
|
||||
|
||||
<!-- 自定义 tabBar -->
|
||||
<!-- #ifdef MP-TOUTIAO -->
|
||||
<custom-tab-bar-toutiao />
|
||||
<customTabBarToutiao />
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-TOUTIAO -->
|
||||
<custom-tab-bar />
|
||||
<customTabBar />
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- 顶部 Tab -->
|
||||
@ -176,10 +176,10 @@ import { getInventory, getProductDetail, redeemInventory, requestShipping, cance
|
||||
import { vibrateShort } from '@/utils/vibrate.js'
|
||||
import { checkPhoneBound, checkPhoneBoundSync } from '@/utils/checkPhone.js'
|
||||
// #ifdef MP-TOUTIAO
|
||||
import customTabBarToutiao from '@/components/custom-tab-bar-toutiao.vue'
|
||||
import customTabBarToutiao from '@/components/app-tab-bar-toutiao.vue'
|
||||
// #endif
|
||||
// #ifndef MP-TOUTIAO
|
||||
import customTabBar from '@/components/custom-tab-bar.vue'
|
||||
import customTabBar from '@/components/app-tab-bar.vue'
|
||||
// #endif
|
||||
|
||||
const currentTab = ref(0)
|
||||
@ -1058,7 +1058,7 @@ function onCopyShareLink() {
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
box-shadow: 0 -4rpx 20rpx rgba(0,0,0,0.05);
|
||||
z-index: 99;
|
||||
z-index: 1000; /* 提高z-index,确保在tabbar(999)上方 */
|
||||
height: auto; /* reset old height */
|
||||
animation: slideUp 0.3s ease-out;
|
||||
}
|
||||
|
||||
@ -8,10 +8,10 @@
|
||||
|
||||
<!-- 自定义 tabBar -->
|
||||
<!-- #ifdef MP-TOUTIAO -->
|
||||
<custom-tab-bar-toutiao />
|
||||
<customTabBarToutiao />
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-TOUTIAO -->
|
||||
<custom-tab-bar />
|
||||
<customTabBar />
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- 顶部导航栏 (搜索) -->
|
||||
@ -146,10 +146,10 @@ import { authRequest, request } from '../../utils/request.js'
|
||||
import SplashScreen from '@/components/SplashScreen.vue'
|
||||
import { checkPhoneBound, checkPhoneBoundSync } from '../../utils/checkPhone.js'
|
||||
// #ifdef MP-TOUTIAO
|
||||
import customTabBarToutiao from '@/components/custom-tab-bar-toutiao.vue'
|
||||
import customTabBarToutiao from '@/components/app-tab-bar-toutiao.vue'
|
||||
// #endif
|
||||
// #ifndef MP-TOUTIAO
|
||||
import customTabBar from '@/components/custom-tab-bar.vue'
|
||||
import customTabBar from '@/components/app-tab-bar.vue'
|
||||
// #endif
|
||||
|
||||
export default {
|
||||
|
||||
@ -5,10 +5,10 @@
|
||||
|
||||
<!-- 自定义 tabBar -->
|
||||
<!-- #ifdef MP-TOUTIAO -->
|
||||
<custom-tab-bar-toutiao />
|
||||
<customTabBarToutiao />
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-TOUTIAO -->
|
||||
<custom-tab-bar />
|
||||
<customTabBar />
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- 头部区域 -->
|
||||
@ -499,10 +499,10 @@ import {
|
||||
} from '../../api/appUser.js'
|
||||
import { checkPhoneBoundSync } from '../../utils/checkPhone.js'
|
||||
// #ifdef MP-TOUTIAO
|
||||
import customTabBarToutiao from '@/components/custom-tab-bar-toutiao.vue'
|
||||
import customTabBarToutiao from '@/components/app-tab-bar-toutiao.vue'
|
||||
// #endif
|
||||
// #ifndef MP-TOUTIAO
|
||||
import customTabBar from '@/components/custom-tab-bar.vue'
|
||||
import customTabBar from '@/components/app-tab-bar.vue'
|
||||
// #endif
|
||||
|
||||
export default {
|
||||
|
||||
@ -4,10 +4,10 @@
|
||||
|
||||
<!-- 自定义 tabBar -->
|
||||
<!-- #ifdef MP-TOUTIAO -->
|
||||
<custom-tab-bar-toutiao />
|
||||
<customTabBarToutiao />
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-TOUTIAO -->
|
||||
<custom-tab-bar />
|
||||
<customTabBar />
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- 顶部固定区域 -->
|
||||
@ -173,10 +173,10 @@ import { ref, watch, onUnmounted } from 'vue'
|
||||
import { getStoreItems, redeemProductByPoints, redeemCouponByPoints, redeemItemCardByPoints } from '../../api/appUser'
|
||||
import { checkPhoneBound, checkPhoneBoundSync } from '../../utils/checkPhone.js'
|
||||
// #ifdef MP-TOUTIAO
|
||||
import customTabBarToutiao from '@/components/custom-tab-bar-toutiao.vue'
|
||||
import customTabBarToutiao from '@/components/app-tab-bar-toutiao.vue'
|
||||
// #endif
|
||||
// #ifndef MP-TOUTIAO
|
||||
import customTabBar from '@/components/custom-tab-bar.vue'
|
||||
import customTabBar from '@/components/app-tab-bar.vue'
|
||||
// #endif
|
||||
|
||||
// 由于是 setup 语法,组件会自动注册,无需手动声明
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user