uniapp类似抖音视频滑动

最近需求说要做个类似抖音那种视频的,我二话不说就用了swiper-view组件,但是效果不太理想,后面改用css属性

先放效果图:

复制代码
<template>
	<view class="video-scroll-container" @touchstart="handleTouchStart" @touchend="handleTouchEnd"
		@touchmove="handleTouchMove">
		<view class="video-list"
			:style="{ transform: 'translateY(' + -currentIndex * windowHeight + 'px)', transition: isSwiping ? 'transform 0.3s ease' : 'none' }">
			<view v-for="(video, index) in videoList" :key="video.id" class="video-item"
				:style="{ height: windowHeight + 'px' }">
				<view class="video-wrapper" @click="handleVideoClick(index)">
					<!-- 视频 -->
					<video :poster="video?.cover" :controls="false" :id="'video' + index" :src="video.video_src" :show-play-btn="false"
						:enable-progress-gesture="false" :autoplay="true" @play="onPlay(video,index)"
						@ended="onEnded(index)" @pause="onPause(index)" @timeupdate="onTimeUpdate($event,index)"
						class="fullscreen-video" :ref="(el) => setVideoRef(el, index)"></video>
					<!-- 圆形进度条 -->
					<view class="progress-wrap">
						<!-- <circle-progress :percent="video.progressPercent || 0" :stroke-width="6"
							stroke-color="#fff" /> -->
						<CircleProgress :percent="video.progressPercent || 0" :stroke-width="6" stroke-color="#fff">
							{{ video.remainingTime }}
						</CircleProgress>
					</view>


					<!-- 控制按钮 -->

					<view v-if="isControlVisible" class="control-btn" @click.stop="togglePlay(index)">
						<cover-view>
							<image style="width: 116rpx;height: 116rpx;" src="/static/images/icon/play.png"
								mode="aspectFit">
							</image>
						</cover-view>
					</view>
					<view class="fixed">
						<cover-view>
							<view class="flex flex_dir_c flex_items_c" @click.stop="toDrap('like',video)">
								<image src="/static/images/icon/img1.png" mode=""></image>
								<view class="txt">
									{{video?.like_num}}
								</view>
							</view>
							<view class="flex flex_dir_c flex_items_c" @click.stop="toDrap('email',video)">
								<image src="/static/images/icon/img2.png" mode=""></image>
								<view class="txt">
									{{video?.comment_num}}
								</view>
							</view>
							<view class="flex flex_dir_c flex_items_c" @click.stop="toDrap('share',video)">
								<image src="/static/images/icon/img3.png" mode=""></image>
								<view class="txt">
									{{video?.share_num}}
								</view>
							</view>
							<view class="flex flex_dir_c flex_items_c" @click.stop="toDrap('send',video)">
								<image src="/static/images/icon/img4.png" mode=""></image>
								<view class="txt">
									发布
								</view>
							</view>
						</cover-view>
					</view>



					<!-- 发布人信息 -->
					<view class="publisher-info">
						<cover-view>

							<!-- <text>{{ video.publisher }}</text> -->
							<view class="Info">
								<view class="good-box" v-if="video?.goods !== null" @click.stop="toDetail(video)">
									<image :src="video?.goods?.thumb" class="good-img" mode=""></image>
									<view class="text-wrap">
										<view class="desc">
											{{video?.goods?.title}}
										</view>
										<view class="money">
											<view class="price">
												<text class="fs_24">¥</text>{{video?.goods?.price}}
											</view>
											<view class="old-price">
												¥{{video?.goods?.market_price}}
											</view>
										</view>
									</view>
									<image class="carImg" src="/static/images/icon/vCar.png" mode=""></image>
								</view>
								<view class="video-detail-box">
									<view class="good-and-title">
										<view class="video-title">
											{{video?.title}}
										</view>
									</view>
									<view class="detail-box iphoneXStyle flex flex_items_c ">
										<view class="flex flex_items_c flex_just_sb" style="width: 100%;">
											<view class="left-user-info flex flex_items_c">
												<image class="avatar" :src="video?.member?.avatar_image" mode="">
												</image>
												<view class="user flex flex_dir_c">
													<text
														class="name">{{video?.member?.nickname || video?.member?.username}}</text>
													<text class="num">共{{video?.member_video_num || 0}}个分享视频</text>
												</view>
											</view>
											<view class="center-follow">
												<view class="btn-follow"
													:class="[video?.is_follow=== 0?'caBtn':'acBtn']"
													@click.stop="toEditFollow(video)">
													{{video?.is_follow=== 0?'关注':'已关注'}}
												</view>
											</view>

										</view>
										<!-- <view class="right-icon flex flex_items_c">
											<view class="flex flex_dir_c flex_items_c rightIcon"
												@click.stop="toDrap('share',video)">
												<uni-icons type="redo" color="#fff" size="20"></uni-icons>
												<view class="">
													{{video?.share_num}}
												</view>
											</view>
											<view class="flex flex_dir_c flex_items_c rightIcon"
												@click.stop="toDrap('like',video)">
												<uni-icons v-if="video?.like_num == 0" type="heart" color="#fff"
													size="20"></uni-icons>
												<uni-icons v-else type="heart-filled" color="red" size="20"></uni-icons>
												<view class="">
													{{video?.like_num}}
												</view>
											</view>
											<view class="flex flex_dir_c flex_items_c rightIcon"
												@click.stop="toDrap('email',video)">
												<uni-icons type="email" color="#fff" size="20"></uni-icons>
												<view class="">
													{{video?.comment_num}}
												</view>
											</view>
										</view> -->
									</view>
								</view>
							</view>
						</cover-view>
					</view>
				</view>
			</view>
		</view>
	</view>
