Browse Source

feat: 商场、电影、会员、泊车

潮流
jiannibang 4 years ago
parent
commit
d7d600a80d
  1. 25
      src/base/ThumbQRCode/ThumbQRCode.vue
  2. 173
      src/components/Benefits/Benefits.vue
  3. 121
      src/components/CarouselWithIntro/CarouselWithIntro.vue
  4. 2
      src/components/PublicComponent/PublicComponent.vue
  5. 82
      src/components/PublicComponent/Tabs.vue
  6. 2
      src/layouts/Dialog.vue
  7. 9
      src/router/routes.js
  8. 21
      src/views/Mall/Mall.vue
  9. 48
      src/views/Member/Member.vue
  10. 313
      src/views/Movie/Movie.vue
  11. 219
      src/views/Parking/Parking.vue

25
src/base/ThumbQRCode/ThumbQRCode.vue

@ -16,26 +16,25 @@ defineProps({
.code-wrapper {
display: flex;
flex-direction: column;
justify-content: center;
justify-content: flex-start;
align-items: center;
padding-top: 8px;
width: 116px;
min-height: 146px;
background: linear-gradient(90deg, #ffbd35 0%, #ffd260 100%);
border-radius: 12px;
padding-top: 15px;
width: 180px;
height: 220px;
background: #fff;
border-radius: 8px;
.code-icon {
width: 100px;
height: 100px;
width: 150px;
height: 150px;
padding: 14px;
}
.tips {
font-weight: 700;
font-family: 'font_bold';
font-size: 12px;
line-height: 14px;
font-size: 14px;
line-height: 16px;
text-align: center;
color: rgba(0, 0, 0, 0.8);
padding-top: 12px;
padding-top: 15px;
}
}
</style>

173
src/components/Benefits/Benefits.vue

@ -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>

121
src/components/CarouselWithIntro/CarouselWithIntro.vue

@ -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>

2
src/components/PublicComponent/PublicComponent.vue

@ -20,6 +20,7 @@
<Temperature />
<Time />
<SearchBar />
<Tabs />
</template>
<script setup>
@ -38,6 +39,7 @@ const Search = defineAsyncComponent(() => import('@/components/Search/Search.vue
const Temperature = defineAsyncComponent(() => import('@/base/Temperature/Temperature.vue'))
const Time = defineAsyncComponent(() => import('@/base/Time/Time.vue'))
const SearchBar = defineAsyncComponent(() => import('./SearchBar.vue'))
const Tabs = defineAsyncComponent(() => import('./Tabs.vue'))
const router = useRouter()
const route = useRoute()

82
src/components/PublicComponent/Tabs.vue

@ -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>

2
src/layouts/Dialog.vue

@ -20,7 +20,7 @@ function close() {
right: 0;
bottom: 0;
left: 0;
z-index: 90;
z-index: 10000;
background: rgba(0, 0, 0, 0.6);
animation-duration: 0.2s;
}

9
src/router/routes.js

@ -48,6 +48,15 @@ export const staticRoutes = [
showMap: false
}
},
{
path: '/mall',
name: 'Mall',
component: () => import(/* webpackChunkName: "member" */ '@/views/Mall/Mall'),
meta: {
showMenu: true,
showMap: false
}
},
{
path: '/parking',
name: 'Parking',

21
src/views/Mall/Mall.vue

@ -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>

48
src/views/Member/Member.vue

@ -1,49 +1,16 @@
<template>
<View title="会员专享" sub-title="member privileges">
<Tabs class="width" @click="handleTab" :list="list" />
<ActivitiesList :list="activityList" v-if="tabIdx === 0" />
<Benefits :benefits="benefits" v-else-if="tabIdx === 1" />
<Busniness v-else />
<View long>
<CarouselWithIntro :data="benefits" />
</View>
</template>
<script setup>
import { ref, defineAsyncComponent } from 'vue'
import { list } from './tabs'
import { getActivityList, getMemberBenefits } from '@/http/api'
import View from '@/layouts/View.vue'
import Tabs from '@/components/Tabs/Tabs.vue'
const ActivitiesList = defineAsyncComponent(() => import('@/components/ActivitiesList/ActivitiesList.vue'))
const Benefits = defineAsyncComponent(() => import('@/components/Benefits/Benefits.vue'))
const Busniness = defineAsyncComponent(() => import('@/components/Busniness/Busniness.vue'))
const activityList = ref([])
const tabIdx = ref(0)
_getActivityList(3)
function handleTab(index) {
tabIdx.value = index
switch (index) {
case 0:
_getActivityList(3)
break
case 1:
_getMemberBenefits()
break
case 2:
break
default:
break
}
}
function _getActivityList(type) {
getActivityList(type).then(({ data }) => {
activityList.value = data?.activityList ?? []
})
}
import CarouselWithIntro from '@/components/CarouselWithIntro/CarouselWithIntro.vue'
_getMemberBenefits()
const benefits = ref({})
function _getMemberBenefits() {
getMemberBenefits().then(({ data }) => {
@ -53,11 +20,4 @@ function _getMemberBenefits() {
</script>
<style lang="scss" scoped>
.width {
position: absolute;
top: 214px;
left: 170px;
width: 491px;
height: 88px;
}
</style>

313
src/views/Movie/Movie.vue

@ -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>

219
src/views/Parking/Parking.vue

@ -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'))
import CarouselWithIntro from '@/components/CarouselWithIntro/CarouselWithIntro.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()
}
//
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…
Cancel
Save