灯笼选择页面及海报生产

This commit is contained in:
梁泽军 2025-01-15 16:27:44 +08:00
parent cc3a3df9bc
commit c55d13ebeb
43 changed files with 851 additions and 335 deletions

View File

@ -18,6 +18,7 @@
"pinia": "^2.1.7",
"qrcode": "^1.5.3",
"qs": "^6.11.2",
"swiper": "^11.2.1",
"vant": "^3.6.12",
"vconsole": "^3.15.1",
"vue": "^3.2.41",

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 432 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 802 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 285 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 635 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 373 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -184,7 +184,7 @@ const showVC = () => {
.index-pet{
pointer-events: none;
@include pos(234px, 386px, 353px, 614px);
@include pos(378px, 452px, 187px, 614px);
@include bg_pos("index/pet-icon.png");
}

View File

@ -7,64 +7,53 @@ import { useMainStore } from "@/store";
import { subAnswer } from "@/api";
//
const emit = defineEmits(["QuestionPage"]);
const emit = defineEmits(["hide", "showResult"]);
const userStore = useMainStore();
const props = defineProps({
questionId: {
default: 0,
required: true,
}
})
//
const currentId = ref(0); //id 0~11
const currentId = ref(props.questionId); //id 0~11
const questionList = ref(data); //
const answerList = ref([]); //
const activeId = ref(""); //
const showResultBtn = ref(false);
const isChecked = ref(false)
//
const answerFn = (item, event) => {
let e = event.target.parentElement;
activeId.value = item.aid; //
console.log('选项', item);
console.log('当前题目:', currentId.value + 1);
debounceTap(e, () => {
let cid = questionList.value[currentId.value].id;
let has = answerList.value.findIndex((obj) => obj.id === cid);
//
if (has == -1) {
answerList.value.push({
id: cid,
aid: item.aid,
answer: item.text,
});
} else {
answerList.value[has].aid = item.aid;
answerList.value[has].answer = item.text;
}
gsap.set('.option-tips,.analysis', { autoAlpha: 1 })
gsap.set('.answer-box', { pointerEvents: 'none' })
isChecked.value = true
console.log('currentId.value',currentId.value);
if(currentId.value == 2 ){
if (item.result === 'correct') {
gsap.set('.create-btn', { display: 'block' })
}else{
gsap.set('.next-btn', { display: 'block' })
} else {
gsap.set('.return-btn', { display: 'block' })
}
})
}
//
const nextQuestion = (event) => {
let e = event.target;
debounceTap(e, () => {
isChecked.value = false
gsap.set('.option-tips,.analysis', { autoAlpha: 0 })
currentId.value++
activeId.value = ''
gsap.set('.answer-box', { pointerEvents: 'initial' })
gsap.set('.next-btn', { display: 'none' })
gsap.to('.question-box', {
duration: 0.5, autoAlpha: 0, scale: 0.3, onComplete: () => {
emit('hide')
}
})
})
@ -74,8 +63,9 @@ const nextQuestion = (event) => {
const viewResult = (event) => {
let e = event.target;
debounceTap(e, () => {
// id
userStore.updatePosterId(getRandomNumber([1, 2, 3]))
// id
userStore.posterId = currentId.value + 1
gsap.set('.question-box', { pointerEvents: 'none' })
Toast('答题结束')
Toast.loading({
@ -106,7 +96,7 @@ const viewResult = (event) => {
Toast.clear()
gsap.to('.QuestionPage', {
duration: 0.5, autoAlpha: 0, onComplete: () => {
emit("QuestionPage", { action: "showResult" });
emit("showResult", { pid: currentId.value });
}
})
}, 1000)
@ -114,32 +104,19 @@ const viewResult = (event) => {
})
}
//
const getRandomNumber = (arr) => {
var randomIndex = Math.floor(Math.random() * arr.length);
return arr[randomIndex];
}
onMounted(() => {
gsap.from('.question-bg', { duration: 0.5, autoAlpha: 0, })
gsap.from('.question-box', { duration: 0.5, scale: 0.4, autoAlpha: 0, })
gsap.to('.question-lantern-icon', { duration: 5, transformOrigin: '100% 0%', rotation: '10deg', repeat: -1, yoyo: true, ease: 'none' })
});
</script>
<template>
<div class="QuestionPage" @touchmove.prevent>
<div class="question-bg">
<div class="bottom-fan-1"></div>
<div class="bottom-fan-2"></div>
<div class="question-bottom-bg"></div>
</div>
<div class="question-bg"></div>
<div class="question-container">
<div class="container-fan-1"></div>
<div class="container-fan-2"></div>
<div class="question-box">
<!-- 问题序号 -->
@ -150,7 +127,7 @@ onMounted(() => {
<div class="question-text" v-for="item in questionList[currentId].question" :key="item">
{{ item }}
</div>
<div class="question-tips">打一系列产品</div>
<div class="question-tips">打一个字</div>
</div>
<!-- 选项 -->
<div class="answer-box">
@ -169,20 +146,20 @@ onMounted(() => {
</div>
</div>
<!-- 解析 -->
<div class="analysis" >
<div v-for="li in questionList[currentId].analysis" :key="li">{{li}}</div>
<div class="analysis">
<div v-for="li in questionList[currentId].analysis" :key="li">
提示<span v-html="li"></span>
</div>
<div class="next-btn" @click="nextQuestion($event)"></div>
</div>
<div class="return-btn" @click="nextQuestion($event)"></div>
<div class="create-btn" @click="viewResult($event)"></div>
</div>
<div class="answer-larnten"></div>
<div class="answer-baozhu"></div>
</div>
<div class="question-lantern-icon"></div>
<div class="question-gold-icon-1"></div>
<div class="question-gold-icon-2"></div>
</div>
<!-- 进度条 -->
<Progress :percentage="(currentId + 1) / 3 * 100" pivot-color="#7232dd" :show-pivot="false"
color="linear-gradient(to right, rgb(255 153 153), rgb(221 50 50))" />
</div>
</template>
@ -194,26 +171,7 @@ onMounted(() => {
.question-bg {
@include pos(750px, 1624px, 0px, 50%);
transform: translateY(-50%);
@include bg_pos('qa/bg.jpg');
.question-bottom-bg {
pointer-events: none;
@include box(750px, 393px);
position: absolute;
left: 0px;
bottom: 0px;
@include bg_pos("qa/bottom-bg.png");
}
.bottom-fan-1 {
@include pos(370px, 334px, 545px, 1022px);
@include bg_pos('index/fan-3.png');
}
.bottom-fan-2 {
@include pos(350px, 205px, 494px, 1128px);
@include bg_pos('index/fan-4.png');
}
background-color: rgba($color: #000000, $alpha: 0.6);
}
@ -223,29 +181,31 @@ onMounted(() => {
@include flexCen();
.question-lantern-icon {
// pointer-events: none;
pointer-events: none;
@include pos(349px, 443px, 489px, 49px);
@include bg_pos('qa/lantern-icon.png');
}
.container-fan-1 {
pointer-events: none;
@include pos(235px, 574px, 0px, 60px);
@include bg_pos("index/fan-1.png");
}
.container-fan-2 {
pointer-events: none;
@include pos(316px, 317px, -205px, 405px);
@include bg_pos("index/fan-2.png");
}
.question-box {
@include pos(656px, 913px, 47px, 339px);
@include pos(616px, 873px, 68px, 350px);
@include bg_pos("qa/question-box.png");
.answer-larnten {
@include pos(310px, 526px, -120px, -120px);
@include bg_pos('qa/lantern-icon.png');
pointer-events: none
}
.answer-baozhu {
@include pos(145px, 167px, 507px, 725px);
@include bg_pos('qa/baozhu.png');
pointer-events: none
}
.qa-number {
@include pos(100px, 56px, 278px, 89px);
@include pos(100px, 56px, 255px, 79px);
font-size: 40px;
font-style: italic;
color: #c61a1a;
@ -256,7 +216,7 @@ onMounted(() => {
}
.qa-question-box {
@include pos(570px, 700px, 43px, 194px);
@include pos(570px, 700px, 22px, 194px);
display: flex;
flex-direction: column;
// justify-content: space-around;
@ -301,6 +261,9 @@ onMounted(() => {
justify-content: space-between;
height: 200px;
//
.correct-bg {
border: 1px solid rgb(255, 238, 186) !important;
@ -334,7 +297,8 @@ onMounted(() => {
.answer {
@include box(476px, 92px);
@include box(350px, 92px);
position: relative;
border-radius: 47.5px;
border: 2px solid rgb(255, 225, 172);
@ -346,7 +310,7 @@ onMounted(() => {
align-items: center;
.click-area {
@include pos(476px, 92px, 0px, 0px);
@include pos(350px, 92px, 0px, 0px);
border-radius: 47.5px;
}
@ -369,7 +333,7 @@ onMounted(() => {
.answer-text-box {
@include box(335px, 100%);
@include box(270px, 100%);
font-family: 'HarmonyOS_Sans_SC_Regular';
color: #ffe2ad;
font-size: 28px;
@ -394,13 +358,12 @@ onMounted(() => {
//
.analysis {
visibility: hidden;
// visibility: hidden;
width: 95%;
font-family: 'HarmonyOS_Sans_SC_Regular';
font-size: 20px;
color: #ffe2ad;
color: #ffffff;
text-align: center;
// padding: 20px;
height: 100px;
display: flex;
justify-content: center;
@ -408,17 +371,17 @@ onMounted(() => {
flex-direction: column;
}
.next-btn{
@include box(234px,65px);
@include bg_pos("qa/next-btn.png");
.return-btn {
@include box(246px, 73px);
@include bg_pos("qa/go-back.png");
display: none;
}
.create-btn{
@include box(234px,65px);
.create-btn {
@include box(246px, 73px);
@include bg_pos("qa/create-btn.png");
display: none;
}
}
@ -430,11 +393,7 @@ onMounted(() => {
@include bg_pos("qa/gold-icon.png");
}
.question-gold-icon-2 {
pointer-events: none;
@include pos(276px, 241px, -70px, 1089px);
@include bg_pos("qa/gold-icon-2.png");
}
}
}

View File

@ -0,0 +1,299 @@
<template>
<div class="QuestionList">
<div class="question-list-bg"></div>
<div class="question-list-container">
<div class="ql--top-icon-1"></div>
<div class="ql--top-icon-3"></div>
<div class="ql--top-icon-2"></div>
<div class="ql--bottom-icon-2"></div>
<div class="ql--bottom-icon-1"></div>
<div class="ql--bottom-gift-2"></div>
<div class="ql--bottom-gift-1"></div>
<div class="ql-select-text">
<div class="select-text">选择一个你喜欢的花灯</div>
<div class="select-text">开始猜谜吧</div>
</div>
<div class="ql-swiper-box">
<div class="larnten-box-firework"></div>
<div class="larnten-box"></div>
<swiper class="larnten-swiper" :slides-per-view="1" :space-between="30" navigation :loop="true">
<swiper-slide v-for="item in 11"
:style="{ width: '100%', display: 'flex', justifyContent: 'center', }">
<div class="larnten-slide" :class="'larnten-slide-' + item">
<img class="larnten-img" :class="'larnten-img-' + item" :src="getLarntenImg(item)" alt=""
srcset="">
</div>
</swiper-slide>
</swiper>
</div>
<div class="ql-start-btn" @click="onShowQuestion"></div>
<div class="ql-bottom-bg"></div>
</div>
</div>
<Question v-if="showQuestion" :question-id="questionId" @showResult="onShowResult" @hide="showQuestion = false" />
</template>
<script setup>
import { register } from 'swiper/element/bundle';
import { Swiper, SwiperSlide } from 'swiper/vue';
import 'swiper/css';
import 'swiper/css/navigation';
import Question from './Question.vue';
const emit = defineEmits(['QuestionList', "showResult"]);
const showQuestion = ref(false)
const questionId = ref(1)
//
function getLarntenImg(item) {
return new URL(`../assets/images/question-list/larnten-${item}.png`, import.meta.url).href
}
const onShowQuestion = () => {
// 1-11
const swiper = document.querySelector('.larnten-swiper').swiper;
// swiperloop
const activeIndex = swiper.realIndex + 1;
console.log('activeIndex', activeIndex);
questionId.value = activeIndex - 1
showQuestion.value = true
// emit('QuestionList', activeIndex);
}
//
const onShowResult = (result) => {
emit('showResult', result)
showQuestion.value = false
}
register();
const hidiQuestion = () => {
showQuestion.value = false
}
defineExpose({
hidiQuestion
})
</script>
<style lang='scss' scoped>
.QuestionList {
@include pos(100%, 100vh, 0px, 0px);
overflow: hidden;
background: linear-gradient(135deg, #a11b15, #f80c00);
.question-list-bg {
@include pos(750px, 1624px, 0px, 50%);
transform: translateY(-50%);
@include bg_pos("question-list/bg.jpg");
}
.question-list-container {
@include pos(750px, 1624px, 0px, 50%);
transform: translateY(-50%);
.ql-select-text {
font-family: 'DouyinSansBold';
position: absolute;
width: 100%;
top: 307px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
.select-text {
line-height: 50px;
font-size: 33px;
color: rgb(255, 255, 255);
font-weight: bold;
text-shadow: 0.675px 2.923px 6px rgba(164, 18, 14, 0.004);
}
}
.ql-swiper-box {
@include pos(655px, 778px, 49px, 448px);
// background-color: aliceblue;
// overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
// pointer-events: none;
.larnten-box {
@include pos(428px, 639px, 113.5px, 0px);
@include bg_pos("question-list/box.png");
}
.larnten-box-firework {
@include pos(102px, 109px, 451.5px, 20px);
@include bg_pos("question-list/firework-icon.png");
}
.larnten-swiper {
@include box(655px, 778px);
position: relative;
// display: flex;
// align-items: center;
// justify-content: center;
.larnten-slide {
pointer-events: none;
}
.larnten-slide-1 {
@include box(527px, 697px);
}
.larnten-slide-2 {
@include box(482px, 743px);
}
.larnten-slide-3 {
@include box(478px, 714px);
}
.larnten-slide-4 {
@include box(441px, 722px);
}
.larnten-slide-5 {
@include box(473px, 778px);
}
.larnten-slide-6 {
@include box(437px, 751px);
}
.larnten-slide-7 {
@include box(478px, 731px);
}
.larnten-slide-8 {
@include box(446px, 743px);
}
.larnten-slide-9 {
@include box(481px, 691px);
}
.larnten-slide-10 {
@include box(460px, 713px);
}
.larnten-slide-11 {
@include box(383px, 756px);
}
.larnten-img {
@include box(100%, 100%);
pointer-events: none;
}
}
}
.ql--top-icon-1 {
pointer-events: none;
@include pos(405px, 659px, -193px, -213px);
@include bg_pos("question-list/icon-1.png");
}
.ql--top-icon-2 {
pointer-events: none;
@include pos(412px, 240px, 503px, -55px);
@include bg_pos("question-list/icon-2.png");
}
.ql--top-icon-3 {
pointer-events: none;
@include pos(300px, 434px, 611px, -71px);
@include bg_pos("question-list/icon-3.png");
}
.ql-bottom-bg {
pointer-events: none;
@include pos(750px, 374px, 0px, 1250px);
@include bg_pos("question-list/bottom-bg.png");
}
.ql--bottom-icon-1 {
pointer-events: none;
@include pos(293px, 292px, -186px, 1109px);
@include bg_pos("question-list/bottom-icon-1.png");
}
.ql--bottom-icon-2 {
pointer-events: none;
@include pos(698px, 497px, -287px, 1130px);
@include bg_pos("question-list/bottom-icon-2.png");
}
.ql--bottom-gift-1 {
pointer-events: none;
@include pos(144px, 145px, 512px, 1215px);
@include bg_pos("question-list/gift-1.png");
}
.ql--bottom-gift-2 {
pointer-events: none;
@include pos(184px, 188px, 611px, 1129px);
@include bg_pos("question-list/gift-2.png");
}
.ql-start-btn {
@include pos(319px, 93px, 235.5px, 1150px);
@include bg_pos("index/start-btn.png");
z-index: 99;
}
}
/* 自定义 Swiper 左右按钮样式 */
::v-deep .swiper-button-next,
::v-deep .swiper-button-prev {
color: white;
/* 设置按钮颜色 */
// background-color: rgba(0, 0, 0, 0.5); /* */
// border-radius: 50%; /* */
@include box(59px, 81px);
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 50%;
transform: translateY(-50%);
}
::v-deep .swiper-button-next::after,
::v-deep .swiper-button-prev::after {
font-size: 24px;
/* 设置按钮图标大小 */
opacity: 0;
}
::v-deep .swiper-button-prev {
// left: 20px; /* */
@include bg_pos("question-list/left-arrow.png");
}
::v-deep .swiper-button-next {
// right: 20px; /* */
@include bg_pos("question-list/right-arrow.png");
// right: 0px;
}
}
</style>

View File

@ -2,7 +2,7 @@
import { gsap } from "gsap";
import { debounceTap } from "@/plugins";
import { useMainStore } from "@/store";
import { posterCreate } from "@/plugins";
import { Toast } from "vant";
import QRCode from "qrcode";
import { reactive } from "vue";
@ -12,83 +12,92 @@ const emit = defineEmits(["ResultPage"]);
const userStore = useMainStore();
const posterId = ref(userStore.posterId); //id14
console.log('海报id', posterId.value);
const posterImgList = reactive([
new URL(`../assets/images/result/poster-1.jpg`, import.meta.url).href,
new URL(`../assets/images/result/poster-2.jpg`, import.meta.url).href,
new URL(`../assets/images/result/poster-3.jpg`, import.meta.url).href,
new URL(`../assets/images/result/poster-4.jpg`, import.meta.url).href,
])
//
const eqcodePic = ref();
onMounted(() => {
console.log('posterId:',posterId.value);
let eqCodeUrl = import.meta.env.VITE_URL;
QRCode.toDataURL(eqCodeUrl)
.then((url) => {
eqcodePic.value = url;
// console.log("eq", eqcodePic.value);
})
.catch((err) => {
console.error(err);
});
onMounted(async () => {
gsap.from(".result-bg", {
//
await executeTasks();
});
//
const executeTasks = async () => {
console.log("二维码生成中...");
//
const eqCodeUrl = import.meta.env.VITE_URL;
eqcodePic.value = await QRCode.toDataURL(eqCodeUrl);
console.log("生成海报中...");
//
console.log('pid', posterImgList[posterId.value - 1]);
if (posterImgList[posterId.value - 1] && eqcodePic.value) {
await posterCreate(
{ width: 750, height: 1334 },
[
{ name: "bg", src: posterImgList[posterId.value - 1], pos: { w: 750, h: 1334, x: 0, y: 0 } },
{ name: "eqcode", src: eqcodePic.value, pos: { w: 164, h: 164, x: 159, y: 1122 } },
]
);
}else{
Toast.fail({message:'生成失败'})
emit("ResultPage",{action: 'hide'})
}
};
const showPoster = () => {
gsap.to(".posterPop", {
duration: 0.3,
autoAlpha: 1,
});
gsap.from(".cls-btn-box", {
duration: 0.7,
scale: 1.2,
autoAlpha: 0,
});
gsap.from(".result-larnten-box", {
gsap.from(".poster-box", {
duration: 0.7,
scale: 1.4,
autoAlpha: 0,
});
gsap.from(".result-larnten", {
gsap.from(".save-tips", {
duration: 0.7,
scale: 0.7,
autoAlpha: 0,
});
gsap.from(".result-blessing-1", {
gsap.from(".go-draw", {
duration: 0.7,
y: -30,
autoAlpha: 0,
delay:0.5
delay: 0.5
});
gsap.from(".result-blessing-2", {
gsap.from(".go-share", {
duration: 0.7,
y: -30,
autoAlpha: 0,
delay:0.7
delay: 0.7
});
gsap.from(".result-product", {
duration: 0.7,
y: -30,
autoAlpha: 0,
delay:1
});
gsap.from(".result-tips", {
duration: 0.7,
y: -30,
autoAlpha: 0,
delay:1.2
});
gsap.from(".create-poster", {
duration: 0.7,
y: -30,
autoAlpha: 0,
delay:1.4,
onComplete:()=>{
// gsap.to('.result-larnten',{duration:5,transformOrigin:'50% 0%',rotation:'10deg',repeat:-1,yoyo:true,ease:'none'})
let gl = gsap.timeline({repeat:-1,yoyo:true})
gl.to('.result-larnten',{duration:1,transformOrigin:'50% 0%',rotation:'3deg',ease:'none'})
gl.to('.result-larnten',{duration:1,transformOrigin:'50% 0%',rotation:'0deg',ease:'none'})
gl.to('.result-larnten',{duration:1,transformOrigin:'50% 0%',rotation:'-3deg',ease:'none'})
// gsap.fo('.result-larnten',{duration:5,transformOrigin:'50% 0%',rotation:'10deg',repeat:-1,yoyo:true,ease:'none'})
}
});
});
}
//
const createPoster = (event) => {
@ -102,7 +111,7 @@ const createPoster = (event) => {
//
{
name: "bg",
src: posterImgList[posterId.value-1],
src: posterImgList[posterId.value - 1],
pos: { w: 750, h: 1334, x: 0, y: 0 },
},
//
@ -135,7 +144,12 @@ const goDraw = (event) => {
const hidePop = (event) => {
let e = event.target;
debounceTap(e, () => {
gsap.to(".posterPop", { duration: 0.5, autoAlpha: 0 });
gsap.to(".posterPop", {
duration: 0.5, autoAlpha: 0,
onComplete: () => {
emit('ResultPage', { action: 'hide' })
}
});
});
};
@ -151,32 +165,87 @@ const goShare = (event) => {
const hideShare = () => {
gsap.to(".sharePop", { duration: 0.5, autoAlpha: 0 });
};
//
const posterCreate = (option, imageArr) => {
let posterUrl = ''
const { width, height } = option
Toast.loading({
message: '海报生成中',
duration: 0,
forbidClick: true
})
let mycanvas = document.createElement('canvas') // canvas
let ctx = mycanvas.getContext('2d')
mycanvas.style.width = `${width}px`; //canvas
mycanvas.style.height = `${height}px`; //canvas
mycanvas.width = width
mycanvas.height = height
//Promise
let loader_p = [];
imageArr.map((item) => {
const _p = new Promise(resolve => {
const img = new Image();
img.crossOrigin = 'Anonymous'
img.onload = () => {
resolve(img)
};
img.src = item.src;
});
loader_p.push(_p);
})
//Promise.all
Promise.all(loader_p)
.then(imgList => {
//
imgList.map((item, index) => {
ctx.drawImage(item, imageArr[index].pos.x, imageArr[index].pos.y, imageArr[index].pos.w, imageArr[index].pos.h); //canvas `js drawImage`
})
//
return mycanvas.toDataURL('image/jpeg', 1);
})
.then(baseURL => {
//DOM
let posterImg = document.querySelector('#posterSrc')
posterImg.src = baseURL
setTimeout(() => {
//
showPoster();
Toast.success({ message: '生成成功!' })
}, 500)
})
.catch(error => {
console.error("生成海报失败");
gsap.to(".posterPop", {
duration: 0.5,
autoAlpha: 0,
onComplete: () => {
emit('ResultPage', { action: 'hide' })
}
});
Toast.fail({ message: '生成失败,请重试!' });
});
// return posterUrl
}
</script>
<template>
<div class="ResultPage" @touchmove.prevent>
<div class="result-bg"></div>
<div class="result-container">
<div class="result-larnten-box" :class="'larnten-box-'+posterId"></div>
<div class="result-larnten" :class="'larnten-'+posterId"></div>
<!-- 新年祝福语 -->
<div class="result-blessing-1" :class="'blessing-'+posterId+'-1'"></div>
<div class="result-blessing-2" :class="'blessing-'+posterId+'-2'"></div>
<!-- 产品 -->
<div class="result-product" :class="'product-'+posterId"></div>
<!-- 提示语 -->
<div class="result-tips"></div>
<!-- 生成海报按钮 -->
<div class="create-poster" @click="createPoster($event)"></div>
</div>
</div>
<!-- 海报弹窗 -->
<div class="posterPop" @touchmove.prevent>
<div class="cls-btn-box">
<div class="cls-btn" @click="hidePop($event)"></div>
</div>
<div class="poster-box">
<div class="poster" :class="'poster-'+posterId">
<div class="poster" :class="'poster-' + posterId">
<img id="posterSrc" src="" alt="" srcset="">
</div>
</div>
@ -197,94 +266,101 @@ const hideShare = () => {
<style lang="scss" scoped>
.ResultPage {
@include fixed();
background-color: azure;
visibility: hidden;
.result-bg {
@include pos(750px, 1624px, 0px, 50%);
@include bg_pos("result/bg.jpg");
transform: translateY(-50%);
pointer-events: none;
background-color: rgba($color: #000000, $alpha: 0.6);
}
.result-container {
@include pos(750px, 1624px, 0px, 50%);
transform: translateY(-50%);
.larnten-box-1{
.larnten-box-1 {
@include pos(437px, 809px, 283px, 181px);
@include bg_pos("result/larnten-box-1.png");
}
.larnten-box-2{
.larnten-box-2 {
@include pos(423px, 790px, 304px, 178px);
@include bg_pos("result/larnten-box-2.png");
}
.larnten-box-3{
.larnten-box-3 {
@include pos(447px, 807px, 280px, 170px);
@include bg_pos("result/larnten-box-3.png");
}
.larnten-1{
.larnten-1 {
@include pos(397px, 787px, 315px, 297px);
@include bg_pos("result/larnten-1.png");
}
.larnten-2{
.larnten-2 {
@include pos(444px, 771px, 306px, 302px);
@include bg_pos("result/larnten-2.png");
}
.larnten-3{
.larnten-3 {
@include pos(472px, 789px, 278px, 285px);
@include bg_pos("result/larnten-3.png");
}
.blessing-1-1{
.blessing-1-1 {
@include pos(86px, 565px, 70px, 347px);
@include bg_pos("result/blessing-text-1-1.png");
}
.blessing-1-2{
.blessing-1-2 {
@include pos(82px, 561px, 165px, 347px);
@include bg_pos("result/blessing-text-1-2.png");
}
.blessing-2-1{
.blessing-2-1 {
@include pos(86px, 563px, 70px, 347px);
@include bg_pos("result/blessing-text-2-1.png");
}
.blessing-2-2{
.blessing-2-2 {
@include pos(88px, 565px, 165px, 347px);
@include bg_pos("result/blessing-text-2-2.png");
}
.blessing-3-1{
.blessing-3-1 {
@include pos(86px, 568px, 70px, 347px);
@include bg_pos("result/blessing-text-3-1.png");
}
.blessing-3-2{
.blessing-3-2 {
@include pos(87px, 563px, 165px, 347px);
@include bg_pos("result/blessing-text-3-2.png");
}
.result-product{
.result-product {
@include pos(619px, 138px, 65px, 1015px);
}
.product-1{
.product-1 {
@include bg_pos("result/product-1.png");
}
.product-2{
.product-2 {
@include bg_pos("result/product-2.png");
}
.product-3{
.product-3 {
@include bg_pos("result/product-3.png");
}
.result-tips{
.result-tips {
@include pos(645px, 71px, 52px, 1183px);
@include bg_pos("result/text.png");
}
.create-poster{
.create-poster {
@include pos(237px, 80px, 257px, 1284px);
@include bg_pos("result/create-btn.png");
}
@ -326,18 +402,22 @@ const hideShare = () => {
.poster {
@include box(100%, 100%);
overflow: hidden;
#posterSrc{
#posterSrc {
@include box(100%, 100%);
opacity: 0;
}
}
.poster-1{
.poster-1 {
@include bg_pos("result/preveiw-1.png");
}
.poster-2{
.poster-2 {
@include bg_pos("result/preveiw-2.png");
}
.poster-3{
.poster-3 {
@include bg_pos("result/preveiw-3.png");
}
}

View File

@ -21,7 +21,7 @@ onMounted(() => {
gsap.from(".RulePage", { duration: 0.2, autoAlpha: 0 });
gsap.from(".rule-container", { duration: 0.5, autoAlpha: 0, scale: 0.7 });
gsap.to(".rule-arrow", { duration: 2.5, y: 10,repeat:-1,yoyo:true });
gsap.to(".rule-arrow", { duration: 2.5, y: 10, repeat: -1, yoyo: true });
});
</script>
@ -33,7 +33,7 @@ onMounted(() => {
<div class="rule-text-area wrapper">
<div>
<div class="part">
<div>活动时间2024年2月23日2月25</div>
<div>活动时间2025年2月12日2月14</div>
<div>活动奖励微信红包</div>
</div>
<div class="part">
@ -46,7 +46,9 @@ onMounted(() => {
<div class="part">
<div>领奖说明</div>
<div>
1中奖后在中奖页面复制兑换码前往<span class="blod">[平安理财服务号]</span>消息框输入元宵快乐获取兑换链接进入链接输入兑换码兑换奖品如关闭了中奖界面可在首页-[我的奖品] 内查看兑换码
1中奖后在中奖页面复制兑换码前往<span
class="blod">[平安理财服务号]</span>消息框输入元宵快乐获取兑换链接进入链接输入兑换码兑换奖品如关闭了中奖界面可在首页-[我的奖品]
内查看兑换码
</div>
<div>2成功领奖后奖品将会在24小时内自动到账请耐心等候</div>
<div>3中奖人请在活动结束前进行兑换逾期视为弃权</div>
@ -125,12 +127,12 @@ onMounted(() => {
font-family: 'HarmonyOS_Sans_SC_Regular';
}
.blod{
.blod {
font-weight: 700;
color: #6c0500;
}
.margin-bottom-area{
.margin-bottom-area {
// margin-bottom: 100px;
height: 100px;
}
@ -142,12 +144,14 @@ onMounted(() => {
@include bg_pos("rule/arrow.png");
pointer-events: none;
}
.rule-bottom-bg {
// visibility: hidden;
@include pos(588px, 102px, 12px, 682px);
pointer-events: none;
background-image: -webkit-linear-gradient( 90deg, rgba(255,238,186,0.7) , rgba(255, 255, 255, 0.1) 100%);
background-image: -webkit-linear-gradient(90deg, rgba(255, 238, 186, 0.7), rgba(255, 255, 255, 0.1) 100%);
}
.rule-icon {
@include pos(118px, 146px, 511px, 25px);
@include bg_pos("rule/icon.png");

View File

@ -1,73 +1,221 @@
export const data = [
{
id: 1,
question: [
'兄弟好多个,个个都爱赢',
'目标很合适,止盈有方法',
],
question: ["把户口迁到一块"],
answer: [
{
aid: 'A',
text: [
'灵活策略目标盈',
],
result:'correct',
aid: "A",
text: ["启"],
result: "correct",
},
{
aid: 'B',
text: [
'灵活策略目标强',
],
result:'incorrect',
aid: "B",
text: ["航"],
result: "incorrect",
},
],
analysis: [
`<span style="color:#ffe2ad">启航</span>系列旗下产品连续3年获得金牛奖。`,
`2022-2024年`,
],
},
{
id: 2,
question: [
'固收旗舰团,兄弟有志气',
'三个金牛奖,开启财富门',
],
question: ["演出时间,不要说话"],
answer: [
{
aid: 'A',
text: [
'启航',
],
result:'correct',
aid: "A",
text: ["灵"],
result: "incorrect",
},
{
aid: 'B',
text: [
'远航',
],
result:'incorrect',
aid: "B",
text: ["活"],
result: "correct",
},
],
analysis: ['截止2024年2月19日启航','系列历史到期正收益概率100%']
analysis: [
`<span style="color:#ffe2ad">灵活成长</span>系列是低波稳健的持有期固收产品,`,
`同时兼顾流动性和收益空间。`,
],
},
{
id: 3,
question: [
'兄弟好多个,口碑都很好',
'考试常满分,稳重不轻浮',
],
question: ["秋前隐后最可靠"],
answer: [
{
aid: 'A',
text: [
'稳健精选(封闭型)',
],
result:'correct',
aid: "A",
text: ["稳"],
result: "correct",
},
{
aid: 'B',
text: [
'稳妥精选',
],
result:'incorrect',
aid: "B",
text: ["健"],
result: "incorrect",
},
],
analysis: ['截止2024年2月19日稳健精选系列封闭型','历史到期业绩基准达标率100%']
analysis: [
`<span style="color:#ffe2ad">稳健精选</span>是主投低波稳健类资产的封闭产品系列,`,
`史到期兑付正收益概率100%数据时间2025.1.9)。`,
],
},
]
{
id: 4,
question: ["上等木料来造桥"],
answer: [
{
aid: "A",
text: ["策"],
result: "correct",
},
{
aid: "B",
text: ["略"],
result: "incorrect",
},
],
analysis: [
`<span style="color:#ffe2ad">启元策略系列</span>运用自研利率债量化交易模型,`,
`时代有助提升收益的固收理财。`,
],
},
{
id: 5,
question: ["秋前别后再相聚"],
answer: [
{
aid: "A",
text: ["稳"],
result: "incorrect",
},
{
aid: "B",
text: ["利"],
result: "correct",
},
],
analysis: [
`<span style="color:#ffe2ad">启元稳利</span>以低波资产筑底,是闲钱理财升级好去处。`,
],
},
{
id: 6,
question: ["宝玉不在姑娘在"],
answer: [
{
aid: "A",
text: ["安"],
result: "correct",
},
{
aid: "B",
text: ["鑫"],
result: "incorrect",
},
],
analysis: [
`<span style="color:#ffe2ad">新安鑫</span>系列运用结构化工具风险向下有底,收益向上有空间,`,
`是投资者参与股市指数的“安鑫”之选。`,
],
},
{
id: 7,
question: ["水帘洞二十三"],
answer: [
{
aid: "A",
text: ["坤"],
result: "incorrect",
},
{
aid: "B",
text: ["润"],
result: "correct",
},
],
analysis: [
`<span style="color:#ffe2ad">坤润红利价值</span>的红利低波策略可筛选出低估值、`,
`高股息、高质量企业。`,
],
},
{
id: 8,
question: ["太阳的儿子"],
answer: [
{
aid: "A",
text: ["星"],
result: "correct",
},
{
aid: "B",
text: ["辰"],
result: "incorrect",
},
],
analysis: [
`<span style="color:#ffe2ad">星辰</span>系列以价值投资为基础,构建低风险低估值`,
`和持续成长的组合,是以绝对收益为目标的含权理财。`,
],
},
{
id: 9,
question: ["人来凑成桌"],
answer: [
{
aid: "A",
text: ["卓"],
result: "correct",
},
{
aid: "B",
text: ["越"],
result: "incorrect",
},
],
analysis: [
`<span style="color:#ffe2ad">卓越稳健</span>系列是适合中长期配置需求的“固收+理财”,`,
`在低息环境下通过合理的资产配置突显股债性价比。`,
],
},
{
id: 10,
question: ["相逢立即成知音"],
answer: [
{
aid: "A",
text: ["智"],
result: "correct",
},
{
aid: "B",
text: ["享"],
result: "incorrect",
},
],
analysis: [
`<span style="color:#ffe2ad">智享全周期</span>运用全天候策略均衡配置全球多元资产,`,
`助力投资者把握全球市场的交易机会。`,
],
},
{
id: 11,
question: ["春来又听泉声响"],
answer: [
{
aid: "A",
text: ["智"],
result: "correct",
},
{
aid: "B",
text: ["享"],
result: "incorrect",
},
],
analysis: [
`<span style="color:#ffe2ad">权心全益</span>是平安理财发挥多资产多策略投资优势,`,
`用心捕捉权益市场机会,打造稳健的含权产品体系。`,
],
},
];

View File

@ -1,6 +1,7 @@
<template>
<div class="home" @click.once="playMusic">
<Index v-if="showIndex" @IndexPage="indexFn"></Index>
<QuestionList v-if="showQuestionList" ref="QuestionListRef" @QuestionList="questionListFn" @showResult="onShowResult"></QuestionList>
<Question v-if="showQuestion" @QuestionPage="questionFn"></Question>
<Result v-if="showResult" @ResultPage="resultFn"></Result>
<MyPrize v-if="showMyPrize" @MyPrizePage="myPrizeFn"></MyPrize>
@ -15,6 +16,7 @@ import gsap from "gsap";
import Loading from "@/components/Loading";
import Index from "@/components/Index";
import Question from "@/components/Question";
import QuestionList from "@/components/QuestionList";
import MyPrize from "@/components/MyPrize";
import Draw from "@/components/Draw";
import Result from "@/components/Result";
@ -76,6 +78,20 @@ const myPrizeFn = (item) => {
}
};
const QuestionListRef= ref(null)
const showQuestionList = ref(true);
const questionListFn = (item) => {
if (item.action == "hide") {
showQuestionList.value = false;
}
};
const posterId = ref(1)
const onShowResult = (item) => {
posterId.value = item.pid || 1
showResult.value = true;
}
const showDraw = ref(false);
const drawFn = (item) => {
if (item.action == "hide") {
@ -86,7 +102,11 @@ const drawFn = (item) => {
const showResult = ref(false);
const resultFn = (item) => {
if (item.action == "hide") {
showResult.value = false;
console.log('hide',showResult.value);
}
if (item.action == "showDraw") {
showDraw.value = true;
@ -220,7 +240,7 @@ const playMusic = () => {
};
</script>
<style lang="scss" >
<style lang="scss">
#app {
overflow: hidden;
background: linear-gradient(135deg, #a11b15, #f80c00);

View File

@ -1398,6 +1398,11 @@ supports-preserve-symlinks-flag@^1.0.0:
resolved "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
swiper@^11.2.1:
version "11.2.1"
resolved "https://registry.npmmirror.com/swiper/-/swiper-11.2.1.tgz#0f3fcafa30301a1c76e3ef9e85979ac2daeefc18"
integrity sha512-62G69+iQRIfUqTmJkWpZDcX891Ra8O9050ckt1/JI2H+0483g+gq0m7gINecDqMtDh2zt5dK+uzBRxGhGOOvQA==
terser@^5.10.0:
version "5.27.0"
resolved "https://registry.npmmirror.com/terser/-/terser-5.27.0.tgz#70108689d9ab25fef61c4e93e808e9fd092bf20c"