</template>

<script setup>
	import {
		onHide,
		onReachBottom
	} from "@dcloudio/uni-app"
	import {
		ref,
		onMounted,
		getCurrentInstance,
		computed,
		watch,
		onUnmounted
	} from 'vue'
	import {
		wxShare
	} from "@/utils/share.js";
	import {
		getEnvironment,
	} from '@/utils/utils.js';
	import CircleProgress from '@/components/circle.vue'
	const {
		proxy
	} = getCurrentInstance()
	const props = defineProps({
		videoList: {
			type: Array,
			required: true,
			default: () => []
		},
		// id: {
		// 	type: [String || Number],
		// 	// required: true,
		// 	default: ''
		// }
	})
	import {
		getBasicSet,
		getVideoList,
		addRecord,
		getlogViewTime,
		getvideoLike,
		getCommentLike,
		createComment,
		getSupport,
		getEditFollow
	} from '@/api/customerCenter.js'
	const playVId = ref({})
	const currentIndex = ref(0)
	const playingIndex = ref(-1)
	const videoRefs = ref([])
	const startY = ref(0)
	const endY = ref(0)
	const isPausedManually = ref(false);
	const isSwiping = ref(false)
	const windowHeight = ref(0)
	const videoId = ref('')
	const content = ref('')
	const playIcon = ref('https://yourdomain.com/icon/play.png')
	const pauseIcon = ref('https://yourdomain.com/icon/pause.png')
	const videoTime = ref('')
	const durateTime = ref('')
	const isControlVisible = ref(false);
	let controlTimeout = null;
	const duration = ref(0); // 视频总时长(秒)
	const currentTime = ref(0); // 当前播放时间(秒)
	const CommentList = ref([])
	const showShare = ref(false)
	const emit = defineEmits(['openPop', 'openShare', 'send']);
	// 剩余时间计算
	const remainingTime = computed(() => {
		return Math.max(duration.value - currentTime.value, 0);
	});
	const previousIndex = ref(-1);
	const popup = ref(null)
	const popup1 = ref(null)
	// 显示控制按钮并设置2秒后隐藏
	const showControl = () => {
		isControlVisible.value = true;
		// if (playingIndex.value !== -1 && !isPausedManually.value) {
		// 	if (controlTimeout) clearTimeout(controlTimeout);
		// 	controlTimeout = setTimeout(() => {
		// 		isControlVisible.value = false;
		// 	}, 2000);
		// }
	};
	// watch(props.id, (newValue) => {

	// 	console.log('变化', props.id);

	// })
	function handleVideoClick(index) {
		const videoContext = uni.createVideoContext(`video${index}`, proxy);
		if (!videoContext) {
			console.error('视频上下文不存在', index);
			return;
		}

		if (playingIndex.value === index) {
			// 当前视频正在播放 → 执行暂停
			videoContext.pause();
			playingIndex.value = -1;
			isPausedManually.value = true;

			// 强制显示控制按钮
			isControlVisible.value = true;
		} else {
			// 暂停之前正在播放的视频(如果有的话)
			if (playingIndex.value !== -1) {
				const prevContext = uni.createVideoContext(`video${playingIndex.value}`, proxy);
				if (prevContext) {
					prevContext.pause();
				}
			}

			// 播放当前视频
			videoContext.play();
			playingIndex.value = index;
			isPausedManually.value = false;

			// 隐藏控制按钮
			isControlVisible.value = false;
		}
	}
	onReachBottom(() => {
		console.log('触底');
	})

	function shareHandler(val) {
		console.log('val', val);
		let link = location.href;
		let shareInfo = {
			title: val?.title,
			desc: 'AI雷达视频',
			link,
			imgUrl: val?.cover,
		}

		if ([1, 2].includes(getEnvironment())) {
			wxShare(shareInfo).then(res => {
				console.log(res);
				emit('openShare')
			})
		} else {
			uni.setClipboardData({
				data: link,
				success: function() {}
			});
		}
	}

	function toDrap(type, e) {
		videoId.value = e.id
		switch (type) {
			case 'like':
				getLick(e)
				break;
			case 'email':
				// 无法在本页面加弹窗会导致滚动视频也滚动恶心
				emit('openPop', e.id)
				// popup.value.open()
				// getCommentList(e.id)
				break;
			case 'share':
				shareHandler(e)
				// showShare.value = true
				break;
			case 'send':
				emit('send')
				break;
			default:
				break;
		}
	}

	function toDetail(e) {
		uni.navigateTo({
			url: `/pages/goods/index?id=${e?.goods?.id}&vid=${e?.id}`
		})
	}
	async function getCommentList() {
		const {
			result,
			data,
			msg
		} = await getCommentLike({
			video_id: videoId.value
		})
		if (result === 1) {
			CommentList.value = data?.list?.data
		} else {
			uni.showToast({
				title: msg,
				icon: 'none'
			})
		}
	}
	onUnmounted(() => {
		pauseAllVideos()
	})

	function toComment() {
		content.value = ''
		popup1.value.open()
	}

	async function popLike(e) {
		const {
			result,
			data,
			msg
		} = await getSupport({
			comment_id: e.id
		})
		if (result == 1) {
			if (e.support_num > 0) {
				e.is_support = 0
				e.support_num -= 1
			} else {
				e.is_support = 1
				e.support_num += 1
			}

		} else {
			uni.showToast({
				title: msg,
				icon: 'none'
			})
		}
	}


	async function getLick(e) {
		const {
			result,
			data,
			msg
		} = await getvideoLike({
			video_goods_id: e.id
		})
		if (result == 1) {
			if (e.like_num > 0) {
				e.like_num -= 1
			} else {
				e.like_num += 1
			}

		} else {
			uni.showToast({
				title: msg,
				icon: 'none'
			})
		}
	}


	// 鼠标离开时立即隐藏
	const hideControl = () => {
		isControlVisible.value = false;
		if (controlTimeout) clearTimeout(controlTimeout);
	};
	async function toEditFollow(item) {
		const {
			result,
			data,
			msg
		} = await getEditFollow({
			member_id: item.uid,
			follow_type: item.is_follow === 0 ? 1 : 2
		})
		if (result == 1) {
			if (item.is_follow === 0) {
				item.is_follow = 1
			} else {
				item.is_follow = 0
			}
		} else {
			uni.showToast({
				title: msg,
				icon: 'none'
			})
		}
	}
	// 播完继续
	// const onEnded = (index) => {
	// 	const videoContext = uni.createVideoContext(`video${index}`, proxy);
	// 	if (playingIndex.value === index) {
	// 		videoContext.play(); // 自动重新播放
	// 	}
	// };
	// const onEnded = (index) => {
	// 	setTimeout(() => {
	// 		playVideo(index);
	// 	}, 500); // 0.5秒后重新播放
	// };
	const onEnded = (index) => {
		if (playingIndex.value === index) {
			const videoContext = uni.createVideoContext(`video${index}`, proxy);
			videoContext.play(); // 只重新播放当前视频
		}
	};

	// 获取窗口高度
	onMounted(() => {
		uni.getSystemInfo({
			success: (res) => {
				windowHeight.value = res.windowHeight
			}
		})
		const videoContext = uni.createVideoContext('video0', proxy)
		console.log('Video context created:', videoContext)
		props.videoList.filter(oid => oid == props.id)
	})

	// 设置 video ref
	const setVideoRef = (el, index) => {
		videoRefs.value[index] = el
	}

	// 开始触摸
	const handleTouchStart = (e) => {
		console.log('开始', e.touches[0].pageY);
		// getLogViewTime(playVId?.value)
		// getRecord(playVId?.value?.id)
		// e.preventDefault();
		startY.value = e.touches[0].pageY
		isSwiping.value = false;
	}
	const handleTouchMove = (e) => {
		const currentY = e.touches[0].pageY;
		if (Math.abs(currentY - startY.value) > 10) {
			isSwiping.value = true; // 超过阈值认为是滑动
			e.preventDefault(); // 此时开始阻止默认行为
		}
	}

	// 结束触摸
	const handleTouchEnd = (e) => {
		endY.value = e.changedTouches[0].pageY;

		if (!isSwiping.value) {
			console.log("这是一个点击事件");
			// 这里可以触发额外的点击处理逻辑
			return;
		}

		const diff = endY.value - startY.value;

		if (diff > 0 && currentIndex.value > 0) {
			currentIndex.value--;
		} else if (diff < 0 && currentIndex.value < props.videoList.length - 1) {
			currentIndex.value++;
		}

		// 防止超出范围
		if (currentIndex.value >= props.videoList.length) {
			currentIndex.value = props.videoList.length - 1;
		}

		setTimeout(() => {
			isSwiping.value = false;
			console.log('currentIndex.value', currentIndex.value);
			console.log('previousIndex.value', previousIndex.value);
			if (currentIndex.value !== previousIndex.value) {
				getLogViewTime(props.videoList[currentIndex.value])
				getRecord(props.videoList[currentIndex.value]?.id);
			}
			pauseOtherVideos(currentIndex.value);
			playCurrentVideo(currentIndex.value);
		}, 300);
	};
	// 优化 关闭页面自动停止所有播放
	function pauseAllVideos() {
		videoRefs.value.forEach((video, idx) => {
			if (video) {
				const videoContext = uni.createVideoContext(`video${idx}`, proxy);
				videoContext.pause();
			}
		});
		console.log('停止所有播放');
		playingIndex.value = -1; // 更新播放索引状态
		isPausedManually.value = true; // 更新手动暂停状态
	}
	const pauseOtherVideos = (currentIdx) => {
		// videoRefs.value.forEach((video, idx) => {
		// 	if (idx !== currentIdx && video) {
		// 		const videoContext = uni.createVideoContext(`video${idx}`, proxy);
		// 		videoContext.pause();
		// 	}
		// });
		videoRefs.value.forEach((video, idx) => {
			if (idx !== currentIdx && video) {
				const videoContext = uni.createVideoContext(`video${idx}`, proxy);
				videoContext.pause();
			}
		});
	};
	// 播放指定视频
	const playCurrentVideo = (index) => {
		previousIndex.value = currentIndex.value;
		const videoContext = uni.createVideoContext(`video${index}`, proxy);
		if (videoContext) {
			videoContext.play();
			playingIndex.value = index;
			isPausedManually.value = false;
		}
	};

	// 停止所有视频
	// const stopAllVideos = () => {
	// 	videoRefs.value.forEach((video, idx) => {
	// 		if (video && idx !== currentIndex.value) {
	// 			const videoContext = uni.createVideoContext(`video${idx}`, proxy);
	// 			console.log('dadadadad', videoContext);
	// 			videoContext.pause();
	// 		}
	// 	});
	// };

	// 播放/暂停切换
	// const togglePlay = (index) => {
	// 	const videoContext = uni.createVideoContext(`video${index}`, proxy);
	// 	if (playingIndex.value === index) {
	// 		videoContext.pause();
	// 		playingIndex.value = -1;
	// 		isPausedManually.value = true;
	// 	} else {
	// 		stopAllVideos();
	// 		playVideo(index); // 使用统一播放方法
	// 	}
	// };
	const togglePlay = (index) => {
		const videoContext = uni.createVideoContext(`video${index}`, proxy);
		if (!videoContext) {
			console.error('无法获取视频上下文', index);
			return;
		}

		if (playingIndex.value === index) {
			console.log('暂停');
			// 当前视频正在播放 → 执行暂停
			videoContext.pause();
			playingIndex.value = -1;
			isPausedManually.value = true;

			// 强制显示控制按钮
			isControlVisible.value = true;
		} else {
			console.log('播放');
			// 不再暂停其他视频,只播放当前视频
			videoContext.play();
			playingIndex.value = index;
			isPausedManually.value = false;

			// 播放时隐藏控制按钮
			isControlVisible.value = false;
		}
	};

	async function createCommem() {
		const {
			result,
			data,
			msg
		} = await createComment({
			content: content.value,
			video_id: videoId.value
		})
		if (result === 1) {
			uni.showToast({
				title: msg,
				icon: 'none'
			})
			popup1.value.close()
			getCommentList()
		} else {
			uni.showToast({
				title: msg,
				icon: 'none'
			})
		}
	}

	const onTimeUpdate = (event, index) => {
		const duration = event.detail.duration;
		const currentTime = event.detail.currentTime;

		// 边界检查:确保时间是有效数值
		if (typeof duration !== 'number' || typeof currentTime !== 'number' || isNaN(duration) || isNaN(
				currentTime)) {
			return;
		}

		// 更新进度条百分比
		if (duration > 0) {
			props.videoList[index].progressPercent = (currentTime / duration) * 100;
		}

		// 计算剩余时间并格式化为 MM:SS
		const remainingSeconds = Math.max(0, duration - currentTime);
		const minutes = Math.floor(remainingSeconds / 60)
			.toString()
			.padStart(2, '0');
		const seconds = Math.floor(remainingSeconds % 60)
			.toString()
			.padStart(2, '0');
		props.videoList[index].remainingTime = `${minutes}:${seconds}`;

		// 视频开始播放时重置手动暂停状态
		if (currentTime === 0 && playingIndex.value === index) {
			isPausedManually.value = false;
		}
	};
	const formatTime = (seconds) => {
		const totalSeconds = Math.floor(seconds);
		const minutes = Math.floor(totalSeconds / 60).toString().padStart(2, '0');
		const secs = (totalSeconds % 60).toString().padStart(2, '0');
		return `${minutes}:${secs}`;
	};

	// 播放事件处理
	const onPlay = (e, index) => {
		playVId.value = e
		playingIndex.value = index
		isControlVisible.value = false;
	}
	async function getLogViewTime(e) {
		const {
			result,
			data,
			msg
		} = await getlogViewTime({
			video_id: e?.id,
			video_length: parseInt(e.remainingTime?.split(":")[1], 10)
		})
	}
	async function getRecord(e) {
		const {
			result,
			data,
			msg
		} = await addRecord({
			video_id: e
		})
		if (result != 1) {
			uni.showToast({
				title: msg,
				icon: 'none'
			})
		}
	}

	// 暂停事件处理
	const onPause = (index) => {
		if (playingIndex.value === index) {
			playingIndex.value = -1;
			isPausedManually.value = true;

			// 强制显示控制按钮
			isControlVisible.value = true;
		}
	};
	const playVideo = (index) => {
		const videoContext = uni.createVideoContext(`video${index}`, proxy);
		if (videoContext) {
			videoContext.play();
			playingIndex.value = index;
			isPausedManually.value = false;
		}
	};
