Files
xdd-uniapp-new/pages/cloud/haveFun.vue
T
2024-09-18 18:11:39 +08:00

380 lines
9.2 KiB
Vue

<template>
<view class="have-fun tabbar-page">
<view class="top-box">
<view class="v12-justify-start v12-align-center">
<view class="flex jc-end">
<view class="city-box" @click="goCity('cloud')">
<text style="white-space:nowrap; width: 100rpx" class="v12-primary-text one-t">{{ cityName }}</text>
<image :src="webUrl+'/orderIcon/map.png'" mode="scaleToFill"></image>
</view>
</view>
<view class="search-box v12-primary-border flex jc-between ai-center">
<input
v-model="name"
type="text"
placeholder="搜索店铺"
placeholder-style="color:#949494"
@confirm="search"
>
<view class="search-btn v12-primary v12-white-text v12-radius-60" @click="search">
<text class="v12-font-bold">搜索</text>
<image
class="icon v12-ml-1"
:src="webUrl+'/orderIcon/搜索 (1).png'"
mode="scaleToFill"
/>
</view>
</view>
</view>
<scroll-view class="type-box flex" scroll-x enable-flex>
<view
v-for="(item, index) in typeList"
:key="index"
:class="{
'active': typeIndex === index
}"
class="item flex-0 flex flex-col jc-center ai-center"
@click="tapType(index)"
>
<image :src="item.icon" mode="scaleToFill"/>
<view class="name">{{ item.name }}</view>
</view>
</scroll-view>
</view>
<view class="type-banner-wrap">
<view v-if="currType.titleImage" class="title">
<image
:src="currType.titleImage"
mode="heightFix"
class="img"
/>
</view>
<view v-if="currType.carousel" class="slider-wrap">
<swiper
indicatorDots="true"
indicator-color="rgba(255, 255, 255, .3)"
indicator-active-color="#ffffff"
autoplay
circular
style="height: 330rpx;"
>
<block
v-for="(item, bannerIndex) in currType.carousel"
:key="bannerIndex"
>
<swiper-item>
<view class="swiper-item" @click="typeBannerItemClick(item)">
<image :src="item.carouselImage" class="img" />
</view>
</swiper-item>
</block>
</swiper>
</view>
</view>
<view class="body">
<view>
<text class="v12-font-bold" v-if="currType.carousel">推荐</text>
</view>
<view v-if="isLoad">
<view v-if="hotelList.length > 0">
<view class="list-wrapper">
<view class="list">
<view
v-for="(item, index) in hotelEvenList"
:key="index"
class="item"
@click="goInnDetail(item)"
>
<fun-hotel-item :item="item" />
</view>
</view>
<view class="list">
<view
v-for="(item, index) in hotelOddList"
:key="index"
class="item"
@click="goInnDetail(item)"
>
<fun-hotel-item :item="item" />
</view>
</view>
</view>
</view>
<view class="v4-nodata" v-else>
<image src="@/static/images/img_nodata.png" mode="scaleToFill"/>
<view class="text">暂无数据</view>
</view>
</view>
<goo-skeleton
v-else
:show-avatar="false"
/>
</view>
<xdd-tabbar :curr-index="4" />
</view>
</template>
<script>
import { getHotelList, getHotelTypeList } from "@/api/inn.js"
import { getCurAddress, getLocation } from "@/utils/common"
import FunHotelItem from './components/HotelItem'
import { pageListenMixins } from '@/mixins/pageListenMixins'
import XddTabbar from '@/components/xdd-tabbar'
export default {
components: {
FunHotelItem,
XddTabbar
},
mixins: [pageListenMixins],
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
name: '',
page: 1,
typeList: [],
typeIndex: 0,
// 当前选中的类型
currType: {},
cityName: '',
hotelList: [],
isLoad: false,
pageKeyId: Object.freeze('findFunIndex')
}
},
computed: {
hotelOddList() {
const arr = this.hotelList.filter(function(item, index) { return index % 2 === 1 })
return arr
},
hotelEvenList() {
const arr = this.hotelList.filter(function(item, index) { return index % 2 === 0 })
return arr
}
},
onReachBottom() {
// 后端接口结构需要调整下,需要补充总页数,前端可判断当前页数大于等于总页数则不发送网络请求
this.page++
this.fetchList()
},
onLoad() {
getHotelTypeList().then(({data}) => {
this.typeList = data
this.currType = data[this.typeIndex]
this.getMapData()
})
},
onShow() {
const memCityName = uni.getStorageSync('cityName')
if (memCityName.length) {
this.cityName = memCityName
uni.removeStorageSync('cityName')
this.name = ''
this.search()
}
},
methods: {
goCity() {
uni.navigateTo({
url: `/pages/chose-city/chose-city?type=2&city=${this.cityName}`
})
},
goInnDetail(item) {
uni.navigateTo({
url: `/pagesInn/inn/innHome?id=${item.id}&from=fun`
})
},
async getMapData() {
const map = await getLocation()
if (map.length > 1) {
const {latitude, longitude} = map[1]
const address = await getCurAddress(latitude, longitude)
this.cityName = address[1].data.result.ad_info.city
this.search()
}
},
tapType(index) {
if (this.typeIndex === index) return
this.typeIndex = index
this.currType = this.typeList[index]
this.name = ''
this.search()
},
search() {
this.isLoad = false
this.page = 1
this.hotelList = []
this.fetchList()
},
fetchList() {
const param = {
page: this.page,
type: this.typeList[this.typeIndex].id,
cityName: this.cityName
}
const name = this.name.trim()
if (name.length > 0) {
param.name = name
}
getHotelList(param).then(res => {
const { success, data } = res
if (success) {
for (let i = 0; i < data.length; i++) {
const cover = data[i].cover
data[i].hide = true
// 视频封面取第一帧图片
if (data[i].coverType === 2) {
data[i].videoCover = cover
data[i].cover = (cover + '?vframe/jpg/offset/1')
} else {
data[i].videoCover = ''
}
this.hotelList.push(data[i])
}
}
}).finally(() => {
this.isLoad = true
})
},
typeBannerItemClick(item) {
if (!item.hotelId) return
uni.navigateTo({ url: `/pagesInn/inn/innHome?id=${item.hotelId}` })
}
}
}
</script>
<style scoped lang="less">
.search-btn{
position: absolute;
top: 2rpx;
bottom: 2rpx;
right: 2rpx;
padding: 0rpx 20rpx;
display: flex;
align-items: center;
font-size: 28rpx;
}
.have-fun {
//padding-top: 120rpx;
.top-box {
padding: 32rpx 0 20rpx;
background: #fff;
.search-box {
position: relative;
width: 575rpx;
height: 60rpx;
box-sizing: border-box;
margin: 0 auto;
padding: 0 24rpx 0 32rpx;
border: 2rpx solid #BBD2D2;
border-radius: 30rpx;
input {
font-size: 24rpx;
}
.icon {
width: 32rpx;
height: 32rpx;
}
}
.type-box {
height: 180rpx;
box-sizing: border-box;
white-space: nowrap;
padding: 20rpx 20rpx 0 48rpx;
.item {
width: 175rpx;
height: 175rpx;
margin-right: 20rpx;
border-radius: 26rpx;
image {
width: 72rpx;
height: 72rpx;
}
.name {
margin-top: 12rpx;
color: #949494;
font-size: 24rpx;
line-height: 34rpx;
}
}
.active {
background: #DCF2FE;
.name {
color: #333;
}
}
}
}
.body {
padding: 20rpx 32rpx;
background: #f5f5f5;
}
.city-box {
display: inline-flex;
align-items: center;
padding: 8rpx 18rpx 8rpx 16rpx;
border-radius: 30px;
background: #fff;
image {
width: 32rpx;
height: 32rpx;
margin-right: 4rpx;
}
text {
color: #333;
font-size: 28rpx;
}
}
.list-wrapper {
display: flex;
justify-content: space-between;
.list {
width: 328rpx;
.item {
width: 100%;
box-sizing: border-box;
}
}
}
}
.tabbar-page {
padding: 0 0 180rpx 0;
}
.type-banner-wrap {
padding: 0 20rpx;
background-color: #f0f0f0;
.title {
padding: 20rpx 0;
.img {
display: block;
height: 48rpx;
}
}
.slider-wrap {
width: 100%;
height: 330rpx;
padding: 0 0 20rpx 0;
.swiper-item {
.img {
display: block;
width: 100%;
height: 330rpx;
}
}
}
}
</style>