Files

1037 lines
27 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="container">
<hx-navbar
:fixed="true"
:background-color="[0,[0,0,0,0],[0,0,0,0]]"
:pageScroll.sync="scrollData"
statusBarFontColor="#ffffff"
barPlaceholder="hidden"
transparent="auto"
color='#ffffff'
/>
<view>
<view class="cover-box">
<image
v-if="store.coverType === 1"
:src="store.cover"
class="full-img"
mode="widthFix"
/>
<view
v-if="store.coverType === 2"
:style="{
'width': videoStyle.width,
'height': videoStyle.height
}"
class="video-box"
>
<video
:src="store.cover"
:autoplay="true"
:controls="true"
:loop="false"
object-fit="contain"
play-btn-position="center"
id="coverVideo"
class="video"
@play="coverPlay"
/>
</view>
</view>
<view class="innInfoWrap">
<view class="bg-color">
<view class="box-mask flex jc-between ai-end">
<view class="inn-name flex-0 more-t">{{ store.name }}</view>
<view
v-if="store.cityName != undefined && store.cityName.length > 0"
class="city-section flex jc-end ai-center"
>
<image
:src="webUrl + '/20210807215539157727.png'"
style="width: 22rpx;height: 22rpx;margin-right: 8rpx;"
/>
<text class="one-t" style="font-size: 24rpx;color: #fff;">{{ store.cityName }}</text>
</view>
</view>
</view>
<view class="body-cont flex ai-end">
<view class="inn-logo flex-0">
<image :src="store.logo" v-if="store.logo"></image>
<image :src="webUrl + '/20230609145651814148.png'" v-else/>
</view>
<view class="a3 flex jc-between ai-end" style="width: 100%">
<view class="inn-owner" style="flex-grow: 1;">{{ store.ownerName }}/店主</view>
<view v-if="store.guaranteeValue" class="guarantee flex jc-center ai-center">
保证金{{ store.guaranteeValue }}
</view>
<view class="flex ai-center zan-favorite-wrap">
<view class="zan-box flex flex-0 ai-end" @click="zanStore">
<template v-if="store.hasZan">
<image :src="webUrl + '/icon/icon-like.png'" class="img" />
<text class="on">{{ store.zan }}</text>
</template>
<template v-else>
<image :src="webUrl + '/icon/icon-like.png'" class="img" />
<text>{{ store.zan }}</text>
</template>
</view>
<view class="flex flex-0 ai-end favorite-box">
<image
v-if="store.hasFavorite"
:src="webUrl + '/icon/icon-star-on.png'"
mode="scaleToFill"
class="icon"
@click="doneFavorite(store.hasFavorite)"
/>
<image
v-else
:src="webUrl + '/icon/icon-star-off.png'"
mode="scaleToFill"
class="icon"
@click="doneFavorite(store.hasFavorite)"
/>
<text>{{ store.favoriteCount }}</text>
</view>
</view>
</view>
</view>
</view>
<view class="inn-signature-wrap">
<view class="triangle"></view>
<view class="inn-signature">
{{ store.content }}
</view>
<!-- <view class="share-btn" @click="changeShare">
<image :src="webUrl + '/page/hotel/share.png'" class="img" />
</view> -->
</view>
<view v-if="store.name" class="map-wrapper">
<view class="map-cont">
<map
:longitude="store.longitude"
:latitude="store.latitude"
style="width: 750rpx;height: 300rpx;"
/>
</view>
<view class="bg"></view>
<view class="map-info">
<view class="map-info-hd">
<image :src="webUrl + '/page/qianxian/icon-location.png'" class="icon" />
</view>
<view class="map-info-bd more-t">
{{ store.address }}
</view>
<view class="map-info-ft flex">
<view class="item" @click="showLocation">
<image :src="webUrl + '/page/qianxian/icon-addr.png'" class="img" />
<view>导航</view>
</view>
<view class="item" @click="call">
<image :src="webUrl + '/page/qianxian/icon-phone.png'" class="img" />
<view>客服</view>
</view>
</view>
</view>
</view>
<view class="top-tab acea-row row-middle row-center">
<view
v-for="(item, index) in tabList"
:key="index"
:class="item.isShow ? '' : 'hide'"
class="tab"
@click="changeTab(item.value)"
>
<view :class="activeIndex === index ? 'active' : ''" class="tab-item">
{{ item.text }}
</view>
<!-- <view v-show="activeIndex === index" class="btLine"></view> -->
</view>
</view>
<view>
<view v-if="activeIndex === 0" class="goods-section">
<view>
<view v-if="store.products && store.products.length > 0">
<view class="flex flex-wrap">
<view
v-for="(item,index) in store.products"
:key="index"
class="item"
@click="goGoodsConByID(item)"
>
<view>
<image
:src="item.productImage"
class="cover"
/>
<view class="v12-pt-2 v12-font-bold v12-font-28 more-t v12-px-2">{{ item.productName }}</view>
</view>
<view class="" style="padding: 20rpx">
<view class="v12-justify-between v12-align-center v12-pt-2">
<view>
<text class="v12-font-bold v12-primary-text v12-font-24"></text>
<text class="v12-font-bold v12-primary-text v12-font-28">{{ item.productPrice }}</text>
</view>
<view class="btn">
<image
:src="webUrl + '/home/icon-cart.png'"
class="img"
/>
</view>
</view>
<!-- <view class="price-line flex ai-center">
<image
:src="webUrl + '/20221118104357701129.png'"
class="label"
mode="scaleToFill"
/>
<text class="v12-primary-text">{{ item.productPrice }}</text>
</view> -->
</view>
</view>
</view>
</view>
<view v-else class="tab-no-data">
店主还没有上传内容哦~
</view>
</view>
<!-- <goo-skeleton v-else /> -->
</view>
<view
v-if="activeIndex === 1"
class="info-section"
>
<view v-if="isLoadInfoListSuccess">
<view v-if="infoArray.length > 0" class="info-wrapper">
<view class="info-list">
<view
v-for="(item, index) in infoArray"
:key="index"
class="info-item"
>
<view
:class="item.isTop === 1 ? 'info-item-top' : ''"
:style="{
'background-image': item.isTop ? ('url(' + webUrl + '/page/hotel/info-top-bg.png)') : 'none'
}"
class="info-item-header"
@click="infoClick(item)"
>
<view class="name">
{{ item.title }}
</view>
<view class="intro">
{{ item.content }}
</view>
</view>
<view class="info-item-body">
<view v-if="item.type === 2" class="video">
<view @click="infoItemViewClick(item, index)" v-if="activeVideo !== 'video-item' + index" class="play-icon">
<u-icon name="play-right-fill" color="#fff" size="48"></u-icon>
</view>
<image
v-if="activeVideo !== 'video-item' + index"
:src="item.video + '?vframe/jpg/offset/1'"
:poster="item.video + '?vframe/jpg/offset/1'"
controls
play-btn-position="center"
:show-fullscreen-btn="false"
:id="'video-item' + index"
class="video-item"
@click="infoItemViewClick(item, index)"
/>
<video
v-else
:src="item.video"
controls
autoplay
play-btn-position="center"
:show-fullscreen-btn="false"
class="video-item"
:id="'video-item' + index"
@click="infoItemViewClick(item, index)"
>
</video>
</view>
<view v-else>
<img-box
:imgList="item.images"
:num="item.images.length"
:img-radius="10"
style="width: 100%;"
@click="infoItemViewClick(item)"
/>
</view>
</view>
<view class="info-item-bottom">
<view class="time">
{{ item.createTime ? item.createTime.replace(/-/g, '.').substr(0, 10) : '' }}
</view>
<view class="btns">
<view class="flex">
<image
:src="webUrl + '/20230803152147141807.png'"
class="icon"
/>
<text class="seeNum-txt">{{ $formatCount(item.pv) }}</text>
</view>
<view class="flex">
<image
v-if="!item.hasZan"
:src="webUrl + '/page/hotel/zan-off-2.png'"
class="zan-off-icon"
@click="likeInfoItemHandle(item)"
/>
<image
v-else
:src="webUrl + '/page/hotel/zan-on-2.png'"
class="zan-on-icon"
@click="likeInfoItemHandle(item)"
/>
<text
v-show="item.zan > 0"
:class="item.zanVo ? 'on' : ''"
class="seeNum-txt"
>{{ $formatCount(item.zan) }}</text>
</view>
</view>
</view>
</view>
</view>
</view>
<view v-else class="tab-no-data">
店主还没有上传内容哦~
</view>
</view>
<goo-skeleton v-else />
</view>
<view
v-if="activeIndex === 2"
class="pics-section"
>
<view
v-if="store.cultureImages.length > 0"
class="pics-list acea-row"
>
<view
v-for="(url, index) in store.cultureImages"
:key="index"
:style="{ width: picColumnWidth }"
class="pics-item"
@click="showPic(index)"
>
<image
:style="{
width: picColumnWidth,
height: picColumnWidth,
borderRadius: '20rpx'
}"
:src="url"
/>
</view>
</view>
<view v-else class="tab-no-data">
店主还没有上传内容哦~
</view>
</view>
<view
v-if="activeIndex === 3"
class="qualifications-section"
>
<view v-if="store.qualifications.length > 0">
<image
v-for="(item, index) in store.qualifications"
:key="index"
:src="item"
class="store-img"
mode="widthFix"
/>
</view>
<view v-else class="tab-no-data">
店主还没有上传内容哦~
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import { getFarmerShop, setFarmerShopZan, getFarmerShopNews, removeFarmerShopCollection, setFarmerShopCollection } from '@/api/farmer'
import { postCountyFamousNewsZan, postCountyFamousNewsView } from '@/api/qianxian'
import imgBox from '@/components/imageTypeSet/imagebox.vue'
export default {
components: {
imgBox
},
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
videoStyle: {
width: '750rpx',
height: '500rpx'
},
scrollData: {},
id: '',
store: {},
tabList: [
{ text: '商品', value: 0, isShow: true },
{ text: '资讯', value: 1, isShow: true },
{ text: '文化', value: 2, isShow: true },
{ text: '资质', value: 3, isShow: true }
],
activeIndex: 0,
isLoadInfoListSuccess: false,
picColumnWidth: '325rpx',
infoArray: [],
videoPlayers: [],
activeVideo: 'coverVideo',
}
},
onPageScroll(e) {
this.scrollData = e
},
onLoad(opts) {
this.id = opts.id
this.getFarmerData()
uni.getSystemInfo({
success: (e) => {
// 两列商品宽度
this.picColumnWidth = (e.screenWidth - uni.upx2px(60)) / 2 + 'px'
}
})
},
methods: {
goGoodsConByID(item) {
this.$yrouter.push({
path: '/pages/shop/GoodsCon/index',
query: {
id: item.productId
}
})
},
getNews() {
const params = {
page: 1,
limit: 9999,
farmerShopId: this.id
}
getFarmerShopNews(params).then(res => {
this.infoArray = res.data.records || []
this.isLoadInfoListSuccess = true
})
},
changeTab(index) {
this.activeIndex = index
if(index === 1) {
this.getNews()
} else {
this.isLoadInfoListSuccess = false
}
// this.loading = false
// // 刷新数据
// switch (this.activeIndex) {
// case 1:
// this.fetchInnInfoList()
// break
// case 0:
// this.fetchGoods()
// break
// default:
// break
// }
},
showLocation() {
if (!this.store.latitude || !this.store.longitude) {
this.$dialog.error('暂无位置信息')
} else {
uni.openLocation({
latitude: this.store.latitude,
longitude: this.store.longitude
})
}
},
likeInfoItemHandle(item) {
const params = {
countyFamousNewsId: item.id
}
postCountyFamousNewsZan(params).then(res => {
const {success} = res
if(success) {
this.getNews()
}
})
},
coverPlay(){
this.activeVideo = 'coverVideo'
this.videoPlayers.forEach(player => {
const playerCtx = uni.createVideoContext(player, this)
playerCtx.pause()
})
},
infoItemViewClick(item, index) {
const playerId = 'video-item' + index
if(item.type === 2) {
const coverCtx = uni.createVideoContext('coverVideo', this)
coverCtx.pause()
this.activeVideo = 'video-item' + index
if(this.videoPlayers.includes(playerId)) {
this.videoPlayers.forEach(player => {
if(player === playerId) return
const playerCtx = uni.createVideoContext(player, this)
playerCtx.pause()
})
} {
this.videoPlayers.push(playerId)
this.videoPlayers.forEach(player => {
if(player === playerId) return
const playerCtx = uni.createVideoContext(player, this)
playerCtx.pause()
})
}
}
if(this.videoPlayers.filter(id => id === playerId).length > 1) return
const params = {
countyFamousNewsId: item.id
}
postCountyFamousNewsView(params).then(res => {
const {success} = res
if(success) {
this.getNews()
}
})
},
call() {
if (this.store.tel != undefined && this.store.tel.length > 0) {
uni.makePhoneCall({
// 手机号
phoneNumber: this.store.tel,
// 成功回调
success: (res) => {
console.log('调用成功!')
},
// 失败回调
fail: (res) => {
console.log('调用失败!')
}
})
} else {
this.$dialog.error('电话为空')
}
},
getFarmerData() {
getFarmerShop(this.id).then(res => {
this.store = res.data || {}
})
},
zanStore() {
const params = {
farmerShopId: this.id
}
setFarmerShopZan(params).then(res => {
const {success} = res
if(success) {
this.getFarmerData()
}
})
},
doneFavorite(has) {
const api = !has ? setFarmerShopCollection : removeFarmerShopCollection
const params = {
farmerShopId: this.id
}
api(params).then(res => {
this.getFarmerData()
})
},
showPic (index) {
uni.previewImage({
current: index,
urls: this.store.cultureImages
})
},
}
}
</script>
<style lang="less" scoped>
.btn {
.img {
display: block;
width: 48rpx;
height: 48rpx;
}
}
.container{
background: #fff;
}
.store-img {
width: 686rpx;
margin-bottom: 20rpx;
vertical-align: middle;
}
.tab-no-data {
text-align: center;
font-size: 32rpx;
color: #999;
line-height: 200rpx;
}
.btLine {
width: 100%;
height: 6rpx;
margin-top: 18rpx;
background: #0DC5C5;
}
.pics-box {
margin: 36rpx;
background: #fff;
}
.pics-list {
position: relative;
padding: 20rpx 0;
flex-wrap: wrap;
}
.pics-list .pics-item {
margin-left: 20rpx;
margin-top: 10rpx;
}
.info-section,
.pics-section,
.qualifications-section {
position: relative;
background-color: #f6f6f6;
}
.info-section,
.qualifications-section {
padding: 32rpx;
}
.info-section {
word-break: break-all;
.info-item + .info-item {
margin: 32rpx 0 0 0;
}
.info-item {
border-radius: 10rpx;
background-color: #fff;
.info-item-header {
position: relative;
padding: 20rpx 20rpx 0 20rpx;
&.info-item-top {
padding-top: 60rpx;
background-size: 100% 80rpx;
background-repeat: no-repeat;
background-image: url();
}
.name {
font-size: 16px;
color: #333;
font-weight: bold;
}
.intro {
margin: 10rpx 0 0 0;
color: #666;
font-size: 14px;
}
}
.info-item-body {
padding: 0 20rpx 20rpx 20rpx;
.video {
padding: 20rpx 0 0 0;
position: relative;
.play-icon {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
width: 80rpx;
height: 80rpx;
}
.video-item {
width: 100%;
height: 400rpx;
border-radius: 10rpx;
}
}
}
.info-item-bottom {
display: flex;
align-items: center;
padding: 20rpx;
border-top: 1px solid #f1f1f1;
font-size: 16px;
.time {
flex: 1;
color: #333;
}
.btns {
display: flex;
color: #999;
.flex + .flex {
margin: 0 0 0 32rpx;
}
.flex {
align-items: center;
}
.icon {
width: 32rpx;
height: 32rpx;
margin: 0 8rpx 0 0;
}
.zan-off-icon {
width: 40rpx;
height: 40rpx;
}
.zan-on-icon {
width: 40rpx;
height: 40rpx;
}
.seeNum-txt {
&.on {
color: #D81E06;
}
}
.more-btn {
position: relative;
.more-wrapper {
position: absolute;
right: -20rpx;
top: -150rpx;
z-index: 5;
width: 200rpx;
border-radius: 12rpx;
background-color: #fff;
box-shadow: 0px 1px 6px rgba(0,0,0,0.16);
.more-item + .more-item {
border-top: 1px solid #d5d5d5;
}
.more-item {
display: flex;
align-items: center;
justify-content: center;
height: 70rpx;
font-size: 14px;
color: #333;
.more-icon {
width: 36rpx;
height: 36rpx;
margin: 0 10rpx 0 0;
}
}
}
}
}
}
}
}
.goods-section {
padding: 40rpx 32rpx 0;
background: #f0f0f0;
.item {
position: relative;
width: 332rpx;
height: 528rpx;
box-sizing: border-box;
margin-right: 22rpx;
margin-bottom: 24rpx;
border-radius: 20rpx;
background: #fff;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: space-between;
.name {
padding: 8rpx 6rpx;
font-size: 26rpx;
line-height: 36rpx;
color: #333333;
height: 70rpx;
}
.price-line {
padding: 0 10rpx;
font-size: 26rpx;
line-height: 38rpx;
color: #ED0F0F;
}
.sales-line {
position: absolute;
bottom: 0;
width: 100%;
padding: 8rpx 10rpx 18rpx;
border-top: 1rpx solid #EFEFEF;
font-size: 24rpx;
line-height: 34rpx;
color: #8D8D8D;
}
}
.item:nth-child(2n) {
margin-right: 0;
}
.cover {
width: 332rpx;
height: 332rpx;
background: rgba(255, 255, 255, 0.39);
border-radius: 8rpx;
vertical-align: middle;
}
.label {
width: 40rpx;
height: 24rpx;
margin-right: 4rpx;
vertical-align: middle;
}
.icon {
width: 24rpx;
height: 24rpx;
margin-right: 6rpx;
vertical-align: middle;
}
.btn {
display: flex;
justify-content: center;
.btn-cont {
padding: 13rpx 30rpx;
border: 1px solid #0DC5C5;
border-radius: 8rpx;
color: #0DC5C5;
.iconfont {
margin: 0 0 0 20rpx;
font-size: 24rpx;
}
}
}
}
.btLine {
width: 100%;
height: 6rpx;
margin-top: 18rpx;
background: #0DC5C5;
}
.tab-item-active {
color:#080F1A;
font-size:32rpx;
}
.tab-item-no-active {
color:#A6AAB3;
font-size:28rpx;
}
.top-tab {
padding-bottom: 30rpx;
padding-top: 30rpx;
background: #fff;
.tab {
width: 20%;
.tab-item {
height: 52rpx;
padding: 0 30rpx;
border-radius: 26rpx 0 0 26rpx;
font-size: 32rpx;
line-height: 52rpx;
font-weight: bold;
&.active {
color: #fff;
background: linear-gradient(90deg, #C52733 0%, rgba(211,92,101,0.91) 54%, rgba(255,255,255,0.62) 100%);
}
}
&.hide {
display: none;
}
}
}
.map-wrapper {
position: relative;
z-index: 2;
height: 200rpx;
margin: 20rpx 0 0 0;
overflow: hidden;
.map-cont {
position: absolute;
top: 0;
left: 0;
z-index: 2;
width: 100%;
opacity: 0.3;
transform: translateY(-50rpx);
}
.bg {
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 3;
height: 60rpx;
background: linear-gradient(180deg, #FFFFFF 0%, rgba(255,255,255,1) 0%, rgba(255,255,255,0) 100%);
}
.map-info {
position: relative;
z-index: 5;
display: flex;
align-items: center;
padding: 40rpx 10rpx 40rpx 32rpx;
color: #333;
font-size: 14px;
background: rgba(255,255,255,0.4);
.map-info-hd {
.icon {
display: block;
width: 34rpx;
height: 42rpx;
}
}
.map-info-bd {
flex: 1;
padding: 0 60rpx 0 20rpx;
line-height: 60rpx;
}
.map-info-ft {
.item + .item {
margin: 0 0 0 6rpx;
}
.item {
text-align: center;
font-weight: 500;
.img {
display: block;
width: 64rpx;
height: 64rpx;
margin: 0 0 16rpx 16rpx;
}
}
}
}
}
.inn-signature-wrap {
position: relative;
z-index: 5;
padding: 0 32rpx;
margin: 20rpx 0 0 0;
.triangle {
position: absolute;
top: -20rpx;
left: 72rpx;
width: 0;
height: 0;
border-left: 20rpx solid transparent;
border-right: 20rpx solid transparent;
border-bottom: 24rpx solid rgba(243,243,246,0.39);
}
.inn-signature {
position: relative;
padding: 20rpx;
border-radius: 20rpx;
font-size: 24rpx;
color: #080F1A;
background: #fff;
box-shadow: 0px 0px 7px 1px rgba(0, 0, 0, 0.08);
}
.share-btn {
position: absolute;
right: 0;
bottom: -68rpx;
.img {
width: 212rpx;
height: 60rpx;
}
}
}
.zan-favorite-wrap {
font-size: 32rpx;
color: #333;
.on {
color: #FF564A;
}
}
.zan-box {
.img {
width: 36rpx;
height: 36rpx;
margin: 0 8rpx 0 0;
vertical-align: middle;
}
}
.favorite-box {
.icon {
width: 36rpx;
height: 36rpx;
margin: 0 8rpx 0 30rpx;
}
}
.cover-box {
position: relative;
.full-img {
width: 750rpx;
}
.video {
display: block;
width: 100%;
height: 100%;
}
}
.innInfoWrap {
position: relative;
margin-top: -76rpx;
padding: 20rpx 36rpx;
line-height: 1;
z-index: 1;
.bg-color {
position: absolute;
top: -5px;
left: 0;
right: 0;
z-index: 1;
height: 50%;
background: linear-gradient(-180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 100%);
.box-mask {
position: absolute;
bottom: 0;
right: 0;
left: 166rpx;
box-sizing: border-box;
padding: 0 32rpx 12rpx 0;
.city-section {
width: 256rpx;
margin-left: 20rpx;
}
}
}
.body-cont {
position: relative;
z-index: 2;
}
}
.inn-logo {
flex-shrink: 0;
width: 56*2rpx;
height: 56*2rpx;
margin-right: 18rpx;
}
.inn-logo image {
width: 100%;
height: 100%;
border-radius: 50%;
}
.inn-name {
width: 280rpx;
font-size: 32rpx;
color: #FFFFFF;
line-height: 48rpx;
}
.inn-owner {
font-size: 24rpx;
color: #8B8F99;
}
</style>