</script>

<style scoped lang="scss">
	.video-scroll-container {
		position: relative;
		width: 100%;
		height: 100vh;
		overflow: hidden;
		// touch-action: pan-y;
		touch-action: none;
	}

	.video-list {
		position: relative;
		width: 100%;
		display: flex;
		flex-direction: column;
		transition: transform 0.3s ease;
	}

	.video-item {
		width: 100%;
		position: relative;
		overflow: hidden;
	}

	.video-wrapper {
		position: relative;
		width: 100%;
		height: 100%;
	}

	.fullscreen-video {
		width: 100%;
		height: 100%;
		object-fit: cover;
	}

	.progress-wrap {
		position: absolute;
		top: 120rpx;
		right: 30rpx;
		z-index: 99;
	}

	.control-btn {
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
		z-index: 98;
		opacity: 0.7;
		transition: opacity 0.3s ease;
	}

	.control-btn:hover {
		opacity: 1;
	}

	.fixed {
		position: absolute;
		right: 0;
		z-index: 999;
		top: 50%;
		right: 24rpx;

		image {
			width: 80rpx;
			height: 80rpx;
		}

		.txt {
			font-weight: 400;
			font-size: 24rpx;
			color: #FFFFFF;
			text-align: left;
			font-style: normal;
			text-transform: none;
		}

	}

	.publisher-info {
		position: absolute;
		bottom: 30rpx;
		// left: 30rpx;
		color: #fff;
		font-size: 28rpx;
		width: 100%;
		z-index: 99;
	}

	.good-box {
		display: flex;
		z-index: 10;
		// background: rgba(0, 0, 0, .4);
		width: 464rpx;
		height: 136rpx;
		background: transparent;
		border-radius: 8rpx 8rpx 8rpx 8rpx;
		border: 2rpx solid rgba(255, 255, 255, 0.4);
		padding: 8rpx;
		position: absolute;
		left: 24rpx;
		bottom: 180rpx;
		justify-content: space-between;
		align-items: center;

		.good-img {
			margin-right: 0.35rem;
			width: 120rpx;
			height: 120rpx;
			flex-shrink: 0;
		}

		.text-wrap {
			padding-right: 20rpx;
			flex: 1;
			display: flex;
			flex-direction: column;
			text-align: left;
			max-width: 10rem;
			min-width: 5rem;
			font-weight: 700;
			justify-content: space-evenly;

			.desc {
				height: 40rpx;
				font-weight: 500;
				font-size: 32rpx;
				line-height: 40rpx;
				text-align: left;
				font-style: normal;
				text-transform: none;
				color: #fff;
				text-overflow: ellipsis;
				white-space: nowrap;
				overflow: hidden;
			}

			.money {
				display: flex;
				word-break: break-all;
				flex-wrap: wrap;
				padding-top: 20rpx;

				.price {
					// font-size: 13px;
					line-height: 13px;
					color: #f15353;
					margin-right: 0.5rem;
				}

				.old-price {
					font-weight: 400;
					font-size: 24rpx;
					color: rgba(255, 255, 255, 0.8);
					text-align: left;
					font-style: normal;
					text-transform: none;
					text-decoration: line-through;
				}
			}

		}

		.carImg {
			width: 56rpx;
			height: 56rpx;
		}
	}

	.video-detail-box {
		position: absolute;
		z-index: 99;
		left: 0;
		bottom: -40rpx;
		width: 100%;
		color: #fff;
		// padding-top: 2rem;

		.good-and-title {
			left: 0;
			bottom: 6.875rem;
			z-index: 99;
			display: flex;
			justify-content: space-between;
			align-items: center;

			.video-title {
				z-index: 10;
				width: 18rem;
				padding: 0.375rem 0 0 1rem;
				text-align: left;
				color: #fff;
				overflow: hidden;
				text-overflow: ellipsis;
				display: -webkit-box;
				line-clamp: 2;
				font-weight: 500;
				font-size: 36rpx;
				line-height: 40rpx;
			}


		}

		.detail-box {
			justify-content: space-between;
			background-color: #232323;
			padding: 40rpx 24rpx;
		}

		.iphoneXStyle {
			// padding-bottom: 20px;
		}

		.left-user-info {
			width: 9rem;
			display: flex;
			text-align: left;
		}

		.avatar {
			margin-right: 0.5rem;
			width: 88rpx;
			height: 88rpx;
			border: 2rpx solid #FFFFFF;
			border-radius: 50%;
			background: #fff;
		}

		.name {
			font-weight: 500;
			font-size: 28rpx;
			color: #FFFFFF;
			line-height: 40rpx;
			text-align: left;
			font-style: normal;
			text-transform: none;
		}

		.num {
			opacity: 0.6;
			font-weight: 400;
			font-size: 24rpx;
			color: #FFFFFF;
			line-height: 40rpx;
			text-align: left;
			font-style: normal;
			text-transform: none;
		}

		.center-follow {
			padding-left: 1rem;
		}

		.btn-follow {
			display: flex;
			justify-content: center;
			width: 128rpx;
			height: 64rpx;
			border-radius: 32rpx;
			line-height: 64rpx;
		}

		.rightIcon {
			padding-left: 1rem;
		}
	}

	.caBtn {
		opacity: 0.5;
		background: #555500;
	}

	.acBtn {
		background-color: #033A89;
		// opacity: 0.1;
	}

	.cont {
		// height: 200px;
		padding: 0.375rem 0;
		position: relative;

		.title {
			text-align: center;
		}

		.input-C {
			position: absolute;
			bottom: 0;
			width: 92%;
			padding-left: 0.875rem;

			.inpitBox {

				border: none;
				margin: 0.875rem auto;
				padding: 0.5rem;
				background: #eaeaea;
				border-radius: 2rem;
				display: block;

			}
		}

		.listC {
			padding: 10rpx 0 100rpx;
			height: calc(100vh - 520rpx);
			overflow: auto;

			.info {
				padding: 10rpx 0;
				font-size: 28rpx;
			}

			.item {
				font-size: 24rpx;
				padding: 0 0.875rem;

				.infoC {
					font-size: 24rpx;

					.imageC {
						width: 70rpx;
						height: 70rpx;
						border-radius: 50%;
						margin-right: 0.72rem;
					}

					.blueC {
						color: #ff6260;
					}
				}
			}

		}
	}

	.con1 {
		padding: 1rem;
	}

	.custom-input {
		flex: 1;
		width: 18.13rem;
		background-color: #f5f5f5;
		border-radius: 0.5rem;
		padding: 0.5rem;
	}

	.pop1Txt {
		color: #999;
		width: 66rpx;
		margin: 0 0.5rem;
		height: 1.88rem;
		font-size: .94rem;
		line-height: 1.88rem;
		color: #0072e8;
	}
