11 changed files with 266 additions and 749 deletions
@ -1,173 +0,0 @@ |
|||
<template> |
|||
<div class="benefits-wrapper"> |
|||
<div class="carousel"> |
|||
<EffectFade :list="benefits?.fileList ?? []"> |
|||
<template v-slot="{ item }"> |
|||
<div class="banner-wrapper"> |
|||
<img class="banner" :src="config.sourceUrl + item" alt="" /> |
|||
</div> |
|||
</template> |
|||
</EffectFade> |
|||
</div> |
|||
<div class="right"> |
|||
<h1 class="title">{{ switchLanguage(benefits, 'title') }}</h1> |
|||
<ScrollView class="intro-scroll" scrollbar> |
|||
<p class="intro">{{ switchLanguage(benefits, 'content') }}</p> |
|||
</ScrollView> |
|||
<div class="right-bottom"> |
|||
<div class="group"> |
|||
<ThumbQRCode v-for="item of qr" :url="config.sourceUrl + item.fileUrl" :title="switchLanguage(item, 'name')" :key="item.name" /> |
|||
</div> |
|||
<div class="bottom-right" @click="showLoginDialog = true"> |
|||
<img src="../../assets/images/member/phone-login.png" alt="" class="phone-icon" /> |
|||
<div class="line"></div> |
|||
<div class="text-box"> |
|||
<p class="enter">点此进入</p> |
|||
<p class="text">手机号注册</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<Teleport to="body"> |
|||
<Transition enter-active-class="animate__animated animate__zoomIn" leave-active-class="animate__animated animate__zoomOut"> |
|||
<LoginByPhone @close="showLoginDialog = false" v-if="showLoginDialog" /> |
|||
</Transition> |
|||
</Teleport> |
|||
|
|||
<LoginError @close="showLoginError = false" v-if="showLoginError" /> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { ref, computed, defineAsyncComponent } from 'vue' |
|||
import { storeToRefs } from 'pinia' |
|||
import { useStore } from '@/store/root' |
|||
import EffectFade from '@/components/EffectFade/EffectFade.vue' |
|||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|||
import ThumbQRCode from '@/base/ThumbQRCode/ThumbQRCode.vue' |
|||
const LoginByPhone = defineAsyncComponent(() => import('@/components/LoginByPhone/LoginByPhone.vue')) |
|||
const LoginError = defineAsyncComponent(() => import('@/components/LoginError/LoginError.vue')) |
|||
|
|||
const props = defineProps({ |
|||
benefits: Object |
|||
}) |
|||
|
|||
const store = useStore() |
|||
const { config } = storeToRefs(store) |
|||
const qr = computed(() => props.benefits.qrFileList ?? []) |
|||
|
|||
const showLoginDialog = ref(false) |
|||
|
|||
const showLoginError = ref(false) |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.benefits-wrapper { |
|||
width: 870px; |
|||
left: 72px; |
|||
top: 344px; |
|||
background: rgba(255, 255, 255, 0.4); |
|||
box-shadow: inset 1px 0px 0px #ffffff; |
|||
border-radius: 12px; |
|||
margin-left: 170px; |
|||
margin-top: 58px; |
|||
padding-bottom: 56px; |
|||
|
|||
:deep(.swiper-pagination-bullet) { |
|||
width: 16px !important; |
|||
height: 3px !important; |
|||
background: rgba(0, 0, 0, 0.1); |
|||
border-radius: 3px !important; |
|||
opacity: inherit !important; |
|||
&.swiper-pagination-bullet-active { |
|||
background: #f1b33e; |
|||
border-radius: 3px !important; |
|||
} |
|||
} |
|||
.carousel { |
|||
flex-shrink: 0; |
|||
width: 870px; |
|||
height: 490px; |
|||
margin-right: 56px; |
|||
background: #ffffff; |
|||
border-radius: 8px; |
|||
overflow: hidden; |
|||
} |
|||
.banner { |
|||
width: 100%; |
|||
height: 100%; |
|||
object-fit: cover; |
|||
} |
|||
} |
|||
.right-bottom { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
padding-right: 56px; |
|||
margin-left: 56px; |
|||
} |
|||
.bottom-right { |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
width: 328px; |
|||
height: 146px; |
|||
background: #ffffff; |
|||
box-shadow: 0px 8px 20px rgba(0, 0, 0, 0.03), inset 0px -4px 0px rgba(177, 189, 220, 0.1); |
|||
border-radius: 8px; |
|||
.phone-icon { |
|||
width: 48px; |
|||
height: 48px; |
|||
} |
|||
.line { |
|||
width: 1px; |
|||
height: 38px; |
|||
left: 134px; |
|||
top: 54px; |
|||
background: rgba(0, 0, 0, 0.1); |
|||
margin: 0 26px; |
|||
} |
|||
.enter { |
|||
font-weight: 700; |
|||
font-size: 16px; |
|||
color: rgba(0, 0, 0, 0.4); |
|||
padding-bottom: 4px; |
|||
font-family: 'font_bold'; |
|||
} |
|||
.text { |
|||
font-weight: 700; |
|||
font-size: 20px; |
|||
text-align: center; |
|||
font-family: 'font_bold'; |
|||
color: rgba(0, 0, 0, 0.6); |
|||
} |
|||
} |
|||
|
|||
.title { |
|||
padding-top: 48px; |
|||
font-weight: 700; |
|||
font-family: 'font_bold'; |
|||
font-size: 24px; |
|||
line-height: 28px; |
|||
color: rgba(0, 0, 0, 0.8); |
|||
padding-bottom: 32px; |
|||
margin-left: 56px; |
|||
} |
|||
|
|||
.intro-scroll { |
|||
position: relative; |
|||
height: 156px; |
|||
overflow: hidden; |
|||
margin-left: 56px; |
|||
margin-right: 34px; |
|||
padding-right: 16px; |
|||
margin-bottom: 67px; |
|||
.intro { |
|||
font-weight: 400; |
|||
font-size: 14px; |
|||
line-height: 200%; |
|||
text-align: justify; |
|||
color: rgba(0, 0, 0, 0.6); |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,121 @@ |
|||
<template> |
|||
<div class="benefits-wrapper"> |
|||
<div class="carousel"> |
|||
<EffectFade :list="data?.fileList ?? []"> |
|||
<template v-slot="{ item }"> |
|||
<div class="banner-wrapper"> |
|||
<img class="banner" :src="config.sourceUrl + item" alt="" /> |
|||
</div> |
|||
</template> |
|||
</EffectFade> |
|||
</div> |
|||
<div class="right"> |
|||
<h1 class="title">{{ switchLanguage(data, 'title') }}</h1> |
|||
<ScrollView class="intro-scroll" scrollbar> |
|||
<p class="intro"> |
|||
{{ switchLanguage(data, 'content') }} |
|||
</p> |
|||
</ScrollView> |
|||
<div class="qrcodeWrapper"> |
|||
<ThumbQRCode class="item" v-for="item of qr" :url="config.sourceUrl + item.fileUrl" :title="switchLanguage(item, 'name')" :key="item.name" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { ref, computed, defineAsyncComponent } from 'vue' |
|||
import { storeToRefs } from 'pinia' |
|||
import { useStore } from '@/store/root' |
|||
import EffectFade from '@/components/EffectFade/EffectFade.vue' |
|||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|||
import ThumbQRCode from '@/base/ThumbQRCode/ThumbQRCode.vue' |
|||
|
|||
const props = defineProps({ |
|||
data: Object |
|||
}) |
|||
|
|||
const store = useStore() |
|||
const { config } = storeToRefs(store) |
|||
const qr = computed(() => props.data.qrFileList ?? []) |
|||
|
|||
const showLoginDialog = ref(false) |
|||
|
|||
const showLoginError = ref(false) |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.benefits-wrapper { |
|||
display: flex; |
|||
flex-direction: column; |
|||
width: 100%; |
|||
flex: 1; |
|||
align-items: center; |
|||
padding-top: 48px; |
|||
|
|||
.carousel { |
|||
flex-shrink: 0; |
|||
width: 944px; |
|||
height: 548px; |
|||
|
|||
overflow: hidden; |
|||
:deep(.swiper) { |
|||
overflow: visible; |
|||
.swiper-pagination { |
|||
bottom: -16px; |
|||
.swiper-pagination-bullet { |
|||
width: 34px !important; |
|||
height: 4px !important; |
|||
background: rgba(0, 0, 0, 0.6); |
|||
border-radius: 6px !important; |
|||
opacity: inherit !important; |
|||
margin: 0; |
|||
&.swiper-pagination-bullet-active { |
|||
background: #ffffff; |
|||
border-radius: 6px !important; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
.banner { |
|||
width: 944px; |
|||
height: 532px; |
|||
border-radius: 8px; |
|||
object-fit: cover; |
|||
} |
|||
} |
|||
} |
|||
.qrcodeWrapper { |
|||
display: flex; |
|||
margin-left: 68px; |
|||
.item { |
|||
margin-right: 10px; |
|||
} |
|||
} |
|||
.title { |
|||
padding-top: 32px; |
|||
padding-left: 68px; |
|||
font-weight: 700; |
|||
font-size: 28px; |
|||
line-height: 150%; |
|||
color: rgba(0, 0, 0, 0.8); |
|||
} |
|||
|
|||
.intro-scroll { |
|||
position: relative; |
|||
height: 250px; |
|||
overflow: hidden; |
|||
margin-left: 68px; |
|||
margin-right: 31px; |
|||
padding-right: 31px; |
|||
margin-bottom: 33px; |
|||
margin-top: 32px; |
|||
.intro { |
|||
font-weight: 400; |
|||
font-size: 16px; |
|||
line-height: 200%; |
|||
text-align: justify; |
|||
color: rgba(0, 0, 0, 0.6); |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,82 @@ |
|||
<template> |
|||
<div class="tabs" v-if="sidebarList.find(({ path }) => path === $route.path)"> |
|||
<div :class="['item', tab.path === $route.path ? 'active' : '']" v-for="tab of sidebarList" :key="tab.title" @click="goPage(tab)"> |
|||
<div class="icon"><img :src="tab.icon" /></div> |
|||
<div class="title">{{ switchLanguage(tab, 'title') }}</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { useStore } from '@/store/root' |
|||
import { storeToRefs } from 'pinia' |
|||
import { useRouter } from 'vue-router' |
|||
const router = useRouter() |
|||
const store = useStore() |
|||
const { sidebarList } = storeToRefs(store) |
|||
const goPage = item => { |
|||
store.SET_SELECTED_MODULE(item.title) |
|||
router.push(item.path) |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.tabs { |
|||
position: fixed; |
|||
top: 400px; |
|||
left: 68px; |
|||
right: 68px; |
|||
display: flex; |
|||
.item { |
|||
position: relative; |
|||
display: flex; |
|||
flex-direction: column; |
|||
flex: 1; |
|||
height: 170px; |
|||
.icon { |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
height: 97px; |
|||
background: rgba(255, 255, 255, 0.4); |
|||
border-radius: 24px; |
|||
img { |
|||
width: 80px; |
|||
height: 80px; |
|||
} |
|||
} |
|||
.title { |
|||
font-weight: 700; |
|||
font-size: 18px; |
|||
line-height: 21px; |
|||
text-align: center; |
|||
color: rgba(0, 0, 0, 0.4); |
|||
margin-top: 12px; |
|||
} |
|||
&.active { |
|||
.icon { |
|||
background: #ffffff; |
|||
} |
|||
.title { |
|||
color: rgba(0, 0, 0, 0.8); |
|||
} |
|||
&::after { |
|||
content: ''; |
|||
display: block; |
|||
position: absolute; |
|||
width: 124px; |
|||
height: 6px; |
|||
left: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
margin: auto; |
|||
background: linear-gradient(113.71deg, #435acd 0%, #749cf3 100%); |
|||
border-radius: 2px 2px 0px 0px; |
|||
} |
|||
} |
|||
} |
|||
.item + .item { |
|||
margin-left: 24px; |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,21 @@ |
|||
<template> |
|||
<View long> |
|||
<CarouselWithIntro :data="mall" /> |
|||
</View> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { ref } from 'vue' |
|||
import { getMallInfoList } from '@/http/api' |
|||
import View from '@/layouts/View.vue' |
|||
import CarouselWithIntro from '@/components/CarouselWithIntro/CarouselWithIntro.vue' |
|||
|
|||
const mall = ref({}) |
|||
getMallInfoList().then(({ data }) => { |
|||
if (!data.title) data.title = '商场介绍' |
|||
mall.value = data |
|||
}) |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
</style> |
|||
@ -1,318 +1,21 @@ |
|||
<template> |
|||
<View title="热门电影" sub-title="Popular Movies"> |
|||
<div class="content"> |
|||
<div class="movie-left"> |
|||
<div class="carousel"> |
|||
<EffectFade :list="banner"> |
|||
<template v-slot="{ item }"> |
|||
<div class="banner-wrapper"> |
|||
<img :src="config.sourceUrl + item" class="banner" alt="" /> |
|||
</div> |
|||
</template> |
|||
</EffectFade> |
|||
</div> |
|||
|
|||
<div class="top-right"> |
|||
<div class="go"> |
|||
<img src="../../assets/images/fly.png" class="fly" alt="" /> |
|||
<div class="text-wrapper"> |
|||
<p class="en">GO HERE!</p> |
|||
<p class="text">去这里!</p> |
|||
</div> |
|||
</div> |
|||
<h1 class="title">{{ switchLanguage(cinema, 'shopName') }}</h1> |
|||
</div> |
|||
</div> |
|||
<ScrollView class="intro-scroll" scrollbar :list="cinema.content"> |
|||
<p class="intro"> |
|||
欧时力(香港)集团全权代理意大利品牌欧时力(OCHIRLY),并组建欧时力(中国)有限公司,全权负责OCHIRLY在大中华区的品牌经营。欧时力自1999年进入中国市场以来,欧时力以前所未有的速度在中国市场发展壮大。在短短的两、三年间,迅速于中国60多个一、二类主要消费城市的160余家加盟店以及专柜年销售额达到2.5亿。销售业绩评效均名列前茅,整体业绩不断上扬!在女装市场享有一定的知名度和美誉度。欧时力(香港)集团全权代理意大利品牌欧时力(OCHIRLY),并组建欧时力(中国)有限公司,全权负责OCHIRLY在大中华区的品牌经营。欧时力自1999年进入中国市场以来,欧时力以前所未有的速度在中国市场发展壮大。在短短的两、三年间,迅速于中国60多个一、二类主要消费城市的160余家加盟店以及专柜年销售额达到2.5亿在短短的两、三年间,迅速于中国60多个一、二类主要消费城市的160余家加盟店以及专柜年销售额达到2.5亿在短短的两、三年间,迅速于中 |
|||
</p> |
|||
</ScrollView> |
|||
<ScrollView class="movie-scroll"> |
|||
<TransitionGroup tag="div" name="zoom" class="scroll-content"> |
|||
<div class="movie-item" v-for="item of list" @click="handleMovie(item)" :key="item.id"> |
|||
<div class="poster-wrapper"> |
|||
<img class="poster" :src="item.posterPath" alt="" /> |
|||
</div> |
|||
<p class="name">{{ item.showName }}</p> |
|||
<div class="info">{{ item.duration }}{{ $t('fenzhong') }} | {{ item.type }} | {{ item.language }} | {{ item.director }}</div> |
|||
<div class="remark"> |
|||
<span>{{ $t('rate') }}</span> |
|||
{{ item.remark }} |
|||
</div> |
|||
<div class="price"> |
|||
<div class="price-num">¥<i>36</i>起</div> |
|||
<div class="buy">{{ $t('ticket') }}</div> |
|||
</div> |
|||
</div> |
|||
</TransitionGroup> |
|||
</ScrollView> |
|||
</div> |
|||
<View long> |
|||
<CarouselWithIntro :data="mall" /> |
|||
</View> |
|||
<Transition enter-active-class="animate__animated animate__fadeIn" leave-active-class="animate__animated animate__fadeOut"> |
|||
<MovieDetail :movie="movie" @close="showDetail = false" v-if="showDetail" /> |
|||
</Transition> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { computed, ref } from 'vue' |
|||
import { storeToRefs } from 'pinia' |
|||
import { useStore } from '@/store/root' |
|||
import { list } from './mock' |
|||
import { ref } from 'vue' |
|||
import { getCinemaInfo } from '@/http/api' |
|||
import View from '@/layouts/View.vue' |
|||
import EffectFade from '@/components/EffectFade/EffectFade.vue' |
|||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|||
import MovieDetail from '@/components/MovieDetail/MovieDetail.vue' |
|||
|
|||
const store = useStore() |
|||
const { config, shopList } = storeToRefs(store) |
|||
import CarouselWithIntro from '@/components/CarouselWithIntro/CarouselWithIntro.vue' |
|||
|
|||
const cinema = ref({}) |
|||
const banner = computed(() => cinema.value?.doorMaterialList ?? []) |
|||
getCinemaInfo(({ data }) => { |
|||
const { cinemaCode = '' } = data |
|||
cinema.value = shopList.value.find(item => item.shopId === cinemaCode) ?? {} |
|||
const mall = ref({}) |
|||
getCinemaInfo().then(({ data }) => { |
|||
console.log(data) |
|||
mall.value = data |
|||
}) |
|||
|
|||
const showDetail = ref(false) |
|||
const movie = ref({}) |
|||
function handleMovie(item) { |
|||
movie.value = item |
|||
showDetail.value = true |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.content { |
|||
width: 870px; |
|||
height: 1504px; |
|||
margin-left: 170px; |
|||
margin-top: 58px; |
|||
background: rgba(255, 255, 255, 0.4); |
|||
border-radius: 12px; |
|||
} |
|||
.flex { |
|||
display: flex; |
|||
} |
|||
.movie-left { |
|||
display: flex; |
|||
position: relative; |
|||
border-radius: 12px; |
|||
margin-bottom: 32px; |
|||
.go { |
|||
position: relative; |
|||
display: flex; |
|||
align-items: center; |
|||
width: 282px; |
|||
height: 80px; |
|||
background: linear-gradient(90deg, #f6a62c 0%, #ffbc3f 100%); |
|||
font-weight: 700; |
|||
font-family: 'font_bold'; |
|||
color: #ffffff; |
|||
margin-top: 32px; |
|||
border-radius: 53px; |
|||
&::before { |
|||
position: absolute; |
|||
content: ''; |
|||
top: 25px; |
|||
left: 105px; |
|||
width: 1px; |
|||
height: 30px; |
|||
background: rgba(255, 255, 255, 0.2); |
|||
} |
|||
.fly { |
|||
width: 40px; |
|||
margin: 0 40px; |
|||
} |
|||
.en { |
|||
font-size: 20px; |
|||
} |
|||
.text { |
|||
font-size: 16px; |
|||
} |
|||
} |
|||
:deep(.swiper) { |
|||
overflow: visible !important; |
|||
z-index: auto; |
|||
} |
|||
:deep(.swiper-pagination) { |
|||
right: 32px; |
|||
left: auto; |
|||
bottom: -15px; |
|||
width: auto; |
|||
} |
|||
:deep(.swiper-pagination-bullet) { |
|||
width: 16px !important; |
|||
height: 3px !important; |
|||
background: rgba(0, 0, 0, 0.1); |
|||
border-radius: 3px !important; |
|||
opacity: inherit !important; |
|||
&.swiper-pagination-bullet-active { |
|||
background: #f1b33e; |
|||
border-radius: 3px !important; |
|||
} |
|||
} |
|||
.carousel { |
|||
flex-shrink: 0; |
|||
position: relative; |
|||
display: inline-block; |
|||
margin-left: 40px; |
|||
margin-right: 24px; |
|||
width: 500px; |
|||
height: 282px; |
|||
margin-top: -40px; |
|||
background-color: #fff; |
|||
border-radius: 10px; |
|||
overflow: hidden; |
|||
:deep(.stay-tuned) { |
|||
height: 200px; |
|||
} |
|||
} |
|||
.banner-wrapper { |
|||
width: 500px; |
|||
height: 282px; |
|||
overflow: hidden; |
|||
border-radius: 8px; |
|||
background: #ffffff; |
|||
.banner { |
|||
width: 100%; |
|||
height: 100%; |
|||
object-fit: cover; |
|||
} |
|||
} |
|||
|
|||
.title { |
|||
font-weight: 700; |
|||
font-size: 24px; |
|||
color: rgba(0, 0, 0, 0.8); |
|||
font-family: 'font_bold'; |
|||
padding-top: 102px; |
|||
text-align: right; |
|||
padding-right: 40px; |
|||
} |
|||
} |
|||
.intro-scroll { |
|||
position: relative; |
|||
margin: 0 18px 52px 40px; |
|||
padding-right: 16px; |
|||
overflow: hidden; |
|||
height: 131px; |
|||
z-index: 1; |
|||
:deep(.bscroll-vertical-scrollbar) { |
|||
width: 6px !important; |
|||
background: rgba(0, 0, 0, 0.02) !important; |
|||
border-radius: 6px !important; |
|||
opacity: 1 !important; |
|||
.bscroll-indicator { |
|||
width: 6px !important; |
|||
background: rgba(0, 0, 0, 0.1) !important; |
|||
border-radius: 6px !important; |
|||
border: none !important; |
|||
} |
|||
} |
|||
.intro { |
|||
font-weight: 400; |
|||
font-size: 14px; |
|||
line-height: 200%; |
|||
text-align: justify; |
|||
color: rgba(0, 0, 0, 0.6); |
|||
} |
|||
} |
|||
.movie-scroll { |
|||
flex: 1; |
|||
overflow: hidden; |
|||
border-radius: 12px 0 0 12px; |
|||
margin-left: 40px; |
|||
height: 1103px; |
|||
|
|||
.scroll-content { |
|||
display: grid; |
|||
grid-template-columns: repeat(3, 260px); |
|||
gap: 36px 8px; |
|||
padding-bottom: 36px; |
|||
} |
|||
|
|||
.movie-item { |
|||
width: 260px; |
|||
height: 600px; |
|||
background: #ffffff; |
|||
border-radius: 12px; |
|||
padding: 4px; |
|||
margin-right: 24px; |
|||
} |
|||
.poster-wrapper { |
|||
width: 252px; |
|||
height: 380px; |
|||
border-radius: 8px; |
|||
overflow: hidden; |
|||
margin-bottom: 24px; |
|||
.poster { |
|||
width: 100%; |
|||
height: 100%; |
|||
object-fit: cover; |
|||
} |
|||
} |
|||
.name { |
|||
font-weight: 700; |
|||
font-size: 20px; |
|||
color: rgba(0, 0, 0, 0.8); |
|||
@include no-wrap; |
|||
padding-bottom: 20px; |
|||
padding-left: 24px; |
|||
} |
|||
.info { |
|||
height: 28px; |
|||
font-weight: 400; |
|||
font-size: 12px; |
|||
line-height: 14px; |
|||
color: rgba(0, 0, 0, 0.4); |
|||
@include more-wrap; |
|||
padding-left: 24px; |
|||
padding-right: 24px; |
|||
margin-bottom: 14px; |
|||
white-space: normal; |
|||
} |
|||
.remark { |
|||
font-weight: 700; |
|||
color: rgba(0, 0, 0, 0.6); |
|||
padding-bottom: 10px; |
|||
margin-left: 24px; |
|||
margin-right: 24px; |
|||
margin-bottom: 16px; |
|||
border-bottom: 1px solid rgba(0, 0, 0, 0.02); |
|||
|
|||
span { |
|||
font-size: 16px; |
|||
} |
|||
} |
|||
|
|||
.price { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
padding-left: 24px; |
|||
padding-right: 24px; |
|||
color: #f1b33e; |
|||
font-weight: 700; |
|||
font-family: 'font_bold'; |
|||
.price-num { |
|||
font-size: 16px; |
|||
i { |
|||
font-size: 32px; |
|||
padding: 0 4px; |
|||
} |
|||
} |
|||
} |
|||
.buy { |
|||
width: 98px; |
|||
height: 38px; |
|||
background: linear-gradient(90deg, #f6a62c 0%, #ffbc3f 100%); |
|||
border-radius: 8px; |
|||
line-height: 38px; |
|||
text-align: center; |
|||
font-weight: 700; |
|||
font-size: 14px; |
|||
color: #ffffff; |
|||
} |
|||
} |
|||
</style> |
|||
|
|||
@ -1,227 +1,20 @@ |
|||
<template> |
|||
<View class="bef" title="泊车缴费" sub-title="parking payment"> |
|||
<Tabs class="width" @click="handleTab" :list="list" /> |
|||
<div class="carousel"> |
|||
<EffectFade :list="banners"> |
|||
<template v-slot="{ item }"> |
|||
<div class="banner-wrapper"> |
|||
<img :src="config.sourceUrl + item" class="banner" alt="" /> |
|||
</div> |
|||
</template> |
|||
</EffectFade> |
|||
</div> |
|||
<PlateInput @confirm="confirm" @handle-energy="handleEnergy" :search-methods="searchMethods" :license="license" :needsEnergy="needsEnergy" /> |
|||
<PlateKeyboard @del="del" @handle-keyboard="handleKeyboard" :search-methods="searchMethods" /> |
|||
<div class="parking-info"> |
|||
<h1 class="title">{{ switchLanguage(parkingInfo, 'title') }}</h1> |
|||
<ScrollView class="intro-scroll" scrollbar :list="parkingInfo.content"> |
|||
<p class="intro">{{ switchLanguage(parkingInfo, 'content') }}</p> |
|||
</ScrollView> |
|||
</div> |
|||
<View long> |
|||
<CarouselWithIntro :data="park" /> |
|||
</View> |
|||
<Transition enter-active-class="animate__animated animate__fadeIn" leave-active-class="animate__animated animate__fadeOut"> |
|||
<CarInfo v-if="showCarInfo" @close="showCarInfo = false" /> |
|||
</Transition> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import Message from '@/base/Message/Message' |
|||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|||
import EffectFade from '@/components/EffectFade/EffectFade.vue' |
|||
import PlateInput from '@/components/PlateInput/PlateInput.vue' |
|||
import PlateKeyboard from '@/components/PlateKeyboard/PlateKeyboard.vue' |
|||
import Tabs from '@/components/Tabs/Tabs.vue' |
|||
import { ref } from 'vue' |
|||
import { getParkingList } from '@/http/api' |
|||
import View from '@/layouts/View.vue' |
|||
import { useStore } from '@/store/root' |
|||
import { isLicensePlate, isUppercaseWord, isZhWord } from '@/utils/utils' |
|||
import { storeToRefs } from 'pinia' |
|||
import { computed, defineAsyncComponent, ref, watch } from 'vue' |
|||
import { list } from './tabs' |
|||
import Shop from '@/utils/Class/Shop' |
|||
import { useRouter } from 'vue-router' |
|||
const CarInfo = defineAsyncComponent(() => import('@/components/CarInfo/CarInfo.vue')) |
|||
|
|||
const NOT_ENERGY_PLATE = 7 //非能源车牌长度 |
|||
const ENERGY_PLATE = 8 //能源车牌长度 |
|||
const SPACE_MAX_LENGTH = 5 //车位最大允许长度 |
|||
|
|||
const router = useRouter() |
|||
const store = useStore() |
|||
const { config, currentBuildingFloorsList } = storeToRefs(store) |
|||
|
|||
const tabIdx = ref(0) |
|||
const needsEnergy = computed(() => tabIdx.value === 0) |
|||
const searchMethods = computed(() => (tabIdx.value === 0 ? '车牌' : '车位')) |
|||
function handleTab(index) { |
|||
tabIdx.value = index |
|||
license.value = index === 0 ? ['苏', 'A'] : [] |
|||
} |
|||
|
|||
const isEnergy = ref(false) |
|||
const license = ref(['苏', 'A']) |
|||
const licenseToString = computed(() => license.value.join('')) |
|||
function handleKeyboard(item) { |
|||
if (license.value.length === 1 && isZhWord(item)) { |
|||
license.value[0] = item |
|||
return |
|||
} |
|||
|
|||
if (tabIdx.value === 0) { |
|||
if ( |
|||
(!isEnergy.value && license.value.length >= NOT_ENERGY_PLATE) || |
|||
(isEnergy.value && license.value.length >= ENERGY_PLATE) || |
|||
(license.value.length === 0 && !isZhWord(item)) || |
|||
(license.value.length === 1 && !isUppercaseWord(item)) || |
|||
(license.value.length >= 2 && license.value.length < 6 && isZhWord(item)) |
|||
) { |
|||
return |
|||
} |
|||
} else { |
|||
if (license.value.length >= SPACE_MAX_LENGTH) return |
|||
} |
|||
|
|||
license.value.push(item) |
|||
} |
|||
function del() { |
|||
license.value.pop() |
|||
} |
|||
import CarouselWithIntro from '@/components/CarouselWithIntro/CarouselWithIntro.vue' |
|||
|
|||
//点击能源输入框 |
|||
function handleEnergy(flag) { |
|||
isEnergy.value = flag |
|||
license.value.length >= ENERGY_PLATE && license.value.pop() |
|||
} |
|||
|
|||
//找车 |
|||
function confirm() { |
|||
if (tabIdx.value === 0) { |
|||
//TODO |
|||
Message({ text: '抱歉暂时无法使用车牌找车', type: 'success' }) |
|||
} else { |
|||
//车位 |
|||
const info = window.Map_QM.pathPark({ shopNum: license.value }) |
|||
if (info?.node?.length) { |
|||
const floorName = currentBuildingFloorsList.value.filter(item => item.order === info.floor)?.[0]?.name |
|||
const shop = new Shop({ name: license.value, floorOrder: info.floor, floorName, logoPath: '/static/img/tcc/png', yaxis: info.node }) |
|||
store.SET_SHOP(shop) |
|||
router.push('/nav') |
|||
} else { |
|||
Message({ text: `暂未查到车位信息`, type: 'success' }) |
|||
license.value = [] |
|||
} |
|||
} |
|||
} |
|||
|
|||
watch( |
|||
license, |
|||
newVal => { |
|||
newVal.length === (isEnergy.value ? ENERGY_PLATE : NOT_ENERGY_PLATE) && !isLicensePlate(licenseToString.value) && Message({ text: '车牌错误', type: 'success' }) |
|||
}, |
|||
{ |
|||
deep: true |
|||
} |
|||
) |
|||
|
|||
const parkingInfo = ref({}) |
|||
const banners = computed(() => parkingInfo.value.fileList ?? []) |
|||
const park = ref({}) |
|||
getParkingList().then(({ data }) => { |
|||
parkingInfo.value = data ?? {} |
|||
park.value = data |
|||
}) |
|||
|
|||
const showCarInfo = ref(false) |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.flex { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
} |
|||
.width { |
|||
position: absolute !important; |
|||
top: 214px !important; |
|||
left: 170px !important; |
|||
width: 468px !important; |
|||
height: 88px !important; |
|||
} |
|||
.carousel { |
|||
position: relative; |
|||
width: 870px; |
|||
height: 490px; |
|||
margin-left: 170px; |
|||
margin-top: 58px; |
|||
margin-bottom: 80px; |
|||
:deep(.swiper) { |
|||
overflow: visible !important; |
|||
z-index: auto; |
|||
} |
|||
:deep(.swiper-pagination) { |
|||
bottom: -24px; |
|||
} |
|||
:deep(.swiper-pagination-bullet) { |
|||
width: 16px !important; |
|||
height: 3px !important; |
|||
background: rgba(0, 0, 0, 0.1); |
|||
border-radius: 3px !important; |
|||
opacity: inherit !important; |
|||
&.swiper-pagination-bullet-active { |
|||
background: #f1b33e; |
|||
border-radius: 3px !important; |
|||
} |
|||
} |
|||
} |
|||
.banner-wrapper { |
|||
width: 870px; |
|||
height: 490px; |
|||
overflow: hidden; |
|||
border-radius: 8px; |
|||
background: #ffffff; |
|||
.banner { |
|||
width: 100%; |
|||
height: 100%; |
|||
object-fit: cover; |
|||
} |
|||
} |
|||
|
|||
.parking-info { |
|||
margin-left: 170px; |
|||
margin-right: 40px; |
|||
background: rgba(255, 255, 255, 0.4); |
|||
border-radius: 12px; |
|||
height: 532px; |
|||
|
|||
.title { |
|||
padding: 48px 0 32px 56px; |
|||
font-weight: 700; |
|||
font-size: 24px; |
|||
color: rgba(0, 0, 0, 0.8); |
|||
font-family: 'font_bold'; |
|||
} |
|||
|
|||
.intro-scroll { |
|||
position: relative; |
|||
margin: 0 34px 0 56px; |
|||
overflow: hidden; |
|||
height: 372px; |
|||
:deep(.bscroll-vertical-scrollbar) { |
|||
width: 6px !important; |
|||
background: rgba(0, 0, 0, 0.02) !important; |
|||
border-radius: 6px !important; |
|||
opacity: 1 !important; |
|||
.bscroll-indicator { |
|||
width: 6px !important; |
|||
background: rgba(0, 0, 0, 0.1) !important; |
|||
border-radius: 6px !important; |
|||
border: none !important; |
|||
} |
|||
} |
|||
.intro { |
|||
font-weight: 400; |
|||
font-size: 14px; |
|||
line-height: 200%; |
|||
text-align: justify; |
|||
color: rgba(0, 0, 0, 0.6); |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
|
|||
Loading…
Reference in new issue