Przeglądaj źródła

fix: 视频播放,商品排序

lxf 3 tygodni temu
rodzic
commit
bc85857921

+ 6 - 0
api/home.js

@@ -25,4 +25,10 @@ export default {
   fetchGoodsList(data) {
 	  return http.get('mini/farm_buy_goods/list', data)
   },
+  fetchGardenInfo(data) {
+	  return http.get('mini/z_farm_buy/farmBuyInfo', data)
+  },
+  fetchGardenDetail(data) {
+	  return http.get('mini/z_farm_buy_shop/get', data)
+  },
 }

+ 45 - 4
pages/tabBar/discover/discover.vue

@@ -8,8 +8,8 @@
 			</view>
 
 			<view class="type-wrap">
-				<up-scroll-list indicatorColor="#FF770033" indicatorActiveColor="#FF7700" :indicatorWidth="30"
-					:indicatorBarWidth="13">
+				<up-scroll-list :indicator="typeList.length>5" indicatorColor="#FF770033" indicatorActiveColor="#FF7700" :indicatorWidth="30"
+					:indicatorBarWidth="15">
 					<view class="item-type" :class="{'active': activeType === 0}" @click="handleSelectType(null, 0)">
 						<image class="type-img" :src="`${config.BASIC_IMG}home/type-icon.png`" alt="" />
 						<view class="type-text">
@@ -36,9 +36,19 @@
 				</view>
 				<view class="filter-item" :class="{'active': filterIndex === 1}" @click="selectFilter(1)">
 					价格
+					<div class="filter-icon">
+						<image v-show="filterIndex !== 1" style="width: 14px; height: 14px;padding-top: 2px;" :src="`${config.BASIC_IMG}home/filter-icon.png`" mode=""></image>
+						<image v-show="filterIndex === 1 && orderType===true" style="width: 14px; height: 14px;padding-top: 2px;" :src="`${config.BASIC_IMG}home/filter-icon-1.png`" mode=""></image>
+						<image v-show="filterIndex === 1 && orderType===false" style="width: 14px; height: 14px;padding-top: 2px;" :src="`${config.BASIC_IMG}home/filter-icon-2.png`" mode=""></image>
+					</div>
 				</view>
 				<view class="filter-item" :class="{'active': filterIndex === 2}" @click="selectFilter(2)">
 					销量
+					<div class="filter-icon">
+						<image v-show="filterIndex !== 2" style="width: 14px; height: 14px;padding-top: 2px;" :src="`${config.BASIC_IMG}home/filter-icon.png`" mode=""></image>
+						<image v-show="filterIndex === 2 && orderType===true" style="width: 14px; height: 14px;padding-top: 2px;" :src="`${config.BASIC_IMG}home/filter-icon-1.png`" mode=""></image>
+						<image v-show="filterIndex === 2 && orderType===false" style="width: 14px; height: 14px;padding-top: 2px;" :src="`${config.BASIC_IMG}home/filter-icon-2.png`" mode=""></image>
+					</div>
 				</view>
 			</view>
 
@@ -83,6 +93,7 @@
 
 	const filterIndex = ref(0)
 	const activeType = ref(0)
+	const orderType = ref(true)
 
 	const discoverData = ref([])
 	let sortObj = {
@@ -92,8 +103,12 @@
 	}
 
 	function selectFilter(i) {
+		if (filterIndex.value !== i) {
+			orderType.value = false
+		}
 		filterIndex.value = i
 		sort.value = sortObj[i]
+		orderType.value = !orderType.value
 		getGoodsList()
 	}
 
@@ -109,17 +124,23 @@
 		HOME.fetchTypeList().then(({
 			data
 		}) => {
-			typeList.value = data
+			typeList.value = [...data, ...data]
 		})
 	}
 
 	const sort = ref("id")
 	function getGoodsList(param) {
 		let params = {...param, sort: sort.value}
+		if (filterIndex.value !== 0) {
+			params = {
+				...params,
+				order: orderType.value ? "asc" : "desc"
+			}
+		}
 		HOME.fetchGoodsList(params).then(({
 			data
 		}) => {
-			discoverData.value = data
+			discoverData.value = [...data, ...data]
 		})
 	}
 	