</style>

基于css属性会超出视频个数范围,所以要加入这个:

复制代码
if (currentIndex.value >= props.videoList.length) {
			currentIndex.value = props.videoList.length - 1;
		}

代码很多不需要,懒得去了,大家可以基于自己需要作为组件传入特定的视频数组就行了

相关推荐
2501_915921436 小时前
没有Mac如何完成iOS 上架:iOS App 上架App Store流程
android·ios·小程序·https·uni-app·iphone·webview
默魔16 小时前
uniapp 微信小程序点击开始倒计时
微信小程序·小程序·uni-app
shmily ....1 天前
医疗预约系统中的录音与图片上传功能实现:Vue3+Uniapp 实战
uni-app
小阿技术1 天前
uniapp制作一个个人页面
uni-app
小阿技术1 天前
uniapp制作一个视频播放页面
uni-app
小周同学:2 天前
uni-app获取手机当前连接的WIFI名称
智能手机·uni-app
书山有路勤为径~2 天前
【解决问题】HBuilderX窗口文字太小
uni-app
qq_424409192 天前
uniapp的app项目,某个页面长时间无操作,返回首页
前端·vue.js·uni-app
2501_915918412 天前
Fiddler中文版全面评测:功能亮点、使用场景与中文网资源整合指南
android·ios·小程序·https·uni-app·iphone·webview