更新周边功能

This commit is contained in:
xiaoaojiao
2025-09-09 23:24:51 +08:00
parent 9a5cf53e3c
commit 246edb68ab
15 changed files with 644 additions and 344 deletions

63
src/components/Ad.vue Normal file
View File

@@ -0,0 +1,63 @@
<template>
<ModalTransition class="ad" :show="show" position="center">
<div class="ad-wrapper">
<div class="btn-ad" v-html="adHtml" @click="adGoto"></div>
<div class="close" @click="emit('close')"></div>
</div>
</ModalTransition>
</template>
<script setup>
import ModalTransition from "./ModalTransition.vue"
import { ref } from "vue"
import { isWeixinPlatform, miniJumpToScene, getMiniPageBtnHack } from "../libs/utils"
const props = defineProps({
show: false,
})
const emit = defineEmits(['close'])
const adHtml = ref('')
//TODO: 这个地址后面要改的
adHtml.value = getMiniPageBtnHack("/pages/unify/unify?orgId=200282401019674482&targetUrl=%2Fpages%2Fcoupon%2Fcoupons-list")
const adGoto = () => {
if (!isWeixinPlatform()) {
weui.alert("请前往「泸州老窖会员中心」小程序进行查询")
}
}
</script>
<style scoped>
.ad-wrapper {
position: relative;
width: 100vw;
height: 190vw;
background-image: url("../assets/images/ad-bg.png");
background-repeat: no-repeat;
background-size: 100%;
}
.btn-ad {
width: 54.351852vw;
height: 20.092593vw;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, 180%);
background-image: url("../assets/images/btn-ad.png");
background-repeat: no-repeat;
background-size: 100%;
}
.close {
position: absolute;
width: 8.148148vw;
height: 8.148148vw;
top: 50%;
left: 50%;
transform: translate(-50%, 0);
margin-top: 58vw;
background-image: url("../assets/images/close-btn.png");
background-repeat: no-repeat;
background-size: 100%;
}
</style>

View File

@@ -1,5 +1,5 @@
<template>
<ModalTransition :show="addressShow">
<ModalTransition :show="show">
<div class="address-wrapper">
<div class="address-title">收货地址填写</div>
<div class="address-content">
@@ -36,7 +36,7 @@ const props = defineProps({
prizeId: Number
})
const emit = defineEmits(['addressSubmit','addressClose'])
const addressShow = computed(() => props.prizeId ? props.show : false)
// const addressShow = computed(() => props.prizeId ? props.show : false)
const btnDisableClass = ref(false)
const name = ref('')
const phone = ref('')

View File

