完成抽奖页面,结果页面事件逻辑,待给到设计稿更新页面
@ -1,14 +1,16 @@
|
||||
import axios from 'axios'
|
||||
import QS from 'qs';
|
||||
import { Toast } from 'vant'
|
||||
|
||||
|
||||
let url = import.meta.env.VITE_HOST + import.meta.env.VITE_API
|
||||
|
||||
// 创建axios
|
||||
const service = axios.create({
|
||||
baseURL: import.meta.env.VITE_API,
|
||||
baseURL: url,
|
||||
timeout: 50000,
|
||||
});
|
||||
|
||||
|
||||
|
||||
// 添加请求拦截器
|
||||
service.interceptors.request.use((config) => {
|
||||
// 在发送请求之前做些什么
|
||||
@ -22,11 +24,10 @@ service.interceptors.request.use((config) => {
|
||||
// 添加响应拦截器
|
||||
service.interceptors.response.use(
|
||||
(response) => {
|
||||
|
||||
return response.data;
|
||||
return response.data || {};
|
||||
}, (error) => {
|
||||
|
||||
|
||||
Toast('网络繁忙')
|
||||
console.log('请求错误:', error.message);
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import http from './http'
|
||||
|
||||
export function addSurveyed(data, authorization) {
|
||||
export function drawApi(data, authorization) {
|
||||
return http.post("/api/user/addSurveyed",
|
||||
data,
|
||||
true,
|
||||
|
||||
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 4.1 KiB |
BIN
src/assets/images/prize/draw-box.png
Normal file
|
After Width: | Height: | Size: 101 KiB |
BIN
src/assets/images/prize/draw-text.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
src/assets/images/prize/light.png
Normal file
|
After Width: | Height: | Size: 375 KiB |
BIN
src/assets/images/prize/no-prize.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
src/assets/images/prize/star.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
src/assets/images/prize/tips.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
src/assets/images/result/bg-1.jpg
Normal file
|
After Width: | Height: | Size: 172 KiB |
BIN
src/assets/images/result/bg-2.jpg
Normal file
|
After Width: | Height: | Size: 352 KiB |
BIN
src/assets/images/result/bg-3.jpg
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
src/assets/images/result/bg-4.jpg
Normal file
|
After Width: | Height: | Size: 45 KiB |
@ -1,21 +1,200 @@
|
||||
<template>
|
||||
<div class="DrawPage">
|
||||
抽奖页面
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { debounceTap } from '@/plugins'
|
||||
import gsap from 'gsap'
|
||||
import { addPoint, debounceTap } from '@/plugins'
|
||||
import { Toast } from "vant";
|
||||
import { Clipboard } from "v-clipboard";
|
||||
import { useMainStore } from "@/store";
|
||||
import { drawApi } from '@/api'
|
||||
|
||||
|
||||
// 页面配置初始化
|
||||
const emit = defineEmits(["DrawPage"]);
|
||||
const userStore = useMainStore()
|
||||
|
||||
const money = ref('8.88')
|
||||
const code = ref('sss')
|
||||
|
||||
const showResult = ref(false)
|
||||
const hasPrize = ref(true)
|
||||
|
||||
const drawFn = (event) => {
|
||||
let e = event.target.parentElement
|
||||
debounceTap(e, async () => {
|
||||
console.log('抽奖');
|
||||
Toast.loading({
|
||||
message: '抽奖中',
|
||||
forbidClick: true,
|
||||
duration: 0
|
||||
})
|
||||
gsap.fromTo(e, { rotation: '-30' }, { rotation: '+30', repeat: -1, yoyo: true, ease: 'none', duration: 0.3 })
|
||||
|
||||
// const res = await drawApi({})
|
||||
|
||||
|
||||
setTimeout(() => {
|
||||
hasPrize.value = false // true 中奖 || false 未中奖
|
||||
showResult.value = true
|
||||
console.log("showResult:", showResult.value);
|
||||
Toast.clear()
|
||||
gsap.from('.result-container', { duration: 0.5, scale: 0.7, autoAlpha: 0 })
|
||||
gsap.killTweensOf('.draw-light,.draw')
|
||||
}, 3000)
|
||||
})
|
||||
}
|
||||
|
||||
const hide = (event) => {
|
||||
let e = event.target;
|
||||
debounceTap(e, () => {
|
||||
gsap.to('.DrawPage', { duration: 0.3, autoAlpha: 0, onComplete: () => { emit('DrawPage', 'hide') } })
|
||||
});
|
||||
}
|
||||
const copyFn = (event) => {
|
||||
let e = event.target;
|
||||
debounceTap(e, () => {
|
||||
Clipboard.copy(code.value);
|
||||
Toast(`复制成功:${code.value}`);
|
||||
});
|
||||
}
|
||||
|
||||
const entryAni = () => {
|
||||
gsap.from(".DrawPage", { duration: 0.2, autoAlpha: 0 });
|
||||
gsap.from(".draw-container", { duration: 0.5, autoAlpha: 0, scale: 0.7 });
|
||||
gsap.from(".draw-light", { duration: 3, rotation: '+=360', ease: 'none', repeat: -1 });
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
entryAni();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="DrawPage" @touchmove.prevent>
|
||||
<!-- 抽奖容器 -->
|
||||
<div v-show="!showResult" class="draw-container">
|
||||
<div class="draw-light"></div>
|
||||
<div class="draw-box">
|
||||
<div class="draw" @click="drawFn($event)"></div>
|
||||
</div>
|
||||
<div class="draw-star"></div>
|
||||
<div class="draw-tips"></div>
|
||||
</div>
|
||||
<div v-show="showResult" class="result-container">
|
||||
<!-- 有奖品 -->
|
||||
<div class="draw-has" v-show="hasPrize">
|
||||
<div class="money">¥{{ money }}元</div>
|
||||
<div class="code-box">
|
||||
<div class="code">{{ code }}</div>
|
||||
<div class="copy-btn" @click="copyFn($event)"></div>
|
||||
</div>
|
||||
<div class="cls-btn" @click="hide($event)"></div>
|
||||
</div>
|
||||
<!-- 没有奖品 -->
|
||||
<div class="draw-none" v-show="!hasPrize">
|
||||
<div class="none-prize"></div>
|
||||
<div class="cls-btn" @click="hide($event)"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.DrawPage {
|
||||
@include fixed();
|
||||
background-color: azure;
|
||||
@include flexCen();
|
||||
background-color: rgba($color: #000000, $alpha: 0.8);
|
||||
|
||||
// 抽奖弹窗样式
|
||||
.draw-container {
|
||||
@include box(685px, 694px);
|
||||
position: relative;
|
||||
|
||||
.draw-light {
|
||||
pointer-events: none;
|
||||
@include pos(685px, 694px, 0px, 0px);
|
||||
@include bg_pos("prize/light.png");
|
||||
}
|
||||
|
||||
.draw-star {
|
||||
pointer-events: none;
|
||||
@include pos(515px, 551px, 89px, 56px);
|
||||
@include bg_pos("prize/star.png");
|
||||
}
|
||||
|
||||
.draw-box {
|
||||
@include pos(690px, 680px, 0px, 0px);
|
||||
@include bg_pos("prize/draw-box.png");
|
||||
|
||||
.draw {
|
||||
@include pos(350px, 347px, 164px, 172px);
|
||||
}
|
||||
}
|
||||
|
||||
.draw-tips {
|
||||
pointer-events: none;
|
||||
@include pos(187px, 34px, 250px, 605px);
|
||||
@include bg_pos("prize/tips.png");
|
||||
}
|
||||
}
|
||||
|
||||
// 中奖弹窗样式
|
||||
.draw-has {
|
||||
position: relative;
|
||||
@include box(665px, 731px);
|
||||
@include bg_pos("prize/myPrize-box.png");
|
||||
|
||||
.money {
|
||||
@include pos(370px, 81px, 139px, 239px);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #e95b46;
|
||||
font-weight: 700;
|
||||
font-size: 58px;
|
||||
letter-spacing: 4px;
|
||||
}
|
||||
|
||||
.code-box {
|
||||
@include pos(312px, 52px, 197px, 508px);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.code {
|
||||
font-size: 25px;
|
||||
font-weight: 700;
|
||||
margin-right: 10px;
|
||||
color: #fff6cc;
|
||||
}
|
||||
|
||||
.copy-btn {
|
||||
@include box(77px, 39px);
|
||||
@include bg_pos("prize/copy-btn.png");
|
||||
}
|
||||
}
|
||||
|
||||
.cls-btn {
|
||||
@include pos(82px, 82px, 517px, 114px);
|
||||
@include bg_pos("prize/cls-btn.png");
|
||||
}
|
||||
}
|
||||
|
||||
// 未中奖弹窗样式
|
||||
.draw-none {
|
||||
@include flexCen();
|
||||
|
||||
.none-prize {
|
||||
@include box(521px, 447px);
|
||||
@include bg_pos("prize/no-prize.png");
|
||||
}
|
||||
|
||||
.cls-btn {
|
||||
@include box(82px, 82px);
|
||||
@include bg_pos("prize/cls-btn.png");
|
||||
margin-top: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -61,7 +61,8 @@ onMounted(() => {
|
||||
.MyPrizePage {
|
||||
@include fixed();
|
||||
@include flexCen();
|
||||
background-color: rgba($color: #000000, $alpha: 0.7);
|
||||
background-color: rgba($color: #000000, $alpha: 0.8);
|
||||
|
||||
.myPrize-container {
|
||||
position: relative;
|
||||
@include box(665px, 731px);
|
||||
@ -83,6 +84,7 @@ onMounted(() => {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.code {
|
||||
font-size: 25px;
|
||||
font-weight: 700;
|
||||
@ -97,7 +99,7 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.myPrize-cls-btn {
|
||||
@include pos(57px, 57px, 517px, 114px);
|
||||
@include pos(82px, 82px, 517px, 114px);
|
||||
@include bg_pos("prize/cls-btn.png");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<script setup name="Question">
|
||||
import { Button, Toast } from "vant";
|
||||
import gsap from "gsap";
|
||||
import data from "@/data";
|
||||
import { data } from "@/data";
|
||||
import { debounceTap, FYShuffle, mostValue } from "@/plugins";
|
||||
import { onMounted } from "vue";
|
||||
|
||||
@ -190,16 +190,9 @@ onMounted(() => {
|
||||
</div>
|
||||
</div>
|
||||
<div class="answer-box">
|
||||
<div
|
||||
class="answer"
|
||||
v-for="(item, index) in questionList[currentId].answer"
|
||||
:class="'answer-' + index"
|
||||
:key="index"
|
||||
>
|
||||
<div
|
||||
class="answer-bg"
|
||||
:class="activeId == item.aid ? 'active' : ''"
|
||||
></div>
|
||||
<div class="answer" v-for="(item, index) in questionList[currentId].answer" :class="'answer-' + index"
|
||||
:key="index">
|
||||
<div class="answer-bg" :class="activeId == item.aid ? 'active' : ''"></div>
|
||||
<div class="answer-text">
|
||||
<div class="content-before"></div>
|
||||
<div class="content-after"></div>
|
||||
@ -245,6 +238,7 @@ onMounted(() => {
|
||||
@include bg_pos("qa/question.png");
|
||||
font-family: "alimama";
|
||||
color: #c6672c;
|
||||
|
||||
.question-order {
|
||||
@include pos(544px, 75px, 87px, 112px);
|
||||
display: flex;
|
||||
@ -254,6 +248,7 @@ onMounted(() => {
|
||||
font-weight: 700;
|
||||
line-height: 80px;
|
||||
}
|
||||
|
||||
.question-text {
|
||||
@include pos(544px, 150px, 87px, 192px);
|
||||
box-sizing: border-box;
|
||||
@ -264,6 +259,7 @@ onMounted(() => {
|
||||
font-size: 40px;
|
||||
font-weight: 700;
|
||||
line-height: 50px;
|
||||
|
||||
.text {
|
||||
width: 80%;
|
||||
// height: 100%;
|
||||
@ -286,11 +282,13 @@ onMounted(() => {
|
||||
position: absolute;
|
||||
// font-family: "alimama";
|
||||
color: #c6672c;
|
||||
|
||||
.answer-bg {
|
||||
@include pos(481px, 471px, 0px, 0px);
|
||||
@include bg_pos("qa/answer-box-1.png");
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.active {
|
||||
@include bg_pos("qa/answer-box-2.png");
|
||||
|
||||
@ -350,6 +348,7 @@ onMounted(() => {
|
||||
top: 0px;
|
||||
left: 6px;
|
||||
}
|
||||
|
||||
.answer:nth-child(2) {
|
||||
top: 414px;
|
||||
left: 258px;
|
||||
|
||||
@ -1,21 +1,83 @@
|
||||
<template>
|
||||
<div class="ResultPage">
|
||||
结果页
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { gsap } from 'gsap'
|
||||
import { debounceTap } from '@/plugins'
|
||||
import { useMainStore } from '@/store'
|
||||
import { mbtiList } from '@/data'
|
||||
|
||||
|
||||
// 页面配置初始化
|
||||
const emit = defineEmits(["ResultPage"]);
|
||||
const userStore = useMainStore()
|
||||
let bgId = ref(1)
|
||||
const bgPic = computed(() => {
|
||||
return new URL(`../assets/images/result/bg-${bgId.value}.jpg`, import.meta.url).href
|
||||
})
|
||||
|
||||
const mbti = ref(mbtiList.find((item) => item.type == 'INFJ') || '没结果')
|
||||
|
||||
console.log('mbti', mbti.value);
|
||||
|
||||
const changBg = (event, number) => {
|
||||
let e = event.target
|
||||
if (number == bgId.value) return
|
||||
debounceTap(e, () => {
|
||||
bgId.value = number
|
||||
console.log('bgId', bgId.value);
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="ResultPage">
|
||||
<div class="result-bg">
|
||||
<img :src="bgPic" alt="" srcset="">
|
||||
</div>
|
||||
<div class="result-container">
|
||||
结果页:{{ mbti.type || '没结果' }}
|
||||
<div class="bg-tab">
|
||||
<div v-for="item in 4" class="li" @click="changBg($event, item)">{{ item }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ResultPage {
|
||||
@include fixed();
|
||||
background-color: azure;
|
||||
|
||||
.result-bg {
|
||||
@include pos(750px, 100%, 0px, 50%);
|
||||
transform: translateY(-50%);
|
||||
pointer-events: none;
|
||||
|
||||
img {
|
||||
@include box(100%, 100%);
|
||||
}
|
||||
}
|
||||
|
||||
.result-container {
|
||||
@include pos(750px, 100%, 0px, 50%);
|
||||
transform: translateY(-50%);
|
||||
|
||||
.bg-tab {
|
||||
width: 90%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-around;
|
||||
|
||||
.li {
|
||||
@include box(80px, 80px);
|
||||
background-color: aquamarine;
|
||||
@include flexCen();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
</style>
|
||||
@ -1,21 +1,21 @@
|
||||
<template>
|
||||
<div class="RulePage">
|
||||
规则页面
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { debounceTap } from '@/plugins'
|
||||
|
||||
// 页面配置初始化
|
||||
const emit = defineEmits(["RulePage"]);
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="RulePage">
|
||||
规则页面
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.RulePage {
|
||||
@include fixed();
|
||||
background-color: azure;
|
||||
@include flexCen();
|
||||
background-color: rgba($color: #000000, $alpha: 0.7);
|
||||
}
|
||||
</style>
|
||||
@ -1,4 +1,4 @@
|
||||
export default [
|
||||
export const data = [
|
||||
{
|
||||
id: 1,
|
||||
type: 'mbti',
|
||||
@ -204,3 +204,66 @@ export default [
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
export const mbtiList = [
|
||||
{
|
||||
type: 'INTJ',
|
||||
spe: '富有想象力和战略性的思想家,一切皆在计划之中',
|
||||
},
|
||||
{
|
||||
type: 'INTP',
|
||||
spe: '富有创造力的发明家,对知识有着止不住的渴望',
|
||||
},
|
||||
{
|
||||
type: 'ENTJ',
|
||||
spe: '大胆,富有想象力且',
|
||||
},
|
||||
{
|
||||
type: 'ENTP',
|
||||
spe: '富有想象力和战略性的思想家,一切皆在计划之中',
|
||||
},
|
||||
{
|
||||
type: 'INFJ',
|
||||
spe: '富有想象力和战略性的思想家,一切皆在计划之中',
|
||||
},
|
||||
{
|
||||
type: 'INFP',
|
||||
spe: '富有想象力和战略性的思想家,一切皆在计划之中',
|
||||
},
|
||||
{
|
||||
type: 'ENFJ',
|
||||
spe: '富有想象力和战略性的思想家,一切皆在计划之中',
|
||||
},
|
||||
{
|
||||
type: 'ENFP',
|
||||
spe: '富有想象力和战略性的思想家,一切皆在计划之中',
|
||||
},
|
||||
{
|
||||
type: 'ISTJ',
|
||||
spe: '富有想象力和战略性的思想家,一切皆在计划之中',
|
||||
},
|
||||
{
|
||||
type: 'ISFJ',
|
||||
spe: '富有想象力和战略性的思想家,一切皆在计划之中',
|
||||
},
|
||||
{
|
||||
type: 'ESTJ',
|
||||
spe: '富有想象力和战略性的思想家,一切皆在计划之中',
|
||||
},
|
||||
{
|
||||
type: 'ISTP',
|
||||
spe: '富有想象力和战略性的思想家,一切皆在计划之中',
|
||||
},
|
||||
{
|
||||
type: 'ISFP',
|
||||
spe: '富有想象力和战略性的思想家,一切皆在计划之中',
|
||||
},
|
||||
{
|
||||
type: 'ESTP',
|
||||
spe: '富有想象力和战略性的思想家,一切皆在计划之中',
|
||||
},
|
||||
{
|
||||
type: 'ESFP',
|
||||
spe: '富有想象力和战略性的思想家,一切皆在计划之中',
|
||||
},
|
||||
]
|
||||
@ -2,8 +2,10 @@
|
||||
<div class="home">
|
||||
<Index v-if="showIndex" @IndexPage="indexFn"></Index>
|
||||
<Question v-if="showQuestion" @QuestionPage="questionFn"></Question>
|
||||
<Loading v-if="showLoad" @LoadPage="loadFn"></Loading>
|
||||
<Result v-if="showResult" @ResultPage="resultFn"></Result>
|
||||
<MyPrize v-if="showMyPrize" @MyPrizePage="myPrizeFn"></MyPrize>
|
||||
<Draw v-if="showDraw" @DrawPage="drawFn"></Draw>
|
||||
<Loading v-if="showLoad" @LoadPage="loadFn"></Loading>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -13,6 +15,8 @@ import Loading from "@/components/Loading";
|
||||
import Index from "@/components/Index";
|
||||
import Question from "@/components/Question";
|
||||
import MyPrize from "@/components/MyPrize";
|
||||
import Draw from "@/components/Draw";
|
||||
import Result from "@/components/Result";
|
||||
import { createBGM } from "@/plugins";
|
||||
|
||||
const showLoad = ref(true);
|
||||
@ -50,6 +54,20 @@ const myPrizeFn = (item) => {
|
||||
}
|
||||
};
|
||||
|
||||
const showDraw = ref(false);
|
||||
const drawFn = (item) => {
|
||||
if (item.action == "hide") {
|
||||
showDraw.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const showResult = ref(true);
|
||||
const resultFn = (item) => {
|
||||
if (item.action == "hide") {
|
||||
showResult.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
// createBGM();
|
||||
});
|
||||
|
||||
@ -1,17 +1,28 @@
|
||||
// pinia仓库
|
||||
import { defineStore } from "pinia"
|
||||
|
||||
|
||||
export const useMainStore = defineStore("counter", {
|
||||
state: () => {
|
||||
return {
|
||||
name: '超级管理员',
|
||||
prizeCode: 'DKS18',
|
||||
prizeMoney: '8.88',
|
||||
token: '',
|
||||
MBTI: '', //测试结果
|
||||
prizeCode: 'DKS18', //兑换码
|
||||
prizeMoney: '8.88', //金额
|
||||
}
|
||||
},
|
||||
// 相当于computed属性,对state进行二次加工
|
||||
getters: {},
|
||||
// 异步处理方法
|
||||
actions: {},
|
||||
actions: {
|
||||
updateToken(token) {
|
||||
this.token = token
|
||||
},
|
||||
updatePrize(code, money) {
|
||||
this.prizeCode = code
|
||||
this.prizeMoney = money
|
||||
},
|
||||
updateMBTI(type) {
|
||||
this.MBTI = type
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||