@ -1 +1,21 @@ |
|||||
{"code":200,"msg":"操作成功","data":{"hotSearch":[{"shopId":271,"shopName":"十日后"},{"shopId":506,"shopName":"弥小爷虾滑"},{"shopId":273,"shopName":"谭木匠"},{"shopId":425,"shopName":"星巴克"},{"shopId":485,"shopName":"荔滋烫捞"}],"temperature":25,"columnList":[{"moduleType":1,"name":"好吃的","nameEn":"DELICIOUS","introduce":"好吃的","introduceEn":"大吉大利今晚吃鸡","crossFileUrl":"/iotFile/2022/06/30/48001398f98b43ea9ba4b4a27e1bbe16.png","verticalFileUrl":"/iotFile/2022/06/21/ea1dfb78855e4ce9b9d0ab1b6e3a307d.png"},{"moduleType":2,"name":"好玩的","nameEn":"FUN","introduce":"好玩的","crossFileUrl":"/iotFile/2022/06/30/f94b26b8157f410b93f8346568a1766d.png","verticalFileUrl":"/iotFile/2022/06/21/50ac7a32182c469aa684dc34cfb11f21.png"},{"moduleType":3,"name":"值得买","nameEn":"WORTH TO BUY","introduce":"值得买","crossFileUrl":"/iotFile/2022/06/30/b85955b2f68a42938c886fac16278aa9.png","verticalFileUrl":"/iotFile/2022/06/20/f7515243eb234e00ae40fe662f79d484.png"}],"status":"多云转晴"}} |
|
||||
|
{ |
||||
|
"code": 200, |
||||
|
"msg": "操作成功", |
||||
|
"data": { |
||||
|
"temperature": "11", |
||||
|
"columnList": [], |
||||
|
"hotSearch": [ |
||||
|
{ "shopId": 43, "shopName": "心血管超声(心超)诊室2" }, |
||||
|
{ "shopId": 63, "shopName": "临床心里科会议室" }, |
||||
|
{ "shopId": 66, "shopName": "临床心里科诊室2" }, |
||||
|
{ "shopId": 96, "shopName": "内镜手术室1" }, |
||||
|
{ "shopId": 102, "shopName": "消化内镜中心VIP诊室2" }, |
||||
|
{ "shopId": 155, "shopName": "妇科门诊护士台" }, |
||||
|
{ "shopId": 286, "shopName": "呼吸内科/胸外科诊室1" }, |
||||
|
{ "shopId": 342, "shopName": "儿科检验" }, |
||||
|
{ "shopId": 358, "shopName": "特需门诊3" }, |
||||
|
{ "shopId": 367, "shopName": "特需门诊19" } |
||||
|
], |
||||
|
"status": "晴" |
||||
|
} |
||||
|
} |
||||
|
|||||
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 302 KiB |
|
Before Width: | Height: | Size: 404 KiB |
|
Before Width: | Height: | Size: 888 B |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 101 KiB |
|
After Width: | Height: | Size: 131 KiB |
|
Before Width: | Height: | Size: 911 B After Width: | Height: | Size: 911 B |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 668 B After Width: | Height: | Size: 668 B |
|
Before Width: | Height: | Size: 795 B After Width: | Height: | Size: 795 B |
|
Before Width: | Height: | Size: 766 B After Width: | Height: | Size: 766 B |
@ -0,0 +1,10 @@ |
|||||
|
import style from './style.json' |
||||
|
function importAll(r) { |
||||
|
const obj = {} |
||||
|
r.keys().forEach(key => { |
||||
|
obj[key.replace('./', '').replace('.png', '')] = r(key) |
||||
|
}) |
||||
|
return obj |
||||
|
} |
||||
|
const images = importAll(require.context('./', false, /\.(png|jpe?g|svg)$/)) |
||||
|
export default { ...style, images } |
||||
|
Before Width: | Height: | Size: 301 B After Width: | Height: | Size: 301 B |
|
Before Width: | Height: | Size: 304 B After Width: | Height: | Size: 304 B |
|
After Width: | Height: | Size: 911 B |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 303 KiB After Width: | Height: | Size: 303 KiB |
|
Before Width: | Height: | Size: 768 B After Width: | Height: | Size: 768 B |
|
Before Width: | Height: | Size: 738 B After Width: | Height: | Size: 738 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
@ -0,0 +1,128 @@ |
|||||
|
{ |
||||
|
"global": { |
||||
|
"background": "#dee6f6", |
||||
|
"appBackground": "#dee6f6", |
||||
|
"radius": "" |
||||
|
}, |
||||
|
"weather": { |
||||
|
"iconColor": "#000", |
||||
|
"textColor": "#000" |
||||
|
}, |
||||
|
"time": { |
||||
|
"timeColor": "#000", |
||||
|
"monthColor": "#000", |
||||
|
"weekColor": "#516dd8" |
||||
|
}, |
||||
|
"searchBar": { |
||||
|
"backBorderRadius": "24px", |
||||
|
"background": "#fff", |
||||
|
"border": "none", |
||||
|
"borderRadius": "24px", |
||||
|
"placeholderColor": "rgba(0, 0, 0, 0.2)", |
||||
|
"stickBg": "linear-gradient(180deg, #6C7CA6 0%, #879ACA 100%)", |
||||
|
"color": "rgba(0, 0, 0, 0.8)" |
||||
|
}, |
||||
|
"menu": { |
||||
|
"bg1": "rgba(255, 255, 255, 0.4)", |
||||
|
"bg2": "rgba(255, 255, 255, 0.4)", |
||||
|
"bg3": "rgba(255, 255, 255, 0.4)", |
||||
|
"bg4": "rgba(255, 255, 255, 0.4)", |
||||
|
"bg5": "rgba(255, 255, 255, 0.4)", |
||||
|
"activeBg1": "#ffffff", |
||||
|
"activeBg2": "#ffffff", |
||||
|
"activeBg3": "#ffffff", |
||||
|
"activeBg4": "#ffffff", |
||||
|
"activeBg5": "#ffffff", |
||||
|
"indexBg1": "#ffffff", |
||||
|
"indexBg2": "#ffffff", |
||||
|
"indexBg3": "#ffffff", |
||||
|
"indexBg4": "#ffffff", |
||||
|
"indexBg5": "#ffffff", |
||||
|
"color": "rgba(0, 0, 0, 0.4)", |
||||
|
"activeColor": "rgba(0, 0, 0, 0.8)", |
||||
|
"indexColor": "rgba(0, 0, 0, 0.8)", |
||||
|
"barBg": "linear-gradient(113.71deg, #435ACD 0%, #749CF3 100%)" |
||||
|
}, |
||||
|
"index": { |
||||
|
"hotSearchTitleColor": "rgba(0, 0, 0, 0.8)", |
||||
|
"hotSearchBg": "rgba(255, 255, 255, 0.8)", |
||||
|
"hotSearchColor": "rgba(0, 0, 0, 0.6)", |
||||
|
"guideBackground": "linear-gradient(99.5deg, #f0b92b 0%, #f9d556 100%)", |
||||
|
"guideBorder": "none", |
||||
|
"guideTopBg": "linear-gradient(180deg, #435acd 0%, #749cf3 100%)", |
||||
|
"guideQrcodeBg": "rgba(255, 255, 255, 0.2)", |
||||
|
"guideColor": "#000000", |
||||
|
"guideMetaColor": "rgba(0, 0, 0, 0.6)", |
||||
|
"foodBg": "linear-gradient(180deg, #ffffff 0%, #f2f4f8 100%)", |
||||
|
"foodBorder": "4px solid #F68B51", |
||||
|
"recBg": "linear-gradient(180deg, #ffffff 0%, #f2f4f8 100%)", |
||||
|
"recBorder": "none" |
||||
|
}, |
||||
|
"brand": { |
||||
|
"background": "rgba(255, 255, 255, 0.6)", |
||||
|
"color": "rgba(0, 0, 0, 0.8)", |
||||
|
"metaColor": "rgba(0, 0, 0, 0.6)", |
||||
|
"floorNameColor": "rgba(0, 0, 0, 0.8)", |
||||
|
"floorMetaColor": "rgba(0, 0, 0, 0.6)", |
||||
|
"qrcodeBg": "rgba(255, 255, 255, 0.8)", |
||||
|
"qrcodeTextColor": "rgba(0, 0, 0, 0.8)" |
||||
|
}, |
||||
|
"food": { |
||||
|
"background": "linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.5) 100%)", |
||||
|
"metaColor": "rgba(0, 0, 0, 0.6)" |
||||
|
}, |
||||
|
"carousel": { |
||||
|
"titleColor": "rgba(0, 0, 0, 0.8)", |
||||
|
"introColor": "rgba(0, 0, 0, 0.6)" |
||||
|
}, |
||||
|
"map": { |
||||
|
"background": "none" |
||||
|
}, |
||||
|
"billboard": { |
||||
|
"background": "#dee6f6", |
||||
|
"arrowRadius": "100px", |
||||
|
"legendColor": "rgba(0, 0, 0, 0.6)", |
||||
|
"titleColor": "#000000", |
||||
|
"metaColor": "rgba(0, 0, 0, 0.6)" |
||||
|
}, |
||||
|
"guide": { |
||||
|
"floorBg": "linear-gradient(113.71deg, #435acd 0%, #749cf3 100%)", |
||||
|
"allFloorBg": "left / 150px 100% no-repeat linear-gradient(180deg, #6c7ca6 0%, #879aca 100%), #dee6f6", |
||||
|
"allFloorBgH": "right / 100px 100vh no-repeat var(--guide-floorBg), left / calc(100vw - 510px - 100px) 100vh no-repeat #dee6f6", |
||||
|
"arrowRadius": "100px", |
||||
|
"floorColor": "#FFFFFF", |
||||
|
"floorActiveColor": "rgba(0, 0, 0, 0.8)", |
||||
|
"floorActiveBg": "linear-gradient(180deg, rgba(255, 255, 255, 0.8) 0%, #FFFFFF 100%)", |
||||
|
"currentBg": "linear-gradient(99.5deg, #F0B92B 0%, #F9D556 100%)", |
||||
|
"currentColor": "rgba(0, 0, 0, 0.8)" |
||||
|
}, |
||||
|
"search": { |
||||
|
"background": "linear-gradient(180deg, #E0E3EE 0%, #D4D9E7 100%)", |
||||
|
"barBackground": "#fff", |
||||
|
"placeholderMetaColor": "rgba(81, 109, 216, 1)", |
||||
|
"keyboardActiveBg": "linear-gradient(180deg, #435ACD 0%, #749CF3 100%)", |
||||
|
"writeColor": "#516DD8", |
||||
|
"topBg": "rgba(255, 255, 255, 0.6)", |
||||
|
"facTitleColor": "rgba(0, 0, 0, 0.8)", |
||||
|
"facNameColor": "rgba(0, 0, 0, 0.6)", |
||||
|
"tabsBg": "rgba(0, 0, 0, 0.05)", |
||||
|
"tabActiveBg": "#FFFFFF", |
||||
|
"tabColor": "rgba(0, 0, 0, 0.6)", |
||||
|
"tabActiveColor": "rgba(0, 0, 0, 0.8)", |
||||
|
"resultTitleColor": "rgba(0, 0, 0, 0.8)", |
||||
|
"resultMetaColor": "rgba(0, 0, 0, 0.6)", |
||||
|
"keyBg": "#FFFFFF", |
||||
|
"keyColor": "rgba(0, 0, 0, 0.8)", |
||||
|
"hotSearchTitleColor": "rgba(0, 0, 0, 0.8)", |
||||
|
"hotSearchBg": "rgba(255, 255, 255, 0.8)", |
||||
|
"hotSearchColor": "rgba(0, 0, 0, 0.6)" |
||||
|
}, |
||||
|
"activities": { |
||||
|
"btnBg": "linear-gradient(113.71deg, #435ACD 0%, #749CF3 100%)", |
||||
|
"btnColor": "#FFFFFF", |
||||
|
"detailBg": "#FFFFFF", |
||||
|
"radius": "16px", |
||||
|
"titleColor": "rgba(0, 0, 0, 0.8)", |
||||
|
"introColor": "rgba(0, 0, 0, 0.6)" |
||||
|
} |
||||
|
} |
||||
|
Before Width: | Height: | Size: 597 B After Width: | Height: | Size: 597 B |
|
Before Width: | Height: | Size: 593 B After Width: | Height: | Size: 593 B |
@ -1,239 +0,0 @@ |
|||||
<template> |
|
||||
<ScrollView class="scroll" :list="list" :scrollX="isH" :scrollbar="!isH"> |
|
||||
<TransitionGroup name="zoom" tag="div" class="scroll-content"> |
|
||||
<div :class="['content-item', item === activity ? 'd' : '']" v-for="item of list" :key="item.activityId"> |
|
||||
<div class="front"> |
|
||||
<img :src="config.sourceUrl + item.fileUrl" alt="" /> |
|
||||
<div class="tr">{{ item.startDate }} - {{ item.endDate }}</div> |
|
||||
<div class="bottom"> |
|
||||
<div class="left">{{ switchLanguage(item, 'activityName') }}</div> |
|
||||
<div class="right" @click="handleActivity(item)">查看详情</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="back"> |
|
||||
<ScrollView class="backscroll" scrollbar stopPropagation> |
|
||||
<div> |
|
||||
<div class="title">{{ switchLanguage(item, 'activityName') }}</div> |
|
||||
<div class="desc"> |
|
||||
{{ switchLanguage(item, 'activityContent') }} |
|
||||
</div> |
|
||||
</div> |
|
||||
</ScrollView> |
|
||||
</div> |
|
||||
</div> |
|
||||
</TransitionGroup> |
|
||||
</ScrollView> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { ref } from 'vue' |
|
||||
import { storeToRefs } from 'pinia' |
|
||||
import { useStore } from '@/store/root' |
|
||||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|
||||
import 'swiper/css' |
|
||||
import 'swiper/css/pagination' |
|
||||
import 'swiper/css/effect-coverflow' |
|
||||
import { useMediaQuery } from '@vueuse/core' |
|
||||
|
|
||||
const isH = useMediaQuery('(min-aspect-ratio: 1/1)') |
|
||||
defineProps({ |
|
||||
list: { |
|
||||
type: Array, |
|
||||
default: () => [] |
|
||||
} |
|
||||
}) |
|
||||
const showDetail = ref(false) |
|
||||
const activity = ref(null) |
|
||||
function handleActivity(item) { |
|
||||
activity.value = item |
|
||||
showDetail.value = true |
|
||||
} |
|
||||
const store = useStore() |
|
||||
const { config } = storeToRefs(store) |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.scroll { |
|
||||
position: relative; |
|
||||
flex: 1; |
|
||||
overflow: hidden; |
|
||||
:deep(.bscroll-vertical-scrollbar) { |
|
||||
width: 48px !important; |
|
||||
top: 48px !important; |
|
||||
right: 7px !important; |
|
||||
background: center / 6px 250px no-repeat url(@/assets/images/scrollBar.png); |
|
||||
border-radius: 6px; |
|
||||
opacity: 1 !important; |
|
||||
height: 250px !important; |
|
||||
&::after { |
|
||||
position: absolute; |
|
||||
content: ''; |
|
||||
left: 0; |
|
||||
top: 120px; |
|
||||
margin: auto; |
|
||||
width: 48px; |
|
||||
height: 61px; |
|
||||
background: center / cover no-repeat url(@/assets/images/scrollHand.png); |
|
||||
} |
|
||||
.bscroll-indicator { |
|
||||
height: 95px !important; |
|
||||
width: 6px !important; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
margin: auto; |
|
||||
background: #ffffff !important; |
|
||||
border-radius: 6px !important; |
|
||||
border: none !important; |
|
||||
} |
|
||||
} |
|
||||
.scroll-content { |
|
||||
width: 100%; |
|
||||
display: inline-flex; |
|
||||
flex-direction: column; |
|
||||
align-items: center; |
|
||||
padding: 48px 0; |
|
||||
} |
|
||||
.content-item { |
|
||||
position: relative; |
|
||||
width: 944px; |
|
||||
height: 532px; |
|
||||
background: var(--activities-detailBg); |
|
||||
border-radius: var(--activities-radius); |
|
||||
overflow: hidden; |
|
||||
margin-bottom: 24px; |
|
||||
&.d { |
|
||||
.front { |
|
||||
z-index: 0; |
|
||||
} |
|
||||
.back { |
|
||||
z-index: 1; |
|
||||
} |
|
||||
} |
|
||||
.front { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
left: 0; |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
z-index: 1; |
|
||||
img { |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
object-fit: cover; |
|
||||
} |
|
||||
.tr { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
right: 0; |
|
||||
font-family: 'Montserrat'; |
|
||||
background: rgba(0, 0, 0, 0.4); |
|
||||
box-shadow: 0px 15px 24px rgba(173, 196, 236, 0.25); |
|
||||
font-weight: 700; |
|
||||
font-size: 16px; |
|
||||
line-height: 40px; |
|
||||
color: #ffffff; |
|
||||
padding: 0 27px; |
|
||||
height: 40px; |
|
||||
border-radius: 0px 0px 0px 12px; |
|
||||
} |
|
||||
.bottom { |
|
||||
position: absolute; |
|
||||
display: flex; |
|
||||
bottom: 0; |
|
||||
width: 100%; |
|
||||
height: 64px; |
|
||||
.left { |
|
||||
flex: 1; |
|
||||
height: 100%; |
|
||||
padding: 0 40px; |
|
||||
background: rgba(0, 0, 0, 0.4); |
|
||||
font-weight: 700; |
|
||||
font-size: 18px; |
|
||||
line-height: 64px; |
|
||||
color: #ffffff; |
|
||||
white-space: nowrap; |
|
||||
overflow: hidden; |
|
||||
text-overflow: ellipsis; |
|
||||
} |
|
||||
.right { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: center; |
|
||||
width: 234px; |
|
||||
height: 100%; |
|
||||
background: var(--activities-btnBg); |
|
||||
box-shadow: 0px 15px 24px rgba(173, 196, 236, 0.25); |
|
||||
font-weight: 700; |
|
||||
font-size: 18px; |
|
||||
line-height: 21px; |
|
||||
text-align: center; |
|
||||
color: var(--activities-btnColor); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.back { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
left: 0; |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
display: flex; |
|
||||
z-index: 0; |
|
||||
background: var(--activities-detailBg); |
|
||||
.backscroll { |
|
||||
position: relative; |
|
||||
flex: 1; |
|
||||
:deep(.bscroll-vertical-scrollbar) { |
|
||||
width: 6px !important; |
|
||||
top: 137px !important; |
|
||||
right: 31px !important; |
|
||||
background: rgba(0, 0, 0, 0.05) !important; |
|
||||
border-radius: 6px; |
|
||||
opacity: 1 !important; |
|
||||
height: 174px !important; |
|
||||
&::after { |
|
||||
display: none; |
|
||||
} |
|
||||
.bscroll-indicator { |
|
||||
height: 95px !important; |
|
||||
width: 6px !important; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
margin: auto; |
|
||||
background: rgba(0, 0, 0, 0.1) !important; |
|
||||
border-radius: 6px !important; |
|
||||
border: none !important; |
|
||||
} |
|
||||
} |
|
||||
.title { |
|
||||
font-weight: 700; |
|
||||
font-size: 28px; |
|
||||
line-height: 150%; |
|
||||
padding: 48px 68px 40px 68px; |
|
||||
color: var(--activities-titleColor); |
|
||||
} |
|
||||
.desc { |
|
||||
padding: 0 68px; |
|
||||
padding-bottom: 23px; |
|
||||
font-weight: 400; |
|
||||
font-size: 16px; |
|
||||
line-height: 200%; |
|
||||
color: var(--activities-introColor); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@media (min-aspect-ratio: 1/1) { |
|
||||
.scroll { |
|
||||
.scroll-content { |
|
||||
width: auto; |
|
||||
flex-direction: row; |
|
||||
padding: 100px 68px; |
|
||||
} |
|
||||
.content-item + .content-item { |
|
||||
margin-left: 32px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,200 +0,0 @@ |
|||||
<template> |
|
||||
<Dialog @close="back"> |
|
||||
<div class="content"> |
|
||||
<div class="carousel"> |
|
||||
<EffectFade :list="[activity.fileUrl, activity.fileUrl]"> |
|
||||
<template v-slot="{ item }"> |
|
||||
<div class="banner-wrapper"> |
|
||||
<img :src="config.sourceUrl + item" alt="" class="banner" /> |
|
||||
</div> |
|
||||
</template> |
|
||||
</EffectFade> |
|
||||
</div> |
|
||||
<div class="intro-content"> |
|
||||
<h1 class="name pos">{{ switchLanguage(activity, 'activityName') }}</h1> |
|
||||
<ScrollView class="content-scroll" scrollbar> |
|
||||
<p class="intro pos">{{ switchLanguage(activity, 'activityContent') }}</p> |
|
||||
</ScrollView> |
|
||||
<div class="time-wrapper pos"> |
|
||||
<p class="common first">{{ $t('ActivityTime') }}:{{ activity.startDate }} {{ $t('zhi') + activity.endDate }}</p> |
|
||||
<p class="common">{{ $t('activityAddress') }}:{{ switchLanguage(activity, 'activityAddress') }}</p> |
|
||||
</div> |
|
||||
<Go class="detail-go" v-if="activity.shopId || activity.point" @click="handleActivity" /> |
|
||||
</div> |
|
||||
<Button class="btn" @click="back" /> |
|
||||
<ThumbQRCode class="thumbs" :title="$t('yuyue')" /> |
|
||||
</div> |
|
||||
</Dialog> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { useRouter } from 'vue-router' |
|
||||
import { useStore } from '@/store/root' |
|
||||
import Dialog from '@/layouts/Dialog.vue' |
|
||||
import Button from '@/base/Button/Button.vue' |
|
||||
import EffectFade from '@/components/EffectFade/EffectFade.vue' |
|
||||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|
||||
import Go from '@/base/Go/Go.vue' |
|
||||
import ThumbQRCode from '@/base/ThumbQRCode/ThumbQRCode.vue' |
|
||||
import Shop from '@/utils/Class/Shop' |
|
||||
|
|
||||
const MALL_TYPE = 1 //商场活动 |
|
||||
const BRAND_TYPE = 2 //品牌活动 |
|
||||
const MEMBER_TYPE = 3 //会员活动 |
|
||||
|
|
||||
const props = defineProps({ |
|
||||
activity: Object, |
|
||||
config: Object |
|
||||
}) |
|
||||
|
|
||||
const router = useRouter() |
|
||||
const store = useStore() |
|
||||
|
|
||||
function handleActivity() { |
|
||||
let shop |
|
||||
if (props.activity.activityType === BRAND_TYPE) { |
|
||||
shop = store.shopList.find(item => item.shopId === props.activity.shopId) |
|
||||
} |
|
||||
if (props.activity.activityType === MALL_TYPE || props.activity.activityType === MEMBER_TYPE) { |
|
||||
const { floorOrder, floor, activityName, fileUrl, point } = props.activity |
|
||||
shop = new Shop(activityName, floorOrder, floor, fileUrl, point) |
|
||||
} |
|
||||
|
|
||||
if (!shop) { |
|
||||
return |
|
||||
} |
|
||||
store.SET_SHOP(shop) |
|
||||
router.push('/nav') |
|
||||
} |
|
||||
|
|
||||
const emits = defineEmits(['close']) |
|
||||
function back() { |
|
||||
emits('close') |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.pos { |
|
||||
position: relative; |
|
||||
z-index: 5; |
|
||||
} |
|
||||
.content { |
|
||||
position: relative; |
|
||||
width: 700px; |
|
||||
margin: 0 auto; |
|
||||
margin-top: 350px; |
|
||||
z-index: 2; |
|
||||
.thumbs { |
|
||||
position: absolute; |
|
||||
top: 120px; |
|
||||
right: -156px; |
|
||||
} |
|
||||
&::before { |
|
||||
content: ''; |
|
||||
position: absolute; |
|
||||
top: 373px; |
|
||||
left: 0; |
|
||||
z-index: 2; |
|
||||
width: 700px; |
|
||||
height: 420px; |
|
||||
background: #ffffff; |
|
||||
border-radius: 12px; |
|
||||
} |
|
||||
.intro-content { |
|
||||
position: relative; |
|
||||
height: 420px; |
|
||||
.name { |
|
||||
padding: 28px 56px 32px 56px; |
|
||||
font-weight: 700; |
|
||||
font-size: 24px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
} |
|
||||
} |
|
||||
.common { |
|
||||
font-weight: 700; |
|
||||
font-size: 14px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
margin-left: 56px; |
|
||||
&.first { |
|
||||
padding-bottom: 8px; |
|
||||
} |
|
||||
} |
|
||||
.content-scroll { |
|
||||
position: relative; |
|
||||
height: 140px; |
|
||||
overflow: hidden; |
|
||||
margin: 0 34px 64px 56px; |
|
||||
padding-right: 16px; |
|
||||
: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); |
|
||||
margin-bottom: 64px; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.detail-go { |
|
||||
bottom: -70px; |
|
||||
} |
|
||||
|
|
||||
.carousel { |
|
||||
width: 700px; |
|
||||
height: 393px; |
|
||||
|
|
||||
:deep(.swiper) { |
|
||||
overflow: visible !important; |
|
||||
z-index: auto; |
|
||||
} |
|
||||
:deep(.swiper-pagination) { |
|
||||
right: 32px; |
|
||||
left: auto; |
|
||||
bottom: 5px; |
|
||||
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; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.banner-wrapper { |
|
||||
width: 700px; |
|
||||
height: 393px; |
|
||||
border-radius: 12px; |
|
||||
.banner { |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
object-fit: cover; |
|
||||
border-radius: 12px; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.btn { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
right: -120px; |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,455 +0,0 @@ |
|||||
<template> |
|
||||
<Dialog @close="back"> |
|
||||
<div class="content" :class="{ active: shop.activityList.length || shop.thirdKouCode }"> |
|
||||
<div class="left"> |
|
||||
<div class="carousel"> |
|
||||
<EffectFade :list="shop.doorMaterialList"> |
|
||||
<template v-slot="{ item }"> |
|
||||
<div class="banner-wrapper"> |
|
||||
<img :src="config.sourceUrl + item" alt="" class="banner" /> |
|
||||
</div> |
|
||||
</template> |
|
||||
</EffectFade> |
|
||||
<div class="like-wrapper" @click="setLike"> |
|
||||
<img :src="showLikeHeart ? require('@/assets/images/detail/like_active.svg') : require('@/assets/images/detail/like.svg')" class="like-icon" alt="" /> |
|
||||
<span class="like-num">{{ likeNumber }}</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="info-content"> |
|
||||
<div class="shop-info"> |
|
||||
<div class="logo-wrapper"> |
|
||||
<img :src="config.sourceUrl + shop.logoUrl" alt="" class="logo" /> |
|
||||
</div> |
|
||||
<div class="group" v-if="shop.industryUrl?.length"> |
|
||||
<div class="icon-box"> |
|
||||
<img :src="config.sourceUrl + shop.industryUrl" alt="" /> |
|
||||
</div> |
|
||||
<div class="group-right"> |
|
||||
<span class="tip-name">业态</span> |
|
||||
<span class="name">{{ switchLanguage(shop, 'industryFatherName') }}</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="group" v-if="shop.houseNumber?.length"> |
|
||||
<div class="icon-box"> |
|
||||
<img src="../../assets/images/nav/detail-add.svg" alt="" /> |
|
||||
</div> |
|
||||
<div class="group-right"> |
|
||||
<span class="tip-name">地址</span> |
|
||||
<span class="name">{{ shop.houseNumber }}</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="group" v-if="shop.contact?.length"> |
|
||||
<div class="icon-box"> |
|
||||
<img src="../../assets/images/nav/phone.svg" alt="" /> |
|
||||
</div> |
|
||||
<div class="group-right"> |
|
||||
<span class="tip-name">电话</span> |
|
||||
<span class="name">{{ shop.contact }}</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="group" v-if="shop.businessHours?.length"> |
|
||||
<div class="icon-box"> |
|
||||
<img src="../../assets/images/nav/time.svg" alt="" /> |
|
||||
</div> |
|
||||
<div class="group-right"> |
|
||||
<span class="tip-name">营业时间</span> |
|
||||
<span class="name">{{ shop.businessHours }}</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="shop-intro"> |
|
||||
<p class="shop-name">{{ switchLanguage(shop, 'shopName') }}</p> |
|
||||
<ScrollView class="intro-scroll" scrollbar> |
|
||||
<p class="intro">{{ switchLanguage(shop, 'intro') }}</p> |
|
||||
</ScrollView> |
|
||||
</div> |
|
||||
<Go class="detail-go" @click="go" /> |
|
||||
</div> |
|
||||
<div class="lineup-wrapper"> |
|
||||
<div class="lineup-left"> |
|
||||
<h1 class="title-tip">{{ $t('qiandengdai') }}</h1> |
|
||||
<div class="flex align-center"> |
|
||||
<ScrollView class="lineup-scroll" scroll-x> |
|
||||
<div class="lineup-content"> |
|
||||
<div class="flex"> |
|
||||
<div class="lineup-item" v-for="item of 10" :key="item"> |
|
||||
<span class="number">12</span> |
|
||||
<span class="line-up-text">小桌</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</ScrollView> |
|
||||
<div class="line"></div> |
|
||||
<p class="abs-money">147<i>¥/人</i></p> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="lineup-btn" @click="handleLineupBtn">{{ $t('join') }}</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="right" v-if="shop.activityList.length || shop.thirdKouCode"> |
|
||||
<Tabs /> |
|
||||
</div> |
|
||||
<Button class="btn" @click="back" /> |
|
||||
<ThumbQRCode class="thumbs" :title="$t('yuyue')" /> |
|
||||
<Transition enter-active-class="animate__animated animate__zoomIn" leave-active-class="animate__animated animate__zoomOut"> |
|
||||
<QRCode v-if="showLineupQr" @close="showLineupQr = false" /> |
|
||||
</Transition> |
|
||||
</div> |
|
||||
</Dialog> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { ref, defineAsyncComponent } from 'vue' |
|
||||
import { storeToRefs } from 'pinia' |
|
||||
import { useRouter } from 'vue-router' |
|
||||
import { useStore } from '@/store/root' |
|
||||
import { getBrandLikesNumber, setBrandLikesNumber } from '@/http/api' |
|
||||
import Dialog from '@/layouts/Dialog.vue' |
|
||||
import Button from '@/base/Button/Button.vue' |
|
||||
import EffectFade from '@/components/EffectFade/EffectFade.vue' |
|
||||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|
||||
import Go from '@/base/Go/Go.vue' |
|
||||
import ThumbQRCode from '@/base/ThumbQRCode/ThumbQRCode.vue' |
|
||||
import Tabs from './children/tabs.vue' |
|
||||
import { useStatistics } from '@/composables/useStatistics' |
|
||||
const QRCode = defineAsyncComponent(() => import('@/components/QRCode/QRCode.vue')) |
|
||||
|
|
||||
const router = useRouter() |
|
||||
const store = useStore() |
|
||||
const { shop, config, showDetail, showSearch, showVoice } = storeToRefs(store) |
|
||||
|
|
||||
useStatistics('shop') |
|
||||
|
|
||||
const showLikeHeart = ref(false) |
|
||||
const likeNumber = ref(0) |
|
||||
getBrandLikesNumber(shop.value.shopId).then(({ data }) => { |
|
||||
likeNumber.value = data ?? 0 |
|
||||
}) |
|
||||
|
|
||||
function setLike() { |
|
||||
setBrandLikesNumber(shop.value.shopId).then(() => { |
|
||||
showLikeHeart.value = true |
|
||||
likeNumber.value++ |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
const showLineupQr = ref(false) |
|
||||
function handleLineupBtn() { |
|
||||
showLineupQr.value = true |
|
||||
} |
|
||||
|
|
||||
async function go() { |
|
||||
await router.push('/nav') |
|
||||
showDetail.value && store.SET_SHOW_DETAIL(false) |
|
||||
showSearch.value && store.SET_SHOW_SEARCH(false) |
|
||||
showVoice.value && store.SET_SHOW_VOICE(false) |
|
||||
} |
|
||||
|
|
||||
function back() { |
|
||||
store.SET_SHOW_DETAIL(false) |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.content { |
|
||||
position: absolute; |
|
||||
top: 350px; |
|
||||
left: 50%; |
|
||||
transform: translate3d(-50%, 0, 0); |
|
||||
z-index: 2; |
|
||||
&.active { |
|
||||
top: 100px; |
|
||||
} |
|
||||
&::before { |
|
||||
content: ''; |
|
||||
position: absolute; |
|
||||
top: 373px; |
|
||||
left: 0; |
|
||||
z-index: 2; |
|
||||
width: 700px; |
|
||||
height: 420px; |
|
||||
background: linear-gradient(180deg, #ffbd35 0%, #ffd260 100%); |
|
||||
border-radius: 12px; |
|
||||
} |
|
||||
.thumbs { |
|
||||
position: absolute; |
|
||||
top: 120px; |
|
||||
right: -156px; |
|
||||
} |
|
||||
|
|
||||
.detail-go { |
|
||||
bottom: -90px; |
|
||||
} |
|
||||
.left { |
|
||||
width: 700px; |
|
||||
.carousel { |
|
||||
position: relative; |
|
||||
width: 700px; |
|
||||
height: 393px; |
|
||||
background-color: #fff; |
|
||||
border-radius: 12px; |
|
||||
overflow: hidden; |
|
||||
.like-wrapper { |
|
||||
position: absolute; |
|
||||
left: 571px; |
|
||||
top: 32px; |
|
||||
height: 52px; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
padding: 0 14px; |
|
||||
background: rgba(0, 0, 0, 0.2); |
|
||||
border-radius: 54px; |
|
||||
|
|
||||
z-index: 1; |
|
||||
.like-num { |
|
||||
padding-left: 8px; |
|
||||
font-weight: 700; |
|
||||
font-size: 20px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: #ffffff; |
|
||||
} |
|
||||
} |
|
||||
:deep(.swiper) { |
|
||||
overflow: visible !important; |
|
||||
z-index: auto; |
|
||||
} |
|
||||
:deep(.swiper-pagination) { |
|
||||
right: 32px; |
|
||||
left: auto; |
|
||||
bottom: 5px; |
|
||||
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: rgba(255, 255, 255, 1); |
|
||||
border-radius: 3px !important; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.banner-wrapper { |
|
||||
width: 700px; |
|
||||
height: 393px; |
|
||||
border-radius: 12px; |
|
||||
.banner { |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
object-fit: cover; |
|
||||
border-radius: 12px; |
|
||||
} |
|
||||
} |
|
||||
.info-content { |
|
||||
position: relative; |
|
||||
display: flex; |
|
||||
align-items: stretch; |
|
||||
width: 700px; |
|
||||
height: 420px; |
|
||||
margin-top: -20px; |
|
||||
} |
|
||||
.shop-info { |
|
||||
position: relative; |
|
||||
z-index: 3; |
|
||||
width: 225px; |
|
||||
background: rgba(0, 0, 0, 0.02); |
|
||||
border-radius: 0px 0px 0px 12px; |
|
||||
padding-left: 32px; |
|
||||
.logo-wrapper { |
|
||||
width: 160px; |
|
||||
height: 160px; |
|
||||
background: #ffffff; |
|
||||
box-shadow: 0px 20px 30px rgba(221, 152, 55, 0.5); |
|
||||
border-radius: 16px; |
|
||||
padding: 20px; |
|
||||
margin-bottom: 32px; |
|
||||
margin-top: -51px; |
|
||||
.logo { |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
object-fit: contain; |
|
||||
} |
|
||||
} |
|
||||
.group { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
margin-bottom: 18px; |
|
||||
.icon-box { |
|
||||
width: 36px; |
|
||||
height: 36px; |
|
||||
background: rgba(0, 0, 0, 0.05); |
|
||||
border-radius: 6px; |
|
||||
margin-right: 12px; |
|
||||
padding: 9px; |
|
||||
img { |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
object-fit: contain; |
|
||||
} |
|
||||
} |
|
||||
.group-right { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
justify-content: center; |
|
||||
.tip-name { |
|
||||
font-size: 12px; |
|
||||
transform: scale(0.83); |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
padding-bottom: 6px; |
|
||||
} |
|
||||
.name { |
|
||||
font-weight: 700; |
|
||||
font-family: 'font_bold'; |
|
||||
font-size: 12px; |
|
||||
line-height: 14px; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.shop-intro { |
|
||||
position: relative; |
|
||||
z-index: 3; |
|
||||
flex: 1; |
|
||||
padding-top: 58px; |
|
||||
padding-left: 40px; |
|
||||
.shop-name { |
|
||||
font-weight: 700; |
|
||||
font-size: 32px; |
|
||||
line-height: 38px; |
|
||||
text-align: justify; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
font-family: 'font_bold'; |
|
||||
padding-bottom: 40px; |
|
||||
} |
|
||||
.intro-scroll { |
|
||||
position: relative; |
|
||||
overflow: hidden; |
|
||||
height: 207px; |
|
||||
margin-right: 16px; |
|
||||
padding-right: 18px; |
|
||||
.intro { |
|
||||
font-size: 14px; |
|
||||
line-height: 200%; |
|
||||
text-align: justify; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
} |
|
||||
flex: 1; |
|
||||
overflow: hidden; |
|
||||
:deep(.bscroll-vertical-scrollbar) { |
|
||||
width: 6px !important; |
|
||||
background: rgba(0, 0, 0, 0.02) !important; |
|
||||
border-radius: 6px !important; |
|
||||
opacity: 1 !important; |
|
||||
height: 200px !important; |
|
||||
.bscroll-indicator { |
|
||||
height: 95px !important; |
|
||||
width: 6px !important; |
|
||||
background: rgba(0, 0, 0, 0.1) !important; |
|
||||
border-radius: 6px !important; |
|
||||
border: none !important; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.flex { |
|
||||
display: flex; |
|
||||
} |
|
||||
.align-center { |
|
||||
align-items: flex-end; |
|
||||
} |
|
||||
.lineup-wrapper { |
|
||||
display: flex; |
|
||||
align-items: flex-end; |
|
||||
margin-top: -20px; |
|
||||
padding: 79px 16px 16px 32px; |
|
||||
background: #ffffff; |
|
||||
border-radius: 12px; |
|
||||
.lineup-left { |
|
||||
flex: 1; |
|
||||
.title-tip { |
|
||||
font-weight: 700; |
|
||||
font-size: 14px; |
|
||||
font-family: 'font_bold'; |
|
||||
text-align: justify; |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
padding-bottom: 15px; |
|
||||
} |
|
||||
} |
|
||||
.lineup-scroll { |
|
||||
display: flex; |
|
||||
width: 310px; |
|
||||
overflow: hidden; |
|
||||
margin-right: 40px; |
|
||||
.lineup-content { |
|
||||
display: inline-block; |
|
||||
white-space: nowrap; |
|
||||
|
|
||||
.lineup-item { |
|
||||
display: flex; |
|
||||
align-items: flex-end; |
|
||||
margin-right: 24px; |
|
||||
} |
|
||||
.number { |
|
||||
font-weight: 700; |
|
||||
font-size: 24px; |
|
||||
line-height: 22px; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
font-family: 'font_bold'; |
|
||||
padding-right: 4px; |
|
||||
} |
|
||||
.line-up-text { |
|
||||
font-weight: 700; |
|
||||
font-size: 14px; |
|
||||
line-height: 16px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.2); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.line { |
|
||||
width: 1px; |
|
||||
height: 20px; |
|
||||
background: rgba(0, 0, 0, 0.1); |
|
||||
margin-right: 40px; |
|
||||
} |
|
||||
.abs-money { |
|
||||
font-weight: 700; |
|
||||
font-family: 'font_bold'; |
|
||||
font-size: 24px; |
|
||||
text-align: right; |
|
||||
color: #f1b33e; |
|
||||
i { |
|
||||
font-size: 14px; |
|
||||
color: rgba(0, 0, 0, 0.2); |
|
||||
} |
|
||||
} |
|
||||
.lineup-btn { |
|
||||
background: linear-gradient(90deg, #f6a62c 0%, #ffbc3f 100%); |
|
||||
box-shadow: 0px 8px 20px rgba(221, 152, 55, 0.2); |
|
||||
border-radius: 24px; |
|
||||
width: 128px; |
|
||||
height: 37px; |
|
||||
font-weight: 700; |
|
||||
font-family: 'font_bold'; |
|
||||
font-size: 14px; |
|
||||
line-height: 37px; |
|
||||
text-align: center; |
|
||||
color: #fff; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.right { |
|
||||
width: 700px; |
|
||||
flex: 1; |
|
||||
margin-top: 40px; |
|
||||
} |
|
||||
.btn { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
right: -120px; |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,266 +0,0 @@ |
|||||
<template> |
|
||||
<div> |
|
||||
<ScrollView class="activity-scroll" :class="{ active: tab.length === 1 }" scrollbar> |
|
||||
<div class="scroll-content"> |
|
||||
<h1 class="title">{{ $t('brandActivity') }}</h1> |
|
||||
<div class="activity-item" v-for="item of list" :key="item.activityId"> |
|
||||
<div class="img-wrapper"> |
|
||||
<img :src="config.sourceUrl + item.fileUrl" alt="" class="img" /> |
|
||||
</div> |
|
||||
<div class="flex-right"> |
|
||||
<div class="activity-title"> |
|
||||
<p class="name">{{ switchLanguage(item, 'activityName') }}</p> |
|
||||
<p class="look" @click="handleActivity(item)">{{ $t('lookActivity') }}</p> |
|
||||
</div> |
|
||||
<p class="activity-intro">{{ switchLanguage(item, 'activityContent') }}</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<h1 class="title">{{ $t('coupon') }}</h1> |
|
||||
<div class="coupon-item"> |
|
||||
<div class="coupon-left"> |
|
||||
<p class="money">¥<i>30</i></p> |
|
||||
<div class="coupon-info"> |
|
||||
<p class="coupon-name">30元代金券,满129可用</p> |
|
||||
<p class="coupon-time">使用时间:2021-01-01至2021-12-30</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="coupon-btn">{{ $t('get') }}</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</ScrollView> |
|
||||
<div class="activity-detail" v-if="showActivityDetail"> |
|
||||
<h1 class="activity-title">{{ switchLanguage(activity, 'activityName') }}</h1> |
|
||||
<ScrollView class="scroll" scrollbar> |
|
||||
<p class="scroll-content">{{ switchLanguage(activity, 'activityContent') }}</p> |
|
||||
</ScrollView> |
|
||||
<div class="common first">{{ $t('ActivityTime') }}:{{ activity.startDate }} {{ $t('zhi') + activity.endDate }}</div> |
|
||||
<div class="common">{{ $t('activityAddress') }}:{{ switchLanguage(activity, 'activityAddress') }}</div> |
|
||||
<div class="close-activity" @click="showActivityDetail = false"> |
|
||||
<img src="../../../assets/images/detail/yellow_close.png" alt="" /> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { computed, ref } from 'vue' |
|
||||
import { storeToRefs } from 'pinia' |
|
||||
import { useStore } from '@/store/root' |
|
||||
|
|
||||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|
||||
|
|
||||
defineProps({ |
|
||||
tab: Array |
|
||||
}) |
|
||||
|
|
||||
const store = useStore() |
|
||||
const { shop, config } = storeToRefs(store) |
|
||||
const list = computed(() => shop.value.activityList) |
|
||||
|
|
||||
const showActivityDetail = ref(false) |
|
||||
const activity = ref({}) |
|
||||
function handleActivity(item) { |
|
||||
activity.value = item |
|
||||
showActivityDetail.value = true |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.activity-scroll { |
|
||||
position: relative; |
|
||||
overflow: hidden; |
|
||||
height: 690px; |
|
||||
&.active { |
|
||||
height: 860px; |
|
||||
} |
|
||||
.title { |
|
||||
font-weight: 700; |
|
||||
font-family: 'font_bold'; |
|
||||
font-size: 24px; |
|
||||
margin-bottom: 24px; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
} |
|
||||
.activity-item { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
width: 700px; |
|
||||
height: 106px; |
|
||||
background: rgba(255, 255, 255, 0.8); |
|
||||
border-radius: 12px; |
|
||||
margin-bottom: 16px; |
|
||||
padding-right: 16px; |
|
||||
padding-left: 6px; |
|
||||
&:last-of-type { |
|
||||
margin-bottom: 40px; |
|
||||
} |
|
||||
.img-wrapper { |
|
||||
width: 160px; |
|
||||
height: 90px; |
|
||||
border-radius: 8px; |
|
||||
overflow: hidden; |
|
||||
margin-right: 32px; |
|
||||
.img { |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
object-fit: cover; |
|
||||
} |
|
||||
} |
|
||||
.flex-right { |
|
||||
flex: 1; |
|
||||
.activity-title { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: space-between; |
|
||||
padding-bottom: 8px; |
|
||||
.name { |
|
||||
font-weight: 700; |
|
||||
font-size: 20px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
} |
|
||||
.look { |
|
||||
font-weight: 400; |
|
||||
font-size: 14px; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
background: url('../../../assets/images/detail/arrow.svg') no-repeat right center; |
|
||||
background-size: 18px 18px; |
|
||||
padding-right: 26px; |
|
||||
} |
|
||||
} |
|
||||
.activity-intro { |
|
||||
font-weight: 400; |
|
||||
font-size: 14px; |
|
||||
line-height: 150%; |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
@include more-wrap; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.coupon-item { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: space-between; |
|
||||
padding: 0 24px 0 32px; |
|
||||
width: 700px; |
|
||||
height: 106px; |
|
||||
margin-bottom: 16px; |
|
||||
background: rgba(255, 255, 255, 0.8); |
|
||||
border-radius: 12px; |
|
||||
.coupon-left { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
} |
|
||||
.coupon-name { |
|
||||
font-weight: 700; |
|
||||
font-size: 18px; |
|
||||
line-height: 21px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
padding-bottom: 6px; |
|
||||
} |
|
||||
.coupon-time { |
|
||||
font-size: 14px; |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
} |
|
||||
.money { |
|
||||
font-weight: 700; |
|
||||
font-family: 'font_bold'; |
|
||||
font-size: 24px; |
|
||||
color: #f1b33e; |
|
||||
margin-right: 27px; |
|
||||
i { |
|
||||
font-size: 48px; |
|
||||
padding-left: 4px; |
|
||||
} |
|
||||
} |
|
||||
.coupon-btn { |
|
||||
width: 140px; |
|
||||
height: 48px; |
|
||||
text-align: center; |
|
||||
line-height: 48px; |
|
||||
background: linear-gradient(90deg, #f6a62c 0%, #ffbc3f 100%); |
|
||||
box-shadow: 0px 20px 30px rgba(221, 152, 55, 0.2); |
|
||||
border-radius: 160px; |
|
||||
color: #fff; |
|
||||
font-weight: 700; |
|
||||
font-family: 'font_bold'; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.activity-detail { |
|
||||
position: absolute; |
|
||||
width: 832px; |
|
||||
min-height: 396px; |
|
||||
top: 50%; |
|
||||
left: 50%; |
|
||||
transform: translate3d(-50%, -50%, 0); |
|
||||
background: #ffffff; |
|
||||
box-shadow: 0px 40px 60px rgba(0, 0, 0, 0.08); |
|
||||
border-radius: 12px; |
|
||||
z-index: 10; |
|
||||
padding-top: 48px; |
|
||||
padding-left: 56px; |
|
||||
.activity-title { |
|
||||
font-weight: 700; |
|
||||
font-size: 24px; |
|
||||
line-height: 28px; |
|
||||
text-align: justify; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
margin-bottom: 32px; |
|
||||
} |
|
||||
.scroll { |
|
||||
position: relative; |
|
||||
height: 155px; |
|
||||
overflow: hidden; |
|
||||
margin-right: 34px; |
|
||||
padding-right: 16px; |
|
||||
: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; |
|
||||
} |
|
||||
} |
|
||||
.scroll-content { |
|
||||
font-size: 14px; |
|
||||
line-height: 200%; |
|
||||
text-align: justify; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
} |
|
||||
} |
|
||||
.common { |
|
||||
font-weight: 700; |
|
||||
font-size: 14px; |
|
||||
line-height: 16px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
&.first { |
|
||||
margin-bottom: 12px; |
|
||||
padding-top: 49px; |
|
||||
} |
|
||||
} |
|
||||
.close-activity { |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
position: absolute; |
|
||||
top: 12px; |
|
||||
right: 12px; |
|
||||
width: 56px; |
|
||||
height: 56px; |
|
||||
background: rgba(0, 0, 0, 0.02); |
|
||||
border-radius: 12px; |
|
||||
img { |
|
||||
width: 56px; |
|
||||
height: 56px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,123 +0,0 @@ |
|||||
<template> |
|
||||
<div class="wrapper"> |
|
||||
<h1 class="title">{{ $t('comment') }}</h1> |
|
||||
<div class="score-wrapper"> |
|
||||
<div class="score-num">{{ score }}</div> |
|
||||
<div class="star"> |
|
||||
<div class="star-num"> |
|
||||
<img |
|
||||
:src="item === 0 ? require('@/assets/images/detail/star_active.svg') : require('@/assets/images/detail/star.svg')" |
|
||||
v-for="item of starList()" |
|
||||
:key="item" |
|
||||
alt="" |
|
||||
class="star-icon" |
|
||||
/> |
|
||||
</div> |
|
||||
<div class="total-comment">{{ totalComment }} {{ $t('totalComment') }}</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<ScrollView class="scroll" :list="commentList" scrollbar> |
|
||||
<ul class="comments"> |
|
||||
<li class="comments-item" v-for="item of commentList" :key="item.tag_count"> |
|
||||
<span class="txt"> |
|
||||
{{ item.tag_content }} |
|
||||
<span>{{ item.tag_count }}</span> |
|
||||
</span> |
|
||||
</li> |
|
||||
</ul> |
|
||||
</ScrollView> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { ref, computed } from 'vue' |
|
||||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|
||||
|
|
||||
const comment = ref({ |
|
||||
comment_info: { |
|
||||
avg_score: '2.912871287128713', |
|
||||
comment_tag_list: { |
|
||||
comment_tag: [ |
|
||||
{ |
|
||||
emotion: 1, |
|
||||
tag_content: '服务周到', |
|
||||
tag_count: 6 |
|
||||
} |
|
||||
] |
|
||||
}, |
|
||||
image_count: 34, |
|
||||
total_comments: 505 |
|
||||
}, |
|
||||
has_more: false, |
|
||||
page_size: 20 |
|
||||
}) |
|
||||
|
|
||||
const commentList = computed(() => comment.value?.comment_info?.comment_tag_list?.comment_tag ?? []) |
|
||||
const score = computed(() => Math.floor(comment.value?.comment_info?.avg_score) ?? 0) |
|
||||
const totalComment = computed(() => comment.value?.comment_info?.total_comments ?? 0) |
|
||||
|
|
||||
function starList() { |
|
||||
return new Array(5).fill(0, 0, score.value).fill(1, score.value) |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.title { |
|
||||
font-weight: 700; |
|
||||
font-family: 'font_bold'; |
|
||||
font-size: 24px; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
margin-bottom: 24px; |
|
||||
} |
|
||||
.scroll { |
|
||||
position: relative; |
|
||||
height: 618px; |
|
||||
overflow: hidden; |
|
||||
.comments { |
|
||||
display: flex; |
|
||||
flex-wrap: wrap; |
|
||||
.comments-item { |
|
||||
height: 43px; |
|
||||
background: #ffffff; |
|
||||
border-radius: 8px; |
|
||||
flex-shrink: 0; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: center; |
|
||||
height: 40px; |
|
||||
padding: 0 24px; |
|
||||
margin: 0 16px 16px 0; |
|
||||
span { |
|
||||
font-size: 16px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
font-weight: 700; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.star-num { |
|
||||
margin-bottom: 4px; |
|
||||
} |
|
||||
.star-icon { |
|
||||
width: 20px; |
|
||||
height: 20px; |
|
||||
margin-right: 8px; |
|
||||
} |
|
||||
.score-wrapper { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
margin-bottom: 25px; |
|
||||
.score-num { |
|
||||
font-weight: 700; |
|
||||
font-family: 'font_bold'; |
|
||||
font-size: 48px; |
|
||||
color: #f1b33e; |
|
||||
margin-right: 19px; |
|
||||
} |
|
||||
.total-comment { |
|
||||
font-size: 14px; |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,155 +0,0 @@ |
|||||
<template> |
|
||||
<div class="wrapper"> |
|
||||
<h1 class="title">{{ $t('goods') }}</h1> |
|
||||
<ScrollView class="scroll" :list="goodsList"> |
|
||||
<ul class="goods"> |
|
||||
<li class="goods-item" v-for="item of goodsList" :key="item.item_name"> |
|
||||
<div class="cover"> |
|
||||
<img :src="item.item_cover" alt="" class="goods-img" /> |
|
||||
</div> |
|
||||
<div class="goods-right"> |
|
||||
<h1 class="goods-title">{{ item.item_name }}</h1> |
|
||||
<h1 class="goods-sub">{{ item.sub_title }}</h1> |
|
||||
<h1 class="price"> |
|
||||
<span class="sell"> |
|
||||
¥<i>{{ item.sell_price }}</i> |
|
||||
</span> |
|
||||
<span class="original"> |
|
||||
¥<i>{{ item.original_price }}</i> |
|
||||
</span> |
|
||||
</h1> |
|
||||
</div> |
|
||||
<div class="button" @click="handleGoods(item)">{{ $t('buy') }}</div> |
|
||||
</li> |
|
||||
</ul> |
|
||||
</ScrollView> |
|
||||
<QRCode v-if="showCodeRef" :url="goodsRef.item_detail_url" :title="$t('scanBuy')" @click="show(false)" /> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { ref, defineAsyncComponent } from 'vue' |
|
||||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|
||||
|
|
||||
const QRCode = defineAsyncComponent(() => import('@/base/QRCode/QRCode.vue')) |
|
||||
|
|
||||
const goodsList = ref([ |
|
||||
{ |
|
||||
item_store: { store_name: '大紧特紧测试门店' }, |
|
||||
item_detail_url: |
|
||||
'alipays://platformapi/startapp?appId=77700272&startMultApp=YES&query=itemId%3D613552052869%26channel%3DALL%26cityId%3D330100%26storeId%3D230021002%26sourceFrom%3DITEM_DETAIL_BASE_INFO&url=%2Findex.html%23pages%2Findex%2Findex&chInfo=ch_tribeopen__chsub_yinli', |
|
||||
item_cover: 'https://wx1.sinaimg.cn/orj360/004j2Ftyly1gt4lt4kltaj60u01c6n8r02.jpg', |
|
||||
item_name: '这是商品的名称', |
|
||||
sub_title: '正文介绍正文介绍正文介绍正文介绍正文介绍正文介绍正文介绍正文介绍正文介绍正文介绍正文介绍正文介绍', |
|
||||
sell_price: '333', |
|
||||
original_price: '11111' |
|
||||
} |
|
||||
]) |
|
||||
|
|
||||
const showCodeRef = ref(false) |
|
||||
const goodsRef = ref({}) |
|
||||
function handleGoods(item) { |
|
||||
goodsRef.value = item |
|
||||
showCodeRef.value = true |
|
||||
} |
|
||||
function show(flag) { |
|
||||
showCodeRef.value = flag |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.title { |
|
||||
font-weight: 700; |
|
||||
font-family: 'font_bold'; |
|
||||
font-size: 24px; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
margin-bottom: 24px; |
|
||||
} |
|
||||
.scroll { |
|
||||
position: relative; |
|
||||
overflow: hidden; |
|
||||
height: 690px; |
|
||||
} |
|
||||
.goods { |
|
||||
padding-bottom: 8px; |
|
||||
} |
|
||||
.goods-item { |
|
||||
width: 700px; |
|
||||
height: 156px; |
|
||||
background: rgba(255, 255, 255, 0.8); |
|
||||
border-radius: 12px; |
|
||||
position: relative; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
margin-bottom: 16px; |
|
||||
padding: 0 24px 0 8px; |
|
||||
.cover { |
|
||||
flex-shrink: 0; |
|
||||
width: 136px; |
|
||||
height: 136px; |
|
||||
margin-right: 24px; |
|
||||
margin-right: 32px; |
|
||||
border-radius: 8px; |
|
||||
overflow: hidden; |
|
||||
|
|
||||
.goods-img { |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
object-fit: cover; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.goods-title { |
|
||||
font-family: 'font_bold'; |
|
||||
font-weight: 700; |
|
||||
font-size: 20px; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
padding-bottom: 8px; |
|
||||
} |
|
||||
.goods-sub { |
|
||||
font-size: 14px; |
|
||||
line-height: 150%; |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
margin-bottom: 10px; |
|
||||
@include more-wrap; |
|
||||
} |
|
||||
.price { |
|
||||
display: flex; |
|
||||
align-items: baseline; |
|
||||
.sell { |
|
||||
display: flex; |
|
||||
align-items: baseline; |
|
||||
font-weight: 700; |
|
||||
font-family: 'font_bold'; |
|
||||
font-size: 16px; |
|
||||
color: #f1b33e; |
|
||||
padding-right: 10px; |
|
||||
i { |
|
||||
font-size: 32px; |
|
||||
} |
|
||||
} |
|
||||
.original { |
|
||||
font-weight: 400; |
|
||||
font-size: 18px; |
|
||||
text-decoration: line-through; |
|
||||
color: rgba(0, 0, 0, 0.2); |
|
||||
} |
|
||||
} |
|
||||
.button { |
|
||||
position: absolute; |
|
||||
bottom: 16px; |
|
||||
right: 24px; |
|
||||
width: 140px; |
|
||||
height: 48px; |
|
||||
text-align: center; |
|
||||
line-height: 48px; |
|
||||
background: linear-gradient(90deg, #f6a62c 0%, #ffbc3f 100%); |
|
||||
box-shadow: 0px 20px 30px rgba(221, 152, 55, 0.2); |
|
||||
border-radius: 150px; |
|
||||
font-weight: 700; |
|
||||
font-size: 14px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: #ffffff; |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,119 +0,0 @@ |
|||||
<template> |
|
||||
<div class="wrapper"> |
|
||||
<h1 class="title">{{ $t('serviceInfo') }}</h1> |
|
||||
<h2 class="time">{{ businessTime }}</h2> |
|
||||
|
|
||||
<h1 class="title">营业信息</h1> |
|
||||
|
|
||||
<div class="info-group"> |
|
||||
<div class="info-list" v-for="(item, index) of serviceList" :key="index"> |
|
||||
<p class="info">{{ item }}</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { ref, computed } from 'vue' |
|
||||
|
|
||||
const info = ref({ |
|
||||
service_info: { |
|
||||
service_desc: '有停车位 有WIFI 有包厢 无烟区', |
|
||||
service_tag_list: ['有停车位', 'sadf', '有停车位', 'sadf', '有停车位', 'sadf', 'sadf', 'sadddddf', 'sadf阿斯蒂芬', 'sa顶顶顶df', 'sadf'] |
|
||||
}, |
|
||||
store_album: { |
|
||||
picture_list: { |
|
||||
picture: [ |
|
||||
{ |
|
||||
picture_name: '门店内景', |
|
||||
picture_url: 'https://img.alicdn.com/i4/2200788639881/O1CN01T3Urj72MrYBKTXquz_!!2200788639881-0-koubei.jpg', |
|
||||
sequence: -1 |
|
||||
}, |
|
||||
{ |
|
||||
picture_name: '门店内景', |
|
||||
picture_url: 'https://img.alicdn.com/i1/2200788639881/O1CN01xyp6q72MrYBGxRpS6_!!2200788639881-0-koubei.jpg', |
|
||||
sequence: -1 |
|
||||
}, |
|
||||
{ |
|
||||
picture_name: '门店内景', |
|
||||
picture_url: 'https://img.alicdn.com/i4/2200788639881/O1CN01T3Urj72MrYBKTXquz_!!2200788639881-0-koubei.jpg', |
|
||||
sequence: -1 |
|
||||
}, |
|
||||
{ |
|
||||
picture_name: '门店内景', |
|
||||
picture_url: 'https://img.alicdn.com/i2/2200788639881/O1CN01WKCpfo2MrYBLru6At_!!2200788639881-0-koubei.jpg', |
|
||||
sequence: -1 |
|
||||
} |
|
||||
] |
|
||||
} |
|
||||
}, |
|
||||
store_dto: { |
|
||||
billboard: '江宁区米粉米线热销榜第2名', |
|
||||
brand_name: '阿香米线', |
|
||||
business_time: '周一-周日 10:00-21:30', |
|
||||
category_name: '美食,快餐小吃,米粉/米线', |
|
||||
comment_score: '3.4444444444444446', |
|
||||
comment_total_count: '9', |
|
||||
contact_info: '18117095769', |
|
||||
district_info: { |
|
||||
address: '浦珠北路1号万象汇商业广场B1层Y103号商铺', |
|
||||
city_code: '320100', |
|
||||
city_name: '南京市', |
|
||||
district_code: '320111', |
|
||||
district_name: '浦口区', |
|
||||
latitude: '32.125232', |
|
||||
longitude: '118.730226', |
|
||||
province_code: '320000', |
|
||||
province_name: '江苏省' |
|
||||
}, |
|
||||
mall_id: '20210207880000000000000009900410', |
|
||||
score: '2.9', |
|
||||
store_detail_url: |
|
||||
'alipays://platformapi/startapp?appId=2021002144672445&supportTourist=true&startMultApp=YES&query=chInfo%3Dch_tribeopen__chsub_1000mu%26sourceFrom%3DTRIBE_OPEN_SHOP', |
|
||||
store_id: '573127418', |
|
||||
store_logo: 'https://img.alicdn.com/i4/2200788639881/O1CN01T3Urj72MrYBKTXquz_!!2200788639881-0-koubei.jpg', |
|
||||
store_name: '阿香米线(南京桥北万象汇餐厅)' |
|
||||
} |
|
||||
}) |
|
||||
|
|
||||
const businessTime = computed(() => info.value?.store_dto?.business_time ?? '') |
|
||||
const serviceList = computed(() => info.value?.service_info?.service_tag_list ?? []) |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.title { |
|
||||
font-weight: 700; |
|
||||
font-family: 'font_bold'; |
|
||||
font-size: 24px; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
margin-bottom: 24px; |
|
||||
} |
|
||||
.time { |
|
||||
font-size: 14px; |
|
||||
line-height: 150%; |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
margin-bottom: 26px; |
|
||||
} |
|
||||
|
|
||||
.info-group { |
|
||||
display: flex; |
|
||||
flex-wrap: wrap; |
|
||||
.info-list { |
|
||||
padding: 0 24px; |
|
||||
text-align: center; |
|
||||
line-height: 43px; |
|
||||
height: 43px; |
|
||||
background: #ffffff; |
|
||||
border-radius: 8px; |
|
||||
margin-right: 16px; |
|
||||
margin-bottom: 16px; |
|
||||
|
|
||||
.info { |
|
||||
font-weight: 700; |
|
||||
font-size: 16px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,75 +0,0 @@ |
|||||
<template> |
|
||||
<div class="wrapper"> |
|
||||
<h1 class="title">{{ $t('recommend') }}</h1> |
|
||||
<ScrollView class="scroll" :list="recommendList"> |
|
||||
<ul class="recommends"> |
|
||||
<li class="recommend-item" v-for="item of recommendList" :key="item.good_detail_name"> |
|
||||
<div class="pic-wrapper"> |
|
||||
<img class="pic" :src="item?.picture?.picture_url" alt="" /> |
|
||||
</div> |
|
||||
<span class="txt">{{ item.good_detail_name }}</span> |
|
||||
</li> |
|
||||
</ul> |
|
||||
</ScrollView> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|
||||
import { ref } from 'vue' |
|
||||
|
|
||||
const recommendList = ref([ |
|
||||
{ |
|
||||
good_detail_name: '测试推荐菜', |
|
||||
picture: { |
|
||||
picture_url: 'https://img0.baidu.com/it/u=2284782435,2170248613&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1657299600&t=624c0227aa15519b1309ace7f41184ec' |
|
||||
} |
|
||||
} |
|
||||
]) |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.title { |
|
||||
font-weight: 700; |
|
||||
font-family: 'font_bold'; |
|
||||
font-size: 24px; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
margin-bottom: 24px; |
|
||||
} |
|
||||
.scroll { |
|
||||
position: relative; |
|
||||
overflow: hidden; |
|
||||
height: 690px; |
|
||||
.recommends { |
|
||||
display: grid; |
|
||||
grid-template-columns: repeat(3, 220px); |
|
||||
flex-wrap: wrap; |
|
||||
gap: 24px 19px; |
|
||||
padding-bottom: 24px; |
|
||||
.recommend-item { |
|
||||
height: 162px; |
|
||||
background: rgba(255, 255, 255, 0.4); |
|
||||
border-radius: 8px; |
|
||||
overflow: hidden; |
|
||||
} |
|
||||
.pic-wrapper { |
|
||||
width: 220px; |
|
||||
height: 124px; |
|
||||
margin-bottom: 12px; |
|
||||
.pic { |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
object-fit: cover; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.txt { |
|
||||
font-weight: 700; |
|
||||
font-size: 12px; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
padding-left: 12px; |
|
||||
font-family: 'font_bold'; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,132 +0,0 @@ |
|||||
<template> |
|
||||
<div class="tabs-wrapper" v-if="menuList.tabList.length > 1"> |
|
||||
<div |
|
||||
class="tab" |
|
||||
:ref="el => tabsEl.push(el)" |
|
||||
:class="{ active: index === tabIdx }" |
|
||||
@click="handleTab(index)" |
|
||||
v-for="(item, index) of menuList.tabList" |
|
||||
:key="item.name" |
|
||||
> |
|
||||
{{ switchLanguage(item, 'name') }} |
|
||||
</div> |
|
||||
</div> |
|
||||
<component :tab="menuList.tabList" :is="currentComp"></component> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { storeToRefs } from 'pinia' |
|
||||
import { useStore } from '@/store/root' |
|
||||
import { ref, defineAsyncComponent, computed } from 'vue' |
|
||||
|
|
||||
const Activity = defineAsyncComponent(() => import('./Activity.vue')) |
|
||||
const Goods = defineAsyncComponent(() => import('./Goods.vue')) |
|
||||
const Comment = defineAsyncComponent(() => import('./Comment.vue')) |
|
||||
const Info = defineAsyncComponent(() => import('./Info.vue')) |
|
||||
const Recommend = defineAsyncComponent(() => import('./Recommend.vue')) |
|
||||
|
|
||||
const tabList = [ |
|
||||
{ |
|
||||
name: '品牌活动', |
|
||||
nameEn: 'Activity' |
|
||||
}, |
|
||||
{ |
|
||||
name: '商品', |
|
||||
nameEn: 'goods' |
|
||||
}, |
|
||||
{ |
|
||||
name: '评价', |
|
||||
nameEn: 'comments' |
|
||||
}, |
|
||||
{ |
|
||||
name: '信息', |
|
||||
nameEn: 'infomation' |
|
||||
}, |
|
||||
{ |
|
||||
name: '推荐菜', |
|
||||
nameEn: 'recommend' |
|
||||
} |
|
||||
] |
|
||||
const tabIdx = ref(0) |
|
||||
function handleTab(index) { |
|
||||
tabIdx.value = index |
|
||||
moveTo(index) |
|
||||
} |
|
||||
|
|
||||
const PADDING_LEFT = 6 |
|
||||
const tabsEl = ref([]) |
|
||||
const distance = ref(0) |
|
||||
|
|
||||
function moveTo(index) { |
|
||||
distance.value = tabsEl.value[index].offsetLeft - PADDING_LEFT + 'px' |
|
||||
} |
|
||||
|
|
||||
const store = useStore() |
|
||||
const { shop } = storeToRefs(store) |
|
||||
|
|
||||
const _dynamicCompList = [Activity, Goods, Comment, Info, Recommend] |
|
||||
const menuList = computed(() => { |
|
||||
if (shop.value.activityList.length && shop.value.thirdKouCode) { |
|
||||
return { tabList, dynamicCompList: _dynamicCompList } |
|
||||
} |
|
||||
|
|
||||
if (shop.value.activityList.length && !shop.value.thirdKouCode) { |
|
||||
return { tabList: tabList.slice(0, 1), dynamicCompList: _dynamicCompList.slice(0, 1) } |
|
||||
} |
|
||||
|
|
||||
if (!shop.value.activityList.length && shop.value.thirdKouCode) { |
|
||||
return { tabList: tabList.slice(1), dynamicCompList: _dynamicCompList.slice(1) } |
|
||||
} |
|
||||
|
|
||||
//无活动和无thirdKouCode |
|
||||
return { tabList: [], dynamicCompList: [] } |
|
||||
}) |
|
||||
const currentComp = computed(() => menuList.value.dynamicCompList[tabIdx.value]) |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.tabs-wrapper { |
|
||||
position: relative; |
|
||||
display: flex; |
|
||||
height: 80px; |
|
||||
padding: 6px; |
|
||||
background: rgba(0, 0, 0, 0.05); |
|
||||
border-radius: 12px; |
|
||||
margin-bottom: 40px; |
|
||||
&::before { |
|
||||
position: absolute; |
|
||||
content: ''; |
|
||||
top: 6px; |
|
||||
left: 6px; |
|
||||
background: #ffffff; |
|
||||
box-shadow: inset 0px -4px 0px rgba(177, 189, 220, 0.1); |
|
||||
border-radius: 8px; |
|
||||
width: 128px; |
|
||||
height: 68px; |
|
||||
z-index: 0; |
|
||||
transition: all 0.5s; |
|
||||
transform: translate3d(v-bind(distance), 0, 0); |
|
||||
} |
|
||||
.tab { |
|
||||
position: relative; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: center; |
|
||||
width: 128px; |
|
||||
height: 68px; |
|
||||
font-weight: 700; |
|
||||
font-family: 'font_bold'; |
|
||||
font-size: 18px; |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
margin-right: 12px; |
|
||||
z-index: 1; |
|
||||
transition: color 0.5s; |
|
||||
&:last-child { |
|
||||
margin-right: 0; |
|
||||
} |
|
||||
&.active { |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,104 +0,0 @@ |
|||||
<template> |
|
||||
<div class="brand-recommend"> |
|
||||
<p class="title">热门推荐</p> |
|
||||
<ScrollView :list="list" scroll-x class="content"> |
|
||||
<div class="recommend-content"> |
|
||||
<div class="group-item" @click="handleShop(item)" v-for="item of list" :key="item.shopId"> |
|
||||
<div class="logo-wrapper"> |
|
||||
<img loading="lazy" :src="config.sourceUrl + item.materialList?.[0]" alt="" class="shop-logo" /> |
|
||||
</div> |
|
||||
<p class="name"> |
|
||||
<span class="shop-name">{{ switchLanguage(item, 'shopName') }}</span> |
|
||||
<span class="name-right"><img :src="config.sourceUrl + item.industryUrl" class="format-icon" alt="" />{{ item.floor }}</span> |
|
||||
</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
</ScrollView> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|
||||
|
|
||||
defineProps({ |
|
||||
list: Array, |
|
||||
config: Object |
|
||||
}) |
|
||||
const emits = defineEmits(['click']) |
|
||||
|
|
||||
function handleShop(item) { |
|
||||
emits('click', item) |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.brand-recommend { |
|
||||
margin-left: 170px; |
|
||||
|
|
||||
.title { |
|
||||
font-weight: 700; |
|
||||
font-size: 24px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
padding-bottom: 12px; |
|
||||
} |
|
||||
.content { |
|
||||
width: 910px; |
|
||||
overflow: hidden; |
|
||||
margin-bottom: 40px; |
|
||||
} |
|
||||
.recommend-content { |
|
||||
display: inline-block; |
|
||||
white-space: nowrap; |
|
||||
padding-top: 32px; |
|
||||
height: 255px; |
|
||||
} |
|
||||
.group-item { |
|
||||
display: inline-block; |
|
||||
width: 320px; |
|
||||
height: 220px; |
|
||||
background: rgba(255, 255, 255, 0.4); |
|
||||
border-radius: 8px; |
|
||||
overflow: hidden; |
|
||||
margin-right: 16px; |
|
||||
} |
|
||||
.logo-wrapper { |
|
||||
width: 320px; |
|
||||
height: 180px; |
|
||||
background-color: #fff; |
|
||||
} |
|
||||
.shop-logo { |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
border-radius: 8px; |
|
||||
object-fit: cover; |
|
||||
} |
|
||||
.name { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: space-between; |
|
||||
padding: 13px 12px; |
|
||||
} |
|
||||
.shop-name { |
|
||||
font-weight: 700; |
|
||||
font-size: 12px; |
|
||||
line-height: 14px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
} |
|
||||
.name-right { |
|
||||
font-weight: 700; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
font-size: 12px; |
|
||||
line-height: 14px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
} |
|
||||
.format-icon { |
|
||||
width: 14px; |
|
||||
height: 14px; |
|
||||
margin-right: 8px; |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,204 +0,0 @@ |
|||||
<template> |
|
||||
<ScrollView class="business-scroll"> |
|
||||
<div class="business-content"> |
|
||||
<div class="three-wrapper" :class="{ active: cardIdx === index }" v-for="(item, index) of 10" :key="item"> |
|
||||
<div class="front"> |
|
||||
<div class="title"> |
|
||||
<p class="title-left">巴黎贝甜</p> |
|
||||
<p class="title-right">¥<i>30</i></p> |
|
||||
</div> |
|
||||
<p class="sub-title">30元代金券,满129可用</p> |
|
||||
<ScrollView class="intro-scroll" scrollbar> |
|
||||
<p class="intro"> |
|
||||
欧时力(香港)集团全权代理意大利品牌欧时力(OCHIRLY),并组建欧时力(中国)有限公司,全权负责OCHIRLY在大中华区的品牌经营。欧时力自1999年进入中国市场以来,欧时力以前所未有的速度在中国市场发展壮大。在短短的两、三年间,迅速于中国60多个一、二类主要消费城市的160余家加盟店以及专柜年销售额达到2.5亿。销售业绩评效均名列前茅,整体业绩不断上扬!在女装市场享有一定的知名度和美誉度。欧时力(香港)集团全权代理意大利品牌欧时力(OCHIRLY),并组建欧时力(中国)有限公司,全权负责OCHIRLY在大中华区的品牌经营。欧时力自1999年进入中国市场以来,欧时力以前所未有的速度在中国市场发展壮大。在短短的两、三年间,迅速于中国60多个一、二类主要消费城市的160余家加盟店以及专柜年销售额达到2.5亿在短短的两、三年间,迅速于中国60多个一、二类主要消费城市的160余家加盟店以及专柜年销售额达到2.5亿在短短的两、三年间,迅速于中 |
|
||||
</p> |
|
||||
</ScrollView> |
|
||||
<p class="time first">领取时间:2021-01-01</p> |
|
||||
<p class="time">使用时间:2021-01-01至2021-12-30</p> |
|
||||
<div class="btn" @click="handleCard(item, index)">立即领取</div> |
|
||||
</div> |
|
||||
<div class="back"> |
|
||||
<div class="code"> |
|
||||
<img src="" alt="" class="code-img" /> |
|
||||
<div class="text">微信扫一扫</div> |
|
||||
</div> |
|
||||
<div class="btn" @click="cardIdx = -1">返回</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</ScrollView> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { ref } from 'vue' |
|
||||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|
||||
|
|
||||
const cardIdx = ref(-1) |
|
||||
function handleCard(item, index) { |
|
||||
cardIdx.value = index |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.business-scroll { |
|
||||
position: relative; |
|
||||
margin-left: 170px; |
|
||||
overflow: hidden; |
|
||||
margin-top: 58px; |
|
||||
height: 1560px; |
|
||||
.business-content { |
|
||||
display: grid; |
|
||||
grid-template-columns: repeat(2, 420px); |
|
||||
gap: 56px 30px; |
|
||||
} |
|
||||
|
|
||||
.three-wrapper { |
|
||||
display: inline-block; |
|
||||
width: 420px; |
|
||||
height: 528px; |
|
||||
position: relative; |
|
||||
transform-style: preserve-3d; |
|
||||
transform: perspective(800px); |
|
||||
transition: all 0.5s; |
|
||||
transform-origin: center; |
|
||||
margin-right: 25px; |
|
||||
|
|
||||
&.active { |
|
||||
transform: rotateY(-180deg); |
|
||||
} |
|
||||
} |
|
||||
.front, |
|
||||
.back { |
|
||||
width: 420px; |
|
||||
height: 528px; |
|
||||
backface-visibility: hidden; |
|
||||
background: url('../../assets/images/member/line.png') no-repeat center 445px rgba(255, 255, 255, 0.8); |
|
||||
background-size: 497px 1px; |
|
||||
overflow: hidden; |
|
||||
border-radius: 12px; |
|
||||
.btn { |
|
||||
height: 83px; |
|
||||
line-height: 83px; |
|
||||
font-weight: 700; |
|
||||
font-size: 20px; |
|
||||
font-family: 'font_bold'; |
|
||||
text-align: center; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
} |
|
||||
&::before, |
|
||||
&::after { |
|
||||
content: ''; |
|
||||
position: absolute; |
|
||||
width: 18px; |
|
||||
height: 18px; |
|
||||
background: #f7f7f9; |
|
||||
bottom: 75px; |
|
||||
border-radius: 50%; |
|
||||
} |
|
||||
&::before { |
|
||||
left: -9px; |
|
||||
} |
|
||||
&::after { |
|
||||
right: -9px; |
|
||||
} |
|
||||
} |
|
||||
.front { |
|
||||
position: relative; |
|
||||
.title { |
|
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
color: #f1b33e; |
|
||||
align-items: baseline; |
|
||||
padding: 32px 56px 25px 56px; |
|
||||
|
|
||||
.title-left { |
|
||||
font-weight: 700; |
|
||||
font-size: 20px; |
|
||||
font-family: 'font_bold'; |
|
||||
} |
|
||||
.title-right { |
|
||||
font-size: 24px; |
|
||||
font-weight: 700; |
|
||||
font-family: 'font_bold'; |
|
||||
i { |
|
||||
font-size: 48px; |
|
||||
font-weight: 700; |
|
||||
padding-left: 6px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.sub-title { |
|
||||
font-weight: 700; |
|
||||
font-size: 24px; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
margin-bottom: 40px; |
|
||||
font-family: 'font_bold'; |
|
||||
margin-left: 56px; |
|
||||
} |
|
||||
.intro-scroll { |
|
||||
height: 152px; |
|
||||
overflow: hidden; |
|
||||
position: relative; |
|
||||
margin-bottom: 45px; |
|
||||
margin-right: 34px; |
|
||||
padding-right: 16px; |
|
||||
margin-left: 56px; |
|
||||
|
|
||||
.intro { |
|
||||
font-size: 14px; |
|
||||
line-height: 200%; |
|
||||
text-align: justify; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
white-space: normal; |
|
||||
} |
|
||||
: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; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.time { |
|
||||
font-size: 14px; |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
margin-left: 56px; |
|
||||
margin-bottom: 41px; |
|
||||
|
|
||||
&.first { |
|
||||
margin-bottom: 9px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.back { |
|
||||
position: absolute; |
|
||||
left: 0; |
|
||||
top: 0; |
|
||||
transform: rotateY(-180deg); |
|
||||
.code { |
|
||||
height: 445px; |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
align-items: center; |
|
||||
justify-content: center; |
|
||||
.code-img { |
|
||||
width: 150px; |
|
||||
height: 150px; |
|
||||
} |
|
||||
.text { |
|
||||
font-weight: 700; |
|
||||
font-size: 20px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
padding-top: 47px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,154 +0,0 @@ |
|||||
<template> |
|
||||
<Dialog @close="close"> |
|
||||
<div class="content"> |
|
||||
<div class="info"> |
|
||||
<div class="group"> |
|
||||
<p class="text">车牌号</p> |
|
||||
<p class="text-bold">沪AB66688</p> |
|
||||
</div> |
|
||||
<div class="group"> |
|
||||
<p class="text">车位号</p> |
|
||||
<p class="text-bold">E-123</p> |
|
||||
</div> |
|
||||
<div class="group"> |
|
||||
<p class="text">停车时长</p> |
|
||||
<p class="text-bold">2<i>小时</i>30<i>分钟</i></p> |
|
||||
</div> |
|
||||
<div class="last"> |
|
||||
<p class="text">费用</p> |
|
||||
<p class="text-bold">¥<i>2</i></p> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="right"> |
|
||||
<div class="car-wrapper"> |
|
||||
<img src="" alt="" class="car-img" /> |
|
||||
</div> |
|
||||
<div class="codes-wrapper"> |
|
||||
<img src="" alt="" class="code" /> |
|
||||
<p class="tip">扫码缴费</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
<Button class="car-btn" @click="close" /> |
|
||||
<Go class="go" /> |
|
||||
</div> |
|
||||
</Dialog> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import Button from '@/base/Button/Button.vue' |
|
||||
import Go from '@/base/Go/Go.vue' |
|
||||
import Dialog from '@/layouts/Dialog.vue' |
|
||||
|
|
||||
const emits = defineEmits(['close']) |
|
||||
function close() { |
|
||||
emits('close') |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.content { |
|
||||
position: relative; |
|
||||
display: flex; |
|
||||
margin: 0 auto; |
|
||||
margin-top: 160px; |
|
||||
width: max-content; |
|
||||
animation-duration: 0.2s; |
|
||||
} |
|
||||
.info { |
|
||||
width: 480px; |
|
||||
height: 668px; |
|
||||
background: #ffffff; |
|
||||
border-radius: 12px; |
|
||||
padding: 64px 0 0 0; |
|
||||
} |
|
||||
.group { |
|
||||
margin-bottom: 64px; |
|
||||
padding-left: 64px; |
|
||||
|
|
||||
.text-bold { |
|
||||
font-weight: 700; |
|
||||
font-size: 32px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
i { |
|
||||
font-size: 20px; |
|
||||
padding: 0 5px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.text { |
|
||||
font-weight: 400; |
|
||||
font-size: 20px; |
|
||||
line-height: 23px; |
|
||||
margin-bottom: 18px; |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
} |
|
||||
|
|
||||
.last { |
|
||||
font-weight: 700; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
padding-left: 64px; |
|
||||
padding-top: 38px; |
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.1); |
|
||||
.text-bold { |
|
||||
font-size: 24px; |
|
||||
i { |
|
||||
font-size: 48px; |
|
||||
padding-left: 5px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.right { |
|
||||
margin-left: 32px; |
|
||||
.car-wrapper { |
|
||||
width: 480px; |
|
||||
height: 270px; |
|
||||
margin-bottom: 32px; |
|
||||
background: #ffffff; |
|
||||
border-radius: 12px; |
|
||||
overflow: hidden; |
|
||||
.car-img { |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
object-fit: cover; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.codes-wrapper { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
width: 480px; |
|
||||
height: 366px; |
|
||||
background: #ffffff; |
|
||||
border-radius: 12px; |
|
||||
.code { |
|
||||
width: 150px; |
|
||||
height: 150px; |
|
||||
} |
|
||||
.tip { |
|
||||
font-weight: 700; |
|
||||
font-size: 20px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
padding-top: 41px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.car-btn { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
right: -112px; |
|
||||
} |
|
||||
|
|
||||
.go { |
|
||||
position: absolute; |
|
||||
bottom: -160px; |
|
||||
left: 50%; |
|
||||
transform: translateX(-50%); |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,131 +0,0 @@ |
|||||
<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 { computed } 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 ?? []) |
|
||||
</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: var(--global-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: var(--carousel-titleColor); |
|
||||
} |
|
||||
|
|
||||
.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: var(--carousel-introColor); |
|
||||
} |
|
||||
} |
|
||||
@media (min-aspect-ratio: 1/1) { |
|
||||
.benefits-wrapper { |
|
||||
flex-direction: row; |
|
||||
align-items: flex-start; |
|
||||
padding-top: 100px; |
|
||||
padding-left: 63px; |
|
||||
.carousel { |
|
||||
position: relative; |
|
||||
} |
|
||||
} |
|
||||
.title { |
|
||||
padding-top: 0; |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,118 +0,0 @@ |
|||||
<template> |
|
||||
<div class="customer-wrapper"> |
|
||||
<div class="masker" @click="close"></div> |
|
||||
<div class="customer-content"> |
|
||||
<div class="customer-avatar"> |
|
||||
<div class="avatar-wrapper"> |
|
||||
<img src="../../assets/images/search/customer.png" class="avatar" alt="" /> |
|
||||
</div> |
|
||||
<p class="customer-name">客服001</p> |
|
||||
</div> |
|
||||
<div class="time">00:34</div> |
|
||||
<div class="status">{{ $t('waiting') }}...</div> |
|
||||
<img src="../../assets/images/search/out.svg" class="off" @click="close" alt="" /> |
|
||||
<div class="close" @click="close"> |
|
||||
<img src="../../assets/images/detail/yellow_close.png" alt="" /> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
const emits = defineEmits(['close']) |
|
||||
function close() { |
|
||||
emits('close') |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.customer-wrapper { |
|
||||
position: fixed; |
|
||||
top: 0; |
|
||||
right: 0; |
|
||||
bottom: 0; |
|
||||
left: 0; |
|
||||
z-index: 1000; |
|
||||
animation-duration: 0.2s; |
|
||||
.masker { |
|
||||
position: fixed; |
|
||||
top: 0; |
|
||||
right: 0; |
|
||||
bottom: 0; |
|
||||
left: 0; |
|
||||
} |
|
||||
.customer-content { |
|
||||
position: relative; |
|
||||
width: 600px; |
|
||||
height: 400px; |
|
||||
margin: 0 auto; |
|
||||
margin-top: 760px; |
|
||||
background: #ffffff; |
|
||||
box-shadow: 0px 40px 60px rgba(0, 0, 0, 0.08); |
|
||||
border-radius: 12px; |
|
||||
.customer-avatar { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
padding: 24px 0 0 32px; |
|
||||
margin-bottom: 50px; |
|
||||
|
|
||||
.avatar-wrapper { |
|
||||
width: 56px; |
|
||||
height: 56px; |
|
||||
box-shadow: 0px 8px 16px rgba(0, 0, 0, 0.04); |
|
||||
border-radius: 50%; |
|
||||
padding: 14px; |
|
||||
background-color: var(--color-fff); |
|
||||
.avatar { |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
object-fit: contain; |
|
||||
} |
|
||||
} |
|
||||
.customer-name { |
|
||||
font-weight: 700; |
|
||||
font-size: 16px; |
|
||||
padding-left: 16px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
} |
|
||||
} |
|
||||
.time { |
|
||||
font-weight: 700; |
|
||||
font-size: 48px; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
font-family: 'font_bold'; |
|
||||
padding-bottom: 8px; |
|
||||
text-align: center; |
|
||||
} |
|
||||
.status { |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
text-align: center; |
|
||||
font-size: 18px; |
|
||||
margin-bottom: 49px; |
|
||||
} |
|
||||
.off { |
|
||||
display: block; |
|
||||
width: 80px; |
|
||||
height: 80px; |
|
||||
margin: 0 auto; |
|
||||
} |
|
||||
} |
|
||||
.close { |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
position: absolute; |
|
||||
top: 12px; |
|
||||
right: 12px; |
|
||||
width: 56px; |
|
||||
height: 56px; |
|
||||
background: rgba(0, 0, 0, 0.02); |
|
||||
border-radius: 12px; |
|
||||
img { |
|
||||
width: 56px; |
|
||||
height: 56px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,36 +0,0 @@ |
|||||
<template> |
|
||||
<swiper v-if="list.length" :watchOverflow="true" :modules="[Autoplay, EffectFade, Pagination]" :pagination="true" effect="fade" :autoplay="true"> |
|
||||
<swiper-slide v-for="item of list" :key="item"> |
|
||||
<slot :item="item"></slot> |
|
||||
</swiper-slide> |
|
||||
</swiper> |
|
||||
<img v-else src="../../assets/images/nodata.svg" class="stay-tuned" alt="" /> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import SwiperCore, { Autoplay, EffectFade, Pagination } from 'swiper' |
|
||||
import { Swiper, SwiperSlide } from 'swiper/vue' |
|
||||
|
|
||||
import 'swiper/css' |
|
||||
import 'swiper/css/effect-fade' |
|
||||
import 'swiper/css/pagination' |
|
||||
|
|
||||
SwiperCore.use([Autoplay, EffectFade, Pagination]) |
|
||||
|
|
||||
defineProps({ |
|
||||
list: { |
|
||||
type: Array, |
|
||||
default: () => [] |
|
||||
} |
|
||||
}) |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.stay-tuned { |
|
||||
position: absolute; |
|
||||
left: 50%; |
|
||||
top: 50%; |
|
||||
transform: translate3d(-50%, -50%, 0); |
|
||||
object-fit: contain; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,194 +0,0 @@ |
|||||
<template> |
|
||||
<ScrollView class="format-wrapper" ref="scroll" :refresh-delay="800" :list="list"> |
|
||||
<div class="format-scroll"> |
|
||||
<div class="format-item" @click="handleFormat({ industryName: '全部品牌', industryNameEn: 'all' }, -1)"> |
|
||||
<div class="parent flex" :class="{ active: parentIdxRef === -1 }"> |
|
||||
<div class="format-left flex"> |
|
||||
<img src="../../assets/images/detail/all.svg" class="icon" alt="" /> |
|
||||
<span class="text">{{ $t('all') }}</span> |
|
||||
</div> |
|
||||
<div class="format-right flex"> |
|
||||
<span class="total">{{ total }}</span> |
|
||||
<img src="../../assets/images/detail/all_dot.svg" class="right-icon" alt="" /> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="format-item" v-for="(item, index) of list" :key="item.industryId"> |
|
||||
<div |
|
||||
class="parent flex" |
|
||||
@click="handleFormat(item, index)" |
|
||||
:class="[index === parentIdxRef ? 'active' : '', index === parentIdxRef && childIdxRef !== -1 ? 'child-active' : '']" |
|
||||
> |
|
||||
<div class="format-left flex"> |
|
||||
<img :src="config.sourceUrl + item.fileUrl" class="icon" alt="" /> |
|
||||
<span class="text">{{ switchLanguage(item, 'industryName') }}</span> |
|
||||
</div> |
|
||||
<div class="format-right flex"> |
|
||||
<span class="total">{{ item.shopNum }}</span> |
|
||||
<Arrow :size="18" fill="rgba(0, 0, 0, 0.2)" v-if="item.industryList?.length" class="right-icon svg-icon" /> |
|
||||
<img src="../../assets/images/detail/all_dot.svg" class="icon" v-else alt="" /> |
|
||||
</div> |
|
||||
</div> |
|
||||
<template v-if="item.industryList?.length"> |
|
||||
<div class="format-child-wrapper" v-if="index === parentIdxRef"> |
|
||||
<div class="format-item" v-for="(child, index) of item.industryList" :key="child.industryId"> |
|
||||
<div class="parent flex" :class="{ active: childIdxRef === index }" @click="handleChildFormat(child, index)"> |
|
||||
<div class="format-left flex"> |
|
||||
<span class="text">{{ switchLanguage(child, 'industryName') }}</span> |
|
||||
</div> |
|
||||
<div class="format-right flex"> |
|
||||
<span class="total">{{ child.shopNum ?? 0 }}</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
</div> |
|
||||
</div> |
|
||||
</ScrollView> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { computed, nextTick, ref } from 'vue' |
|
||||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|
||||
import { Arrow } from '@/base/Svg' |
|
||||
|
|
||||
const props = defineProps({ |
|
||||
list: { |
|
||||
type: Array, |
|
||||
default: () => [] |
|
||||
}, |
|
||||
config: { |
|
||||
type: Object, |
|
||||
default: () => ({}) |
|
||||
} |
|
||||
}) |
|
||||
const total = computed(() => props.list.reduce((_total, item) => _total + item.shopNum, 0)) |
|
||||
|
|
||||
const emits = defineEmits(['click']) |
|
||||
emits('click', { industryName: '全部品牌', industryNameEn: 'all' }, -1) |
|
||||
|
|
||||
const scroll = ref(null) |
|
||||
const parentIdxRef = ref(-1) |
|
||||
const childIdxRef = ref(-1) |
|
||||
function handleFormat(item, index) { |
|
||||
emits('click', item, index) |
|
||||
childIdxRef.value = -1 |
|
||||
parentIdxRef.value = index |
|
||||
nextTick(() => { |
|
||||
scroll.value.refresh() |
|
||||
}) |
|
||||
} |
|
||||
function handleChildFormat(child, childIdx) { |
|
||||
childIdxRef.value = childIdx |
|
||||
emits('click', child, childIdx) |
|
||||
nextTick(() => { |
|
||||
scroll.value.refresh() |
|
||||
}) |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.format-wrapper { |
|
||||
overflow: hidden; |
|
||||
height: 810px; |
|
||||
border-radius: 8px; |
|
||||
width: 200px; |
|
||||
margin-top: 18px; |
|
||||
.format-scroll { |
|
||||
overflow: hidden; |
|
||||
border-radius: 8px; |
|
||||
} |
|
||||
.format-item { |
|
||||
width: 200px; |
|
||||
background-color: #fff; |
|
||||
.parent { |
|
||||
height: 56px; |
|
||||
padding: 0 12px 0 24px; |
|
||||
justify-content: space-between; |
|
||||
align-items: center; |
|
||||
&.active { |
|
||||
background: linear-gradient(90deg, #ffbd35 0%, #ffd260 100%); |
|
||||
.icon, |
|
||||
.right-icon { |
|
||||
filter: brightness(50) invert(70%); |
|
||||
&.svg-icon { |
|
||||
filter: none; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
:deep(path) { |
|
||||
fill: rgba(0, 0, 0, 0.6); |
|
||||
} |
|
||||
|
|
||||
.svg-icon { |
|
||||
transform: rotate(-180deg); |
|
||||
} |
|
||||
.text, |
|
||||
.total { |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
} |
|
||||
} |
|
||||
&.child-active { |
|
||||
background: transparent; |
|
||||
.icon, |
|
||||
.right-icon { |
|
||||
filter: none; |
|
||||
} |
|
||||
:deep(path) { |
|
||||
fill: rgba(0, 0, 0, 0.6); |
|
||||
} |
|
||||
.right-icon { |
|
||||
transform: rotate(-180deg); |
|
||||
} |
|
||||
.text, |
|
||||
.total { |
|
||||
color: var(--color-9b0); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.format-right { |
|
||||
.icon { |
|
||||
margin-left: 8px; |
|
||||
margin-right: 0; |
|
||||
} |
|
||||
} |
|
||||
.icon { |
|
||||
width: 16px; |
|
||||
height: 16px; |
|
||||
margin-right: 8px; |
|
||||
} |
|
||||
.text, |
|
||||
.total { |
|
||||
font-weight: 700; |
|
||||
font-size: 14px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
} |
|
||||
.total { |
|
||||
font-weight: 400; |
|
||||
font-family: 'font_regular'; |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
} |
|
||||
.right-icon { |
|
||||
margin-left: 8px; |
|
||||
transition: transform 0.3s; |
|
||||
} |
|
||||
} |
|
||||
.format-child-wrapper { |
|
||||
.parent { |
|
||||
padding: 0 48px; |
|
||||
} |
|
||||
.text { |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
} |
|
||||
.total { |
|
||||
color: rgba(0, 0, 0, 0.2); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.flex { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,86 +0,0 @@ |
|||||
<template> |
|
||||
<div class="keyboard"> |
|
||||
<div |
|
||||
class="letter-item" |
|
||||
@click="handleLetter(item, index)" |
|
||||
:class="[item === '空格' ? 'space' : '', item === 'del' ? 'del' : '', letterIdx === index ? 'active' : '']" |
|
||||
v-for="(item, index) of letter" |
|
||||
:key="item" |
|
||||
v-html="generateInnerHTML(item)" |
|
||||
></div> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { ref } from 'vue' |
|
||||
import { letter } from '../Search/tabs' |
|
||||
import { storeToRefs } from 'pinia' |
|
||||
import { useStore } from '@/store/root' |
|
||||
const store = useStore() |
|
||||
const { theme } = storeToRefs(store) |
|
||||
function generateInnerHTML(item) { |
|
||||
return item === 'del' ? `<img style="width:24px;height:24px" src="${theme.value.images.delete}" alt="">` : item |
|
||||
} |
|
||||
|
|
||||
const emits = defineEmits(['del', 'handle-letter']) |
|
||||
const timer = ref(null) |
|
||||
const letterIdx = ref(-1) |
|
||||
function handleLetter(item, index) { |
|
||||
letterIdx.value = index |
|
||||
clearTimeout(timer.value) |
|
||||
timer.value = setTimeout(() => { |
|
||||
letterIdx.value = -1 |
|
||||
clearTimeout(timer.value) |
|
||||
}, 300) |
|
||||
|
|
||||
if (item !== '空格' && item !== 'del') { |
|
||||
emits('handle-letter', item) |
|
||||
return |
|
||||
} |
|
||||
|
|
||||
item === 'del' && emits('del') |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.keyboard { |
|
||||
display: flex; |
|
||||
flex-wrap: wrap; |
|
||||
padding-top: 40px; |
|
||||
.letter-item { |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
width: 48px; |
|
||||
height: 48px; |
|
||||
text-align: center; |
|
||||
line-height: 48px; |
|
||||
background: var(--search-keyBg, #ffffff); |
|
||||
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.03), inset 0px -1px 0px rgba(177, 189, 220, 0.1); |
|
||||
border-radius: var(--global-radius, 8px); |
|
||||
font-weight: 700; |
|
||||
font-size: 18px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: var(--search-keyColor, rgba(0, 0, 0, 0.6)); |
|
||||
margin-right: 8px; |
|
||||
margin-bottom: 8px; |
|
||||
&:nth-child(21) { |
|
||||
margin-left: 28px; |
|
||||
} |
|
||||
&.space { |
|
||||
font-size: 14px; |
|
||||
} |
|
||||
&.del { |
|
||||
width: 104px; |
|
||||
img { |
|
||||
width: 24px; |
|
||||
height: 24px; |
|
||||
} |
|
||||
} |
|
||||
&.active { |
|
||||
background: var(--search-keyboardActiveBg); |
|
||||
color: #fff; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,107 +0,0 @@ |
|||||
<template> |
|
||||
<div class="written-wrapper"> |
|
||||
<ScrollView class="word-scroll" scroll-x :list="wordsList"> |
|
||||
<div class="word-content"> |
|
||||
<div class="word" @click="handleWord(item, index)" :class="{ active: wordIdx === index }" v-for="(item, index) of wordsList" :key="item">{{ item }}</div> |
|
||||
</div> |
|
||||
</ScrollView> |
|
||||
<Written |
|
||||
@result="getWordList" |
|
||||
:width="552" |
|
||||
:height="196" |
|
||||
background-color="transparent" |
|
||||
fill-font-size="48px" |
|
||||
fill-style="rgba(0, 0, 0, 0.02)" |
|
||||
:stroke-style="theme.search.writeColor" |
|
||||
/> |
|
||||
<div class="del" @click="del"> |
|
||||
<img :src="theme.images.delete" class="del-icon" alt="" /> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { ref } from 'vue' |
|
||||
import Written from '../Written/Written.vue' |
|
||||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|
||||
import { storeToRefs } from 'pinia' |
|
||||
import { useStore } from '@/store/root' |
|
||||
const wordsList = ref([]) |
|
||||
const store = useStore() |
|
||||
const { theme } = storeToRefs(store) |
|
||||
|
|
||||
function getWordList(list) { |
|
||||
wordsList.value = list |
|
||||
} |
|
||||
|
|
||||
const emits = defineEmits(['handle-word', 'del']) |
|
||||
const wordIdx = ref(-1) |
|
||||
const timer = ref(null) |
|
||||
function handleWord(item, index) { |
|
||||
clearTimeout(timer.value) |
|
||||
wordIdx.value = index |
|
||||
emits('handle-word', item) |
|
||||
timer.value = setTimeout(() => { |
|
||||
wordIdx.value = -1 |
|
||||
clearTimeout(timer.value) |
|
||||
}, 300) |
|
||||
} |
|
||||
|
|
||||
function del() { |
|
||||
emits('del') |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.written-wrapper { |
|
||||
position: relative; |
|
||||
width: 552px; |
|
||||
height: 252px; |
|
||||
background: var(--search-keyBg, #ffffff); |
|
||||
border-radius: var(--global-radius, 12px); |
|
||||
margin-top: 16px; |
|
||||
overflow: hidden; |
|
||||
.word-scroll { |
|
||||
position: relative; |
|
||||
height: 56px; |
|
||||
background: var(--search-keyBg, #ffffff); |
|
||||
box-shadow: 0px 8px 16px rgba(0, 0, 0, 0.04); |
|
||||
.word-content { |
|
||||
display: inline-block; |
|
||||
white-space: nowrap; |
|
||||
} |
|
||||
.word { |
|
||||
display: inline-block; |
|
||||
width: 66px; |
|
||||
height: 56px; |
|
||||
text-align: center; |
|
||||
line-height: 56px; |
|
||||
font-weight: 700; |
|
||||
font-size: 18px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: var(--search-keyColor, rgba(0, 0, 0, 0.6)); |
|
||||
&.active { |
|
||||
color: #fff; |
|
||||
background: var(--search-keyboardActiveBg); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.del { |
|
||||
position: absolute; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: center; |
|
||||
width: 104px; |
|
||||
height: 48px; |
|
||||
right: 8px; |
|
||||
bottom: 8px; |
|
||||
background: rgba(0, 0, 0, 0.05); |
|
||||
box-shadow: inset 0px -1px 0px rgba(177, 189, 220, 0.1); |
|
||||
border-radius: var(--global-radius, 8px); |
|
||||
img { |
|
||||
width: 24px; |
|
||||
height: 24px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,49 +0,0 @@ |
|||||
<template> |
|
||||
<div class="language"> |
|
||||
<div class="language-item" @click="setLanguage('zh')" :class="{ active: language === 'zh' }">中</div> |
|
||||
<div class="language-item" @click="setLanguage('en')" :class="{ active: language === 'en' }">EN</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { useStore } from '@/store/root' |
|
||||
import { storeToRefs } from 'pinia' |
|
||||
|
|
||||
const store = useStore() |
|
||||
const { language } = storeToRefs(store) |
|
||||
|
|
||||
function setLanguage(lang) { |
|
||||
store.language !== lang && store.SET_LANGUAGE(lang) |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.language { |
|
||||
position: absolute; |
|
||||
left: 24px; |
|
||||
bottom: 56px; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: center; |
|
||||
width: 93px; |
|
||||
height: 32px; |
|
||||
border-radius: 12px; |
|
||||
background-color: var(--color-black-opacity-02); |
|
||||
padding: 0 3px; |
|
||||
} |
|
||||
.language-item { |
|
||||
width: 43px; |
|
||||
height: 26px; |
|
||||
border-radius: 10px; |
|
||||
text-align: center; |
|
||||
line-height: 26px; |
|
||||
font-size: 14px; |
|
||||
color: var(--color-black-opacity-4); |
|
||||
font-family: 'font_bold'; |
|
||||
font-weight: bolder; |
|
||||
&.active { |
|
||||
background: var(--color-linear-lightgoldenyellow); |
|
||||
color: var(--color-black-opacity-6); |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,314 +0,0 @@ |
|||||
<template> |
|
||||
<div class="login-by-phone"> |
|
||||
<div class="masker" @click="handleClose"></div> |
|
||||
<div class="detail-content"> |
|
||||
<h4 class="login-text">{{ $t('login') }}</h4> |
|
||||
<div class="phone-group" @click="changeInputFocus('phone')"> |
|
||||
<img src="../../assets/images/member/hpone_tip.png" alt="" class="group-icon" /> |
|
||||
<div class="line"></div> |
|
||||
<input v-model="phoneRef" readonly type="text" :placeholder="$t('phoneNum')" class="input" /> |
|
||||
</div> |
|
||||
<div class="pwd-box"> |
|
||||
<div class="phone-group pwd"> |
|
||||
<img src="../../assets/images/member/pwd.png" alt="" class="group-icon" /> |
|
||||
<div class="line"></div> |
|
||||
<input v-model="msgRef" @click="changeInputFocus('msg')" readonly type="text" :placeholder="$t('enterCode')" class="input" /> |
|
||||
</div> |
|
||||
<div class="button" @click="sendMsg" :class="{ active: isSended }">{{ isSended ? countDownRef + ' ' + $t('again') : $t('sendCode') }}</div> |
|
||||
</div> |
|
||||
<div class="comfirm" @click="comfirm" :class="{ active: phoneRef.length && msgRef.length }">{{ $t('denglu') }}</div> |
|
||||
<div class="phone-keyboard"> |
|
||||
<div |
|
||||
class="num" |
|
||||
@click="handleNum(item === 10 ? '' : item === 11 ? 0 : item, index)" |
|
||||
:class="{ active: numIdx === index }" |
|
||||
v-for="(item, index) of 12" |
|
||||
:key="item" |
|
||||
v-html="generate(item)" |
|
||||
></div> |
|
||||
</div> |
|
||||
<div class="close" @click="handleClose"> |
|
||||
<img src="../../assets/images/detail/yellow_close.png" alt="" /> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { ref, onBeforeUnmount } from 'vue' |
|
||||
import { checkPhoneNumber } from '@/utils/utils' |
|
||||
import Message from '@/base/Message/Message' |
|
||||
|
|
||||
const emits = defineEmits(['success', 'error', 'close']) |
|
||||
|
|
||||
function generate(item) { |
|
||||
return item === 10 ? '' : item === 11 ? 0 : item === 12 ? `<img src=${require('../../assets/images/member/del.svg')} class="del-icon" alt="" />` : item |
|
||||
} |
|
||||
|
|
||||
const phoneRef = ref('') |
|
||||
const msgRef = ref('') |
|
||||
const inputFocusRef = ref('phone') |
|
||||
const numIdx = ref(-1) |
|
||||
const numTimer = ref(null) |
|
||||
|
|
||||
function handleNum(item, index) { |
|
||||
clearTimeout(numTimer.value) |
|
||||
numIdx.value = index |
|
||||
numTimer.value = setTimeout(() => { |
|
||||
numIdx.value = -1 |
|
||||
clearTimeout(numTimer.value) |
|
||||
}, 300) |
|
||||
|
|
||||
if (item === 12) { |
|
||||
del() |
|
||||
return |
|
||||
} |
|
||||
|
|
||||
if (inputFocusRef.value === 'phone') { |
|
||||
if (phoneRef.value.length < 11) { |
|
||||
phoneRef.value += item |
|
||||
} |
|
||||
} |
|
||||
if (inputFocusRef.value === 'msg') { |
|
||||
msgRef.value += item |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
function changeInputFocus(name) { |
|
||||
inputFocusRef.value = name |
|
||||
} |
|
||||
function del() { |
|
||||
if (inputFocusRef.value === 'phone') { |
|
||||
phoneRef.value = phoneRef.value.substring(0, phoneRef.value.length - 1) |
|
||||
} |
|
||||
if (inputFocusRef.value === 'msg') { |
|
||||
msgRef.value = msgRef.value.substring(0, msgRef.value.length - 1) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
const countDownRef = ref(60) |
|
||||
const countDownTimer = ref(null) |
|
||||
const isSended = ref(false) |
|
||||
//发送验证码 |
|
||||
function sendMsg() { |
|
||||
if (isSended.value) return |
|
||||
if (!checkPhoneNumber(phoneRef.value)) { |
|
||||
Message({ type: 'error', text: '请输入正确的手机号' }) |
|
||||
return |
|
||||
} |
|
||||
if (!phoneRef.value.length) { |
|
||||
Message({ type: 'error', text: '手机号不能为空' }) |
|
||||
return |
|
||||
} |
|
||||
isSended.value = true |
|
||||
inputFocusRef.value = 'msg' |
|
||||
countDownTimer.value = setInterval(countDown, 1000) |
|
||||
} |
|
||||
//一分钟倒计时 |
|
||||
function countDown() { |
|
||||
countDownRef.value-- |
|
||||
if (countDownRef.value <= 0) { |
|
||||
isSended.value = false |
|
||||
countDownRef.value = 60 |
|
||||
clearInterval(countDownTimer.value) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
//登录 |
|
||||
function comfirm() { |
|
||||
if (!checkPhoneNumber(phoneRef.value)) { |
|
||||
Message({ type: 'error', text: '请输入正确的手机号' }) |
|
||||
return |
|
||||
} |
|
||||
emits('success') |
|
||||
} |
|
||||
|
|
||||
onBeforeUnmount(() => { |
|
||||
clearInterval(countDownTimer.value) |
|
||||
}) |
|
||||
|
|
||||
function handleClose() { |
|
||||
emits('close') |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.login-by-phone { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
right: 0; |
|
||||
bottom: 0; |
|
||||
left: 0; |
|
||||
z-index: 51; |
|
||||
animation-duration: 0.3s; |
|
||||
} |
|
||||
.masker { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
right: 0; |
|
||||
bottom: 0; |
|
||||
left: 0; |
|
||||
z-index: 20; |
|
||||
} |
|
||||
.detail-content { |
|
||||
position: relative; |
|
||||
width: 484px; |
|
||||
height: 732px; |
|
||||
margin: 0 auto; |
|
||||
margin-top: 594px; |
|
||||
background: #ffffff; |
|
||||
box-shadow: 0px 40px 60px rgba(0, 0, 0, 0.08); |
|
||||
border-radius: 12px; |
|
||||
z-index: 21; |
|
||||
|
|
||||
.close { |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
position: absolute; |
|
||||
top: 12px; |
|
||||
right: 12px; |
|
||||
width: 56px; |
|
||||
height: 56px; |
|
||||
background: rgba(0, 0, 0, 0.02); |
|
||||
border-radius: 12px; |
|
||||
img { |
|
||||
width: 56px; |
|
||||
height: 56px; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.login-text { |
|
||||
font-weight: 700; |
|
||||
font-size: 24px; |
|
||||
line-height: 28px; |
|
||||
margin-bottom: 40px; |
|
||||
padding-top: 48px; |
|
||||
padding-left: 72px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
} |
|
||||
::-webkit-input-placeholder { |
|
||||
font-size: 12px; |
|
||||
color: var(--color-0cb); |
|
||||
} |
|
||||
.pwd-box { |
|
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
width: 340px; |
|
||||
margin-top: 12px; |
|
||||
margin-left: 72px; |
|
||||
margin-bottom: 24px; |
|
||||
|
|
||||
.phone-group { |
|
||||
margin-left: 0; |
|
||||
} |
|
||||
|
|
||||
.button { |
|
||||
width: 116px; |
|
||||
height: 64px; |
|
||||
left: 296px; |
|
||||
top: 192px; |
|
||||
text-align: center; |
|
||||
line-height: 64px; |
|
||||
background: linear-gradient(90deg, #ffbd35 0%, #ffd260 100%); |
|
||||
border-radius: 12px; |
|
||||
font-weight: 700; |
|
||||
font-size: 14px; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
font-family: 'font_bold'; |
|
||||
} |
|
||||
} |
|
||||
.phone-group { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
width: 340px; |
|
||||
height: 64px; |
|
||||
margin-left: 72px; |
|
||||
background: rgba(0, 0, 0, 0.05); |
|
||||
border-radius: 12px; |
|
||||
padding-left: 20px; |
|
||||
&.pwd { |
|
||||
width: 212px; |
|
||||
} |
|
||||
.group-icon { |
|
||||
width: 20px; |
|
||||
} |
|
||||
.line { |
|
||||
width: 1px; |
|
||||
height: 14px; |
|
||||
background: rgba(0, 0, 0, 0.05); |
|
||||
border-radius: 1px; |
|
||||
margin: 0 14px; |
|
||||
} |
|
||||
} |
|
||||
.input { |
|
||||
width: 100%; |
|
||||
display: block; |
|
||||
border: none; |
|
||||
outline: none; |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
font-size: 16px; |
|
||||
background-color: transparent; |
|
||||
} |
|
||||
|
|
||||
.comfirm { |
|
||||
width: 340px; |
|
||||
height: 64px; |
|
||||
line-height: 64px; |
|
||||
left: 72px; |
|
||||
top: 280px; |
|
||||
background: linear-gradient(90deg, #ffbd35 0%, #ffd260 100%); |
|
||||
border-radius: 12px; |
|
||||
font-weight: 700; |
|
||||
font-size: 18px; |
|
||||
text-align: center; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
font-family: 'font_bold'; |
|
||||
margin: 0 auto; |
|
||||
margin-bottom: 40px; |
|
||||
} |
|
||||
.phone-keyboard { |
|
||||
display: grid; |
|
||||
grid-template-columns: repeat(3, 108px); |
|
||||
grid-template-rows: repeat(4, 56px); |
|
||||
gap: 12px 8px; |
|
||||
background: linear-gradient(180deg, rgba(0, 0, 0, 0.05) 0%, rgba(0, 0, 0, 0.025) 100%); |
|
||||
padding: 40px 70px 48px 70px; |
|
||||
.num { |
|
||||
background: #ffffff; |
|
||||
box-shadow: inset 0px -4px 0px rgba(177, 189, 220, 0.1); |
|
||||
border-radius: 8px; |
|
||||
font-weight: 700; |
|
||||
font-size: 20px; |
|
||||
font-family: 'font_bold'; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: center; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
&.active { |
|
||||
background: linear-gradient(90deg, #ffbd35 0%, #ffd260 100%); |
|
||||
box-shadow: inset 0px -4px 0px rgba(177, 189, 220, 0.1); |
|
||||
} |
|
||||
} |
|
||||
.del { |
|
||||
height: 56px; |
|
||||
width: 112px; |
|
||||
display: inline-flex; |
|
||||
align-items: center; |
|
||||
justify-content: center; |
|
||||
.del-icon { |
|
||||
width: 24px; |
|
||||
height: 24px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.close { |
|
||||
position: absolute; |
|
||||
top: 24px; |
|
||||
width: 56px; |
|
||||
height: 56px; |
|
||||
right: 24px; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,83 +0,0 @@ |
|||||
<template> |
|
||||
<div class="full-code"> |
|
||||
<div class="code-wrapper"> |
|
||||
<img :src="icon" class="img" alt="" /> |
|
||||
<p class="youhui">{{ title }}</p> |
|
||||
<slot /> |
|
||||
<div class="close" @click="handleClose"> |
|
||||
<img src="../../assets/images/detail/yellow_close.png" alt="" /> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
defineProps({ |
|
||||
title: { |
|
||||
type: String, |
|
||||
default: '注册成功' |
|
||||
}, |
|
||||
icon: { |
|
||||
type: String, |
|
||||
default: require('@/assets/images/member/login_success.png') |
|
||||
} |
|
||||
}) |
|
||||
const emits = defineEmits(['close']) |
|
||||
|
|
||||
function handleClose() { |
|
||||
emits('close') |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.full-code { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
right: 0; |
|
||||
bottom: 0; |
|
||||
left: 0; |
|
||||
} |
|
||||
.code-wrapper { |
|
||||
position: absolute; |
|
||||
top: 50%; |
|
||||
left: 50%; |
|
||||
width: 592px; |
|
||||
min-height: 512px; |
|
||||
transform: translate3d(-50%, -50%, 0); |
|
||||
background: #ffffff; |
|
||||
box-shadow: 0px 0px 80px rgba(0, 0, 0, 0.163735); |
|
||||
padding-top: 96px; |
|
||||
z-index: 10; |
|
||||
.img { |
|
||||
display: block; |
|
||||
margin: 0 auto; |
|
||||
margin-bottom: 96px; |
|
||||
width: 200px; |
|
||||
height: 200px; |
|
||||
} |
|
||||
.youhui { |
|
||||
font-weight: 700; |
|
||||
font-size: 20px; |
|
||||
line-height: 23px; |
|
||||
text-align: center; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
} |
|
||||
|
|
||||
.close { |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
position: absolute; |
|
||||
top: 12px; |
|
||||
right: 12px; |
|
||||
width: 56px; |
|
||||
height: 56px; |
|
||||
background: rgba(0, 0, 0, 0.02); |
|
||||
border-radius: 12px; |
|
||||
img { |
|
||||
width: 56px; |
|
||||
height: 56px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,104 +0,0 @@ |
|||||
<template> |
|
||||
<div class="mall-wrapper"> |
|
||||
<div class="carousel"> |
|
||||
<EffectFade :list="banner"> |
|
||||
<template v-slot="{ item }"> |
|
||||
<div class="banner-wrapper"> |
|
||||
<img :src="config.sourceUrl + item" alt="" class="banner" /> |
|
||||
</div> |
|
||||
</template> |
|
||||
</EffectFade> |
|
||||
</div> |
|
||||
<h1 class="title">{{ $t('mallIntroduce') }}</h1> |
|
||||
<ScrollView :list="introduce.content" scrollbar class="mall-intro-scroll"> |
|
||||
<p class="mall-intro"> |
|
||||
{{ switchLanguage(introduce, 'content') }} |
|
||||
</p> |
|
||||
</ScrollView> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { ref, computed } from 'vue' |
|
||||
import { storeToRefs } from 'pinia' |
|
||||
import { useStore } from '@/store/root' |
|
||||
import { getMallInfoList } from '@/http/api' |
|
||||
import EffectFade from '@/components/EffectFade/EffectFade.vue' |
|
||||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|
||||
|
|
||||
const store = useStore() |
|
||||
const { config } = storeToRefs(store) |
|
||||
|
|
||||
const introduce = ref({}) |
|
||||
const banner = computed(() => introduce.value?.fileList ?? []) |
|
||||
getMallInfoList().then(({ data }) => { |
|
||||
introduce.value = data ?? {} |
|
||||
}) |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.mall-wrapper { |
|
||||
width: 870px; |
|
||||
margin-left: 170px; |
|
||||
margin-right: 40px; |
|
||||
margin-top: 58px; |
|
||||
background: rgba(255, 255, 255, 0.4); |
|
||||
box-shadow: inset 1px 0px 0px #ffffff; |
|
||||
border-radius: 12px; |
|
||||
padding-bottom: 52px; |
|
||||
.carousel { |
|
||||
width: 870px; |
|
||||
height: 490px; |
|
||||
background: #ffffff; |
|
||||
margin-right: 56px; |
|
||||
border-radius: 8px; |
|
||||
overflow: hidden; |
|
||||
.banner-wrapper { |
|
||||
width: 870px; |
|
||||
height: 490px; |
|
||||
} |
|
||||
.banner { |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
object-fit: cover; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.title { |
|
||||
padding-top: 48px; |
|
||||
padding-bottom: 32px; |
|
||||
margin-left: 56px; |
|
||||
font-weight: 700; |
|
||||
font-size: 24px; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
font-family: 'font_bold'; |
|
||||
} |
|
||||
.mall-intro-scroll { |
|
||||
position: relative; |
|
||||
overflow: hidden; |
|
||||
height: 758px; |
|
||||
margin-left: 56px; |
|
||||
margin-right: 34px; |
|
||||
padding-right: 16px; |
|
||||
.mall-intro { |
|
||||
font-weight: 400; |
|
||||
font-size: 14px; |
|
||||
line-height: 200%; |
|
||||
text-align: justify; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
} |
|
||||
: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; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,105 +0,0 @@ |
|||||
<template> |
|
||||
<div class="big-input"> |
|
||||
<div class="input-left" @click="handleSearch"> |
|
||||
<div class="search-content"> |
|
||||
<img src="../../assets/images/index/index_search.png" class="index-search-icon" alt="" /> |
|
||||
<div class="mock-input"> |
|
||||
<p class="search">搜索</p> |
|
||||
<p class="search-en">search</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="input-right" @click="handleVoice"> |
|
||||
<img src="../../assets/images/index/index_voice.png" class="index-voice-icon" alt="" /> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { useStore } from '@/store/root' |
|
||||
|
|
||||
const store = useStore() |
|
||||
function handleSearch() { |
|
||||
store.SET_SHOW_SEARCH(true) |
|
||||
} |
|
||||
|
|
||||
function handleVoice() { |
|
||||
store.SET_SHOW_SEARCH(true) |
|
||||
store.SET_SHOW_VOICE(true) |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.big-input { |
|
||||
display: flex; |
|
||||
height: 108px; |
|
||||
margin-right: 40px; |
|
||||
margin-bottom: 46px; |
|
||||
z-index: 55; |
|
||||
.input-left { |
|
||||
position: relative; |
|
||||
flex: 1; |
|
||||
background: linear-gradient(90deg, #f6a62c 0%, #ffbc3f 100%); |
|
||||
box-shadow: 0px 12px 20px rgba(253, 177, 48, 0.1); |
|
||||
border-radius: 12px; |
|
||||
margin-right: 20px; |
|
||||
&::after { |
|
||||
position: absolute; |
|
||||
border-radius: 12px; |
|
||||
content: ''; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
top: 0; |
|
||||
bottom: 4px; |
|
||||
background: #fff; |
|
||||
} |
|
||||
.search-content { |
|
||||
position: relative; |
|
||||
z-index: 2; |
|
||||
} |
|
||||
.search-content { |
|
||||
position: relative; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
width: 629px; |
|
||||
height: 104px; |
|
||||
background-color: var(--color-white-opacity); |
|
||||
box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.3), inset 0px 4px 30px rgba(0, 0, 0, 0.02); |
|
||||
border-radius: 12px; |
|
||||
&::before { |
|
||||
position: absolute; |
|
||||
content: ''; |
|
||||
width: 2px; |
|
||||
height: 30px; |
|
||||
left: 112px; |
|
||||
top: 37px; |
|
||||
background: var(--color-black-opacity-2); |
|
||||
} |
|
||||
.index-search-icon { |
|
||||
width: 48px; |
|
||||
height: 48px; |
|
||||
margin-right: 54px; |
|
||||
margin-left: 44px; |
|
||||
} |
|
||||
.search { |
|
||||
font-weight: 700; |
|
||||
font-size: 20px; |
|
||||
line-height: 28px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: var(--color-black-opacity-6); |
|
||||
} |
|
||||
.search-en { |
|
||||
font-weight: 700; |
|
||||
font-family: 'font_bold'; |
|
||||
font-size: 14px; |
|
||||
text-transform: uppercase; |
|
||||
color: var(--color-black-opacity-4); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.index-voice-icon { |
|
||||
margin-top: -9px; |
|
||||
width: 246px; |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,388 +0,0 @@ |
|||||
<template> |
|
||||
<Dialog @close="close"> |
|
||||
<div class="content"> |
|
||||
<div class="content-left"> |
|
||||
<div class="poster-wrapper"> |
|
||||
<img class="poster" :src="movie.posterPath" alt="" /> |
|
||||
</div> |
|
||||
<p class="name">{{ movie.showName }}</p> |
|
||||
<div class="group"> |
|
||||
<div class="text">导演:</div> |
|
||||
<div class="info">{{ movie.director }}</div> |
|
||||
</div> |
|
||||
<div class="group"> |
|
||||
<div class="text">类型:</div> |
|
||||
<div class="info">{{ movie.type }}</div> |
|
||||
</div> |
|
||||
<div class="group"> |
|
||||
<div class="text">语言:</div> |
|
||||
<div class="info">{{ movie.language }}</div> |
|
||||
</div> |
|
||||
<div class="group"> |
|
||||
<div class="text">片长:</div> |
|
||||
<div class="info">{{ movie.duration }} 分钟</div> |
|
||||
</div> |
|
||||
<div class="group last"> |
|
||||
<div class="text">主演:</div> |
|
||||
<div class="info">{{ movie.leadingRole }}</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="remark"> |
|
||||
<span>{{ $t('rate') }}</span> |
|
||||
{{ movie.remark }} |
|
||||
</div> |
|
||||
|
|
||||
<div class="price"> |
|
||||
<div class="price-num"> |
|
||||
¥ |
|
||||
<i>{{ movie.price / 100 }}</i> |
|
||||
起 |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="content-right"> |
|
||||
<ScrollView class="date-scroll" scroll-x :list="dateList"> |
|
||||
<div class="date-content"> |
|
||||
<div |
|
||||
class="date-item" |
|
||||
:ref="el => tabsEl.push(el)" |
|
||||
:class="{ active: index === tabIdx }" |
|
||||
@click="handleTab(index)" |
|
||||
v-for="(item, index) of dateList" |
|
||||
:key="item.week" |
|
||||
> |
|
||||
<span class="date">{{ item.customDate }}</span> |
|
||||
<span class="week">{{ item.week }}</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</ScrollView> |
|
||||
<ScrollView class="list-scroll"> |
|
||||
<div class="list-content"> |
|
||||
<table> |
|
||||
<tr v-for="item of 2" :key="item"> |
|
||||
<td class="w-190"> |
|
||||
<div class="start">12:00</div> |
|
||||
<div class="end">12:00</div> |
|
||||
</td> |
|
||||
<td class="w-190"> |
|
||||
<div class="type">IMAX</div> |
|
||||
<div class="ting">激光 3 厅</div> |
|
||||
</td> |
|
||||
<td class="w-190 line"> |
|
||||
<div class="ticket">06<i>张</i></div> |
|
||||
<div class="rest">余票</div> |
|
||||
</td> |
|
||||
<td class="w-222 center"> |
|
||||
<div class="price-num">¥<i>36</i>起</div> |
|
||||
</td> |
|
||||
<td> |
|
||||
<div class="button" @click="showQRCodeDialog">{{ $t('ticket') }}</div> |
|
||||
</td> |
|
||||
</tr> |
|
||||
</table> |
|
||||
</div> |
|
||||
</ScrollView> |
|
||||
</div> |
|
||||
<Button @click="close" class="btn" /> |
|
||||
</div> |
|
||||
<QRCode v-if="showCode" @close="showCode = false" title="微信扫码购买" /> |
|
||||
</Dialog> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { computed, ref, defineAsyncComponent } from 'vue' |
|
||||
import { futureDate } from '@/utils/utils' |
|
||||
import Dialog from '@/layouts/Dialog.vue' |
|
||||
import Button from '@/base/Button/Button.vue' |
|
||||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|
||||
const QRCode = defineAsyncComponent(() => import('@/base/QRCode/QRCode.vue')) |
|
||||
|
|
||||
defineProps({ |
|
||||
movie: { |
|
||||
type: Object, |
|
||||
default: () => ({}) |
|
||||
} |
|
||||
}) |
|
||||
|
|
||||
const dateList = computed(() => futureDate()) |
|
||||
|
|
||||
const tabIdx = ref(0) |
|
||||
function handleTab(index) { |
|
||||
tabIdx.value = index |
|
||||
moveTo(index) |
|
||||
} |
|
||||
|
|
||||
const PADDING_LEFT = 6 |
|
||||
const tabsEl = ref([]) |
|
||||
const distance = ref(0) |
|
||||
|
|
||||
function moveTo(index) { |
|
||||
distance.value = tabsEl.value[index].offsetLeft - PADDING_LEFT + 'px' |
|
||||
} |
|
||||
|
|
||||
const showCode = ref(false) |
|
||||
function showQRCodeDialog() { |
|
||||
showCode.value = true |
|
||||
} |
|
||||
|
|
||||
const emits = defineEmits(['close']) |
|
||||
function close() { |
|
||||
emits('close') |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.content { |
|
||||
position: relative; |
|
||||
display: flex; |
|
||||
margin: 0 auto; |
|
||||
margin-top: 360px; |
|
||||
width: max-content; |
|
||||
z-index: 10; |
|
||||
|
|
||||
.price-num { |
|
||||
padding-left: 24px; |
|
||||
padding-right: 24px; |
|
||||
color: #f1b33e; |
|
||||
font-weight: 700; |
|
||||
font-family: 'font_bold'; |
|
||||
font-size: 16px; |
|
||||
i { |
|
||||
font-size: 32px; |
|
||||
padding: 0 4px; |
|
||||
} |
|
||||
} |
|
||||
.content-left { |
|
||||
width: 260px; |
|
||||
height: 727px; |
|
||||
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); |
|
||||
font-family: 'font_bold'; |
|
||||
margin-bottom: 20px; |
|
||||
@include no-wrap; |
|
||||
padding-left: 24px; |
|
||||
} |
|
||||
.group { |
|
||||
display: flex; |
|
||||
padding: 0 24px; |
|
||||
margin-bottom: 8px; |
|
||||
&.last { |
|
||||
margin-bottom: 14px; |
|
||||
.info { |
|
||||
height: 28px; |
|
||||
@include more-wrap; |
|
||||
} |
|
||||
} |
|
||||
.text { |
|
||||
font-weight: 700; |
|
||||
font-size: 12px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
padding-right: 8px; |
|
||||
flex-shrink: 0; |
|
||||
} |
|
||||
.info { |
|
||||
font-weight: 400; |
|
||||
font-size: 12px; |
|
||||
line-height: 14px; |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.remark { |
|
||||
font-weight: 700; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
margin-left: 24px; |
|
||||
font-family: 'font_bold'; |
|
||||
font-size: 14px; |
|
||||
margin-right: 24px; |
|
||||
padding-bottom: 47px; |
|
||||
margin-bottom: 16px; |
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.02); |
|
||||
|
|
||||
span { |
|
||||
font-size: 16px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.content-right { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
} |
|
||||
.date-scroll { |
|
||||
position: relative; |
|
||||
overflow: hidden; |
|
||||
width: 680px; |
|
||||
height: 128px; |
|
||||
background: rgba(0, 0, 0, 0.2); |
|
||||
border-radius: 12px; |
|
||||
padding: 6px 0; |
|
||||
margin-bottom: 24px; |
|
||||
|
|
||||
.date-content { |
|
||||
display: inline-block; |
|
||||
white-space: nowrap; |
|
||||
padding: 0 6px; |
|
||||
|
|
||||
&::before { |
|
||||
position: absolute; |
|
||||
content: ''; |
|
||||
left: 6px; |
|
||||
background: linear-gradient(90deg, #f6a62c 0%, #ffbc3f 100%); |
|
||||
box-shadow: 0 20px 30px rgba(221, 152, 55, 0.2); |
|
||||
border-radius: 8px; |
|
||||
border: 1px solid rgba(255, 189, 53, 1); |
|
||||
width: 134px; |
|
||||
height: 116px; |
|
||||
z-index: 0; |
|
||||
transition: all 0.5s; |
|
||||
transform: translate3d(v-bind(distance), 0, 0); |
|
||||
} |
|
||||
|
|
||||
.date-item { |
|
||||
display: inline-flex; |
|
||||
flex-direction: column; |
|
||||
align-items: center; |
|
||||
justify-content: center; |
|
||||
margin-right: 12px; |
|
||||
width: 134px; |
|
||||
height: 116px; |
|
||||
} |
|
||||
.date { |
|
||||
position: relative; |
|
||||
z-index: 5; |
|
||||
font-weight: 700; |
|
||||
font-family: 'font_bold'; |
|
||||
font-size: 20px; |
|
||||
color: #ffffff; |
|
||||
padding-bottom: 5px; |
|
||||
} |
|
||||
.week { |
|
||||
font-weight: 400; |
|
||||
position: relative; |
|
||||
z-index: 5; |
|
||||
font-size: 14px; |
|
||||
text-align: center; |
|
||||
color: #ffffff; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.list-scroll { |
|
||||
flex: 1; |
|
||||
overflow: hidden; |
|
||||
border-radius: 8px; |
|
||||
table { |
|
||||
width: 680px; |
|
||||
tr { |
|
||||
display: block; |
|
||||
background-color: #fff; |
|
||||
border-radius: 8px; |
|
||||
margin-bottom: 8px; |
|
||||
padding: 26px 48px; |
|
||||
} |
|
||||
td { |
|
||||
position: relative; |
|
||||
vertical-align: middle; |
|
||||
text-align: left; |
|
||||
&.center { |
|
||||
text-align: center; |
|
||||
} |
|
||||
.start { |
|
||||
font-weight: 700; |
|
||||
font-size: 24px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
padding-bottom: 4px; |
|
||||
} |
|
||||
.end { |
|
||||
font-weight: 400; |
|
||||
font-size: 14px; |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
} |
|
||||
.type { |
|
||||
font-weight: 700; |
|
||||
font-family: 'font_bold'; |
|
||||
font-size: 24px; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
padding-bottom: 4px; |
|
||||
} |
|
||||
.ting { |
|
||||
font-weight: 400; |
|
||||
font-size: 14px; |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
} |
|
||||
.ticket { |
|
||||
font-weight: 700; |
|
||||
font-size: 24px; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
font-family: 'font_bold'; |
|
||||
padding-bottom: 4px; |
|
||||
} |
|
||||
.rest { |
|
||||
font-weight: 400; |
|
||||
font-size: 14px; |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
} |
|
||||
.button { |
|
||||
width: 136px; |
|
||||
height: 56px; |
|
||||
line-height: 56px; |
|
||||
text-align: center; |
|
||||
background: linear-gradient(90deg, #f6a62c 0%, #ffbc3f 100%); |
|
||||
box-shadow: 0px 20px 30px rgba(221, 152, 55, 0.2); |
|
||||
border-radius: 53px; |
|
||||
font-weight: 700; |
|
||||
font-size: 18px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: #ffffff; |
|
||||
} |
|
||||
} |
|
||||
.w-190 { |
|
||||
width: 190px; |
|
||||
} |
|
||||
.w-150 { |
|
||||
width: 150px; |
|
||||
} |
|
||||
.w-222 { |
|
||||
width: 222px; |
|
||||
} |
|
||||
} |
|
||||
.line { |
|
||||
&:after { |
|
||||
content: ''; |
|
||||
position: absolute; |
|
||||
right: 0; |
|
||||
height: 32px; |
|
||||
width: 1px; |
|
||||
border-right: 1px solid rgba(38, 36, 36, 0.1); |
|
||||
top: 50%; |
|
||||
transform: translateY(-50%); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.btn { |
|
||||
position: absolute; |
|
||||
right: 0; |
|
||||
top: -104px; |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,231 +0,0 @@ |
|||||
<template> |
|
||||
<TransitionGroup name="width" mode="out-in" tag="div" class="plateinput-wrapper" :class="[searchMethods === '车位' ? 'active' : '']"> |
|
||||
<div |
|
||||
class="input" |
|
||||
v-for="(item, index) of renderInputLength" |
|
||||
:key="item" |
|
||||
:class="[index === license.length - 1 ? 'active' : '', searchMethods === '车位' ? 'space' : '']" |
|
||||
> |
|
||||
<span class="text">{{ license[index] }}</span> |
|
||||
</div> |
|
||||
<div |
|
||||
key="energy" |
|
||||
v-if="needsEnergy" |
|
||||
class="last input" |
|
||||
@click="handleEnergy" |
|
||||
:class="[_isEnergy ? 'enrgy' : '', _isEnergy && license.length === ENERGY_PLATE ? 'active' : '']" |
|
||||
> |
|
||||
<span class="text" v-if="!_isEnergy">新能源</span> |
|
||||
<span class="text" v-else>{{ _isEnergy ? (license.length === ENERGY_PLATE && license[license.length - 1]) || '' : '' }}</span> |
|
||||
</div> |
|
||||
<div key="btn" class="btn" @click="confirm"> |
|
||||
<img src="../../assets/images/parking/search-parking.png" class="icon" alt="" /> |
|
||||
</div> |
|
||||
</TransitionGroup> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { ref, computed } from 'vue' |
|
||||
|
|
||||
const NOT_ENERGY_PLATE = 7 |
|
||||
const ENERGY_PLATE = 8 |
|
||||
|
|
||||
const props = defineProps({ |
|
||||
spaceMaxLength: { |
|
||||
type: Number, |
|
||||
default: 5 |
|
||||
}, |
|
||||
license: { |
|
||||
type: Array, |
|
||||
default: () => [] |
|
||||
}, |
|
||||
needsEnergy: { |
|
||||
type: Boolean, |
|
||||
default: true |
|
||||
}, |
|
||||
searchMethods: { |
|
||||
type: String, |
|
||||
validator: status => ['车牌', '车位'].includes(status) |
|
||||
} |
|
||||
}) |
|
||||
|
|
||||
const renderInputLength = computed(() => (props.searchMethods === '车牌' ? NOT_ENERGY_PLATE : props.spaceMaxLength)) |
|
||||
|
|
||||
const emits = defineEmits(['handle-energy', 'confirm']) |
|
||||
const _isEnergy = ref(false) |
|
||||
emits('handle-energy', _isEnergy.value) |
|
||||
|
|
||||
function handleEnergy() { |
|
||||
_isEnergy.value = !_isEnergy.value |
|
||||
emits('handle-energy', _isEnergy.value) |
|
||||
} |
|
||||
|
|
||||
function confirm() { |
|
||||
emits('confirm') |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.plateinput-wrapper { |
|
||||
display: flex; |
|
||||
position: relative; |
|
||||
margin-bottom: 32px; |
|
||||
margin-left: 170px; |
|
||||
&.active { |
|
||||
&::before { |
|
||||
left: 141px; |
|
||||
} |
|
||||
} |
|
||||
&::before { |
|
||||
content: ''; |
|
||||
position: absolute; |
|
||||
width: 2px; |
|
||||
height: 63px; |
|
||||
background: rgba(0, 0, 0, 0.1); |
|
||||
border-radius: 2px; |
|
||||
left: 176px; |
|
||||
top: 50%; |
|
||||
transform: translateY(-50%); |
|
||||
transition: left 0.5s; |
|
||||
} |
|
||||
} |
|
||||
.input { |
|
||||
position: relative; |
|
||||
border-radius: 8px; |
|
||||
width: 80px; |
|
||||
height: 100px; |
|
||||
margin-right: 8px; |
|
||||
font-weight: 700; |
|
||||
font-size: 32px; |
|
||||
line-height: 100px; |
|
||||
text-align: center; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
font-family: 'font_bold'; |
|
||||
background: #ffffff; |
|
||||
box-shadow: 0px 10px 20px rgba(0, 0, 0, 0.03); |
|
||||
border-radius: 8px; |
|
||||
&.space { |
|
||||
margin-right: 8px !important; |
|
||||
width: 132px; |
|
||||
&:first-child { |
|
||||
margin-right: 22px !important; |
|
||||
} |
|
||||
} |
|
||||
.text { |
|
||||
position: relative; |
|
||||
z-index: 3; |
|
||||
} |
|
||||
|
|
||||
&::after { |
|
||||
width: 80px; |
|
||||
height: 100px; |
|
||||
left: 0; |
|
||||
top: 0; |
|
||||
content: ''; |
|
||||
position: absolute; |
|
||||
background: #ffffff; |
|
||||
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.03); |
|
||||
border-radius: 8px; |
|
||||
z-index: 2; |
|
||||
} |
|
||||
&.space { |
|
||||
&:nth-child(2) { |
|
||||
margin-right: 12px; |
|
||||
} |
|
||||
&::after { |
|
||||
width: 132px; |
|
||||
} |
|
||||
} |
|
||||
&.active { |
|
||||
&::before { |
|
||||
position: absolute; |
|
||||
content: ''; |
|
||||
top: -2px; |
|
||||
right: -2px; |
|
||||
bottom: -2px; |
|
||||
left: -2px; |
|
||||
background: var(--color-linear-lightgoldenyellow); |
|
||||
border-radius: 8px; |
|
||||
z-index: 1; |
|
||||
} |
|
||||
} |
|
||||
&:nth-child(2) { |
|
||||
margin-right: 18px; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.last { |
|
||||
line-height: initial; |
|
||||
&.enrgy { |
|
||||
.text { |
|
||||
padding-top: 0; |
|
||||
font-weight: 700; |
|
||||
font-size: 32px; |
|
||||
line-height: 90px; |
|
||||
text-align: center; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
} |
|
||||
&::after { |
|
||||
background: #ffffff; |
|
||||
content: ''; |
|
||||
} |
|
||||
} |
|
||||
&::after { |
|
||||
content: '+'; |
|
||||
font-weight: 700; |
|
||||
font-size: 32px; |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
line-height: 60px; |
|
||||
background: transparent; |
|
||||
} |
|
||||
.text { |
|
||||
width: 80px; |
|
||||
height: 100px; |
|
||||
display: inline-block; |
|
||||
font-weight: 700; |
|
||||
font-size: 18px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
border: 2px solid #fff; |
|
||||
text-align: center; |
|
||||
border-radius: 8px; |
|
||||
padding-top: 51px; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.btn { |
|
||||
position: absolute; |
|
||||
right: 40px; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: center; |
|
||||
margin-left: 12px; |
|
||||
width: 156px; |
|
||||
height: 100px; |
|
||||
background: linear-gradient(90deg, #ffbd35 0%, #ffd260 100%); |
|
||||
box-shadow: 0px 10px 20px rgba(0, 0, 0, 0.03), inset 0px -4px 0px rgba(243, 176, 36, 0.5); |
|
||||
border-radius: 8px; |
|
||||
transition: all 0.5s; |
|
||||
|
|
||||
.icon { |
|
||||
width: 32px; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.width-enter-active, |
|
||||
.width-leave-active { |
|
||||
width: 80px; |
|
||||
transition: all 0.5s; |
|
||||
transition-timing-function: cubic-bezier(0.75, 0, 0.24, 1); |
|
||||
} |
|
||||
|
|
||||
.width-enter-from, |
|
||||
.width-leave-to { |
|
||||
width: 0; |
|
||||
opacity: 0; |
|
||||
} |
|
||||
.width-move { |
|
||||
transition: transform 0.5s !important; |
|
||||
transition-timing-function: cubic-bezier(0.75, 0, 0.24, 1); |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,91 +0,0 @@ |
|||||
<template> |
|
||||
<div class="keyboard-wrapper"> |
|
||||
<div |
|
||||
class="keyboard-item" |
|
||||
@click="handleKeyboard(item, index)" |
|
||||
:class="[isUppercaseWord(item) ? 'uppercase' : '', item === 'del' ? 'del' : '', keyboardIdx === index ? 'active' : '', searchMethods === '车位' ? 'space' : '']" |
|
||||
v-for="(item, index) of list" |
|
||||
:key="item" |
|
||||
v-html="generateInnerHTML(item)" |
|
||||
></div> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { ref, computed } from 'vue' |
|
||||
import { keyboard } from './keyboard' |
|
||||
import { isUppercaseWord, isZhWord } from '@/utils/utils' |
|
||||
|
|
||||
const props = defineProps({ |
|
||||
searchMethods: { |
|
||||
type: String, |
|
||||
validator: status => ['车牌', '车位'].includes(status) |
|
||||
} |
|
||||
}) |
|
||||
|
|
||||
const list = computed(() => (props.searchMethods === '车位' ? keyboard.filter(item => !isZhWord(item)) : keyboard)) |
|
||||
|
|
||||
function generateInnerHTML(item) { |
|
||||
return item === 'del' ? `<img src="${require('@/assets/images/parking/del.svg')}" alt="">` : item |
|
||||
} |
|
||||
|
|
||||
const emits = defineEmits(['handle-keyboard', 'del']) |
|
||||
const keyboardIdx = ref(-1) |
|
||||
const keyboardTimer = ref(null) |
|
||||
function handleKeyboard(item, index) { |
|
||||
item === 'del' ? emits('del') : emits('handle-keyboard', item) |
|
||||
clearTimeout(keyboardTimer.value) |
|
||||
keyboardIdx.value = index |
|
||||
keyboardTimer.value = setTimeout(() => { |
|
||||
keyboardIdx.value = -1 |
|
||||
clearTimeout(keyboardTimer.value) |
|
||||
}, 300) |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.keyboard-wrapper { |
|
||||
display: flex; |
|
||||
flex-wrap: wrap; |
|
||||
margin-left: 170px; |
|
||||
margin-right: 32px; |
|
||||
margin-bottom: 56px; |
|
||||
.keyboard-item { |
|
||||
width: 41.76px; |
|
||||
height: 48px; |
|
||||
background: rgba(255, 255, 255, 0.6); |
|
||||
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.03), inset 0px -1px 0px rgba(177, 189, 220, 0.1); |
|
||||
border-radius: 6px; |
|
||||
text-align: center; |
|
||||
margin-right: 7px; |
|
||||
margin-bottom: 8px; |
|
||||
font-size: 18px; |
|
||||
font-family: 'font_medium'; |
|
||||
line-height: 48px; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
&.space { |
|
||||
width: 90.48px; |
|
||||
&.del { |
|
||||
width: 187.92px; |
|
||||
} |
|
||||
} |
|
||||
&.uppercase { |
|
||||
background: #ffffff; |
|
||||
} |
|
||||
&.del { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: center; |
|
||||
width: 90px; |
|
||||
line-height: initial; |
|
||||
background: rgba(0, 0, 0, 0.05); |
|
||||
box-shadow: inset 0px -1px 0px rgba(0, 0, 0, 0.1); |
|
||||
} |
|
||||
&.active { |
|
||||
background: #f1b33e; |
|
||||
color: #fff; |
|
||||
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.03), inset 0px -1px 0px rgba(177, 189, 220, 0.1); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,73 +0,0 @@ |
|||||
export const keyboard = [ |
|
||||
'粤', |
|
||||
'京', |
|
||||
'津', |
|
||||
'渝', |
|
||||
'冀', |
|
||||
'豫', |
|
||||
'云', |
|
||||
'辽', |
|
||||
'黑', |
|
||||
'A', |
|
||||
'B', |
|
||||
'C', |
|
||||
'D', |
|
||||
'E', |
|
||||
'F', |
|
||||
1, |
|
||||
2, |
|
||||
3, |
|
||||
'湘', |
|
||||
'皖', |
|
||||
'鲁', |
|
||||
'苏', |
|
||||
'浙', |
|
||||
'赣', |
|
||||
'鄂', |
|
||||
'桂', |
|
||||
'甘', |
|
||||
'G', |
|
||||
'H', |
|
||||
'J', |
|
||||
'K', |
|
||||
'L', |
|
||||
'M', |
|
||||
4, |
|
||||
5, |
|
||||
6, |
|
||||
'晋', |
|
||||
'蒙', |
|
||||
'陕', |
|
||||
'吉', |
|
||||
'闽', |
|
||||
'贵', |
|
||||
'沪', |
|
||||
'青', |
|
||||
'藏', |
|
||||
'N', |
|
||||
'P', |
|
||||
'Q', |
|
||||
'R', |
|
||||
'S', |
|
||||
'T', |
|
||||
7, |
|
||||
8, |
|
||||
9, |
|
||||
'川', |
|
||||
'宁', |
|
||||
'琼', |
|
||||
'港', |
|
||||
'澳', |
|
||||
'新', |
|
||||
'使', |
|
||||
'领', |
|
||||
'警', |
|
||||
'U', |
|
||||
'V', |
|
||||
'W', |
|
||||
'X', |
|
||||
'Y', |
|
||||
'Z', |
|
||||
'0', |
|
||||
'del' |
|
||||
] |
|
||||
@ -1,91 +0,0 @@ |
|||||
<template> |
|
||||
<div class="row"> |
|
||||
<div class="back" :style="{ backgroundImage: `url(${theme.images.back})` }" v-if="$route.path !== '/index'" @click="() => $router.push('/index')"></div> |
|
||||
<div class="bar" @click="handleSearch"> |
|
||||
<div class="icon" :style="{ backgroundImage: `url(${theme.images.searchIcon})` }"></div> |
|
||||
<div class="stick"></div> |
|
||||
<div class="placeholder">精确查询品牌/公共设施</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { useStore } from '@/store/root' |
|
||||
import { storeToRefs } from 'pinia' |
|
||||
const store = useStore() |
|
||||
const handleSearch = () => store.SET_SHOW_SEARCH(true) |
|
||||
const { theme } = storeToRefs(store) |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
@media (max-aspect-ratio: 1/1) { |
|
||||
.row { |
|
||||
position: fixed; |
|
||||
top: 260px; |
|
||||
left: 68px; |
|
||||
right: 68px; |
|
||||
height: 100px; |
|
||||
display: flex; |
|
||||
z-index: 100; |
|
||||
} |
|
||||
} |
|
||||
.row { |
|
||||
.back { |
|
||||
width: 130px; |
|
||||
height: 100px; |
|
||||
margin-right: 40px; |
|
||||
background: center / cover no-repeat; |
|
||||
box-shadow: 0px 15px 24px rgba(0, 0, 0, 0.05); |
|
||||
border-radius: var(--searchBar-backBorderRadius); |
|
||||
} |
|
||||
.bar { |
|
||||
flex: 1; |
|
||||
height: 100px; |
|
||||
background: var(--searchBar-background); |
|
||||
border: var(--searchBar-border); |
|
||||
box-shadow: 0px 15px 24px rgba(0, 0, 0, 0.05); |
|
||||
border-radius: var(--searchBar-borderRadius); |
|
||||
display: flex; |
|
||||
padding-left: 40px; |
|
||||
align-items: center; |
|
||||
.icon { |
|
||||
width: 56px; |
|
||||
height: 56px; |
|
||||
background: center / cover no-repeat; |
|
||||
} |
|
||||
.stick { |
|
||||
width: 4px; |
|
||||
height: 38px; |
|
||||
background: var(--searchBar-stickBg); |
|
||||
margin: 0 32px; |
|
||||
} |
|
||||
.placeholder { |
|
||||
font-family: 'HarmonyOS Sans SC'; |
|
||||
font-style: normal; |
|
||||
font-weight: 700; |
|
||||
font-size: 20px; |
|
||||
line-height: 23px; |
|
||||
color: var(--searchBar-placeholderColor); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@media (min-aspect-ratio: 1/1) { |
|
||||
.row { |
|
||||
.back { |
|
||||
position: fixed; |
|
||||
left: 68px; |
|
||||
top: 161px; |
|
||||
z-index: 100; |
|
||||
} |
|
||||
.bar { |
|
||||
position: fixed; |
|
||||
width: 698px; |
|
||||
top: 38px; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
margin: auto; |
|
||||
z-index: 100; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,142 +0,0 @@ |
|||||
<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="theme.images[tab.moduleName]" /></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, theme } = 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:nth-child(5n + 1) { |
|
||||
&.active { |
|
||||
.icon { |
|
||||
background: var(--menu-activeBg1); |
|
||||
} |
|
||||
} |
|
||||
.icon { |
|
||||
background: var(--menu-bg1); |
|
||||
} |
|
||||
} |
|
||||
.item:nth-child(5n + 2) { |
|
||||
&.active { |
|
||||
.icon { |
|
||||
background: var(--menu-activeBg2); |
|
||||
} |
|
||||
} |
|
||||
.icon { |
|
||||
background: var(--menu-bg2); |
|
||||
} |
|
||||
} |
|
||||
.item:nth-child(5n + 3) { |
|
||||
&.active { |
|
||||
.icon { |
|
||||
background: var(--menu-activeBg3); |
|
||||
} |
|
||||
} |
|
||||
.icon { |
|
||||
background: var(--menu-bg3); |
|
||||
} |
|
||||
} |
|
||||
.item:nth-child(5n + 4) { |
|
||||
&.active { |
|
||||
.icon { |
|
||||
background: var(--menu-activeBg4); |
|
||||
} |
|
||||
} |
|
||||
.icon { |
|
||||
background: var(--menu-bg4); |
|
||||
} |
|
||||
} |
|
||||
.item:nth-child(5n + 5) { |
|
||||
&.active { |
|
||||
.icon { |
|
||||
background: var(--menu-activeBg5); |
|
||||
} |
|
||||
} |
|
||||
.icon { |
|
||||
background: var(--menu-bg5); |
|
||||
} |
|
||||
} |
|
||||
.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: var(--global-radius, 24px); |
|
||||
img { |
|
||||
width: 80px; |
|
||||
height: 80px; |
|
||||
} |
|
||||
} |
|
||||
.title { |
|
||||
font-weight: 700; |
|
||||
font-size: 18px; |
|
||||
line-height: 21px; |
|
||||
text-align: center; |
|
||||
color: var(--menu-color); |
|
||||
margin-top: 12px; |
|
||||
} |
|
||||
&.active { |
|
||||
.title { |
|
||||
color: var(--menu-activeColor); |
|
||||
} |
|
||||
&::after { |
|
||||
content: ''; |
|
||||
display: block; |
|
||||
position: absolute; |
|
||||
width: 124px; |
|
||||
height: 6px; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
bottom: 0; |
|
||||
margin: auto; |
|
||||
background: var(--menu-barBg); |
|
||||
border-radius: 2px 2px 0px 0px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.item + .item { |
|
||||
margin-left: 24px; |
|
||||
} |
|
||||
} |
|
||||
@media (min-aspect-ratio: 1/1) { |
|
||||
.tabs { |
|
||||
top: 156px; |
|
||||
left: 456px; |
|
||||
right: 456px; |
|
||||
.item { |
|
||||
height: 124px; |
|
||||
.icon { |
|
||||
height: 80px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,92 +0,0 @@ |
|||||
<template> |
|
||||
<div class="full-code"> |
|
||||
<div class="code-wrapper"> |
|
||||
<img :src="icon" class="img" alt="" v-if="icon.length" /> |
|
||||
<img src="../../assets/images/nodata.svg" class="img nodata" alt="" v-else /> |
|
||||
|
|
||||
<p class="youhui" v-if="icon.length">{{ title }}</p> |
|
||||
<slot /> |
|
||||
<div class="close" @click="handleClose"> |
|
||||
<img src="../../assets/images/detail/yellow_close.png" alt="" /> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
defineProps({ |
|
||||
title: { |
|
||||
type: String, |
|
||||
default: '扫码排队' |
|
||||
}, |
|
||||
icon: { |
|
||||
type: String, |
|
||||
default: '' |
|
||||
} |
|
||||
}) |
|
||||
const emits = defineEmits(['close']) |
|
||||
|
|
||||
function handleClose() { |
|
||||
emits('close') |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.full-code { |
|
||||
position: fixed; |
|
||||
top: 0; |
|
||||
right: 0; |
|
||||
bottom: 0; |
|
||||
left: 0; |
|
||||
z-index: 10; |
|
||||
animation-duration: 0.2s; |
|
||||
} |
|
||||
.code-wrapper { |
|
||||
position: absolute; |
|
||||
top: 50%; |
|
||||
left: 50%; |
|
||||
width: 480px; |
|
||||
min-height: 366px; |
|
||||
transform: translate3d(-50%, -50%, 0); |
|
||||
background: #ffffff; |
|
||||
box-shadow: 0 40px 60px rgba(0, 0, 0, 0.08); |
|
||||
border-radius: 12px; |
|
||||
padding-top: 80px; |
|
||||
z-index: 10; |
|
||||
.img { |
|
||||
display: block; |
|
||||
margin: 0 auto 49px; |
|
||||
width: 150px; |
|
||||
height: 150px; |
|
||||
&.nodata { |
|
||||
width: 300px; |
|
||||
height: 300px; |
|
||||
} |
|
||||
} |
|
||||
.youhui { |
|
||||
font-weight: 700; |
|
||||
font-family: 'font_bold'; |
|
||||
font-size: 20px; |
|
||||
line-height: 23px; |
|
||||
text-align: center; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
} |
|
||||
|
|
||||
.close { |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
position: absolute; |
|
||||
top: 12px; |
|
||||
right: 12px; |
|
||||
width: 56px; |
|
||||
height: 56px; |
|
||||
background: rgba(0, 0, 0, 0.02); |
|
||||
border-radius: 12px; |
|
||||
img { |
|
||||
width: 56px; |
|
||||
height: 56px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,125 +0,0 @@ |
|||||
<template> |
|
||||
<div class="question-content"> |
|
||||
<div class="masker" @click="closeQuestionClassify"></div> |
|
||||
<div class="question-detail"> |
|
||||
<h1 class="title">商场相关常见问题</h1> |
|
||||
<h1 class="sub">全部分类</h1> |
|
||||
<ScrollView class="question-scroll" scrollbar> |
|
||||
<div class="scroll"> |
|
||||
<QuestionList /> |
|
||||
</div> |
|
||||
</ScrollView> |
|
||||
<div class="close" @click="closeQuestionClassify"> |
|
||||
<img src="../../assets/images/detail/yellow_close.png" alt="" /> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|
||||
import QuestionList from '@/components/QuestionList/QuestionList.vue' |
|
||||
|
|
||||
const emits = defineEmits(['close']) |
|
||||
|
|
||||
function closeQuestionClassify() { |
|
||||
emits('close') |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.question-content { |
|
||||
position: fixed; |
|
||||
top: 0; |
|
||||
right: 0; |
|
||||
bottom: 0; |
|
||||
left: 0; |
|
||||
z-index: 999; |
|
||||
animation-duration: 0.2s; |
|
||||
} |
|
||||
.masker { |
|
||||
position: fixed; |
|
||||
top: 0; |
|
||||
right: 0; |
|
||||
bottom: 0; |
|
||||
left: 0; |
|
||||
} |
|
||||
|
|
||||
.question-detail { |
|
||||
position: absolute; |
|
||||
width: 854px; |
|
||||
height: 964px; |
|
||||
background: #ffffff; |
|
||||
box-shadow: 0px 40px 60px rgba(0, 0, 0, 0.08); |
|
||||
border-radius: 16px; |
|
||||
top: 462px; |
|
||||
left: 50%; |
|
||||
margin-left: -427px; |
|
||||
.title { |
|
||||
font-weight: 700; |
|
||||
font-size: 32px; |
|
||||
font-family: 'font_bold'; |
|
||||
text-align: center; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
padding-bottom: 40px; |
|
||||
padding-top: 56px; |
|
||||
} |
|
||||
.sub { |
|
||||
text-align: center; |
|
||||
font-weight: 700; |
|
||||
font-size: 24px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
margin-bottom: 24px; |
|
||||
} |
|
||||
.question-scroll { |
|
||||
position: relative; |
|
||||
padding-right: 16px; |
|
||||
overflow: hidden; |
|
||||
height: 788px; |
|
||||
background: rgba(0, 0, 0, 0.02); |
|
||||
.scroll { |
|
||||
display: flex; |
|
||||
flex-wrap: wrap; |
|
||||
padding: 80px 80px 0 117px; |
|
||||
:deep(.question_item) { |
|
||||
margin-right: 16px; |
|
||||
margin-bottom: 40px; |
|
||||
} |
|
||||
} |
|
||||
:deep(.bscroll-vertical-scrollbar) { |
|
||||
width: 6px !important; |
|
||||
right: 95px !important; |
|
||||
top: 80px !important; |
|
||||
background: rgba(0, 0, 0, 0.02) !important; |
|
||||
border-radius: 6px !important; |
|
||||
opacity: 1 !important; |
|
||||
height: 152px !important; |
|
||||
|
|
||||
.bscroll-indicator { |
|
||||
height: 95px !important; |
|
||||
width: 6px !important; |
|
||||
background: rgba(0, 0, 0, 0.1) !important; |
|
||||
border-radius: 6px !important; |
|
||||
border: none !important; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.close { |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
position: absolute; |
|
||||
top: 12px; |
|
||||
right: 12px; |
|
||||
width: 56px; |
|
||||
height: 56px; |
|
||||
background: rgba(0, 0, 0, 0.02); |
|
||||
border-radius: 12px; |
|
||||
img { |
|
||||
width: 56px; |
|
||||
height: 56px; |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,193 +0,0 @@ |
|||||
<template> |
|
||||
<div class="question_item" @click="handleQuestion"> |
|
||||
<h1 class="prefix_title">停车相关</h1> |
|
||||
<h1 class="prefix_sub">如:停车如何收费</h1> |
|
||||
<p class="prefix_detail">MORE</p> |
|
||||
</div> |
|
||||
|
|
||||
<Teleport to="body"> |
|
||||
<Transition enter-active-class="animate__animated animate__fadeInDown" leave-active-class="animate__animated animate__fadeOutUp"> |
|
||||
<div class="question-content" v-if="showQuestion"> |
|
||||
<div class="masker" @click="closeQuestionDetail"></div> |
|
||||
<div class="question-detail"> |
|
||||
<h1 class="title">商场相关常见问题</h1> |
|
||||
<h1 class="sub">停车相关</h1> |
|
||||
<ScrollView class="question-scroll" scrollbar> |
|
||||
<div class="questions"> |
|
||||
<div class="question" v-for="item of 10" :key="item"> |
|
||||
<div class="ask">问:停车如何收费?</div> |
|
||||
<div class="answer"> |
|
||||
答:迪奥小姐仿佛一曲爱之赞歌,承袭Christian |
|
||||
Dior迪奥先生心中的玫瑰挚恋及DIOR迪奥的高订格调,曼妙香韵,尽现摩登时尚、自由洒脱、优雅从容的风格。迪奥小姐玫舞轻旋淡香水,活力花香调。 |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</ScrollView> |
|
||||
<div class="close" @click="closeQuestionDetail"> |
|
||||
<img src="../../assets/images/detail/yellow_close.png" alt="" /> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</Transition> |
|
||||
</Teleport> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { ref } from 'vue' |
|
||||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|
||||
|
|
||||
defineProps({ |
|
||||
list: { |
|
||||
type: Array, |
|
||||
default: () => [] |
|
||||
} |
|
||||
}) |
|
||||
|
|
||||
const showQuestion = ref(false) |
|
||||
function handleQuestion() { |
|
||||
showQuestion.value = true |
|
||||
} |
|
||||
function closeQuestionDetail() { |
|
||||
showQuestion.value = false |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.question_item { |
|
||||
width: 175px; |
|
||||
height: 225px; |
|
||||
background: #ffffff; |
|
||||
box-shadow: 0px 20px 40px rgba(31, 46, 84, 0.04); |
|
||||
border-radius: 12px; |
|
||||
.prefix_title { |
|
||||
font-weight: 700; |
|
||||
font-size: 20px; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
font-family: 'font_bold'; |
|
||||
padding: 32px 20px 15px 32px; |
|
||||
@include no-wrap; |
|
||||
} |
|
||||
.prefix_sub { |
|
||||
font-size: 14px; |
|
||||
padding: 0 20px 75px 32px; |
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05); |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
@include no-wrap; |
|
||||
} |
|
||||
.prefix_detail { |
|
||||
padding-top: 23px; |
|
||||
font-family: 'font_bold'; |
|
||||
padding-left: 32px; |
|
||||
font-weight: 700; |
|
||||
font-size: 16px; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.question-content { |
|
||||
position: fixed; |
|
||||
top: 0; |
|
||||
right: 0; |
|
||||
bottom: 0; |
|
||||
left: 0; |
|
||||
z-index: 999; |
|
||||
animation-duration: 0.2s; |
|
||||
} |
|
||||
.masker { |
|
||||
position: fixed; |
|
||||
top: 0; |
|
||||
right: 0; |
|
||||
bottom: 0; |
|
||||
left: 0; |
|
||||
} |
|
||||
|
|
||||
.question-detail { |
|
||||
position: absolute; |
|
||||
width: 854px; |
|
||||
height: 964px; |
|
||||
background: #ffffff; |
|
||||
box-shadow: 0px 40px 60px rgba(0, 0, 0, 0.08); |
|
||||
border-radius: 16px; |
|
||||
top: 462px; |
|
||||
left: 50%; |
|
||||
margin-left: -427px; |
|
||||
.title { |
|
||||
font-weight: 700; |
|
||||
font-size: 32px; |
|
||||
font-family: 'font_bold'; |
|
||||
text-align: center; |
|
||||
color: rgba(0, 0, 0, 0.8); |
|
||||
padding-bottom: 40px; |
|
||||
padding-top: 56px; |
|
||||
} |
|
||||
.sub { |
|
||||
text-align: center; |
|
||||
font-weight: 700; |
|
||||
font-size: 24px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
margin-bottom: 24px; |
|
||||
} |
|
||||
.question-scroll { |
|
||||
position: relative; |
|
||||
margin-left: 56px; |
|
||||
margin-right: 34px; |
|
||||
padding-right: 16px; |
|
||||
overflow: hidden; |
|
||||
height: 788px; |
|
||||
:deep(.bscroll-vertical-scrollbar) { |
|
||||
width: 6px !important; |
|
||||
background: rgba(0, 0, 0, 0.02) !important; |
|
||||
border-radius: 6px !important; |
|
||||
opacity: 1 !important; |
|
||||
height: 152px !important; |
|
||||
|
|
||||
.bscroll-indicator { |
|
||||
height: 95px !important; |
|
||||
width: 6px !important; |
|
||||
background: rgba(0, 0, 0, 0.1) !important; |
|
||||
border-radius: 6px !important; |
|
||||
border: none !important; |
|
||||
} |
|
||||
} |
|
||||
.questions { |
|
||||
padding-bottom: 24px; |
|
||||
} |
|
||||
.question { |
|
||||
margin-bottom: 24px; |
|
||||
padding: 40px; |
|
||||
background: rgba(0, 0, 0, 0.02); |
|
||||
border-radius: 12px; |
|
||||
} |
|
||||
.ask { |
|
||||
font-weight: 700; |
|
||||
font-size: 18px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
margin-bottom: 16px; |
|
||||
} |
|
||||
.answer { |
|
||||
font-size: 16px; |
|
||||
line-height: 200%; |
|
||||
text-align: justify; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.close { |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
position: absolute; |
|
||||
top: 12px; |
|
||||
right: 12px; |
|
||||
width: 56px; |
|
||||
height: 56px; |
|
||||
background: rgba(0, 0, 0, 0.02); |
|
||||
border-radius: 12px; |
|
||||
img { |
|
||||
width: 56px; |
|
||||
height: 56px; |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,396 +0,0 @@ |
|||||
<template> |
|
||||
<Dialog @close="close"> |
|
||||
<div class="bar"> |
|
||||
<div class="icon" :style="{ backgroundImage: `url(${theme.images.searchIcon})` }"></div> |
|
||||
<div class="stick"></div> |
|
||||
<div v-if="!keywords" class="placeholder">请输入中英文<span class="meta">首字母</span>查询,例如 XBK (星巴克)</div> |
|
||||
<input v-else @click="setSearch" v-model="keywords" type="text" readonly class="input" /> |
|
||||
<img :src="theme.images.searchClear" class="clear" v-if="keywords" @click="clear" /> |
|
||||
</div> |
|
||||
<div class="search-content"> |
|
||||
<div class="top" v-if="!showVoice"> |
|
||||
<div class="facs"> |
|
||||
<h1 class="title">公共设施</h1> |
|
||||
<div class="facility-list"> |
|
||||
<FacilityItem @click="_handleFacility(item)" class="margin" :facility="item" v-for="item of facilityList" :key="item.title" /> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="keyboard-wrapper"> |
|
||||
<div class="tabs tabs-wrapper"> |
|
||||
<div class="tab" :class="{ active: tabIdx === index }" @click="handleTab(index)" v-for="(item, index) of list" :key="item.name"> |
|
||||
<img :src="tabIdx === index ? item.iconActive : item.icon" alt="" /> |
|
||||
{{ item.name }} |
|
||||
</div> |
|
||||
</div> |
|
||||
<KeyboardByLetter @del="del" @handle-letter="handleLetter" v-if="tabIdx === 0" /> |
|
||||
<KeyboardByWritten @del="del" @handle-word="handleLetter" v-else /> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="recs" v-show="!keywords.length && !showVoice"> |
|
||||
<h1 class="title">大家都在找</h1> |
|
||||
<div class="hot-scroll"> |
|
||||
<div class="item" v-for="(item, i) of hotRecommend" :key="item.shopId" @click="handleShop(item)"> |
|
||||
<div class="text">{{ item.shopName }}</div> |
|
||||
<img class="medal" v-if="i === 0" src="@/views/Index/fir.svg" /> |
|
||||
<img class="medal" v-if="i === 1" src="@/views/Index/sec.svg" /> |
|
||||
<img class="medal" v-if="i === 2" src="@/views/Index/thi.svg" /> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<SearchResultList @handle-shop="handleShop" :list="searchShopListRef" :config="config" v-if="keywords.length && !showVoice" /> |
|
||||
|
|
||||
<Voice @handle-question="showClassify = true" v-if="showVoice" /> |
|
||||
</div> |
|
||||
<img :src="theme.images.searchClose" class="search-btn" @click="close" /> |
|
||||
</Dialog> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { computed, defineAsyncComponent, ref, onBeforeUnmount } from 'vue' |
|
||||
import { useRouter } from 'vue-router' |
|
||||
import { storeToRefs } from 'pinia' |
|
||||
import { useStore } from '@/store/root' |
|
||||
|
|
||||
import { useSearchShop } from '@/composables/useSearchShop' |
|
||||
import { useFacilityNav } from '@/composables/useFacilityNav' |
|
||||
import { useStatistics } from '@/composables/useStatistics' |
|
||||
import Dialog from '@/layouts/Dialog.vue' |
|
||||
import FacilityItem from '@/base/FacilityItem/FacilityItem.vue' |
|
||||
import SearchResultList from '@/components/SearchResultList/SearchResultList.vue' |
|
||||
|
|
||||
const KeyboardByLetter = defineAsyncComponent(() => import('@/components/KeyboardByLetter/KeyboardByLetter.vue')) |
|
||||
const KeyboardByWritten = defineAsyncComponent(() => import('@/components/KeyboardByWritten/KeyboardByWritten.vue')) |
|
||||
const Voice = defineAsyncComponent(() => import('@/components/Voice/Voice.vue')) |
|
||||
|
|
||||
const MAX_LENGTH = 7 |
|
||||
|
|
||||
const { _handleFacility } = useFacilityNav() |
|
||||
|
|
||||
const router = useRouter() |
|
||||
|
|
||||
const store = useStore() |
|
||||
const { indexList, shopList, facilityList, config, showVoice, theme } = storeToRefs(store) |
|
||||
|
|
||||
const list = computed(() => |
|
||||
theme.value |
|
||||
? [ |
|
||||
{ |
|
||||
name: '键盘输入', |
|
||||
nameEn: 'keyboard input', |
|
||||
icon: theme.value.images.keyboard, |
|
||||
iconActive: theme.value.images.keyboard_active |
|
||||
}, |
|
||||
{ |
|
||||
name: '手写输入', |
|
||||
nameEn: 'handwriting input', |
|
||||
icon: theme.value.images.write, |
|
||||
iconActive: theme.value.images.write_active |
|
||||
} |
|
||||
] |
|
||||
: [] |
|
||||
) |
|
||||
|
|
||||
const hotRecommend = computed(() => indexList.value.hotSearch ?? []) |
|
||||
const showClassify = ref(false) |
|
||||
|
|
||||
async function handleShop(item) { |
|
||||
useStatistics('brandSearch') |
|
||||
const shop = shopList.value.find(_shop => _shop.shopId === item.shopId) |
|
||||
store.SET_SHOP(shop) |
|
||||
if (router.currentRoute.value.fullPath !== '/guide') { |
|
||||
store.SET_SELECTED_MODULE('Guide') |
|
||||
await router.push('/guide') |
|
||||
} |
|
||||
store.SET_SHOW_SEARCH(false) |
|
||||
} |
|
||||
|
|
||||
const tabIdx = ref(0) |
|
||||
function handleTab(index) { |
|
||||
tabIdx.value = index |
|
||||
} |
|
||||
|
|
||||
const keywords = ref('') |
|
||||
const searchType = ref(0) //0: 键盘 1: 手写 |
|
||||
const { searchShopListRef } = useSearchShop(keywords, searchType) |
|
||||
function handleLetter(item) { |
|
||||
if (keywords.value.length >= MAX_LENGTH) return |
|
||||
keywords.value += item |
|
||||
} |
|
||||
function del() { |
|
||||
keywords.value = keywords.value.substring(0, keywords.value.length - 1) |
|
||||
} |
|
||||
const clear = () => { |
|
||||
keywords.value = '' |
|
||||
} |
|
||||
|
|
||||
function setSearch() { |
|
||||
showVoice.value && store.SET_SHOW_VOICE(false) |
|
||||
} |
|
||||
|
|
||||
function close() { |
|
||||
store.SET_SHOW_SEARCH(false) |
|
||||
} |
|
||||
|
|
||||
onBeforeUnmount(() => { |
|
||||
showVoice.value && store.SET_SHOW_VOICE(false) |
|
||||
}) |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
:deep(.header-left) { |
|
||||
padding-left: 80px; |
|
||||
} |
|
||||
:deep(.view-container) { |
|
||||
position: relative; |
|
||||
z-index: 50; |
|
||||
} |
|
||||
.bar { |
|
||||
position: fixed; |
|
||||
top: 260px; |
|
||||
left: 68px; |
|
||||
right: 68px; |
|
||||
background: var(--search-barBackground); |
|
||||
border: var(--searchBar-border); |
|
||||
box-shadow: 0px 15px 24px rgba(0, 0, 0, 0.05); |
|
||||
border-radius: var(--searchBar-borderRadius); |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
padding-right: 10px; |
|
||||
padding-left: 40px; |
|
||||
height: 100px; |
|
||||
z-index: 52; |
|
||||
.icon { |
|
||||
width: 56px; |
|
||||
height: 56px; |
|
||||
background: center / cover no-repeat; |
|
||||
} |
|
||||
.stick { |
|
||||
width: 4px; |
|
||||
height: 38px; |
|
||||
background: var(--searchBar-stickBg); |
|
||||
margin: 0 32px; |
|
||||
} |
|
||||
.placeholder { |
|
||||
font-weight: 700; |
|
||||
font-size: 20px; |
|
||||
line-height: 23px; |
|
||||
color: var(--searchBar-placeholderColor); |
|
||||
.meta { |
|
||||
color: var(--search-placeholderMetaColor); |
|
||||
} |
|
||||
} |
|
||||
.input { |
|
||||
flex: 1; |
|
||||
border: none; |
|
||||
outline: none; |
|
||||
width: 262px; |
|
||||
background: transparent; |
|
||||
font-weight: 700; |
|
||||
font-size: 48px; |
|
||||
line-height: 59px; |
|
||||
color: var(--searchBar-color); |
|
||||
} |
|
||||
.clear { |
|
||||
display: flex; |
|
||||
width: 80px; |
|
||||
height: 80px; |
|
||||
} |
|
||||
.voice-icon { |
|
||||
width: 190px; |
|
||||
} |
|
||||
} |
|
||||
.search-content { |
|
||||
position: absolute; |
|
||||
top: 315px; |
|
||||
right: 40px; |
|
||||
bottom: 302px; |
|
||||
left: 40px; |
|
||||
background: var(--search-background); |
|
||||
backdrop-filter: blur(10px); |
|
||||
border-radius: var(--searchBar-borderRadius); |
|
||||
z-index: 2; |
|
||||
overflow: hidden; |
|
||||
|
|
||||
.top { |
|
||||
height: 460px; |
|
||||
background: var(--search-topBg, rgba(255, 255, 255, 0.6)); |
|
||||
border-radius: var(--searchBar-borderRadius); |
|
||||
margin: 10px 10px 48px 10px; |
|
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
padding-left: 46px; |
|
||||
overflow: hidden; |
|
||||
.facs { |
|
||||
.title { |
|
||||
font-weight: 900; |
|
||||
font-size: 24px; |
|
||||
line-height: 28px; |
|
||||
color: var(--search-facTitleColor); |
|
||||
} |
|
||||
width: 300px; |
|
||||
padding-top: 111px; |
|
||||
.facility-list { |
|
||||
display: grid; |
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr; |
|
||||
width: 264px; |
|
||||
margin-top: 40px; |
|
||||
gap: 12px 24px; |
|
||||
} |
|
||||
} |
|
||||
.tabs-wrapper { |
|
||||
display: flex; |
|
||||
width: 100%; |
|
||||
height: 64px; |
|
||||
background: var(--search-tabsBg, rgba(0, 0, 0, 0.05)); |
|
||||
border-radius: var(--global-radius, 12px); |
|
||||
overflow: hidden; |
|
||||
|
|
||||
.tab { |
|
||||
height: 100%; |
|
||||
flex: 1; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: center; |
|
||||
color: var(--search-tabColor, rgba(0, 0, 0, 0.6)); |
|
||||
border-radius: var(--global-radius, 12px); |
|
||||
&.active { |
|
||||
background: var(--search-tabActiveBg, #ffffff); |
|
||||
color: var(--search-tabActiveColor, rgba(0, 0, 0, 0.8)); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
img { |
|
||||
width: 24px; |
|
||||
height: 24px; |
|
||||
margin-right: 12px; |
|
||||
} |
|
||||
} |
|
||||
.keyboard-wrapper { |
|
||||
flex: 1; |
|
||||
padding-top: 75px; |
|
||||
padding-left: 36px; |
|
||||
background: rgba(0, 0, 0, 0.05); |
|
||||
padding-right: 38px; |
|
||||
.tabs { |
|
||||
padding-right: 8px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.recs { |
|
||||
padding-left: 56px; |
|
||||
.title { |
|
||||
color: var(--search-hotSearchTitleColor); |
|
||||
} |
|
||||
.hot-scroll { |
|
||||
padding-top: 16px; |
|
||||
white-space: nowrap; |
|
||||
width: 944px; |
|
||||
|
|
||||
.item { |
|
||||
position: relative; |
|
||||
display: inline-block; |
|
||||
max-width: 170px; |
|
||||
height: 52px; |
|
||||
background: var(--search-hotSearchBg); |
|
||||
border-radius: var(--global-radius, 100px); |
|
||||
.text { |
|
||||
text-align: center; |
|
||||
font-weight: 900; |
|
||||
font-size: 16px; |
|
||||
line-height: 52px; |
|
||||
color: var(--search-hotSearchColor); |
|
||||
overflow: hidden; |
|
||||
white-space: nowrap; |
|
||||
text-overflow: ellipsis; |
|
||||
padding: 0 32px; |
|
||||
} |
|
||||
.medal { |
|
||||
position: absolute; |
|
||||
width: 32px; |
|
||||
height: 32px; |
|
||||
left: 4px; |
|
||||
top: -10px; |
|
||||
} |
|
||||
} |
|
||||
.item + .item { |
|
||||
margin-left: 24px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.search-right { |
|
||||
position: relative; |
|
||||
background: rgba(255, 255, 255, 0.6); |
|
||||
padding-top: 180px; |
|
||||
padding-left: 64px; |
|
||||
width: 696px; |
|
||||
|
|
||||
.title, |
|
||||
.title-en { |
|
||||
margin-right: 76px; |
|
||||
} |
|
||||
} |
|
||||
.search-btn { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: center; |
|
||||
position: fixed; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
margin: auto; |
|
||||
bottom: 242px; |
|
||||
width: 120px; |
|
||||
height: 120px; |
|
||||
z-index: 52; |
|
||||
} |
|
||||
@media (min-aspect-ratio: 1/1) { |
|
||||
.search-content { |
|
||||
top: 87px; |
|
||||
right: 125px; |
|
||||
bottom: 87px; |
|
||||
left: 125px; |
|
||||
padding: 100px 670px 0 0; |
|
||||
.top { |
|
||||
position: absolute; |
|
||||
top: 10px; |
|
||||
right: 10px; |
|
||||
bottom: 10px; |
|
||||
width: 660px; |
|
||||
height: auto; |
|
||||
margin: 0; |
|
||||
padding-left: 0; |
|
||||
flex-direction: column; |
|
||||
.facs { |
|
||||
width: auto; |
|
||||
flex: 1; |
|
||||
padding-top: 90px; |
|
||||
padding: 90px 54px; |
|
||||
.facility-list { |
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr; |
|
||||
} |
|
||||
} |
|
||||
.keyboard-wrapper { |
|
||||
flex: 0 0 456px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.bar { |
|
||||
top: 32px; |
|
||||
width: 698px; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
margin: auto; |
|
||||
} |
|
||||
.search-btn { |
|
||||
left: auto; |
|
||||
bottom: auto; |
|
||||
right: 145px; |
|
||||
top: 107px; |
|
||||
width: 87px; |
|
||||
height: 87px; |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
|
Before Width: | Height: | Size: 760 B |
|
Before Width: | Height: | Size: 5.2 KiB |
@ -1,40 +0,0 @@ |
|||||
export const letter = [ |
|
||||
1, |
|
||||
2, |
|
||||
3, |
|
||||
4, |
|
||||
5, |
|
||||
6, |
|
||||
7, |
|
||||
8, |
|
||||
9, |
|
||||
0, |
|
||||
'Q', |
|
||||
'W', |
|
||||
'E', |
|
||||
'R', |
|
||||
'T', |
|
||||
'Y', |
|
||||
'U', |
|
||||
'I', |
|
||||
'O', |
|
||||
'P', |
|
||||
'A', |
|
||||
'S', |
|
||||
'D', |
|
||||
'F', |
|
||||
'G', |
|
||||
'H', |
|
||||
'J', |
|
||||
'K', |
|
||||
'L', |
|
||||
'Z', |
|
||||
'X', |
|
||||
'C', |
|
||||
'V', |
|
||||
'B', |
|
||||
'N', |
|
||||
'M', |
|
||||
'空格', |
|
||||
'del' |
|
||||
] |
|
||||
@ -1,84 +0,0 @@ |
|||||
<template> |
|
||||
<div class="item" @click="handleShop"> |
|
||||
<div class="icon-wrapper"> |
|
||||
<img :src="config.sourceUrl + shop.logoUrl" class="icon" alt="" /> |
|
||||
</div> |
|
||||
<div class="item-bottom"> |
|
||||
<div class="left">{{ switchLanguage(shop, 'shopName') }}</div> |
|
||||
|
|
||||
<div class="right">{{ shop.floor }}</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
const props = defineProps({ |
|
||||
shop: { |
|
||||
type: Object, |
|
||||
default: () => ({}) |
|
||||
}, |
|
||||
config: { |
|
||||
type: Object, |
|
||||
default: () => ({}) |
|
||||
} |
|
||||
}) |
|
||||
|
|
||||
const emits = defineEmits(['click']) |
|
||||
function handleShop() { |
|
||||
emits('click', props.shop) |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.item { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
align-items: center; |
|
||||
width: 210px; |
|
||||
height: 200px; |
|
||||
background: var(--brand-background); |
|
||||
border-radius: var(--global-radius, 8px); |
|
||||
margin-right: 8px; |
|
||||
margin-top: 24px; |
|
||||
.icon-wrapper { |
|
||||
display: flex; |
|
||||
width: 210px; |
|
||||
height: 160px; |
|
||||
background: #ffffff; |
|
||||
border-radius: var(--global-radius, 8px); |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
.icon { |
|
||||
width: 120px; |
|
||||
height: 120px; |
|
||||
object-fit: contain; |
|
||||
} |
|
||||
} |
|
||||
.item-bottom { |
|
||||
display: flex; |
|
||||
width: 100%; |
|
||||
flex: 1; |
|
||||
padding: 0 12px; |
|
||||
align-items: center; |
|
||||
|
|
||||
.left, |
|
||||
.right { |
|
||||
font-weight: 700; |
|
||||
font-size: 14px; |
|
||||
line-height: 16px; |
|
||||
} |
|
||||
.left { |
|
||||
flex: 1; |
|
||||
white-space: nowrap; |
|
||||
overflow: hidden; |
|
||||
text-overflow: ellipsis; |
|
||||
color: var(--brand-color); |
|
||||
} |
|
||||
.right { |
|
||||
width: 40px; |
|
||||
text-align: right; |
|
||||
color: var(--brand-metaColor); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,140 +0,0 @@ |
|||||
<template> |
|
||||
<ScrollView :list="list" class="search-result-scroll" :scrollbar="true"> |
|
||||
<div class="scroll-result"> |
|
||||
<h1 class="title"> |
|
||||
搜索结果 <span class="meta">/ {{ list.length }}</span> |
|
||||
</h1> |
|
||||
<TransitionGroup name="zoom" tag="div" class="list"> |
|
||||
<SearchResultItem :config="config" @click="handleShop" :shop="item" v-for="item of list" :key="item.shopId" /> |
|
||||
</TransitionGroup> |
|
||||
</div> |
|
||||
</ScrollView> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|
||||
import SearchResultItem from '@/components/SearchResultItem/SearchResultItem.vue' |
|
||||
defineProps({ |
|
||||
list: { |
|
||||
type: Array, |
|
||||
default: () => [] |
|
||||
}, |
|
||||
config: { |
|
||||
type: Object, |
|
||||
default: () => ({}) |
|
||||
} |
|
||||
}) |
|
||||
const emits = defineEmits(['handle-shop']) |
|
||||
|
|
||||
function handleShop(item) { |
|
||||
emits('handle-shop', item) |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.search-result-scroll { |
|
||||
position: relative; |
|
||||
height: 842px; |
|
||||
overflow: hidden; |
|
||||
margin-left: 68px; |
|
||||
margin-right: 7px; |
|
||||
.scroll-result { |
|
||||
padding-bottom: 200px; |
|
||||
} |
|
||||
|
|
||||
.list { |
|
||||
display: flex; |
|
||||
flex-wrap: wrap; |
|
||||
margin-bottom: 44px; |
|
||||
} |
|
||||
.activity { |
|
||||
display: flex; |
|
||||
flex-wrap: wrap; |
|
||||
.flex { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
justify-content: space-between; |
|
||||
} |
|
||||
.pl-24 { |
|
||||
padding-left: 24px; |
|
||||
} |
|
||||
.activity-item { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
padding: 0 8px; |
|
||||
|
|
||||
width: 457px; |
|
||||
height: 84px; |
|
||||
background: rgba(255, 255, 255, 0.8); |
|
||||
border-radius: 12px; |
|
||||
margin-right: 6px; |
|
||||
margin-bottom: 8px; |
|
||||
.activity-name { |
|
||||
font-weight: 700; |
|
||||
font-size: 18px; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
font-family: 'font_bold'; |
|
||||
padding-bottom: 16px; |
|
||||
} |
|
||||
.intro { |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
font-size: 14px; |
|
||||
} |
|
||||
.img-wrapper { |
|
||||
width: 120px; |
|
||||
height: 68px; |
|
||||
margin-right: 24px; |
|
||||
border-radius: 8px; |
|
||||
|
|
||||
.img { |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
border-radius: 8px; |
|
||||
object-fit: cover; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.title { |
|
||||
font-style: normal; |
|
||||
font-weight: 900; |
|
||||
font-size: 24px; |
|
||||
line-height: 28px; |
|
||||
color: var(--search-resultTitleColor, rgba(0, 0, 0, 0.8)); |
|
||||
.meta { |
|
||||
font-weight: 500; |
|
||||
font-size: 20px; |
|
||||
line-height: 23px; |
|
||||
color: var(--search-resultMetaColor, rgba(0, 0, 0, 0.6)); |
|
||||
} |
|
||||
} |
|
||||
:deep(.bscroll-vertical-scrollbar) { |
|
||||
width: 48px !important; |
|
||||
background: center / 6px 250px no-repeat url(@/assets/images/scrollBar.png); |
|
||||
border-radius: 6px; |
|
||||
opacity: 1 !important; |
|
||||
height: 250px !important; |
|
||||
&::after { |
|
||||
position: absolute; |
|
||||
content: ''; |
|
||||
left: 0; |
|
||||
|
|
||||
top: 120px; |
|
||||
margin: auto; |
|
||||
width: 48px; |
|
||||
height: 61px; |
|
||||
background: center / cover no-repeat url(@/assets/images/scrollHand.png); |
|
||||
} |
|
||||
.bscroll-indicator { |
|
||||
height: 95px !important; |
|
||||
width: 6px !important; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
margin: auto; |
|
||||
background: #ffffff !important; |
|
||||
border-radius: 6px !important; |
|
||||
border: none !important; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,86 +0,0 @@ |
|||||
<template> |
|
||||
<ScrollView class="serve-scroll" :list="serveList"> |
|
||||
<TransitionGroup name="zoom" tag="div" class="serve-content"> |
|
||||
<div class="serve-item" v-for="item of serveList" :key="item.name"> |
|
||||
<div class="white-bg"> |
|
||||
<div class="icon-box"> |
|
||||
<img class="icon" :src="config.sourceUrl + item.fileUrl" alt="" /> |
|
||||
</div> |
|
||||
</div> |
|
||||
<p class="name">{{ item.name }}</p> |
|
||||
<p class="en">{{ item.nameEn }}</p> |
|
||||
</div> |
|
||||
</TransitionGroup> |
|
||||
</ScrollView> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { ref } from 'vue' |
|
||||
import { storeToRefs } from 'pinia' |
|
||||
import { useStore } from '@/store/root' |
|
||||
import { getServeList } from '@/http/api' |
|
||||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|
||||
|
|
||||
const store = useStore() |
|
||||
const { config } = storeToRefs(store) |
|
||||
|
|
||||
const serveList = ref([]) |
|
||||
getServeList().then(({ data }) => { |
|
||||
serveList.value = data?.serveList ?? [] |
|
||||
}) |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.serve-scroll { |
|
||||
position: relative; |
|
||||
overflow: hidden; |
|
||||
margin-left: 170px; |
|
||||
margin-right: 24px; |
|
||||
margin-top: 58px; |
|
||||
height: 1560px; |
|
||||
.serve-content { |
|
||||
display: flex; |
|
||||
flex-wrap: wrap; |
|
||||
.serve-item { |
|
||||
width: 279px; |
|
||||
height: 225px; |
|
||||
// TODO 需动态切换背景色 |
|
||||
background: #fcf8ec; |
|
||||
box-shadow: 0px 20px 40px rgba(31, 46, 84, 0.04); |
|
||||
border-radius: 12px; |
|
||||
margin-right: 16px; |
|
||||
margin-bottom: 29px; |
|
||||
.white-bg { |
|
||||
height: 147px; |
|
||||
background: #fff; |
|
||||
border-radius: 12px; |
|
||||
padding: 32px; |
|
||||
margin-bottom: 20px; |
|
||||
} |
|
||||
.icon-box { |
|
||||
width: 56px; |
|
||||
height: 56px; |
|
||||
.icon { |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
object-fit: contain; |
|
||||
} |
|
||||
} |
|
||||
.name { |
|
||||
font-weight: 700; |
|
||||
font-family: 'font_bold'; |
|
||||
font-size: 16px; |
|
||||
padding-left: 32px; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
padding-bottom: 6px; |
|
||||
} |
|
||||
.en { |
|
||||
font-weight: 400; |
|
||||
font-size: 12px; |
|
||||
padding-left: 32px; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,104 +0,0 @@ |
|||||
<template> |
|
||||
<div class="sidebar-wrapper"> |
|
||||
<div class="menu-list" @click="goPage(item)" :class="{ active: selectedModule === item.title }" v-for="item of sidebarList" :key="item.title"> |
|
||||
<img :src="item.icon" alt="" /> |
|
||||
<span class="text">{{ item.title }}</span> |
|
||||
<span class="text-en">{{ item.titleEn }}</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { storeToRefs } from 'pinia' |
|
||||
import { useStore } from '@/store/root' |
|
||||
import { useRouter } from 'vue-router' |
|
||||
|
|
||||
const router = useRouter() |
|
||||
const store = useStore() |
|
||||
const { sidebarList, selectedModule } = storeToRefs(store) |
|
||||
|
|
||||
function goPage(item) { |
|
||||
store.SET_SELECTED_MODULE(item.title) |
|
||||
router.push(item.path) |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.sidebar-wrapper { |
|
||||
position: fixed; |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
align-items: center; |
|
||||
width: 130px; |
|
||||
height: 1920px; |
|
||||
left: 0px; |
|
||||
top: 0; |
|
||||
background: var(--color-white-opacity-8); |
|
||||
box-shadow: var(--shadow-seven); |
|
||||
backdrop-filter: blur(20px); |
|
||||
z-index: 50; |
|
||||
|
|
||||
.menu-list { |
|
||||
position: relative; |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
width: 110px; |
|
||||
height: 140px; |
|
||||
margin-bottom: 10px; |
|
||||
|
|
||||
&::before, |
|
||||
&::after { |
|
||||
position: absolute; |
|
||||
content: ''; |
|
||||
width: 110px; |
|
||||
height: 140px; |
|
||||
left: 0; |
|
||||
bottom: 0; |
|
||||
border-radius: 8px; |
|
||||
transition: bottom 0.5s; |
|
||||
} |
|
||||
|
|
||||
&.active { |
|
||||
&::before { |
|
||||
background-color: #fff; |
|
||||
z-index: 3; |
|
||||
bottom: 4px; |
|
||||
} |
|
||||
|
|
||||
&::after { |
|
||||
background: var(--color-linear-lightgoldenyellow); |
|
||||
z-index: 2; |
|
||||
bottom: 0; |
|
||||
height: 136px; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
img { |
|
||||
position: relative; |
|
||||
width: 80px; |
|
||||
height: 80px; |
|
||||
z-index: 10; |
|
||||
} |
|
||||
|
|
||||
.text { |
|
||||
position: relative; |
|
||||
z-index: 10; |
|
||||
color: var(--color-black-opacity-6); |
|
||||
font-family: 'font_bold'; |
|
||||
font-weight: 700; |
|
||||
font-size: 14px; |
|
||||
padding: 4px 0; |
|
||||
} |
|
||||
|
|
||||
.text-en { |
|
||||
position: relative; |
|
||||
z-index: 10; |
|
||||
color: var(--color-black-opacity-4); |
|
||||
font-size: 12px; |
|
||||
transform: scale(0.83); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,72 +0,0 @@ |
|||||
export const sidebarList = [ |
|
||||
{ |
|
||||
icon: require('@/assets/images/sidebar/activity.png'), |
|
||||
title: '商场活动', |
|
||||
moduleName: 'activity', |
|
||||
titleEn: 'SELECTION', |
|
||||
path: '/activity' |
|
||||
}, |
|
||||
{ |
|
||||
icon: require('@/assets/images/sidebar/member.png'), |
|
||||
title: '尊享会员', |
|
||||
moduleName: 'member', |
|
||||
titleEn: 'MEMBER', |
|
||||
path: '/member' |
|
||||
}, |
|
||||
{ |
|
||||
icon: require('@/assets/images/sidebar/parking.png'), |
|
||||
title: '泊车缴费', |
|
||||
moduleName: 'parking', |
|
||||
titleEn: 'PARKING', |
|
||||
path: '/parking' |
|
||||
}, |
|
||||
{ |
|
||||
icon: require('@/assets/images/sidebar/movie.png'), |
|
||||
title: '影视天地', |
|
||||
moduleName: 'movie', |
|
||||
titleEn: 'MOVIE', |
|
||||
path: '/movie' |
|
||||
}, |
|
||||
{ |
|
||||
icon: require('@/assets/images/sidebar/mall.png'), |
|
||||
title: '商场介绍', |
|
||||
moduleName: 'mall', |
|
||||
titleEn: 'MALL', |
|
||||
path: '/mall' |
|
||||
} |
|
||||
// {
|
|
||||
// icon: require('@/assets/images/sidebar/index.png'),
|
|
||||
// title: '首页',
|
|
||||
// moduleName: 'home',
|
|
||||
// titleEn: 'HOME',
|
|
||||
// path: '/'
|
|
||||
// },
|
|
||||
// {
|
|
||||
// icon: require('@/assets/images/sidebar/guide.png'),
|
|
||||
// title: '地图导览',
|
|
||||
// moduleName: 'home',
|
|
||||
// titleEn: 'MAP',
|
|
||||
// path: '/guide'
|
|
||||
// },
|
|
||||
// {
|
|
||||
// icon: require('@/assets/images/sidebar/brand.png'),
|
|
||||
// title: '品牌列表',
|
|
||||
// moduleName: 'brand',
|
|
||||
// titleEn: 'BRAND',
|
|
||||
// path: '/brand'
|
|
||||
// }
|
|
||||
// {
|
|
||||
// icon: require('@/assets/images/sidebar/foods.png'),
|
|
||||
// title: '特色美食',
|
|
||||
// moduleName: 'food',
|
|
||||
// titleEn: 'FOOD',
|
|
||||
// path: '/foods'
|
|
||||
// },
|
|
||||
// {
|
|
||||
// icon: require('@/assets/images/sidebar/service.png'),
|
|
||||
// title: '商场服务',
|
|
||||
// titleEn: 'SERVICE',
|
|
||||
// moduleName: 'service',
|
|
||||
// path: '/service'
|
|
||||
// }
|
|
||||
] |
|
||||
@ -1,57 +0,0 @@ |
|||||
<template> |
|
||||
<div class="tabs-wrapper"> |
|
||||
<div class="tab" :class="{ active: tabIdx === index }" @click="handleTab(index)" v-for="(item, index) of list" :key="item.name"> |
|
||||
<img :src="tabIdx === index ? item.iconActive : item.icon" alt="" /> |
|
||||
{{ item.name }} |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { ref } from 'vue' |
|
||||
|
|
||||
defineProps({ |
|
||||
list: { |
|
||||
type: Array, |
|
||||
default: () => [] |
|
||||
} |
|
||||
}) |
|
||||
const emits = defineEmits(['click']) |
|
||||
|
|
||||
const tabIdx = ref(0) |
|
||||
function handleTab(index) { |
|
||||
tabIdx.value = index |
|
||||
emits('click', index) |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.tabs-wrapper { |
|
||||
display: flex; |
|
||||
width: 100%; |
|
||||
height: 64px; |
|
||||
background: var(--search-tabsBg, rgba(0, 0, 0, 0.05)); |
|
||||
border-radius: var(--global-radius, 12px); |
|
||||
overflow: hidden; |
|
||||
|
|
||||
.tab { |
|
||||
height: 100%; |
|
||||
flex: 1; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: center; |
|
||||
color: var(--search-tabColor, rgba(0, 0, 0, 0.6)); |
|
||||
border-radius: var(--global-radius, 12px); |
|
||||
&.active { |
|
||||
background: var(--search-tabActiveBg, #ffffff); |
|
||||
color: var(--search-tabActiveColor, rgba(0, 0, 0, 0.8)); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
img { |
|
||||
width: 24px; |
|
||||
height: 24px; |
|
||||
margin-right: 12px; |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,49 +0,0 @@ |
|||||
<template> |
|
||||
<div class="carousel"> |
|
||||
<EffectFade :list="list"> |
|
||||
<template v-slot="{ item }"> |
|
||||
<div class="banner-wrapper"> |
|
||||
<img :src="config.sourceUrl + item" alt="" class="banner" /> |
|
||||
</div> |
|
||||
</template> |
|
||||
</EffectFade> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { ref } from 'vue' |
|
||||
import { storeToRefs } from 'pinia' |
|
||||
import { useStore } from '@/store/root' |
|
||||
import { getTrafficList } from '@/http/api' |
|
||||
import EffectFade from '../EffectFade/EffectFade.vue' |
|
||||
|
|
||||
const store = useStore() |
|
||||
const { config } = storeToRefs(store) |
|
||||
|
|
||||
const list = ref([]) |
|
||||
getTrafficList().then(({ data }) => { |
|
||||
list.value = data?.fileList ?? [] |
|
||||
}) |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.carousel { |
|
||||
position: relative; |
|
||||
width: 870px; |
|
||||
height: 1300px; |
|
||||
margin-top: 58px; |
|
||||
margin-left: 170px; |
|
||||
margin-right: 40px; |
|
||||
} |
|
||||
.banner-wrapper { |
|
||||
width: 870px; |
|
||||
height: 1300px; |
|
||||
overflow: hidden; |
|
||||
} |
|
||||
.banner { |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
border-radius: 10px; |
|
||||
object-fit: cover; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,241 +0,0 @@ |
|||||
<template> |
|
||||
<div class="speech-wrapper" :class="{ active: !startSpeech }"> |
|
||||
<div class="lottie-box"> |
|
||||
<Lottie :isLocale="true" ref="lottieInstance" :path="lottie" v-show="startSpeech" /> |
|
||||
</div> |
|
||||
<div class="start-btn" @click="handleSpeech"> |
|
||||
<img src="../../assets/images/search/speech.png" alt="" /> |
|
||||
<span class="text">点我开始说话</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<ScrollView class="voice-scroll"> |
|
||||
<div class="voice-content"> |
|
||||
<h1 class="title">试着问我一下这些问题吧</h1> |
|
||||
<div class="commons"> |
|
||||
<div class="common-question"> |
|
||||
<img class="img" src="/static/img/xsj.png" alt="" /> |
|
||||
<div class="common-right"> |
|
||||
<h1 class="sub">卫生间</h1> |
|
||||
<h1 class="desc">附近卫生间怎么走?</h1> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<h1 class="title">您还可查看更多商场相关问题</h1> |
|
||||
<div class="groups"> |
|
||||
<div class="box-group" @click="showCustomerDialog = true"> |
|
||||
<img src="../../assets/images/search/customer.png" class="icon" alt="" /> |
|
||||
<p class="text">转人工服务</p> |
|
||||
</div> |
|
||||
<div class="box-group" @click="handleMoreQuestion"> |
|
||||
<img src="../../assets/images/search/question.png" class="icon" alt="" /> |
|
||||
<p class="text">常见问题</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="dialog flex"> |
|
||||
<div class="customer">我想开小票</div> |
|
||||
</div> |
|
||||
<div class="dialog"> |
|
||||
<p class="machine">您可以尝试换一种提问方式,导航到服务台,或是拨打400-888-8888,或转人工服务</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
</ScrollView> |
|
||||
<Teleport to="body"> |
|
||||
<Transition enter-active-class="animate__aniamted animate__zoomIn" leave-active-class="animate__aniamted animate__zoomOut"> |
|
||||
<Customer @close="showCustomerDialog = false" v-if="showCustomerDialog" /> |
|
||||
</Transition> |
|
||||
</Teleport> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { ref, nextTick, defineAsyncComponent } from 'vue' |
|
||||
import lottie from './voice.json' |
|
||||
import Lottie from '@/components/Lottie/Lottie.vue' |
|
||||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|
||||
const Customer = defineAsyncComponent(() => import('@/components/Customer/Customer.vue')) |
|
||||
|
|
||||
const startSpeech = ref(false) |
|
||||
const lottieInstance = ref(null) |
|
||||
function handleSpeech() { |
|
||||
startSpeech.value = !startSpeech.value |
|
||||
nextTick(() => { |
|
||||
if (!startSpeech.value) { |
|
||||
lottieInstance.value.lottieInstance.stop() |
|
||||
} else { |
|
||||
lottieInstance.value.lottieInstance.play() |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
const emits = defineEmits(['handle-question']) |
|
||||
function handleMoreQuestion() { |
|
||||
emits('handle-question') |
|
||||
} |
|
||||
|
|
||||
const showCustomerDialog = ref(false) |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.speech-wrapper { |
|
||||
position: absolute; |
|
||||
left: 16px; |
|
||||
right: 16px; |
|
||||
top: 416px; |
|
||||
height: 360px; |
|
||||
:deep(svg) { |
|
||||
height: 85px !important; |
|
||||
} |
|
||||
|
|
||||
.lottie-box { |
|
||||
position: relative; |
|
||||
height: 115px; |
|
||||
margin-top: -42px; |
|
||||
&::before, |
|
||||
&::after { |
|
||||
content: ''; |
|
||||
position: absolute; |
|
||||
width: 328px; |
|
||||
top: 42px; |
|
||||
height: 2px; |
|
||||
background: linear-gradient(90deg, #ffbd35 0%, #ffd260 100%); |
|
||||
} |
|
||||
&::before { |
|
||||
left: 0; |
|
||||
} |
|
||||
&::after { |
|
||||
right: 0; |
|
||||
} |
|
||||
} |
|
||||
:deep(svg) { |
|
||||
transform: scale(3.5) !important; |
|
||||
} |
|
||||
.start-btn { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
align-items: center; |
|
||||
position: absolute; |
|
||||
left: 50%; |
|
||||
top: 98px; |
|
||||
transform: translateX(-50%); |
|
||||
img { |
|
||||
width: 160px; |
|
||||
} |
|
||||
.text { |
|
||||
font-weight: 700; |
|
||||
font-size: 18px; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
font-family: 'font_bold'; |
|
||||
} |
|
||||
} |
|
||||
&.active { |
|
||||
&:before { |
|
||||
position: absolute; |
|
||||
content: ''; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
height: 2px; |
|
||||
background: linear-gradient(90deg, #ffbd35 0%, #ffd260 100%); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.voice-scroll { |
|
||||
position: fixed; |
|
||||
top: 802px; |
|
||||
left: 80px; |
|
||||
right: 58px; |
|
||||
bottom: 0; |
|
||||
.title { |
|
||||
font-weight: 700; |
|
||||
font-size: 24px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
padding-bottom: 24px; |
|
||||
} |
|
||||
.commons { |
|
||||
display: flex; |
|
||||
flex-wrap: wrap; |
|
||||
margin-bottom: 56px; |
|
||||
} |
|
||||
.common-question { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
width: 352px; |
|
||||
height: 72px; |
|
||||
background: rgba(255, 255, 255, 0.8); |
|
||||
border-radius: 12px; |
|
||||
padding: 14px 24px; |
|
||||
margin-right: 8px; |
|
||||
margin-bottom: 8px; |
|
||||
.img { |
|
||||
width: 44px; |
|
||||
height: 44px; |
|
||||
margin-right: 24px; |
|
||||
} |
|
||||
.sub { |
|
||||
font-weight: 700; |
|
||||
font-size: 14px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
padding-bottom: 6px; |
|
||||
} |
|
||||
.desc { |
|
||||
color: rgba(0, 0, 0, 0.4); |
|
||||
font-size: 12px; |
|
||||
} |
|
||||
} |
|
||||
.groups { |
|
||||
display: flex; |
|
||||
} |
|
||||
.box-group { |
|
||||
width: 196px; |
|
||||
height: 177px; |
|
||||
background: #ffffff; |
|
||||
box-shadow: 0px 20px 40px rgba(31, 46, 84, 0.04); |
|
||||
border-radius: 12px; |
|
||||
margin-right: 16px; |
|
||||
margin-bottom: 24px; |
|
||||
.icon { |
|
||||
display: inline-block; |
|
||||
margin: 32px 0 32px 32px; |
|
||||
width: 48px; |
|
||||
} |
|
||||
.text { |
|
||||
font-weight: 700; |
|
||||
font-size: 16px; |
|
||||
line-height: 19px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
padding-left: 32px; |
|
||||
padding-top: 23px; |
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.05); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.machine { |
|
||||
display: inline-block; |
|
||||
padding: 24px 40px; |
|
||||
background: rgba(0, 0, 0, 0.05); |
|
||||
border-radius: 0px 32px 32px 32px; |
|
||||
font-size: 18px; |
|
||||
line-height: 21px; |
|
||||
color: #605e74; |
|
||||
margin-bottom: 16px; |
|
||||
} |
|
||||
.flex { |
|
||||
display: flex; |
|
||||
flex-direction: row-reverse; |
|
||||
} |
|
||||
|
|
||||
.customer { |
|
||||
padding: 24px 40px; |
|
||||
background: #ffffff; |
|
||||
font-weight: 700; |
|
||||
font-size: 24px; |
|
||||
line-height: 28px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: rgba(0, 0, 0, 0.6); |
|
||||
border-radius: 32px 0px 32px 32px; |
|
||||
text-align: right; |
|
||||
margin-bottom: 24px; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,116 +0,0 @@ |
|||||
<template> |
|
||||
<ScrollView class="waterfall-scroll" :list="list" observe-image> |
|
||||
<TransitionGroup name="zoom" tag="div" class="waterfall-content-scroll"> |
|
||||
<div class="waterfall-item" v-for="item of list" @click="handleWaterfall(item)" :key="item.name"> |
|
||||
<img :src="config.sourceUrl + item.fileUrl" alt="" class="waterfall-img" /> |
|
||||
<div class="title-wrapper"> |
|
||||
<h6 class="waterfall-title">{{ switchLanguage(item, 'name') }}</h6> |
|
||||
<h5 class="sub" v-if="item?.shopId"> |
|
||||
<h6 class="waterfall-name">{{ switchLanguage(item, 'shopName') }}</h6> |
|
||||
<h6 class="house-num pb-32">{{ item.houseNumber }}</h6> |
|
||||
</h5> |
|
||||
</div> |
|
||||
</div> |
|
||||
</TransitionGroup> |
|
||||
</ScrollView> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { storeToRefs } from 'pinia' |
|
||||
import { useRouter } from 'vue-router' |
|
||||
import { useStore } from '@/store/root' |
|
||||
import ScrollView from '@/base/ScrollView/ScrollView.vue' |
|
||||
import Shop from '@/utils/Class/Shop' |
|
||||
|
|
||||
defineProps({ |
|
||||
list: { |
|
||||
type: Array, |
|
||||
default: () => [] |
|
||||
}, |
|
||||
config: { |
|
||||
type: Object, |
|
||||
default: () => ({}) |
|
||||
} |
|
||||
}) |
|
||||
|
|
||||
const router = useRouter() |
|
||||
const store = useStore() |
|
||||
const { shopList } = storeToRefs(store) |
|
||||
|
|
||||
function handleWaterfall(item) { |
|
||||
let shop |
|
||||
if (item?.shopId) { |
|
||||
shop = shopList.value.find(_shop => _shop.shopId === item.shopId) |
|
||||
if (shop) { |
|
||||
store.SET_SHOP(shop) |
|
||||
store.SET_SHOW_DETAIL(true) |
|
||||
} |
|
||||
} else { |
|
||||
const { name, floorOrder, floor, logoUrl, point } = item |
|
||||
shop = new Shop(name, floorOrder, floor, logoUrl, point) |
|
||||
if (shop) { |
|
||||
store.SET_SHOP(shop) |
|
||||
router.push('/nav') |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.waterfall-scroll { |
|
||||
position: absolute; |
|
||||
left: 88px; |
|
||||
right: 70px; |
|
||||
top: 272px; |
|
||||
bottom: 0; |
|
||||
overflow: hidden; |
|
||||
z-index: 10; |
|
||||
border-radius: 12px; |
|
||||
|
|
||||
.waterfall-content-scroll { |
|
||||
column-count: 2; |
|
||||
padding-bottom: 16px; |
|
||||
} |
|
||||
.waterfall-item { |
|
||||
break-inside: avoid; |
|
||||
height: auto; |
|
||||
width: 440px; |
|
||||
background-color: var(--color-white-opacity); |
|
||||
margin-right: 24px; |
|
||||
margin-bottom: 16px; |
|
||||
overflow: hidden; |
|
||||
border-radius: 12px; |
|
||||
.waterfall-img { |
|
||||
width: 440px; |
|
||||
margin-bottom: 32px; |
|
||||
} |
|
||||
.title-wrapper { |
|
||||
padding-left: 32px; |
|
||||
padding-right: 32px; |
|
||||
} |
|
||||
.waterfall-title { |
|
||||
font-weight: 700; |
|
||||
font-size: 20px; |
|
||||
font-family: 'font_bold'; |
|
||||
color: var(--color-black-opacity-8); |
|
||||
padding-bottom: 13px; |
|
||||
@include no-wrap; |
|
||||
} |
|
||||
.sub { |
|
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
} |
|
||||
.waterfall-name, |
|
||||
.house-num { |
|
||||
font-weight: 700; |
|
||||
font-family: 'font_bold'; |
|
||||
font-size: 16px; |
|
||||
line-height: 19px; |
|
||||
color: var(--color-black-opacity-4); |
|
||||
} |
|
||||
.pb-32 { |
|
||||
padding-bottom: 32px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,171 +0,0 @@ |
|||||
<template> |
|
||||
<canvas :style="{ backgroundColor: backgroundColor, borderRadius: borderRadius }" ref="inkCanvasRef" :width="width" :height="height" id="ink-canvas"></canvas> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { reactive, computed, onMounted, onBeforeUnmount, watch, ref } from 'vue' |
|
||||
import { getHandWriting } from '@/http/api' |
|
||||
|
|
||||
const props = defineProps({ |
|
||||
width: { |
|
||||
type: Number, |
|
||||
default: 800 |
|
||||
}, |
|
||||
height: { |
|
||||
type: Number, |
|
||||
default: 800 |
|
||||
}, |
|
||||
lang: { |
|
||||
type: String, |
|
||||
default: 'CN', |
|
||||
validator(value) { |
|
||||
return ['CN', 'EN'].includes(value) |
|
||||
} |
|
||||
}, |
|
||||
backgroundColor: { |
|
||||
type: String, |
|
||||
default: '#f2f2f2' |
|
||||
}, |
|
||||
borderRadius: { |
|
||||
type: String, |
|
||||
default: '10px' |
|
||||
}, |
|
||||
fillText: { |
|
||||
type: String, |
|
||||
default: '手写区域' |
|
||||
}, |
|
||||
fillFontSize: { |
|
||||
type: String, |
|
||||
default: '100px' |
|
||||
}, |
|
||||
strokeStyle: { |
|
||||
type: String, |
|
||||
default: '#000' |
|
||||
}, |
|
||||
fillStyle: { |
|
||||
type: String, |
|
||||
default: 'rgba(85, 73, 54, 0.1)' |
|
||||
} |
|
||||
}) |
|
||||
const emits = defineEmits(['result']) |
|
||||
|
|
||||
const state = reactive({ |
|
||||
handWrite: '', |
|
||||
isClick: false, |
|
||||
//轨迹X |
|
||||
clickX: [], |
|
||||
//轨迹Y |
|
||||
clickY: [], |
|
||||
//轨迹标志位,为1则是终点 |
|
||||
clickC: [], |
|
||||
X: 0, |
|
||||
Y: 0, |
|
||||
oldX: 0, |
|
||||
oldY: 0, |
|
||||
timer: 0, |
|
||||
list: [] |
|
||||
}) |
|
||||
|
|
||||
const inkCanvasRef = ref(null) |
|
||||
const ctxRef = computed(() => inkCanvasRef.value.getContext('2d')) |
|
||||
|
|
||||
function updateBound() { |
|
||||
const bound = inkCanvasRef.value.getBoundingClientRect() |
|
||||
state.X = bound.x |
|
||||
state.Y = bound.y |
|
||||
} |
|
||||
function down(ev) { |
|
||||
const cx = Math.floor(ev.clientX || ev.targetTouches[0].clientX) - state.X |
|
||||
|
|
||||
const cy = Math.floor(ev.clientY || ev.targetTouches[0].clientY) - state.Y |
|
||||
|
|
||||
clearTimeout(state.timer) |
|
||||
state.oldX = cx |
|
||||
state.oldY = cy |
|
||||
ctxRef.value.beginPath() |
|
||||
state.isClick = true |
|
||||
} |
|
||||
function move(ev) { |
|
||||
ev.preventDefault() |
|
||||
if (state.isClick) { |
|
||||
const cx = Math.floor(ev.clientX || ev.targetTouches[0].clientX) - state.X |
|
||||
const cy = Math.floor(ev.clientY || ev.targetTouches[0].clientY) - state.Y |
|
||||
|
|
||||
state.clickX.push(cx) |
|
||||
state.clickY.push(cy) |
|
||||
state.clickC.push(0) |
|
||||
//画图 |
|
||||
|
|
||||
ctxRef.value.lineWidth = 8 |
|
||||
ctxRef.value.lineCap = 'round' |
|
||||
ctxRef.value.moveTo(state.oldX, state.oldY) |
|
||||
ctxRef.value.lineTo(cx, cy) |
|
||||
ctxRef.value.stroke() |
|
||||
state.oldX = cx |
|
||||
state.oldY = cy |
|
||||
} |
|
||||
} |
|
||||
function mouseUp() { |
|
||||
if (state.isClick) { |
|
||||
state.isClick = false |
|
||||
state.timer = setTimeout(() => { |
|
||||
reload() |
|
||||
}, 1500) |
|
||||
//标记最后一点为终点 |
|
||||
state.clickC.pop() |
|
||||
state.clickC.push(1) |
|
||||
_getHandWriting() |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
function reload() { |
|
||||
if (!inkCanvasRef.value) { |
|
||||
return |
|
||||
} |
|
||||
state.clickX = [] |
|
||||
state.clickY = [] |
|
||||
state.clickC = [] |
|
||||
ctxRef.value.strokeStyle = props.strokeStyle |
|
||||
ctxRef.value.fillStyle = props.fillStyle |
|
||||
ctxRef.value.clearRect(0, 0, props.width, props.height) |
|
||||
ctxRef.value.font = `bold ${props.fillFontSize} Arial` |
|
||||
ctxRef.value.textAlign = 'center' |
|
||||
ctxRef.value.textBaseline = 'middle' |
|
||||
ctxRef.value.fillText(props.fillText, props.width / 2, props.height / 2, 1000) |
|
||||
} |
|
||||
function _getHandWriting() { |
|
||||
const params = { |
|
||||
lib: props.lang, |
|
||||
lpXis: state.clickX, |
|
||||
lpYis: state.clickY, |
|
||||
lpCis: state.clickC |
|
||||
} |
|
||||
getHandWriting(params) |
|
||||
.then(res => { |
|
||||
state.list = res |
|
||||
}) |
|
||||
.catch(err => { |
|
||||
console.log(err) |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
watch( |
|
||||
() => state.list, |
|
||||
newVal => { |
|
||||
emits('result', newVal) |
|
||||
} |
|
||||
) |
|
||||
|
|
||||
onMounted(() => { |
|
||||
updateBound() |
|
||||
reload() |
|
||||
inkCanvasRef.value.addEventListener('touchstart', down) |
|
||||
inkCanvasRef.value.addEventListener('touchmove', move) |
|
||||
inkCanvasRef.value.addEventListener('touchend', mouseUp) |
|
||||
}) |
|
||||
onBeforeUnmount(() => { |
|
||||
inkCanvasRef.value.removeEventListener('touchstart', down) |
|
||||
inkCanvasRef.value.removeEventListener('touchmove', move) |
|
||||
inkCanvasRef.value.removeEventListener('touchend', mouseUp) |
|
||||
}) |
|
||||
</script> |
|
||||