Browse Source

feat: 活动列表

潮流
jiannibang 4 years ago
parent
commit
f39d31d427
  1. 246
      src/components/ActivitiesList/ActivitiesList.vue
  2. 146
      src/layouts/View.vue
  3. 20
      src/views/Activities/Activities.vue
  4. 74
      src/views/Index/Index.vue

246
src/components/ActivitiesList/ActivitiesList.vue

@ -1,41 +1,35 @@
<template> <template>
<ScrollView class="scroll" :list="list">
<ScrollView class="scroll" :list="list" scrollbar>
<TransitionGroup name="zoom" tag="div" class="scroll-content"> <TransitionGroup name="zoom" tag="div" class="scroll-content">
<div class="content-item" v-for="item of list" :key="item.activityId" @click="handleActivity(item)">
<div class="item-left">
<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="" /> <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>
<div class="item-right">
<div class="full">
<h1 class="activity-name">{{ switchLanguage(item, 'activityName') }}</h1>
<div class="common-box">
<div class="common">{{ $t('ActivityTime') }}</div>
<div class="info">{{ item.startDate }} {{ $t('zhi') + item.endDate }}</div>
</div>
<div class="common-box">
<div class="common">{{ $t('activityAddress') }}</div>
<div class="info">{{ switchLanguage(item, 'activityAddress') }}</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> </div>
</div>
<div class="btn">查看活动</div>
</ScrollView>
</div> </div>
</div> </div>
</TransitionGroup> </TransitionGroup>
</ScrollView> </ScrollView>
<Teleport to="body">
<Transition enter-active-class="animate__animated animate__fadeIn" leave-active-class="animate__animated animate__fadeOut">
<ActivityDetail @close="showDetail = false" :config="config" :activity="activity" v-if="showDetail" />
</Transition>
</Teleport>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue' import { ref } from 'vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useStore } from '@/store/root' import { useStore } from '@/store/root'
import ActivityDetail from '../ActivityDetail/ActivityDetail.vue'
import ScrollView from '@/base/ScrollView/ScrollView.vue' import ScrollView from '@/base/ScrollView/ScrollView.vue'
import 'swiper/css' import 'swiper/css'
import 'swiper/css/pagination' import 'swiper/css/pagination'
import 'swiper/css/effect-coverflow' import 'swiper/css/effect-coverflow'
@ -46,89 +40,183 @@ defineProps({
default: () => [] default: () => []
} }
}) })
const showDetail = ref(false) const showDetail = ref(false)
const activity = ref({})
const activity = ref(null)
function handleActivity(item) { function handleActivity(item) {
activity.value = item activity.value = item
showDetail.value = true showDetail.value = true
} }
const store = useStore() const store = useStore()
const { config } = storeToRefs(store) const { config } = storeToRefs(store)
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.scroll { .scroll {
position: absolute;
top: 360px;
left: 170px;
right: 40px;
bottom: 0;
position: relative;
flex: 1;
overflow: hidden; 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 { .content-item {
display: flex;
height: 340px;
position: relative;
width: 944px;
height: 532px;
background: #ffffff; background: #ffffff;
border-radius: 12px;
border-radius: 16px;
overflow: hidden; overflow: hidden;
margin-bottom: 24px; margin-bottom: 24px;
.item-left {
flex-shrink: 0;
width: 600px;
height: 340px;
&.d {
.front {
z-index: 0;
}
.back {
z-index: 1;
}
}
.front {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
img { img {
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: cover; object-fit: cover;
} }
}
.item-right {
display: flex;
flex-direction: column;
flex: 1;
padding: 32px 0 0 0;
.full {
flex: 1;
}
.btn {
.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-weight: 700;
font-size: 16px; font-size: 16px;
line-height: 56px;
text-align: center;
font-family: 'font_bold';
color: rgba(0, 0, 0, 0.6);
height: 56px;
border-top: 1px solid rgba(0, 0, 0, 0.05);
line-height: 40px;
color: #ffffff;
padding: 0 27px;
height: 40px;
border-radius: 0px 0px 0px 12px;
} }
.activity-name {
font-weight: 700;
font-size: 20px;
line-height: 150%;
text-align: justify;
color: rgba(0, 0, 0, 0.8);
font-family: 'font_bold';
margin: 0 32px;
margin-bottom: 49px;
@include more-wrap(3);
.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: linear-gradient(113.71deg, #435acd 0%, #749cf3 100%);
box-shadow: 0px 15px 24px rgba(173, 196, 236, 0.25);
font-weight: 700;
font-size: 18px;
line-height: 21px;
text-align: center;
color: #ffffff;
}
} }
.common-box {
margin-bottom: 16px;
font-weight: 700;
margin-left: 32px;
margin-right: 32px;
font-family: 'font_bold';
.common {
font-size: 12px;
color: rgba(0, 0, 0, 0.6);
padding-bottom: 6px;
}
.back {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
z-index: 0;
background: #ffffff;
.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: rgba(0, 0, 0, 0.8);
} }
.info {
font-size: 10px;
color: rgba(0, 0, 0, 0.4);
.desc {
padding: 0 68px;
padding-bottom: 23px;
font-weight: 400;
font-size: 16px;
line-height: 200%;
color: rgba(0, 0, 0, 0.6);
} }
} }
} }

