From c9928dd4f6d25e2339ea1400f59ec58674a927a7 Mon Sep 17 00:00:00 2001
From: zxl <763096477@qq.com>
Date: 星期四, 19 六月 2025 20:07:42 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev' into dev

---
 pages/tabbar/index/home.vue |  401 +++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 349 insertions(+), 52 deletions(-)

diff --git a/pages/tabbar/index/home.vue b/pages/tabbar/index/home.vue
index e65155f..ade53fe 100644
--- a/pages/tabbar/index/home.vue
+++ b/pages/tabbar/index/home.vue
@@ -9,52 +9,98 @@
       @change="onSwiperChange"
     >
       <swiper-item v-for="(item, index) in videoList" :key="item.id">
-		<!-- 鎾斁鎸夐挳锛堜粎褰撹棰戞殏鍋滄椂鏄剧ず锛� -->
-		<view 
-		  class="play-icon" 
-		  @click="togglePlay(index)"
-		  v-if="!currentVideoIsPlaying"
-		>
-		  <image src="/static/video/play.png" style="width: 45px;height: 45px" mode="aspectFit"></image>
+		<view style="width: 100%;height: 100%;" v-if="item.videoContentType === 'video'">
+			  <!-- 鎾斁鎸夐挳锛堜粎褰撹棰戞殏鍋滄椂鏄剧ず锛� -->
+			  <view 
+				class="play-icon" 
+				@click="togglePlay(index)"
+				v-if="!currentVideoIsPlaying"
+			  >
+				<image src="/static/video/play.png" style="width: 45px;height: 45px" mode="aspectFit"></image>
+			  </view>
+			  <video
+				:id="'video'+index"
+				:ref="'video'+index"
+				:src="item.videoUrl"
+				:autoplay="currentIndex === index"
+				:controls="false"
+				:loop="true"
+				:object-fit="item.objectFit"
+				:enable-progress-gesture="false"
+				class="video-item"
+				@play="onPlay(item.id, index)"
+				@pause="onPause(index)"
+				@ended="onEnded(index)"
+				@click="togglePlay(index)"
+				@timeupdate="onTimeUpdate($event)"
+				@loadedmetadata="onLoadedMetadata($event)"
+				
+			  ></video>
+			  <!-- 鑷畾涔夋帶鍒舵潯 -->
+			  <view 
+				@touchstart="handleTouchStart"
+				@touchmove="handleTouchMove"
+				@touchend="handleTouchEnd"
+				class="container">
+				<!-- 杩涘害鏉� - 鏁翠釜鍖哄煙鍙嫋鍔� -->
+				<view class="process-warp" :style="{ opacity: showProcess ? 1 : 0 }">
+				  <!-- 鏄剧ず褰撳墠杩涘害 -->
+				  <view class="progress-text">{{ hasPlayTime }}/{{formartDuration}}</view>
+				  <view 
+					class="progress-bar" 
+					id="progressBar"
+				  >
+							  
+					<!-- 宸插~鍏呴儴鍒� -->
+					<view class="progress-fill" :style="{ width: progress + '%' }"></view>
+				  </view>
+				</view>
+			  </view>
 		</view>
-        <video 
-          :id="'video'+index"
-		  :ref="'video'+index"
-          :src="item.videoUrl"
-          :autoplay="currentIndex === index"
-          :controls="false"
-          :loop="true"
-		  :object-fit="item.objectFit"
-          class="video-item"
-          @play="onPlay(item.id, index)"
-          @pause="onPause(index)"
-          @ended="onEnded(index)"
-		  @click="togglePlay(index)"
-		  @timeupdate="onTimeUpdate($event)"
-        ></video>
+		<view style="width: 100%; height: 100%;" v-else-if="item.videoContentType === 'img'">
+		  <uni-swiper-dot 
+			:info="item.imgs" 
+			:current="currentImgIndex" 
+			mode="round" 
+			style="width: 100%;height: 100%;display: flex;justify-content: center;align-items: center;"
+			:dots-styles="{width: 24, bottom: 24,selectedBackgroundColor: 'green', backgroundColor: 'gray'}"
+			>
+		    <swiper class="swiper-box" @change="imgChange" :autoplay="true" :interval="3000">
+		      <swiper-item v-for="img in item.imgs" :key="img">
+		        <view class="swiper-item">
+		          <!-- 璋冩暣 image 鏍峰紡锛屼娇鍏跺眳涓笖鎸夋瘮渚嬬缉鏀� -->
+		          <image 
+		            :src="img" 
+		            mode="aspectFit" 
+		            style="width: 100%; height: 100%; display: block; margin: 0 auto;"
+		          ></image>
+		        </view>
+		      </swiper-item>
+		    </swiper>
+		  </uni-swiper-dot>
+		</view>
+		
 		
 		<!-- 鎮寕鍟嗗搧閾炬帴灞� -->
