Commit a594b3c2 authored by lg's avatar lg

chore: temp

parent eed47846
import requestModule from '@/api/request.js' import requestModule from '@/api/request.js'
const {api} = requestModule const {api} = requestModule
import {homeConfig} from "./home/config"; import {homeConfig} from "./mock-configs";
import {ActivityInfo, CodeResponse} from "@/activities/1015/types"; import {InvitationInfo, CodeResponse} from "@/activities/1015/types";
/** /**
* 获取页面配置 * 获取页面配置
...@@ -10,7 +10,7 @@ import {ActivityInfo, CodeResponse} from "@/activities/1015/types"; ...@@ -10,7 +10,7 @@ import {ActivityInfo, CodeResponse} from "@/activities/1015/types";
export function fetchPageConfig() { export function fetchPageConfig() {
//return api.get('/c/front/content', {type: 'act915',version: '1'}) //return api.get('/c/front/content', {type: 'act915',version: '1'})
return Promise.resolve({ return Promise.resolve({
data: homeConfig, data: homeConfig(),
}) })
} }
...@@ -23,11 +23,11 @@ export function fetchLotteryConfig (){ ...@@ -23,11 +23,11 @@ export function fetchLotteryConfig (){
} }
/** /**
* 获取915活动首页信息 * 获取邀请助力组件信息
* @returns * @returns
*/ */
export function fetchActivityInfo (){ export function fetchInvitationInfo (){
return api.post('/c/activity/use_invite_915/invitation/home') as Promise<CodeResponse<ActivityInfo>> return api.post('/c/activity/use_invite_101/invitation/home') as Promise<CodeResponse<InvitationInfo>>
} }
/** /**
...@@ -35,7 +35,7 @@ export function fetchActivityInfo (){ ...@@ -35,7 +35,7 @@ export function fetchActivityInfo (){
* @returns * @returns
*/ */
export function invitationAssist(inviterUserId, unionId) { export function invitationAssist(inviterUserId, unionId) {
return api.post('/c/activity/use_invite_915/invitation/assist', {invitationCode: inviterUserId, wxUnionId: unionId}) return api.post('/c/activity/use_invite_101/invitation/assist', {invitationCode: inviterUserId, wxUnionId: unionId})
} }
/** /**
...@@ -43,7 +43,7 @@ export function invitationAssist(inviterUserId, unionId) { ...@@ -43,7 +43,7 @@ export function invitationAssist(inviterUserId, unionId) {
* @returns * @returns
*/ */
export function fetchLotteryInfo (){ export function fetchLotteryInfo (){
return api.get('/c/activity/turntable_lottery_915/home') return api.get('/c/activity/turntable_lottery_101/home')
} }
/** /**
...@@ -51,5 +51,5 @@ export function fetchLotteryInfo (){ ...@@ -51,5 +51,5 @@ export function fetchLotteryInfo (){
* @returns * @returns
*/ */
export function lotteryDraw (){ export function lotteryDraw (){
return api.post('/c/activity/turntable_lottery_915/lottery/draw') return api.post('/c/activity/turntable_lottery_101/lottery/draw')
} }
<template> <template>
<view class="got-prize-modal" v-if="visible"> <view class="got-prize-modal" v-if="visible">
<!-- 蒙层 -->
<view class="got-prize-modal-mask" @click="handleCloseClick"></view>
<!-- 弹窗内容 --> <!-- 弹窗内容 -->
<view class="got-prize-modal-content"> <view class="content">
<span class="got-prize-modal-bg" <p class="title">
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.background)})` }"></span> {{showOptions?.awardImageUrl ? '恭喜您获得了' : '很遗憾未中奖'}}</p>
<image class="got-prize-modal-awardimg" :src="`${$baseUrl}${awardImageUrl}`" mode="aspectFit" <image v-if="showOptions?.awardImageUrl" class="prize-image"
v-if="awardImageUrl" @error="console.log('奖品图片加载失败')"></image> :src="showOptions?.awardImageUrl" mode="aspectFit"
<span class="got-prize-modal-awardname">{{ awardName }}</span> @error="console.log('奖品图片加载失败')"/>
<span class="got-prize-modal-happygetbtn" <span class="prize-name">
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.happyGetBtn)})` }" {{ showOptions?.awardImageUrl ? showOptions?.awardName : '别灰心,再试试吧~' }}
@click="handleHappyGetClick"></span> </span>
<span class="got-prize-modal-closebtn" <button class="confirm-btn" @click="onClickConfirm">
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.closeBtn)})` }" {{ showOptions?.awardImageUrl ? '开心收下' : '我知道了' }}
@click="handleCloseClick"></span> </button>
<p v-if="showOptions?.awardImageUrl" class="tips">奖品可在首页 我的奖品 中查看</p>
<span class="close-btn"
:style="{ backgroundImage: `url(${closeBtnUrl})` }"
@click="onClickClose"/>
</view> </view>
</view> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {ref} from 'vue' import {ref} from 'vue'
import {config, getImageUrl} from './GotPrizeModal/config.js' import closeBtnUrl from '@/assets/images/close-btn.png'
import './GotPrizeModal/index.less'
export interface ShowGotPrizeModalOptions { export interface ShowGotPrizeModalOptions {
awardName: string prizeName: string
awardImageUrl: string prizeImageUrl: string
} }
const visible = ref(false) const visible = ref(false)
const options = ref<ShowGotPrizeModalOptions>() const showOptions = ref<ShowGotPrizeModalOptions>()
// Emits // Emits
const emit = defineEmits<{ const emit = defineEmits<{
...@@ -40,7 +41,7 @@ const emit = defineEmits<{ ...@@ -40,7 +41,7 @@ const emit = defineEmits<{
}>() }>()
function show(options: ShowGotPrizeModalOptions) { function show(options: ShowGotPrizeModalOptions) {
options.value = options showOptions.value = options
visible.value = true visible.value = true
} }
...@@ -48,13 +49,23 @@ function hide() { ...@@ -48,13 +49,23 @@ function hide() {
visible.value = false visible.value = false
} }
function onClickConfirm() {
hide()
emit('confirm')
}
function onClickClose() {
hide()
emit('close')
}
defineExpose({ defineExpose({
show, show,
hide, hide,
}) })
</script> </script>
<style scoped> <style scoped lang="less">
.got-prize-modal { .got-prize-modal {
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
...@@ -65,95 +76,81 @@ defineExpose({ ...@@ -65,95 +76,81 @@ defineExpose({
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
background-color: rgba(0, 0, 0, 0.5);
// 蒙层
&-mask {
width: 100%;
height: 100%;
position: absolute;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1;
}
// 弹窗内容 // 弹窗内容
.content {
&-content {
width: 550rpx;
height: 616rpx;
position: relative; position: relative;
z-index: 2; width: 550rpx;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} background-color: white;
gap: 48rpx;
border-radius: 48rpx;
padding: 56rpx 48rpx 64rpx;
.title {
color: #bc7900;
font-weight: bold;
font-size: 44rpx;
}
&-bg { .prize-image {
width: 550rpx; width: 187rpx;
height: 616rpx; height: 187rpx;
position: absolute; border-radius: 18px;
top: 0; object-fit: contain;
left: 0; z-index: 3;
background-size: cover; background-color: #fff9f1;
background-repeat: no-repeat; }
background-position: center;
}
&-awardimg { .prize-name {
width: 180rpx; width: 348rpx;
height: 180rpx; height: 30rpx;
position: absolute; font-size: 34rpx;
top: 150rpx; line-height: 30rpx;
left: 185rpx; color: rgba(0, 0, 0, 1);
object-fit: contain; text-align: center;
z-index: 3; overflow: hidden;
} text-overflow: ellipsis;
white-space: nowrap;
}
&-awardname { .confirm-btn {
width: 348rpx; width: 100%;
height: 30rpx; height: 97rpx;
position: absolute; color: white;
top: 365rpx; background: #d3a357;
left: 101rpx; border-radius: 100rpx;
font-size: 29rpx;
line-height: 30rpx;
color: rgba(0, 0, 0, 1);
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&-happygetbtn { &::after {
width: 465rpx; border: none;
height: 97rpx; }
position: absolute; }
top: 434rpx;
left: 42rpx; .tips{
background-size: cover; text-align: center;
background-repeat: no-repeat; position: absolute;
background-position: center; left: 0;
transition: opacity 0.3s ease; bottom: 24rpx;
width: 100%;
&:hover { font-size: 24rpx;
opacity: 0.8; color: #3b3b3b;
} }
}
&-closebtn { .close-btn {
width: 60rpx; width: 60rpx;
height: 59rpx; height: 59rpx;
position: absolute; position: absolute;
top: 660rpx; left: 50%;
left: 245rpx; bottom: -100rpx;
background-size: cover; transform: translateX(-50%);
background-repeat: no-repeat; background-size: cover;
background-position: center; background-repeat: no-repeat;
transition: opacity 0.3s ease; background-position: center;
transition: opacity 0.3s ease;
&:hover {
opacity: 0.8;
} }
} }
} }
......
<script setup lang="ts"> <script setup lang="ts">
import {ref, computed, watch, inject} from 'vue' import {ref, computed, inject, onMounted} from 'vue'
import ClickArea from "./ClickArea.vue"; import ClickArea from "./ClickArea.vue";
import {ActivityInfo} from "../types" import {InvitationInfo} from "../types"
import {invitationAssist} from "../api"; import {getCdnUrl} from "../utils"
import {fetchInvitationInfo, invitationAssist} from "../api";
import GotPrizeModal from "./GotPrizeModal.vue";
const isAssist = ref(false) const isAssist = ref(false)
const invitationInfo = ref<InvitationInfo>()
const gotPrizeModalRef = ref<InstanceType<typeof GotPrizeModal>>()
const isLogin = inject('isLogin') const updateShareData = inject('updateShareData')
const updateActivityInfo = inject('updateActivityInfo')
const onGetPhoneNumber = inject('onGetPhoneNumber') const onGetPhoneNumber = inject('onGetPhoneNumber')
const props = defineProps<{ const props = defineProps<{
...@@ -15,15 +18,11 @@ const props = defineProps<{ ...@@ -15,15 +18,11 @@ const props = defineProps<{
area?: { x: number, y: number, width: number, height: number } area?: { x: number, y: number, width: number, height: number }
mdConfig?: MdConfig mdConfig?: MdConfig
} }
activityData?: ActivityInfo
debugMode?: boolean debugMode?: boolean
}>() }>()
const inviteBtnProperties = computed(() => { const isLogin = computed(() => {
return { return !invitationInfo.value?.notLogin
area: {x: 220, y: 110, width: 165, height: 55},
mdConfig: props.properties.mdConfig,
}
}) })
const style = computed(() => { const style = computed(() => {
...@@ -36,71 +35,105 @@ const style = computed(() => { ...@@ -36,71 +35,105 @@ const style = computed(() => {
} }
}) })
watch(() => props.activityData, (activityData) => { const inviteBtnProperties = computed(() => {
if (activityData) { return {
area: {x: 220, y: 110, width: 165, height: 55},
mdConfig: props.properties.mdConfig,
}
})
async function updateInvitationInfo() {
const resp = await fetchInvitationInfo()
return invitationInfo.value = resp.data
}
async function tryAssist() {
if (invitationInfo) {
const pages = getCurrentPages(); const pages = getCurrentPages();
const currentPage = pages[pages.length - 1]; const currentPage = pages[pages.length - 1];
const options = currentPage.options; const options = currentPage.options;
const invitationCode = options.invitationCode; const invitationCode = options.invitationCode;
if (invitationCode && !isAssist.value && isLogin.value) { if (invitationCode && !isAssist.value && isLogin.value) {
handleInvitationAssist(invitationCode); console.log('处理助力邀请码:', incomingCode)
}
} try {
}) const unionId = uni.getStorageSync('unionId');
// 处理邀请助力的通用函数 const res = await invitationAssist(incomingCode, unionId);
const handleInvitationAssist = async (incomingCode) => { if (res && res.success) {
try { uni.showToast({
console.log('处理助力邀请码:', incomingCode) title: '助力成功',
const unionId = uni.getStorageSync('unionId'); icon: 'none',
duration: 2000
const res = await invitationAssist(incomingCode, unionId); });
if (res && res.success) { isAssist.value = true;
uni.showToast({ // 助力成功后重新获取数据
title: '助力成功', await updateInvitationInfo();
icon: 'none', return Promise.resolve();
duration: 2000 } else {
}); uni.showToast({
isAssist.value = true; title: res.message,
// 助力成功后重新获取数据 icon: 'none',
await updateActivityInfo(); duration: 2000
return Promise.resolve(); });
} else { return Promise.reject();
uni.showToast({ }
title: res.message, } catch (error) {
icon: 'none', console.error('助力请求失败:', error)
duration: 2000 uni.showToast({
}); title: error.message,
return Promise.reject(); icon: 'none',
duration: 2000
});
return Promise.reject();
}
} }
} catch (error) {
console.error('助力请求失败:', error)
uni.showToast({
title: error.message,
icon: 'none',
duration: 2000
});
return Promise.reject();
} }
} }
function clickInvite() { onMounted(async () => {
await updateInvitationInfo()
} updateShareData({
path: '/activities/1015/home/index?invitationCode=' + invitationInfo.value.invitationCode,
})
const {unclaimedPrizes} = invitationInfo.value
if (unclaimedPrizes.value?.length > 0) {
const totalQuantity = unclaimedPrizes.value.reduce((sum, prize) => sum + (prize.quantity || 1), 0)
const firstPrize = unclaimedPrizes.value[0]
gotPrizeModalRef.value.show({
prizeName: `${firstPrize.prizeName} × ${totalQuantity}`,
prizeImageUrl: firstPrize.prizeImageUrl,
})
}
await tryAssist()
})
</script> </script>
<template> <template>
<view class="invite-task" :class="{'debug-mode': debugMode}" :style="style"> <view class="invite-task" :class="{'debug-mode': debugMode}" :style="style">
<view class="avatars">
<template
v-for="i in 2">
<image
v-if="i-1 < 2 - invitationInfo.nextRewardNeedCount"
class="avatar"
:src="getCdnUrl('home/icon-fill.png')"
/>
</template>
</view>
<ClickArea <ClickArea
:properties="inviteBtnProperties" :properties="inviteBtnProperties"
:open-type="isLogin ? 'share' : 'getPhoneNumber'" :open-type="isLogin ? 'share' : 'getPhoneNumber'"
@click="clickInvite"
@getphonenumber="onGetPhoneNumber" @getphonenumber="onGetPhoneNumber"
debug-mode :debug-mode="debugMode"
/> />
</view> </view>
<GotPrizeModal ref="gotPrizeModalRef"/>
</template> </template>
<style scoped lang="less"> <style scoped lang="less">
...@@ -110,5 +143,18 @@ function clickInvite() { ...@@ -110,5 +143,18 @@ function clickInvite() {
&.debug-mode { &.debug-mode {
background-color: rgba(255, 0, 0, 0.3); background-color: rgba(255, 0, 0, 0.3);
} }
.avatars{
position: absolute;
left: 24rpx;
top: 108rpx;
display: flex;
gap: 25rpx;
.avatar{
width: 63rpx;
height: 63rpx;
}
}
} }
</style> </style>
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<view class="activity-page" v-if="!loading" :style="bgStyle"> <view class="activity-page" v-if="!loading" :style="bgStyle">
<!-- 返回按钮 --> <!-- 返回按钮 -->
<view class="nav-left"> <view class="nav-left">
<image class="back-btn" src="@/assets/images/backBtn.png" mode="aspectFit" <image class="back-btn" src="@/assets/images/back-btn.png" mode="aspectFit"
@click="handleBack"/> @click="handleBack"/>
</view> </view>
...@@ -10,52 +10,40 @@ ...@@ -10,52 +10,40 @@
<ImageSwiper <ImageSwiper
v-if="component.type === 'image-swiper'" v-if="component.type === 'image-swiper'"
v-bind="component" v-bind="component"
:activity-data="activityInfo"
/> />
<ClickArea <ClickArea
v-else-if="component.type === 'click-area'" v-else-if="component.type === 'click-area'"
v-bind="component" v-bind="component"
debug-mode debug-mode
:activity-data="activityInfo"
/> />
<InviteTask <InviteTask
v-else-if="component.type === 'invite-task'" v-else-if="component.type === 'invite-task'"
v-bind="component" v-bind="component"
:debug-mode="false" :debug-mode="true"
:activity-data="activityInfo"
/> />
</template> </template>
<GotPrizeModal :visible="showGotPrizeModal" :award-name="currentAwardName" :award-image-url="currentAwardImageUrl" <GotPrizeModal :visible="showGotPrizeModal" :award-name="currentAwardName" :award-image-url="currentAwardImageUrl"
@close="handleGotPrizeModalClose" @happy-get="handleHappyGet"/> @close="handleGotPrizeModalClose" @happy-get="handleHappyGet"/>
</view> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {ref, onMounted, computed, getCurrentInstance, provide} from 'vue' import {ref, onMounted, computed, getCurrentInstance, provide} from 'vue'
import {fetchPageConfig, fetchActivityInfo, invitationAssist} from '../api.ts' import {fetchPageConfig} from './api.ts'
import {useHomeStore} from '@/stores/home'; // Assuming homeStore path import {useHomeStore} from '@/stores/home'; // Assuming homeStore path
import {useUserStore} from '@/stores/user'; // Import userStore import {useUserStore} from '@/stores/user'; // Import userStore
import {jump, JumpType} from '@/utils/index.js'; // Import jump function import GotPrizeModal from './components/GotPrizeModal.vue'; // Import GotPrizeModal if needed
import GotPrizeModal from '../components/GotPrizeModal.vue'; // Import GotPrizeModal if needed import ClickArea from "./components/ClickArea.vue";
import md from '@/md.js'; import ImageSwiper from "./components/ImageSwiper.vue";
import ClickArea from "../components/ClickArea.vue"; import InviteTask from "./components/InviteTask.vue";
import ImageSwiper from "../components/ImageSwiper.vue";
import './index.less'
import InviteTask from "../components/InviteTask.vue";
import {ActivityInfo} from "../types";
// 响应式数据 // 响应式数据
const pageConfig = ref({}) // 配置对象 const pageConfig = ref({}) // 配置对象
const loading = ref(true) // 加载状态 const loading = ref(true) // 加载状态
// 邀请相关数据 // 邀请相关数据
const showGotPrizeModal = ref(true);
const currentAwardName = ref('');
const currentAwardImageUrl = ref('');
const isLogin = ref(false);
const activityInfo = ref<ActivityInfo>(undefined)
const shareData = ref({ const shareData = ref({
title: '星妈会超级品牌周来啦!', title: '星妈会超级品牌周来啦!',
imageUrl: 'https://course.feihe.com/momclub-picture/Act915Page/v2/act915ShareImg.png', imageUrl: 'https://course.feihe.com/momclub-picture/Act915Page/v2/act915ShareImg.png',
...@@ -67,7 +55,7 @@ const homeStore = useHomeStore(); ...@@ -67,7 +55,7 @@ const homeStore = useHomeStore();
const userStore = useUserStore(); const userStore = useUserStore();
function updateShareData(data) { function updateShareData(data) {
shareData.value = data Object.assign(shareData.value, data)
} }
// 获取背景样式的辅助函数 // 获取背景样式的辅助函数
...@@ -95,18 +83,15 @@ const getShareData = (type) => { ...@@ -95,18 +83,15 @@ const getShareData = (type) => {
const {title, imageUrl, path} = shareData.value const {title, imageUrl, path} = shareData.value
const sharePath = type.from == 'button' ? `${path}?invitationCode=${invitationCode.value}` : path
console.log('分享参数:', { console.log('分享参数:', {
title, title,
path: sharePath, path,
imageUrl, imageUrl,
invitationCode: invitationCode.value,
}) })
return { return {
title, title,
path: sharePath, path,
imageUrl, imageUrl,
} }
} }
...@@ -152,57 +137,6 @@ const updatePageConfig = async () => { ...@@ -152,57 +137,6 @@ const updatePageConfig = async () => {
} }
} }
const updateActivityInfo = async () => {
try {
console.log('开始请求 fetchActivityInfo 接口...')
const response = await fetchActivityInfo()
console.log('fetchActivityInfo 接口返回结果:', response)
if (response && response.ok && response.data) {
const data = response.data
activityInfo.value = data
isLogin.value = !data.notLogin
invitationCode.value = data.invitationCode
}
return response
} catch (error) {
console.error('getAct915Home 接口请求失败:', error)
return null
}
}
// 显示奖品弹窗
const showPrizeModal = () => {
if (unclaimedPrizes.value.length > 0) {
// 计算总奖品数量
const totalQuantity = unclaimedPrizes.value.reduce((sum, prize) => sum + (prize.quantity || 1), 0)
const firstPrize = unclaimedPrizes.value[0]
currentAwardName.value = `${firstPrize.prizeName} × ${totalQuantity}`
currentAwardImageUrl.value = firstPrize.prizeImageUrl
showGotPrizeModal.value = true
}
}
const handleLotteryClick = () => {
md.sensorComponentLogTake({
xcxComponentClick: "true",
pageName: "1015专题活动首页",
componentName: "中部抽奖banner",
componentContent: "中部抽奖banner"
});
// 从配置中获取抽奖banner链接
const lotteryLink = pageConfig.value?.lottery?.link
if (lotteryLink) {
jump(lotteryLink)
} else {
uni.navigateTo({
url: '/activity01015/lottery/lottery'
})
}
}
// 页面初始化逻辑 // 页面初始化逻辑
const initPage = async () => { const initPage = async () => {
console.log('开始初始化页面...') console.log('开始初始化页面...')
...@@ -211,13 +145,6 @@ const initPage = async () => { ...@@ -211,13 +145,6 @@ const initPage = async () => {
await updatePageConfig() await updatePageConfig()
console.log('配置数据:', pageConfig.value) console.log('配置数据:', pageConfig.value)
// 请求 getAct915Home 接口(包含助力逻辑处理)
await updateActivityInfo();
if (unclaimedPrizes.value?.length > 0) {
showPrizeModal()
}
} }
// 生命周期 // 生命周期
...@@ -261,7 +188,7 @@ const onGetPhoneNumber = async (e) => { ...@@ -261,7 +188,7 @@ const onGetPhoneNumber = async (e) => {
// 隐藏授权弹窗 // 隐藏授权弹窗
userStore.phoneCallback(e.detail, null, null, async () => { userStore.phoneCallback(e.detail, null, null, async () => {
// 重新获取用户信息(登录后) // 重新获取用户信息(登录后)
await updateActivityInfo(); // todo 更新组件状态
console.warn('授权后重新获取用户信息') console.warn('授权后重新获取用户信息')
}, { }, {
...@@ -278,31 +205,13 @@ const onGetPhoneNumber = async (e) => { ...@@ -278,31 +205,13 @@ const onGetPhoneNumber = async (e) => {
} }
}; };
// 抽奖成功弹窗关闭处理
const handleGotPrizeModalClose = () => {
console.log('关闭抽奖成功弹窗');
showGotPrizeModal.value = false;
};
// 开心领取处理
const handleHappyGet = () => {
console.log('点击开心领取');
showGotPrizeModal.value = false;
// uni.showToast({
// title: '奖品领取成功',
// icon: 'success'
// });
};
// 暴露给 Options API 使用 // 暴露给 Options API 使用
defineExpose({ defineExpose({
getShareData getShareData
}) })
provide('pageName', '1015专题活动首页') provide('pageName', '1015专题活动首页')
provide('isLogin', isLogin)
provide('updateShareData', updateShareData) provide('updateShareData', updateShareData)
provide('updateActivityInfo', updateActivityInfo)
provide('onGetPhoneNumber', onGetPhoneNumber) provide('onGetPhoneNumber', onGetPhoneNumber)
</script> </script>
...@@ -319,3 +228,29 @@ export default { ...@@ -319,3 +228,29 @@ export default {
}, },
} }
</script> </script>
<style scoped lang="less">
.activity-page {
width: 750rpx;
height: calc(4937rpx + 845rpx);
position: relative;
max-width: 100vw; // 确保不超过视口宽度
overflow-x: hidden; // 防止水平滚动
background-size: contain;
background-repeat: no-repeat;
background-position: left 845rpx;
// 返回按钮样式
.nav-left {
position: fixed;
top: 100rpx;
left: 30rpx;
z-index: 999;
.back-btn {
width: 60rpx;
height: 60rpx;
}
}
}
</style>
import bgUrl from '../images/bg.png'
import banner0Url from '../images/banner-0.png'
import banner1Url from '../images/banner-1.png'
const pageName = '1015专题活动页面'
// 页面配置
export const homeConfig = {
"background": {
image: bgUrl,
style: {
backgroundPosition: {y: "calc(4937rpx + 845rpx)"}
}
},
shareConfig: {
title: '星妈会超级品牌周来啦!',
path: '/activities/1015/home/index',
imageUrl: 'https://course.feihe.com/momclub-picture/Act915Page/v2/act915ShareImg.png',
},
components: [
{
type: "image-swiper",
properties: {
autoplay: true,
interval: 3000,
duration: 500,
circular: true,
indicatorDots: true,
items: [{
image: banner0Url,
mdConfig: {
pageName,
componentName: "banner头图",
componentContent: "北纬47 °",
logExposure: true,
},
}, {
image: banner1Url,
mdConfig: {
pageName,
componentName: "banner头图",
componentContent: "国际大米节金奖",
logExposure: true,
},
link: {
type: 2,
url: "subPackages/shopMainProcess/product/index?productId=643246351932056828&skuId=643246351932056829&entrySource=xmh_wechatmp_activity_1015ppz",
extra: {envVersion: "release", appId: "wx4205ec55b793245e"},
}
}]
},
style: {
height: "845rpx",
}
},
{
type: "click-area",
properties: {
area: {x: 35, y: 915, width: 685, height: 245},
mdConfig: {
pageName,
componentName: "商品banner",
componentContent: "商品banner",
logExposure: true,
logClick: true,
},
link: {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=720448018529899563&skuId=720448018529899564&entrySource=xmh_wechatmp_activity_1015ppz"
},
},
},
{
type: "click-area",
properties: {
area: {x: 50, y: 2095, width: 320, height: 390},
mdConfig: {
pageName,
componentName: "品牌宣传1",
componentContent: "商品名称1",
logExposure: true,
logClick: true,
},
link: {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=643246351932056828&skuId=643246351932056829&entrySource=xmh_wechatmp_activity_1015ppz"
},
}
},
{
type: "click-area",
properties: {
area: {x: 380, y: 2095, width: 320, height: 390},
mdConfig: {
pageName,
componentName: "品牌宣传1",
componentContent: "商品名称2",
logExposure: true,
logClick: true,
},
link: {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=643245114369684591&skuId=643245114369684592&entrySource=xmh_wechatmp_activity_1015ppz"
},
}
},
{
type: "click-area",
properties: {
area: {x: 50, y: 3405, width: 320, height: 390},
mdConfig: {
pageName,
componentName: "品牌宣传2",
componentContent: "商品名称1",
logExposure: true,
logClick: true,
},
link: {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=368848644886521333&skuId=368848644886521334&entrySource=xmh_wechatmp_activity_1015ppz"
},
}
},
{
type: "click-area",
properties: {
area: {x: 380, y: 3405, width: 320, height: 390},
mdConfig: {
pageName,
componentName: "品牌宣传2",
componentContent: "商品名称2",
logExposure: true,
logClick: true,
},
link: {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=367056951412568222&skuId=367056951412568223&entrySource=xmh_wechatmp_activity_1015ppz"
},
}
},
{
type: "invite-task",
properties: {
area: {x: 35, y: 3865, width: 685, height: 195},
mdConfig: {
pageName,
componentName: "邀请得好礼",
componentContent: "立即邀请",
logExposure: true,
logClick: true,
},
},
},
{
type: "click-area",
properties: {
area: {x: 35, y: 4080, width: 685, height: 245},
mdConfig: {
pageName,
componentName: "中部抽奖banner",
componentContent: "中部抽奖banner",
logExposure: true,
logClick: true,
},
link: {
"type": 1,
"url": "/activities/1015/lottery/index"
},
},
},
{
"type": "click-area",
"properties": {
"area": {"x": 50, "y": 4405, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品1",
componentContent: "商品1",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=643243579803297229&skuId=643243579803297230&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
{
"type": "click-area",
"properties": {
"area": {"x": 270, "y": 4405, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品1",
componentContent: "商品2",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=367070126091559975&skuId=367070126091559976&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
{
"type": "click-area",
"properties": {
"area": {"x": 490, "y": 4405, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品1",
componentContent: "商品3",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=367072891644670759&skuId=367072891644670760&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
{
"type": "click-area",
"properties": {
"area": {"x": 50, "y": 4705, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品1",
componentContent: "商品4",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=649435440113431085&skuId=649435440113431086&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
{
"type": "click-area",
"properties": {
"area": {"x": 270, "y": 4705, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品1",
componentContent: "商品5",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=662389781175669644&skuId=662389781175669645&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
{
"type": "click-area",
"properties": {
"area": {"x": 490, "y": 4705, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品1",
componentContent: "商品6",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=759248536249386165&skuId=759248536249386166&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
{
"type": "click-area",
"properties": {
"area": {"x": 50, "y": 5110, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品2",
componentContent: "商品1",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=399302177175705120&skuId=399302177175705121&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
{
"type": "click-area",
"properties": {
"area": {"x": 270, "y": 5110, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品2",
componentContent: "商品2",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=650599779914081413&skuId=650599779914081414&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
{
"type": "click-area",
"properties": {
"area": {"x": 490, "y": 5110, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品2",
componentContent: "商品3",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=667527760599458548&skuId=667527760599458549&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
{
"type": "click-area",
"properties": {
"area": {"x": 50, "y": 5410, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品2",
componentContent: "商品4",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=548984197069284758&skuId=548984197069284759&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
{
"type": "click-area",
"properties": {
"area": {"x": 270, "y": 5410, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品2",
componentContent: "商品5",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=792232869316748776&skuId=792232869316748777&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
{
"type": "click-area",
"properties": {
"area": {"x": 490, "y": 5410, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品2",
componentContent: "商品6",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=704050114989893289&skuId=704050114989893290&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
],
"lottery": {
"image": "act1015Page/v3/act1015PageLotteryBanner.png",
"link": {"type": 1, "url": "/activity0915/lottery/lottery"}
},
"invite": {
"image": "act1015Page/v3/act1015PageInviteConBg.png",
"link": {"type": 1, "url": "/pages/invite/invite"},
"inviteConStatusNo1Img": "act1015Page/v3/act1015PageInviteConStatusNo.png",
"inviteConStatusYes2Img": "act1015Page/v3/act1015PageInviteConStatusYes.png",
"inviteConStatusYes1Img": "act1015Page/v3/act1015PageInviteConStatusYes.png",
"inviteConStatusNo2Img": "act1015Page/v3/act1015PageInviteConStatusNo.png"
}
}
//console.log('page-config:', JSON.stringify(act1015Config, null, 2))
// 获取图片URL的工具函数
export const getImageUrl = (imagePath) => {
return imagePath
}
.activity-page {
width: 750rpx;
height: calc(4937rpx + 845rpx);
position: relative;
max-width: 100vw; // 确保不超过视口宽度
overflow-x: hidden; // 防止水平滚动
background-size: contain;
background-repeat: no-repeat;
background-position: left 845rpx;
// 返回按钮样式
.nav-left {
position: fixed;
top: 100rpx;
left: 30rpx;
z-index: 999;
.back-btn {
width: 60rpx;
height: 60rpx;
}
}
}
# 抽奖页面弹窗组件
## 组件结构
```
activity0915/lottery/
├── lottery.vue # 主抽奖页面
├── config.js # 主页面配置
├── lotterypage.less # 主页面样式
└── components/ # 弹窗组件目录
├── ruleModal/ # 规则弹窗
│ ├── ruleModal.vue
│ ├── config.js
│ └── rulemodal.less
├── drawSucModal/ # 抽奖成功弹窗
│ ├── drawSucModal.vue
│ ├── config.js
│ └── drawsucmodal.less
└── drawFailModal/ # 抽奖失败弹窗
├── drawFailModal.vue
├── config.js
└── drawfailmodal.less
```
## 组件说明
### 1. RuleModal (规则弹窗)
- **功能**: 显示活动规则说明
- **Props**:
- `visible`: Boolean - 控制弹窗显示/隐藏
- **Events**:
- `close`: 关闭弹窗事件
### 2. DrawSucModal (抽奖成功弹窗)
- **功能**: 显示抽奖成功和奖品信息
- **Props**:
- `visible`: Boolean - 控制弹窗显示/隐藏
- `awardName`: String - 中奖奖品名称
- **Events**:
- `close`: 关闭弹窗事件
- `happy-get`: 点击"开心领取"按钮事件
### 3. DrawFailModal (抽奖失败弹窗)
- **功能**: 显示抽奖失败提示
- **Props**:
- `visible`: Boolean - 控制弹窗显示/隐藏
- **Events**:
- `close`: 关闭弹窗事件
- `i-know`: 点击"我知道了"按钮事件
## 使用方法
### 在主页面中引入组件
```vue
<template>
<view class="lotterypage">
<!-- 主页面内容 -->
<!-- 规则弹窗 -->
<RuleModal
:visible="showRuleModal"
@close="handleRuleModalClose"
/>
<!-- 抽奖成功弹窗 -->
<DrawSucModal
:visible="showDrawSucModal"
:award-name="currentAwardName"
@close="handleDrawSucModalClose"
@happy-get="handleHappyGet"
/>
<!-- 抽奖失败弹窗 -->
<DrawFailModal
:visible="showDrawFailModal"
@close="handleDrawFailModalClose"
@i-know="handleIKnow"
/>
</view>
</template>
<script setup>
import RuleModal from './components/ruleModal/ruleModal.vue'
import DrawSucModal from '../components/drawSucModal/drawSucModal.vue'
import DrawFailModal from './components/drawFailModal/drawFailModal.vue'
// 弹窗状态
const showRuleModal = ref(false)
const showDrawSucModal = ref(false)
const showDrawFailModal = ref(false)
const currentAwardName = ref('')
// 事件处理
const handleRuleModalClose = () => {
showRuleModal.value = false
}
const handleDrawSucModalClose = () => {
showDrawSucModal.value = false
}
const handleHappyGet = () => {
showDrawSucModal.value = false
// 处理奖品领取逻辑
}
const handleDrawFailModalClose = () => {
showDrawFailModal.value = false
}
const handleIKnow = () => {
showDrawFailModal.value = false
// 处理失败确认逻辑
}
</script>
```
## 抽奖逻辑
抽奖页面会根据奖品配置中的概率进行随机抽奖:
```javascript
// 根据奖品概率判断是否中奖
const isWin = Math.random() < award.probability
if (isWin) {
// 中奖 - 显示成功弹窗
currentAwardName.value = award.name
showDrawSucModal.value = true
} else {
// 未中奖 - 显示失败弹窗
showDrawFailModal.value = true
}
```
## 样式说明
所有弹窗组件都使用绝对定位,覆盖在主页面之上。弹窗背景使用半透明遮罩,确保用户注意力集中在弹窗内容上。
每个弹窗组件都有独立的样式文件,可以根据设计需求进行调整。
const version = 'v1'
// 抽奖失败弹窗配置
export const drawFailModalConfig = {
// 图片配置
images: {
background: `act1015Component/DrawFailModal/${version}/DrawFailModalBg.png`,
iKnowBtn: `act1015Component/DrawFailModal/${version}/DrawFailModalBgIKnowBtn.png`,
closeBtn: `act1015Component/DrawFailModal/${version}/DrawFailModalBgCloseBtn.png`
},
// 文本配置
texts: {
iKnowButton: '我知道了',
closeButton: '关闭'
},
// 弹窗配置
modal: {
width: 550,
height: 396,
animationDuration: 300
}
}
// 获取图片URL的工具函数
export const getImageUrl = (imagePath) => {
return imagePath
}
<template>
<view class="drawfailmodal" v-if="visible">
<!-- 蒙层 -->
<view class="drawfailmodal-mask" @click="handleCloseClick"></view>
<!-- 弹窗内容 -->
<view class="drawfailmodal-content">
<span class="drawfailmodalbg"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.background)})` }"></span>
<span class="drawfailmodalbgiknowbtn"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.iKnowBtn)})` }"
@click="handleIKnowClick"></span>
<span class="drawfailmodalbgclosebtn"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.closeBtn)})` }"
@click="handleCloseClick"></span>
</view>
</view>
</template>
<script setup>
import { drawFailModalConfig, getImageUrl } from './config.js'
// 组件名称
defineOptions({
name: 'DrawFailModal'
})
// Props
defineProps({
visible: {
type: Boolean,
default: false
}
})
// Emits
const emit = defineEmits(['close', 'i-know'])
// 配置对象
const config = drawFailModalConfig
// 我知道了按钮点击处理
const handleIKnowClick = () => {
console.log('点击我知道了按钮')
emit('i-know')
}
// 关闭按钮点击处理
const handleCloseClick = () => {
console.log('关闭抽奖失败弹窗')
emit('close')
}
</script>
<style lang="less" scoped>
@import './drawfailmodal.less';
</style>
@import "@/common.less";
.drawfailmodal {
width: 100vw;
height: 100vh;
left: 0rpx;
top: 0rpx;
position: fixed;
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
// 蒙层
.drawfailmodal-mask {
width: 100%;
height: 100%;
position: absolute;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1;
}
// 弹窗内容
.drawfailmodal-content {
width: 550rpx;
height: 396rpx;
position: relative;
z-index: 2;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.drawfailmodalbg {
width: 550rpx;
height: 396rpx;
position: absolute;
top: 0;
left: 0;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
.drawfailmodalbgiknowbtn {
width: 465rpx;
height: 97rpx;
position: absolute;
top: 243rpx;
left: 42rpx;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
transition: opacity 0.3s ease;
&:hover {
opacity: 0.8;
}
}
.drawfailmodalbgclosebtn {
width: 59rpx;
height: 59rpx;
position: absolute;
top: 437rpx;
left: 245rpx;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
transition: opacity 0.3s ease;
&:hover {
opacity: 0.8;
}
}
}
const version = 'v1' const version = 'v1'
const baseUrl = 'http://127.0.0.1:8080/activity/1015'
export const getCdnUrl = (path) => `${baseUrl}/${version}/${path}`
import closeBtnUrl from '@/assets/images/close-btn.png'
// 活动规则弹窗配置 // 活动规则弹窗配置
export const act1015RuleModalConfig = { export const act1015RuleModalConfig = {
// 图片配置 // 图片配置
images: { images: {
background: `act1015Component/act1015RuleModal/${version}/act1015RuleModalBg.png`, background: `act1015Component/act1015RuleModal/${version}/act1015RuleModalBg.png`,
textImg: `act1015Component/act1015RuleModal/${version}/act1015RuleModalTextImg.png`, textImg: `act1015Component/act1015RuleModal/${version}/act1015RuleModalTextImg.png`,
closeBtn: `act1015Component/act1015RuleModal/${version}/act1015RuleModalCloseBtn.png` closeBtn: closeBtnUrl
}, },
// 文本配置 // 文本配置
......
...@@ -5,9 +5,8 @@ ...@@ -5,9 +5,8 @@
<!-- 弹窗内容 --> <!-- 弹窗内容 -->
<view class="rulemodal-content"> <view class="rulemodal-content">
<span class="rulemodalbg" <p class="rulemodal-title">活动规则</p>
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.background)})` }"></span>
<!-- 规则内容区域 - 支持滚动 --> <!-- 规则内容区域 - 支持滚动 -->
<view class="rulemodal-text-container"> <view class="rulemodal-text-container">
<image class="rulemodaltextimg" <image class="rulemodaltextimg"
...@@ -16,9 +15,9 @@ ...@@ -16,9 +15,9 @@
@load="console.log('规则图片加载成功')" @load="console.log('规则图片加载成功')"
@error="console.log('规则图片加载失败')"></image> @error="console.log('规则图片加载失败')"></image>
</view> </view>
<span class="rulemodalclosebtn" <span class="rulemodalclosebtn"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.closeBtn)})` }" :style="{ backgroundImage: `url(${getImageUrl(config.images.closeBtn)})` }"
@click="handleCloseClick"></span> @click="handleCloseClick"></span>
</view> </view>
</view> </view>
......
...@@ -31,24 +31,21 @@ ...@@ -31,24 +31,21 @@
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
background-color: white;
border-radius: 48rpx;
} }
.rulemodalbg { .rulemodal-title{
width: 550rpx; color: #bc7900;
height: 667rpx; font-weight: bold;
position: absolute; font-size: 44rpx;
top: 0;
left: 0;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
} }
// 规则内容滚动容器 // 规则内容滚动容器
.rulemodal-text-container { .rulemodal-text-container {
width: 100%; width: 100%;
height: 471rpx; height: 471rpx;
position: absolute; //position: absolute;
// top: 154rpx; // top: 154rpx;
// left: 35rpx; // left: 35rpx;
overflow-y: auto; overflow-y: auto;
......
const version = 'v1' const version = 'v1'
const baseUrl = 'http://127.0.0.1:8080/activity/1015'
function getCdnUrl(path){
return `${baseUrl}/${version}/${path}`
}
// 抽奖页面配置 // 抽奖页面配置
export const lotteryConfig = { export const lotteryConfig = {
// 页面状态 // 页面状态
...@@ -10,22 +16,15 @@ export const lotteryConfig = { ...@@ -10,22 +16,15 @@ export const lotteryConfig = {
// 图片配置 // 图片配置
images: { images: {
background: `LotteryPage/${version}/LotteryPageBg.png`, background: getCdnUrl('turntable/bg.jpg'),
turnTableBg: `LotteryPage/${version}/LotteryPageTurnTableBg.png`, turnTableBg: getCdnUrl('turntable/panebg.png'),
turnTableLogo: `LotteryPage/${version}/LotteryPageTurnTableLogo.png`, turnTableLogo: getCdnUrl('turntable/center.png'),
awards6Bg: `LotteryPage/${version}/LotteryPageTurnTableAwards6Bg.png`, title: getCdnUrl('turntable/title.png'),
awards5Bg: `LotteryPage/${version}/LotteryPageTurnTableAwards5Bg.png`, ruleBtn: getCdnUrl('turntable/rule-btn.png'),
awards4Bg: `LotteryPage/${version}/LotteryPageTurnTableAwards4Bg.png`, awardBtn: getCdnUrl('turntable/award-btn.png'),
awards3Bg: `LotteryPage/${version}/LotteryPageTurnTableAwards3Bg.png`, noticeConBg: getCdnUrl('turntable/notice-bg.png'),
awards2Img: `LotteryPage/${version}/LotteryPageTurnTableAwards2Img.png`, drawBtn: getCdnUrl('turntable/draw-btn.png'),
awards1Img: `LotteryPage/${version}/LotteryPageTurnTableAwards1Img.png`, lotterypageturntableawardsSelBg: getCdnUrl('turntable/sel-bg.png'),
title: `LotteryPage/${version}/LotteryPageTitle.png`,
ruleBtn: `LotteryPage/${version}/LotteryPageRuleBtn.png`,
awardBtn: `LotteryPage/${version}/LotteryPageAwardBtn.png`,
noticeConBg: `LotteryPage/${version}/LotteryPageNoticeConBg.png`,
noticeConSoundIcon: `LotteryPage/${version}/LotteryPageNoticeConSoundIcon.png`,
drawBtn: `LotteryPage/${version}/LotteryPageDrawBtn.png`,
lotterypageturntableawardsSelBg: `LotteryPage/${version}/lotterypageturntableawardsSelBg.png`,
}, },
// 奖品配置 // 奖品配置
...@@ -89,11 +88,6 @@ export const lotteryConfig = { ...@@ -89,11 +88,6 @@ export const lotteryConfig = {
} }
} }
// 获取图片URL的工具函数
export const getImageUrl = (imagePath) => {
return imagePath
}
// 获取随机公告 // 获取随机公告
export const getRandomNotice = () => { export const getRandomNotice = () => {
const notices = [ const notices = [
......
...@@ -361,9 +361,9 @@ ...@@ -361,9 +361,9 @@
} }
.lotterypagetitle { .lotterypagetitle {
width: 531rpx; width: 503rpx;
height: 99rpx; height: 68rpx;
left: 111rpx; left: 121rpx;
top: 257rpx; top: 257rpx;
position: absolute; position: absolute;
background-size: cover; background-size: cover;
...@@ -424,7 +424,7 @@ ...@@ -424,7 +424,7 @@
} }
.lotterypagenoticecontext-wrapper { .lotterypagenoticecontext-wrapper {
width: 482rpx; width: 490rpx;
height: 40rpx; height: 40rpx;
left: 135rpx; left: 135rpx;
top: 5rpx; top: 5rpx;
...@@ -441,44 +441,34 @@ ...@@ -441,44 +441,34 @@
} }
.lotterypagenoticecontext { .lotterypagenoticecontext {
width: 502rpx; position: absolute;
height: 40rpx; height: 40rpx;
position: absolute;
top: 0;
left: 0;
font-size: 24rpx; font-size: 24rpx;
line-height: 40rpx;
color: rgba(255, 255, 255, 1);
display: block;
margin: 0; margin: 0;
padding: 0; padding: 0;
white-space: nowrap; display: flex;
text-align: left; align-items: center;
overflow: hidden;
text-overflow: ellipsis;
} }
.lotterypagenoticeconsoundicon { .lotterypagenoticetext{
width: 23rpx; width: 390rpx;
height: 22rpx; white-space: nowrap;
left: 98rpx; text-align: left;
top: 14rpx; overflow: hidden;
position: absolute; text-overflow: ellipsis;
background-size: cover; display: inline-block;
background-repeat: no-repeat; }
background-position: center;
.lotterypagenoticetime{
transition: opacity 0.3s ease; color: #797979;
margin-left: 10rpx;
&:hover { flex-shrink: 0;
opacity: 0.8; }
}
}
} }
.lotterypagedrawbtn { .lotterypagedrawbtn {
width: 481rpx; width: 466rpx;
height: 113rpx; height: 97rpx;
left: 135rpx; left: 135rpx;
top: 1256rpx; top: 1256rpx;
position: absolute; position: absolute;
...@@ -516,6 +506,6 @@ ...@@ -516,6 +506,6 @@
position: absolute; position: absolute;
font-size: 24rpx; font-size: 24rpx;
line-height: 23rpx; line-height: 23rpx;
color: rgba(255, 255, 255, 1); //color: rgba(255, 255, 255, 1);
} }
} }
<template> <template>
<view class="lotterypage"> <view class="lotterypage">
<!-- 返回按钮 --> <!-- 返回按钮 -->
<view class="nav-left"> <view class="nav-left">
<image class="back-btn" :src="$baseUrl + 'xingmaLab/1001/backBtn.png'" mode="aspectFit" <image class="back-btn" src="@/assets/images/back-btn.png" mode="aspectFit"
@click="handleBack" /> @click="handleBack"/>
</view> </view>
<view class="lotterypageCon"> <view class="lotterypageCon">
<span class="lotterypagebg" <span class="lotterypagebg"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.background)})` }"></span> :style="{ backgroundImage: `url(${config.images.background})` }"></span>
<div class="lotterypageturntable"> <div class="lotterypageturntable">
<span class="lotterypageturntablebg" <span class="lotterypageturntablebg"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.turnTableBg)})` }"></span> :style="{ backgroundImage: `url(${config.images.turnTableBg})` }"></span>
<span class="lotterypageturntablelogo" <span class="lotterypageturntablelogo"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.turnTableLogo)})` }"></span> :style="{ backgroundImage: `url(${config.images.turnTableLogo})` }"></span>
<div class="lotterypageturntableawards" :style="turntableRotationStyle"> <div class="lotterypageturntableawards" :style="turntableRotationStyle">
<div class="lotterypageturntableawards6" v-if="turntablePrizes.length > 5"> <div class="lotterypageturntableawards6" v-if="turntablePrizes.length > 5">
<span class="lotterypageturntableawards6selbg" <span class="lotterypageturntableawards6selbg"
v-if="isPrizeSelected(5) || isPrizeHighlighted(5)" v-if="isPrizeSelected(5) || isPrizeHighlighted(5)"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.lotterypageturntableawardsSelBg)})` }"></span> :style="{ backgroundImage: `url(${config.images.lotterypageturntableawardsSelBg})` }"></span>
<image class="lotterypageturntableawards6img" <image class="lotterypageturntableawards6img"
:src="`${$baseUrl}${turntablePrizes[5].prizeImageUrl}`" mode="aspectFit" :src="`${$baseUrl}${turntablePrizes[5].prizeImageUrl}`" mode="aspectFit"
@error="console.log('奖品6图片加载失败')"></image> @error="console.log('奖品6图片加载失败')"></image>
<span class="lotterypageturntableawards6name">{{ turntablePrizes[5].prizeName }}</span> <span class="lotterypageturntableawards6name">{{ turntablePrizes[5].prizeName }}</span>
</div> </div>
<div class="lotterypageturntableawards5" v-if="turntablePrizes.length > 4"> <div class="lotterypageturntableawards5" v-if="turntablePrizes.length > 4">
<span class="lotterypageturntableawards5selbg" <span class="lotterypageturntableawards5selbg"
v-if="isPrizeSelected(4) || isPrizeHighlighted(4)" v-if="isPrizeSelected(4) || isPrizeHighlighted(4)"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.lotterypageturntableawardsSelBg)})` }"></span> :style="{ backgroundImage: `url(${config.images.lotterypageturntableawardsSelBg})` }"></span>
<image class="lotterypageturntableawards5img" <image class="lotterypageturntableawards5img"
:src="`${$baseUrl}${turntablePrizes[4].prizeImageUrl}`" mode="aspectFit" :src="`${$baseUrl}${turntablePrizes[4].prizeImageUrl}`" mode="aspectFit"
@error="console.log('奖品5图片加载失败')"></image> @error="console.log('奖品5图片加载失败')"></image>
<span class="lotterypageturntableawards5name">{{ turntablePrizes[4].prizeName }}</span> <span class="lotterypageturntableawards5name">{{ turntablePrizes[4].prizeName }}</span>
</div> </div>
<div class="lotterypageturntableawards4" v-if="turntablePrizes.length > 3"> <div class="lotterypageturntableawards4" v-if="turntablePrizes.length > 3">
<span class="lotterypageturntableawards4selbg" <span class="lotterypageturntableawards4selbg"
v-if="isPrizeSelected(3) || isPrizeHighlighted(3)" v-if="isPrizeSelected(3) || isPrizeHighlighted(3)"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.lotterypageturntableawardsSelBg)})` }"></span> :style="{ backgroundImage: `url(${config.images.lotterypageturntableawardsSelBg})` }"></span>
<image class="lotterypageturntableawards4img" <image class="lotterypageturntableawards4img"
:src="`${$baseUrl}${turntablePrizes[3].prizeImageUrl}`" mode="aspectFit" :src="`${$baseUrl}${turntablePrizes[3].prizeImageUrl}`" mode="aspectFit"
@error="console.log('奖品4图片加载失败')"></image> @error="console.log('奖品4图片加载失败')"></image>
<span class="lotterypageturntableawards4name">{{ turntablePrizes[3].prizeName }}</span> <span class="lotterypageturntableawards4name">{{ turntablePrizes[3].prizeName }}</span>
</div> </div>
<div class="lotterypageturntableawards3" v-if="turntablePrizes.length > 2"> <div class="lotterypageturntableawards3" v-if="turntablePrizes.length > 2">
<span class="lotterypageturntableawards3selbg" <span class="lotterypageturntableawards3selbg"
v-if="isPrizeSelected(2) || isPrizeHighlighted(2)" v-if="isPrizeSelected(2) || isPrizeHighlighted(2)"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.lotterypageturntableawardsSelBg)})` }"></span> :style="{ backgroundImage: `url(${config.images.lotterypageturntableawardsSelBg})` }"></span>
<image class="lotterypageturntableawards3img" <image class="lotterypageturntableawards3img"
:src="`${$baseUrl}${turntablePrizes[2].prizeImageUrl}`" mode="aspectFit" :src="`${$baseUrl}${turntablePrizes[2].prizeImageUrl}`" mode="aspectFit"
@error="console.log('奖品3图片加载失败')"></image> @error="console.log('奖品3图片加载失败')"></image>
<span class="lotterypageturntableawards3name">{{ turntablePrizes[2].prizeName }}</span> <span class="lotterypageturntableawards3name">{{ turntablePrizes[2].prizeName }}</span>
</div> </div>
<div class="lotterypageturntableawards2" v-if="turntablePrizes.length > 1"> <div class="lotterypageturntableawards2" v-if="turntablePrizes.length > 1">
<span class="lotterypageturntableawards2selbg" <span class="lotterypageturntableawards2selbg"
v-if="isPrizeSelected(1) || isPrizeHighlighted(1)" v-if="isPrizeSelected(1) || isPrizeHighlighted(1)"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.lotterypageturntableawardsSelBg)})` }"></span> :style="{ backgroundImage: `url(${config.images.lotterypageturntableawardsSelBg})` }"></span>
<image class="lotterypageturntableawards2img" <image class="lotterypageturntableawards2img"
:src="`${$baseUrl}${turntablePrizes[1].prizeImageUrl}`" mode="aspectFit" :src="`${$baseUrl}${turntablePrizes[1].prizeImageUrl}`" mode="aspectFit"
@error="console.log('奖品2图片加载失败')"></image> @error="console.log('奖品2图片加载失败')"></image>
<span class="lotterypageturntableawards2name">{{ turntablePrizes[1].prizeName }}</span> <span class="lotterypageturntableawards2name">{{ turntablePrizes[1].prizeName }}</span>
</div> </div>
<div class="lotterypageturntableawards1" v-if="turntablePrizes.length > 0"> <div class="lotterypageturntableawards1" v-if="turntablePrizes.length > 0">
<span class="lotterypageturntableawards1selbg" <span class="lotterypageturntableawards1selbg"
v-if="isPrizeSelected(0) || isPrizeHighlighted(0)" v-if="isPrizeSelected(0) || isPrizeHighlighted(0)"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.lotterypageturntableawardsSelBg)})` }"></span> :style="{ backgroundImage: `url(${config.images.lotterypageturntableawardsSelBg})` }"></span>
<image class="lotterypageturntableawards1img" <image class="lotterypageturntableawards1img"
:src="`${$baseUrl}${turntablePrizes[0].prizeImageUrl}`" mode="aspectFit" :src="`${$baseUrl}${turntablePrizes[0].prizeImageUrl}`" mode="aspectFit"
@error="console.log('奖品1图片加载失败')"></image> @error="console.log('奖品1图片加载失败')"></image>
<span class="lotterypageturntableawards1name">{{ turntablePrizes[0].prizeName }}</span> <span class="lotterypageturntableawards1name">{{ turntablePrizes[0].prizeName }}</span>
</div> </div>
</div> </div>
</div> </div>
<span class="lotterypagetitle" <span class="lotterypagetitle"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.title)})` }"></span> :style="{ backgroundImage: `url(${config.images.title})` }"></span>
<span class="lotterypagerulebtn" <span class="lotterypagerulebtn"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.ruleBtn)})` }" :style="{ backgroundImage: `url(${config.images.ruleBtn})` }"
@click="handleRuleClick"></span> @click="handleRuleClick"></span>
<span class="lotterypageawardbtn" <span class="lotterypageawardbtn"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.awardBtn)})` }" :style="{ backgroundImage: `url(${config.images.awardBtn})` }"
@click="handleAwardClick"></span> @click="handleAwardClick"></span>
<div class="lotterypagenoticecon"> <div class="lotterypagenoticecon">
<span class="lotterypagenoticeconbg" <span class="lotterypagenoticeconbg"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.noticeConBg)})` }"></span> :style="{ backgroundImage: `url(${config.images.noticeConBg})` }"></span>
<div class="lotterypagenoticecontext-wrapper"> <div class="lotterypagenoticecontext-wrapper">
<div class="lotterypagenoticecontext-container" :class="{ 'no-transition': isResetting }" <div class="lotterypagenoticecontext-container" :class="{ 'no-transition': isResetting }"
:style="{ transform: `translateY(-${currentNoticeIndex * 40}rpx)` }"> :style="{ transform: `translateY(-${currentNoticeIndex * 40}rpx)` }">
<span class="lotterypagenoticecontext" v-for="(notice, index) in displayNotices" <p class="lotterypagenoticecontext" v-for="(notice, index) in displayNotices"
:key="`${notice.userNickname}-${index}`" :style="{ top: `${index * 40}rpx` }">{{ :key="`${notice.userNickname}-${index}`" :style="{ top: `${index * 40}rpx` }">
formatNotice(notice.userNickname, notice.prizeName) <span class="lotterypagenoticetext">{{ formatNotice(notice.userNickname, notice.prizeName) }}</span>
}}</span> <span class="lotterypagenoticetime">
</div> {{getDetailedHumanizedTimeDiff(notice.winningTime)}}
</div> </span>
<span class="lotterypagenoticeconsoundicon" </p>
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.noticeConSoundIcon)})` }"></span> </div>
</div> </div>
</div>
<span class="lotterypagedrawbtn"
:style="{ backgroundImage: `url(${$baseUrl}${getImageUrl(config.images.drawBtn)})` }" <span class="lotterypagedrawbtn"
@click="handleDrawClick" :class="{ 'disabled-draw-btn': !canDraw }"></span> :style="{ backgroundImage: `url(${config.images.drawBtn})` }"
<span class="lotterypagelefttimes">剩余次数:{{ remainingTimes }}</span> @click="handleDrawClick" :class="{ 'disabled-draw-btn': !canDraw }"></span>
<span class="lotterypagelefttimes">剩余次数:{{ remainingTimes }}</span>
<!-- 规则弹窗 -->
<RuleModal :visible="showRuleModal" :rules="activityRules" :config="ruleModalConfig" <!-- 规则弹窗 -->
@close="handleRuleModalClose" /> <RuleModal :visible="showRuleModal" :rules="activityRules" :config="ruleModalConfig"
@close="handleRuleModalClose"/>
<!-- 抽奖成功弹窗 -->
<GotPrizeModal :visible="showGotPrizeModal" :award-name="currentAwardName" <GotPrizeModal ref="gotPrizeModalRef"/>
:award-image-url="currentAwardImageUrl" @close="handleGotPrizeModalClose" @happy-get="handleHappyGet" /> </view>
</view>
<!-- 抽奖失败弹窗 -->
<DrawFailModal :visible="showDrawFailModal" @close="handleDrawFailModalClose" @i-know="handleIKnow" />
</view>
</view>
</template> </template>
<script setup> <script setup>
import { ref, onMounted, computed, getCurrentInstance, onUnmounted } from 'vue' import {ref, onMounted, computed, getCurrentInstance, onUnmounted} from 'vue'
import { lotteryConfig, getImageUrl } from './config.js' import {lotteryConfig} from './config.js'
import RuleModal from './components/ruleModal/ruleModal.vue' import RuleModal from './components/ruleModal/ruleModal.vue'
import GotPrizeModal from '../components/GotPrizeModal.vue' import {lotteryDraw, fetchLotteryInfo, fetchLotteryConfig} from '../api.ts'
import DrawFailModal from './components/drawFailModal/drawFailModal.vue'
import { lotteryDraw, fetchLotteryInfo, fetchLotteryConfig } from '../api.ts'
import md from '@/md.js' import md from '@/md.js'
import { jump, JumpType } from '@/utils/index.js' import {jump, JumpType} from '@/utils/index.js'
import GotPrizeModal from "../components/GotPrizeModal.vue";
import {getDetailedHumanizedTimeDiff} from "../utils";
// 组件名称 // 组件名称
defineOptions({ defineOptions({
name: 'LotteryPage' name: 'LotteryPage'
}) })
// 响应式数据 // 响应式数据
...@@ -151,10 +147,7 @@ const isResetting = ref(false) // 是否正在重置轮播位置 ...@@ -151,10 +147,7 @@ const isResetting = ref(false) // 是否正在重置轮播位置
// 弹窗状态 // 弹窗状态
const showRuleModal = ref(false) // 规则弹窗 const showRuleModal = ref(false) // 规则弹窗
const showGotPrizeModal = ref(false) // 抽奖成功弹窗 const gotPrizeModalRef = ref()
const showDrawFailModal = ref(false) // 抽奖失败弹窗
const currentAwardName = ref('') // 当前中奖奖品名称
const currentAwardImageUrl = ref('') // 当前中奖奖品图片URL
// 配置对象 // 配置对象
const config = lotteryConfig const config = lotteryConfig
...@@ -165,433 +158,404 @@ const $baseUrl = instance.proxy.$baseUrl ...@@ -165,433 +158,404 @@ const $baseUrl = instance.proxy.$baseUrl
// 计算属性 - 是否可以抽奖 // 计算属性 - 是否可以抽奖
const canDraw = computed(() => { const canDraw = computed(() => {
return remainingTimes.value > 0 && currentState.value === 'normal' && !isDrawing.value return remainingTimes.value > 0 && currentState.value === 'normal' && !isDrawing.value
}) })
// 转盘不需要旋转,保持静态 // 转盘不需要旋转,保持静态
const turntableRotationStyle = computed(() => { const turntableRotationStyle = computed(() => {
return { return {
transform: 'rotate(0deg)', transform: 'rotate(0deg)',
transition: 'none' transition: 'none'
} }
}) })
// 检查奖品是否被选中(用于最终结果) // 检查奖品是否被选中(用于最终结果)
const isPrizeSelected = (index) => { const isPrizeSelected = (index) => {
return selectedPrizeIndex.value === index return selectedPrizeIndex.value === index
} }
// 检查奖品是否正在高亮(用于轮流亮起效果) // 检查奖品是否正在高亮(用于轮流亮起效果)
const isPrizeHighlighted = (index) => { const isPrizeHighlighted = (index) => {
return currentHighlightIndex.value === index return currentHighlightIndex.value === index
} }
// 获取最近的20条公告 // 获取最近的20条公告
const recentNotices = computed(() => { const recentNotices = computed(() => {
let notices = []; let notices = [];
if (winningCarousel.value.length > 0) { if (winningCarousel.value.length > 0) {
notices = winningCarousel.value.slice(0, 20); notices = winningCarousel.value.slice(0, 20);
} else { } else {
// 提供默认数据确保轮播能正常工作 // 提供默认数据确保轮播能正常工作
notices = [ notices = [
{ userNickname: '用户1', prizeName: '奖品A' }, {userNickname: '用户1', prizeName: '奖品A'},
{ userNickname: '用户2', prizeName: '奖品B' }, {userNickname: '用户2', prizeName: '奖品B'},
{ userNickname: '用户3', prizeName: '奖品C' } {userNickname: '用户3', prizeName: '奖品C'}
]; ];
} }
// 如果只有1条数据,复制成3条以确保轮播效果 // 如果只有1条数据,复制成3条以确保轮播效果
if (notices.length === 1) { if (notices.length === 1) {
const singleNotice = notices[0]; const singleNotice = notices[0];
notices = [singleNotice, singleNotice, singleNotice]; notices = [singleNotice, singleNotice, singleNotice];
console.log('轮播数据只有1条,已复制成3条:', notices); console.log('轮播数据只有1条,已复制成3条:', notices);
} }
return notices; return notices;
}); });
// 用于轮播显示的公告列表(重复数据以实现无缝循环) // 用于轮播显示的公告列表(重复数据以实现无缝循环)
const displayNotices = computed(() => { const displayNotices = computed(() => {
const notices = recentNotices.value; const notices = recentNotices.value;
if (notices.length === 0) return []; if (notices.length === 0) return [];
// 重复数据以实现无缝循环 // 重复数据以实现无缝循环
return [...notices, ...notices]; return [...notices, ...notices];
}); });
// 格式化公告内容,限制为20个字符 // 格式化公告内容,限制为20个字符
const formatNotice = (nickname, prize) => { const formatNotice = (nickname, prize) => {
const fullText = `${nickname} 获得了 ${prize}`; return `${nickname} 获得了 ${prize}`
return fullText;
}; };
// 返回按钮处理 // 返回按钮处理
const handleBack = () => { const handleBack = () => {
console.log('点击返回按钮') console.log('点击返回按钮')
// md.sensorComponentLogTake({ // md.sensorComponentLogTake({
// xcxComponentClick: "true", // xcxComponentClick: "true",
// pageName: "915专题活动抽奖页", // pageName: "915专题活动抽奖页",
// componentName: "返回按钮", // componentName: "返回按钮",
// componentContent: "返回" // componentContent: "返回"
// }); // });
try { try {
uni.navigateBack({ uni.navigateBack({
delta: 1, delta: 1,
success: () => { success: () => {
console.log('返回成功') console.log('返回成功')
}, },
fail: () => { fail: () => {
// 如果返回失败,跳转到首页 // 如果返回失败,跳转到首页
uni.redirectTo({ uni.redirectTo({
url: '/activity0915/act0915/act0915' url: '/activities/1015/home'
}) })
} }
}) })
} catch (error) { } catch (error) {
console.log('返回失败:', error) console.log('返回失败:', error)
uni.redirectTo({ uni.redirectTo({
url: '/activity0915/act0915/act0915' url: '/activities/1015/home'
}) })
} }
} }
// 规则按钮点击处理 // 规则按钮点击处理
const handleRuleClick = () => { const handleRuleClick = () => {
console.log('点击规则按钮') console.log('点击规则按钮')
md.sensorComponentLogTake({ md.sensorComponentLogTake({
xcxComponentClick: "true", xcxComponentClick: "true",
pageName: "915专题活动抽奖页", pageName: "915专题活动抽奖页",
componentName: "抽奖板块", componentName: "抽奖板块",
componentContent: "规则" componentContent: "规则"
}); });
showRuleModal.value = true showRuleModal.value = true
} }
// 规则弹窗关闭处理 // 规则弹窗关闭处理
const handleRuleModalClose = () => { const handleRuleModalClose = () => {
showRuleModal.value = false showRuleModal.value = false
} }
// 奖品按钮点击处理 // 奖品按钮点击处理
const handleAwardClick = () => { const handleAwardClick = () => {
console.log('点击奖品按钮') console.log('点击奖品按钮')
md.sensorComponentLogTake({ md.sensorComponentLogTake({
xcxComponentClick: "true", xcxComponentClick: "true",
pageName: "915专题活动抽奖页", pageName: "915专题活动抽奖页",
componentName: "抽奖板块", componentName: "抽奖板块",
componentContent: "奖品" componentContent: "奖品"
}); });
// // 根据环境获取对应的appId // // 根据环境获取对应的appId
// const getAppId = () => { // const getAppId = () => {
// // 可以根据实际环境判断 // // 可以根据实际环境判断
// // uat2: wxabebc35e71e66795 // // uat2: wxabebc35e71e66795
// // test2: wx18428fc8a569a3c7 // // test2: wx18428fc8a569a3c7
// // 生产: wx4205ec55b793245e // // 生产: wx4205ec55b793245e
// // 这里可以根据实际需求调整环境判断逻辑 // // 这里可以根据实际需求调整环境判断逻辑
// // 例如:根据域名、配置等判断当前环境 // // 例如:根据域名、配置等判断当前环境
// const currentEnv = 'prod' // 可以动态获取 // const currentEnv = 'prod' // 可以动态获取
// const appIdMap = { // const appIdMap = {
// 'uat2': 'wxabebc35e71e66795', // 'uat2': 'wxabebc35e71e66795',
// 'test2': 'wx18428fc8a569a3c7', // 'test2': 'wx18428fc8a569a3c7',
// 'prod': 'wx4205ec55b793245e' // 'prod': 'wx4205ec55b793245e'
// } // }
// return appIdMap[currentEnv] || appIdMap['uat2'] // 默认uat2环境 // return appIdMap[currentEnv] || appIdMap['uat2'] // 默认uat2环境
// } // }
jump({ jump({
type: JumpType.MINI, type: JumpType.MINI,
url: '/subPackages/xmhMainProcess/mine/index', url: '/subPackages/xmhMainProcess/mine/index',
extra: { extra: {
appId: 'wx4205ec55b793245e', appId: 'wx4205ec55b793245e',
envVersion: 'release' envVersion: 'release'
} }
}) })
// const appId = getAppId() // const appId = getAppId()
// const path = '/subPackages/xmhMainProcess/mine/index' // const path = '/subPackages/xmhMainProcess/mine/index'
// uni.navigateToMiniProgram({ // uni.navigateToMiniProgram({
// appId: appId, // appId: appId,
// path: path, // path: path,
// extraData: {}, // extraData: {},
// envVersion: 'release', // 可以根据环境调整:develop, trial, release // envVersion: 'release', // 可以根据环境调整:develop, trial, release
// success: (res) => { // success: (res) => {
// console.log('跳转小程序成功:', res) // console.log('跳转小程序成功:', res)
// }, // },
// fail: (err) => { // fail: (err) => {
// console.error('跳转小程序失败:', err) // console.error('跳转小程序失败:', err)
// // uni.showToast({ // // uni.showToast({
// // title: '跳转失败', // // title: '跳转失败',
// // icon: 'none' // // icon: 'none'
// // }) // // })
// } // }
// }) // })
} }
// 加载规则弹窗配置 // 加载规则弹窗配置
const loadRuleModalConfig = async () => { const loadRuleModalConfig = async () => {
try { try {
console.log('开始请求 fetchAct915LotteryJSON 接口...') console.log('开始请求 fetchAct915LotteryJSON 接口...')
const response = await fetchLotteryConfig() const response = await fetchLotteryConfig()
console.log('fetchAct915LotteryJSON 接口返回结果:', response) console.log('fetchAct915LotteryJSON 接口返回结果:', response)
if (response && response.ok && response.data) { if (response && response.ok && response.data) {
ruleModalConfig.value = response.data ruleModalConfig.value = response.data
console.log('规则弹窗配置加载成功:', ruleModalConfig.value) console.log('规则弹窗配置加载成功:', ruleModalConfig.value)
} else { } else {
console.warn('规则弹窗配置接口返回异常:', response) console.warn('规则弹窗配置接口返回异常:', response)
} }
} catch (error) { } catch (error) {
console.error('fetchAct915LotteryJSON 接口请求失败:', error) console.error('fetchAct915LotteryJSON 接口请求失败:', error)
} }
} }
// 加载抽奖信息 // 加载抽奖信息
const loadLotteryInfo = async () => { const loadLotteryInfo = async () => {
try { try {
console.log('开始请求 getAct915LotteryInfo 接口...') console.log('开始请求 getAct915LotteryInfo 接口...')
const response = await fetchLotteryInfo() const response = await fetchLotteryInfo()
console.log('getAct915LotteryInfo 接口返回结果:', response) console.log('getAct915LotteryInfo 接口返回结果:', response)
if (response && response.ok) { if (response && response.ok) {
remainingTimes.value = response.data.remainingChances remainingTimes.value = response.data.remainingChances
turntablePrizes.value = response.data.turntablePrizes turntablePrizes.value = response.data.turntablePrizes
winningCarousel.value = response.data.winningCarousel winningCarousel.value = response.data.winningCarousel
userWinningPrizes.value = response.data.userWinningPrizes userWinningPrizes.value = response.data.userWinningPrizes
activityRules.value = response.data.activityRules || '' activityRules.value = response.data.activityRules || ''
// 启动公告轮播(无论是否有API数据) // 启动公告轮播(无论是否有API数据)
startNoticeCarousel() startNoticeCarousel()
} else { } else {
// uni.showToast({ // uni.showToast({
// title: response.msg || '获取抽奖信息失败', // title: response.msg || '获取抽奖信息失败',
// icon: 'none' // icon: 'none'
// }) // })
// 即使API失败也启动轮播 // 即使API失败也启动轮播
startNoticeCarousel() startNoticeCarousel()
} }
} catch (error) { } catch (error) {
console.error('getAct915LotteryInfo 接口请求失败:', error) console.error('getAct915LotteryInfo 接口请求失败:', error)
uni.showToast({ uni.showToast({
title: '网络错误,请稍后重试', title: '网络错误,请稍后重试',
icon: 'none' icon: 'none'
}) })
// 即使网络错误也启动轮播 // 即使网络错误也启动轮播
startNoticeCarousel() startNoticeCarousel()
} }
} }
// 公告轮播 // 公告轮播
const startNoticeCarousel = () => { const startNoticeCarousel = () => {
// 确保有数据可以轮播 //return
if (recentNotices.value.length > 0) { // 确保有数据可以轮播
carouselTimer.value = setInterval(() => { if (recentNotices.value.length > 0) {
currentNoticeIndex.value = currentNoticeIndex.value + 1 carouselTimer.value = setInterval(() => {
console.log('当前公告索引:', currentNoticeIndex.value) currentNoticeIndex.value = currentNoticeIndex.value + 1
//console.log('当前公告索引:', currentNoticeIndex.value)
// 当滚动到重复数据的开始位置时,立即重置到原始位置(无动效)
if (currentNoticeIndex.value >= recentNotices.value.length) { // 当滚动到重复数据的开始位置时,立即重置到原始位置(无动效)
// 禁用过渡动效 if (currentNoticeIndex.value >= recentNotices.value.length) {
isResetting.value = true // 禁用过渡动效
isResetting.value = true
// 立即重置到原始位置
currentNoticeIndex.value = 0 // 立即重置到原始位置
currentNoticeIndex.value = 0
// 下一帧恢复过渡动效
setTimeout(() => { // 下一帧恢复过渡动效
isResetting.value = false setTimeout(() => {
}, 100) // 确保重置完成 isResetting.value = false
} }, 100) // 确保重置完成
}, 3000) // 每3秒切换一次 }
} }, 3000) // 每3秒切换一次
}
} }
// 停止轮播 // 停止轮播
const stopNoticeCarousel = () => { const stopNoticeCarousel = () => {
if (carouselTimer.value) { if (carouselTimer.value) {
clearInterval(carouselTimer.value) clearInterval(carouselTimer.value)
carouselTimer.value = null carouselTimer.value = null
} }
} }
// 抽奖按钮点击处理 // 抽奖按钮点击处理
const handleDrawClick = async () => { const handleDrawClick = async () => {
md.sensorComponentLogTake({ md.sensorComponentLogTake({
xcxComponentClick: "true", xcxComponentClick: "true",
pageName: "915专题活动抽奖页", pageName: "915专题活动抽奖页",
componentName: "抽奖板块", componentName: "抽奖板块",
componentContent: "立即抽奖" componentContent: "立即抽奖"
}); });
if (!canDraw.value) { if (!canDraw.value) {
uni.showToast({ uni.showToast({
title: '抽奖次数已用完', title: '抽奖次数已用完',
icon: 'none' icon: 'none'
}) })
return return
} }
console.log('开始抽奖') console.log('开始抽奖')
isDrawing.value = true isDrawing.value = true
selectedPrizeIndex.value = -1 // 重置选中状态 selectedPrizeIndex.value = -1 // 重置选中状态
currentHighlightIndex.value = -1 // 重置高亮状态 currentHighlightIndex.value = -1 // 重置高亮状态
// uni.showLoading({ // uni.showLoading({
// title: '抽奖中...', // title: '抽奖中...',
// mask: true // mask: true
// }) // })
try { try {
const response = await lotteryDraw() const response = await lotteryDraw()
console.log('getAct915LotteryDraw 接口返回结果:', response) console.log('getAct915LotteryDraw 接口返回结果:', response)
if (response && response.ok) { if (response && response.ok) {
remainingTimes.value = response.data.remainingChances remainingTimes.value = response.data.remainingChances
// 根据接口返回的prizeId找到对应的奖品索引 // 根据接口返回的prizeId找到对应的奖品索引
const prizeIndex = turntablePrizes.value.findIndex(prize => prize.prizeId === response.data.prizeId) const prizeIndex = turntablePrizes.value.findIndex(prize => prize.prizeId === response.data.prizeId)
console.warn("prizeIndex", prizeIndex) console.warn("prizeIndex", prizeIndex)
if (prizeIndex !== -1) { if (prizeIndex !== -1) {
// 开始轮流亮起效果 // 开始轮流亮起效果
startHighlightAnimation(prizeIndex, response.data.isWin) startHighlightAnimation(prizeIndex, response.data.isWin)
} else { } else {
// 如果找不到对应奖品,显示失败 // 如果找不到对应奖品,显示失败
// uni.hideLoading() // uni.hideLoading()
isDrawing.value = false isDrawing.value = false
showDrawFailModal.value = true gotPrizeModalRef.show()
} }
} else { } else {
// uni.hideLoading() // uni.hideLoading()
isDrawing.value = false isDrawing.value = false
uni.showToast({ uni.showToast({
title: response.msg || '抽奖失败', title: response.msg || '抽奖失败',
icon: 'none' icon: 'none'
}) })
} }
} catch (error) { } catch (error) {
console.error('getAct915LotteryDraw 接口请求失败:', error) console.error('getAct915LotteryDraw 接口请求失败:', error)
uni.hideLoading() uni.hideLoading()
isDrawing.value = false isDrawing.value = false
uni.showToast({ uni.showToast({
title: '网络错误,请稍后重试', title: '网络错误,请稍后重试',
icon: 'none' icon: 'none'
}) })
} }
} }
// 轮流亮起动画 // 轮流亮起动画
const startHighlightAnimation = (targetIndex, isWin) => { const startHighlightAnimation = (targetIndex, isWin) => {
console.log(`开始轮流亮起动画,目标奖品索引: ${targetIndex}, 是否中奖: ${isWin}`) console.log(`开始轮流亮起动画,目标奖品索引: ${targetIndex}, 是否中奖: ${isWin}`)
// 按照指定顺序:1 -> 5 -> 3 -> 2 -> 4 -> 6 // 按照指定顺序:1 -> 5 -> 3 -> 2 -> 4 -> 6
// 对应索引:0 -> 4 -> 2 -> 1 -> 3 -> 5 // 对应索引:0 -> 4 -> 2 -> 1 -> 3 -> 5
const turntableOrder = [0, 4, 2, 1, 3, 5] // 按照指定顺序 const turntableOrder = [0, 4, 2, 1, 3, 5] // 按照指定顺序
const totalPrizes = turntableOrder.length const totalPrizes = turntableOrder.length
let currentOrderIndex = 0 let currentOrderIndex = 0
let roundCount = 0 let roundCount = 0
const maxRounds = 2 // 最多转2圈 const maxRounds = 2 // 最多转2圈
const highlightSpeed = 200 // 每个奖品高亮200ms const highlightSpeed = 200 // 每个奖品高亮200ms
const highlightTimer = setInterval(() => { const highlightTimer = setInterval(() => {
// 获取当前转盘顺序中的奖品索引 // 获取当前转盘顺序中的奖品索引
const currentPrizeIndex = turntableOrder[currentOrderIndex] const currentPrizeIndex = turntableOrder[currentOrderIndex]
currentHighlightIndex.value = currentPrizeIndex currentHighlightIndex.value = currentPrizeIndex
// 检查是否到达目标位置 // 检查是否到达目标位置
if (roundCount >= maxRounds && currentPrizeIndex === targetIndex) { if (roundCount >= maxRounds && currentPrizeIndex === targetIndex) {
clearInterval(highlightTimer) clearInterval(highlightTimer)
// 停止高亮,显示最终选中状态 // 停止高亮,显示最终选中状态
setTimeout(() => { setTimeout(() => {
currentHighlightIndex.value = -1 currentHighlightIndex.value = -1
selectedPrizeIndex.value = targetIndex selectedPrizeIndex.value = targetIndex
uni.hideLoading() uni.hideLoading()
// 显示结果弹窗 // 显示结果弹窗
setTimeout(() => { setTimeout(() => {
isDrawing.value = false isDrawing.value = false
if (isWin) { if (isWin) {
currentAwardName.value = turntablePrizes.value[targetIndex].prizeName const {prizeName, prizeImageUrl} = turntablePrizes.value[targetIndex]
currentAwardImageUrl.value = turntablePrizes.value[targetIndex].prizeImageUrl gotPrizeModalRef.value.show({
showGotPrizeModal.value = true prizeName,
} else { prizeImageUrl,
showDrawFailModal.value = true })
} } else {
gotPrizeModalRef.value.show({})
// 延迟重置选中状态 }
setTimeout(() => {
selectedPrizeIndex.value = -1 // 延迟重置选中状态
}, 2000) setTimeout(() => {
}, 1000) selectedPrizeIndex.value = -1
}, highlightSpeed) }, 2000)
} else { }, 1000)
// 移动到下一个奖品(按转盘顺序) }, highlightSpeed)
currentOrderIndex = (currentOrderIndex + 1) % totalPrizes } else {
// 移动到下一个奖品(按转盘顺序)
// 如果回到起点,增加圈数 currentOrderIndex = (currentOrderIndex + 1) % totalPrizes
if (currentOrderIndex === 0) {
roundCount++ // 如果回到起点,增加圈数
} if (currentOrderIndex === 0) {
} roundCount++
}, highlightSpeed) }
} }
}, highlightSpeed)
// 抽奖成功弹窗关闭处理
const handleGotPrizeModalClose = () => {
showGotPrizeModal.value = false
}
// 开心领取处理
const handleHappyGet = () => {
console.log('点击开心领取')
showGotPrizeModal.value = false
// uni.showToast({
// title: '奖品领取成功',
// icon: 'success'
// })
}
// 抽奖失败弹窗关闭处理
const handleDrawFailModalClose = () => {
showDrawFailModal.value = false
}
// 我知道了处理
const handleIKnow = () => {
console.log('点击我知道了')
showDrawFailModal.value = false
// uni.showToast({
// title: '下次再来试试吧',
// icon: 'none'
// })
} }
// 生命周期 // 生命周期
onMounted(() => { onMounted(() => {
console.log('抽奖页面已加载') console.log('抽奖页面已加载')
loadRuleModalConfig() // 先加载规则弹窗配置 loadRuleModalConfig() // 先加载规则弹窗配置
loadLotteryInfo() loadLotteryInfo()
md.sensorComponentLogTake({ md.sensorComponentLogTake({
xcxComponentExposure: "true", xcxComponentExposure: "true",
pageName: "915专题活动抽奖页", pageName: "915专题活动抽奖页",
componentName: "抽奖板块", componentName: "抽奖板块",
componentContent: "规则、奖品、立即抽奖" componentContent: "规则、奖品、立即抽奖"
}); });
}) })
onUnmounted(() => { onUnmounted(() => {
stopNoticeCarousel() stopNoticeCarousel()
}) })
</script> </script>
......
import {getCdnUrl} from "./utils";
const pageName = '1015专题活动页面'
// 页面配置
export function homeConfig(){
return {
"background": {
image: getCdnUrl('home/bg.png'),
style: {
backgroundPosition: {y: "calc(4937rpx + 845rpx)"}
}
},
shareConfig: {
title: '星妈会超级品牌周来啦!',
path: '/activities/1015/home/index',
imageUrl: 'https://course.feihe.com/momclub-picture/Act915Page/v2/act915ShareImg.png',
},
components: [
{
type: "image-swiper",
properties: {
autoplay: true,
interval: 3000,
duration: 500,
circular: true,
indicatorDots: true,
items: [{
image: getCdnUrl('home/banner-0.png'),
mdConfig: {
pageName,
componentName: "banner头图",
componentContent: "北纬47 °",
logExposure: true,
},
}, {
image: getCdnUrl('home/banner-1.png'),
mdConfig: {
pageName,
componentName: "banner头图",
componentContent: "国际大米节金奖",
logExposure: true,
},
link: {
type: 2,
url: "subPackages/shopMainProcess/product/index?productId=643246351932056828&skuId=643246351932056829&entrySource=xmh_wechatmp_activity_1015ppz",
extra: {envVersion: "release", appId: "wx4205ec55b793245e"},
}
}]
},
style: {
height: "845rpx",
}
},
{
type: "click-area",
properties: {
area: {x: 35, y: 915, width: 685, height: 245},
mdConfig: {
pageName,
componentName: "商品banner",
componentContent: "商品banner",
logExposure: true,
logClick: true,
},
link: {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=720448018529899563&skuId=720448018529899564&entrySource=xmh_wechatmp_activity_1015ppz"
},
},
},
{
type: "click-area",
properties: {
area: {x: 50, y: 2095, width: 320, height: 390},
mdConfig: {
pageName,
componentName: "品牌宣传1",
componentContent: "商品名称1",
logExposure: true,
logClick: true,
},
link: {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=643246351932056828&skuId=643246351932056829&entrySource=xmh_wechatmp_activity_1015ppz"
},
}
},
{
type: "click-area",
properties: {
area: {x: 380, y: 2095, width: 320, height: 390},
mdConfig: {
pageName,
componentName: "品牌宣传1",
componentContent: "商品名称2",
logExposure: true,
logClick: true,
},
link: {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=643245114369684591&skuId=643245114369684592&entrySource=xmh_wechatmp_activity_1015ppz"
},
}
},
{
type: "click-area",
properties: {
area: {x: 50, y: 3405, width: 320, height: 390},
mdConfig: {
pageName,
componentName: "品牌宣传2",
componentContent: "商品名称1",
logExposure: true,
logClick: true,
},
link: {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=368848644886521333&skuId=368848644886521334&entrySource=xmh_wechatmp_activity_1015ppz"
},
}
},
{
type: "click-area",
properties: {
area: {x: 380, y: 3405, width: 320, height: 390},
mdConfig: {
pageName,
componentName: "品牌宣传2",
componentContent: "商品名称2",
logExposure: true,
logClick: true,
},
link: {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=367056951412568222&skuId=367056951412568223&entrySource=xmh_wechatmp_activity_1015ppz"
},
}
},
{
type: "invite-task",
properties: {
area: {x: 35, y: 3865, width: 685, height: 195},
mdConfig: {
pageName,
componentName: "邀请得好礼",
componentContent: "立即邀请",
logExposure: true,
logClick: true,
},
},
},
{
type: "click-area",
properties: {
area: {x: 35, y: 4080, width: 685, height: 245},
mdConfig: {
pageName,
componentName: "中部抽奖banner",
componentContent: "中部抽奖banner",
logExposure: true,
logClick: true,
},
link: {
"type": 1,
"url": "/activities/1015/lottery/index"
},
},
},
{
"type": "click-area",
"properties": {
"area": {"x": 50, "y": 4405, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品1",
componentContent: "商品1",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=643243579803297229&skuId=643243579803297230&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
{
"type": "click-area",
"properties": {
"area": {"x": 270, "y": 4405, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品1",
componentContent: "商品2",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=367070126091559975&skuId=367070126091559976&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
{
"type": "click-area",
"properties": {
"area": {"x": 490, "y": 4405, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品1",
componentContent: "商品3",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=367072891644670759&skuId=367072891644670760&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
{
"type": "click-area",
"properties": {
"area": {"x": 50, "y": 4705, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品1",
componentContent: "商品4",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=649435440113431085&skuId=649435440113431086&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
{
"type": "click-area",
"properties": {
"area": {"x": 270, "y": 4705, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品1",
componentContent: "商品5",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=662389781175669644&skuId=662389781175669645&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
{
"type": "click-area",
"properties": {
"area": {"x": 490, "y": 4705, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品1",
componentContent: "商品6",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=759248536249386165&skuId=759248536249386166&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
{
"type": "click-area",
"properties": {
"area": {"x": 50, "y": 5110, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品2",
componentContent: "商品1",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=399302177175705120&skuId=399302177175705121&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
{
"type": "click-area",
"properties": {
"area": {"x": 270, "y": 5110, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品2",
componentContent: "商品2",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=650599779914081413&skuId=650599779914081414&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
{
"type": "click-area",
"properties": {
"area": {"x": 490, "y": 5110, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品2",
componentContent: "商品3",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=667527760599458548&skuId=667527760599458549&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
{
"type": "click-area",
"properties": {
"area": {"x": 50, "y": 5410, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品2",
componentContent: "商品4",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=548984197069284758&skuId=548984197069284759&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
{
"type": "click-area",
"properties": {
"area": {"x": 270, "y": 5410, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品2",
componentContent: "商品5",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=792232869316748776&skuId=792232869316748777&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
{
"type": "click-area",
"properties": {
"area": {"x": 490, "y": 5410, "width": 200, "height": 285},
"mdConfig": {
pageName,
componentName: "6组商品2",
componentContent: "商品6",
logExposure: true,
logClick: true,
},
"link": {
"extra": {"envVersion": "release", "appId": "wx4205ec55b793245e"},
"type": 2,
"url": "subPackages/shopMainProcess/product/index?productId=704050114989893289&skuId=704050114989893290&entrySource=xmh_wechatmp_activity_1015ppz"
}
}
},
],
"lottery": {
"image": "act1015Page/v3/act1015PageLotteryBanner.png",
"link": {"type": 1, "url": "/activity0915/lottery/lottery"}
},
"invite": {
"image": "act1015Page/v3/act1015PageInviteConBg.png",
"link": {"type": 1, "url": "/pages/invite/invite"},
"inviteConStatusNo1Img": "act1015Page/v3/act1015PageInviteConStatusNo.png",
"inviteConStatusYes2Img": "act1015Page/v3/act1015PageInviteConStatusYes.png",
"inviteConStatusYes1Img": "act1015Page/v3/act1015PageInviteConStatusYes.png",
"inviteConStatusNo2Img": "act1015Page/v3/act1015PageInviteConStatusNo.png"
}
}
}
//console.log('page-config:', JSON.stringify(act1015Config, null, 2))
// 获取图片URL的工具函数
export const getImageUrl = (imagePath) => {
return imagePath
}
...@@ -31,7 +31,7 @@ export interface Prize{ ...@@ -31,7 +31,7 @@ export interface Prize{
prizeImageUrl: string prizeImageUrl: string
} }
export interface ActivityInfo { export interface InvitationInfo {
invitationCode: string invitationCode: string
invitationText: string invitationText: string
invitationImageUrl: string invitationImageUrl: string
......
import {useGlobalStore} from "@/stores/global";
const version = 'v1'
export function getCdnUrl(path){
const {baseUrl} = useGlobalStore()
return `${baseUrl}activity/1015/${version}/${path}`
}
function normalizeDateInput(dateInput: any): Date {
if (dateInput instanceof Date) {
return dateInput;
}
if (typeof dateInput === 'string') {
// 处理 "yyyy-MM-dd HH:mm:ss" 格式
if (dateInput.includes(' ') && dateInput.includes('-')) {
return new Date(dateInput.replace(' ', 'T'));
}
// 其他情况直接尝试创建Date对象
return new Date(dateInput);
}
return new Date(dateInput);
}
export function getDetailedHumanizedTimeDiff(targetTime: any) {
const nowTimestamp = Date.now();
const targetDate = normalizeDateInput(targetTime ?? nowTimestamp);
if (isNaN(targetDate.getTime())) {
debugger
console.warn('Invalid date input:', targetTime);
return '无效时间';
}
const targetTimestamp = targetDate.getTime();
const diff = nowTimestamp - targetTimestamp;
const isPast = diff > 0;
const absDiff = Math.abs(diff);
let result = '';
if (absDiff < 60 * 1000) {
// 小于1分钟
result = '刚刚';
} else if (absDiff < 60 * 60 * 1000) {
// 小于1小时
const minutes = Math.floor(absDiff / (60 * 1000));
result = isPast ? `${minutes}分钟前` : `${minutes}分钟后`;
} else if (absDiff < 24 * 60 * 60 * 1000) {
// 小于1天
const hours = Math.floor(absDiff / (60 * 60 * 1000));
result = isPast ? `${hours}小时前` : `${hours}小时后`;
} else if (absDiff < 30 * 24 * 60 * 60 * 1000) {
// 小于30天
const days = Math.floor(absDiff / (24 * 60 * 60 * 1000));
result = isPast ? `${days}天前` : `${days}天后`;
} else if (absDiff < 12 * 30 * 24 * 60 * 60 * 1000) {
// 小于12个月
const months = Math.floor(absDiff / (30 * 24 * 60 * 60 * 1000));
result = isPast ? `${months}个月前` : `${months}个月后`;
} else {
// 超过12个月
const years = Math.floor(absDiff / (12 * 30 * 24 * 60 * 60 * 1000));
result = isPast ? `${years}年前` : `${years}年后`;
}
return result;
}
...@@ -5,20 +5,20 @@ ...@@ -5,20 +5,20 @@
``` ```
activity0915/lottery/ activity0915/lottery/
├── lottery.vue # 主抽奖页面 ├── lottery.vue # 主抽奖页面
├── config.js # 主页面配置 ├── mock-configs.js # 主页面配置
├── lotterypage.less # 主页面样式 ├── lotterypage.less # 主页面样式
└── components/ # 弹窗组件目录 └── components/ # 弹窗组件目录
├── ruleModal/ # 规则弹窗 ├── ruleModal/ # 规则弹窗
│ ├── ruleModal.vue │ ├── ruleModal.vue
│ ├── config.js │ ├── mock-configs.js
│ └── rulemodal.less │ └── rulemodal.less
├── drawSucModal/ # 抽奖成功弹窗 ├── drawSucModal/ # 抽奖成功弹窗
│ ├── drawSucModal.vue │ ├── drawSucModal.vue
│ ├── config.js │ ├── mock-configs.js
│ └── drawsucmodal.less │ └── drawsucmodal.less
└── drawFailModal/ # 抽奖失败弹窗 └── drawFailModal/ # 抽奖失败弹窗
├── drawFailModal.vue ├── drawFailModal.vue
├── config.js ├── mock-configs.js
└── drawfailmodal.less └── drawfailmodal.less
``` ```
......
...@@ -343,7 +343,7 @@ components/xingmaLab/ ...@@ -343,7 +343,7 @@ components/xingmaLab/
├── Xingmalabconfirmpop.vue # 确认弹窗组件 ├── Xingmalabconfirmpop.vue # 确认弹窗组件
├── Xingmalabnotimepop.vue # 无时间弹窗组件 ├── Xingmalabnotimepop.vue # 无时间弹窗组件
├── xingmalabImages.js # 图片配置文件 ├── xingmalabImages.js # 图片配置文件
├── config.js # 旧版配置文件(已废弃) ├── mock-configs.js # 旧版配置文件(已废弃)
├── README.md # 使用说明 ├── README.md # 使用说明
└── IMAGES.md # 图片资源说明 └── IMAGES.md # 图片资源说明
``` ```
...@@ -352,7 +352,7 @@ components/xingmaLab/ ...@@ -352,7 +352,7 @@ components/xingmaLab/
从旧版配置系统迁移到新的图片配置系统: 从旧版配置系统迁移到新的图片配置系统:
1. **移除依赖**: 不再依赖 `config.js` 中的复杂配置 1. **移除依赖**: 不再依赖 `mock-configs.js` 中的复杂配置
2. **简化导入**: 直接导入 `XINGMALAB_IMAGES` 常量 2. **简化导入**: 直接导入 `XINGMALAB_IMAGES` 常量
3. **简化样式**: 移除计算属性,直接使用 CSS 样式 3. **简化样式**: 移除计算属性,直接使用 CSS 样式
4. **保持兼容**: 按钮位置和尺寸与 React 版本完全一致 4. **保持兼容**: 按钮位置和尺寸与 React 版本完全一致
...@@ -24,22 +24,28 @@ Vue.config.productionTip = false; ...@@ -24,22 +24,28 @@ Vue.config.productionTip = false;
App.mpType = "app"; App.mpType = "app";
const app = new Vue({ const app = new Vue({
...App, ...App,
}); });
app.$mount(); app.$mount();
// #endif // #endif
// #ifdef VUE3 // #ifdef VUE3
import { createSSRApp } from "vue"; import {createSSRApp} from "vue";
import {useGlobalStore} from "@/stores/global";
export function createApp() { export function createApp() {
const app = createSSRApp(App); const app = createSSRApp(App);
app.use(Pinia.createPinia()); app.use(Pinia.createPinia());
// app.config.globalProperties.$api = apiRequest.api; // app.config.globalProperties.$api = apiRequest.api;
app.config.globalProperties.$baseUrl = BASE_URL; app.config.globalProperties.$baseUrl = BASE_URL;
app.config.globalProperties.$sensors = md.sensors; app.config.globalProperties.$sensors = md.sensors;
return {
app, useGlobalStore().setBaseUrl(BASE_URL)
Pinia,
}; return {
app,
Pinia,
};
} }
// #endif // #endif
...@@ -279,7 +279,7 @@ ...@@ -279,7 +279,7 @@
"root": "activities/1015", "root": "activities/1015",
"pages": [ "pages": [
{ {
"path": "home/index", "path": "home",
"style": { "style": {
"navigationBarTitleText": "", "navigationBarTitleText": "",
"shareAppMessage": true, "shareAppMessage": true,
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
XingmaLabDetailPage/ XingmaLabDetailPage/
├── XingmaLabDetailPage.vue # 主组件文件 ├── XingmaLabDetailPage.vue # 主组件文件
├── XingmaLabDetailPage.less # 样式文件 ├── XingmaLabDetailPage.less # 样式文件
├── config.js # 配置文件 ├── mock-configs.js # 配置文件
└── README.md # 说明文档 └── README.md # 说明文档
``` ```
...@@ -57,7 +57,7 @@ import XingmaLabDetailPage from '@/pages/XingmaLabDetailPage/XingmaLabDetailPage ...@@ -57,7 +57,7 @@ import XingmaLabDetailPage from '@/pages/XingmaLabDetailPage/XingmaLabDetailPage
### 图片资源配置 ### 图片资源配置
`config.js` 中配置图片资源路径: `mock-configs.js` 中配置图片资源路径:
```javascript ```javascript
export const xingmaLabDetailConfig = { export const xingmaLabDetailConfig = {
......
...@@ -72,7 +72,7 @@ upload: { ...@@ -72,7 +72,7 @@ upload: {
pages/XingmaLabPublishPage/ pages/XingmaLabPublishPage/
├── XingmaLabPublishPage.vue # 主组件文件 ├── XingmaLabPublishPage.vue # 主组件文件
├── XingmaLabPublishPage.less # 样式文件 ├── XingmaLabPublishPage.less # 样式文件
├── config.js # 配置文件 ├── mock-configs.js # 配置文件
├── README.md # 功能说明文档 ├── README.md # 功能说明文档
└── CHANGELOG.md # 更新日志 └── CHANGELOG.md # 更新日志
``` ```
......
...@@ -14,10 +14,14 @@ export const useGlobalStore = defineStore('global', { ...@@ -14,10 +14,14 @@ export const useGlobalStore = defineStore('global', {
isWxFriendCircle:false, isWxFriendCircle:false,
isShowLoading: false, isShowLoading: false,
openId: openId, openId: openId,
unionId: unionId unionId: unionId,
baseUrl: '',
}; };
}, },
actions: { actions: {
setBaseUrl(url){
this.baseUrl = url
},
/** /**
* 设置用户cuk * 设置用户cuk
* @param {Object} cuk * @param {Object} cuk
......
...@@ -81,7 +81,7 @@ ...@@ -81,7 +81,7 @@
npm update mp-html npm update mp-html
``` ```
使用 *cli* 方式运行的项目,通过 *npm* 方式引入时,需要在 *vue.config.js* 中配置 *transpileDependencies*,详情可见 [#330](https://github.com/jin-yufeng/mp-html/issues/330#issuecomment-913617687) 使用 *cli* 方式运行的项目,通过 *npm* 方式引入时,需要在 *vue.mock-configs.js* 中配置 *transpileDependencies*,详情可见 [#330](https://github.com/jin-yufeng/mp-html/issues/330#issuecomment-913617687)
如果在 **nvue** 中使用还要将 `dist/uni-app/static` 目录下的内容拷贝到项目的 `static` 目录下,否则无法运行 如果在 **nvue** 中使用还要将 `dist/uni-app/static` 目录下的内容拷贝到项目的 `static` 目录下,否则无法运行
查看 [快速开始](https://jin-yufeng.github.io/mp-html/#/overview/quickstart) 了解更多 查看 [快速开始](https://jin-yufeng.github.io/mp-html/#/overview/quickstart) 了解更多
...@@ -158,7 +158,7 @@ ...@@ -158,7 +158,7 @@
```bash ```bash
npm install mp-html npm install mp-html
``` ```
2. 编辑 `tools/config.js` 中的 `plugins` 项,选择需要的插件 2. 编辑 `tools/mock-configs.js` 中的 `plugins` 项,选择需要的插件
3. 生成新的组件包 3. 生成新的组件包
`node_modules/mp-html` 目录下执行 `node_modules/mp-html` 目录下执行
```bash ```bash
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment