123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821 |
- <template>
- <page-layout>
- <nav-bar title="逛展打卡路线" @init="onInitNavbar"></nav-bar>
- <scroll-view id="scrollContainer" scroll-with-animation="true" :scroll-top="scroll_top" :scroll-y="true"
- style="height: 100vh" :scroll-into-view="scrollIntoViewId">
- <view class="outter">
- <view class="body">
- <view class="theme-title">
- <text class="title">逛展打卡路线</text>
- <image mode="aspectFit" class="title-bg"
- src="https://www.productronicachina.com.cn/resources/files/0221/67b7dd27b30b7/标题星星.png"></image>
- </view>
- <view class="pagination">
- <view class="page-change">
- <view @click="current_page=true" :class="['page-item',current_page?'active':'']">活动介绍</view>
- <view @click="current_page=false" :class="['page-item',current_page?'':'active']">活动规则</view>
- </view>
- <view class="page">
- <view v-show="current_page" class="page-item">
- <mp-html :content="routeInfoData.description"></mp-html>
- </view>
- <view v-show="!current_page" class="page-item">
- <view style="margin-bottom: 24rpx;">2025慕尼黑上海电子展展会现场将设有9条热门路线。观众可参与打卡调整。
- <text style="font-weight: bold;color: #E57519;">
- 打卡满任意2条,5条,8条分别获对应礼品。满9条路线完成终极挑战,除获得对应礼品以外,更有机会参与抽奖,赢取幸运大奖。
- </text>
- </view>
- <view style="margin-bottom: 16rpx;">
- <text style="font-weight: bold;">活动时间:</text>
- 2025年3月26日-3月28日
- </view>
- <view style="margin-bottom: 16rpx;">
- <text style="font-weight: bold;">参与人员:</text>
- 2025慕尼黑上海电子生产设备展现场观众
- </view>
- <view style="margin-bottom: 24rpx;">
- <text style="font-weight: bold;">奖品兑换区:</text>
- 展会现场礼品发放处【展位号待定】
- </view>
- <view style="margin-bottom: 16rpx;">① 展会期间,每人可领取完成最高线路的对应奖品,每人仅有一次兑奖机会。
- </view>
- <view style="margin-bottom: 16rpx;">② 礼品数量有限,仅限展会期间领取,先到先得,一旦赠完即止。</view>
- <view style="margin-bottom: 16rpx;">③
- 【我的奖品】页面可了解获奖详情。点击【可领取奖品】至展会现场礼品发放处【展位号待定】进行奖品核销与兑换。
- </view>
- <view>④ 满9条路线的观众可将名片放置抽奖箱,获奖结果将于展后公布。</view>
- </view>
- <view class="light" :style="{transform:current_page?'translateX(-100%)':'translateX(100%)'}"></view>
- </view>
- </view>
- <van-collapse custom-class="check_list" :border="false" v-model="activeNames" @change="onChange">
- <van-collapse-item :custom-class="activeNames.includes(r_index) ? 'expand_item' : ''" :border="false"
- class="router-item" v-for="(route,r_index) in routeInfoData.routes" :key="r_index"
- :name="r_index">
- <view slot="title" class="item-head" :id="'module' + r_index">
- <view class="route-name">{{ route.name }}</view>
- <view class="product-type">
- <view class="text">{{ route.description }}</view>
- <view class="button" @click.stop="showOverlayEvent(route.map_url)">
- {{ route.map_btn_name }}
- <text class="iconfont icon-Search"></text>
- </view>
- </view>
- <view class="progress">
- <view class="text" v-if="getProcess(route.exhibitors,true)">
- 打卡已完成{{ getProcess(route.exhibitors, false) }}
- </view>
- <view class="text disable_text" v-else>未开始{{ getProcess(route.exhibitors, false) }}</view>
- <view class="inner">
- <view :style="{width:getProcess(route.exhibitors,true)*100+'%'}" class="inner-process">
- <view class="text" :style="{width:'calc(100% / '+getProcess(route.exhibitors,true)+')'}">
- 打卡已完成{{ getProcess(route.exhibitors, false) }}
- </view>
- </view>
- </view>
- </view>
- </view>
- <view class="iconfont icon-Down" @click="onChangeVanItem(r_index)"></view>
- <view class="item-body">
- <view v-for="(exhibit,e_index) in route.exhibitors"
- :id="'module' + r_index + '_' + e_index"
- :class="['exhibit-item',exhibit.checkin_status === 1 ?'checked':'']">
- <image mode="aspectFit" class="logo" :src="exhibit.logo"></image>
- <view class="name">{{ exhibit.name_zh_cn }}</view>
- <view class="code">
- <text class="text">展位号:</text>
- <text class="code-inner">{{ exhibit.hall_booth_no }}</text>
- </view>
- <view class="button" @click="scanCodeEvent(route,r_index,e_index,exhibit)">
- <text :class="['iconfont',exhibit.checkin_status === 1 ?'icon-Check':'icon-saoyisao_1']"></text>
- <text class="text">打卡</text>
- </view>
- </view>
- </view>
- </van-collapse-item>
- </van-collapse>
- <view class="side-button">
- <view @click="gotoPrizes()" class="button">
- <text style="font-size: 50rpx;" class="iconfont icon-jiangpin"></text>
- <text class="title">我的奖品</text>
- </view>
- <view @click="gotoRule()" class="button">
- <text class="iconfont icon-xiaochengxu-canguandengjiicon"></text>
- <text class="title">活动规则</text>
- </view>
- <view class="button">
- <button open-type="share"></button>
- <text style="font-size: 56rpx;" class="iconfont icon-zhuanfa"></text>
- <text class="title">分享</text>
- </view>
- </view>
- </view>
- </view>
- </scroll-view>
- <van-overlay :show="mapShow">
- <view class="overlay_wrapper">
- <image :src="mapUrl" style="width: 90%;" mode="widthFix"></image>
- <view class="iconfont icon-Cancel-copy" @click="hideOverlay"></view>
- </view>
- </van-overlay>
- <van-dialog id="van-dialog"/>
- </page-layout>
- </template>
- <script>
- import PageLayout from "@/components/layout/page-layout";
- import NavBar from "@/components/layout/nav-bar";
- import UScrollView from "@/components/common/u-scroll-view";
- import {getRouteList, qrcodeDecode} from "@/api/checkIn";
- import Dialog from "@/wxcomponents/vant/dialog/dialog";
- import VanOverlay from '@/wxcomponents/vant/overlay/index'
- import VanCollapse from '@/wxcomponents/vant/collapse/index'
- import VanCollapseItem from '@/wxcomponents/vant/collapse-item/index'
- import Toast from '@/wxcomponents/vant/toast/toast';
- import store from "@/store";
- export default {
- components: {
- PageLayout,
- NavBar,
- UScrollView,
- VanOverlay,
- VanCollapse,
- VanCollapseItem
- },
- data() {
- return {
- scrollIntoViewId: '',
- scene: '',
- activeNames: [0],
- mapShow: false,
- mapUrl: '',
- current_page: true,
- current_unfold: -1,
- scroll_top: 0,
- is_receipts: null,
- routeInfoData: []
- };
- },
- mounted() {
- this.getRouteListEvent()
- },
- methods: {
- initSceneEvent() {
- //微信扫码进入
- if (this.scene) {
- const sceneParams = this.getSceneParamsEvent(this.scene)
- console.log(sceneParams)
- this.getRouteListEvent(() => {
- let item = {
- index: 0,
- child_index: 0
- }
- this.routeInfoData.routes.forEach((route_item, route_index) => {
- if (route_item.exhibitors && route_item.exhibitors.length > 0) {
- route_item.exhibitors.forEach((exhibitors_item, exhibitors_index) => {
- if (exhibitors_item.exhibitor_id === sceneParams.a) {
- item.index = route_index
- item.child_index = exhibitors_index
- }
- })
- }
- })
- this.qrcodeDecodeEvent(this.scene, async () => {
- /* */
- this.scrollIntoViewId = '#module' + item.index;
- if (!(this.activeNames.includes(item.index))) {
- this.activeNames.push(item.index)
- }
- setTimeout(async () => {
- // this.scrollIntoViewId = '#module' + item.index + '_' + item.child_index;
- }, 500)
- this.$set(this.routeInfoData.routes[item.index].exhibitors[item.child_index], 'checkin_status', 1)
- })
- })
- }
- },
- onChangeVanItem(val) {
- let index = this.activeNames.indexOf(val); // 查找数组中元素1的索引
- if (index !== -1) {
- // 如果找到了元素1,则使用splice方法删除它
- this.activeNames.splice(index, 1);
- } else {
- // 如果没有找到元素1,则将其添加到数组的末尾
- this.activeNames.push(val);
- }
- }
- ,
- onChange(event) {
- this.activeNames = event.detail
- this.$forceUpdate()
- }
- ,
- hideOverlay() {
- this.mapShow = false
- this.mapUrl = ''
- }
- ,
- showOverlayEvent(map_url) {
- this.mapShow = true
- this.mapUrl = map_url
- }
- ,
- getSceneParamsEvent(finalStr) {
- const {a, t} = finalStr.split('&').reduce((obj, pair) => {
- const [key, value] = pair.split('=');
- obj[key] = Number(value) || null; // 自动转数字
- return obj;
- }, {});
- return {a: a, t: t}
- }
- ,
- scanCodeEvent(route, r_index, e_index, exhibit) {
- if (exhibit.checkin_status === 1) {
- return false
- }
- if (this.is_receipts > 0) {
- Dialog.alert({
- message: '已经确认领取奖品,不能继续打卡',
- }).then(() => {
- });
- return false
- }
- let that = this
- wx.scanCode({
- onlyFromCamera: true,
- success(res) {
- console.log(res, 'qrcode_res')
- let scene = res.path.split('scene=')
- const decoded = decodeURIComponent(scene[1])
- .replace(/\%/g, '%25'); // 防止二次解码丢失%
- const finalStr = decodeURIComponent(decoded);
- const params = that.getSceneParamsEvent(finalStr)
- console.log(finalStr)
- if (that.routeInfoData.routes[r_index].exhibitors[e_index].exhibitor_id !== params.a) {
- Dialog.alert({
- message: '该展商和打卡二维码数据不一致',
- }).then(() => {
- });
- } else {
- that.qrcodeDecodeEvent(finalStr, () => {
- that.$set(that.routeInfoData.routes[r_index].exhibitors[e_index], 'checkin_status', 1)
- })
- }
- }
- })
- }
- ,
- qrcodeDecodeEvent(scene, callback) {
- qrcodeDecode({scene: scene}).then(res => {
- if (res.code === 0) {
- Toast.success('打卡成功');
- if (callback) {
- callback()
- }
- }
- })
- }
- ,
- getRouteListEvent(callback) {
- getRouteList().then(res => {
- this.is_receipts = res.data.is_receipts
- this.routeInfoData = res.data
- if (callback) {
- callback()
- }
- })
- }
- ,
- navigateBack() {
- uni.navigateBack(1)
- }
- ,
- gotoRule() {
- this.current_page = false
- this.scroll_top = 1
- this.$nextTick(function () {
- this.scroll_top = 0
- });
- }
- ,
- gotoPrizes() {
- uni.navigateTo({
- url: '/pages/user/award'
- })
- }
- ,
- onShareAppMessage() {
- return {
- title: '逛展会,领福利!',
- path: '/pages/checkIn/index',
- imageUrl: 'https://www.productronicachina.com.cn/resources/files/0221/67b7e5190bd22/share.png'
- }
- }
- ,
- /**
- * 返回完成进度
- * @param {Object} item exhibitors_list内的数据
- * @param {Boolean} per 是否返回百分比 true:返回0~1之间的小数;false:返回n/n格式分数。
- */
- getProcess(item, per) {
- if (!item) {
- return 0
- }
- let length = item.length
- let process = 0
- item.forEach((value, index) => {
- if (value.checkin_status)
- process++
- })
- if (per) {
- return process / length
- } else {
- return process + '/' + length
- }
- }
- },
- onLoad(option) {
- console.log(option, 'option')
- if (!store.getters.user) {
- this.navigateTo('/pages/user/login?redirect=' + encodeURIComponent('/pages/checkIn/checkInRoute?scene=' + option.scene))
- return false
- }
- this.scene = decodeURIComponent(option.scene || '');
- console.log(this.scene, 'option_this.scene')
- this.initSceneEvent()
- if (option.rule === 'true')
- this.gotoRule()
- }
- ,
- }
- </script>
- <style lang="scss">
- ::v-deep {
- .van-hairline--top, .item-index--van-hairline--top {
- border: none;
- //background-color: unset;
- box-shadow: unset;
- .item-index--van-cell {
- border: none;
- //background-color: unset;
- box-shadow: unset;
- }
- &:after {
- content: unset;
- }
- &:before {
- content: unset;
- }
- }
- }
- </style>
- <style lang="scss" scoped>
- ::v-deep {
- .van-cell, .van-collapse-item__content {
- border-radius: 20rpx;
- }
- .van-cell {
- padding-top: 66rpx;
- }
- .van-cell__right-icon-wrap {
- display: none;
- }
- .van-collapse-item {
- position: relative;
- padding-bottom: 48rpx;
- &.expand_item {
- .icon-Down {
- transform: rotate(180deg);
- }
- }
- .icon-Down {
- position: absolute;
- left: 0;
- right: 0;
- bottom: 0;
- margin: 0 auto;
- text-align: center;
- }
- }
- }
- .overlay_wrapper {
- display: flex;
- justify-content: center;
- align-items: center;
- width: 100%;
- height: 100%;
- position: relative;
- .iconfont {
- position: absolute;
- right: 30rpx;
- top: 250rpx;
- color: #ffffff;
- font-size: 40rpx;
- }
- }
- .outter {
- height: 100%;
- position: relative;
- .head_title {
- width: 100%;
- background: linear-gradient(270deg, #332968 9%, #435797 44%, #382E73 92%), rgba(0, 0, 0, 0.2);
- padding-bottom: 15px;
- display: flex;
- align-items: flex-end;
- padding-left: 28rpx;
- .title {
- display: flex;
- align-items: center;
- color: white;
- font-size: 32rpx;
- .iconfont {
- font-size: 36rpx;
- margin-right: 8rpx;
- }
- }
- }
- .body {
- overflow: hidden;
- overflow-y: auto;
- background: linear-gradient(180deg, #015A92 0%, #56A3E9 24%, #106591 98%);
- .router-item {
- position: relative;
- //padding: 60rpx 37rpx;
- border-radius: 20rpx;
- margin: 0 30rpx 56rpx;
- background-color: white;
- display: grid;
- transition-duration: 300ms;
- //overflow: hidden;
- &.fold {
- .item-body {
- padding-top: 0;
- }
- }
- .item-body {
- transition-duration: 300ms;
- padding-top: 40rpx;
- display: grid;
- grid-template-columns: 1fr 1fr 1fr;
- grid-gap: 70rpx 30rpx;
- //overflow: hidden;
- color: #333333;
- .exhibit-item {
- position: relative;
- background-color: white;
- box-shadow: 0 4rpx 20rpx 0 rgba(0, 0, 0, 0.15);
- border-radius: 10rpx;
- padding: 60rpx 16rpx 16rpx;
- transition-duration: 300ms;
- &.checked {
- background-color: #4085C7;
- color: white;
- .code {
- .text, .code-inner {
- color: white;
- }
- }
- .button {
- width: 38rpx;
- grid-gap: 0;
- border: 2rpx solid white;
- background-color: white;
- color: #4085C7;
- .text {
- width: 0;
- height: 0;
- }
- .iconfont {
- font-size: 30rpx;
- }
- }
- animation: checked 300ms;
- }
- @keyframes checked {
- 0% {
- transform: scale(1) rotate(0deg);
- }
- 50% {
- transform: scale(0.92) rotate(6deg);
- }
- 100% {
- transform: scale(1) rotate(0deg);
- }
- }
- .logo {
- background-color: white;
- position: absolute;
- left: 50%;
- transform: translate(-50%, -50%);
- top: 0;
- width: 76rpx;
- height: 76rpx;
- border: 1rpx solid #E1E1E1;
- border-radius: 6rpx;
- padding: 2rpx;
- }
- .name {
- font-size: 20rpx;
- font-weight: bold;
- margin-bottom: 10rpx;
- min-height: 60rpx;
- }
- .code {
- transition-duration: 300ms;
- margin-bottom: 10rpx;
- display: flex;
- align-items: center;
- .text {
- transition-duration: 300ms;
- color: #555555;
- font-size: 16rpx;
- }
- .code-inner {
- transition-duration: 300ms;
- color: #E57519;
- font-size: 24rpx;
- font-weight: bold;
- flex: 1;
- min-width: 1rpx;
- padding-left: 5rpx;
- }
- }
- .button {
- transition-duration: 300ms;
- margin: auto;
- width: 100%;
- height: 40rpx;
- font-size: 20rpx;
- border: 2rpx solid #D9D9D9;
- border-radius: 60rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- grid-gap: 8rpx;
- .text {
- font-size: 20rpx;
- transition-duration: 300ms;
- overflow: hidden;
- margin-top: -4rpx;
- }
- .iconfont {
- transition-duration: 300ms;
- font-size: inherit;
- }
- }
- }
- }
- .item-head {
- .route-name {
- position: absolute;
- left: 30rpx;
- top: -16rpx;
- color: white;
- border: solid 6rpx white;
- background-color: #FF9A00;
- font-size: 30rpx;
- font-weight: bold;
- padding: 15rpx 30rpx;
- border-radius: 60rpx;
- width: fit-content;
- }
- .product-type {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-top: 16rpx;
- .text {
- font-size: 32rpx;
- font-weight: bold;
- flex: 1;
- min-width: 1rpx;
- }
- .button {
- color: #4085C7;
- border: solid 3rpx #4085C7;
- border-radius: 60rpx;
- font-size: 20rpx;
- padding: 10rpx 20rpx;
- line-height: 1;
- .iconfont {
- font-size: inherit;
- margin-left: 6rpx;
- }
- }
- }
- .progress {
- position: relative;
- margin-top: 24rpx;
- height: 36rpx;
- width: 100%;
- background-color: #EBEBEB;
- border-radius: 18rpx;
- .inner {
- height: 100%;
- width: 100%;
- position: relative;
- .inner-process {
- transition-duration: 300ms;
- position: relative;
- overflow: hidden;
- height: 100%;
- width: 50%;
- background-color: #E57519;
- border-radius: 18rpx;
- .text {
- transition-duration: 300ms;
- color: white;
- }
- }
- }
- .text {
- position: absolute;
- width: 100%;
- height: 100%;
- left: 0;
- top: 0;
- color: #555555;
- font-size: 20rpx;
- line-height: 36rpx;
- text-align: center;
- /*&.disable_text {
- text-align: left;
- left: 24rpx;
- }*/
- }
- }
- }
- }
- .pagination {
- margin-bottom: 57rpx;
- .page {
- overflow: hidden;
- position: relative;
- background-color: white;
- padding: 40rpx 50rpx;
- border-radius: 20rpx;
- margin: 0 30rpx;
- .page-item {
- font-size: 24rpx;
- line-height: 1.6;
- }
- .light {
- transition-duration: 300ms;
- position: absolute;
- background: linear-gradient(75deg, #ffffff00, #ffffff 50%, #ffffff00 100%);
- width: 100%;
- height: 100%;
- left: 0;
- top: 0;
- }
- }
- .page-change {
- display: flex;
- justify-content: center;
- .page-item {
- transition-duration: 300ms;
- font-weight: bold;
- font-size: 24rpx;
- padding: 14rpx 40rpx;
- background: linear-gradient(#2D2B76 50%, #FF9A00 50%);
- background-position: 0 0;
- background-size: 100% 200%;
- color: #ffffff99;
- border-radius: 20rpx 20rpx 0 0;
- &.active {
- background-position: 0 100%;
- color: white;
- }
- }
- }
- }
- .theme-title {
- margin-top: 54rpx;
- margin-bottom: 32rpx;
- position: relative;
- height: 130rpx;
- display: flex;
- justify-content: center;
- align-items: center;
- .title {
- color: white;
- font-size: 55rpx;
- font-weight: bold;
- }
- .title-bg {
- position: absolute;
- left: 0;
- top: 0;
- height: 100%;
- }
- }
- }
- .side-button {
- position: fixed;
- right: 32rpx;
- bottom: 32rpx;
- display: flex;
- flex-direction: column;
- grid-gap: 17rpx;
- .button {
- background-color: white;
- width: 125rpx;
- height: 125rpx;
- border-radius: 50%;
- box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.25);
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- grid-gap: 6rpx;
- padding-bottom: 6rpx;
- position: relative;
- button {
- width: 100%;
- height: 100%;
- opacity: 0;
- left: 0;
- top: 0;
- position: absolute;
- }
- .title {
- color: #94A3B8;
- font-size: 24rpx;
- }
- .iconfont {
- font-size: 60rpx;
- color: #016BF3;
- }
- }
- }
- }
- </style>
|