-		<view class="goods-link-warp">
+		<view class="goods-link-warp" v-if="item.goodsList.length > 0">
 			<view class="goods-link">
-			  <view class="goods-container">
-			    <!-- 鍟嗗搧鍥剧墖 -->
-			    <image class="goods-image" :src="item.goods.imageUrl" mode="aspectFill"></image>
-			    
-			    <!-- 鍟嗗搧淇℃伅 -->
-			    <view class="goods-info">
-			      <text class="goods-name">{{item.goods.name}}</text>
-			      <view class="price-section">
-			        <text class="current-price">楼{{item.goods.price}}</text>
-			        <text class="original-price" v-if="item.goods.originalPrice">楼{{item.goods.originalPrice}}</text>
-			      </view>
-			      <text class="sales-count">{{item.goods.saleNum}}浜哄凡璐�</text>
-			    </view>
-			    
-			    <!-- 璐拱鎸夐挳 -->
-			    <view class="buy-button">
-			      <text>璐拱</text>
-			    </view>
-			  </view>
+			  <swiper @change="goodsChange" :autoplay="true" :interval="4000" style="height: 120rpx;">
+				<swiper-item v-for="goods in item.goodsList" :key="goods.goodsId">
+				  <view class="goods-container" @click="jumpToPay(item.id)">
+					<!-- 鍟嗗搧鍥剧墖 -->
+					<image class="goods-image" :src="goods.thumbnail" mode="aspectFill"></image>
+					
+					<!-- 鍟嗗搧淇℃伅 -->
+					<view class="goods-info">
+					  <text class="goods-name">{{goods.goodsName}}</text>
+					  <view class="price-section">
+						<text class="current-price">楼{{goods.price}}</text>
+						<text class="original-price" v-if="goods.originalPrice">楼{{goods.originalPrice}}</text>
+					  </view>
+					</view>
+				  </view>
+				</swiper-item>
+			  </swiper>
 			</view>
 		</view>
 		
@@ -88,6 +134,12 @@
             <text class="iconfont">&#xe7f7;</text>
             <text style="font-size: 10px;font-weight: lighter;">{{item.commentNum}}</text>
           </view>
+		  <view class="action-item">
+			  <button open-type="share" class="custom-share-btn" :data-obj="item">
+			        <text class="iconfont">&#xe602;</text>
+			      </button>
+		     
+		  </view>
         </view>
 		
       </swiper-item>
@@ -180,9 +232,31 @@
 <script>
 import { getRecommendVideos, savePlayRecord, subscribe, getVideoComments, addVideoComment, thubmsUpComment, cancelThubmsUpComment } from "@/api/video.js";
 import { changeCollect } from "@/api/collect.js";
