Files
xdd-uniapp-new/pkg_product/views/healthSanctum.vue
T

430 lines
12 KiB
Vue

<template>
<view class="sanctum-wrap">
<!-- <view class="v12-justify-center">
<view class="v12-mr-3 v12-radius-100 v12-primary v12-white-text v12-px-5 v12-py-2 v12-font-28 v12-font-bold">养生胜地</view>
<view class="v12-radius-100 v12-grey v12-dark-text v12-px-5 v12-py-2 v12-font-28 v12-font-bold" @click="toFoods">养生食材</view>
</view> -->
<view class="banner-tabs v12-justify-center">
<image
class="tab-btn v12-mr-3"
:src="travelButtonSrc"
mode="widthFix"
/>
<image
class="tab-btn"
:src="wellnessButtonSrc"
mode="widthFix"
@click="toFoods"
/>
</view>
<view class="v12-justify-between v12-align-center v12-mt-5">
<image
:src="webUrl + '/orderIcon/map_dark.png'"
mode="widthFix"
class="icon"
/>
<view class="v12-font-28 v12-secondary-dark-text v12-mr-3">{{ cityName }}</view>
<view class="flex-1" @click="search">
<u-search searchIconColor="#C52733" :disabled="true" :showAction="false" v-model="keyword" ></u-search>
</view>
</view>
<swiper v-if="traveItems.length > 0" class="v12-justify-between swap" autoplay circular next-margin="300rpx" duration="10000" interval="3000" >
<swiper-item v-for="(item, index) in traveItems" :key="index" >
<view class="trave-item v12-mr-3 v12-mt-3" @click="toStore(item)">
<view class="trave-item">
<image class="trave-item" :src="item.cover" v-if="item.coverType === 1"></image>
<video
class="trave-item"
:src="item.cover"
:show-fullscreen-btn="false"
:show-center-play-btn="false"
:show-play-btn="false"
:poster="item.cover + '?vframe/jpg/offset/1'"
v-if="item.coverType === 2"
></video>
</view>
<view class="trave-btn">
<text>旅居预约</text>
<image :src="webUrl + '/orderIcon/arrow.png'" class="arrow-icon v12-ml-1"></image>
</view>
</view>
</swiper-item>
</swiper>
<view class="v12-justify-between v12-align-center v12-px-3 v12-mt-3 tabs-wrap">
<!-- <view
class="tab v12-font-34 v12-dark-text v12-mr-5"
v-for="(tab, index) in tabs"
@click="handleTab(index,tab)"
:class="{'v12-font-bold' : index === actived}"
:key="index">
<text>{{ tab.name }}</text>
<view :class="{'slider': index === actived}"></view>
</view> -->
<text class=" v12-font-34 v12-dark-text v12-mr-5 v12-font-bold">大家都在看</text>
</view>
<view class="waterfall-box v12-mt-3">
<view class="waterfall-column">
<view v-for="(item, index) in leftItems" :key="index" class="v12-pa-1" @click="toStore(item)">
<view class="img">
<video
class="img"
:src="item.cover"
:play-btn-position="center"
:show-fullscreen-btn="false"
:show-center-play-btn="flase"
:show-play-btn="false"
:controls="false"
:poster="item.cover + '?vframe/jpg/offset/1'"
v-if="item.coverType === 2">
</video>
<image v-else class="img" :src="item.cover" mode="aspectFill"></image>
<view class="v12-white-text address">
<image
class="map-icon v12-mr-1"
:src="webUrl + '/orderIcon/map_white.png'"
></image>
<text class="v12-font-28">{{ item.areaName }}</text>
</view>
</view>
<view v-if="item.intro" class="v12-font-bold v12-font-28 v12-mt-1 more-t desc-txt">{{ item.intro }}</view>
<view class="v12-justify-start v12-align-center v12-my-1">
<view class="atr">
<image class="atr" :src="item.avatar"></image>
</view>
<view class="v12-font-26 v12-ml-2 v12-dark-text one-t">{{ item.name }}</view>
</view>
</view>
</view>
<view class="waterfall-column">
<view v-for="(item, index) in rightItems" :key="index" class="v12-pa-1" @click="toStore(item)">
<view class="img">
<video
class="img"
:src="item.cover"
:play-btn-position="center"
:show-fullscreen-btn="false"
:show-center-play-btn="flase"
:show-play-btn="false"
:controls="false"
:poster="item.cover + '?vframe/jpg/offset/1'"
v-if="item.coverType === 2">
</video>
<image v-else class="img" :src="item.cover" mode="aspectFill"></image>
<view class="v12-white-text address">
<image
class="map-icon v12-mr-1"
:src="webUrl + '/orderIcon/map_white.png'"
></image>
<text class="v12-font-28">{{ item.areaName }}</text>
</view>
</view>
<view v-if="item.intro" class="v12-font-bold v12-font-28 v12-mt-1 more-t desc-txt">{{ item.intro }}</view>
<view class="v12-justify-start v12-align-center v12-my-1">
<view class="atr">
<image class="atr" :src="item.avatar"></image>
</view>
<view class="v12-font-26 v12-ml-2 v12-dark-text one-t">{{ item.name }}</view>
</view>
</view>
</view>
</view>
<view v-if="items.length === 0" class="v12-justify-center v12-mt-6">
<view class="no-data-wrap">
<image :src="webUrl + '/orderIcon/微信图片_20241009220552.png'" mode="widthFix"></image>
</view>
</view>
<view v-if="items.length > 0" class="load-more-status">
{{ loading ? '加载中...' : (hasMore ? '上拉加载更多' : '没有更多了') }}
</view>
</view>
</template>
<script>
import { getJiaLouList } from '@/api/qianxian'
import { getWellnessTopImage } from '@/api/health'
export default {
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
items: [],
traveItems: [],
cityId: '',
cityName: '',
topImageConfig: {},
page: 1,
pageSize: 10,
loading: false,
hasMore: true
}
},
computed: {
travelButtonSrc() {
const config = this.topImageConfig || {}
return config.travelButtonImageFocus || config.travelButtonImage || ''
},
wellnessButtonSrc() {
const config = this.topImageConfig || {}
return config.wellnessButtonImage || config.wellnessButtonImageFocus || ''
},
leftItems() {
return this.items.filter((item, index) => index % 2 === 0)
},
rightItems() {
return this.items.filter((item, index) => index % 2 !== 0)
}
},
onLoad(opts) {
console.log(opts);
this.cityId = opts.city
this.cityName = decodeURIComponent(decodeURIComponent(opts.cityName))
this.getList(true)
this.getTop()
this.getTopImage()
},
onReachBottom() {
this.getList()
},
onUnload() {
// uni.navigateBack({
// delta: 0
// })
},
methods: {
toFoods() {
uni.redirectTo({
url: '/pkg_product/views/healthFoods?city=' + this.cityId + '&cityName=' + this.cityName
})
},
getPageList(data) {
if (Array.isArray(data)) {
return data
}
return (data && (data.records || data.list || data.data)) || []
},
getHasMore(data, list, page) {
const pageCount = Number(
data && (data.pages || data.totalPage || data.last_page || data.pageCount || 0)
)
const total = Number(
data && (data.total || data.totalCount || data.count || 0)
)
if (pageCount > 0) {
return page < pageCount
}
if (total > 0) {
return page * this.pageSize < total
}
return list.length >= this.pageSize
},
getList(reset = false) {
if (this.loading) return
if (!reset && !this.hasMore) return
const page = reset ? 1 : this.page
if (reset) {
this.page = 1
this.hasMore = true
this.items = []
}
const params = {
// countyId: this.cityId,
goodCityId: this.cityId,
shopType: 'wellnessTravel',
page,
limit: this.pageSize
}
this.loading = true
getJiaLouList(params).then(res => {
const list = this.getPageList(res.data)
this.items = page === 1 ? list : this.items.concat(list)
this.hasMore = this.getHasMore(res.data, list, page)
this.page = page + 1
}).finally(() => {
this.loading = false
})
},
search() {
uni.navigateTo({
url: '/pkg_product/views/healthSearch?city=' + this.cityId + '&cityName=' + this.cityName
})
},
getTop() {
const params = {
goodCityId: this.cityId,
shopType: 'wellnessTop',
page: 1,
limit: 10
}
getJiaLouList(params).then(res => {
this.traveItems = this.getPageList(res.data)
})
},
toStore(item) {
if(item.dataType === 'wellnessPlace'){
this.$yrouter.push({
path: '/pagesInn/inn/innHome',
query: {
id: item.hotelId
}
})
}else{
uni.navigateTo({ url: '/pkg_product/views/sojoumStore?id=' + item.id })
}
},
getTopImage() {
const cached = uni.getStorageSync('wellnessTopImageConfig')
if (cached) {
this.topImageConfig = cached
}
getWellnessTopImage().then(res => {
this.topImageConfig = res.data || {}
uni.setStorageSync('wellnessTopImageConfig', this.topImageConfig)
})
}
}
}
</script>
<style lang="less" scoped>
.banner-wrap{
position: relative;
margin-left: -20rpx;
margin-right: -20rpx;
}
.banner-img{
width: 100%;
height: auto;
display: block;
will-change: transform;
}
.banner-tabs{
left: 0;
right: 0;
top: 40rpx;
display: flex;
justify-content: center;
}
.tab-btn{
width: 200rpx;
will-change: transform;
display: block;
height: auto;
}
.tabs-wrap{
white-space: nowrap;
overflow: scroll;
.tab:last-child{
margin-right: 0 !important;
}
}
.map-icon{
width: 28rpx;
height: 28rpx;
}
.arrow-icon{
width: 25rpx;
height: 25rpx;
}
.icon{
width: 30rpx;
height: 30rpx;
}
.flex-1{
flex: 1;
}
.swap{
overflow: auto;
}
.trave-item-wrap{
position: relative;
}
.trave-btn{
position: absolute;
left: 0;
right: 0;
margin: auto;
bottom: 30rpx;
text-align: center;
width: 212rpx;
background: rgba(255,255,255,0.7);
border-radius: 60rpx;
font-size: 28rpx;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
padding: 10rpx 20rpx;
}
.trave-item{
width: 382rpx;
height: 272rpx;
background: rgba(230,178,178,0.39);
border-radius: 20rpx;
position: relative;
}
.desc-txt {
line-height: 40rpx;
max-height: 78rpx;
}
.address{
position: absolute;
left: 30rpx;
bottom: 30rpx;
display: flex;
align-items: center;
justify-content: center;
}
.sanctup-items{
display: grid;
grid-template-columns: 50% 50%;
}
.waterfall-box {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.waterfall-column {
width: 49.9%;
display: flex;
flex-direction: column;
.img{
height: 670rpx;
}
}
.atr{
width: 52rpx;
height: 52rpx;
border-radius: 50%;
}
.img{
width: 100%;
border-radius: 16rpx;
position: relative;
overflow: hidden;
max-height: 460rpx;
display: block;
min-height: 200rpx;
}
.sanctum-wrap{
min-height: 100vh;
background-color: #fff;
padding: 10rpx ;
}
.tab{
position: relative;
}
.slider{
position: absolute;
width: 100%;
height: 6rpx;
background: linear-gradient(to right, #C52733 0%, rgba(255,255,255,0) 100%);
border-radius: 6rpx;
bottom: 5rpx;
}
.load-more-status{
padding: 24rpx 0 40rpx;
text-align: center;
font-size: 24rpx;
color: #999;
}
</style>