Merge branch 'dev' into test

This commit is contained in:
lifizer
2024-12-30 11:46:59 +08:00
31 changed files with 1740 additions and 140 deletions
+3
View File
@@ -21,4 +21,7 @@ export function setFarmerShopCollection(data) {
return request.post("/collection/farmerShop/add", data)
}
export function removeFarmerShopCollection(data) {
return request.post("/collection/farmerShop/remove", data)
}
+27
View File
@@ -241,3 +241,30 @@ export function hotelNewsView(data) {
export function getFarmerShop(id) {
return request.get("/api/countyFamous/farmerShop/" + id)
}
export function getAncientTownIcon() {
return request.get("/ancientTown/icon")
}
export function getAncientTownList(params) {
return request.get("/ancientTown", params)
}
export function getAncientTownInfo(id) {
return request.get("/ancientTown/" + id)
}
export function getAncientTownActive(params) {
return request.get("/ancientTown/activity", params)
}
export function watchTownActive(data) {
return request.post("/ancientTown/activity/view", data, {login: true})
}
export function shareTown(id) {
return request.get("/ancientTown/poster/" + id, {login: true})
}
+4
View File
@@ -99,3 +99,7 @@ export function getCountyFamousVillageNews(param) {
export function getShareImg(id) {
return request.get('/countyFamous/poster/' + id, {login: true})
}
export function getSaleList(params) {
return request.get('/countyFamous/village/category', params, {login: true})
}
+3 -1
View File
@@ -169,7 +169,9 @@ each(@colors, {
display: grid;
grid-template-columns: 1fr 1fr;
}
.v12-gap-10{
grid-gap: 20rpx 20rpx;
}
.v12-text-right{
text-align: right;
+6
View File
@@ -75,6 +75,9 @@
@change="selectCoupon"
v-if="index !== maxIndex"
/>
<view v-if="list.length === 1" class="no-quan v12-font-28 v12-dark1-text text-center">
暂无更多可使用优惠券快去抽奖去吧~
</view>
</view>
<view
v-if="list.length === 0"
@@ -193,6 +196,9 @@ export default {
</script>
<style scoped lang="less">
.text-center{
text-align: center;
}
.popup-coupons {
background: #F0F0F0;
.popup-box {
+2
View File
@@ -13,6 +13,8 @@ export const pageListenMixins = {
onShow() {
this.pageViewDateTime = getCurrDateTime()
this.pageToWatchShowCount(this.pageKeyId)
this.videoContext = uni.createVideoContext('indexVideo', this);
},
onUnload() {
this.pageToHideHandle()
+12 -4
View File
@@ -103,7 +103,15 @@
{
"path": "pages/cloud/haveFun",
"style": {
"navigationBarTitleText": "探索生活好去处"
"navigationBarTitleText": "趣游生活"
}
},
{
"path": "pages/town/index",
"style": {
"navigationBarTextStyle": "white",
"navigationStyle": "custom",
"navigationBarTitleText": "趣游生活"
}
},
{
@@ -609,7 +617,7 @@
{
"path": "views/heritage",
"style": {
"navigationBarTitleText": "非遗文化"
"navigationBarTitleText": "非遗技艺"
}
},
{
@@ -621,14 +629,14 @@
{
"path": "views/heritage/index",
"style": {
"navigationBarTitleText": "非遗文化",
"navigationBarTitleText": "非遗技艺",
"navigationBarBackgroundColor": "#FAEED8"
}
},
{
"path": "views/heritage/details",
"style": {
"navigationBarTitleText": "非遗文化",
"navigationBarTitleText": "非遗技艺",
"navigationBarBackgroundColor": "#FAEED8"
}
},
+6 -2
View File
@@ -90,7 +90,11 @@
class="item flex-0 flex flex-col jc-between ai-center"
@click="goToStore(item.hotelId || '')"
>
<image class="cover" :src="item.hotelImage" mode="scaleToFill" />
<image
:src="item.hotelImage + (item.hotelImage.indexOf('.mp4') > -1 ? '?vframe/jpg/offset/1' : '')"
class="cover"
mode="scaleToFill"
/>
<image class="logo" :src="item.hotelLogo" mode="scaleToFill" />
<view style="width: 100%;box-sizing: border-box;padding:0 8rpx">
<view class="name tc one-t">{{ item.hotelName }}</view>
@@ -310,7 +314,7 @@ export default {
},
select(item) {
if (this.type === 0 && item.hasData === 0) return
if ((this.type === 1 || this.type === 2) && item.hasShop === 0) return
// if ((this.type === 1 || this.type === 2) && item.hasShop === 0) return
uni.setStorageSync("cityName", item.cityName)
switch (this.type) {
+211 -28
View File
@@ -5,9 +5,10 @@
<view class="flex jc-end">
<view class="city-box" @click="goCity('cloud')">
<text style="white-space:nowrap; width: 90rpx" class="v12-primary-text one-t">{{ cityName }}</text>
<image :src="webUrl+'/orderIcon/map.png'" mode="scaleToFill"></image>
<image :src="webUrl+'/icon/fun-city-change.png'" mode="scaleToFill"></image>
</view>
</view>
<view class="search-box v12-primary-border flex jc-between ai-center">
<input
v-model="name"
@@ -26,20 +27,52 @@
</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 class="v12-pa-2" style="position: relative">
<view class="v12-radius-20 v12-px-2 v12-py-1 tip-wrap v12-align-center v12-justify-between">
<view class="v12-align-center">
<image
class="map-icon"
mode="scaleToFill"
:src="webUrl + '/orderIcon/map_white.png'"
></image>
<text style="width: 95%" class="v12-font-24 v12-white-text">定位显示你在 {{ cityName }} 点击可切换其他城市</text>
</view>
<view @click="goCity('cloud')" class="qh-btn v12-white v12-radius-10 v12-font-24 v12-font-bold v12-dark-text v12-px-2">点击切换</view>
</view>
</scroll-view>
</view>
<view>
<scroll-view class="type-box flex" scroll-x enable-flex>
<view class="first-box">
<view class="first-box__inner">
<view
:class="{
'active': typeIndex === -1
}"
class="item flex-0 flex flex-col jc-center ai-center"
@click="tapType(-1)"
>
<image :src="townConfig.icon" mode="scaleToFill"/>
<view class="name">{{ townConfig.label }}</view>
</view>
</view>
</view>
<view class="scroll-box">
<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>
</view>
</scroll-view>
</view>
</view>
<view class="type-banner-wrap">
<view v-if="currType.titleImage" class="title">
@@ -71,9 +104,26 @@
</swiper>
</view>
</view>
<view class="body">
<view>
<view class="body" v-if="typeIndex === -1">
<view class="town-card" v-for="(town, i) in townList" :key="i" @click="toTown(town)">
<!-- <view class="town-title">{{ town.name }}</view> -->
<image :src="town.frontImage" mode="scaleToFill"/>
<view class="v12-primary enter-btn">点击进入
<view class="icon-box"><u-icon name="arrow-rightward" color="#fff" size="8"></u-icon></view>
</view>
</view>
<view class="v4-nodata" v-if="townList.length === 0">
<image src="@/static/images/img_nodata.png" mode="scaleToFill"/>
<view class="text">暂无数据</view>
</view>
</view>
<view class="body" v-else>
<view class="v12-justify-between v12-align-center">
<text class="v12-font-bold" v-if="currType.carousel">推荐</text>
<view class="v12-dark1-text v12-font-28 v12-align-center" @click="handleRefresh">
<u-icon name="reload"></u-icon>
换一换
</view>
</view>
<view v-if="isLoad">
<view v-if="hotelList.length > 0">
@@ -114,7 +164,7 @@
</view>
</template>
<script>
import { getHotelList, getHotelTypeList } from "@/api/inn.js"
import { getHotelList, getHotelTypeList, getAncientTownIcon, getAncientTownList } from "@/api/inn.js"
import { getCurAddress, getLocation } from "@/utils/common"
import FunHotelItem from './components/HotelItem'
import { pageListenMixins } from '@/mixins/pageListenMixins'
@@ -131,14 +181,17 @@ export default {
name: '',
page: 1,
typeList: [],
typeIndex: 0,
typeIndex: -1,
// 当前选中的类型
currType: {},
cityName: '',
hotelList: [],
isLoad: false,
pageKeyId: Object.freeze('findFunIndex'),
isNext: false
isNext: false,
townConfig: {},
townList: [],
randomSeed: null
}
},
computed: {
@@ -155,17 +208,18 @@ export default {
// 后端接口结构需要调整下,需要补充总页数,前端可判断当前页数大于等于总页数则不发送网络请求
if(this.isNext) {
this.page++
this.fetchList()
const random = this.randomSeed ? 1 : 0
this.fetchList(random, this.randomSeed)
}
},
onLoad() {
this.currType = {}
getHotelTypeList().then(({data}) => {
this.typeList = data
this.currType = data[this.typeIndex]
this.currType = this.typeIndex === -1 ? {} : data[this.typeIndex]
this.getMapData()
})
this.getIcon()
},
onShow() {
const memCityName = uni.getStorageSync('cityName')
@@ -190,6 +244,22 @@ export default {
}
},
methods: {
handleRefresh() {
uni.showLoading()
this.page = 1
this.hotelList = []
this.fetchList(1, this.randomSeed)
},
toTown(town) {
uni.navigateTo({
url: `/pages/town/index?id=${town.id}`
})
},
getIcon() {
getAncientTownIcon().then(res => {
this.townConfig = res.data
})
},
goCity() {
uni.navigateTo({
url: `/pages/chose-city/chose-city?type=2&city=${this.cityName}`
@@ -212,9 +282,11 @@ export default {
}
},
tapType(index) {
if (this.typeIndex === index) return
this.typeIndex = index
this.currType = this.typeList[index]
this.randomSeed = null
this.currType = index === -1 ? {} : this.typeList[index]
this.name = ''
this.search()
},
@@ -224,19 +296,35 @@ export default {
this.hotelList = []
this.fetchList()
},
fetchList() {
fetchList(random = 0, randomSeed) {
if(this.typeIndex === -1) {
const params = {
cityName: this.cityName,
page: 1,
limit: 999
}
getAncientTownList(params).then(res => {
this.townList = res.data.records
})
return
}
const param = {
page: this.page,
type: this.typeList[this.typeIndex].id,
cityName: this.cityName
cityName: this.cityName,
random: random,
randomSeed: this.page > 1 ? randomSeed : null
}
const name = this.name.trim()
if (name.length > 0) {
param.name = name
}
getHotelList(param).then(res => {
const { success, data } = res
const { success, data, msg } = res
if (success) {
if(random === 1) {
this.randomSeed = msg
}
for (let i = 0; i < data.length; i++) {
const cover = data[i].cover
data[i].hide = true
@@ -257,6 +345,7 @@ export default {
}
}).finally(() => {
this.isLoad = true
uni.hideLoading()
})
},
typeBannerItemClick(item) {
@@ -267,6 +356,100 @@ export default {
}
</script>
<style scoped lang="less">
.map-icon{
width: 30rpx;
height: 30rpx;
margin-right: 5rpx;
}
.qh-btn{
padding-top: 4rpx;
padding-bottom: 4rpx;
// border: thin dashed #999;
white-space: nowrap;
}
.tip-wrap{
background: #AAAEB3;
position: relative;
align-items: self-start !important;
&::before{
position: absolute;
content: '';
border-left: 15rpx solid transparent;
border-right: 15rpx solid transparent;
border-top: 20rpx solid transparent;
border-bottom: 20rpx solid #AAAEB3;
top: -30rpx;
left: 10%;
}
}
.icon-box{
border: 1rpx solid #fff;
border-radius: 100%;
width: 16rpx;
height: 16rpx;
margin-left: 5rpx;
padding: 2rpx;
}
.enter-btn{
color: #fff;
width: fit-content;
display: flex;
align-items: center;
padding: 10rpx 16rpx;
position: absolute;
right: 0;
bottom: 0;
border-radius: 30rpx 0;
font-size: 24rpx;
}
.town-title{
border-radius: 100rpx;
/* border-color: #333; */
// mix-blend-mode: difference;
width: fit-content;
padding: 5rpx 20rpx;
border: 1rpx solid #fff;
color: #fff;
position: absolute;
margin: auto;
top: 20rpx;
left: 0;
right: 0;
}
.town-card{
width: 100%;
height: 400rpx;
background: #fff;
border-radius: 30rpx;
position: relative;
overflow: hidden;
margin-bottom: 30rpx;
image{
width: -webkit-fit-content;
width: inherit;
height: -webkit-fit-content;
height: inherit;
}
}
.first-box{
padding-right: 15rpx;
position: sticky;
left: 0;
background-color: #f5f5f5;
z-index: 9;
}
.first-box__inner{
padding: 10rpx;
background: #fff;
border-radius: 30rpx;
}
.scroll-box{
display: flex;
height: fit-content;
background: #fff;
padding: 10rpx;
border-radius: 30rpx;
}
.search-btn{
position: absolute;
top: 2rpx;
@@ -308,7 +491,7 @@ export default {
height: 200rpx;
box-sizing: border-box;
white-space: nowrap;
padding: 20rpx 20rpx 0 20rpx;
padding: 0rpx 20rpx 0 20rpx;
.item {
width: 154rpx;
@@ -340,7 +523,7 @@ export default {
}
.body {
padding: 20rpx 20rpx;
padding: 0 20rpx 20rpx;
background: #f5f5f5;
}
+40 -2
View File
@@ -20,13 +20,25 @@
</view>
</view>
<view class="info-item-body">
<video
v-if="item.type === 2"
@play="infoItemViewClick(item, index)"
play-btn-position="center"
:show-fullscreen-btn="false"
class="video-item v12-mt-0"
:src="item.video"
controls
:id="'video-item' + index"
:poster="item.video + '?vframe/jpg/offset/1'"></video>
<img-box
v-else
:imgList="item.images"
:num="item.images.length"
:img-radius="10"
style="width: 100%"
@click="infoItemViewClick(item)"
/>
</view>
<view class="info-item-bottom">
<view class="time">
@@ -101,7 +113,8 @@ export default {
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
infoArray: []
infoArray: [],
videoPlayers:[]
}
},
watch: {
@@ -137,7 +150,27 @@ export default {
}
})
},
infoItemViewClick(item) {
infoItemViewClick(item, index) {
if(item.type === 2) {
// const coverCtx = uni.createVideoContext('coverVideo', this)
// coverCtx.pause()
const playerId = '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()
})
}
this.$emit('video')
}
uni.$u.debounce(() => {
hadView({ landmarkNewsId: item.id }).finally(() => {
this.infoArray.map(info => {
@@ -152,6 +185,11 @@ export default {
};
</script>
<style lang="scss" scoped>
.video-item {
width: 100%;
height: 400rpx;
border-radius: 10rpx;
}
.info-wrapper{
padding: 20px 10px;
}
+18 -5
View File
@@ -166,16 +166,16 @@
</swiper-item>
</swiper> -->
<view class="new-zone-wrap">
<view class="kd" @click="toKD">
<view class="kd" >
<view class="img-wrap" style="padding-top: 10rpx; box-sizing:border-box">
<image style="width: 112rpx; height:26rpx" :src="webUrl + '/orderIcon/kd.png'" mode="heightFix|widthFix"></image>
</view>
<view class="tip-img">
<image style="width: 142rpx; height:66.11rpx;border-radius: 0" :src="webUrl + '/orderIcon/dot.png'" mode="heightFix|widthFix"></image>
</view>
<view class="kd-cover">
<video play-btn-position="center" v-if="indexVideo" :show-fullscreen-btn="false" class="kd-cover v12-mt-0" :src="indexVideo" controls autoplay :poster="indexVideo + '?vframe/jpg/offset/1'"></video>
<view class="enter-btn">点击进入</view>
<view class="kd-cover" @click.stop="played">
<video play-btn-position="center" id="indexVideo" v-if="indexVideo" :show-fullscreen-btn="false" class="kd-cover v12-mt-0" :src="indexVideo" controls autoplay :poster="indexVideo + '?vframe/jpg/offset/1'"></video>
<view class="enter-btn" >点击进入</view>
</view>
</view>
<view class="xpsx">
@@ -383,7 +383,9 @@ export default {
contentFestival: {},
pageKeyId: Object.freeze('appIndex'),
scrollTop: 0,
lotteryCanDraw: false
lotteryCanDraw: false,
videoContext: null,
isPlay: true,
}
},
onLoad() {
@@ -417,6 +419,17 @@ export default {
this.scrollTop = e.scrollTop
},
methods: {
played() {
this.isPlay = !this.isPlay
if(this.isPlay) {
this.videoContext.play()
} else {
this.videoContext.pause()
}
this.toKD()
},
pause() {
},
toKD() {
this.$yrouter.push('/pages/VideoPlayBackList/VideoPlayBackList')
},
+4 -4
View File
@@ -30,14 +30,14 @@
</view>
<!-- <view class="reject-reason" v-if="orderInfo._status._type==-3 && orderInfo.refundRejectReason">驳回原因{{ orderInfo.refundRejectReason }}</view> -->
<view @click="goLogistics(orderInfo)" class="v12-radius-20 v12-white v12-pa-3 v12-mt-4" v-if="orderInfo._status._type == 3 || (orderInfo._status._type == 2 && orderInfo.isTickets!==1)">
<view >
<view class="v12-radius-20 v12-white v12-pa-3 v12-mt-4" v-if="orderInfo._status._type == 3 || (orderInfo._status._type == 2 && orderInfo.isTickets!==1)">
<view>
<text class="v12-secondary-dark-text v12-font-28">{{ orderInfo.deliveryName }}{{ orderInfo.deliveryId }}</text>
<text class="v12-font-22 v12-px-2 v12-py-1 v12-ml-1 v12-primary-text v12-primary-border v12-radius-40" @click="copyClipboard(orderInfo.orderId)">
<text class="v12-font-22 v12-px-2 v12-py-1 v12-ml-1 v12-primary-text v12-primary-border v12-radius-40" @click="copyClipboard(orderInfo.deliveryId)">
复制
</text>
</view>
<view class="v12-mt-2 v12-justify-between">
<view class="v12-mt-2 v12-justify-between" @click="goLogistics(orderInfo)">
<view class="v12-align-center">
<view class="v12-align-center v12-mr-2">
<image class="logo" :src="webUrl+'/orderIcon/car.png'" mode="" style="margin-right:0; width: 32rpx; height:32rpx"/>
+1 -1
View File
@@ -68,7 +68,7 @@
<view class="text">
<view class="name more-t">{{ item.storeName }}</view>
<view class="vip acea-row row-between-wrapper">
<view class="flex ai-end">
<view class="ai-end" :class="{'flex': force2Decimal(item.price).length < 6}">
<view class="money">
<text class="num" v-if="item.vipPrice && item.vipPrice > 0">{{ force2Decimal(item.vipPrice) }}</text>
+70
View File
@@ -0,0 +1,70 @@
<template>
<view class="v12-pa-2">
<view class="culture v12-d-grid-columns-2" v-if="list.length > 0">
<view class="img-item " v-for="(item, index) in list" :key="index" @click="viewImg(item)">
<image class="img-item" :src="item" mode="widthFix|heightFix" lazy-load="false"></image>
</view>
</view>
<image
v-if="list.length === 0"
:src="webUrl + '/orderIcon/wu.png'"
class="img-nodata"
mode="scaleToFill"
/>
</view>
</template>
<script>
export default {
props: {
list: {
type: Array,
default: () => []
}
},
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
}
},
watch: {
landmarkDataId(value) {
if(value) {
this.getData()
}
}
},
methods: {
viewImg(item) {
uni.previewImage({
current: item, // 当前显示图片的http链接
urls: this.list || [] // 需要预览的图片http链接列表
})
}
}
}
</script>
<style lang="scss" scoped>
.culture{
grid-gap: 20rpx 20rpx;
padding: 20rpx 10rpx;
background: #fff;
border-radius: 30rpx;
margin-top: 20rpx;
}
.img-item{
width: 340rpx;
height: 340rpx;
border-radius: 30rpx;
}
.img-nodata {
position: relative;
top: 0;
left: 50%;
transform: translate(-50%, 0);
width: 352rpx;
height: 338rpx;
margin-bottom: 60rpx;
}
</style>
+294
View File
@@ -0,0 +1,294 @@
<template>
<view>
<view v-if="actives.length > 0" class="info-wrapper">
<view class="info-list">
<view v-for="(item, index) in actives" :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"
>
<view class="name">
{{ item.name }}
</view>
<view class="intro">
{{ item.intro }}
</view>
<view class="intro v12-dark-text">活动时间: {{ item.activityTime }}</view>
</view>
<view class="info-item-body" v-if="item.contentType === 1">
<img-box
:imgList="item.images"
:num="item.images.length"
:img-radius="10"
style="width: 100%"
@click="infoItemViewClick(item)"
/>
</view>
<view class="info-item-body" v-if="item.contentType === 2">
<video
@play="infoItemViewClick(item, index)"
play-btn-position="center"
:show-fullscreen-btn="false"
class="video-item v12-mt-0"
:src="item.images[0]"
controls
:id="'video-item' + index"
:poster="item.images[0] + '?vframe/jpg/offset/1'"></video>
</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 v12-font-28">{{ item.pv }}</text>
</view>
</view>
</view>
</view>
</view>
<image
:src="webUrl + '/home/no-data-bg.png'"
mode="widthFix"
class="no-data-loadend"
style="width: 100%;"
/>
</view>
<image
v-if="actives.length === 0"
:src="webUrl + '/orderIcon/wu.png'"
class="img-nodata"
mode="scaleToFill"
/>
</view>
</template>
<script>
import { watchTownActive } from "@/api/inn.js"
import imgBox from '@/components/imageTypeSet/imagebox.vue'
export default {
props: {
infoArray: {
type: Array,
default: () => []
}
},
components: {
imgBox
},
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
actives: this.infoArray,
videoPlayers: []
}
},
watch: {
infoArray(val) {
this.actives = val
}
},
methods: {
coverPlay(){
this.videoPlayers.forEach(player => {
const playerCtx = uni.createVideoContext(player, this)
playerCtx.pause()
})
},
handlePlayer() {
this.videoPlayers.forEach(player => {
const playerCtx = uni.createVideoContext(player, this)
playerCtx.pause()
})
},
infoItemViewClick(item, index) {
if(item.contentType === 2) {
// const coverCtx = uni.createVideoContext('coverVideo', this)
// coverCtx.pause()
const playerId = '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()
})
}
this.$emit('video')
}
uni.$u.debounce(() => {
watchTownActive({ id: item.id }).finally(() => {
this.actives.forEach(info => {
if (info.id === item.id) {
info.pv += 1
}
})
})
}, 500)
},
}
};
</script>
<style lang="scss" scoped>
.video-item {
width: 100%;
height: 400rpx;
border-radius: 10rpx;
}
.info-wrapper{
padding: 20px 10px;
}
.info-item + .info-item {
margin: 22rpx 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;
.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: #999999;
font-size: 28rpx;
}
.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: 32rpx;
height: 32rpx;
}
.zan-on-icon {
width: 32rpx;
height: 32rpx;
}
.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;
}
}
}
}
}
}
}
.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;
}
.img-nodata {
position: relative;
top: 0;
left: 50%;
transform: translate(-50%, 0);
width: 352rpx;
height: 338rpx;
margin-bottom: 60rpx;
}
</style>
+287
View File
@@ -0,0 +1,287 @@
<template>
<view class="projects">
<view class="tabs-wrap">
<view
@click="handleTab(item.value)"
class="tab-item"
:class="{
'tab-isActived': actived === item.value
}"
v-for="(item, index) in tabs"
:key="index">
<view
:class="{
'tab-isActived': actived === item.value,
'no-actived-1': actived === 2 && item.value === 1,
'no-actived-2': actived === 1 && item.value === 2,
'no-actived-3': actived === 3 && item.value === 2,
'no-actived-4': actived === 2 && item.value === 3,
}"
>
{{ item.name }}
</view>
</view>
</view>
<view
v-if="tabs.length > 0"
class="content v12-justify-center"
:class="{
'first-one': actived === 1,
'last-one': actived === 3
}"
>
<view v-if="items.length > 0" class="v12-d-grid-columns-2 v12-gap-10">
<view v-for="(item, index) in items" :key="index" class="store-card" @click="toStore(item.hotelId)">
<view class="cover-box">
<image
v-if="item.coverType === 1"
class="town-cover"
:src="item.cover"
mode="aspectFit|aspectFill|widthFix"></image>
<video
v-if="item.coverType === 2"
play-btn-position="center"
:show-fullscreen-btn="false"
class="town-cover"
:src="item.cover"
:show-play-btn="false"
:show-center-play-btn="false"
controls
:poster="item.cover + '?vframe/jpg/offset/1'"></video>
<view class="name-box">
<image
:src="webUrl + '/home/icon-location.png'"
class="icon"
/>
<view class="one-t">
{{ item.cityName }}
</view>
</view>
</view>
<view class="v12-pa-2 card-bottom">
<view class="v12-dark-text v12-font-bold v12-font-30 more-t v12-pb-1 v12-mb-2">{{ item.content }}</view>
<view class="v12-align-center">
<view class="avtor">
<image class="avtor" :src="item.logo" mode="scaleToFill"></image>
</view>
<view class="v12-secondary-dark-text v12-font-28 v12-ml-3 one-t">{{ item.hotelName }}</view>
</view>
</view>
</view>
</view>
<image
v-if="items.length === 0"
:src="webUrl + '/orderIcon/wu.png'"
class="img-nodata"
style="left: 25%;"
mode="scaleToFill"
/>
</view>
<image
v-if="tabs.length === 0"
:src="webUrl + '/orderIcon/wu.png'"
class="img-nodata"
mode="scaleToFill"
/>
</view>
</template>
<script>
export default {
props: {
info: {
default:() => {}
}
},
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
actived: 1,
items: [],
itemsMap: {
1: 'project1Hotels',
2: 'project2Hotels',
3: 'project3Hotels'
}
}
},
watch: {
info(value) {
this.items = value && value[this.itemsMap[this.actived]]
},
actived: {
handler(value) {
this.items = this.info && this.info[this.itemsMap[value]]
},
deep: true,
immediate: true
}
},
computed: {
tabs() {
return this.info && [
{name: this.info.project1Name, value: 1},
{name: this.info.project2Name, value: 2},
{name: this.info.project3Name, value: 3},
] || []
}
},
methods: {
handleTab(value) {
this.actived = value
},
toStore(id) {
if (!id) {
return
}
uni.navigateTo({
url: '/pagesInn/inn/innHome?id=' + id
})
},
}
}
</script>
<style lang="scss" scoped>
.icon {
display: block;
width: 28rpx;
height: 28rpx;
margin: 0 10rpx 0 0;
}
.name-box{
color: #fff;
position: absolute;
left: 20rpx;
bottom: 20rpx;
font-size: 28rpx;
position: absolute;
bottom: 0;
left: 0;
right: 0;
z-index: 5;
display: flex;
align-items: flex-end;
height: 60rpx;
padding: 0 16rpx 16rpx 16rpx;
border-radius: 0rpx 0rpx 16rpx 16rpx;
box-sizing: border-box;
font-size: 24rpx;
line-height: 28rpx;
color: #fff;
background: linear-gradient(180deg, rgba(0,0,0,0) 0%, #000000 100%);
.icon {
display: block;
width: 28rpx;
height: 28rpx;
margin: 0 10rpx 0 0;
}
.one-t{
width: 240rpx !important;
}
}
.cover-box{
position: relative;
height: 316rpx;
}
.img-nodata {
position: relative;
top: 0;
left: 50%;
transform: translate(-50%, 0);
width: 352rpx;
height: 338rpx;
margin-bottom: 60rpx;
}
.card-bottom{
display: flex;
flex-direction: column;
justify-content: space-between;
height: calc(100% - 356rpx);
}
.avtor{
width: 52rpx;
height: 52rpx;
background: #eee;
border-radius: 50%;
}
.town-cover{
height: 316rpx;
width: 316rpx;
border-radius: 30rpx;
background: rgba(77,39,39,0.1);
}
.store-card{
width: 316rpx;
border-radius: 30rpx;
}
.tab-icon{
height: 30rpx;
width: 30rpx;
margin-right: 10rpx;
}
.fit-box-inner{
background: #f0f0f0;
width: initial;
height: inherit;
width: 40rpx;
}
.first-one{
border-radius: 0 24rpx 24rpx 24rpx !important;
}
.last-one{
border-radius: 24rpx 0 24rpx 24rpx !important;
}
.fit-box{
width: 40rpx;
height: initial;
background: #fff;
display: flex;
}
.projects{
padding: 20rpx;
}
.tabs-wrap{
display: flex;
justify-content: space-between;
}
.tab-item{
text-align: center;
flex: 1;
font-size: 32rpx;
font-weight: bold;
background: #fff;
view{
padding: 20rpx 0;
background: #f0f0f0;
width: inherit;
height: inherit;
display: flex;
justify-content: center;
align-items: center
}
}
.no-actived-1{
border-radius: 0 0 24rpx 0 !important;
}
.no-actived-2{
border-radius: 0 0 0 24rpx !important;
}
.no-actived-3{
border-radius: 0 0 24rpx 0 !important;
}
.no-actived-4{
border-radius: 0 0 0 24rpx !important;
}
.tab-isActived{
background: #fff !important;
border-radius: 24rpx 24rpx 0 0 !important;
position: relative;
}
.content{
background: #fff;
padding: 20rpx 10rpx;
border-radius: 24rpx;
}
</style>
+131
View File
@@ -0,0 +1,131 @@
<template>
<view class="service">
<view class="map-cont">
<map
:longitude="info.longitude"
:latitude="info.latitude"
:markers="[{id:1, latitude: info.latitude,longitude: info.longitude,width: 20, height: 25, iconPath: webUrl + '/page/qianxian/icon-location.png'}]"
style="width: 100%;height: 100%; border-radius: 20rpx;"
/>
</view>
<view class="v12-px-3 v12-font-32 v12-font-bold">{{ info.name || '' }}</view>
<view class="info-wrap">
<view>
<view class="v12-font-28 v12-mb-1 v12-dark1-text">{{ info.openTime || '' }}</view>
<view class="v12-font-28 v12-mb-1 v12-dark1-text">{{ info.address || '' }}</view>
<view class="v12-font-28 v12-mb-1 v12-dark1-text v12-d-flex">
<u-icon size="16" :name="webUrl + '/orderIcon/laba.png'"></u-icon>
{{ info.announcement || '' }}
</view>
</view>
<view class="action-wrap">
<view @click="showLocation">
<view>
<image :src="webUrl + '/page/qianxian/icon-addr.png'" class="img" />
</view>
<view class="text-center">导航</view>
</view>
<view @click="call">
<view>
<image :src="webUrl + '/page/qianxian/icon-phone.png'" class="img" />
</view>
<view class="text-center">咨询</view>
</view>
</view>
</view>
<view style="padding: 0 20rpx;"><u-divider></u-divider></view>
<view class="intro-wrap">
<view class="v12-dark-text v12-font-bold">
简介
</view>
<view class="intro-text">
<rich-text class="" :nodes="info.desc"></rich-text>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
info: {
default: () => {}
}
},
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
}
},
methods: {
showLocation() {
if (!this.info.latitude || !this.info.longitude) {
this.$dialog.error('暂无位置信息')
} else {
uni.openLocation({
latitude: this.info.latitude,
longitude: this.info.longitude
})
}
},
call() {
if (this.info.tel) {
uni.makePhoneCall({
phoneNumber: this.info.tel
})
} else {
this.$dialog.error('电话为空')
}
},
}
}
</script>
<style lang="scss" scoped>
.service {
background: #fff;
margin-top: 20rpx;
border-radius: 30rpx;
padding: 20rpx;
}
.intro-text{
color: #999;
font-size: 24rpx;
margin-top: 20rpx;
}
.intro-wrap{
padding: 0 20rpx 20rpx;
}
.action-wrap{
display: flex;
align-items: center;
.text-center{
text-align: center;
font-size: 24rpx;
color: #666;
}
}
.info-wrap{
display: flex;
justify-content: space-between;
padding: 20rpx 20rpx 0;
}
.service{
position: relative;
}
.map-cont {
height: 400rpx;
border-radius: 20rpx;
background: #fff;
padding: 20rpx;
box-sizing: border-box;
overflow: hidden;
}
.img{
display: block;
width: 64rpx;
height: 64rpx;
margin: 0 0 16rpx 16rpx;
}
</style>
+313
View File
@@ -0,0 +1,313 @@
<template>
<view class="town">
<hx-navbar :back="true" :fixed="true" color="#fff" :statusBar="true" transparent="hidden" barPlaceholder="hidden" />
<view class="top-img">
<image v-if="townInfo.coverType === 1" :src="townInfo.cover" mode="scaleToFill" class="img"></image>
<video
v-if="townInfo.coverType === 2"
id="videoCover"
class="img"
:src="townInfo.cover"
autoplay
play-btn-position="center"
:show-fullscreen-btn="false"
@play="handlePlay"
> </video>
</view>
<view class="top-intro">
<view class="intro-title v12-pa-3">
<text class="v12-font-bold v12-font-40">{{ townInfo.name }}</text>
<text class="aaaa" v-if="townInfo.qualityRating">
{{ townInfo.qualityRating }}
</text>
</view>
<view class="shareBtn" @click="shareImg"><u-icon name="share-square" color="#C52733"></u-icon>分享给好友</view>
<!-- <u-line dashed></u-line> -->
<view v-if="townInfo.intro" class="v12-pa-3 intro-content">
<u-read-more :toggle="true" showHeight="200">
{{ townInfo.intro }}
</u-read-more>
</view>
</view>
<view class="tabs-wrap">
<view @click="handleTab(item.value)" :class="{ 'tab-actived' : item.value === actived }" class="tab-item" v-for="(item, index) in tabs" :key="index">{{ item.name }}</view>
</view>
<view class="list-wrap">
<view v-if="actived === 1">
<projects :info="townInfo.projectInfo"></projects>
</view>
<view v-if="actived === 2">
<culture :list="townInfo.cultureInfo.cultureImages"></culture>
</view>
<view v-if="actived === 3">
<information ref="information" :infoArray="activeties" @video="handleVideo"></information>
</view>
<view v-if="actived === 4">
<service :info="{...townInfo.serviceInfo, name: townInfo.name}"></service>
</view>
</view>
<!-- 分享 -->
<u-popup
:show="showShare"
mode="center"
bgColor="transparent"
>
<view class="box-share">
<view class="box-img">
<image
:src="webUrl + '/20230608112219219303.png'"
class="icon"
@click="closeShare"
/>
<image :src="posterUrl" class="main-img" mode="widthFix" />
</view>
<image
:src="webUrl + '/20230608112210135038.png'"
mode="widthFix"
class="btn"
@click="saveImg"
/>
</view>
</u-popup>
</view>
</template>
<script>
import { getAncientTownInfo, getAncientTownActive, shareTown } from "@/api/inn.js"
import {getUrlParam} from '@/utils/common.js'
import culture from './components/culture.vue'
import information from './components/information.vue'
import service from './components/service.vue'
import projects from './components/projects.vue'
export default {
components: {
culture,
information,
service,
projects
},
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
showShare: false,
townInfo: {},
posterUrl: '',
activeties: [],
id: '',
actived: 1,
tabs: [
{name: '项目', value: 1},
{name: '文化', value: 2},
{name: '活动', value: 3},
{name: '服务', value: 4},
],
}
},
onLoad(opts) {
this.id = opts.id
const obj = uni.getEnterOptionsSync()
if(opts.scene || obj.query.scene) {
const query = opts ? decodeURIComponent(opts.scene) : decodeURIComponent(obj.query.scene)
this.id = getUrlParam(query, 'id') || null
}
this.getInfo()
this.getActive()
},
methods: {
handlePlay() {
this.$refs.information.handlePlayer()
},
handleVideo() {
const videoCtx = uni.createVideoContext('videoCover', this)
videoCtx.pause()
},
shareImg() {
uni.showLoading()
shareTown(this.id).then(res => {
this.posterUrl = res.data
this.showShare = !this.showShare
}).finally(() => {
uni.hideLoading()
})
},
closeShare() {
this.showShare = false
},
saveImg() {
const _this = this
uni.getSetting({
success: getRes => {
if (getRes.authSetting["scope.writePhotosAlbum"]) {
_this.downloadImage()
} else {
uni.authorize({
scope: "scope.writePhotosAlbum",
success: () => {
_this.downloadImage()
},
fail: () => {
uni.openSetting({
success: openRes => {
console.log(typeof openRes, openRes)
},
fail: () => {
uni.showToast({
title: "请在设置中打开对应权限",
icon: "none"
})
}
})
}
})
}
},
fail: (err) => {
console.log(err, 2)
}
})
},
downloadImage() {
const _this = this
const randomID = () => Math.random().toString(36).substring(2)
uni.downloadFile({
url: this.posterUrl, // 网络图片的地址
filePath: wx.env.USER_DATA_PATH + "/share_" + randomID() + ".png", // 指定的本地文件路径
success: downRes => {
uni.saveImageToPhotosAlbum({
filePath: downRes.filePath, // 临时文件地址
success: function () {
uni.showToast({
title: "保存成功",
icon: "success",
success() {
_this.showShare = false
}
})
},
fail: function (err) {
uni.showToast({
title: err,
icon: "none"
})
}
})
},
fail: function (err) {
uni.showToast({
title: err.errMsg,
icon: "error"
})
}
})
},
getInfo() {
uni.showLoading()
getAncientTownInfo(this.id).then(res => {
this.townInfo = res.data
}).finally(() => {
uni.hideLoading()
})
},
getActive() {
const params = {
ancientTownId: this.id
}
getAncientTownActive(params).then(res => {
this.activeties = res.data.records || []
})
},
handleTab(value) {
this.actived = value
},
}
}
</script>
<style lang="less" scoped>
@import "@/assets/css/store.less";
.shareBtn{
width: fit-content;
padding: 5rpx 15rpx;
background: #edbfc2;
box-shadow: 0rpx 4rpx 4rpx rgba(0,0,0,0.16);
border-radius: 24rpx 0rpx 0rpx 24rpx;
color: #C52733;
font-weight: bold;
font-size: 28rpx;
position: absolute;
right: 0;
top: 24rpx;
display: flex;
align-items: center;
}
.town{
min-height: 100vh;
background: #f0f0f0;
}
.tab-actived{
color: #fff;
font-weight: bold;
background: linear-gradient(to right, #C52733 0%, rgba(211,92,101,0.91) 54%, rgba(255,255,255,0.62) 100%);
border-radius: 38rpx 0rpx 0 38rpx;
padding: 0 20rpx;
}
.tabs-wrap{
display: flex;
justify-content: space-around;
padding: 20rpx 20rpx 0;
color: #333;
font-weight: bold;
font-size: 36rpx;
}
.intro-content{
letter-spacing: 2.5px;
line-height: 40rpx;
font-size: 28rpx;
color: #666;
}
.aaaa{
background: #F1B61A;
color: #fff;
border-radius: 100px;
padding: 0 10rpx;
font-size: 24rpx;
margin-left: 10rpx;
}
.top-intro{
width: 100%;
min-height: 360rpx;
background: #fff;
box-shadow: 0rpx 0rpx 12rpx rgba(0,0,0,0.13);
border-radius: 30rpx;
margin-top: -30rpx;
position: relative;
z-index: 11;
}
.top-img{
width: 100%;
background: #fff;
height: 560rpx;
position: relative;
.img{
height: inherit;
width: 100%;
}
.img1{
z-index: 10;
position: absolute;
top: 0;
left: 0;
border-radius: 30rpx;
}
.bg{
height: 100%;
width: 50%;
background: #fff;
position: absolute;
top: -30rpx;
right: 0;
z-index: 9;
}
}
</style>
+4 -3
View File
@@ -43,9 +43,9 @@
<view class="v12-primary-text v12-primary-border v12-radius-6 v12-font-18 v12-px-1">{{ historyItem.couponName }}</view>
</view>
<view class="v12-justify-between v12-mt-2 price">
<view class="v12-font-bold v12-primary-text v12-align-center">
<view class="v12-font-bold v12-primary-text" :class="{'v12-align-center': (historyItem.price).toString().length < 5 && (historyItem.otPrice).toString().length < 5 }">
<text class="v12-font-16"></text>
<text class="v12-font-24">{{ historyItem.price }}</text>
<text class="v12-font-24 v12-mr-1">{{ historyItem.price }}</text>
<view class="ot-price v12-font-weight-400">
<text class="v12-font-22"></text>
<text class="v12-font-22">{{ historyItem.otPrice }}</text>
@@ -254,8 +254,9 @@ export default {
padding: 12rpx 12rpx 20rpx 12rpx;
.price {
line-height: 34rpx;
align-items: flex-end;
.ot-price {
margin: 0 0 0 10rpx;
// margin: 0 0 0 10rpx;
color: #CBCBCB;
position: relative;
}
+38 -8
View File
@@ -32,7 +32,9 @@
:loop="false"
object-fit="contain"
play-btn-position="center"
id="coverVideo"
class="video"
@play="coverPlay"
/>
</view>
</view>
@@ -79,14 +81,14 @@
:src="webUrl + '/icon/icon-star-on.png'"
mode="scaleToFill"
class="icon"
@click="doneFavorite"
@click="doneFavorite(store.hasFavorite)"
/>
<image
v-else
:src="webUrl + '/icon/icon-star-off.png'"
mode="scaleToFill"
class="icon"
@click="doneFavorite"
@click="doneFavorite(store.hasFavorite)"
/>
<text>{{ store.favoriteCount }}</text>
</view>
@@ -230,7 +232,8 @@
play-btn-position="center"
:show-fullscreen-btn="false"
class="video-item"
@play="infoItemViewClick(item)"
:id="'video-item' + index"
@play="infoItemViewClick(item, index)"
/>
</view>
<view v-else>
@@ -337,7 +340,7 @@
</template>
<script>
import { getFarmerShop, setFarmerShopZan, getFarmerShopNews, setFarmerShopCollection } from '@/api/farmer'
import { getFarmerShop, setFarmerShopZan, getFarmerShopNews, removeFarmerShopCollection, setFarmerShopCollection } from '@/api/farmer'
import { postCountyFamousNewsZan, postCountyFamousNewsView } from '@/api/qianxian'
import imgBox from '@/components/imageTypeSet/imagebox.vue'
export default {
@@ -363,7 +366,8 @@ export default {
activeIndex: 0,
isLoadInfoListSuccess: false,
picColumnWidth: '325rpx',
infoArray: []
infoArray: [],
videoPlayers: []
}
},
onPageScroll(e) {
@@ -440,7 +444,32 @@ export default {
}
})
},
infoItemViewClick(item) {
coverPlay(){
this.videoPlayers.forEach(player => {
const playerCtx = uni.createVideoContext(player, this)
playerCtx.pause()
})
},
infoItemViewClick(item, index) {
if(item.type === 2) {
const coverCtx = uni.createVideoContext('coverVideo', this)
coverCtx.pause()
const playerId = '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()
})
}
}
const params = {
countyFamousNewsId: item.id
}
@@ -485,11 +514,12 @@ export default {
}
})
},
doneFavorite() {
doneFavorite(has) {
const api = !has ? setFarmerShopCollection : removeFarmerShopCollection
const params = {
farmerShopId: this.id
}
setFarmerShopCollection(params).then(res => {
api(params).then(res => {
this.getFarmerData()
})
},
+32 -3
View File
@@ -31,9 +31,11 @@
:autoplay="true"
:controls="true"
:loop="false"
id="coverVideo"
object-fit="contain"
play-btn-position="center"
class="video"
@play="coverPlay"
/>
</view>
</view>
@@ -232,7 +234,8 @@
controls
play-btn-position="center"
class="video-item"
@play="infoItemViewClick(item)"
:id="'video-item' + index"
@play="infoItemViewClick(item, index)"
/>
</view>
<view v-else>
@@ -482,7 +485,8 @@ export default {
isLoadGoodListoSuccess: false,
isLoadInfoListSuccess: false,
pageKeyId: '',
shareImg: ''
shareImg: '',
videoPlayers: []
}
},
// 必须在页面加 onPageScroll(e){} ,才能滑动显示背景
@@ -665,7 +669,32 @@ export default {
infoClick: function (info) {
// this.$yrouter.push('/pagesInn/inn/innInfoDetail?id=' + info.id)
},
infoItemViewClick(item) {
coverPlay(){
this.videoPlayers.forEach(player => {
const playerCtx = uni.createVideoContext(player, this)
playerCtx.pause()
})
},
infoItemViewClick(item, index) {
if(item.type === 'NT_VIDEO') {
const coverCtx = uni.createVideoContext('coverVideo', this)
coverCtx.pause()
const playerId = '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()
})
}
}
uni.$u.debounce(() => {
hotelNewsView({ id: item.id }).finally(() => {
this.infoArray.map(info => {
+2 -2
View File
@@ -119,7 +119,7 @@
<template #label>
<u-upload
:fileList="pics"
:maxCount="9"
:maxCount="99999"
:disabled="reviewing"
name="pics"
multiple
@@ -447,7 +447,7 @@ export default {
'coverVideo': {
type: 'string',
required: true,
message: '请上传店铺视频面',
message: '请上传店铺视频面',
trigger: ['blur', 'change']
},
'logo': {
+2 -2
View File
@@ -297,7 +297,7 @@
<template #title>
<u-upload
:fileList="pics"
:maxCount="9"
:maxCount="99999"
:disabled="reviewing"
name="pics"
multiple
@@ -625,7 +625,7 @@ export default {
'coverVideo': {
type: 'string',
required: true,
message: '请上传店铺视频面',
message: '请上传店铺视频面',
trigger: ['blur', 'change']
},
'logo': {
+130 -20
View File
@@ -33,6 +33,8 @@
object-fit="contain"
play-btn-position="center"
class="video"
id="coverVideo"
@play="coverPlay"
/>
</view>
</view>
@@ -171,12 +173,24 @@
</view>
<view class="info-item-body">
<img-box
v-if="item.type === 1"
:imgList="item.images"
:num="item.images.length"
:img-radius="10"
style="width: 100%;"
@click="infoItemViewClick(item)"
/>
<video
v-else
@play="infoItemViewClick(item, index)"
play-btn-position="center"
:show-fullscreen-btn="false"
class="video-item v12-mt-0"
:src="item.video"
objectFit
controls
:id="'video-item' + index"
:poster="item.video + '?vframe/jpg/offset/1'"></video>
</view>
<view class="info-item-bottom">
<view class="time">
@@ -302,6 +316,7 @@
<goo-skeleton v-else />
</view>
<!-- 产业 -->
<view
v-if="activeIndex === 0"
class="industry-section"
@@ -456,6 +471,11 @@
</view>
</view>
<view class="village-wrap">
<view class="v12-pa-2 sale-wrap">
<view :class="{'saleActive' : saleActived === sale.id}" v-for="(sale, i) in saleList" :key="i" @click="handleSale(sale)">
{{ sale.name }}
</view>
</view>
<view v-if="villageList.length > 0" class="village-list">
<view
v-for="(village, villageIndex) in villageList"
@@ -565,7 +585,7 @@
<image :src="item.cover" v-if="item.coverType === 1" class="img" mode="heightFix|widthFix"></image>
<video :src="item.cover" v-else :show-center-play-btn="false" :show-fullscreen-btn="false" :show-play-btn="false" class="img" :poster="item.cover + '?vframe/jpg/offset/1'"></video>
<image
:src="webUrl + '/orderIcon/farmer.png'"
:src="webUrl + '/orderIcon/nm.png'"
class="mark-img"
/>
</view>
@@ -630,7 +650,8 @@ import {
getCountyFamousInvestmentFile,
getCountyFamousVillage,
getCountyFamousCityDetail,
getShareImg
getShareImg,
getSaleList
} from '@/api/qianxian'
import {formatDateTime} from '@/utils'
import {getUrlParam} from '@/utils/common.js'
@@ -647,11 +668,13 @@ export default {
mixins: [pageListenMixins],
data() {
return {
saleActived: null,
webUrl: this.$VUE_APP_RESOURCES_URL,
isLoad: false,
activeIndex: 0,
loading: false,
scrollData: {},
saleList: [],
inn: {
cityName: '',
pics: [],
@@ -704,6 +727,7 @@ export default {
// 产品
leftList: [],
rightList: [],
videoPlayers:[]
}
},
// 必须在页面加 onPageScroll(e){} ,才能滑动显示背景
@@ -729,8 +753,36 @@ export default {
this.getGuideReq()
// this.initPoster()
this.getListReq()
this.getsaleList()
},
methods: {
handleSale(e) {
if(this.saleActived === e.id) {
this.saleActived = null
} else {
this.saleActived = e.id
}
getCountyFamousVillage({
countyFamousDataId: this.id,
categoryId: this.saleActived,
page: 1,
limit: 9999
}).then(res => {
const { success, data } = res
if (success) {
this.villageList = data.records || []
}
})
},
getsaleList() {
const params = {
countyFamousDataId: this.id
}
getSaleList(params).then(res => {
this.saleList = res.data || []
})
},
goStore(item) {
if (item.farmerShopId === 0) {
uni.showToast({
@@ -755,7 +807,7 @@ export default {
}
})
},
getListReq() {
getListReq(id) {
// getPoster(this.id).then(({data}) => this.posterUrl = data)
getCountyFamousIndustry({
countyFamousDataId: this.id,
@@ -789,6 +841,7 @@ export default {
})
getCountyFamousVillage({
countyFamousDataId: this.id,
categoryId: id,
page: 1,
limit: 9999
}).then(res => {
@@ -802,22 +855,28 @@ export default {
if (success) {
const products = data.products || []
const farmerShops = data.farmerShops || []
this.leftList = this.sortProductsAndStores(products, farmerShops)
console.log(this.leftList);
// products.map((item, index) => {
// item.isOldBrand = 0
// item.isLandmarkGoods = 0
// if (index % 2 === 0) {
// this.leftList.push(item)
// }
// if (index % 2 === 1) {
// item.isFarmer = 1
// this.rightList.push(item)
// }
// })
this.leftList = this.newSort(products, farmerShops)
}
})
},
newSort(a, b) {
const minLen = Math.min(a.length, b.length)
const megerMap = []
for (let i = 0; i < minLen; i ++) {
if(i % 2 === 0) {
megerMap.push(a[i], b[i])
} else {
megerMap.push(b[i], a[i])
}
}
if(a.length > minLen) {
megerMap.push(...a.slice(minLen))
}
if(b.length > minLen) {
megerMap.push(...b.slice(minLen))
}
return megerMap
},
shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
let j = Math.floor(Math.random() * (i + 1));
@@ -1050,7 +1109,33 @@ export default {
infoClick(info) {
// this.$yrouter.push('/pagesInn/inn/innInfoDetail?id=' + info.id)
},
infoItemViewClick(item) {
coverPlay(){
this.videoPlayers.forEach(player => {
const playerCtx = uni.createVideoContext(player, this)
playerCtx.pause()
})
},
infoItemViewClick(item, index) {
if(item.type === 2) {
const coverCtx = uni.createVideoContext('coverVideo', this)
coverCtx.pause()
const playerId = '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()
})
}
this.$emit('video')
}
uni.$u.debounce(() => {
postCountyFamousNewsView({ countyFamousNewsId: item.id }).finally(() => {
this.infoArray.map(info => {
@@ -1156,6 +1241,31 @@ export default {
<style scoped lang="less">
@import "@/assets/css/store.less";
.saleActive{
background: #C52733 !important;
color: #fff !important;
}
.sale-wrap{
display: flex;
align-items: center;
flex-wrap: wrap;
justify-content: flex-start;
view {
background: #f5f5f5;
border-radius: 6rpx;
padding: 6rpx 16rpx;
margin-right: 10rpx;
margin-bottom: 10rpx;
font-size: 26rpx;
font-weight: bold;
white-space: nowrap;
}
}
.video-item {
width: 100%;
height: 400rpx;
border-radius: 10rpx;
}
.focus-img {
position: relative;
.img {
@@ -1172,8 +1282,8 @@ export default {
right: 0;
z-index: 3;
display: block;
width: 125rpx;
height: 83rpx;
width: 100%;
height: 100%;
border-radius: 0 25rpx 0 0;
}
}
@@ -1733,7 +1843,7 @@ export default {
}
.village-wrap {
height: 980rpx;
padding: 16rpx 0 0 0;
// padding: 16rpx 0 0 0;
overflow-y: auto;
}
.village-list {
@@ -33,6 +33,8 @@
object-fit="contain"
play-btn-position="center"
class="video"
id="coverVideo"
@play="coverPlay"
/>
</view>
</view>
@@ -175,6 +177,8 @@
controls
play-btn-position="center"
class="video-item"
:id='"video-item" + index'
@play="handleVideo(item, index)"
/>
</view>
<view v-else>
@@ -239,7 +243,8 @@ export default {
// 资讯
infoArray: [],
isLoadInfoListSuccess: false,
pageKeyId: ''
pageKeyId: '',
videoPlayers: []
}
},
onPageScroll(e) {
@@ -252,6 +257,33 @@ export default {
this.getInfoReq()
},
methods: {
coverPlay(){
this.videoPlayers.forEach(player => {
const playerCtx = uni.createVideoContext(player, this)
playerCtx.pause()
})
},
handleVideo(item, index) {
if(item.type === 2) {
const coverCtx = uni.createVideoContext('coverVideo', this)
coverCtx.pause()
const playerId = '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()
})
}
}
},
getShopDetailReq() {
const _this = this
getCountyFamousVillageDetail(_this.id).then((res) => {
+1
View File
@@ -257,6 +257,7 @@ export default {
text-align: center;
font-size: 12px;
color: #fff;
width: 180rpx;
.good-img {
width: 90px;
height: 90px;
+2 -2
View File
@@ -38,7 +38,7 @@
duration="10000"
interval="3000"
>
<swiper-item v-for="(item, index) in foodItems" :key="index">
<swiper-item v-for="(item, index) in foodItems" :key="index" @click="toDetails(item.id)">
<view class="trave-item-wrap v12-mr-3 v12-mt-3">
<view class="trave-item">
<image
@@ -47,7 +47,7 @@
:src="item.indexImage"
></image>
</view>
<view class="trave-btn" @click="toDetails(item.id)">
<view class="trave-btn">
<text class="one-t">{{ item.name }}</text>
<image
:src="webUrl + '/orderIcon/arrow.png'"
+2 -2
View File
@@ -17,12 +17,12 @@
</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">
<view class="trave-item v12-mr-3 v12-mt-3" @click="toStore(item.hotelId)">
<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="flase" :show-play-btn="false" v-if="item.coverType === 2"></video>
</view>
<view class="trave-btn" @click="toStore(item.hotelId)">
<view class="trave-btn">
<text>旅居预约</text>
<image :src="webUrl + '/orderIcon/arrow.png'" class="arrow-icon v12-ml-1"></image>
</view>
+57 -44
View File
@@ -1,50 +1,81 @@
<template>
<view class="pkg-product-heritage">
<image style="width: 100%" :src="topImage" mode="widthFix" />
<view class="main-box">
<image style="width: 100%" :src="backgroundImage" mode="widthFix" />
<view
class="item"
:style="{ left: item.gx + 'rpx', top: item.gy + 'rpx' }"
v-for="(item, index) in contents"
:key="index"
@click="goDetails(item)"
>
<image
class="img-item"
:src="item.image"
:class="{ unlink: !item.isLink }"
/>
<!-- <view
class="v12-text-center v12-white-text v12-radius-80 v12-px-1 title"
:class="{
'v12-primary': item.isLink,
'un-actived': !item.isLink,
}"
>
{{ item.title }}</view
> -->
</view>
</view>
</view>
</template>
<script>
import {getICH} from '@/api/product'
import { pageListenMixins } from '@/mixins/pageListenMixins'
import { getICH } from "@/api/product";
import { pageListenMixins } from "@/mixins/pageListenMixins";
export default {
name: 'HeritagePage',
name: "HeritagePage",
mixins: [pageListenMixins],
data() {
return {
contents: [],
topImage: '',
backgroundImage: '',
topImage: "",
backgroundImage: "",
bgImgWidth: 0,
pageKeyId: Object.freeze('ichIndex')
}
pageKeyId: Object.freeze("ichIndex"),
};
},
computed: {
scale() {
return 750 / this.bgImgWidth
}
return 750 / this.bgImgWidth;
},
},
onLoad() {
this.init()
this.init();
},
methods: {
init() {
getICH().then(({data}) => {
getICH().then(({ data }) => {
this.contents = data.contents;
this.topImage = data.topImage;
this.backgroundImage = data.backgroundImage;
this.bgImgWidth = data.backgroundImageWidth;
this.calcPosition();
})
});
},
// 计算位置
calcPosition() {
this.contents?.forEach(item => {
item.gx = item.x * this.scale
item.gy = item.y * this.scale
})
this.contents?.forEach((item) => {
item.gx = item.x * this.scale;
item.gy = item.y * this.scale;
});
},
goDetails(item) {
if (!item.isLink) return
if (!item.isLink) return;
// 1-视频,2-图文(可配置商品),3-商品+视频
uni.navigateTo({
url: '/pkg_product/views/heritage/index?id=' + item.id
})
url: "/pkg_product/views/heritage/index?id=" + item.id,
});
// if (item.type === 1) {
// uni.navigateTo({
// url: '/pkg_product/views/heritage/index?id=' + item.id
@@ -58,36 +89,18 @@ export default {
// url: '/pkg_product/views/heritage/index?id=' + item.id
// })
// }
}
}
}
},
},
};
</script>
<template>
<view class="pkg-product-heritage">
<image style="width: 100%" :src="topImage" mode="widthFix"/>
<view class="main-box">
<image style="width: 100%" :src="backgroundImage" mode="widthFix"/>
<view class="item" :style="{'left':item.gx+'rpx','top':item.gy+'rpx'}" v-for="(item,index) in contents"
:key="index" @click="goDetails(item)">
<image class="img-item" :src="item.image" :class="{'unlink': !item.isLink}"/>
<view
class=" v12-text-center v12-white-text v12-radius-80 v12-px-1 title"
:class="{
'v12-primary': item.isLink,
'un-actived': !item.isLink
}">
{{ item.title }}</view>
</view>
</view>
</view>
</template>
<style scoped lang="less">
.unlink{
.unlink {
filter: grayscale(100%);
}
.un-actived{
.un-actived {
background: #494949 !important;
background-color: #494949 !important;
}
@@ -119,4 +132,4 @@ export default {
}
}
}
</style>
</style>
+4 -5
View File
@@ -28,11 +28,9 @@
<view class="card-item" v-for="(item, i) in details.pageA.images" :key="i" @click="viewImg(item)">
<image class="card-item-img" :src="item.image" mode="aspectFit|aspectFill|widthFix" lazy-load="false"></image>
<view class="v12-justify-center">
<view class="one-t p-name">
<view class="more-t p-name">
{{ item.imageText }}
</view>
</view>
</view>
</view>
@@ -49,7 +47,8 @@
<!-- -->
<view class="card-item v12-white v12-radius-20 column-flex" v-for="(item, index) in details.pageB.hotels" :key="index" @click="toStore(item)">
<view>
<image class="card-item-img" :src="item.cover" mode="aspectFit|aspectFill|widthFix" lazy-load="false"></image>
<image v-if="item.coverType === 1" class="card-item-img" :src="item.cover" mode="aspectFit|aspectFill|widthFix" lazy-load="false"></image>
<video v-if="item.coverType === 2" class="card-item-img" :show-center-play-btn="false" :show-fullscreen-btn="false" :show-play-btn="false" :src="item.cover" :poster="item.cover + '?vframe/jpg/offset/1'"></video>
<view class="more-t v12-font-28 v12-font-bold v12-px-2">
{{ item.content || '' }}
</view>
@@ -156,7 +155,7 @@ export default {
line-height: 70rpx;
}
.p-name{
max-width: 200rpx;
// max-width: 200rpx;
text-align: center;
}
.card-footer{
+1 -1
View File
@@ -27,7 +27,7 @@
</view>
</view>
<view class="wiper-wrap v12-mt-3">
<swiper v-if="contents.length > 0" class="" style="width: 100%;height: 400rpx" :autoplay="contents.length > 2" circular next-margin="400rpx">
<swiper v-if="contents.length > 0" class="" style="width: 100%;height: 400rpx" :autoplay="contents.length > 2" circular next-margin="400rpx" duration="10000" interval="3000">
<swiper-item v-for="(item, index) in contents" :key="index" @click="toDetails(item.ichContentId)">
<view class="wiper-item">
<image class="wiper-item" :src="item.cover" mode="aspectFit|aspectFill|widthFix" lazy-load="false"> </image>