@@ -1,6 +1,7 @@
<script setup>
import { ref, computed, watch, onMounted } from "vue"
import { useRouter } from 'vue-router'
import globalToastEvent, { ToastType } from '../globalToastEvent';
import { Request, Storage } from "../libs/utils"
import faceFamily from "../assets/audio/faceFamily.mp3"
defineProps({
@@ -28,12 +29,12 @@ const tryAutoPlay = () => {
isMusicOn.value = true;
console.log("自动播放成功");
})
.catch(error => {
// 自动播放被阻止
console.log("自动播放被阻止,需要用户交互:", error);
isMusicOn.value = false;
audioElement.value.pause();
});
.catch(error => {
// 自动播放被阻止
console.log("自动播放被阻止,需要用户交互:", error);
isMusicOn.value = false;
audioElement.value.pause();
});
}
};
@@ -41,7 +42,7 @@ const tryAutoPlay = () => {
const toggleMusicState = () => {
isMusicOn.value = !isMusicOn.value;
if (!isMusicOn.value) {
audioElement.value.pause();
audioElement.value.pause();
} else {
audioElement.value.play().catch(error => {
console.log("播放失败:", error);
@@ -56,12 +57,25 @@ const navigateSelectTemplatePage = () => {
})
}
const navigateTodoList = () => {
globalToastEvent.emit(ToastType.SHOW_TODO)
}
const handlePrizeList = async () => {
globalToastEvent.emit(ToastType.SHOW_PRIZELIST)
}
const handleRule = () => {
globalToastEvent.emit(ToastType.SHOW_RULE)
}
const handleLottery = () => {
globalToastEvent.emit(ToastType.SHOW_LOTTERY)
}
</script>
<template>
<div :show="show">
<div class="home-wrapper">
<div class="scene-item item-1">
<div class="scene-item item-1" @click="handleLottery">
<img src="../assets/images/lottery.png" alt="抽奖">
<div class="lottery-main">
<p class="lottery-value">3</p>
@@ -85,10 +99,10 @@ const navigateSelectTemplatePage = () => {
<img src="../assets/images/music-off.png" alt="音乐关">
</div>
</div>
<div class="scene-item item-6">
<div class="scene-item item-6" @click="handleRule">
<img src="../assets/images/rule.png" alt="规则">
</div>
<div class="scene-item item-7">
<div class="scene-item item-7" @click="handlePrizeList">
<img src="../assets/images/award.png" alt="奖励">
</div>
<div class="scene-item item-8">
@@ -193,36 +207,42 @@ const navigateSelectTemplatePage = () => {
right: 0;
animation-delay: 0s;
}
.item-4 {
width: 46px;
top: 1.5%;
right: 1.5%;
animation-delay: 0s;
}
.item-5 {
width: 46px;
top: 1.5%;
right: 1.5%;
animation-delay: 0s;
}
.item-6 {
width: 62px;
top: 8%;
right: 0;
animation-delay: 0s;
}
.item-7 {
width: 62px;
top: 13.5%;
right: 0;
animation-delay: 0s;
}
.item-8 {
width: 50px;
bottom: 32%;
right: 1%;
animation-delay: 0s;
}
.item-9 {
width: 50px;
bottom: 23%;

View File

@@ -1,235 +1,378 @@
<template>
<ModalTransition class="lottery" :show="show" name="opacity" position="center">
<div class="lottery-wrapper">
<div class="laohuji">
<div class="laohuji-temp" ref="tempRef"></div>
<div class="laohuji-bottom">
<div class="laohuji-list">
<div class="laohuji-item a" ref="itemaRef"></div>
<div class="laohuji-item b" ref="itembRef"></div>
<div class="laohuji-item c" ref="itemcRef"></div>
<div class="guang" ref="guangRef"></div>
<div class="guangyun" ref="guangyunRef"></div>
<div class="lottery-scene" ref="sceneRef">
<div class="lottery-card" ref="cardRef">
<div class="lottery-face">
<img :src="lotteryFaceUrl" alt="">
</div>
<div class="lottery-prize">
<div class="lottery-title" ref="titleRef"></div>
<div class="lottery-image" :class="activePrizeData.prize_code"></div>
<div class="lottery-name">{{ activePrizeData.name }}</div>
<div class="lottery-btngroup" v-show="btngroupShow">
<div class="btn-more" @click="handleBtnMore"></div>
<div class="btn-kaixin" @click="handleLotteryAction"></div>
</div>
</div>
</div>
<div class="btn-kaixin" ref="btnRef" @click="handleGetLottery"></div>
<div class="laohuji-kapian" ref="kapianRef">
<div class="laohuji-kapian-bg" ref="kapianBgRef">
<div class="laohuji-kapian-cover" :class="kapianCover"></div>
</div>
</div>
<div class="laohuji-top"></div>
</div>
</div>
</ModalTransition>
</template>
<script setup>
import { gsap } from "gsap";
import Phaser from "phaser"
import { ref, watch, onMounted, onUnmounted } from "vue"
import globalToastEvent, { ToastType } from "../globalToastEvent";
import ModalTransition from "./ModalTransition.vue"
import confetti from "canvas-confetti";
import { Howl } from 'howler';
import { Request } from "../libs/utils"
import lotterySoundUrl from '../assets/audio/lottery.mp3'
import laohujiSoundUrl from '../assets/audio/laohuji.mp3'
import { Request, Sleep } from "../libs/utils"
import { globalStore } from "@/globalstore";
const laohujiSound = new Howl({
src: [laohujiSoundUrl]
});
const lotterySoundSuccess = new Howl({
src: [lotterySoundUrl]
});
//TODO: 这里这张图要用用户分享那张图
import lotteryFace from "../assets/images/haibao-cover.png"
const lotteryFaceUrl = ref(lotteryFace)
const cardRef = ref(null)
const sceneRef = ref(null)
const guangRef = ref(null)
const guangyunRef = ref(null)
const titleRef = ref(null)
const activePrizeData = ref({})
const btngroupShow = ref(false)
gsap.registerPlugin()
const props = defineProps({
show: false,
})
const emit = defineEmits(['close', 'address'])
const emit = defineEmits(['close'])
const kapianRef = ref(null)
const tempRef = ref(null)
const btnRef = ref(null)
const itemaRef = ref(null)
const itembRef = ref(null)
const itemcRef = ref(null)
const kapianCover = ref('')
const kapianBgRef = ref(null)
const PRIZE_LIST = ['TJGJ','XINCHUN_WEIZUN', 'TEQU_JL_52_60Y_100ML_2', 'LZLJ_TEQU_LZH_52_100ML_2', 'HEIGAI_42_GPJ_500ML', 'DZCZ', 'DZSCZ', '66_POINTS', 'NO']
// 滚动奖品图片的高度(所有奖品)
const GRID = 165.833333
let PRIZEDATA = null
let interval = null
const PRIZE_LIST = ['TJGJ', 'XINCHUN_WEIZUN', 'TEQU_JL_52_60Y_100ML_2', 'LZLJ_TEQU_LZH_52_100ML_2', 'HEIGAI_42_GPJ_500ML', 'DZCZ', 'DZSCZ', '66_POINTS', 'NO']
let gsapCtx = null
let shakeTimeline = null
let PRIZEDATA = null
const closeThis = () => {
initAnimateStyle()
emit("close")
}
const handleBtnMore = () => {
closeThis()
globalToastEvent.emit(ToastType.SHOW_AD)
}
const handleLotteryAction = () => {
//实物
closeThis()
if (activePrizeData.value.coupon_type === 'scene') {
globalToastEvent.emit(ToastType.SHOW_ADDRESS, activePrizeData.value.id)
}
}
onMounted(() => {
gsap.registerPlugin()
initAnimateStyle()
})
const initAnimateStyle = () => {
interval && clearInterval(interval)
interval = null
const list = [itemaRef.value, itembRef.value, itemcRef.value]
const randomHeight = [Phaser.Math.Between(3, 8), Phaser.Math.Between(3, 8), Phaser.Math.Between(3, 8)]
gsap.set(kapianBgRef.value, { y: '-72vw' })
gsap.set(btnRef.value, { scale: 0, display: 'none' })
gsap.set(tempRef.value, { height: '63.518519vw' })
list.forEach((v, idx) => {
gsap.set(v, { y: `-${randomHeight[idx] * GRID - GRID / PRIZE_LIST.length}vw`, height: `${randomHeight[idx] * GRID}vw` })
})
let keyframes = [];
const frames = 20; // 关键帧数量
const strength = 5; // 抖动强度
// 生成关键帧
for (let i = 0; i < frames; i++) {
keyframes.push({
x: gsap.utils.random(-strength, strength),
y: gsap.utils.random(-strength, strength),
duration: 0.05 // 每帧的持续时间
});
}
// 创建一个时间线,添加关键帧,并循环
shakeTimeline = gsap.timeline({ repeat: -1, paused: true });
shakeTimeline.to(cardRef.value, { duration: 0, x: 0, y: 0 }); // 初始位置
keyframes.forEach(keyframe => {
shakeTimeline.to(cardRef.value, keyframe);
});
shakeTimeline.to(cardRef.value, { duration: 0.1, x: 0, y: 0 })
gsap.set(guangyunRef.value, { scale: 0, opacity: 1 })
gsap.set(titleRef.value, { scaleY: 0 })
gsap.set(sceneRef.value, { scale: .5 })
gsap.set(cardRef.value, { rotateY: 0 })
btngroupShow.value = false
}
onMounted(() => {
gsap.set(btnRef.value, { display: "none", scale: 0 })
})
watch(() => props.show, async (newVal) => {
if (!newVal) {
return
}
const lottteryResult = await Request("lottery/draw", { pool: 'game', consume_type: 'points' })
// const lottteryResult = {
// res: { status: 200 },
// json: {
// code: "HEIGAI_42_GPJ_500ML",
// prize_code: 'HEIGAI_42_GPJ_500ML'
// }
// }
shakeTimeline.play()
//TODO: 延时测试,上限删掉
await Sleep(2000)
shakeTimeline.pause()
// const lottteryResult = await Request("lottery/draw", { pool: 'game', consume_type: 'points' })
// TODO: 测试数据
const lottteryResult = {
res: { status: 200 },
json: {
id: 0,
code: "HEIGAI_42_GPJ_500ML",
prize_code: 'HEIGAI_42_GPJ_500ML',
coupon_type: "scene",
name: "泸州老窖的一瓶酒"
}
}
if (lottteryResult.res.status !== 200) {
emit('close')
return
} else {
globalStore.consumeBingyin(globalStore.CONSUME_POINT_1_PER_DRAW)
PRIZEDATA = lottteryResult.json
globalStore.lotteryCut()
activePrizeData.value = lottteryResult.json
// 未中奖的情况
if (lottteryResult.json.code === 204) {
PRIZEDATA = { prize_code: 'NO', coupon_type: 'NO' }
activePrizeData.value = { prize_code: 'NO', coupon_type: 'NO' }
}
kapianCover.value = PRIZEDATA.prize_code === '66_POINTS' ? 'POINTS' : PRIZEDATA.prize_code
// kapianCover.value = PRIZEDATA.prize_code === '66_POINTS' ? 'POINTS' : PRIZEDATA.prize_code
}
gsapCtx = gsap.context(() => {
initAnimateStyle()
const prizeIndex = PRIZE_LIST.findIndex(v => v === PRIZEDATA.prize_code)
const durationArr = [Phaser.Math.Between(3, 9), Phaser.Math.Between(3, 9), Phaser.Math.Between(3, 9)]
gsap.to([itemaRef.value, itembRef.value, itemcRef.value], {
y: `-${GRID / PRIZE_LIST.length * prizeIndex}vw`,
ease: "expo.out",
duration: (idx) => {
return durationArr[idx]
},
onStart: () => {
laohujiSound.play()
laohujiSound.fade(1, 0, Math.max(...durationArr)*1000)
},
delay: .4,
const prizeshowTime = gsap.timeline({
onComplete: () => {
lotterySoundSuccess.play()
var duration = 4 * 1000;
var animationEnd = Date.now() + duration;
var defaults = { startVelocity: 30, spread: 360, ticks: 60, zIndex: 0 };
function randomInRange (min, max) {
return Math.random() * (max - min) + min;
}
interval = setInterval(function () {
var timeLeft = animationEnd - Date.now();
if (timeLeft <= 0) {
return clearInterval(interval);
}
var particleCount = 50 * (timeLeft / duration);
confetti({ ...defaults, particleCount, origin: { x: randomInRange(0.1, 0.3), y: Math.random() - 0.2 } });
confetti({ ...defaults, particleCount, origin: { x: randomInRange(0.7, 0.9), y: Math.random() - 0.2 } });
}, 250);
gsap.to(kapianBgRef.value, { y: '0', duration: 4, ease: "sine.inOut", })
gsap.to(tempRef.value, {
height: '+=90vw', duration: 4, ease: "sine.inOut", onComplete: () => {
gsap.set(btnRef.value, { display: "block" })
gsap.to(btnRef.value, { scale: 1, ease: "sine.inOut", duration: .3 })
}
})
btngroupShow.value = true
}
});
prizeshowTime.to(sceneRef.value, {
duration: .4,
scale: .2,
})
prizeshowTime.to(sceneRef.value, {
duration: 1,
scale: 1,
opacity: 1,
ease: "power4.out"
})
prizeshowTime.to(guangyunRef.value, {
duration: 1.5,
scale: 2,
}, "-=1")
prizeshowTime.to(cardRef.value, {
rotateY: 180 * 3,
duration: 1,
}, "-=1.4")
prizeshowTime.to(titleRef.value, {
scaleY: 1,
ease: "elastic.out(1,0.3)"
})
var duration = 4 * 1000;
var animationEnd = Date.now() + duration;
var defaults = { startVelocity: 30, spread: 360, ticks: 60, zIndex: 0 };
function randomInRange (min, max) {
return Math.random() * (max - min) + min;
}
interval = setInterval(function () {
var timeLeft = animationEnd - Date.now();
if (timeLeft <= 0) {
return clearInterval(interval);
}
var particleCount = 50 * (timeLeft / duration);
confetti({ ...defaults, particleCount, origin: { x: randomInRange(0.1, 0.3), y: Math.random() - 0.2 } });
confetti({ ...defaults, particleCount, origin: { x: randomInRange(0.7, 0.9), y: Math.random() - 0.2 } });
}, 250);
})
})
const handleGetLottery = () => {
emit('close', { coupon_type: PRIZEDATA.coupon_type })
initAnimateStyle()
if (PRIZEDATA.coupon_type === 'scene') {
emit('address', PRIZEDATA.id)
}
}
onUnmounted(() => {
shakeTimeline = null
gsapCtx && gsapCtx.revert()
})
</script>
<style scoped>
.laohuji {
.guang,
.guangyun {
position: absolute;
left: 50%;
margin-left: -66.2vw;
top: 50%;
margin-top: -64.5vw;
width: 129.62963vw;
height: 129.62963vw;
background-repeat: no-repeat;
background-size: 100%;
}
.guang {
background-image: url("../assets/images/guang.png");
animation: rotateGuang 20s linear infinite;
}
.guangyun {
background-image: url("../assets/images/guangyun.png");
/* animation: rotateGuangyun 3s linear infinite; */
}
.lottery-title {
position: absolute;
top: 24vw;
left: 50%;
transform: translateX(-50%);
width: 65.462963vw;
height: 19.907407vw;
background-image: url("../assets/images/lottery-title.png");
background-repeat: no-repeat;
background-size: 100%;
}
.lottery-name {
position: absolute;
bottom: 18vw;
text-align: center;
width: 100%;
font-size: 6vw;
font-weight: 700;
color: rgb(255, 255, 255);
text-shadow:
0 0 0.37037vw #ff0000,
0 0 0.740741vw #ff0000,
0 0 1.111111vw #ff0000,
0.092593vw 0.092593vw 0 #ff0000,
-0.092593vw -0.092593vw 0 #ff0000;
}
.lottery-btngroup {
position: absolute;
bottom: -24vw;
width: 100%;
display: flex;
justify-content: space-between;
}
.btn-more {
width: 48.703704vw;
height: 18.240741vw;
background-image: url("../assets/images/btn-more.png");
background-repeat: no-repeat;
background-size: 100%;
}
.btn-kaixin {
width: 48.703704vw;
height: 18.240741vw;
background-image: url("../assets/images/btn-kaixin.png");
background-repeat: no-repeat;
background-size: 100%;
}
.lottery-image {
position: absolute;
top: 45vw;
width: 100%;
height: 60vw;
background-position: center bottom;
background-repeat: no-repeat;
background-size: auto 100%;
}
.lottery-image.HEIGAI_42_GPJ_500ML {
background-image: url("../assets/images/HEIGAI_42_GPJ_500ML.png");
}
@keyframes rotateGuangyun {
0% {
transform: scale(.3);
opacity: 0;
}
50% {
transform: scale(1);
opacity: 1;
}
100% {
transform: scale(1.4);
opacity: 0;
}
}
@keyframes rotateGuang {
from {
transform: rotate(0deg);
}
to {
transform: rotate(-360deg);
}
}
.lottery-scene {
position: relative;
margin-top: -20vw;
width: 88.055556vw;
height: 148.796296vw;
}
.laohuji-temp {
width: 80.833333vw;
height: 63.518519vw;
.lottery-card {
position: absolute;
width: 100%;
height: 100%;
transform-style: preserve-3d;
}
.laohuji-top {
width: 80.833333vw;
height: 63.518519vw;
.lottery-card.flip {
transform: rotateY(180deg);
}
.lottery-face {
position: absolute;
top: 0;
left: 0;
background-image: url("../assets/images/laohuji-top.webp");
background-repeat: no-repeat;
background-size: 100% 100%;
width: 100%;
height: 100%;
backface-visibility: hidden;
}
.laohuji-bottom {
width: 80.833333vw;
height: 63.518519vw;
.lottery-card img {
width: 100%;
display: block;
}
.lottery-prize {
position: absolute;
top: 0;
left: 0;
background-image: url("../assets/images/laohuji-bottom.webp");
width: 100%;
height: 100%;
background-image: url("../assets/images/prize-bg.png");
background-repeat: no-repeat;
background-size: 100% 100%;
}
.laohuji-kapian {
position: absolute;
overflow: hidden;
top: 58vw;
left: 14.4vw;
}
.laohuji-kapian-bg {
width: 51.851852vw;
clip-path: rect(0px 51.851852vw 74vw 0px);
height: 72vw;
background-image: url("../assets/images/laohuji-kapian.webp");
background-position: left bottom;
background-repeat: no-repeat;
background-size: 100% 73.333333vw;
background-size: 100%;
backface-visibility: hidden;
transform: rotateY(180deg);
}
.close {
@@ -242,80 +385,4 @@ onUnmounted(() => {
background-repeat: no-repeat;
background-size: 100%;
}
.btn-kaixin {
width: 40.092593vw;
height: 15.555556vw;
position: absolute;
bottom: 0;
left: 50%;
margin-left: -20vw;
background-image: url("../assets/images/btn-kaixin.webp");
background-repeat: no-repeat;
background-size: 100%;
}
.laohuji-list {
position: absolute;
top: 31.5vw;
left: 14vw;
width: 53.6vw;
height: 18.425926vw;
background-color: #fff;
display: flex;
justify-content: space-between;
overflow: hidden;
}
.laohuji-item {
width: 16.296296vw;
height: 18.425926vw;
background-color: #ccc;
background-image: url("../assets/images/laohuji-item-1.webp");
background-repeat: repeat-y;
background-size: 16.296296vw 165.833333vw;
}
.laohuji-kapian-cover {
position: relative;
left: 3vw;
top: 13vw;
width: 45.555556vw;
height: 55.185185vw;
background-image: url("../assets/images/NO.webp");
background-repeat: no-repeat;
background-size: 100% 100%;
}
.laohuji-kapian-cover.TJGJ {
background-image: url("../assets/images/TJGJ.webp");
}
.laohuji-kapian-cover.XINCHUN_WEIZUN {
background-image: url("../assets/images/XINCHUN_WEIZUN.webp");
}
.laohuji-kapian-cover.TEQU_JL_52_60Y_100ML_2 {
background-image: url("../assets/images/TEQU_JL_52_60Y_100ML_2.webp");
}
.laohuji-kapian-cover.LZLJ_TEQU_LZH_52_100ML_2 {
background-image: url("../assets/images/LZLJ_TEQU_LZH_52_100ML_2.webp");
}
.laohuji-kapian-cover.HEIGAI_42_GPJ_500ML {
background-image: url("../assets/images/HEIGAI_42_GPJ_500ML.webp");
}
.laohuji-kapian-cover.DZCZ {
background-image: url("../assets/images/DZCZ.webp");
}
.laohuji-kapian-cover.DZSCZ {
background-image: url("../assets/images/DZSCZ.webp");
}
.laohuji-kapian-cover.POINTS {
background-image: url("../assets/images/66_POINTS.webp");
}
</style>

View File

@@ -27,7 +27,7 @@
</template>
<script setup>
import { ref } from "vue"
import { ref, watch } from "vue"
import { isWeixinPlatform, miniJumpToScene, getMiniPageBtnHack } from "../libs/utils"
import ModalTransition from "./ModalTransition.vue";
const props = defineProps({
@@ -37,7 +37,8 @@ const props = defineProps({
default: () => []
}
})
const emit = defineEmits(['address','close'])
const emit = defineEmits(['address', 'close'])
const sceneBtnHtml = ref('')
const couponBtnHtml = ref('')
sceneBtnHtml.value = getMiniPageBtnHack("/pages/unify/unify?orgId=200282401019674482&targetUrl=%2Fpages%2Fretail%2Forder%2Forder-list%3Ftab%3DAll%26topTab%3D1")
@@ -62,8 +63,8 @@ const handleItemBtn = (id, event) => {
.prizelist {
position: relative;
width: 100vw;
height: 140.740741vw;
background-image: url("../assets/images/prizelist-bg.webp");
height: 131.759259vw;
background-image: url("../assets/images/prizelist-bg.png");
background-repeat: no-repeat;
background-size: 100%;
display: flex;
@@ -72,7 +73,7 @@ const handleItemBtn = (id, event) => {
.prizelist-wrapper {
width: 100%;
height: 90vw;
height: 84vw;
overflow: auto;
}
@@ -87,12 +88,12 @@ const handleItemBtn = (id, event) => {
margin-bottom: 4vw;
margin-left: 2.5vw;
padding-left: 3vw;
width: 95.092593vw;
height: 19.814815vw;
width: 95.833333vw;
height: 20.648148vw;
flex-direction: row;
justify-content: space-between;
align-items: center;
background-image: url("../assets/images/prizelist-item-bg.webp");
background-image: url("../assets/images/prizelist-item-bg.png");
background-repeat: no-repeat;
background-size: 100% 100%;
}
@@ -121,10 +122,10 @@ const handleItemBtn = (id, event) => {
.prizelist-close {
position: absolute;
width: 8.148148vw;
height: 8.055556vw;
height: 8.148148vw;
right: 5vw;
top: 0;
background-image: url("../assets/images/icon-close.webp");
top: 15vw;
background-image: url("../assets/images/close-btn.png");
background-repeat: no-repeat;
background-size: 100%;
}
@@ -134,7 +135,7 @@ const handleItemBtn = (id, event) => {
width: 23.981481vw;
height: 9.074074vw;
background-size: 100% 100%;
background-image: url("../assets/images/btn-gotomember.webp");
background-image: url("../assets/images/btn-goto.png");
background-repeat: no-repeat;
background-size: 100%;
}
@@ -149,7 +150,7 @@ wx-open-launch-weapp,
}
.btn-goto.noaddress {
background-image: url("../assets/images/btn-address.webp");
background-image: url("../assets/images/btn-address.png");
}
.prizelist-cover.USER_TJGJ {

View File

@@ -25,8 +25,8 @@ const emit = defineEmits(['close'])
.rule-wrapper {
position: relative;
width: 100%;
height: 200vw;
background-image: url("../assets/images/rule-bg.webp");
height: 175.740741vw;
background-image: url("../assets/images/rule-bg.png");
background-repeat: no-repeat;
background-size: 100%;
}
@@ -48,10 +48,10 @@ const emit = defineEmits(['close'])
.close {
position: absolute;
width: 8.148148vw;
height: 8.055556vw;
height: 8.148148vw;
right: 5vw;
top: 10vw;
background-image: url("../assets/images/icon-close.webp");
top: 15vw;
background-image: url("../assets/images/close-btn.png");
background-repeat: no-repeat;
background-size: 100%;
}

View File

@@ -1,34 +1,17 @@
<template>
<div class="home-wrapper" style="z-index: 9;">
<img src="../assets/images/todo-bg.png" alt="任务列表背景图">
<div class="scene-item item-1" @click="closeTodoList">
<img src="../assets/images/close-btn.png" alt="关闭按钮">
</div>
<div class="scene-item item-2" @click="openQiwei($event)">
<img src="../assets/images/add-wx.png" alt="去添加">
</div>
<div class="scene-item item-3" @click="handleScan($event)">
<img src="../assets/images/scan-code.png" alt="去扫码">
</div>
<div class="scene-item item-4" @click="openHaibao($event)">
<img src="../assets/images/share-link.png" alt="去分享">
</div>
</div>
<ModalTransition class="todolist" :show="show">
<div class="todolist-wrapper">
<div class="btn-group">
<div class="btn-share" :class="globalStore.invitees >= globalStore.MAX_INVITE_DAILY && 'has'"
@click="openHaibao($event)"></div>
<div class="btn-qiwei" :class="globalStore.followed_official && 'has'" @click="openQiwei($event)"></div>
<div class="btn-scan" :class="globalStore.cap_scan >= globalStore.MAX_CAP_SCAN && 'has'"
@click="handleScan($event)"></div>
<div class="btn-peifang" :class="globalStore.game_chances_view_recipes >= globalStore.MAX_VIEW_RECIPES_DAILY && 'has'" @click="openPeifang($event)"></div>
<div class="btn-share" :class="globalStore.invitees >= globalStore.MAX_INVITE_DAILY && 'has'"
@click="openHaibao($event)"></div>
</div>
<div class="close" @click="$emit('close')"></div>
</div>
<div class="fullsection" v-show="haibaoShow">
<div class="haibao">
<div class="haibao" :style="userhaibaoCover">
<img :src="haibaoUrl" alt="">
<div class="close" @click="haibaoShow = false"></div>
</div>
@@ -36,7 +19,7 @@
<div class="fullsection" v-show="qiweiShow">
<div class="qiwei">
<img src="../assets/images/qiwei-bg.webp" alt="">
<img src="../assets/images/qiwei-bg.png" alt="">
<div class="close" @click="qiweiShow = false"></div>
</div>
</div>
@@ -44,38 +27,67 @@
</template>
<script setup>
import { ref } from "vue"
import { ref, computed } from "vue"
import { globalStore } from "@/globalstore";
import ModalTransition from "./ModalTransition.vue"
import { Storage, generateQR, isWeixin, isMiniPage } from "../libs/utils"
import Haibao from "@/libs/haibao"
import bg from "../assets/images/haibao-bg.webp"
import userPicture from "../assets/images/home-bg.png" //TODO: 这里得图片后面要换成用户参榜的图片
import bg from "../assets/images/haibao-bg.png"
import mask from "../assets/images/haibao-mask.png"
import haibaoCoverBorder from "../assets/images/haibao-cover.png"
const props = defineProps({
show: true,
show: false,
})
const emit = defineEmits(['close','open'])
const emit = defineEmits(['close', 'open'])
const shareShow = ref(false)
const qiweiShow = ref(false)
const haibaoShow = ref(false)
const haibaoUrl = ref('')
const userHaibaoUrl = ref('')
const userhaibaoCover = computed(() => {
return { backgroundImage: `url(${userHaibaoUrl.value})` }
})
const handleHaibao = async () => {
if (haibaoUrl.value) {
return
}
const loading = weui.loading()
const infos = Storage.get("userinfos")
const haibao = new Haibao(1080, 2160)
const qrcode = await generateQR(`fromid=${infos.invite_code}&org_id=${infos.org_id}`)
haibao.add(bg, 0, 0)
haibao.add(qrcode, 802, 1908)
haibao.generate().then(url => {
haibaoUrl.value = url
loading.hide()
}).catch(err => {
weui.alert("海报生成失败,请重新生成")
const haibaoCover = new Haibao(951, 1607)
haibaoCover.add(userPicture, 0, 0)
haibaoCover.add(mask, 10, 100)
haibaoCover.add(haibaoCoverBorder, 0, 0)
haibaoCover.draw('destination-in').then(() => {
haibaoCover.generate({ mimeType: 'image/png' }).then(async (url) => {
userHaibaoUrl.value = url
const haibaoSave = new Haibao(1080, 2160)
const qrcode = await generateQR(`fromid=${infos.invite_code}&org_id=${infos.org_id}`, 200, 200)
haibaoSave.add(url, 62, 350)
haibaoSave.add(bg, 0, 0)
haibaoSave.add(qrcode, 115, 1875)
haibaoSave.draw().then(() => {
haibaoSave.text(infos.nickname, haibaoSave.canvas.width / 2, 200, { font: 'bold 50px Arial', color: '#ffee6f' })
haibaoSave.generate({ mimeType: 'image/png' }).then(url => {
haibaoUrl.value = url
loading.hide()
}).catch(err => {
console.log(err)
weui.alert("海报生成失败,请重新生成")
loading.hide()
})
}).catch(err => {
console.log(err)
weui.alert("海报生成失败,请重新生成")
loading.hide()
})
})
})
}
const openQiwei = (e) => {
const target = e.currentTarget
@@ -101,7 +113,7 @@ const openPeifang = (e) => {
if (target.classList.contains("has")) {
return
}
emit('open',{ type: 'peifang' })
emit('open', { type: 'peifang' })
}
const handleScan = (e) => {
const target = e.currentTarget
@@ -131,11 +143,13 @@ const handleScan = (e) => {
position: relative;
min-height: -webkit-fill-available;
}
.home-wrapper img {
width: 100%;
background-size: cover;
background-repeat: no-repeat;
}
.scene-item {
position: absolute;
z-index: 2;
@@ -196,8 +210,8 @@ const handleScan = (e) => {
.qiwei {
position: relative;
width: 71.851852vw;
height: 89.259259vw;
width: 80.740741vw;
/* height: 89.259259vw; */
}
.qiwei img {
@@ -227,15 +241,6 @@ const handleScan = (e) => {
background-size: 100%;
}
.haibao .close {
right: -10vw;
}
.qiwei .close {
right: -10vw;
}
.haibao img {
width: 100%;
height: 100%;
@@ -246,19 +251,32 @@ const handleScan = (e) => {
.close {
position: absolute;
width: 8.148148vw;
height: 8.055556vw;
height: 8.148148vw;
right: 5vw;
top: 0;
background-image: url("../assets/images/icon-close.webp");
top: 15vw;
background-image: url("../assets/images/close-btn.png");
background-repeat: no-repeat;
background-size: 100%;
}
.haibao .close {
left: 50%;
bottom: -5vw;
top: initial;
transform: translate3d(-50%,0,0);
}
.qiwei .close {
right: 50%;
top: 90vw;
margin-right: -4vw;
}
.todolist-wrapper {
position: relative;
width: 100vw;
height: 136.018519vw;
background-image: url("../assets/images/todo-bg.webp");
height: 123.333333vw;
background-image: url("../assets/images/todo-bg.png");
background-repeat: no-repeat;
background-size: 100%;
}
@@ -266,23 +284,23 @@ const handleScan = (e) => {
.btn-group {
position: absolute;
right: 6vw;
top: 46vw;
width: 23.981481vw;
height: 84vw;
top: 45vw;
width: 24.907407vw;
height: 70vw;
display: flex;
flex-direction: column;
justify-content: space-around;
}
.btn-group div {
width: 23.981481vw;
height: 9.074074vw;
width: 24.907407vw;
height: 10vw;
background-repeat: no-repeat;
background-size: 100%;
}
.btn-share {
background-image: url("../assets/images/btn-share.webp");
background-image: url("../assets/images/share-link.png");
}
.btn-share.has {
@@ -290,7 +308,7 @@ const handleScan = (e) => {
}
.btn-qiwei {
background-image: url("../assets/images/btn-qiwei.webp");
background-image: url("../assets/images/add-wx.png");
}
.btn-qiwei.has {
@@ -298,15 +316,10 @@ const handleScan = (e) => {
}
.btn-scan {
background-image: url("../assets/images/btn-scan.webp");
background-image: url("../assets/images/scan-code.png");
}
.btn-scan.has {
background-image: url("../assets/images/btn-max.webp");
}
.btn-peifang {
background-image: url("../assets/images/btn-look.webp");
}
.btn-peifang.has {
background-image: url("../assets/images/btn-max.webp");
}
</style>