+import { saveShare, saveShareClickRecord } from "@/api/share.js";
+import { silentLogin } from "@/api/connect.js";
+import { getUserInfo } from "@/api/members";
+import storage from "@/utils/storage.js";
 export default {
+  computed: {
+	    hasPlayTime() {
+	      return this.sliderFormatTime(this.progress > 0 ? this.duration * this.progress / 100 : 0);
+	    }
+  },
   data() {
     return {
+		currentImgIndex: 0, // 鎾斁鍒扮鍑犲紶鍥�--绱㈠紩
+		currentGoodsIndex: 0, // 鎾斁鍒扮鍑犱釜鍟嗗搧--绱㈠紩
+		currentTime: 0,
+		formartDuration: '',
+		duration: 0,
+		startX: 0,
+		progress: 0, // 瑙嗛杩涘害
+		startProgress : 0, // 寮�濮嬫粦鍔ㄦ椂鐨勮繘搴�
+		barLeft: 0, // 杩涘害鏉″乏杈圭晫浣嶇疆
+		barWidth: 0, // 杩涘害鏉″搴�
+		isDragging: false, // 鏄惁姝e湪鎷栧姩
+		processHidenTimer: null, // 杩涘害鏉¢殣钘忓畾鏃跺櫒
+		showProcess: false, // 鏄惁鏄剧ず杩涘害鏉�
 		videoNoMore: false, // 鏄惁杩樻湁鏇村瑙嗛
 		commentNoMore: false, // 鏄惁杩樻湁鏇村璇勮
 		commentQuery: {
@@ -237,7 +311,14 @@
     }
   },
   onShow() {
-	  this.loadVideos()
+	  // const token = storage.getAccessToken();
+	  // if (! token) {
+		 //  this.wxSilentLogin(() => {
+			//   this.loadVideos();
+		 //  })
+	  // } else { 
+	  // 	  this.loadVideos();
+	  // }
 	  // 濡傛灉瑙嗛鎸変笅鏆傚仠鍚庡垏鎹㈤〉闈㈠啀鍥炲埌椤甸潰鏃讹紝鍙畻鏆傚仠鏃堕棿锛堝洜涓烘殏鍋滄椂闂村拰绂诲紑椤甸潰鏃堕棿鏄噸澶嶇殑锛屽彧绠椾竴涓級
 	  if(this.startHidenTime !== 0 && this.currentVideoIsPlaying) {
 		  const duration = Date.now() - this.startHidenTime
@@ -247,14 +328,95 @@
   onHide() {
   	this.startHidenTime = Date.now()
   },
-  onLoad() {
-	  this.loadVideos();
+  onLoad(option) {
+	  const token = storage.getAccessToken();
+	  if (! token) {
+		  this.wxSilentLogin(() => {
+			  this.loadVideos();
+			  // 鍒ゆ柇鏄笉鏄偣鍑诲垎浜摼鎺ヨ繘鏉ョ殑
+			  if (option.userId && option.videoId) {
+				  // 淇濆瓨鍒嗕韩鐐瑰嚮璁板綍
+				  saveShareClickRecord({refId: option.videoId, shareUserId: option.userId})
+			  }
+		  })
+	  } else { 
+		this.loadVideos();
+	  }
   },
   onReady() {
     // 鍒濆鍖栬棰戜笂涓嬫枃
     this.initVideoContexts();
   },
+  onShareAppMessage(e) {
+	const userInfo = storage.getUserInfo();
+	if(!userInfo) {
+		console.log("鏈櫥褰曚笉鑳藉垎浜�");
+		return
+	}
+	const videoInfo = e.target.dataset.obj;
+	// 淇濆瓨鍒嗕韩璁板綍
+	const data = {
+		shareType: 'video',
+		refId: videoInfo.id,
+		shareUser: userInfo.id
+	}
+	saveShare(data)
+  	return {
+  		title: videoInfo.title,
+  		path: `/pages/tabbar/index/home?videoId=${videoInfo.id}&userId=${userInfo.id}`,
+  		imageUrl: videoInfo.coverUrl
+  	}
+  },
   methods: {
+	  // 闈欓粯鐧诲綍
+	  wxSilentLogin(callback) {
+		  //鑾峰彇code
+		  uni.login({
+		    success: (codeRes) => {
+		      if(codeRes.errMsg === "login:ok") {
+				// 闈欓粯鐧诲綍
+				silentLogin({code: codeRes.code}).then(res => {
+					storage.setAccessToken(res.data.data.accessToken);
+					storage.setRefreshToken(res.data.data.refreshToken);
+					//鑾峰彇鐢ㄦ埛淇℃伅
+					getUserInfo().then((user) => {
+					  storage.setUserInfo(user.data.result);
+					  storage.setHasLogin(true);
+					  callback()
+					});
+				})
+		      } else {
+		        uni.showToast({
+		          title: "绯荤粺寮傚父锛岃鑱旂郴绠$悊鍛橈紒"
+		        })
+		      }
+		    },
+		  });
+	  },
+	  // 鐐瑰嚮鍟嗗搧璺宠浆
+	  jumpToPay(videoId) {
+		uni.navigateTo({
+			url: '/pages/video/video-goods-detail?videoId=' + videoId
+		});
+	  },
+	  // 杞挱鍥惧彉鍖�
+	  imgChange(e) {
+		  this.currentImgIndex = e.detail.current;
+	  },
+	  // 鍟嗗搧杞挱鍥惧彉鍖�
+	  goodsChange(e) {
+		  this.currentGoodsIndex = e.detail.current;
+	  },
+	  // 鑾峰彇杩涘害鏉$殑浣嶇疆鍜屽昂瀵�
+	  getBarRect() {
+	    const query = uni.createSelectorQuery().in(this);
+	    query.select('#progressBar').boundingClientRect(rect => {
+	      if (rect) {
+	        this.barLeft = rect.left;
+	        this.barWidth = rect.width;
+	      }
+	    }).exec();
+	  },
 		// 璺宠浆涓汉涓婚〉
 		jumpToHomePage(authorId) {
 			uni.navigateTo({
@@ -323,7 +485,7 @@
 			const videoId = this.commentForm.videoId;
 			this.commentForm = { // 璇勮琛ㄥ崟鏁版嵁
 				id: '',
-				videoId: '',
+				videoId: videoId,
 				commentContent: '',
 				replyId: '',
 				replyUserId: '',
@@ -351,6 +513,12 @@
 			const input = this.$refs.commentInput;
 			if (input) input.focus();
 		  });
+		},
+		// 杩涘害鏉℃椂闂存牸寮忓寲 (00:00)
+		sliderFormatTime(seconds) {
+		  const mins = Math.floor(seconds / 60);
+		  const secs = Math.floor(seconds % 60);
+		  return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
 		},
 		// 鏍煎紡鍖栨椂闂�
 	    formatTime(time) {
@@ -549,6 +717,9 @@
 		if (this.videoContexts[this.currentIndex]) {
 			this.videoContexts[this.currentIndex].play();
 		}
+		// 璁剧疆褰撳墠鎾斁瑙嗛鐨勬�绘椂闀�
+		this.duration = this.videoList[this.currentIndex].videoDuration;
+		this.formartDuration = this.sliderFormatTime(this.duration);
     },
     
     // 鏀惰棌/鍙栨秷鏀惰棌
@@ -584,9 +755,16 @@
 	},
     // 瑙嗛鎾斁浜嬩欢
     onPlay(id, index) {
+		this.getBarRect()
+		this.progress = 0
 		console.log(id, index, "瑙﹀彂鎾斁");
 		if(index === this.currentIndex) {
 			this.currentVideoIsPlaying = true;
+			if(! this.duration) {
+				// 璁剧疆褰撳墠鎾斁瑙嗛鐨勬�绘椂闀�
+				this.duration = this.videoList[this.currentIndex].videoDuration;
+				this.formartDuration = this.sliderFormatTime(this.duration);
+			}
 		} else {
 			this.currentVideoIsPlaying = false;
 			return
@@ -600,6 +778,7 @@
 			const duration = Date.now() - this.startPauseTime
 			this.totalPauseTime += duration
 		}
+		
     },
     
     // 瑙嗛鏆傚仠浜嬩欢
@@ -613,7 +792,6 @@
 		}
 	  this.startPauseTime = Date.now()
     },
-    
     // 瑙嗛缁撴潫浜嬩欢
     onEnded(index) {
       // this.currentVideoIsPlaying = false;
@@ -621,9 +799,66 @@
 	
 	// 璁板綍鎾斁鏃堕暱
 	onTimeUpdate(e) {
-		this.playRecord.playAt = e.detail.currentTime
+		this.playRecord.playAt = e.detail.currentTime;
+		
+		this.currentTime = e.detail.currentTime;
+		this.progress = (e.detail.currentTime / this.duration) * 100
+	},
+	// 瑙︽懜寮�濮�
+	handleTouchStart(e) {
+	  this.isDragging = true;
+	  this.showProcess = true;
+	  this.startProgress = this.progress; // 璁板綍寮�濮嬫椂鐨勮繘搴�
+	  this.startX = e.touches[0].pageX;
+	  console.log("璁板綍寮�濮嬫椂鐨勮繘搴�", this.startProgress);
+	  this.videoContexts[this.currentIndex].pause()
+	  // this.updateProgress(e);
 	},
 	
+	// 瑙︽懜绉诲姩
+	handleTouchMove(e) {
+	  if (!this.isDragging || !this.barWidth) return;
+	  clearTimeout(this.processHidenTimer)
+	  this.videoContexts[this.currentIndex].pause()
+	  this.updateProgress(e);
+	},
+	
+	// 瑙︽懜缁撴潫
+	handleTouchEnd() {
+	  this.isDragging = false;
+	  console.log("婊戝姩缁撴潫", this.duration * this.progress);
+	  this.videoContexts[this.currentIndex].seek(this.duration * this.progress / 100)
+	  this.videoContexts[this.currentIndex].play()
+	  this.processHidenTimer = setTimeout(() => {
+		  this.showProcess = false;
+		}, 1000);
+	},
+	
+	// 鏇存柊杩涘害
+	updateProgress(e) {
+		// 鑾峰彇褰撳墠瑙︽懜鐐筙鍧愭爣
+		const currentX = e.touches[0].pageX;
+		
+		// 璁$畻婊戝姩璺濈(鍍忕礌)
+		const deltaX = currentX - this.startX;
+		
+		// 灏嗗儚绱犺窛绂昏浆鎹负杩涘害澧為噺
+		const deltaProgress = (deltaX / this.barWidth) * 100;
+		console.log("杩涘害澧為噺", deltaProgress);
+		// 璁$畻鏂拌繘搴� = 寮�濮嬫椂鐨勮繘搴� + 婊戝姩澧為噺
+		let newProgress = this.startProgress + deltaProgress;
+		
+		// 闄愬埗鑼冨洿鍦�0-100涔嬮棿
+		newProgress = Math.max(0, Math.min(100, newProgress));
+		
+		this.progress = newProgress;
+	},
+	// 鑾峰彇瑙嗛鎬绘椂闀�
+	onLoadedMetadata(e) {
+	  // this.duration = e.detail.duration;
+	  // this.formartDuration = this.sliderFormatTime(this.duration);
+	  // console.log("瑙嗛鎬绘椂闀�", this.duration);
+	},
 	// 淇濆瓨鎾斁璁板綍
 	async savePlayRecord() {
 		console.log(Date.now(), this.playRecord.startPlayTime, this.totalHidenTime);
@@ -659,7 +894,7 @@
 	
 	.video-swiper {
 	  width: 100%;
-	  height: 100%;
+	  height: calc(100% - 50px);
 	}
 	
 	.video-item {
@@ -681,7 +916,7 @@
 	.video-info {
 	  width: 70%;
 	  position: absolute;
-	  bottom: 70px;
+	  bottom: 20px;
 	  left: 20px;
 	  color: #f8f8f8;
 	  z-index: 10;
@@ -755,6 +990,7 @@
 	}
 	.goods-link {
 	  position: relative;
+	  width: 450rpx;
 	  margin: 20rpx 0;
 	  padding: 12rpx;
 	  background-color: rgba(255, 255, 255, 0.9);
@@ -763,6 +999,7 @@
 	}
 	
 	.goods-container {
+	  width: 100%;
 	  display: flex;
 	  align-items: center;
 	}
@@ -785,11 +1022,13 @@
 	  font-size: 28rpx;
 	  color: #333;
 	  font-weight: bold;
-	  display: -webkit-box;
 	  -webkit-line-clamp: 2;
 	  -webkit-box-orient: vertical;
-	  overflow: hidden;
 	  margin-bottom: 8rpx;
+	  width: 280rpx; /* 闇�瑕佹寚瀹氬搴� */
+	  overflow: hidden;
+	  white-space: nowrap;
+	  text-overflow: ellipsis;
 	}
 	
 	.price-section {
@@ -1015,4 +1254,62 @@
 	.thumbs-num {
 		margin-left: 4rpx;
 	}
+	.container {
+	  display: flex;
+	  flex-direction: column;
+	  align-items: center;
+	  position: absolute;
+	  bottom: 0;
+	  width: 100%;
+	}
+	
+	.progress-bar {
+	  position: relative;
+	  width: 100%;
+	  height: 16px;
+	  background-color: #eee;
+	  overflow: hidden;
+	}
+	
+	.progress-fill {
+	  position: absolute;
+	  left: 0;
+	  top: 0;
+	  height: 100%;
+	  background-color: lightgray;
+	  transition: width 0.1s;
+	}
+	.process-warp {
+		width: 100%;
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+	}
+	.progress-text {
+	  margin-top: 10px;
+	  font-size: 14px;
+	  color: #666;
+	}
+	.swiper-box {
+	  width: 100%;
+	  height: 1400rpx;
+	}
+	.swiper-item {
+	  display: flex;
+	  justify-content: center;
+	  align-items: center;
+	  width: 100%;
+	  height: 100%;
+	}
+	.custom-share-btn {
+	  font-size: unset;
+	  background: none;
+	  padding: 0;
+	  margin: 0;
+	  line-height: normal;
+	  border: none;
+	}
+	.custom-share-btn::after {
+	  border: none;
+	}
 </style>
\ No newline at end of file

--
Gitblit v1.8.0