146
src/layouts/View.vue

@ -1,146 +1,40 @@
<template> <template>
<div class="view-container"> <div class="view-container">
<div class="header-left">
<h1 class="title">{{ title }}</h1>
<h2 class="sub">{{ subTitle }}</h2>
</div>
<div class="align-right" v-if="showInput && isUseSpeech">
<div class="top-right">
<img src="../assets/images/index/index_search.png" class="index-search-icon" alt="" />
<div class="mock-input" @click="handleSearch">
<p class="search">搜索</p>
<p class="search-en">search</p>
</div>
<img @click="handleVoice" src="../assets/images/guide/voice_white.png" class="index-voice-icon" alt="" />
</div>
</div>
<img src="@/assets/images/mall_logo.png" class="mall-logo" alt="" />
<div :class="['bgTop', long ? 'long' : '', mid ? 'mid' : '']"></div>
<slot /> <slot />
</div> </div>
</template> </template>
<script setup> <script setup>
import { storeToRefs } from 'pinia'
import { useStore } from '@/store/root'
defineProps({ defineProps({
showInput: {
long: {
type: Boolean, type: Boolean,
default: true
default: false
}, },
title: {
type: String,
default: ''
},
subTitle: {
type: String,
default: ''
mid: {
type: Boolean,
default: false
} }
}) })
const store = useStore()
const { isUseSpeech } = storeToRefs(store)
function handleSearch() {
store.SET_SHOW_SEARCH(true)
}
function handleVoice() {
store.SET_SHOW_SEARCH(true)
store.SET_SHOW_VOICE(true)
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.view-container { .view-container {
width: 1080px;
height: 1920px;
}
.mall-logo {
position: absolute;
top: 56px;
right: 40px;
width: 108px;
z-index: 51;
}
.header-left {
position: relative;
display: flex; display: flex;
align-items: center;
padding-left: 170px;
padding-right: 40px;
padding-top: 56px;
z-index: 51;
margin-bottom: 102px;
.title {
font-weight: 700;
font-family: 'font_bold';
font-size: 48px;
color: var(--color-black-opacity-8);
margin-right: 32px;
}
.sub {
width: 100px;
font-weight: 700;
font-size: 24px;
line-height: 28px;
font-family: 'font_bold';
text-transform: uppercase;
color: var(--color-black-opacity-6);
}
}
.align-right {
display: flex;
justify-content: flex-end;
}
.top-right {
position: relative;
display: flex;
align-items: center;
width: 365px;
height: 88px;
background: var(--color-black-opacity-05);
box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.3), inset 0px 4px 30px rgba(0, 0, 0, 0.02);
border-radius: 51px;
margin-right: 40px;
&::before {
position: absolute;
content: '';
width: 2px;
height: 30px;
left: 76px;
top: 29px;
background: var(--color-black-opacity-2);
}
.index-search-icon {
width: 32px;
height: 32px;
margin-right: 42px;
margin-left: 24px;
}
.mock-input {
width: 298px;
}
.search {
font-weight: 700;
font-size: 16px;
line-height: 28px;
font-family: 'font_bold';
color: var(--color-black-opacity-6);
}
.search-en {
font-size: 12px;
font-weight: 700;
font-family: 'font_bold';
text-transform: uppercase;
color: var(--color-black-opacity-4);
}
.index-voice-icon {
width: 132px;
height: 78px;
margin-right: 5px;
flex-direction: column;
width: 100vw;
height: 100vh;
background: #dee6f6;
.bgTop {
background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.5) 100%);
border-bottom: 1px solid rgba(255, 255, 255, 0.8);
height: 408px;
&.long {
height: 570px;
}
&.mid {
height: 515px;
}
} }
} }
</style> </style>

20
src/views/Activities/Activities.vue

