Commit eee10c90 by 陆志强

feat: 新增竞答抽奖

parent 6af9d603
/* eslint-disable no-confusing-arrow */ /* eslint-disable no-confusing-arrow */
import { post, get } from '@/api/request' import { post, get } from '@/api/request'
import CONFIG, { ENV_CONFIG } from '@/config' import CONFIG, { ENV_CONFIG } from '@/config'
const { activityDomain, privateDomain, voteDomain } = CONFIG const { activityDomain, privateDomain, voteDomain, consolesDomain } = CONFIG
const flag = ENV_CONFIG.X_CA_STAGE const flag = ENV_CONFIG.X_CA_STAGE
// 获取抽奖(场次)列表 // 获取抽奖(场次)列表
...@@ -70,3 +70,13 @@ export const checkVote = data => ...@@ -70,3 +70,13 @@ export const checkVote = data =>
// 检测前置活动问卷 // 检测前置活动问卷
export const checkQuestionnaire = data => export const checkQuestionnaire = data =>
flag ? get('/activity/Questionnaire/checkQuestionnaired', { data }) : get('/activity/Questionnaire/checkQuestionnaired', { data, baseURL: activityDomain }) flag ? get('/activity/Questionnaire/checkQuestionnaired', { data }) : get('/activity/Questionnaire/checkQuestionnaired', { data, baseURL: activityDomain })
// 获取用户简单信息
export const getUserSimpleInfo = (data) => get('/user/openapi/getUserSimpleInfo', { data, baseURL: consolesDomain })
// 提交问卷
export const saveAnswer = (data) =>
flag
? post('/activity/Draw/saveAnswer', data)
: post('/activity/Draw/saveAnswer', { data, baseURL: activityDomain })
<template>
<section class="banner">
<a
v-lazy:background-image="bannerImg"
class="banner__wrap"
target="_blank"
:style="`padding-top: ${paddingTop}%`"
>
<div
v-lazy:background-image="bannerImg"
class="banner__glazing-firefox"
:style="`filter: blur(${filterBlur}px)`"
></div>
<slot></slot>
<div class="banner__glazing" :style="`backdrop-filter: saturate(${saturate}%) blur(${blur}px)`"></div>
</a>
</section>
</template>
<script>
// 默认背景图
import { mapGetters } from 'vuex'
import CONFIG,{ ENV_CONFIG } from '@/config'
export default {
name: 'Banner',
props: {
scrollTop: {
type: Number,
default: 0,
},
},
data() {
return {
paddingTop: (160 / 375) * 100,
saturate: 100,
blur: 0,
filterBlur: 0,
}
},
computed: {
...mapGetters({
info: 'questionnaire/questionnaireInfo',
}),
bannerImg() {
const img = `//${ENV_CONFIG.OSS_DOMAIN}/common/img/questionLottery.png`
return `${img}${CONFIG.ossImageServe}`
},
},
watch: {
scrollTop: {
handler(nVal) {
const headDistance = 98
const saturateMax = 80
const blurMax = 20
const filterBlurMax = 6
const scroll = nVal > headDistance ? headDistance : nVal <= 0 ? 0 : nVal
const scale = scroll / headDistance
this.saturate = scale * saturateMax + 100
this.blur = scale * blurMax
this.filterBlur = scale * filterBlurMax
this.paddingTop = (160 / 375) * 100 - (scroll / 375) * 100
},
immediate: true,
},
},
}
</script>
<style lang="less" scoped>
.banner {
width: 100%;
display: flex;
overflow: hidden;
&__wrap {
width: 100%;
position: relative;
padding-top: 160 / 375 * 100%;
height: 0;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
&__glazing {
/* chrome safiri 等浏览器下的毛玻璃实现 */
@supports ((-webkit-backdrop-filter: saturate(180%) blur(20px)) or (backdrop-filter: saturate(180%) blur(20px))) {
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
}
&__glazing-firefox {
display: none;
/* 兼容 firefox 浏览器下的毛玻璃实现 */
@supports not (backdrop-filter: saturate(180%) blur(20px)) {
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
z-index: 0;
}
}
}
</style>
<template>
<section class="questionnaire">
<Banner class="questionnaire__banner" :scroll-top="scrollTop">
</Banner>
<div class="questionnaire__main">
<Scroll class="questionnaire__scroll" @onScroll="onScroll">
<div class="questionnaire__scroll-wrap" :style="{'padding-bottom': isShowContent ? '160px' : '0'}">
<div class="introduction">
<van-collapse v-model="activeName" class="introduction__collapse" :border="false" accordion>
<van-collapse-item class="introduction__collapse-item" title="介绍" name="1">
<div class="ql-editor introduction__content" v-html="info.intro"></div>
</van-collapse-item>
</van-collapse>
</div>
<div ref="progressWrap" class="questionnaire__sticky-wrap" :style="stickyPlaceholder">
<div :class="{ 'questionnaire__progress--sticky': isProgressSticky }">
<div class="progress">
<div class="progress__text">共1道题,当前进度:1/1</div>
</div>
</div>
</div>
<QuestionForm :info="info" />
</div>
</Scroll>
</div>
</section>
</template>
<script>
/* 组件 */
import Banner from './Banner'
// import Loading from '@/components/Loading'
import Scroll from '@/components/Common/Scroll'
import debounce from 'lodash/debounce'
import Bus from '@/utils/Bus'
import QuestionForm from './QuestionForm'
// import { ENV_CONFIG } from '@/config'
export default {
name: 'QuestionWarp',
components: {
Banner,
// FinishedNotice,
// Loading,
Scroll,
QuestionForm,
},
props: {
info: {
type: Object,
default: () => ({})
}
},
data() {
return {
activeName: '1',
scrollTop: 0,
stickyPlaceholder: {},
isProgressSticky: false,
isShowResult: false,
isIframe: false,
loginInstance: null,
}
},
computed: {
isShowContent() {
return this.info.isAnswer ? this.info.isAnswer : true
},
pageLoading: {
get() {
return this.isPageLoading
},
set(nVal) {
this.updateIsPageLoading(nVal)
},
},
},
mounted() {
this.eventBusInit()
setTimeout(() => {
this.isIframe = !(window.self === window.top)
},2000)
Bus.$on('showLogin', this.toggleLogin)
},
destroyed() {
Bus.$off('onFinished')
Bus.$off('showLogin')
},
methods: {
eventBusInit() {
Bus.$on('onFinished', () => {
this.loadData()
})
},
onScroll({ vertical }) {
this.scrollTop = vertical?.scrollTop || 0
this.stickyListener()
},
/* eslint-disable no-invalid-this */
stickyListener: debounce(
function () {
const targetDom = this.$refs?.progressWrap
if (targetDom) {
const domRect = targetDom.getBoundingClientRect()
if (domRect.top <= 65) {
this.isProgressSticky = true
this.stickyPlaceholder = { height: `${domRect.height}px` }
} else {
this.isProgressSticky = false
this.stickyPlaceholder = {}
}
}
},
100,
{ maxWait: 100 }
),
},
}
</script>
<style lang="less" scoped>
@bannerHeight: 150px; // 上半部分高度
.questionnaire {
margin: 0 auto;
width: 100%;
height: 100vh;
overflow: hidden;
position: relative;
&__main {
// position: absolute;
// left: 0;
// top: 0;
width: 100%;
height: calc(100% - 60px);
background-color: #fff;
}
&__scroll {
// padding: 80px 16px 0px !important;
.__panel {
// in order to hide system scrollbar
&::-webkit-scrollbar {
display: none;
}
// border-radius: 11px;
}
.__view {
// min-height: unset !important;
height: calc(100% - 170px);
}
}
&__scroll-wrap {
// box-shadow: 0px 2px 4px 0px rgba(189, 189, 189, 0.5);
// FIXME Comput margin-top: 98px;
// margin-top: 30%;
min-height: 100%;
padding: 0 10px;
background-color: #fff;
// border-radius: 11px;
overflow: hidden;
.progress {
width: 100%;
height: 14px;
padding: 14px 0;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
box-sizing: content-box;
background-color: #fff;
// border-radius: 11px;
&__text {
font-size: 12px;
color: #666;
transform: scale(9/12);
position: relative;
&::before {
content: '';
width: 47px;
height: 1px;
position: absolute;
transform: translateY(-50%);
top: 50%;
left: -55px;
background: linear-gradient(to left, #d5d5d5, #ececec);
}
&::after {
content: '';
width: 47px;
height: 1px;
position: absolute;
transform: translateY(-50%);
top: 50%;
right: -55px;
background: linear-gradient(to right, #d5d5d5, #ececec);
}
}
}
}
&__progress {
&--sticky {
position: fixed;
top: 62px;
z-index: 99;
left: 0;
right: 0;
// padding: 0 14px;
// max-width: @--body-max-width;
margin: 0 auto;
}
}
&__user-info {
margin: 20px 0;
}
// &__form {
// margin-bottom: 100px;
// }
}
.introduction {
width: 100%;
font-size: 14px;
line-height: 18px;
color: #333;
padding: 6px 4px;
&__collapse-item {
::v-deep .van-collapse-item__title--expanded::after {
display: none !important;
}
::v-deep .van-cell {
&:after {
display: none !important;
}
}
::v-deep .van-collapse-item__content {
padding-top: 0;
padding-bottom: 0;
font-size: 12px;
color: #666;
}
::v-deep .van-collapse-item__title--expanded::after {
display: none !important;
}
::v-deep .van-cell {
.van-cell__title {
span {
font-size: 14px;
font-weight: 500;
color: #333;
}
}
}
}
&__content {
padding: 0;
::v-deep img {
max-width: 100%;
}
}
}
</style>
...@@ -10,4 +10,5 @@ export default { ...@@ -10,4 +10,5 @@ export default {
defBanner: `//${ENV_CONFIG.OSS_DOMAIN}/common/img/lottery_banner_default_v2.png`, defBanner: `//${ENV_CONFIG.OSS_DOMAIN}/common/img/lottery_banner_default_v2.png`,
defShareImg: `${protocol || 'https:'}//${ENV_CONFIG.OSS_DOMAIN}/common/img/lottery.png`, // 必须带协议头,否则微信分享配置时无法生效 defShareImg: `${protocol || 'https:'}//${ENV_CONFIG.OSS_DOMAIN}/common/img/lottery.png`, // 必须带协议头,否则微信分享配置时无法生效
ossImageServe: ENV_CONFIG.IS_PRIVATE ? '' : '?x-oss-process=style/mobilebackground', ossImageServe: ENV_CONFIG.IS_PRIVATE ? '' : '?x-oss-process=style/mobilebackground',
consolesDomain: `//${ENV_CONFIG.CONSOLES_API_DOMAIN}/v1`,
} }
...@@ -24,7 +24,8 @@ export default { ...@@ -24,7 +24,8 @@ export default {
isLoading: true, isLoading: true,
lotteryComponents: { lotteryComponents: {
[LOTTERY_TYPE.instant]: () => import('@/components/Lottery/Instant/Main'), [LOTTERY_TYPE.instant]: () => import('@/components/Lottery/Instant/Main'),
[LOTTERY_TYPE.timing]: () => import('@/components/Lottery/Timing/Main') [LOTTERY_TYPE.timing]: () => import('@/components/Lottery/Timing/Main'),
[LOTTERY_TYPE.question]: () => import('@/components/Lottery/Question/Main')
}, },
id: this.$route.query.id || null, // 接收抽奖id id: this.$route.query.id || null, // 接收抽奖id
sessionId: this.$route.query.sessionId || null, // 接收抽奖场次id sessionId: this.$route.query.sessionId || null, // 接收抽奖场次id
......
...@@ -25,7 +25,8 @@ export default { ...@@ -25,7 +25,8 @@ export default {
isLoading: true, isLoading: true,
lotteryComponents: { lotteryComponents: {
[LOTTERY_TYPE.instant]: () => import('@/components/Lottery/Instant/MiniMain'), [LOTTERY_TYPE.instant]: () => import('@/components/Lottery/Instant/MiniMain'),
[LOTTERY_TYPE.timing]: () => import('@/components/Lottery/Timing/MiniMain') [LOTTERY_TYPE.timing]: () => import('@/components/Lottery/Timing/MiniMain'),
[LOTTERY_TYPE.question]: () => import('@/components/Lottery/Question/MiniMain')
}, },
id: this.$route.query.id || null, // 接收抽奖id id: this.$route.query.id || null, // 接收抽奖id
sessionId: this.$route.query.sessionId || null, // 接收抽奖场次id sessionId: this.$route.query.sessionId || null, // 接收抽奖场次id
......
...@@ -21,7 +21,14 @@ import { ...@@ -21,7 +21,14 @@ import {
Tab, Tab,
Tabs, Tabs,
Field, Field,
Area Area,
Collapse,
CollapseItem,
Radio,
RadioGroup,
Form,
Cell,
CellGroup
} from 'vant' } from 'vant'
import errorImg from '@/assets/images/lazyLoad/error.png' import errorImg from '@/assets/images/lazyLoad/error.png'
import loadingImg from '@/assets/images/lazyLoad/loading.png' import loadingImg from '@/assets/images/lazyLoad/loading.png'
...@@ -89,3 +96,18 @@ Vue.use(Field) ...@@ -89,3 +96,18 @@ Vue.use(Field)
/* 地区选择 */ /* 地区选择 */
Vue.use(Area) Vue.use(Area)
/* 折叠 */
Vue.use(Collapse)
Vue.use(CollapseItem)
/* 单选 */
Vue.use(Radio)
Vue.use(RadioGroup)
/* 表单 */
Vue.use(Form)
/* 单元格 */
Vue.use(Cell)
Vue.use(CellGroup)
...@@ -2,12 +2,14 @@ ...@@ -2,12 +2,14 @@
export const LOTTERY_TYPE = { export const LOTTERY_TYPE = {
instant: 1, instant: 1,
timing: 2, timing: 2,
message: 3 message: 3,
question: 4
} }
export const LOTTERY_TYPE_TXT = { export const LOTTERY_TYPE_TXT = {
[LOTTERY_TYPE.instant]: '即时抽奖', [LOTTERY_TYPE.instant]: '即时抽奖',
[LOTTERY_TYPE.timing]: '定时抽奖', [LOTTERY_TYPE.timing]: '定时抽奖',
[LOTTERY_TYPE.message]: '留言抽奖' [LOTTERY_TYPE.message]: '留言抽奖',
[LOTTERY_TYPE.question]: '问答抽奖'
} }
/* 抽奖活动状态 */ /* 抽奖活动状态 */
......
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 sign in to comment