Refactor(首页):改版重构-界面完成

This commit is contained in:
lifizer
2024-07-31 16:36:13 +08:00
parent 37fa7fab05
commit b9c3ff756c
3 changed files with 466 additions and 143 deletions
+287 -141
View File
@@ -1,5 +1,28 @@
<template>
<view class="tabbar-page">
<view
:style="{
'padding-top': statusBarHeight + 'px',
'padding-right': rightDistance + 'px'
}"
:class="scrollTop > 40 ? 'blur' : ''"
class="fix-header"
@click="goGoodSearch"
>
<view class="location">
昆明
<image
:src="webUrl + '/home/icon-location.png'"
class="icon"
/>
</view>
<view class="search-wrap">
<image
:src="webUrl + '/home/icon-search.png'"
class="icon"
/>
</view>
</view>
<view class="slider-banner">
<swiper
v-if="banner.length > 0"
@@ -45,19 +68,24 @@
</view>
</view>
<!-- 千县名品和地标好物 -->
<view class="land-famous-wrap">
<view class="pic-wrap">
<view
v-if="landmarkGoodsImage.image || countyFamousImage.image"
class="land-famous-wrap"
>
<view v-if="countyFamousImage.image" class="pic-wrap">
<image
:src="webUrl + '/home/land-pic.png'"
:src="countyFamousImage.image"
mode="heightFix"
class="img"
@click="landAndFamousItemClickHandle(countyFamousImage)"
/>
</view>
<view class="pic-wrap">
<view v-if="landmarkGoodsImage.image" class="pic-wrap">
<image
:src="webUrl + '/home/famous-pic.png'"
:src="landmarkGoodsImage.image"
mode="heightFix"
class="img"
@click="landAndFamousItemClickHandle(landmarkGoodsImage)"
/>
</view>
</view>
@@ -102,78 +130,77 @@
<view class="bast-list">
<view class="bast-list-left">
<view
v-for="(item,index) in bastLeftList"
v-for="(item, index) in bastLeftList"
:key="index"
class="item flex"
>
<template v-if="item.storeName === 'swiper'">
<swiper class="item bannar-swiper" autoplay circular>
<swiper-item v-for="swipe in bannerList" :key="swipe">
<image
:src="swipe.pic"
mode="aspectFit"
@click="goGoodsConByProductID(swipe)"
/>
</swiper-item>
</swiper>
</template>
<template v-else>
<view
v-if="item.type === 'hotel'"
class="hotel-list-wrap"
>
<image
:src="item.image"
class="top-img"
mode="scaleToFill"
@click="goGoodsCon(item)"
:src="webUrl + '/home/hotel-list-bg.png'"
mode="widthFix"
class="bg"
/>
<view class="content" @click="goGoodsCon(item)">
<view class="title more-t">{{ item.storeName }}</view>
<view class="price flex">
<text class="red">{{ item.price }}</text>
<text
v-if="item.productPrice"
class="gray"
>{{ item.productPrice }}
</text>
<view class="list">
<view
v-for="(hotelItem, hotelIndex) in item.list"
:key="hotelIndex"
class="hotel-item"
@click="hotelItemClickHandle(hotelItem)"
>
<image :src="webUrl + '/home/home-number' + (hotelIndex + 1) + '.png'" class="mark" />
<image :src="webUrl + '/home/icon-hotel-btn'" class="btn" />
<image :src="hotelItem.logo" class="logo" />
<view class="info">
<view class="name one-t">{{ hotelItem.name }}</view>
<view class="desc more-t">{{ hotelItem.content }}</view>
</view>
</view>
</view>
</template>
</view>
<xdd-product-item
v-else
:item="item"
@view="goGoodsCon(item)"
/>
</view>
</view>
<view class="bast-list-right">
<view
v-for="(item,index) in bastRightList"
v-for="(item, index) in bastRightList"
:key="index"
class="item flex"
>
<template v-if="item.storeName === 'swiper'">
<swiper class="item bannar-swiper" autoplay circular>
<swiper-item v-for="swipe in bannerList" :key="swipe">
<view
v-if="item.type === 'swiper'"
class="swiper-wrap"
>
<swiper
class="swiper"
circular
autoplay
:interval="3000"
>
<swiper-item
v-for="(swiperItem, swiperIndex) in item.list"
:key="swiperIndex"
>
<image
:src="swipe.pic"
mode="aspectFit"
@click="goGoodsConByProductID(swipe)"
:src="swiperItem.image"
mode="scaleToFill"
class="swiper-img"
@click="goHomeStay(swiperItem)"
/>
</swiper-item>
</swiper>
</template>
<template v-else>
<image
:src="item.image"
class="top-img"
mode="scaleToFill"
@click="goGoodsCon(item)"
/>
<view class="content" @click="goGoodsCon(item)">
<view class="title more-t">{{ item.storeName }}</view>
<view class="price flex">
<text class="red">{{ item.price }}</text>
<text
v-if="item.productPrice"
class="gray"
>{{ item.productPrice }}
</text>
</view>
</view>
</template>
</view>
<xdd-product-item
v-else
:item="item"
@view="goGoodsCon(item)"
/>
</view>
</view>
</view>
@@ -218,7 +245,7 @@
<script>
import XddTabbar from '@/components/xdd-tabbar'
import imgBox from '@/components/imageTypeSet/imagebox.vue'
import XddProductItem from '@/components/xdd-product-item'
import { mapGetters } from 'vuex'
import { getCouponReceive } from '@/api/user'
import { getHomeData, getShareImage } from '@/api/public'
@@ -227,25 +254,28 @@ import { pageListenMixins } from '@/mixins/pageListenMixins'
export default {
name: 'IndexPage',
components: {
imgBox,
XddTabbar
XddTabbar,
XddProductItem
},
mixins: [pageListenMixins],
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
hotGoodsColumnWidth: '325rpx',
bgImgHeight: '20px',
// 状态栏高度
statusBarHeight: 20,
// 右侧距离
rightDistance: 10,
banner: [],
menus: [],
cityName: '',
// 尖货
bastList: [],
// 地标好物
landmarkGoodsImage: {},
// 千县名品
countyFamousImage: {},
// 尖货推荐左侧
bastLeftList: [],
// 尖货推荐右侧
bastRightList: [],
statusBarHeight: 64,
// 尖货推荐横幅
bannerList: [],
// 分享图片
@@ -268,17 +298,13 @@ export default {
uni.getSystemInfo({
success: (e) => {
let statusBar = 0
let customBar = 0
// #ifdef MP-WEIXIN
statusBar = e.statusBarHeight
const custom = uni.getMenuButtonBoundingClientRect()
customBar = custom.bottom + custom.top - e.statusBarHeight
_this.rightDistance = e.windowWidth - custom.left + 10
// #endif
_this.statusBarHeight = customBar
// 两列商品宽度
_this.hotGoodsColumnWidth = (e.screenWidth - uni.upx2px(90)) / 2 + 'px'
// 状态栏图片高度
_this.bgImgHeight = statusBar + 'px'
// 状态栏高度
_this.statusBarHeight = statusBar
}
})
},
@@ -297,43 +323,68 @@ export default {
imageUrl: this.shareAppImg
}
},
onPullDownRefresh() {
uni.stopPullDownRefresh()
uni.navigateTo({
url: '/pkg-video/views/lottery'
})
},
onPageScroll(e) {
this.scrollTop = e.scrollTop
},
methods: {
init() {
getShareImage().then(({ data }) => this.shareAppImg = data)
sharpBannar().then(res => {
const { data } = res
this.bannerList = data.banner
this.getPageData()
})
},
getPageData() {
const _this = this
getShareImage().then(({ data }) => _this.shareAppImg = data)
sharpBannar().then(response => {
_this.bannerList = response.data.banner
uni.showLoading({ title: '加载中' })
getHomeData().then(res => {
const { data } = res
_this.$set(_this, 'banner', data.banner)
_this.$set(_this, 'menus', data.menus)
_this.$set(_this, 'oldUserPopup', data.oldUserPopup)
_this.$set(_this, 'contentHomestay', data.contentHomestay)
_this.$set(_this, 'contentFestival', data.contentFestival)
_this.bastLeftList = []
_this.bastRightList = []
for (let i = 0; i < data.bastList.length; i++) {
if (i % 2 === 0) {
_this.bastLeftList.push(data.bastList[i])
}
if (i % 2 === 1) {
_this.bastRightList.push(data.bastList[i])
uni.showLoading({ title: '加载中' })
getHomeData().then(res => {
const { data } = res
_this.$set(_this, 'banner', data.banner)
_this.$set(_this, 'menus', data.menus)
_this.$set(_this, 'landmarkGoodsImage', data.landmarkGoodsImage)
_this.$set(_this, 'countyFamousImage', data.countyFamousImage)
_this.$set(_this, 'oldUserPopup', data.oldUserPopup)
_this.$set(_this, 'contentHomestay', data.contentHomestay)
_this.$set(_this, 'contentFestival', data.contentFestival)
_this.bastLeftList = []
_this.bastRightList = []
for (let i = 0; i < data.bastList.length; i++) {
if (i % 2 === 0) {
if (i === 4 && data.hotelList.length > 0) {
_this.bastLeftList.push({
type: 'hotel',
list: data.hotelList
})
}
_this.bastLeftList.push(data.bastList[i])
}
uni.hideLoading()
}).catch(() => {
uni.hideLoading()
})
if (i % 2 === 1) {
if (i === 3) {
_this.bastRightList.push({
type: 'swiper',
list: [
{
image: 'http://resource.xdd618.com/19/20240722/1721615384602_入口图8.jpg',
url: '/pkg_product/views/festival'
},
{
image: 'http://resource.xdd618.com/19/20240715/1721006994007_微信图片_20240715092549.jpg',
url: '/pkg_product/views/festival'
},
{
image: 'http://resource.xdd618.com/19/20240722/1721615384602_入口图8.jpg',
url: '/pkg_product/views/festival'
}
]
})
}
_this.bastRightList.push(data.bastList[i])
}
}
uni.hideLoading()
}).catch(() => {
uni.hideLoading()
})
},
goRoll(item) {
@@ -352,16 +403,6 @@ export default {
}
})
},
goGoodsConByProductID(item, from) {
this.$yrouter.push({
path: '/pages/shop/GoodsCon/index',
query: {
id: item.productId,
activityId: item.id,
from
}
})
},
changeOldPopup(state) {
this.isOldUser = state
},
@@ -424,6 +465,19 @@ export default {
this.$global.levelJump(pageLevel, url, params)
}
},
landAndFamousItemClickHandle(item) {
const url = item.url
if (!url) return
if (item.level === '1') {
uni.switchTab({ url })
}
if (item.level === '2') {
uni.navigateTo({ url })
}
},
hotelItemClickHandle(item) {
uni.navigateTo({ url: item.url })
},
setTopHandle() {
uni.pageScrollTo({
scrollTop: 0,
@@ -491,7 +545,7 @@ export default {
.bast-title {
width: 312rpx;
height: 40rpx;
margin: 21rpx 0 21rpx 0;
margin: 32rpx 0 0;
}
.bannar-swiper {
height: 534rpx;
@@ -509,34 +563,18 @@ export default {
}
.item {
position: relative;
flex-direction: column;
border-radius: 20rpx;
margin: 21rpx 0 0 0;
background: #fff;
overflow: hidden;
.top-img {
width: 343rpx;
height: 343rpx;
.swiper-wrap {
width: 100%;
border-radius: 20rpx;
overflow: hidden;
}
.content {
box-sizing: border-box;
padding: 10rpx 10rpx 20rpx;
.title {
color: #333;
font-size: 28rpx;
}
.price {
font-size: 32rpx;
.red {
color: #DA0000;
}
.gray {
margin-left: 16rpx;
text-decoration: line-through;
font-size: 20rpx;
line-height: 30rpx;
color: #C2C5CC;
}
.swiper {
width: 100%;
height: 486rpx;
.swiper-img {
width: 100%;
height: 486rpx;
}
}
}
@@ -584,7 +622,7 @@ export default {
top: 0;
left: -21rpx;
z-index: 2;
width: calc(100% + 42rpx);
width: calc(100% + 40rpx);
height: 180rpx;
background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #F0F0F0 40%, #F0F0F0 100%);
content: " ";
@@ -609,4 +647,112 @@ export default {
}
}
}
.hotel-list-wrap {
position: relative;
width: 344rpx;
.bg {
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 2;
width: 100%;
}
.list {
position: relative;
z-index: 5;
padding: 100rpx 21rpx 21rpx 21rpx;
.hotel-item + .hotel-item {
margin: 21rpx 0 0 0;
}
.hotel-item {
position: relative;
display: flex;
align-items: center;
padding: 8rpx 16rpx 8rpx 8rpx;
border-radius: 16rpx;
background-color: #fff;
.mark {
position: absolute;
top: 8rpx;
left: 20rpx;
z-index: 5;
width: 26rpx;
height: 26rpx;
}
.btn {
position: absolute;
bottom: 8rpx;
right: 0;
z-index: 5;
width: 60rpx;
height: 22rpx;
}
.logo {
display: block;
width: 116rpx;
height: 116rpx;
border-radius: 16rpx;
}
.info {
width: calc(100% - 116rpx);
padding: 0 0 0 16rpx;
box-sizing: border-box;
.name {
font-size: 24rpx;
color: #333;
line-height: 40rpx;
}
.desc {
font-size: 20rpx;
color: #999;
line-height: 28rpx;
}
}
}
}
}
.fix-header {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 99;
display: flex;
align-items: center;
height: 44px;
padding-left: 21rpx;
line-height: 32px;
&.blur {
backdrop-filter: blur(5px);
}
.location {
display: flex;
align-items: center;
margin: -4px 20rpx 0 0;
color: #fff;
font-size: 32rpx;
.icon {
display: block;
width: 32rpx;
height: 32rpx;
margin: 0 0 0 10rpx;
}
}
.search-wrap {
display: flex;
align-items: center;
flex: 1;
height: 36px;
margin: -4px 0 0 0;
border-radius: 18px;
background-color: #fff;
.icon {
display: block;
width: 36rpx;
height: 36rpx;
margin: 0 0 0 20rpx;
}
}
}
</style>