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"><textclass="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.idswitch (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 = truebreak;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 = 0e.support_num -= 1} else {e.is_support = 1e.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 refconst 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].pageYisSwiping.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:SSconst 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 = eplayingIndex.value = indexisControlVisible.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;}

代碼很多不需要,懶得去了,大家可以基于自己需要作為組件傳入特定的視頻數組就行了

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/914017.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/914017.shtml
英文地址,請注明出處:http://en.pswp.cn/news/914017.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Umi-OCR 的 Docker(win制作鏡像,Linux(Ubuntu Server 22.04)離線部署)

前置博客&#xff1a;Ubuntu-Server 22.04.4 詳細安裝圖文教程 wget命令在windows終端下不能使用的原因及解決辦法 在 Ubuntu 22.04 LTS 上離線安裝 Docker 手把手教你在Win11下安裝docker Umi-OCR 完整部署流程 第一步&#xff1a;在 Windows 上構建/獲取 Umi-OCR Docker…

AI Agent革命:當大模型學會使用工具、記憶與規劃

以下是針對Lilian Weng的AI Agent綜述文章&#xff08;原文鏈接&#xff09;的深度解析與整理&#xff1a; AI Agent革命&#xff1a;當大模型學會使用工具、記憶與規劃 ——解析LLM驅動的下一代智能體技術架構 一、核心范式轉變 傳統AI模型&#xff08;如ChatGPT&#xff09…

Claude Code:完爆 Cursor 的編程體驗

前言 最近&#xff0c;聽說Claude Code這款代碼輔助編寫產品很強&#xff0c;有人把Cursor比作實習生水平&#xff0c;Claude Code比作高級工程師水平。 起初不以為意&#xff0c;因為特殊原因&#xff0c;Claude 無法直接訪問。然而&#xff0c;有人做了鏡像站&#xff0c;可以…

ModbusTCP通訊

supply服務-ModbusTCP通訊&#xff1a; winForm-HZHControls-Sqllite本地小項目架構補充&#xff1a;

前端面試專欄-算法篇:23. 圖結構與遍歷算法

&#x1f525; 歡迎來到前端面試通關指南專欄&#xff01;從js精講到框架到實戰&#xff0c;漸進系統化學習&#xff0c;堅持解鎖新技能&#xff0c;祝你輕松拿下心儀offer。 前端面試通關指南專欄主頁 前端面試專欄規劃詳情 圖結構與遍歷算法 在計算機科學中&#xff0c;圖&a…

滲透測試之木馬后門實驗

一、實驗背景 根據CNCERT的監測數據顯示&#xff0c;2018年位于美國的1.4萬余臺木馬或僵尸網絡控制服務器&#xff0c;控制了中國境內334萬余臺主機&#xff1b;2018年位于美國的3325個IP地址向中國境內3607個網站植入木馬&#xff0c;根據對控制中國境內主機數量及控制中國境內…

【LeetCode 熱題 100】24. 兩兩交換鏈表中的節點——(解法一)迭代+哨兵

Problem: 24. 兩兩交換鏈表中的節點 題目&#xff1a;給你一個鏈表&#xff0c;兩兩交換其中相鄰的節點&#xff0c;并返回交換后鏈表的頭節點。你必須在不修改節點內部的值的情況下完成本題&#xff08;即&#xff0c;只能進行節點交換&#xff09;。 文章目錄整體思路完整代碼…

微積分核心考點全解析

一、微積分核心知識框架 1. 極限與連續&#xff08;重點&#xff01;&#xff09; 核心概念&#xff1a; 極限定義&#xff08;ε-δ語言&#xff09;重要極限&#xff1a;lim?x→0sin?xx1limx→0?xsinx?1&#xff0c;lim?x→∞(11x)xelimx→∞?(1x1?)xe連續性判定&am…

TypeScript---泛型

一.簡介TypeScript 就引入了“泛型”&#xff08;generics&#xff09;。泛型的特點就是帶有“類型參數”&#xff08;type parameter&#xff09;。在日常 TypeScript 編程中&#xff0c;我們經常會遇到這樣的場景&#xff1a;函數的參數類型與返回值類型密切相關。此時&#…

手把手一起使用Miniforge3+mamba平替Anaconda(Win10)

Anaconda 開始對企業收費&#xff0c;目前急需平替Anaconda。這里采用Minforgemamba作為替代&#xff0c;可以避免Anaconda追責&#xff0c;并100%兼容原conda倉庫及使用方式&#xff0c;如果各位小伙伴有更好的平替方式&#xff0c;歡迎分享。 Miniforge3安裝 下載并安裝Min…