@ -1,15 +1,11 @@
<template> <template>
<View title="活动精选" sub-title="event selection">
<Tabs class="width" @click="handleTab" :list="list" />
<View long>
<ActivitiesList :list="activityList" /> <ActivitiesList :list="activityList" />
</View> </View>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue' import { ref } from 'vue'
import { list } from './tabs'
import Tabs from '@/components/Tabs/Tabs.vue'
import View from '@/layouts/View.vue' import View from '@/layouts/View.vue'
import ActivitiesList from '@/components/ActivitiesList/ActivitiesList.vue' import ActivitiesList from '@/components/ActivitiesList/ActivitiesList.vue'
import { getActivityList } from '@/http/api' import { getActivityList } from '@/http/api'
@ -17,13 +13,6 @@ import { getActivityList } from '@/http/api'
const activityList = ref([]) const activityList = ref([])
_getActivityList(1) _getActivityList(1)
function handleTab(index) {
if (index === 0) {
_getActivityList(1)
} else {
_getActivityList(2)
}
}
function _getActivityList(type) { function _getActivityList(type) {
getActivityList(type).then(({ data }) => { getActivityList(type).then(({ data }) => {
@ -33,11 +22,4 @@ function _getActivityList(type) {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.width {
position: absolute !important;
top: 214px !important;
left: 170px !important;
width: 440px !important;
height: 88px !important;
}
</style> </style>

74
src/views/Index/Index.vue

@ -1,38 +1,39 @@
<template> <template>
<div class="index-container">
<div class="header">
<div class="hot-search">
<h1 class="title">{{ $t('hotSearch') }}</h1>
<div class="row">
<div class="item" v-for="(item, i) of hotRecommend" :key="item.shopId" @click="handleHot(item)">
<img class="medal" v-if="i === 0" src="./fir.svg" />
<img class="medal" v-if="i === 1" src="./sec.svg" />
<img class="medal" v-if="i === 2" src="./thi.svg" />
<div class="text">{{ item.shopName }}</div>
<View mid>
<div class="index-container">
<div class="header">
<div class="hot-search">
<h1 class="title">{{ $t('hotSearch') }}</h1>
<div class="row">
<div class="item" v-for="(item, i) of hotRecommend" :key="item.shopId" @click="handleHot(item)">
<img class="medal" v-if="i === 0" src="./fir.svg" />
<img class="medal" v-if="i === 1" src="./sec.svg" />
<img class="medal" v-if="i === 2" src="./thi.svg" />
<div class="text">{{ item.shopName }}</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="content">
<div class="r1">
<div class="guide" @click="goPage({ title: '地图导览', path: '/guide' })">
<div class="top">
<div class="title">找店</div>
<div class="meta">{{ guideDesc }}</div>
<img src="./guideImg.svg" />
<div class="content">
<div class="r1">
<div class="guide" @click="goPage({ title: '地图导览', path: '/guide' })">
<div class="top">
<div class="title">找店</div>
<div class="meta">{{ guideDesc }}</div>
<img src="./guideImg.svg" />
</div>
<div class="meta1">当前位置<img src="./pos.svg" /></div>
<div class="meta2">{{ bf }}</div>
<div class="bottom-right"></div>
</div> </div>
<div class="meta1">当前位置<img src="./pos.svg" /></div>
<div class="meta2">{{ bf }}</div>
<div class="bottom-right"></div>
</div> </div>
</div>
<div class="r2">
<div class="item" v-for="tab of sidebarList" :key="tab.title" @click="goPage(tab)">
<div class="icon"><img :src="tab.icon" /></div>
<div class="title">{{ switchLanguage(tab, 'title') }}</div>
<div class="r2">
<div class="item" v-for="tab of sidebarList" :key="tab.title" @click="goPage(tab)">
<div class="icon"><img :src="tab.icon" /></div>
<div class="title">{{ switchLanguage(tab, 'title') }}</div>
</div>
</div> </div>
</div>
<!-- <div class="cards pos">
<!-- <div class="cards pos">
<div class="card" @click="handleCard(item)" v-for="item of cardsList" :key="item.moduleType"> <div class="card" @click="handleCard(item)" v-for="item of cardsList" :key="item.moduleType">
<h1 class="name">{{ item.name }}</h1> <h1 class="name">{{ item.name }}</h1>
<h1 class="sub-title">{{ item.nameEn }}</h1> <h1 class="sub-title">{{ item.nameEn }}</h1>
@ -40,10 +41,11 @@
<img :src="config.sourceUrl + item.crossFileUrl" alt="" class="bg" /> <img :src="config.sourceUrl + item.crossFileUrl" alt="" class="bg" />
</div> </div>
</div> --> </div> -->
</div>
</div>
<router-view />
</div>
<router-view />
</div>
</View>
</template> </template>
<script setup> <script setup>
@ -52,6 +54,7 @@ import { useRouter } from 'vue-router'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useStore } from '@/store/root' import { useStore } from '@/store/root'
import { getBrandList } from '@/http/brand/api' import { getBrandList } from '@/http/brand/api'
import View from '@/layouts/View.vue'
const router = useRouter() const router = useRouter()
const store = useStore() const store = useStore()
@ -87,13 +90,13 @@ function handleHot(item) {
.index-container { .index-container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 1920px;
position: relative;
width: 100vw;
height: 100vh;
position: absolute;
top: 0;
.header { .header {
width: 100%; width: 100%;
height: 515px; height: 515px;
background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.5) 100%);
border-bottom: 1px solid rgba(255, 255, 255, 0.8);
padding: 392px 0 0 68px; padding: 392px 0 0 68px;
.hot-search { .hot-search {
.title { .title {
@ -142,7 +145,6 @@ function handleHot(item) {
.content { .content {
width: 100%; width: 100%;
flex: 1; flex: 1;
background: #dee6f6;
padding: 40px 68px 0 68px; padding: 40px 68px 0 68px;
.r1 { .r1 {
display: flex; display: flex;

Loading…
Cancel
Save