@@ -139,6 +160,7 @@
 	.discover-page {
 		padding: 0;
 		background: #F2F3F5;
+		height: 100vh;
 
 		.discover-top {
 			padding: 20rpx 24rpx;
@@ -199,10 +221,20 @@
 				border-radius: 16rpx;
 				height: 200rpx;
 				box-sizing: border-box;
+				
+				// 覆盖 up-scroll-list 的默认样式,实现两端对齐
+				:deep(.u-scroll-list__scroll-view__content) {
+					display: flex;
+					justify-content: space-between;
+					align-items: center;
+					width: 100%;
+					min-width: 100%;
+				}
 
 				.item-type {
 					text-align: center;
 					font-size: 24rpx;
+					flex-shrink: 0;
 
 					.type-img {
 						width: 92rpx;
@@ -230,6 +262,10 @@
 
 		.discover-content {
 			padding: 0rpx 24rpx 24rpx;
+			height: calc(100% - 352rpx);
+			overflow: auto;
+			background: #F2F3F5;
+			box-sizing: border-box;
 
 			.discover-filter {
 				color: #A6A6A6;
@@ -239,10 +275,15 @@
 
 				.filter-item {
 					padding: 12rpx 20rpx;
+					display: flex;
+					align-items: center;
 
 					&.active {
 						color: #000000;
 					}
+					.filter-icon {
+						padding-left: 4rpx;
+					}
 				}
 			}
 

+ 139 - 14
pages/tabBar/home/home.vue

@@ -31,7 +31,14 @@
 			</view>
 		</view>
 		<view class="type-wrap">
-			 <up-scroll-list indicatorColor="#F3C11D33" indicatorActiveColor="#F3C11D" :indicatorWidth="30" :indicatorBarWidth="13">
+			 <up-scroll-list 
+				:indicator="typeList.length>5" 
+				indicatorColor="#F3C11D33" 
+				indicatorActiveColor="#F3C11D" 
+				:indicatorWidth="30" 
+				:indicatorBarWidth="13"
+				ref="scrollListRef"
+			>
 				<view class="item-type">
 					<image class="type-img" :src="`${config.BASIC_IMG}home/type-icon.png`" alt="" />
 					<view class="type-text">
@@ -48,8 +55,8 @@
 			</up-scroll-list>
 		</view>
 		<!-- 好味热卖 -->
-		<view class="home-hot">
-			<hot-component-vue :farmId="766"></hot-component-vue>
+		<view class="home-hot" v-if="gardenList && gardenList.length">
+			<hot-component-vue :farmId="gardenList[0].farmId"></hot-component-vue>
 		</view>
 		
 		<!-- 有味果园 -->
@@ -71,9 +78,9 @@
 						@click="goGardenItem(farm)"
 					>
 						<view class="garden-l" v-if="farm.coverVideo">
-							<video :src="farm.coverVideo" :show-progress="false" :show-play-btn="false"
-								:show-center-play-btn="false" object-fit="cover" :show-fullscreen-btn="false"
-								 disablePictureInPicture :autoplay="true" class="video-dom"
+							<video :id="`home-video-${farm.farmId || farm.id}`" :src="farm.coverVideo" :show-progress="false" :show-play-btn="true"
+								:picture-in-picture-mode="[]" :show-background-playback-button="false" :show-center-play-btn="false" object-fit="cover" :show-fullscreen-btn="false"
+								  disable-picture-in-picture :autoplay="false"  x5-video-player-type="h5" class="video-dom"
 								loop muted>
 							</video>
 						</view>
@@ -109,11 +116,11 @@
 </template>
 
 <script setup>
-import { ref, onMounted } from 'vue'
+import { ref, onMounted, onUnmounted, nextTick } from 'vue'
 import config from "@/api/config.js"
 import HOME from '@/api/home'
 import hotComponentVue from './hotComponent.vue'
-import { onLoad } from "@dcloudio/uni-app"
+import { onLoad, onPageScroll } from "@dcloudio/uni-app"
 
 const typeSearch = ref(null)
  
@@ -126,16 +133,109 @@ function toPage(path) {
 function goGardenItem(farm) {
 	const id = farm?.farmId
 	uni.navigateTo({
-		url: `/pages/tabBar/home/subPages/gardenItem?id=${id}`
+		url: `/pages/tabBar/home/subPages/gardenItem?farmId=${id}`
 	});
 }
 
 function goSourceReport(farm) {
 	const id = farm?.farmId
 	uni.navigateTo({
-		url: `/pages/tabBar/home/subPages/sourceReport?id=${id}`
+		url: `/pages/tabBar/home/subPages/sourceReport?farmId=${id}`
 	});
 }
+
+onMounted(() => {
+	
+			// 初始计算
+			nextTick(() => {
+				setTimeout(updateCenterVideo, 50)
+			})
+})
+
+	onPageScroll(() => handlePageScroll())
+
+	onUnmounted(() => {
+		// 离开页面时全部暂停
+		pauseAll()
+	})
+	
+	const playingId = ref(null)
+	
+		function throttle(fn, wait = 150) {
+			let lastTime = 0
+			let timer = null
+			return function(...args) {
+				const now = Date.now()
+				if (now - lastTime >= wait) {
+					lastTime = now
+					fn.apply(this, args)
+				} else {
+					clearTimeout(timer)
+					timer = setTimeout(() => {
+						lastTime = Date.now()
+						fn.apply(this, args)
+					}, wait - (now - lastTime))
+				}
+			}
+		}
+	
+		const handlePageScroll = throttle(() => {
+			updateCenterVideo()
+		}, 200)
+	
+		function updateCenterVideo() {
+			// 计算视口中心点附近的 video,播放该 video,其余暂停
+			const query = uni.createSelectorQuery()
+			query.selectAll('.video-dom').fields({ id: true, rect: true, size: true }, rects => {
+				if (!rects || !rects.length) return
+				const viewportHeight = uni.getSystemInfoSync().windowHeight
+				const viewportCenter = viewportHeight / 2
+				let minDistance = Number.POSITIVE_INFINITY
+				let closestId = null
+				rects.forEach(rect => {
+					if (!rect) return
+					const height = (typeof rect.height === 'number' ? rect.height : (rect.bottom - rect.top))
+					const elementCenter = rect.top + height / 2
+					// 仅考虑在可视区域内的元素
+					if (rect.bottom < 0 || rect.top > viewportHeight) return
+					const distance = Math.abs(elementCenter - viewportCenter)
+					if (distance < minDistance) {
+						minDistance = distance
+						closestId = rect.id
+					}
+				})
+				if (closestId && playingId.value !== closestId) {
+					playOnly(closestId)
+				}
+			}).exec()
+		}
+	
+		function playOnly(targetId) {
+			// 暂停所有,再播放目标
+			const ctxs = []
+			gardenList.value.forEach(item => {
+				if (!item.coverVideo) return
+				const id = `home-video-${item.farmId || item.id}`
+				const ctx = uni.createVideoContext(id)
+				ctxs.push({ id, ctx })
+			})
+			ctxs.forEach(({ id, ctx }) => {
+				if (id === targetId) {
+					try { ctx.play() } catch (e) {}
+					playingId.value = id
+				} else {
+					try { ctx.pause() } catch (e) {}
+				}
+			})
+		}
+	
+		function pauseAll() {
+			gardenList.value.forEach(item => {
+				if (!item.coverVideo) return
+				const id = `home-video-${item.farmId || item.id}`
+				try { uni.createVideoContext(id).pause() } catch (e) {}
+			})
+		}
  
 const latitude = ref(23.099994)
 const longitude = ref(113.324520)
@@ -155,12 +255,12 @@ onLoad(async () => {
   //   console.log('markerClusterClick', res)
   // })
   
+  // bindEvent()
+  // #endif
+  
   getTypeList()
   
   getFarmData()
-  
-  // bindEvent()
-  // #endif
 })
 
 const typeList = ref([])
@@ -173,6 +273,7 @@ function getTypeList() {
 function getFarmData() {
   HOME.getAllFarm().then(({data}) => {
 	gardenList.value = data.filter(item => item.recommend !== null)
+	nextTick(() => setTimeout(updateCenterVideo, 50))
  //     farmList.value = (data || []).sort((a, b) => {
 	//   // 优先排序:lighten为true的排前面,然后按recommend排序
 	//   if (a.lighten !== b.lighten) return b.lighten ? 1 : -1
@@ -323,7 +424,7 @@ const onMarkerTap = (e) => {
     console.log('点击了果园:', marker.customData.name)
     // 可以在这里跳转到果园详情页
     uni.navigateTo({
-      url: `/pages/tabBar/home/subPages/gardenItem?id=${marker.customData.farmId}`
+      url: `/pages/tabBar/home/subPages/gardenItem?farmId=${marker.customData.farmId}`
     })
   }
 }
@@ -351,6 +452,19 @@ const removeMarkers = () => {
 </script>
 
 <style lang="scss" scoped>
+	.garden-l {
+		::v-deep {
+			.uni-video-control-button {
+				width: 10px;
+				height: 10px;
+			}
+		}
+	}
+	
+	/* 或者全局隐藏 */
+	::v-deep .uni-video-pip {
+	  display: none !important;
+	}
 	.home-wrap {
 		background-color: #F2F3F5;
 		padding: 0 0 16rpx 0;
@@ -430,9 +544,19 @@ const removeMarkers = () => {
 			height: 200rpx;
 			box-sizing: border-box;
 			
+			// 覆盖 up-scroll-list 的默认样式,实现两端对齐
+			:deep(.u-scroll-list__scroll-view__content) {
+				display: flex;
+				justify-content: space-between;
+				align-items: center;
+				width: 100%;
+				min-width: 100%;
+			}
+			
 			.item-type {
 				text-align: center;
 				font-size: 24rpx;
+				flex-shrink: 0;
 				.type-img {
 					width: 92rpx;
 					height: 92rpx;
@@ -521,6 +645,7 @@ const removeMarkers = () => {
 									font-weight: bold;
 									height: 56rpx;
 									line-height: 56rpx;
+									margin-left: 20rpx;
 								}
 							}
 						}

+ 12 - 4
pages/tabBar/home/hotComponent.vue

@@ -1,5 +1,5 @@
 <template>
-	<view class="hot-wrap">
+	<view class="hot-wrap" v-if="hotList && hotList.length">
 		<view class="hot-content" :class="{'hot-border': isGardeItem}">
 			<view class="hot-title">
 				<view class="title-l" v-show="!isGardeItem">
@@ -13,7 +13,7 @@
 				</view>
 			</view>
 			<view class="hot-list">
-				<up-scroll-list indicatorColor="#FF770033" indicatorActiveColor="#FF7700" :indicatorWidth="30"
+				<up-scroll-list :indicator="hotList && hotList.length>2" indicatorColor="#FF770033" indicatorActiveColor="#FF7700" :indicatorWidth="30"
 					:indicatorBarWidth="13">
 					<view class="hot-panel">
 						<view class="hot-item" v-for="(item, index) in hotList" :key="index">
@@ -57,7 +57,6 @@
 	})
 	const hotList = ref([])
 	watch(() => props.farmId, (newVal) => {
-		console.log('newVal', newVal)
 		getHotList()
 	})
 
@@ -69,7 +68,6 @@
 		HOME.fetchHotList({
 			farmId: props.farmId
 		}).then(({data}) => {
-			console.log('data', data)
 			hotList.value = data
 		})
 	}
@@ -116,6 +114,15 @@
 				border: 2rpx solid #F3F3F3;
 			}
 			.hot-list {
+				// 覆盖 up-scroll-list 的默认样式,实现两端对齐
+				:deep(.u-scroll-list__scroll-view__content) {
+					display: flex;
+					justify-content: space-between;
+					align-items: center;
+					width: 100%;
+					min-width: 100%;
+				}
+
 				.hot-panel {
 					width: 100%;
 					display: flex;
@@ -125,6 +132,7 @@
 						// width: calc(100% - 20rpx);
 						display: flex;
 						white-space: nowrap;
+						flex-shrink: 0;
 
 						.hot-img {
 							flex: none;

+ 3 - 3
pages/tabBar/home/subPages/allGardenMap.vue

@@ -14,8 +14,8 @@
 	const webViewUrl = ref('')
 
 	onMounted(() => {
-		webViewUrl.value =
-			`https://feiniao-mini-h5-dev.sysuimars.cn/youwei/#/allGardenMap?userId=${userInfo.id}&token=${userInfo.token}`
-		// webViewUrl.value = "http://localhost:8081/#/allGardenMap?userId=91754&token=034d7cf5-25fc-42d3-993e-460120419e5a"
+		// webViewUrl.value =
+		// 	`https://feiniao-mini-h5-dev.sysuimars.cn/youwei/#/allGardenMap?userId=${userInfo.id}&token=${userInfo.token}`
+		webViewUrl.value = "http://localhost:8081/#/allGardenMap?userId=91754&token=034d7cf5-25fc-42d3-993e-460120419e5a"
 	})
 </script>

+ 104 - 53
pages/tabBar/home/subPages/gardenItem.vue

@@ -18,38 +18,40 @@
 				<source-report-vue :showStep="false"></source-report-vue>
 			</view>
 		</view>
-		<l-floating-panel :height="panelHeight" @heightChange="changePanel" :anchors="anchors" :defaultAnchor="2" :content-draggable="false">
+		<l-floating-panel v-model:height="panelHeight" ref="floatingPanelRef" @heightChange="changePanel" :anchors="anchors" :defaultAnchor="2" :content-draggable="false">
 			<view class="panel-content" ref="scrollViewRef">
 				<view class="panel-title">
 					<view class="title-l">
-						<image class="garden-img" :src="`${config.BASIC_IMG}home/garden.png`" mode=""></image>
+						<image class="garden-img" :src="gardenDetail?.icon" mode=""></image>
 						<view class="title-info">
 							<view class="title-garden">
-								从化荔枝博览园
+								{{gardenInfo?.farmName}}
 							</view>
 							<view class="btn-second">
 								有味指数
-								<text>4.5分</text>
+								<text>{{gardenInfo?.youweiIndex}}分</text>
 							</view>
 						</view>
 					</view>
-					<view class="title-r">
+					<!-- <view class="title-r">
 						+
 						<text class="add-text">关注</text>
-					</view>
+					</view> -->
 				</view>
 				<view class="garden-home" v-show="activeMenu === 0">
 					<view class="panel-video">
 						<!-- <video class="video-dom" src="https://birdseye-img.sysuimars.com/temp/5-25lby.mp4" controls></video> -->
 						
-						<video src="https://birdseye-img.sysuimars.com/temp/5-25lby.mp4" object-fit="cover" :show-fullscreen-btn="false"
+						<video :src="gardenDetail?.coverVideo" object-fit="cover" :show-fullscreen-btn="false"
 							:autoplay="true" class="video-dom" loop muted controls>
 						</video>
 					</view>
 					<!-- 果园热卖 -->
-					<hot-component-vue :isGardeItem="true"></hot-component-vue>
+					<view class="hot-box" v-if="currentFarmId">
+						<hot-component-vue :isGardeItem="true" :farmId="currentFarmId"></hot-component-vue>
+					</view>
 					<view class="garden-detail">
-						<view class="detial-item">
+						<view class="detial-item" v-if="gardenDetail?.ecology">
 							<view class="sub-title">
 								<view class="line-l"></view>
 								<view class="title-text">
@@ -58,31 +60,31 @@
 								<view class="line-r"></view>
 							</view>
 							<view class="detail-img">
-								<up-image class="img-dom" radius="8" width="100%" :src="`${config.BASIC_IMG}home/fruit.png`"  mode="widthFix"></up-image>
+								<up-image class="img-dom" radius="8" width="100%" :src="gardenDetail?.ecology"  mode="widthFix"></up-image>
 							</view>
 						</view>
-						<view class="detial-item">
+						<view class="detial-item" v-if="gardenDetail?.plantImage">
 							<view class="sub-title">
 								<view class="line-l"></view>
 								<view class="title-text">
-									果园生态
+									果园种植
 								</view>
 								<view class="line-r"></view>
 							</view>
 							<view class="detail-img">
-								<up-image class="img-dom" radius="8" width="100%" :src="`${config.BASIC_IMG}home/fruit.png`"  mode="widthFix"></up-image>
+								<up-image class="img-dom" radius="8" width="100%" :src="gardenDetail.plantImage"  mode="widthFix"></up-image>
 							</view>
 						</view>
-						<view class="detial-item">
+						<view class="detial-item" v-if="gardenDetail?.varietyImage">
 							<view class="sub-title">
 								<view class="line-l"></view>
 								<view class="title-text">
-									果园生态
+									果园品种
 								</view>
 								<view class="line-r"></view>
 							</view>
 							<view class="detail-img">
-								<up-image class="img-dom" radius="8" width="100%" :src="`${config.BASIC_IMG}home/fruit.png`"  mode="widthFix"></up-image>
+								<up-image class="img-dom" radius="8" width="100%" :src="gardenDetail.varietyImage"  mode="widthFix"></up-image>
 							</view>
 						</view>
 					</view>
@@ -97,9 +99,19 @@
 						</view>
 						<view class="filter-item" :class="{'active': filterIndex === 1}" @click="selectFilter(1)">
 							价格
+							<div class="filter-icon">
+								<image v-show="filterIndex !== 1" style="width: 14px; height: 14px;padding-top: 2px;" :src="`${config.BASIC_IMG}home/filter-icon.png`" mode=""></image>
+								<image v-show="filterIndex === 1 && orderType===true" style="width: 14px; height: 14px;padding-top: 2px;" :src="`${config.BASIC_IMG}home/filter-icon-1.png`" mode=""></image>
+								<image v-show="filterIndex === 1 && orderType===false" style="width: 14px; height: 14px;padding-top: 2px;" :src="`${config.BASIC_IMG}home/filter-icon-2.png`" mode=""></image>
+							</div>
 						</view>
 						<view class="filter-item" :class="{'active': filterIndex === 2}" @click="selectFilter(2)">
 							销量
+							<div class="filter-icon">
+								<image v-show="filterIndex !== 2" style="width: 14px; height: 14px;padding-top: 2px;" :src="`${config.BASIC_IMG}home/filter-icon.png`" mode=""></image>
+								<image v-show="filterIndex === 2 && orderType===true" style="width: 14px; height: 14px;padding-top: 2px;" :src="`${config.BASIC_IMG}home/filter-icon-1.png`" mode=""></image>
+								<image v-show="filterIndex === 2 && orderType===false" style="width: 14px; height: 14px;padding-top: 2px;" :src="`${config.BASIC_IMG}home/filter-icon-2.png`" mode=""></image>
+							</div>
 						</view>
 					</view>
 				
@@ -127,6 +139,9 @@
 								</view>
 							</view>
 						</view>
+						<view class="no-data" v-if="!discoverData || !discoverData.length">
+							当前果园暂未上架商品,请耐心等候
+						</view>
 					</view>
 				</view>
 			</view>
@@ -151,7 +166,8 @@
 	import config from "@/api/config.js"
 	import hotComponentVue from '../hotComponent.vue'
 	import sourceReportVue from './sourceReport.vue'
-
+	import { onLoad, onShow } from '@dcloudio/uni-app'
+	import HOME from '@/api/home'
 
 	const typeSearch = ref(null)
 
@@ -161,29 +177,50 @@
 	const anchors = [
 		50,
 		Math.round(0.5 * windowHeight),
-		Math.round(0.86 * windowHeight),
+		Math.round(0.92 * windowHeight),
 	];
 	const panelHeight = ref(anchors[2]);
 	
 	function changePanel({height}) {
 		if (height === 50) {
 			uni.navigateTo({
-				url: "/pages/tabBar/home/subPages/sourceReport"
+				url: `/pages/tabBar/home/subPages/sourceReport?farmId=${currentFarmId.value}`
 			})
 		}
-		console.log('height',height)
 	}
 	
 	const activeMenu = ref(0)
 	const scrollViewRef = ref(null)
 	function changeMenu(i) {
 		activeMenu.value = i
-		nextTick(() => { 
-		     scrollViewRef.value.scrollTo({
-		          top: 0,
-		          duration: 300 // 动画时间(ms)
-		        });
-		});
+	}
+	
+	const currentFarmId = ref(null)
+	onLoad(({farmId})=>{
+		currentFarmId.value = farmId||766
+		getFarmInfo()
+		getFarmDetail()
+		getGoodsList()
+	})
+	 const floatingPanelRef = ref(null)
+	onShow(() => {
+		nextTick(() => {
+			floatingPanelRef.value && floatingPanelRef.value.toAnchor(2)
+		})
+	})
+	
+	const gardenInfo = ref({})
+	function getFarmInfo() {
+		HOME.fetchGardenInfo({farmId: currentFarmId.value, isLighten: 1}).then(({data}) => {
+			gardenInfo.value = data
+		})
+	}
+	
+	const gardenDetail = ref({})
+	function getFarmDetail() {
+		HOME.fetchGardenDetail({farmId: currentFarmId.value}).then(({data}) => {
+			gardenDetail.value = data
+		})
 	}
 	
 	// 好味
@@ -191,35 +228,37 @@
 	const filterIndex = ref(0)
 	const activeType = ref(0)
 	
-	const discoverData = ref([
-		{
-			name: "海南妃子笑荔枝新鲜采摘新鲜采摘",
-			text: "",
-			price: '107',
-			sold: "1250"
-		},
-		{
-			name: "海南妃子笑荔枝新鲜采摘新鲜采摘",
-			text: "",
-			price: '107',
-			sold: "1250"
-		},
-		{
-			name: "海南妃子笑荔枝新鲜采摘新鲜采摘",
-			text: "",
-			price: '107',
-			sold: "1250"
-		},
-		{
-			name: "海南妃子笑荔枝新鲜采摘新鲜采摘",
-			text: "",
-			price: '107',
-			sold: "1250"
-		}
-	])
+	const discoverData = ref([])
+	let sortObj = {
+		0: "id",
+		1: "price",
+		2: "salesVal"
+	}
 	
+	const orderType = ref(true)
 	function selectFilter(i) {
+		if (filterIndex.value !== i) {
+			orderType.value = false
+		}
 		filterIndex.value = i
+		sort.value = sortObj[i]
+		orderType.value = !orderType.value
+		getGoodsList()
+	}
+	const sort = ref("id")
+	function getGoodsList() {
+		let params = {sort: sort.value, farmId: currentFarmId.value,}
+		if (filterIndex.value !== 0) {
+			params = {
+				...params,
+				order: orderType.value ? "asc" : "desc"
+			}
+		}
+		HOME.fetchGoodsList(params).then(({
+			data
+		}) => {
+			discoverData.value = data
+		})
 	}
 </script>
 
@@ -416,6 +455,7 @@
 		.discover-content {
 		
 			.discover-filter {
+				padding-top: 30rpx;
 				color: #A6A6A6;
 				font-size: 28rpx;
 				display: flex;
@@ -423,14 +463,25 @@
 		
 				.filter-item {
 					padding: 12rpx 20rpx;
-		
+					display: flex;
+					align-items: center;
+				
 					&.active {
 						color: #000000;
 					}
+					.filter-icon {
+						padding-left: 4rpx;
+					}
 				}
 			}
 			.discover-list {
 				padding-top: 20rpx;
+				.no-data {
+					padding-top: 40rpx;
+					font-size: 26rpx;
+					color: rgba(0, 0, 0, 0.6);
+					text-align: center;
+				}
 				.list-line {
 					padding-bottom: 20rpx;
 					display: flex;

+ 96 - 3
pages/tabBar/home/subPages/gardenList.vue

@@ -4,9 +4,9 @@
 			<view class="garden-item" v-for="farm in gardenList" :key="farm.farmId || farm.id"
 				>
 				<view class="garden-l" v-if="farm.coverVideo">
-					<video :src="farm.coverVideo" :show-progress="false" :show-play-btn="false"
+					<video :id="`gl-video-${farm.farmId || farm.id}`" :src="farm.coverVideo" :show-progress="false" :show-play-btn="true"
 						:show-center-play-btn="false" object-fit="cover" :show-fullscreen-btn="false"
-						 disablePictureInPicture :autoplay="true" class="video-dom"
+						  disable-picture-in-picture :autoplay="false" class="video-dom"
 						loop muted>
 					</video>
 				</view>
@@ -42,22 +42,114 @@
 <script setup>
 	import {
 		onMounted,
-		ref
+		onUnmounted,
+		ref,
+		nextTick
 	} from "vue";
 	import config from "@/api/config.js"
 	import HOME from '@/api/home'
+	import { onPageScroll } from '@dcloudio/uni-app'
 
 	onMounted(() => {
 		getGardenList()
+		// 初始计算
+		nextTick(() => {
+			setTimeout(updateCenterVideo, 50)
+		})
+	})
+
+	onPageScroll(() => handlePageScroll())
+
+	onUnmounted(() => {
+		// 离开页面时全部暂停
+		pauseAll()
 	})
 
 	const gardenList = ref([])
+	const playingId = ref(null)
+
+	function throttle(fn, wait = 150) {
+		let lastTime = 0
+		let timer = null
+		return function(...args) {
+			const now = Date.now()
+			if (now - lastTime >= wait) {
+				lastTime = now
+				fn.apply(this, args)
+			} else {
+				clearTimeout(timer)
+				timer = setTimeout(() => {
+					lastTime = Date.now()
+					fn.apply(this, args)
+				}, wait - (now - lastTime))
+			}
+		}
+	}
+
+	const handlePageScroll = throttle(() => {
+		updateCenterVideo()
+	}, 200)
+
+	function updateCenterVideo() {
+		// 计算视口中心点附近的 video,播放该 video,其余暂停
+		const query = uni.createSelectorQuery()
+		query.selectAll('.video-dom').fields({ id: true, rect: true, size: true }, rects => {
+			if (!rects || !rects.length) return
+			const viewportHeight = uni.getSystemInfoSync().windowHeight
+			const viewportCenter = viewportHeight / 2
+			let minDistance = Number.POSITIVE_INFINITY
+			let closestId = null
+			rects.forEach(rect => {
+				if (!rect) return
+				const height = (typeof rect.height === 'number' ? rect.height : (rect.bottom - rect.top))
+				const elementCenter = rect.top + height / 2
+				// 仅考虑在可视区域内的元素
+				if (rect.bottom < 0 || rect.top > viewportHeight) return
+				const distance = Math.abs(elementCenter - viewportCenter)
+				if (distance < minDistance) {
+					minDistance = distance
+					closestId = rect.id
+				}
+			})
+			if (closestId && playingId.value !== closestId) {
+				playOnly(closestId)
+			}
+		}).exec()
+	}
+
+	function playOnly(targetId) {
+		// 暂停所有,再播放目标
+		const ctxs = []
+		gardenList.value.forEach(item => {
+			if (!item.coverVideo) return
+			const id = `gl-video-${item.farmId || item.id}`
+			const ctx = uni.createVideoContext(id)
+			ctxs.push({ id, ctx })
+		})
+		ctxs.forEach(({ id, ctx }) => {
+			if (id === targetId) {
+				try { ctx.play() } catch (e) {}
+				playingId.value = id
+			} else {
+				try { ctx.pause() } catch (e) {}
+			}
+		})
+	}
+
+	function pauseAll() {
+		gardenList.value.forEach(item => {
+			if (!item.coverVideo) return
+			const id = `gl-video-${item.farmId || item.id}`
+			try { uni.createVideoContext(id).pause() } catch (e) {}
+		})
+	}
 
 	function getGardenList() {
 		HOME.getAllFarm().then(({
 			data
 		}) => {
 			gardenList.value = data.filter(item => item.recommend !== null)
+			nextTick(() => setTimeout(updateCenterVideo, 50))
 		})
 	}
 
@@ -155,6 +247,7 @@
 							font-weight: bold;
 							height: 56rpx;
 							line-height: 56rpx;
+							margin-left: 20rpx;
 						}
 					}
 				}