【Note】Linux Kernel 主題學習之“完整的嵌入式 Linux 環境、構建工具、編譯工具鏈、CPU 架構”

Linux Kernel 主題學習之“完整的嵌入式 Linux 環境、構建工具、編譯工具鏈、CPU 架構” 一、完整的嵌入式 Linux 環境 一個嵌入式 Linux 系統通常包括以下關鍵組件&#xff08;以 Jetson、樹莓派等 ARM 版 SBC 為例&#xff09;&#xff1a; 交叉編譯工具鏈&#xff08;cros…

Lecture #20:Database Logging

Lecture20目錄&#xff1a;崩潰恢復緩沖池管理策略竊取策略強制策略NO-STEAL-FORCE影子分頁執行恢復缺點日志文件預寫日志&#xff08;WAL&#xff09;執行緩沖池策略日志方案檢查點崩潰恢復 恢復算法是一種確保數據庫ACID的技術&#xff0c;數據庫崩潰后&#xff0c; 所有已經…

Kubernetes高級調度1

目錄 一:初始化容器 Initcontainer 1:Initcontainer 的基本概念 2:示例 1--延遲指定時間后啟動 3:示例 2--使用初始化容器修改內核參數 4:示例 3--等待依賴服務啟動 4:pause容器 二&#xff1a;臨時容器 Ephemeral Containers 1.臨時容器的概念 2.臨時容器的使用 三&a…

服務器機柜與網絡機柜各自的優勢

一、服務器機柜優勢服務器機柜設計有強大的承重結構&#xff0c;能承受大量服務器設備堆疊產生的重量&#xff0c;保障設備安全穩定放置&#xff0c;防止因承重不足導致機柜變形甚至設備損壞&#xff0c;同時&#xff0c;服務器在運行的過程中&#xff0c;會產生大量熱量&#…

AI技術通過提示詞工程(Prompt Engineering)正在深度重塑職場生態和行業格局,這種變革不僅體現在效率提升,更在重構人機協作模式。

AI技術通過提示詞工程&#xff08;Prompt Engineering&#xff09;正在深度重塑職場生態和行業格局&#xff0c;這種變革不僅體現在效率提升&#xff0c;更在重構人機協作模式。以下是關鍵影響維度及未來趨勢分析&#xff1a;一、職場效率革命&#xff08;效率提升300%場景&…

Hugging Face 開源機器人 Reachy Mini 開啟預定

我們最新的開源機器人 Reachy Mini 正式亮相 &#x1f389; 這款富有表現力的開源機器人由 Pollen Robotics 與 Hugging Face 聯合打造&#xff0c;專為人機交互、創意編程和 AI 實驗而設計。它價格親民&#xff0c;體積小巧&#xff0c;卻蘊藏著無限可能。來自全球的各個年齡段…

vue3+node.js+mysql寫接口(二)

目錄 一、產品模塊(products表) 1.1、添加產品(/adminapi/product/add) 1.2、產品列表(/adminapi/product/list) 1.3、編輯產品(/adminapi/product/update) 1.4、首頁產品聯動 二、前臺模塊 2.1、路由配置 2.2、NavBar組件 2.3、新聞搜索 2.4、新聞選項卡 2.5、新聞…

解析LLM層裁剪:Qwen實戰指南

怎么實現對LLM 部分層裁剪輸出結果 Qwen 7b 是28層MLP,28頭 Qwen 14b 是48層MLP,40頭,詞向量維度:5120 模型加載部分 from transformers import AutoTokenizer, AutoModelForCausalLM

【AI大模型】深度學習正則化技術:Batch Normalization (BatchNorm) 詳解

1. 為什么需要 BatchNorm&#xff1f; - 問題的根源&#xff1a;Internal Covariate Shift (ICS)問題描述&#xff1a; 深度神經網絡在訓練過程中&#xff0c;隨著網絡層數的加深&#xff0c;前面層參數的微小更新會導致后面層輸入數據的分布發生顯著變化。這種現象稱為內部協變…

20.緩存問題與解決方案詳解教程

文章目錄1. 緩存基礎概念1.1 什么是緩存1.2 緩存的作用1.3 常見的緩存類型1.4 緩存架構示例2. 緩存雪崩 (Cache Avalanche)2.1 什么是緩存雪崩2.2 緩存雪崩的原因2.3 緩存雪崩的危害2.4 緩存雪崩的解決方案方案1&#xff1a;設置隨機過期時間方案2&#xff1a;緩存集群和主從復…