From 28167c45044ddb9ceff22b44e48a7ab496b8839a Mon Sep 17 00:00:00 2001
From: peng <peng.com>
Date: 星期三, 25 六月 2025 10:47:25 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev' into dev

---
 uni_modules/zero-loading/components/zero-loading/static/loading-surround.vue |   91 ++
 uni_modules/zero-loading/components/zero-loading/static/loading-sun.vue      |  140 +++
 uni_modules/zero-loading/readme.md                                           |   69 +
 uni_modules/zero-loading/components/zero-loading/static/loading-sword.vue    |   81 +
 uni_modules/zero-loading/components/zero-loading/static/loading-radar.vue    |  132 +++
 uni_modules/zero-loading/components/zero-loading/static/loading-atom.vue     |  108 ++
 pages/tabbar/index/home.vue                                                  |  158 +--
 uni_modules/zero-loading/components/zero-loading/static/loading-annulus.vue  |   45 +
 uni_modules/zero-loading/components/zero-loading/static/loading-bounce.vue   |   84 ++
 pages/video/video-edit.vue                                                   |   22 
 uni_modules/zero-loading/components/zero-loading/static/loading-pulse.vue    |   67 +
 uni_modules/zero-loading/components/zero-loading/static/loading-gear.vue     |  118 ++
 uni_modules/zero-loading/components/zero-loading/static/loading-circle.vue   |   96 ++
 uni_modules/zero-loading/changelog.md                                        |   51 +
 uni_modules/zero-loading/components/zero-loading/static/loading-locating.vue |   81 +
 uni_modules/zero-loading/package.json                                        |   83 +
 pages/video/video-goods-detail.vue                                           |   14 
 uni_modules/zero-loading/components/zero-loading/static/loading-equal.vue    |   81 +
 uni_modules/zero-loading/components/zero-loading/static/loading-eyes.vue     |   78 +
 uni_modules/zero-loading/components/zero-loading/static/loading-photo.vue    |   87 ++
 pages/tabbar/video/video.vue                                                 |   11 
 uni_modules/zero-loading/components/zero-loading/static/loading-wobble.vue   |  127 +++
 uni_modules/zero-loading/components/zero-loading/static/loading-love.vue     |  201 ++++
 pages/video/video-play.vue                                                   |  199 +++-
 uni_modules/zero-loading/components/zero-loading/zero-loading.vue            |  186 ++++
 pages/video/home-page.vue                                                    |   52 
 26 files changed, 2,236 insertions(+), 226 deletions(-)

diff --git a/pages/tabbar/index/home.vue b/pages/tabbar/index/home.vue
index 1c56703..a2cf82d 100644
--- a/pages/tabbar/index/home.vue
+++ b/pages/tabbar/index/home.vue
@@ -1,11 +1,14 @@
 <template>
   <view class="video-container">
+	<!-- 瑙嗛鍔犺浇 -->
+	<zero-loading v-show="videoLoading" type="circle" color="#0ebd57" text=""></zero-loading>
     <!-- 瑙嗛鍒楄〃 -->
     <swiper
       class="video-swiper"
       vertical
       :current="currentIndex"
       @change="onSwiperChange"
+	  :duration="250"
 	  easing-function="linear"
     >
       <swiper-item
@@ -25,14 +28,16 @@
 				<image src="/static/video/play.png" style="width: 45px;height: 45px" mode="aspectFit"></image>
 			  </view>
 			  <video
+				v-if="index >= currentIndex - videoLiveOffset && index <= currentIndex + videoLiveOffset"
 				:id="'video'+index"
 				:ref="'video'+index"
 				:src="item.videoUrl"
-				:autoplay="false"
+				:autoplay="index === currentIndex"
 				:controls="false"
 				:loop="true"
 				:object-fit="item.objectFit"
 				:enable-progress-gesture="false"
+				:show-center-play-btn="false"
 				class="video-item"
 				@play="onPlay(item.id, index)"
 				@pause="onPause(index)"
@@ -40,12 +45,13 @@
 				@click="togglePlay(index)"
 				@timeupdate="onTimeUpdate($event)"
 				@loadedmetadata="onLoadedMetadata($event)"
+				@waiting="videoWaiting(index)"
 			  ></video>
 			  <!-- 鑷畾涔夋帶鍒舵潯 -->
 			  <view
-				@touchstart="handleTouchStart"
-				@touchmove="handleTouchMove"
-				@touchend="handleTouchEnd"
+				@touchstart.stop="handleTouchStart"
+				@touchmove.stop="handleTouchMove"
+				@touchend.stop="handleTouchEnd"
 				class="container">
 				<!-- 杩涘害鏉� - 鏁翠釜鍖哄煙鍙嫋鍔� -->
 				<view class="process-warp" :style="{ opacity: showProcess ? 1 : 0 }">
@@ -300,13 +306,11 @@
 			startPlayTime: 0 // 杩欎釜瑙嗛浠庝粈涔堟椂鍊欏紑濮嬫挱鏀剧殑
 		},
 		currentVideoIsPlaying: true, // 褰撳墠瑙嗛鏄惁姝e湪鎾斁
-		isFullScreen: false,
-		windowHeight: 0,
 		currentIndex: 0, // 褰撳墠鎾斁鐨勮棰戠储寮�
+		videoLoading: false, // 瑙嗛缂撳啿涓�
 		videoList: [],   // 瑙嗛鍒楄〃鏁版嵁
-		videoContexts: [], // 瑙嗛涓婁笅鏂囧璞¢泦鍚�
 		videoBufferOffset: 0.1 ,// 瑙嗛棰勫姞杞藉弬鏁�
-		videoLiveOffset: 5, // 淇濈暀褰撳墠瑙嗛鍓嶅悗鍚勫灏戜釜瑙嗛涓婁笅鏂�
+		videoLiveOffset: 2, // 淇濈暀褰撳墠瑙嗛鍓嶅悗鍚勫灏戜釜瑙嗛涓婁笅鏂�
 		touchXY: {  // 鐩戝惉宸︽粦鍙虫粦
 			startX: 0,
 			endX: 0,
@@ -662,56 +666,6 @@
 			}
 		})
 	  },
-    // 鍒濆鍖栬棰戜笂涓嬫枃
-    initVideoContexts() {
-	  const start = Math.max(0, this.currentIndex - this.videoLiveOffset);
-	  const end = Math.min(this.currentIndex + this.videoLiveOffset, this.videoList.length - 1);
-	  let contextsLength = this.videoContexts.length;
-	  if (contextsLength === 0) {
-		  // 绗竴娆″垵濮嬪寲
-		  for (let i = 0; i < this.videoList.length; i++) {
-			if (i < start || i > end) {
-				this.videoContexts.push(null)
-			} else {
-				let videoContent = uni.createVideoContext(`video${i}`, this);
-				videoContent.seek(this.videoBufferOffset);
-				videoContent.pause();
-				this.videoContexts.push(videoContent);
-			}
-		  }
-	  } else {
-		 for (let i = 0; i < this.videoList.length; i++) {
-		 	contextsLength = this.videoContexts.length
-			if (contextsLength - 1 >= i) {
-				// 濡傛灉宸茬粡鏄痭ull浜嗗氨涓嶇敤绠★紝鍥犱负瑙嗛鍔犺浇鍙細鍦ㄥ悗闈ush锛屽墠闈㈠凡缁忚缃负null鍒欐棤闇�澶勭悊
-				if (this.videoContexts[i] == null) {
-					continue
-				}
-				// 瓒呭嚭鍙鍖栬寖鍥寸殑瑙嗛鐩存帴閲婃斁璧勬簮锛屽苟缃负null
-				if (i < start || i > end) {
-					if (this.videoContexts[i]) {
-						this.videoContexts[i].stop();
-						this.videoContexts[i] = null
-					}
-				}
-			} else {
-				if (i < start || i > end) {
-					this.videoContexts.push(null);
-				} else {
-					let videoContent = uni.createVideoContext(`video${i}`, this);
-					videoContent.seek(this.videoBufferOffset);
-					videoContent.pause();
-					this.videoContexts.push(videoContent);
-				}
-			}
-		 }
-	  }
-	  // 灏嗗綋鍓嶈棰戣缃负鎾斁
-	  if (this.videoContexts[this.currentIndex]) {
-		  this.videoContexts[this.currentIndex].play()
-	  }
-
-    },
 
     // 鍔犺浇瑙嗛鏁版嵁
     async loadVideos() {
@@ -730,9 +684,6 @@
 			  ),
 			];
 		  }
-		  this.$nextTick(() => {
-		    this.initVideoContexts();
-		  });
 		  this.loading = false;
 		  if(res.data.data.length < this.videoQuery.pageSize) {
 			  this.videoNoMore = true;
@@ -745,6 +696,7 @@
 
     // 婊戝姩鍒囨崲瑙嗛
     onSwiperChange(e) {
+		this.videoLoading = false
 		// 濡傛灉瑙嗛澶勪簬鏆傚仠鐘舵�佸線涓嬪埛瑙嗛锛岄偅涔堥渶瑕佸啀璁$畻涓�娆℃殏鍋滄椂闂�
 		if(!this.currentVideoIsPlaying) {
 			if(this.startPauseTime !== 0) {
@@ -756,49 +708,23 @@
 		this.savePlayRecord()
 		const oldIndex = this.currentIndex;
 		this.currentIndex = e.detail.current;
-
+		const videoContext = uni.createVideoContext(`video${oldIndex}`, this);
 		// 鏆傚仠涓婁竴涓棰�
-		if (this.videoContexts[oldIndex]) {
-			this.videoContexts[oldIndex].pause();
-		}
-
+		videoContext.pause();
 		this.startPauseTime = 0;
 
 		// 璁剧疆褰撳墠鎾斁瑙嗛鐨勬�绘椂闀�
 		this.duration = this.videoList[this.currentIndex].videoDuration;
 		this.formartDuration = this.sliderFormatTime(this.duration);
-		// 鎾斁褰撳墠瑙嗛
-		if (this.videoContexts[this.currentIndex]) {
-			this.videoContexts[this.currentIndex].play();
-		}
-		this.clearVideoContext()
-    },
 
-	// 娓呴櫎瓒呭嚭瑙嗛鍙鍖栧尯鍩熺殑瑙嗛涓婁笅鏂�
-    async clearVideoContext() {
-		// 瀵硅秴鍑哄彲瑙嗗寲鍖哄煙鐨勮棰戜笂涓嬫枃鍋氶攢姣佸鐞�
-		const start = Math.max(0, this.currentIndex - this.videoLiveOffset);
-		const end = Math.min(this.currentIndex + this.videoLiveOffset, this.videoList.length - 1);
-		for (let i = 0; i < this.videoContexts.length; i++) {
-			if (i < start || i > end) {
-				if (this.videoContexts[i]) {
-					this.videoContexts[i].stop();
-					this.videoContexts[i] = null
-				}
-			} else {
-				if (this.videoContexts[i] == null) {
-					let videoContent = uni.createVideoContext(`video${i}`, this);
-					videoContent.seek(this.videoBufferOffset);
-					videoContent.pause();
-					this.videoContexts[i] = videoContent;
-				}
-			}
-		}
+		// 鎾斁褰撳墠瑙嗛
+		const videoContext1 = uni.createVideoContext(`video${this.currentIndex}`, this);
+		videoContext1.play()
 		// 濡傛灉鍓╀綑瑙嗛涓嶈冻锛岃Е鍙戣姹傝幏鍙栨洿澶氳棰�
 		if (this.videoList.length - 1 < this.currentIndex + this.videoLiveOffset) {
 			this.loadVideos()
 		}
-	},
+    },
 
 	// 寮�濮嬭Е鎽�
 	handleSwiperStart(e) {
@@ -808,12 +734,15 @@
 	},
 	// 瑙︽懜涓�
 	handleSwiperMove(e) {
-		console.log("瑙︽懜涓�", e);
 	    this.touchXY.endX = e.touches[0].pageX
 	    this.touchXY.endY = e.touches[0].pageY
 	},
 	// 缁撴潫瑙︽懜
 	handleSwiperEnd(item) {
+		// 闃叉婊戝姩婊氬姩鏉′篃瑙﹀彂璺宠浆
+		if (this.showProcess) {
+			return
+		}
 	    const diffX = this.touchXY.endX - this.touchXY.startX
 	    const diffY = this.touchXY.endY - this.touchXY.startY
 
@@ -861,18 +790,16 @@
     },
     // 鍗曞嚮灞忓箷锛氭殏鍋滄垨缁х画鎾斁
 	togglePlay(index) {
-		console.log("鍗曞嚮瑙嗛", index, this.videoContexts);
+		console.log("鍗曞嚮瑙嗛", index);
+		const videoContext = uni.createVideoContext(`video${index}`, this);
 		if(this.currentVideoIsPlaying) {
-			this.videoContexts[index].pause();
+			videoContext.pause();
 		} else {
-			this.videoContexts[index].play();
+			videoContext.play();
 		}
 	},
     // 瑙嗛鎾斁浜嬩欢
     onPlay(id, index) {
-		this.getBarRect()
-		this.progress = 0
-		console.log(id, index, "瑙﹀彂鎾斁");
 		if(index === this.currentIndex) {
 			this.currentVideoIsPlaying = true;
 			if(! this.duration) {
@@ -881,9 +808,11 @@
 				this.formartDuration = this.sliderFormatTime(this.duration);
 			}
 		} else {
-			this.currentVideoIsPlaying = false;
 			return
 		}
+		this.getBarRect()
+		this.progress = 0
+		console.log(id, index, "瑙﹀彂鎾斁");
 		this.playRecord.videoId = id;
 		// 娌″垵濮嬪寲鎵嶈祴鍊硷紝鍥犱负涓�涓棰戦噸澶嶆挱鏀緊nPlay浼氶噸澶嶈Е鍙�
 		if(this.playRecord.startPlayTime === 0) {
@@ -893,7 +822,7 @@
 			const duration = Date.now() - this.startPauseTime
 			this.totalPauseTime += duration
 		}
-
+		this.videoLoading = false
     },
 
     // 瑙嗛鏆傚仠浜嬩欢
@@ -901,11 +830,8 @@
 		console.log(index, "瑙﹀彂鏆傚仠");
 		if(index === this.currentIndex) {
 			this.currentVideoIsPlaying = false;
-		} else {
-			this.currentVideoIsPlaying = true;
-			return
+			this.startPauseTime = Date.now()
 		}
-	  this.startPauseTime = Date.now()
     },
     // 瑙嗛缁撴潫浜嬩欢
     onEnded(index) {
@@ -914,6 +840,7 @@
 
 	// 璁板綍鎾斁鏃堕暱
 	onTimeUpdate(e) {
+		this.videoLoading = false
 		this.playRecord.playAt = e.detail.currentTime;
 
 		this.currentTime = e.detail.currentTime;
@@ -926,7 +853,8 @@
 	  this.startProgress = this.progress; // 璁板綍寮�濮嬫椂鐨勮繘搴�
 	  this.startX = e.touches[0].pageX;
 	  console.log("璁板綍寮�濮嬫椂鐨勮繘搴�", this.startProgress);
-	  this.videoContexts[this.currentIndex].pause()
+	  const videoContext = uni.createVideoContext(`video${this.currentIndex}`, this);
+	  videoContext.pause()
 	  // this.updateProgress(e);
 	},
 
@@ -934,7 +862,6 @@
 	handleTouchMove(e) {
 	  if (!this.isDragging || !this.barWidth) return;
 	  clearTimeout(this.processHidenTimer)
-	  this.videoContexts[this.currentIndex].pause()
 	  this.updateProgress(e);
 	},
 
@@ -942,8 +869,9 @@
 	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()
+	  const videoContext = uni.createVideoContext(`video${this.currentIndex}`, this);
+	  videoContext.seek(this.duration * this.progress / 100)
+	  videoContext.play()
 	  this.processHidenTimer = setTimeout(() => {
 		  this.showProcess = false;
 		}, 1000);
@@ -959,7 +887,6 @@
 
 		// 灏嗗儚绱犺窛绂昏浆鎹负杩涘害澧為噺
 		const deltaProgress = (deltaX / this.barWidth) * 100;
-		console.log("杩涘害澧為噺", deltaProgress);
 		// 璁$畻鏂拌繘搴� = 寮�濮嬫椂鐨勮繘搴� + 婊戝姩澧為噺
 		let newProgress = this.startProgress + deltaProgress;
 
@@ -967,6 +894,13 @@
 		newProgress = Math.max(0, Math.min(100, newProgress));
 
 		this.progress = newProgress;
+	},
+	// 瑙嗛缂撳啿
+	videoWaiting(index) {
+		if (index === this.currentIndex) {
+			console.log("瑙嗛缂撳啿涓�傘�傘��");
+			this.videoLoading = true;
+		}
 	},
 	// 鑾峰彇瑙嗛鎬绘椂闀�
 	onLoadedMetadata(e) {
@@ -1015,7 +949,7 @@
 	.video-item {
 	  width: 100%;
 	  height: 100%;
-	  object-fit: cover;
+	  /* object-fit: cover; */
 	}
 	.play-icon {
 	  position: absolute;
diff --git a/pages/tabbar/video/video.vue b/pages/tabbar/video/video.vue
index af7dfeb..619c135 100644
--- a/pages/tabbar/video/video.vue
+++ b/pages/tabbar/video/video.vue
@@ -132,7 +132,7 @@
 					<view class="goods-price" style="flex: 1;">楼{{ goods.price }}</view>
 					<view @click.stop="() => {}" style="flex: 1;display: flex;justify-content: center;align-items: center;">
 						<view style="width: 90rpx">鏁伴噺锛�</view>
-						<uni-number-box v-model="goods.goodsNum" :min="0"/>
+						<uni-number-box v-model="goods.goodsNum" :min="1"/>
 					</view>
 				</view>
               </view>
@@ -249,7 +249,6 @@
 		videoFileKey: '',
 		videoDuration: 0,
 		videoFit: 'cover',
-        goodsId: '',
         videoContentType: 'video',
         videoImgs: [],
         tags: [],
@@ -543,10 +542,9 @@
     // 閫夋嫨鍟嗗搧
     chooseGoods() {
 	  if(this.selectedGoodsList.length > 0) {
-	  		  const selectedGoodsIds = new Set(this.selectedGoodsList.map(i => i.goodsId));
-	  			  console.log(selectedGoodsIds, "mimade");
+	  		  const selectedGoodsSkuIds = new Set(this.selectedGoodsList.map(i => i.id));
 	  		  this.goodsList?.forEach(goods => {
-	  		      this.$set(goods, 'selected', selectedGoodsIds.has(goods.goodsId));
+	  		      this.$set(goods, 'selected', selectedGoodsSkuIds.has(goods.id));
 	  		    });
 	  }
       this.showGoodsPicker = true;
@@ -638,7 +636,7 @@
         if (valid && this.canPublish) {
           this.loading = true;
           this.formData.fileInfo = this.videoInfo;
-		  this.formData["goodsList"] = this.selectedGoodsList.map(item => {return {goodsId: item.goodsId, goodsNum: item.goodsNum}});
+		  this.formData["goodsList"] = this.selectedGoodsList.map(item => {return {goodsId: item.goodsId, goodsSkuId: item.id, goodsNum: item.goodsNum}});
           publish(this.formData).then(res => {
 			  uni.showToast({
 			    title: '瑙嗛宸叉彁浜ゅ鏍竳',
@@ -683,7 +681,6 @@
 		  cover: '',
 		  videoFit: 'cover',
 		  videoDuration: 0,
-		  goodsId: '',
 		  videoContentType: 'video',
 		  videoImgs: [],
 		  tags: [],
diff --git a/pages/video/home-page.vue b/pages/video/home-page.vue
index 5ce3063..4aebb07 100644
--- a/pages/video/home-page.vue
+++ b/pages/video/home-page.vue
@@ -24,47 +24,47 @@
           <text class="stat-label">鑾疯禐</text>
         </view>
       </view>
-      
+
       <!-- 鍏虫敞鎸夐挳 -->
       <view class="follow-btn-container" v-if="!userInfo.self">
-        <button 
-          class="follow-btn" 
-          :class="{followed: userInfo.hasSub}" 
+        <button
+          class="follow-btn"
+          :class="{followed: userInfo.hasSub}"
           @click="toggleFollow"
         >
           {{userInfo.hasSub ? '鍙栨秷鍏虫敞' : '鍏虫敞'}}
         </button>
       </view>
-	  
+
 	  <view class="edit-icon" @click="editInfo" v-if="userInfo.self">
 	    <uni-icons type="compose" size="20" color="#666"></uni-icons>缂栬緫涓婚〉淇℃伅
 	  </view>
     </view>
-    
+
         <!-- 浣滃搧/鍠滄鍒囨崲 -->
         <view class="tab-bar">
-          <view 
-            class="tab-item" 
-            :class="{active: currentTab === 'works'}" 
+          <view
+            class="tab-item"
+            :class="{active: currentTab === 'works'}"
             @click="switchTab('works')"
           >
             浣滃搧{{`(${videoTotal})`}}
           </view>
-          <view 
-            class="tab-item" 
-            :class="{active: currentTab === 'likes'}" 
+          <view
+            class="tab-item"
+            :class="{active: currentTab === 'likes'}"
             @click="switchTab('likes')"
           >
             鍠滄
           </view>
         </view>
-        
+
         <!-- 瑙嗛鍒楄〃 -->
 		<scroll-view class="video-list" scroll-y :show-scrollbar="false" @scrolltolower="getPage" v-show="currentTab === 'works' && videoList.length > 0">
 			<view class="video-container">
 				<view
-				  class="video-item" 
-				  v-for="(item, index) in videoList" 
+				  class="video-item"
+				  v-for="(item, index) in videoList"
 				  :key="item.id"
 				>
 				  <image class="video-cover" @click="playAuthorVideo(index)" :src="item.videoContentType === 'video' ? item.coverUrl : item.imgs[0]" mode="aspectFill"></image>
@@ -91,8 +91,8 @@
 		<scroll-view class="video-list" scroll-y :show-scrollbar="false" @scrolltolower="getPage" v-show="currentTab === 'likes' && collectVideoList.length > 0">
 			<view class="video-container">
 				<view
-				  class="video-item" 
-				  v-for="(item, index) in collectVideoList" 
+				  class="video-item"
+				  v-for="(item, index) in collectVideoList"
 				  :key="item.id"
 				  @click="playCollectVideo(index)"
 				>
@@ -105,10 +105,10 @@
 				      </view>
 				    </view>
 				  </view>
-				</view> 
+				</view>
 			</view>
 		</scroll-view>
-        
+
         <!-- 绌虹姸鎬� -->
         <view class="empty-state" v-if="videoList.length === 0 && currentTab === 'works'">
           <!-- <image src="/static/images/empty.png" mode="aspectFit" class="empty-image"></image> -->
@@ -119,13 +119,13 @@
 		  <!-- <image src="/static/images/empty.png" mode="aspectFit" class="empty-image"></image> -->
 		  <text class="empty-text">杩樻病鏈夌偣璧炰綔鍝佸摝~</text>
 		</view>
-		
+
 		<!-- 鍒犻櫎瑙嗛鎻愰啋妗� -->
 		<uni-popup ref="delDialog" type="dialog">
 			<uni-popup-dialog type="error" cancelText="鍙栨秷" confirmText="鍒犻櫎" title="鎻愰啋" :content="`鎮ㄦ鍦ㄥ垹闄わ細${opVideo.title}`" @confirm="deleteVideo"
 				@close="dialogClose"></uni-popup-dialog>
 		</uni-popup>
-		
+
 		<!-- 涓嬫灦瑙嗛鎻愰啋妗� -->
 		<uni-popup ref="downDialog" type="dialog">
 			<uni-popup-dialog type="error" cancelText="鍙栨秷" confirmText="涓嬫灦" title="鎻愰啋" :content="`鎮ㄦ鍦ㄤ笅鏋讹細${opVideo.title}`" @confirm="downVideo"
@@ -383,14 +383,14 @@
         url: `/pages/video/home-page-edit?authorId=${this.authorId}&avatar=${this.userInfo.avatar}&motto=${this.userInfo.motto || ''}&nickName=${this.userInfo.nickName}`
       });
     },
-    
+
     // 璺宠浆鍒扮矇涓�/鍏虫敞鍒楄〃
     navigateToFollow(type) {
       uni.navigateTo({
         url: `/pages/user/follow?type=${type}`
       });
     },
-    
+
     // 璺宠浆鍒扮偣璧炲垪琛�
     navigateToLike() {
       uni.navigateTo({
@@ -624,15 +624,15 @@
   height: 70rpx;
   line-height: 70rpx;
   padding: 0 40rpx;
-  
+
   &::after {
     border: none;
   }
-  
+
   &.followed {
     background-color: #f5f5f5;
     color: #666;
   }
 }
 
-</style>
\ No newline at end of file
+</style>
diff --git a/pages/video/video-edit.vue b/pages/video/video-edit.vue
index 1b51fe7..bfa119a 100644
--- a/pages/video/video-edit.vue
+++ b/pages/video/video-edit.vue
@@ -132,7 +132,7 @@
 					<view class="goods-price" style="flex: 1;">楼{{ goods.price }}</view>
 					<view @click.stop="() => {}" style="flex: 1;display: flex;justify-content: center;align-items: center;">
 						<view style="width: 90rpx">鏁伴噺锛�</view>
-						<uni-number-box v-model="goods.goodsNum" :min="0"/>
+						<uni-number-box v-model="goods.goodsNum" :min="1"/>
 					</view>
 				</view>
               </view>
@@ -250,7 +250,6 @@
 		videoFileKey: '',
 		videoDuration: 0,
 		videoFit: 'cover',
-        goodsId: '',
         videoContentType: 'video',
         videoImgs: [],
         tags: [],
@@ -306,7 +305,7 @@
 	  		  getVideoDetail(id).then(res => {
 	  			  this.videoInfo.cover = res.data.data.coverUrl
 	  			  this.videoInfo.url = res.data.data.videoUrl
-				  this.formData.videoImgs = res.data.data.imgs
+				  this.formData.videoImgs = res.data.data.videoImgs
 				  this.formData.videoContentType = res.data.data.videoContentType
 	  			  this.formData.cover = res.data.data.coverFileKey
 	  			  this.formData.id = res.data.data.id
@@ -316,6 +315,9 @@
 	  			  this.formData.videoDuration = res.data.data.videoDuration
 	  			  this.selectedGoodsList = res.data.data.goodsList
 	  			  this.formData.tags = res.data.data.tags
+				  if (this.formData.videoContentType === 'img') {
+					  this.videoPreviewImgs = res.data.data.imgs
+				  }
 				  this.showUploadProgress = false
 	  			  console.log("瑙嗛璇︽儏", this.formData);
 	  		  })
@@ -565,10 +567,9 @@
     // 閫夋嫨鍟嗗搧
     chooseGoods() {
 	  if(this.selectedGoodsList.length > 0) {
-	  		  const selectedGoodsIds = new Set(this.selectedGoodsList.map(i => i.goodsId));
-			  console.log(selectedGoodsIds, "mimade");
+	  		  const selectedGoodsSkuIds = new Set(this.selectedGoodsList.map(i => i.id));
 	  		  this.goodsList?.forEach(goods => {
-	  		      this.$set(goods, 'selected', selectedGoodsIds.has(goods.goodsId));
+	  		      this.$set(goods, 'selected', selectedGoodsSkuIds.has(goods.id));
 	  		    });
 	  }
       this.showGoodsPicker = true;
@@ -660,7 +661,7 @@
         if (valid && this.canPublish) {
           this.loading = true;
           this.formData.fileInfo = this.videoInfo;
-		  this.formData["goodsList"] = this.selectedGoodsList.map(item => {return {goodsId: item.goodsId, goodsNum: item.goodsNum}});
+		  this.formData["goodsList"] = this.selectedGoodsList.map(item => {return {goodsId: item.goodsId, goodsSkuId: item.id, goodsNum: item.goodsNum}});
           updateVideo(this.formData).then(res => {
 			  uni.showToast({
 			    title: '瑙嗛宸叉彁浜ゅ鏍竳',
@@ -673,10 +674,10 @@
 			  this.tagInput = '';
 			  this.recommendedTags = [];
 
-			  // TODO 鍏堣烦棣栭〉,鍚庨潰璺虫垜鐨勮棰戦〉闈�
+			  // 璺虫垜鐨勮棰戦〉闈�
 			  setTimeout(() => {
-			    uni.switchTab({
-			    	url: '/pages/tabbar/index/home'
+			    uni.navigateBack({
+			    	delta: 1
 			    });
 			  }, 1500);
 		  })
@@ -705,7 +706,6 @@
 		  cover: '',
 		  videoFit: 'cover',
 		  videoDuration: 0,
-		  goodsId: '',
 		  videoContentType: 'video',
 		  videoImgs: [],
 		  tags: [],
diff --git a/pages/video/video-goods-detail.vue b/pages/video/video-goods-detail.vue
index 9d06578..a8fc8a1 100644
--- a/pages/video/video-goods-detail.vue
+++ b/pages/video/video-goods-detail.vue
@@ -29,7 +29,7 @@
 
 <script>
 	import {getGoodsDetail} from "@/api/video.js"
-	
+	import { buyBack } from "@/api/trade.js";
 	import '@/components/uview-components/uview-ui';
 	export default {
 		computed: {
@@ -61,7 +61,17 @@
 			},
 			// 鐢熸垚璁㈠崟-鏀粯
 			toPay() {
-				
+				const buyList = this.goodsList.map(goods => {
+					return {
+						skuId: goods.id,
+						num: goods.goodsNum
+					}
+				})
+				buyBack(buyList).then(res => {
+					uni.navigateTo({
+						url: "/pages/order/fillorder?way=CART"
+					})
+				})
 			}
 		}
 	}
diff --git a/pages/video/video-play.vue b/pages/video/video-play.vue
index 4cf61c2..e16b6ac 100644
--- a/pages/video/video-play.vue
+++ b/pages/video/video-play.vue
@@ -1,32 +1,43 @@
 <template>
   <view class="video-container">
+	<!-- 瑙嗛鍔犺浇 -->
+	<zero-loading v-show="videoLoading" type="circle" color="#0ebd57" text=""></zero-loading>
     <!-- 瑙嗛鍒楄〃 -->
     <swiper 
       class="video-swiper" 
       vertical 
-      circular 
       :current="currentIndex"
       @change="onSwiperChange"
+	  :duration="250"
+	  easing-function="linear"
     >
-      <swiper-item v-for="(item, index) in videoList" :key="item.id">
+      <swiper-item
+		v-for="(item, index) in videoList"
+		:key="item.id"
+		@touchstart="handleSwiperStart"
+		@touchmove="handleSwiperMove"
+		@touchend="handleSwiperEnd(item)"
+		 >
       	<view style="width: 100%;height: 100%;" v-if="item.videoContentType === 'video'">
       		  <!-- 鎾斁鎸夐挳锛堜粎褰撹棰戞殏鍋滄椂鏄剧ず锛� -->
       		  <view 
       			class="play-icon" 
       			@click="togglePlay(index)"
-      			v-if="!currentVideoIsPlaying"
+      			v-show="!currentVideoIsPlaying"
       		  >
       			<image src="/static/video/play.png" style="width: 45px;height: 45px" mode="aspectFit"></image>
       		  </view>
       		  <video
+				v-if="index >= currentIndex - videoLiveOffset && index <= currentIndex + videoLiveOffset"
       			:id="'video'+index"
       			:ref="'video'+index"
       			:src="item.videoUrl"
-      			:autoplay="currentIndex === index"
+      			:autoplay="index === currentIndex"
       			:controls="false"
       			:loop="true"
       			:object-fit="item.objectFit"
       			:enable-progress-gesture="false"
+				:show-center-play-btn="false"
       			class="video-item"
       			@play="onPlay(item.id, index)"
       			@pause="onPause(index)"
@@ -34,13 +45,13 @@
       			@click="togglePlay(index)"
       			@timeupdate="onTimeUpdate($event)"
       			@loadedmetadata="onLoadedMetadata($event)"
-      			
+      			@waiting="videoWaiting(index)"
       		  ></video>
       		  <!-- 鑷畾涔夋帶鍒舵潯 -->
       		  <view 
-      			@touchstart="handleTouchStart"
-      			@touchmove="handleTouchMove"
-      			@touchend="handleTouchEnd"
+      			@touchstart.stop="handleTouchStart"
+      			@touchmove.stop="handleTouchMove"
+      			@touchend.stop="handleTouchEnd"
       			class="container">
       			<!-- 杩涘害鏉� - 鏁翠釜鍖哄煙鍙嫋鍔� -->
       			<view class="process-warp" :style="{ opacity: showProcess ? 1 : 0 }">
@@ -291,24 +302,28 @@
 			startPlayTime: 0 // 杩欎釜瑙嗛浠庝粈涔堟椂鍊欏紑濮嬫挱鏀剧殑
 		},
 		currentVideoIsPlaying: true, // 褰撳墠瑙嗛鏄惁姝e湪鎾斁
-		isFullScreen: false,
-		windowHeight: 0,
 		currentIndex: 0, // 褰撳墠鎾斁鐨勮棰戠储寮�
-		videoList: [
-		  
-		],   // 瑙嗛鍒楄〃鏁版嵁
-		videoContexts: [], // 瑙嗛涓婁笅鏂囧璞¢泦鍚�
+		videoLoading: false, // 瑙嗛缂撳啿涓�
+		videoList: [],   // 瑙嗛鍒楄〃鏁版嵁
+		videoBufferOffset: 0.1 ,// 瑙嗛棰勫姞杞藉弬鏁�
+		videoLiveOffset: 2, // 淇濈暀褰撳墠瑙嗛鍓嶅悗鍚勫灏戜釜瑙嗛涓婁笅鏂�
+		touchXY: {  // 鐩戝惉宸︽粦鍙虫粦
+			startX: 0,
+			endX: 0,
+			startY: 0,
+			endY: 0
+		},
 		loading: false,  // 鏄惁姝e湪鍔犺浇
 		videoQuery: {
 			pageNumber: 1,
-			pageSize: 6,
+			pageSize: 10,
 			authorId: '',
 			videoFrom: ''
 		}
     }
   },
   onShow() {
-	  this.loadVideos()
+	  // this.loadVideos()
 	  // 濡傛灉瑙嗛鎸変笅鏆傚仠鍚庡垏鎹㈤〉闈㈠啀鍥炲埌椤甸潰鏃讹紝鍙畻鏆傚仠鏃堕棿锛堝洜涓烘殏鍋滄椂闂村拰绂诲紑椤甸潰鏃堕棿鏄噸澶嶇殑锛屽彧绠椾竴涓級
 	  if(this.startHidenTime !== 0 && this.currentVideoIsPlaying) {
 		  const duration = Date.now() - this.startHidenTime
@@ -321,24 +336,28 @@
   onUnload() {
 	  uni.removeStorageSync("playInfo");
   },
+  onReady() {
+  	
+  },
   onLoad(option) {
 	  const playInfo = uni.getStorageSync("playInfo", playInfo);
 	  if(playInfo) {
+		  this.currentIndex = playInfo.playIndex;
 		  this.videoList = playInfo.videoList;
 		  console.log("鎷垮埌鏁版嵁浜�",playInfo);
 		  this.videoQuery.pageNumber = playInfo.pageNumber;
 		  this.videoNoMore = playInfo.nomore;
 		  this.videoQuery.authorId = option.authorId;
 		  this.videoQuery.videoFrom = option.videoFrom;
-		  this.currentIndex = playInfo.playIndex;
+		  this.currentVideoIsPlaying = true;
+		  this.$nextTick(() => {
+			  const videoContext = uni.createVideoContext(`video${this.currentIndex}`, this);
+			  videoContext.play()
+		  })
 	  } else {
 		  this.videoQuery.videoFrom = 'recommend';
 		  this.loadVideos();
 	  }
-  },
-  onReady() {
-    // 鍒濆鍖栬棰戜笂涓嬫枃
-    this.initVideoContexts();
   },
   onShareAppMessage(e) {
   	const userInfo = storage.getUserInfo();
@@ -623,13 +642,6 @@
 			}
 		})
 	  },
-    // 鍒濆鍖栬棰戜笂涓嬫枃
-    initVideoContexts() {
-      this.videoContexts = this.videoList.map((_, index) => {
-		  let videoContent = uni.createVideoContext(`video${index}`, this);
-		  return videoContent;
-      });
-    },
     
     // 鍔犺浇瑙嗛鏁版嵁
     async loadVideos() {
@@ -647,9 +659,6 @@
 		      ),
 		    ];
 		  }
-		  this.$nextTick(() => {
-		    this.initVideoContexts();
-		  });
 		  this.loading = false;
 		  if(res.data.data.length < this.videoQuery.pageSize) {
 			  this.videoNoMore = true;
@@ -661,29 +670,75 @@
     
     // 婊戝姩鍒囨崲瑙嗛
     onSwiperChange(e) {
-		// 濡傛灉瑙嗛澶勪簬鏆傚仠鐘舵�佸線涓嬪埛瑙嗛锛岄偅涔堥渶瑕佸啀璁$畻涓�娆℃殏鍋滄椂闂�
-		if(!this.currentVideoIsPlaying) {
-			if(this.startPauseTime !== 0) {
-				const duration = Date.now() - this.startPauseTime
-				this.totalPauseTime += duration
-			}
-		}
-		// 淇濆瓨涓婁竴涓棰戠殑鎾斁璁板綍
-		this.savePlayRecord()
-		const oldIndex = this.currentIndex;
-		this.currentIndex = e.detail.current;
-
-		// 鏆傚仠涓婁竴涓棰�
-		if (this.videoContexts[oldIndex]) {
-			this.videoContexts[oldIndex].pause();
+		this.videoLoading = false
+    	// 濡傛灉瑙嗛澶勪簬鏆傚仠鐘舵�佸線涓嬪埛瑙嗛锛岄偅涔堥渶瑕佸啀璁$畻涓�娆℃殏鍋滄椂闂�
+    	if(!this.currentVideoIsPlaying) {
+    		if(this.startPauseTime !== 0) {
+    			const duration = Date.now() - this.startPauseTime
+    			this.totalPauseTime += duration
+    		}
+    	}
+    	// 淇濆瓨涓婁竴涓棰戠殑鎾斁璁板綍
+    	this.savePlayRecord()
+    	const oldIndex = this.currentIndex;
+    	this.currentIndex = e.detail.current;
+    	const videoContext = uni.createVideoContext(`video${oldIndex}`, this);
+    	// 鏆傚仠涓婁竴涓棰�
+    	videoContext.pause();
+    	this.startPauseTime = 0;
+    	
+    	// 璁剧疆褰撳墠鎾斁瑙嗛鐨勬�绘椂闀�
+    	this.duration = this.videoList[this.currentIndex].videoDuration;
+    	this.formartDuration = this.sliderFormatTime(this.duration);
+    	
+    	// 鎾斁褰撳墠瑙嗛
+    	const videoContext1 = uni.createVideoContext(`video${this.currentIndex}`, this);
+    	videoContext1.play()
+    	// 濡傛灉鍓╀綑瑙嗛涓嶈冻锛岃Е鍙戣姹傝幏鍙栨洿澶氳棰�
+    	if (this.videoList.length - 1 < this.currentIndex + this.videoLiveOffset) {
+    		this.loadVideos()
+    	}
+    },
+	
+	// 寮�濮嬭Е鎽�
+	handleSwiperStart(e) {
+	    this.touchXY.startX = e.touches[0].pageX
+	    this.touchXY.startY = e.touches[0].pageY
+	},
+	// 瑙︽懜涓�
+	handleSwiperMove(e) {
+	    this.touchXY.endX = e.touches[0].pageX
+	    this.touchXY.endY = e.touches[0].pageY
+	},
+	// 缁撴潫瑙︽懜
+	handleSwiperEnd(item) {
+		// 闃叉婊戝姩婊氬姩鏉′篃瑙﹀彂璺宠浆
+		if (this.showProcess) {
+			return
 		}
 		
-		this.startPauseTime = 0;
-		// 鎾斁褰撳墠瑙嗛
-		if (this.videoContexts[this.currentIndex]) {
-			this.videoContexts[this.currentIndex].play();
+	    const diffX = this.touchXY.endX - this.touchXY.startX
+	    const diffY = this.touchXY.endY - this.touchXY.startY
+	
+	    // 鍒ゆ柇鏄惁鏄í鍚戞粦鍔紙X杞村彉鍖栧ぇ浜嶻杞村彉鍖栵級
+	    if (Math.abs(diffX) > Math.abs(diffY)) {
+	      if (diffX > 0) {
+	        console.log('鍙虫粦')
+			if (item.goodsList && item.goodsList.length > 0) {
+				this.jumpToPay(item.id)
+			}
+	      } else {
+	        console.log('宸︽粦')
+	      }
+	    }
+	    // 閲嶇疆鍧愭爣
+	    this.touchXY = {
+			startX: 0,
+			endX: 0,
+			startY: 0,
+			endY: 0
 		}
-    },
+	},
 	
 	// 鑾峰彇杩涘害鏉$殑浣嶇疆鍜屽昂瀵�
 	getBarRect() {
@@ -703,7 +758,8 @@
 	  this.startProgress = this.progress; // 璁板綍寮�濮嬫椂鐨勮繘搴�
 	  this.startX = e.touches[0].pageX;
 	  console.log("璁板綍寮�濮嬫椂鐨勮繘搴�", this.startProgress);
-	  this.videoContexts[this.currentIndex].pause()
+	  const videoContext = uni.createVideoContext(`video${this.currentIndex}`, this);
+	  videoContext.pause()
 	  // this.updateProgress(e);
 	},
 	
@@ -711,7 +767,6 @@
 	handleTouchMove(e) {
 	  if (!this.isDragging || !this.barWidth) return;
 	  clearTimeout(this.processHidenTimer)
-	  this.videoContexts[this.currentIndex].pause()
 	  this.updateProgress(e);
 	},
 	
@@ -719,11 +774,12 @@
 	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()
+	  const videoContext = uni.createVideoContext(`video${this.currentIndex}`, this);
+	  videoContext.seek(this.duration * this.progress / 100)
+	  videoContext.play()
 	  this.processHidenTimer = setTimeout(() => {
-		  this.showProcess = false;
-		}, 1000);
+	  		  this.showProcess = false;
+	  		}, 1000);
 	},
 	
 	// 鏇存柊杩涘害
@@ -736,7 +792,6 @@
 		
 		// 灏嗗儚绱犺窛绂昏浆鎹负杩涘害澧為噺
 		const deltaProgress = (deltaX / this.barWidth) * 100;
-		console.log("杩涘害澧為噺", deltaProgress);
 		// 璁$畻鏂拌繘搴� = 寮�濮嬫椂鐨勮繘搴� + 婊戝姩澧為噺
 		let newProgress = this.startProgress + deltaProgress;
 		
@@ -770,16 +825,16 @@
     },
     // 鍗曞嚮灞忓箷锛氭殏鍋滄垨缁х画鎾斁
 	togglePlay(index) {
+		console.log("鍗曞嚮瑙嗛", index);
+		const videoContext = uni.createVideoContext(`video${index}`, this);
 		if(this.currentVideoIsPlaying) {
-			this.videoContexts[index].pause();
+			videoContext.pause();
 		} else {
-			this.videoContexts[index].play();
+			videoContext.play();
 		}
 	},
     // 瑙嗛鎾斁浜嬩欢
     onPlay(id, index) {
-		this.getBarRect()
-		this.progress = 0
 		if(index === this.currentIndex) {
 			this.currentVideoIsPlaying = true;
 			if(! this.duration) {
@@ -788,9 +843,11 @@
 				this.formartDuration = this.sliderFormatTime(this.duration);
 			}
 		} else {
-			this.currentVideoIsPlaying = false;
 			return
 		}
+		this.getBarRect()
+		this.progress = 0
+		console.log(id, index, "瑙﹀彂鎾斁");
 		this.playRecord.videoId = id;
 		// 娌″垵濮嬪寲鎵嶈祴鍊硷紝鍥犱负涓�涓棰戦噸澶嶆挱鏀緊nPlay浼氶噸澶嶈Е鍙�
 		if(this.playRecord.startPlayTime === 0) {
@@ -800,6 +857,7 @@
 			const duration = Date.now() - this.startPauseTime
 			this.totalPauseTime += duration
 		}
+		this.videoLoading = false
     },
     
     // 瑙嗛鏆傚仠浜嬩欢
@@ -807,11 +865,8 @@
 		console.log(index, "瑙﹀彂鏆傚仠");
 		if(index === this.currentIndex) {
 			this.currentVideoIsPlaying = false;
-		} else {
-			this.currentVideoIsPlaying = true;
-			return
+			this.startPauseTime = Date.now()
 		}
-	  this.startPauseTime = Date.now()
     },
     
     // 瑙嗛缁撴潫浜嬩欢
@@ -821,9 +876,17 @@
 	
 	// 璁板綍鎾斁鏃堕暱
 	onTimeUpdate(e) {
+		this.videoLoading = false
 		this.playRecord.playAt = e.detail.currentTime
 		this.currentTime = e.detail.currentTime;
 		this.progress = (e.detail.currentTime / this.duration) * 100
+	},
+	// 瑙嗛缂撳啿
+	videoWaiting(index) {
+		if (index === this.currentIndex) {
+			console.log("瑙嗛缂撳啿涓�傘�傘��");
+			this.videoLoading = true;
+		}
 	},
 	// 鑾峰彇瑙嗛鎬绘椂闀�
 	onLoadedMetadata(e) {
@@ -872,7 +935,7 @@
 	.video-item {
 	  width: 100%;
 	  height: 100%;
-	  object-fit: cover;
+	  /* object-fit: cover; */
 	}
 	.play-icon {
 	  position: absolute;
diff --git a/uni_modules/zero-loading/changelog.md b/uni_modules/zero-loading/changelog.md
new file mode 100644
index 0000000..af6947d
--- /dev/null
+++ b/uni_modules/zero-loading/changelog.md
@@ -0,0 +1,51 @@
+## 1.4.2锛�2025-04-03锛�
+## 澧炲姞涓や釜鍔ㄧ敾
+| locating | 瀹氫綅 (鑷畾涔夐鑹�) |
+| photo    | 鐓х墖 (鑷畾涔夐鑹�) |
+## 1.4.1锛�2024-07-02锛�
+### 1. 澧炲姞鍔ㄧ敾equal(绛夎竟), wobble(鎽囨憜)
+### 2. 鍘熸潵鐨則riangle(涓夎)鏀逛负surround(鐜粫)
+### 3. 鏂板鍙嚜瀹氫箟棰滆壊椤�
+## 1.4.0锛�2024-06-28锛�
+
+## 澧炲姞 loading 鍔犺浇鏂囧瓧鎻愰啋閰嶇疆椤�,榛樿 false
+
+## 1.3.2锛�2023-10-31锛�
+
+淇敼閬僵榛樿閫忔槑搴︿负 0.1
+
+## 1.3.1锛�2023-10-31锛�
+
+## 鏂板鏀寔,鑷畾涔夊姩鐢婚鑹�(浠呴儴鍒嗗姩鐢绘敮鎸�)
+
+## 鏂板鍔ㄧ敾-annulus(鍦嗙幆)
+
+## 1.3.0锛�2023-08-11锛�
+
+鏀寔 vue3 浣跨敤, 澧炲姞鍔ㄧ敾绫诲瀷 radar(闆疯揪)
+
+## 1.2.2锛�2023-06-12锛�
+
+澧炲姞 maskOpacity, maskMini, maskDark 鑷畾涔夊弬鏁�, 鎻愪緵鏇翠赴瀵岀殑鑷畾涔夐伄缃╁眰鑳藉姏
+
+## 1.2.1锛�2022-09-09锛�
+
+澧炲姞榻胯疆鍔ㄧ敾 type=gear
+
+## 1.2.0锛�2022-05-27锛�
+
+1. 澧炲姞鍔犺浇绫诲瀷-鍓戞皵锛坰word锛夛紝鍘熷瓙锛坅tom锛�
+2. 榛樿绫诲瀷鏀逛负 atom
+3. 閬僵閫忔槑搴﹁皟鏁�
+
+## 1.1.1锛�2022-04-02锛�
+
+鏇存柊浣跨敤璇存槑
+
+## 1.1.0锛�2022-02-23锛�
+
+澧炲姞 type="love" 鐨勫績褰㈠姞杞藉姩鐢�
+
+## 1.0.0锛�2022-01-28锛�
+
+棣栨鍙戝竷
diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-annulus.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-annulus.vue
new file mode 100644
index 0000000..260301f
--- /dev/null
+++ b/uni_modules/zero-loading/components/zero-loading/static/loading-annulus.vue
@@ -0,0 +1,45 @@
+<template>
+  <view class="animations">
+    <view class="loader" :style="{ '--color': color }"></view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: "loading-annulus",
+  props: {
+    color: {
+      type: String,
+      default: "#0396FF",
+    },
+  },
+  data() {
+    return {};
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.loader {
+  width: 60px;
+  height: 60px;
+}
+
+.loader::before {
+  content: "";
+  box-sizing: border-box;
+  position: absolute;
+  width: 60px;
+  height: 60px;
+  border-radius: 50%;
+  border-top: 2px solid var(--color);
+  border-right: 2px solid transparent;
+  animation: spinner 1s linear infinite;
+}
+
+@keyframes spinner {
+  to {
+    transform: rotate(360deg);
+  }
+}
+</style>
diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-atom.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-atom.vue
new file mode 100644
index 0000000..3b3b75e
--- /dev/null
+++ b/uni_modules/zero-loading/components/zero-loading/static/loading-atom.vue
@@ -0,0 +1,108 @@
+<template>
+  <view class="animations">
+    <view class="box" :style="{ '--color': color }">
+      <view class="atom"></view>
+      <view class="atom"></view>
+      <view class="atom"></view>
+      <view class="dot"></view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: "loading-atom",
+  props: {
+    color: {
+      type: String,
+      default: "#0396FF",
+    },
+  },
+  data() {
+    return {};
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.box {
+  position: relative;
+  width: 120rpx;
+  height: 120rpx;
+}
+.dot {
+  position: absolute;
+  width: 10px;
+  height: 10px;
+  border-radius: 50%;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  background: var(--color);
+  animation: dotbreath 2s linear infinite;
+}
+.atom {
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  border-radius: 50%;
+  border-left-width: 6rpx;
+  border-top-width: 6rpx;
+  border-left-color: var(--color);
+  border-left-style: solid;
+  border-top-style: solid;
+  border-top-color: transparent;
+}
+.atom:nth-of-type(1) {
+  left: 0%;
+  top: 0%;
+  animation: atom1 1s linear infinite;
+}
+.atom:nth-of-type(2) {
+  right: 0%;
+  top: 0%;
+  animation: atom2 1s linear infinite;
+}
+.atom:nth-of-type(3) {
+  right: 0%;
+  bottom: 0%;
+  animation: atom3 1s linear infinite;
+}
+@keyframes dotbreath {
+  0% {
+    opacity: 1;
+  }
+
+  50% {
+    opacity: 0.5;
+  }
+  100% {
+    opacity: 1;
+  }
+}
+@keyframes atom1 {
+  0% {
+    transform: rotateZ(120deg) rotateX(66deg) rotateZ(0deg);
+  }
+  100% {
+    transform: rotateZ(120deg) rotateX(66deg) rotateZ(360deg);
+  }
+}
+@keyframes atom2 {
+  0% {
+    transform: rotateZ(240deg) rotateX(66deg) rotateZ(0deg);
+  }
+  100% {
+    transform: rotateZ(240deg) rotateX(66deg) rotateZ(360deg);
+  }
+}
+
+@keyframes atom3 {
+  0% {
+    transform: rotateZ(360deg) rotateX(66deg) rotateZ(0deg);
+  }
+  100% {
+    transform: rotateZ(360deg) rotateX(66deg) rotateZ(360deg);
+  }
+}
+</style>
diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-bounce.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-bounce.vue
new file mode 100644
index 0000000..860d23d
--- /dev/null
+++ b/uni_modules/zero-loading/components/zero-loading/static/loading-bounce.vue
@@ -0,0 +1,84 @@
+<template>
+  <view class="animations">
+    <view class="box">
+      <view class="dot dot1"></view>
+      <view class="dot dot2"></view>
+      <view class="dot dot3"></view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: "loading-bounce",
+  data() {
+    return {};
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.box {
+  width: 100rpx;
+  height: 50rpx;
+  position: relative;
+}
+.dot {
+  width: 14rpx;
+  height: 14rpx;
+  background: #007aff;
+  border-radius: 50%;
+  position: absolute;
+  top: calc(50% - 5rpx);
+}
+
+.dot1 {
+  background: #1fa2ff;
+  left: 0rpx;
+  -webkit-animation: bounce 0.5s cubic-bezier(0.77, 0.47, 0.64, 0.28) alternate
+    infinite;
+  animation: bounce 0.5s cubic-bezier(0.77, 0.47, 0.64, 0.28) alternate infinite;
+}
+
+.dot2 {
+  background: #12d8fa;
+  left: 40rpx;
+  -webkit-animation: bounce 0.5s 0.2s cubic-bezier(0.77, 0.47, 0.64, 0.28)
+    alternate infinite;
+  animation: bounce 0.5s 0.2s cubic-bezier(0.77, 0.47, 0.64, 0.28) alternate
+    infinite;
+}
+
+.dot3 {
+  background: #29ffc6;
+  left: 80rpx;
+  -webkit-animation: bounce 0.5s 0.4s cubic-bezier(0.77, 0.47, 0.64, 0.28)
+    alternate infinite;
+  animation: bounce 0.5s 0.4s cubic-bezier(0.77, 0.47, 0.64, 0.28) alternate
+    infinite;
+}
+
+@-webkit-keyframes bounce {
+  0% {
+    -webkit-transform: translateY(0);
+    transform: translateY(0);
+  }
+
+  100% {
+    -webkit-transform: translateY(-20rpx);
+    transform: translateY(-20rpx);
+  }
+}
+
+@keyframes bounce {
+  0% {
+    -webkit-transform: translateY(0);
+    transform: translateY(0);
+  }
+
+  100% {
+    -webkit-transform: translateY(-20rpx);
+    transform: translateY(-20rpx);
+  }
+}
+</style>
diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-circle.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-circle.vue
new file mode 100644
index 0000000..958bb14
--- /dev/null
+++ b/uni_modules/zero-loading/components/zero-loading/static/loading-circle.vue
@@ -0,0 +1,96 @@
+<template>
+  <view class="animations">
+    <view class="loader" :style="{ '--color': color }"></view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: "loading-circle",
+  props: {
+    color: {
+      type: String,
+      default: "#0396FF",
+    },
+  },
+  data() {
+    return {};
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+// .container {
+// 	position: absolute;
+// 	top: 50%;
+// 	left: 50%;
+// 	transform: translate(-50%, -50%);
+// }
+.loader {
+  display: block;
+  width: 120rpx;
+  height: 120rpx;
+  border-radius: 50%;
+  border: 3rpx solid transparent;
+  border-top-color: var(--color);
+  -webkit-animation: spin 2s linear infinite;
+  animation: spin 2s linear infinite;
+  position: relative;
+}
+
+.loader::before {
+  content: "";
+  position: absolute;
+  top: 8rpx;
+  left: 8rpx;
+  right: 8rpx;
+  bottom: 8rpx;
+  border-radius: 50%;
+  border: 3rpx solid transparent;
+  border-top-color: var(--color);
+  -webkit-animation: spin 3s linear infinite;
+  animation: spin 3s linear infinite;
+}
+
+.loader::after {
+  content: "";
+  position: absolute;
+  top: 16rpx;
+  left: 16rpx;
+  right: 16rpx;
+  bottom: 16rpx;
+  border-radius: 50%;
+  border: 3rpx solid transparent;
+  border-top-color: var(--color);
+  -webkit-animation: spin 1.5s linear infinite;
+  animation: spin 1.5s linear infinite;
+}
+
+@-webkit-keyframes spin {
+  0% {
+    -webkit-transform: rotate(0deg);
+    -ms-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+
+  100% {
+    -webkit-transform: rotate(360deg);
+    -ms-transform: rotate(360deg);
+    transform: rotate(360deg);
+  }
+}
+
+@keyframes spin {
+  0% {
+    -webkit-transform: rotate(0deg);
+    -ms-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+
+  100% {
+    -webkit-transform: rotate(360deg);
+    -ms-transform: rotate(360deg);
+    transform: rotate(360deg);
+  }
+}
+</style>
diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-equal.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-equal.vue
new file mode 100644
index 0000000..b68b86c
--- /dev/null
+++ b/uni_modules/zero-loading/components/zero-loading/static/loading-equal.vue
@@ -0,0 +1,81 @@
+<template>
+  <view class="animations">
+    <view class="loader" :style="{ '--color': color }"></view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: "loading-equal",
+  props: {
+    color: {
+      type: String,
+      default: "#ff1919",
+    },
+  },
+  data() {
+    return {};
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.loader {
+  width: 50px;
+  aspect-ratio: 1.154;
+  position: relative;
+  background: conic-gradient(
+    from 120deg at 50% 64%,
+    #0000,
+    var(--color) 1deg 120deg,
+    #0000 121deg
+  );
+  animation: spin 1.5s infinite cubic-bezier(0.3, 1, 0, 1);
+}
+
+.loader:before,
+.loader:after {
+  content: "";
+  position: absolute;
+  inset: 0;
+  background: inherit;
+  transform-origin: 50% 66%;
+  animation: separate 1.5s infinite;
+}
+
+.loader:after {
+  --s: -1;
+}
+
+@keyframes spin {
+  0%,
+  30% {
+    transform: rotate(0);
+  }
+
+  70% {
+    transform: rotate(120deg);
+  }
+
+  70.01%,
+  100% {
+    transform: rotate(360deg);
+  }
+}
+
+@keyframes separate {
+  0% {
+    transform: rotate(calc(var(--s, 1) * 120deg)) translate(0);
+  }
+
+  30%,
+  70% {
+    transform: rotate(calc(var(--s, 1) * 120deg))
+      translate(calc(var(--s, 1) * -5px), 10px);
+  }
+
+  100% {
+    transform: rotate(calc(var(--s, 1) * 120deg)) translate(0);
+  }
+}
+</style>
diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-eyes.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-eyes.vue
new file mode 100644
index 0000000..f7a18d1
--- /dev/null
+++ b/uni_modules/zero-loading/components/zero-loading/static/loading-eyes.vue
@@ -0,0 +1,78 @@
+<template>
+  <view class="animations">
+    <view class="box">
+      <view class="eye"></view>
+      <view class="eye"></view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: "loading-eyes",
+  data() {
+    return {};
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.box {
+  width: 110rpx;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.eye {
+  width: 50rpx;
+  height: 50rpx;
+  background: linear-gradient(135deg, #1fa2ff, #12d8fa);
+  border-radius: 50%;
+  position: relative;
+}
+
+.eye:after {
+  background-color: #ffffff;
+  width: 18rpx;
+  height: 18rpx;
+  border-radius: 50%;
+  left: 20rpx;
+  top: 24rpx;
+  position: absolute;
+  content: "";
+  -webkit-animation: eyeball 1s linear infinite alternate;
+  -moz-animation: eyeball 1s linear infinite alternate;
+  animation: eyeball 1s linear infinite alternate;
+}
+
+@-webkit-keyframes eyeball {
+  0% {
+    left: 30rpx;
+  }
+
+  100% {
+    left: 2rpx;
+  }
+}
+
+@-moz-keyframes eyeball {
+  0% {
+    left: 30rpx;
+  }
+
+  100% {
+    left: 2rpx;
+  }
+}
+
+@keyframes eyeball {
+  0% {
+    left: 30rpx;
+  }
+
+  100% {
+    left: 2rpx;
+  }
+}
+</style>
diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-gear.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-gear.vue
new file mode 100644
index 0000000..19ce873
--- /dev/null
+++ b/uni_modules/zero-loading/components/zero-loading/static/loading-gear.vue
@@ -0,0 +1,118 @@
+<template>
+  <view class="animations">
+    <view class="box">
+      <view class="gear1">
+        <view class="inner inner1"> </view>
+        <view class="inner inner2"> </view>
+        <view class="inner inner3"> </view>
+      </view>
+      <view class="gear2">
+        <view class="inner inner1"> </view>
+        <view class="inner inner2"> </view>
+        <view class="inner inner3"> </view>
+      </view>
+      <view class="gear3">
+        <view class="inner inner1"> </view>
+        <view class="inner inner2"> </view>
+        <view class="inner inner3"> </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: "loading-gear",
+  data() {
+    return {};
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+$size: 80rpx;
+$bgc: red;
+
+.box {
+  width: 200rpx;
+  height: 200rpx;
+  position: relative;
+}
+
+@mixin gear($size: $size, $bgc: $bgc) {
+  width: $size;
+  height: $size;
+  .inner {
+    position: absolute;
+    width: $size;
+    height: $size;
+    top: 0;
+    left: 0;
+    background: $bgc;
+    border-radius: 6rpx;
+    mask: radial-gradient(transparent 40%, #fff 60%);
+  }
+
+  .inner2 {
+    transform: rotate(120deg);
+  }
+
+  .inner3 {
+    transform: rotate(240deg);
+  }
+
+  // &:after {
+  // 	position: absolute;
+  // 	content: '';
+  // 	background: #fff;
+  // 	width: $size / 1.8;
+  // 	height: $size / 1.8;
+  // 	border-radius: 100%;
+  // 	top: 50%;
+  // 	left: 50%;
+  // 	transform: translate(-50%, -50%);
+  // }
+}
+
+.gear1 {
+  @include gear(60rpx, #0396ff);
+  position: absolute;
+  top: 35rpx;
+  left: 35rpx;
+  animation: rotate 5s infinite linear;
+}
+
+.gear2 {
+  @include gear(50rpx, #dd524d);
+  position: absolute;
+  top: 50rpx;
+  left: 110rpx;
+  animation: rotateR 5s infinite linear;
+}
+.gear3 {
+  @include gear(50rpx, #f0ad4e);
+  position: absolute;
+  top: 110rpx;
+  left: 50rpx;
+  animation: rotateR 5s infinite linear;
+}
+
+@keyframes rotate {
+  from {
+    transform: rotate(0deg);
+  }
+
+  to {
+    transform: rotate(360deg);
+  }
+}
+@keyframes rotateR {
+  from {
+    transform: rotate(0deg);
+  }
+
+  to {
+    transform: rotate(-360deg);
+  }
+}
+</style>
diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-locating.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-locating.vue
new file mode 100644
index 0000000..7e140ec
--- /dev/null
+++ b/uni_modules/zero-loading/components/zero-loading/static/loading-locating.vue
@@ -0,0 +1,81 @@
+<template>
+    <view class="animations">
+      <view class="loader" :style="{ '--color': color }"></view>
+    </view>
+  </template>
+  
+  <script>
+  export default {
+    name: "loading-locating",
+    props: {
+      color: {
+        type: String,
+        default: "#0396FF",
+      },
+    },
+    data() {
+      return {};
+    },
+  };
+  </script>
+  
+  <style lang="scss" scoped>
+  
+  .loader {
+    width: 96rpx;
+    height: 96rpx;
+    display: block;
+    margin: 40rpx auto;
+    box-sizing: border-box;
+    position: relative;
+  }
+
+  .loader::after {
+    content: '';
+    width: 96rpx;
+    height: 96rpx;
+    left: 0;
+    bottom: 0;
+    position: absolute;
+    border-radius: 50% 50% 0;
+    border: 30rpx solid var(--color);
+    transform: rotate(45deg) translate(0, 0);
+    box-sizing: border-box;
+    animation: animMarker 0.4s ease-in-out infinite alternate;
+  }
+
+  .loader::before {
+    content: '';
+    box-sizing: border-box;
+    position: absolute;
+    left: 0;
+    right: 0;
+    margin: auto;
+    top: 150%;
+    width: 48rpx;
+    height: 8rpx;
+    border-radius: 50%;
+    background: rgba(0, 0, 0, 0.2);
+    animation: animShadow 0.4s ease-in-out infinite alternate;
+  }
+
+  @keyframes animMarker {
+    0% {
+      transform: rotate(45deg) translate(10rpx, 10rpx);
+    }
+
+    100% {
+      transform: rotate(45deg) translate(-10rpx, -10rpx);
+    }
+  }
+
+  @keyframes animShadow {
+    0% {
+      transform: scale(0.5);
+    }
+
+    100% {
+      transform: scale(1);
+    }
+  }
+</style>
\ No newline at end of file
diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-love.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-love.vue
new file mode 100644
index 0000000..9b5e6cd
--- /dev/null
+++ b/uni_modules/zero-loading/components/zero-loading/static/loading-love.vue
@@ -0,0 +1,201 @@
+<template>
+  <view class="animations">
+    <view class="box">
+      <view class="item"></view>
+      <view class="item"></view>
+      <view class="item"></view>
+      <view class="item"></view>
+      <view class="item"></view>
+      <view class="item"></view>
+      <view class="item"></view>
+      <view class="item"></view>
+      <view class="item"></view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: "loading-love",
+  data() {
+    return {};
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.box {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  flex-flow: row nowrap;
+  height: 160rpx;
+}
+
+.item {
+  background: linear-gradient(to bottom, #f00000, #e73827);
+  width: 16rpx;
+  height: 16rpx;
+  border-radius: 20rpx;
+  margin-right: 10rpx;
+}
+
+.item:nth-child(1) {
+  animation: love1 4s infinite;
+}
+
+.item:nth-child(2) {
+  animation: love2 4s infinite;
+  animation-delay: 0.15s;
+}
+
+.item:nth-child(3) {
+  animation: love3 4s infinite;
+  animation-delay: 0.3s;
+}
+
+.item:nth-child(4) {
+  animation: love4 4s infinite;
+  animation-delay: 0.45s;
+}
+
+.item:nth-child(5) {
+  animation: love5 4s infinite;
+  animation-delay: 0.6s;
+}
+
+.item:nth-child(6) {
+  animation: love4 4s infinite;
+  animation-delay: 0.75s;
+}
+
+.item:nth-child(7) {
+  animation: love3 4s infinite;
+  animation-delay: 0.9s;
+}
+
+.item:nth-child(8) {
+  animation: love2 4s infinite;
+  animation-delay: 1.05s;
+}
+
+.item:nth-child(9) {
+  animation: love1 4s infinite;
+  animation-delay: 1.2s;
+}
+
+@keyframes love1 {
+  30%,
+  50% {
+    height: 50rpx;
+    transform: translateY(-20rpx);
+  }
+
+  75%,
+  100% {
+    height: 20rpx;
+    transform: translateY(0);
+  }
+}
+
+@keyframes love2 {
+  30%,
+  50% {
+    height: 90rpx;
+    transform: translateY(-25rpx);
+  }
+
+  75%,
+  100% {
+    height: 20rpx;
+    transform: translateY(0);
+  }
+}
+
+@keyframes love3 {
+  30%,
+  50% {
+    height: 120rpx;
+    transform: translateY(-20rpx);
+  }
+
+  75%,
+  100% {
+    height: 20rpx;
+    transform: translateY(0);
+  }
+}
+
+@keyframes love4 {
+  30%,
+  50% {
+    height: 130rpx;
+    transform: translateY(-10rpx);
+  }
+
+  75%,
+  100% {
+    height: 20rpx;
+    transform: translateY(0);
+  }
+}
+
+@keyframes love5 {
+  30%,
+  50% {
+    height: 130rpx;
+    transform: translateY(10rpx);
+  }
+
+  75%,
+  100% {
+    height: 20rpx;
+    transform: translateY(0);
+  }
+}
+
+// .item:nth-child(1) {
+// 	height: 50rpx;
+// 	transform: translateY(-20rpx);
+// }
+
+// .item:nth-child(2) {
+// 	height: 90rpx;
+// 	transform: translateY(-25rpx);
+// }
+
+// .item:nth-child(3) {
+// 	height: 120rpx;
+// 	transform: translateY(-20rpx);
+// }
+
+// .item:nth-child(4) {
+// 	height: 130rpx;
+// 	transform: translateY(-10rpx);
+// }
+
+// .item:nth-child(5) {
+// 	height: 130rpx;
+// 	transform: translateY(10rpx);
+// }
+
+// .item:nth-child(6) {
+// 	height: 130rpx;
+// 	transform: translateY(-10rpx);
+// }
+
+// .item:nth-child(7) {
+// 	height: 120rpx;
+// 	transform: translateY(-20rpx);
+// }
+
+// .item:nth-child(8) {
+// 	height: 90rpx;
+// 	transform: translateY(-25rpx);
+// }
+
+// .item:nth-child(9) {
+// 	height: 50rpx;
+// 	transform: translateY(-20rpx);
+// }
+</style>
diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-photo.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-photo.vue
new file mode 100644
index 0000000..3c9b383
--- /dev/null
+++ b/uni_modules/zero-loading/components/zero-loading/static/loading-photo.vue
@@ -0,0 +1,87 @@
+<template>
+  <view class="animations">
+    <view class="loader" :style="{ '--color': color }"></view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: "loading-photo",
+  props: {
+    color: {
+      type: String,
+      default: "#0396FF",
+    },
+  },
+  data() {
+    return {};
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+
+.loader {
+  width: 128rpx;
+  height: 128rpx;
+  position: relative;
+  background: #f4f4f4;
+  border-radius: 8rpx;
+  overflow: hidden;
+}
+
+.loader:before {
+  content: "";
+  position: absolute;
+  left: 0;
+  bottom: 0;
+  width: 80rpx; 
+  height: 80rpx; 
+  transform: rotate(45deg) translate(30%, 40%);
+  background: var(--color);
+  box-shadow: 64rpx -68rpx 0 10rpx var(--color); 
+  animation: slide 2s infinite ease-in-out alternate;
+}
+
+.loader:after {
+  content: "";
+  position: absolute;
+  left: 20rpx; 
+  top: 20rpx; 
+  width: 28rpx; 
+  height: 28rpx; 
+  border-radius: 50%;
+  background: var(--color);
+  transform: rotate(0deg);
+  transform-origin: 70rpx 290rpx; 
+  animation: rotate 2s infinite ease-in-out;
+}
+
+@keyframes slide {
+  0% , 100% {
+    bottom: -70rpx
+  }
+
+  25% , 75% {
+    bottom: -4rpx
+  }
+
+  20% , 80% {
+    bottom: 4rpx
+  }
+}
+
+@keyframes rotate {
+  0% {
+    transform: rotate(-15deg)
+  }
+
+  25% , 75% {
+    transform: rotate(0deg)
+  }
+
+  100% {
+    transform: rotate(25deg)
+  }
+}
+</style>
diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-pulse.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-pulse.vue
new file mode 100644
index 0000000..9c32c7e
--- /dev/null
+++ b/uni_modules/zero-loading/components/zero-loading/static/loading-pulse.vue
@@ -0,0 +1,67 @@
+<template>
+  <view class="animations">
+    <view class="box" :style="{ '--color': color }">
+      <view class="pulse-bubble pulse-bubble-1"></view>
+      <view class="pulse-bubble pulse-bubble-2"></view>
+      <view class="pulse-bubble pulse-bubble-3"></view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: "loading-pulse",
+  props: {
+    color: {
+      type: String,
+      default: "#0396FF",
+    },
+  },
+  data() {
+    return {};
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.box {
+  width: 100rpx;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.pulse-bubble {
+  width: 16rpx;
+  height: 16rpx;
+  border-radius: 50%;
+  background: var(--color);
+}
+
+.pulse-bubble-1 {
+  // background: #1fa2ff;
+  animation: pulse 0.4s ease 0s infinite alternate;
+}
+
+.pulse-bubble-2 {
+  // background: #12d8fa;
+  animation: pulse 0.4s ease 0.2s infinite alternate;
+}
+
+.pulse-bubble-3 {
+  // background: #29ffc6;
+  animation: pulse 0.4s ease 0.4s infinite alternate;
+}
+
+@keyframes pulse {
+  from {
+    opacity: 1;
+    transform: scale(1);
+  }
+
+  to {
+    opacity: 0.25;
+    transform: scale(0.75);
+  }
+}
+</style>
diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-radar.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-radar.vue
new file mode 100644
index 0000000..ebafa85
--- /dev/null
+++ b/uni_modules/zero-loading/components/zero-loading/static/loading-radar.vue
@@ -0,0 +1,132 @@
+<template>
+  <view class="animations">
+    <view class="radar">
+      <view class="dot dot-1"></view>
+      <view class="dot dot-2"></view>
+      <view class="dot dot-3"></view>
+      <view class="cover"></view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: "loading-radar",
+  data() {
+    return {};
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+$size: 180rpx;
+$dotSize: 4rpx;
+$maincolor: #2da3f6;
+
+.radar {
+  position: relative;
+  z-index: 1;
+  height: $size;
+  width: $size;
+  background: -webkit-repeating-radial-gradient(
+    rgba(45, 163, 246, 0) 0%,
+    rgba(45, 163, 246, 0) 23%,
+    rgba(45, 163, 246, 0.7) 24%,
+    rgba(45, 163, 246, 0) 25%
+  );
+  margin: 0 auto;
+  border-radius: 50%;
+  border: 2rpx solid rgba(45, 163, 246, 0.7);
+  overflow: hidden;
+}
+
+.radar::after {
+  content: "";
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  width: $dotSize;
+  height: $dotSize;
+  background: $maincolor;
+  margin-left: -1rpx;
+  margin-top: -1rpx;
+  border-radius: 1rpx;
+}
+
+.dot {
+  position: absolute;
+  width: $dotSize;
+  height: $dotSize;
+  background: $maincolor;
+  opacity: 0;
+  border-radius: 50%;
+  animation: breath 3s linear infinite;
+  box-shadow: 0 0 2rpx 2rpx rgba(45, 163, 246, 0.5);
+}
+
+.dot-1 {
+  top: 50rpx;
+  left: 30rpx;
+  animation-delay: 1s;
+}
+
+.dot-2 {
+  top: 60rpx;
+  right: 20rpx;
+  animation-delay: 0.2s;
+}
+
+.dot-3 {
+  top: 140rpx;
+  right: 100rpx;
+  animation-delay: 2.3s;
+}
+
+.cover {
+  transform-origin: bottom right;
+  border-right: 1rpx solid $maincolor;
+  background: linear-gradient(
+    45deg,
+    rgba(255, 255, 255, 0) 45%,
+    $maincolor 100%
+  );
+  width: 50%;
+  height: 50%;
+  position: absolute;
+  top: 0;
+  left: 0;
+  animation: rotation 3s linear infinite;
+}
+
+@keyframes rotation {
+  0% {
+    transform: rotate(0deg);
+  }
+
+  100% {
+    transform: rotate(360deg);
+  }
+}
+
+@keyframes breath {
+  0% {
+    opacity: 0;
+  }
+
+  10% {
+    opacity: 1;
+  }
+
+  20% {
+    opacity: 1;
+  }
+
+  40% {
+    opacity: 0;
+  }
+
+  100% {
+    opacity: 0;
+  }
+}
+</style>
diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-sun.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-sun.vue
new file mode 100644
index 0000000..ed079d8
--- /dev/null
+++ b/uni_modules/zero-loading/components/zero-loading/static/loading-sun.vue
@@ -0,0 +1,140 @@
+<template>
+  <view class="animations">
+    <view class="box">
+      <view class="sun"></view>
+      <view class="orbit orbit1">
+        <view class="planetX planet1"></view>
+      </view>
+      <view class="orbit orbit2">
+        <view class="planetX planet2"></view>
+      </view>
+      <view class="orbit orbit3">
+        <view class="planetX planet3"></view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: "loading-sun",
+  data() {
+    return {};
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.box {
+  width: 210rpx;
+  height: 210rpx;
+  position: relative;
+}
+.sun {
+  background: radial-gradient(#ff0, #f90);
+  height: 50rpx;
+  width: 50rpx;
+  border-radius: 50%;
+  position: absolute;
+  left: 0;
+  right: 0;
+  top: 0;
+  bottom: 0;
+  margin: auto;
+}
+
+.planetX {
+  position: absolute;
+  z-index: 100;
+  border-radius: 50%;
+}
+
+.planet1 {
+  left: 20rpx;
+  height: 13rpx;
+  width: 13rpx;
+  background-color: #fed313;
+}
+
+.planet2 {
+  left: 23rpx;
+  height: 20rpx;
+  width: 20rpx;
+  background: linear-gradient(#00ff00, #09f, #09f);
+  -webkit-animation: rotation 1s infinite linear;
+  animation: rotation 1s infinite linear;
+}
+
+.planet3 {
+  left: 49rpx;
+  height: 17rpx;
+  width: 17rpx;
+  background: radial-gradient(#ff9900, #ff4400);
+}
+
+.orbit {
+  background: transparent;
+  border-radius: 50%;
+  border: 1rpx solid #cccccc;
+  position: absolute;
+  left: 0;
+  right: 0;
+  top: 0;
+  bottom: 0;
+  margin: auto;
+}
+
+.orbit1 {
+  height: 100rpx;
+  width: 100rpx;
+  -webkit-animation: rotation 2s infinite linear;
+  -moz-animation: rotation 2s infinite linear;
+  animation: rotation 2s infinite linear;
+}
+
+.orbit2 {
+  height: 150rpx;
+  width: 150rpx;
+  -webkit-animation: rotation 3s infinite linear;
+  -moz-animation: rotation 3s infinite linear;
+  animation: rotation 3s infinite linear;
+}
+
+.orbit3 {
+  height: 200rpx;
+  width: 200rpx;
+  -moz-animation: rotation 6s infinite linear;
+  -webkit-animation: rotation 6s infinite linear;
+  animation: rotation 6s infinite linear;
+}
+
+@-webkit-keyframes rotation {
+  from {
+    -webkit-transform: rotate(0deg);
+  }
+
+  to {
+    -webkit-transform: rotate(359deg);
+  }
+}
+
+@keyframes rotation {
+  from {
+    transform: rotate(0deg);
+  }
+
+  to {
+    transform: rotate(359deg);
+  }
+}
+
+@-moz-keyframes rotation {
+  from {
+    -moz-transform: rotate(0deg);
+  }
+
+  to {
+    -moz-transform: rotate(359deg);
+  }
+}
+</style>
diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-surround.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-surround.vue
new file mode 100644
index 0000000..0e47a11
--- /dev/null
+++ b/uni_modules/zero-loading/components/zero-loading/static/loading-surround.vue
@@ -0,0 +1,91 @@
+<template>
+  <view class="animations">
+    <view class="box">
+      <view class="loader">
+        <view class="loader__ball"></view>
+        <view class="loader__ball"></view>
+        <view class="loader__ball"></view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: "loading-triangle",
+  data() {
+    return {};
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+$dotColor: linear-gradient(135deg, #1fa2ff, #12d8fa, #29ffc6);
+$dotSize: 30rpx;
+$duration: 2s;
+.animations {
+  width: 160rpx;
+  height: 160rpx;
+  position: relative;
+}
+.box {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+}
+.loader {
+  animation: rotate $duration linear infinite normal;
+  position: relative;
+  transform-origin: 50% 50%;
+
+  &__ball {
+    height: $dotSize;
+    width: $dotSize;
+    left: -$dotSize * 0.5;
+    position: absolute;
+    top: -$dotSize * 0.5;
+    transform-origin: 50% 50%;
+
+    &:nth-of-type(2) {
+      transform: rotate(120deg);
+    }
+
+    &:nth-of-type(3) {
+      transform: rotate(240deg);
+    }
+
+    &::after {
+      animation: move $duration * 0.5 ease-in-out infinite alternate;
+      background: $dotColor;
+      border-radius: 50%;
+      content: "";
+      display: inline-block;
+      height: 100%;
+      width: 100%;
+      transform-origin: 50% 50%;
+    }
+  }
+}
+
+@keyframes rotate {
+  from {
+    transform: rotate(0);
+  }
+
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@keyframes move {
+  0%,
+  15% {
+    transform: translateY(0);
+  }
+
+  100% {
+    transform: translateY(-150%);
+  }
+}
+</style>
diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-sword.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-sword.vue
new file mode 100644
index 0000000..8efb848
--- /dev/null
+++ b/uni_modules/zero-loading/components/zero-loading/static/loading-sword.vue
@@ -0,0 +1,81 @@
+<template>
+  <view class="animations">
+    <view class="box" :style="{ '--color': color }">
+      <view class="sword"></view>
+      <view class="sword"></view>
+      <view class="sword"></view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: "loading-sword",
+  props: {
+    color: {
+      type: String,
+      default: "#ED213A",
+    },
+  },
+  data() {
+    return {};
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.box {
+  position: relative;
+  width: 120rpx;
+  height: 120rpx;
+}
+.sword {
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  border-radius: 50%;
+}
+.sword:nth-of-type(1) {
+  left: 0%;
+  top: 0%;
+  border-bottom: 8rpx solid var(--color);
+  animation: sword1 0.8s linear infinite;
+}
+.sword:nth-of-type(2) {
+  right: 0%;
+  top: 0%;
+  border-right: 8rpx solid var(--color);
+  animation: sword2 0.8s linear infinite;
+}
+.sword:nth-of-type(3) {
+  right: 0%;
+  bottom: 0%;
+  border-top: 8rpx solid var(--color);
+  animation: sword3 0.8s linear infinite;
+}
+@keyframes sword1 {
+  0% {
+    transform: rotateX(35deg) rotateY(-45deg) rotateZ(0deg);
+  }
+  100% {
+    transform: rotateX(35deg) rotateY(-45deg) rotateZ(360deg);
+  }
+}
+@keyframes sword2 {
+  0% {
+    transform: rotateX(50deg) rotateY(10deg) rotateZ(0deg);
+  }
+  100% {
+    transform: rotateX(50deg) rotateY(10deg) rotateZ(360deg);
+  }
+}
+
+@keyframes sword3 {
+  0% {
+    transform: rotateX(35deg) rotateY(55deg) rotateZ(0deg);
+  }
+  100% {
+    transform: rotateX(35deg) rotateY(55deg) rotateZ(360deg);
+  }
+}
+</style>
diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-wobble.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-wobble.vue
new file mode 100644
index 0000000..d8f6283
--- /dev/null
+++ b/uni_modules/zero-loading/components/zero-loading/static/loading-wobble.vue
@@ -0,0 +1,127 @@
+<template>
+  <view class="animations">
+    <view class="three-body" :style="{ '--color': color }">
+      <view class="three-body__dot"></view>
+      <view class="three-body__dot"></view>
+      <view class="three-body__dot"></view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: "loading-wobble",
+  props: {
+    color: {
+      type: String,
+      default: "#0396FF",
+    },
+  },
+  data() {
+    return {};
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+$size: 100rpx;
+$speed: 1s;
+.three-body {
+  position: relative;
+  display: inline-block;
+  height: $size;
+  width: $size;
+  animation: spin78236 calc($speed * 2.5) infinite linear;
+}
+
+.three-body__dot {
+  position: absolute;
+  height: 100%;
+  width: 27%;
+}
+
+.three-body__dot:after {
+  content: "";
+  position: absolute;
+  height: 0%;
+  width: 100%;
+  padding-bottom: 100%;
+  background-color: var(--color);
+  border-radius: 50%;
+}
+
+.three-body__dot:nth-child(1) {
+  bottom: 5%;
+  left: 0;
+  transform: rotate(60deg);
+  transform-origin: 50% 85%;
+}
+
+.three-body__dot:nth-child(1)::after {
+  bottom: 0;
+  left: 0;
+  animation: wobble1 $speed infinite ease-in-out;
+  animation-delay: calc($speed * -0.3);
+}
+
+.three-body__dot:nth-child(2) {
+  bottom: 5%;
+  right: 0;
+  transform: rotate(-60deg);
+  transform-origin: 50% 85%;
+}
+
+.three-body__dot:nth-child(2)::after {
+  bottom: 0;
+  left: 0;
+  animation: wobble1 $speed infinite calc($speed * -0.15) ease-in-out;
+}
+
+.three-body__dot:nth-child(3) {
+  bottom: -5%;
+  left: 0;
+  transform: translateX(116.666%);
+}
+
+.three-body__dot:nth-child(3)::after {
+  top: 0;
+  left: 0;
+  animation: wobble2 $speed infinite ease-in-out;
+}
+
+@keyframes spin78236 {
+  0% {
+    transform: rotate(0deg);
+  }
+
+  100% {
+    transform: rotate(360deg);
+  }
+}
+
+@keyframes wobble1 {
+  0%,
+  100% {
+    transform: translateY(0%) scale(1);
+    opacity: 1;
+  }
+
+  50% {
+    transform: translateY(-66%) scale(0.65);
+    opacity: 0.8;
+  }
+}
+
+@keyframes wobble2 {
+  0%,
+  100% {
+    transform: translateY(0%) scale(1);
+    opacity: 1;
+  }
+
+  50% {
+    transform: translateY(66%) scale(0.65);
+    opacity: 0.8;
+  }
+}
+</style>
diff --git a/uni_modules/zero-loading/components/zero-loading/zero-loading.vue b/uni_modules/zero-loading/components/zero-loading/zero-loading.vue
new file mode 100644
index 0000000..62db5eb
--- /dev/null
+++ b/uni_modules/zero-loading/components/zero-loading/zero-loading.vue
@@ -0,0 +1,186 @@
+<template>
+  <!--  -->
+  <view
+    :style="{ position: position, 'z-index': zIndex, '--opacity': maskOpacity }"
+    class="container"
+    :class="[
+      mask ? 'mask' : '',
+      maskMini ? 'mask-mini' : '',
+      (mask || maskMini) && maskDark ? 'mask-dark' : '',
+    ]"
+    @click.prevent="handleClick"
+  >
+    <view>
+      <view class="main">
+        <loading0 v-if="type == 'circle'" :color="color"></loading0>
+        <loading1 v-if="type == 'pulse'" :color="color"></loading1>
+        <loading2 v-if="type == 'bounce'"></loading2>
+        <loading3 v-if="type == 'eyes'"></loading3>
+        <loading4 v-if="type == 'surround'"></loading4>
+        <loading5 v-if="type == 'sun'"></loading5>
+        <loading6 v-if="type == 'love'"></loading6>
+        <loading7 v-if="type == 'sword'" :color="color"></loading7>
+        <loading8 v-if="type == 'atom'" :color="color"></loading8>
+        <loading9 v-if="type == 'gear'"></loading9>
+        <loading10 v-if="type == 'radar'"></loading10>
+        <loading11 v-if="type == 'annulus'" :color="color"></loading11>
+        <loading12 v-if="type == 'wobble'" :color="color"></loading12>
+        <loading13 v-if="type == 'equal'" :color="color"></loading13>
+        <loading14 v-if="type == 'photo'" :color="color"></loading14>
+        <loading15 v-if="type == 'locating'" :color="color"></loading15>
+      </view>
+      <view
+        class="tips"
+        v-if="showText"
+        :style="{ color: textColor, fontSize: textSize, marginTop: textGap }"
+        >{{ text }}</view
+      >
+    </view>
+  </view>
+</template>
+
+<script>
+import loading0 from "./static/loading-circle.vue";
+import loading1 from "./static/loading-pulse.vue";
+import loading2 from "./static/loading-bounce.vue";
+import loading3 from "./static/loading-eyes.vue";
+import loading4 from "./static/loading-surround.vue";
+import loading5 from "./static/loading-sun.vue";
+import loading6 from "./static/loading-love.vue";
+import loading7 from "./static/loading-sword.vue";
+import loading8 from "./static/loading-atom.vue";
+import loading9 from "./static/loading-gear.vue";
+import loading10 from "./static/loading-radar.vue";
+import loading11 from "./static/loading-annulus.vue";
+import loading12 from "./static/loading-wobble.vue";
+import loading13 from "./static/loading-equal.vue";
+import loading14 from "./static/loading-photo.vue"; 
+import loading15 from "./static/loading-locating.vue";
+
+export default {
+  name: "zero-loading",
+  components: {
+    loading0,
+    loading1,
+    loading2,
+    loading3,
+    loading4,
+    loading5,
+    loading6,
+    loading7,
+    loading8,
+    loading9,
+    loading10,
+    loading11,
+    loading12,
+    loading13,
+    loading14,
+    loading15,
+  },
+  props: {
+    type: {
+      type: String,
+      default: "atom",
+    },
+    position: {
+      type: String,
+      default: "fixed",
+    },
+    zIndex: {
+      type: Number,
+      default: 9,
+    },
+    mask: {
+      type: Boolean,
+      default: false,
+    },
+    maskOpacity: {
+      type: Number,
+      default: 0.1,
+    },
+    maskMini: {
+      type: Boolean,
+      default: false,
+    },
+    maskDark: {
+      type: Boolean,
+      default: true,
+    },
+    color: {
+      type: String,
+      default: "#0396FF",
+    },
+    showText: {
+      type: Boolean,
+      default: false,
+    },
+    text: {
+      type: String,
+      default: "鍔犺浇涓�...",
+    },
+    textSize: {
+      type: String,
+      default: "28rpx",
+    },
+    textColor: {
+      type: String,
+      default: "#333333",
+    },
+    textGap: {
+      type: String,
+      default: "40rpx",
+    },
+  },
+  data() {
+    return {};
+  },
+  methods: {
+    handleClick() {
+      this.$emit("click");
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.container {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+.tips {
+  //   margin-top: 40rpx;
+  text-align: center;
+}
+
+.mask {
+  z-index: 999 !important;
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  height: 100vh;
+  width: 100vw;
+  background: rgba(255, 255, 255, var(--opacity));
+  transform: translate(0, 0);
+}
+
+.mask-mini {
+  height: 300rpx;
+  width: 300rpx;
+  border-radius: 20rpx;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+}
+
+.mask-dark {
+  background: rgba(7, 17, 27, var(--opacity));
+}
+</style>
diff --git a/uni_modules/zero-loading/package.json b/uni_modules/zero-loading/package.json
new file mode 100644
index 0000000..17f7d3e
--- /dev/null
+++ b/uni_modules/zero-loading/package.json
@@ -0,0 +1,83 @@
+{
+  "id": "zero-loading",
+  "displayName": "zero-loading(鍔犺浇鍔ㄧ敾)",
+  "version": "1.4.2",
+  "description": "绾痗ss鍔犺浇鍔ㄧ敾, 涓�涓爣绛惧厓绱犲嵆鍙疄鐜扮偒閰风殑鍏ㄥ睆loading鏁堟灉,鏀寔vue2,vue3",
+  "keywords": [
+    "loading",
+    "鍔犺浇鍔ㄧ敾",
+    "css鍔ㄧ敾",
+    "鍔犺浇"
+],
+  "repository": "",
+  "engines": {
+    "HBuilderX": "^3.1.0"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "鏃�",
+      "data": "鎻掍欢涓嶉噰闆嗕换浣曟暟鎹�",
+      "permissions": "鏃�"
+    },
+    "npmurl": "",
+    "type": "component-vue"
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y",
+        "alipay": "n"
+      },
+      "client": {
+        "Vue": {
+          "vue2": "y",
+          "vue3": "y"
+        },
+        "App": {
+            "app-vue": "u",
+            "app-nvue": "u",
+            "app-harmony": "u",
+            "app-uvue": "u"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "寰俊娴忚鍣�(Android)": "y",
+          "QQ娴忚鍣�(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "u",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "灏忕▼搴�": {
+          "寰俊": "y",
+          "闃块噷": "u",
+          "鐧惧害": "u",
+          "瀛楄妭璺冲姩": "u",
+          "QQ": "u"
+        },
+        "蹇簲鐢�": {
+          "鍗庝负": "u",
+          "鑱旂洘": "u"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/uni_modules/zero-loading/readme.md b/uni_modules/zero-loading/readme.md
new file mode 100644
index 0000000..2f14f69
--- /dev/null
+++ b/uni_modules/zero-loading/readme.md
@@ -0,0 +1,69 @@
+# zero-loading
+
+> 浠呮祴璇曚簬 vue2, vue3, 寰俊灏忕▼搴�. 鍏朵粬骞冲彴鑷娴嬭瘯
+
+## 浣跨敤鏂规硶
+
+瀵煎叆 `uni_modules` 鍚庣洿鎺ヤ娇鐢ㄥ嵆鍙�
+
+鎻愪緵澶氱鍔犺浇鍔ㄧ敾绫诲瀷,浼犲叆 type 鏀瑰彉 loading 鏍峰紡锛屼笉浼犻粯璁� circle
+
+### 鍏ㄥ睆浣跨敤
+
+```html
+<zero-loading v-if="loading"></zero-loading>
+```
+
+### 灞�閮ㄤ娇鐢�
+
+**鐖跺厓绱犵殑 `position` 璁板緱鏀逛负 `relative` 涓嶇劧鍙兘褰卞搷鏁堟灉**
+
+```html
+<zero-loading type="pulse" position="absolute"></zero-loading>
+```
+
+## 鍙傛暟璇存槑
+
+| 鍙傛暟        | 绫诲瀷     | 榛樿鍊�    | 鎻忚堪                                           |
+| ----------- | -------- | --------- | ---------------------------------------------- |
+| type        | String   | atom      | 鏍峰紡                                           |
+| position    | String   | fixed     | 瀹氫綅鏂瑰紡                                       |
+| zIndex      | Number   | 9         |                                                |
+| mask        | Boolean  | false     | 鏄惁闇�瑕侀伄缃� (榛樿涓哄叏灞忛伄缃�,鑳屾櫙鑹查粯璁や负榛戣壊) |
+| maskOpacity | Number   | 0.1       | 閬僵閫忔槑搴�                                     |
+| maskMini    | Boolean  | false     | 浼犲叆 true 鏃�,浣跨敤灏忛伄缃�                        |
+| maskDark    | Boolean  | true      | 浼犲叆 false 鏃�,閬僵鑳屾櫙鑹蹭负鐧借壊                 |
+| color       | String   | #0396FF   | 鑷畾涔夐鑹�,浠呴儴鍒嗘敮鎸�                          |
+| showText    | showText | false     | 鏄惁鏄剧ず鏂囧瓧                                   |
+| text        | String   | 鍔犺浇涓�... | 鏂囨湰鍐呭                                       |
+| textSize    | String   | 28rpx     | 鏂囧瓧澶у皬                                       |
+| textColor   | String   | #333333   | 鏂囧瓧棰滆壊                                       |
+| textGap     | String   | 40rpx     | 鏂囧瓧涓� loading 鍔ㄧ敾鐨勯棿璺�                      |
+
+### type 鍙�夊�硷細
+
+| type 鍊�  | 鎻忚堪              |
+| -------- | ----------------- |
+| locating | 瀹氫綅 (鑷畾涔夐鑹�) |
+| photo    | 鐓х墖 (鑷畾涔夐鑹�) |
+| equal    | 绛夎竟 (鑷畾涔夐鑹�) |
+| wobble   | 鎽囨憜 (鑷畾涔夐鑹�) |
+| annulus  | 鍦嗙幆 (鑷畾涔夐鑹�) |
+| sword    | 鍓戞皵 (鑷畾涔夐鑹�) |
+| atom     | 鍘熷瓙 (鑷畾涔夐鑹�) |
+| pulse    | 鑴夊啿 (鑷畾涔夐鑹�) |
+| circle   | 鍦嗗湀 (鑷畾涔夐鑹�) |
+| eyes     | 鐪肩潧              |
+| surround | 鐜粫              |
+| bounce   | 寮硅烦              |
+| radar    | 闆疯揪              |
+| gear     | 榻胯疆              |
+| love     | 鐖卞績              |
+| sun      | 澶槼              |
+
+鎻掍欢棰勮:
+![code](https://cdn.zerojs.cn/image/common/code-z_1722414660881_1.jpg?imageMogr2/thumbnail/200x)
+
+> 灏忕▼搴忔悳绱�: 闆舵妧鏈�
+
+> 棰勮鐨勫皬绋嬪簭涓嶄竴瀹氳兘鍙婃椂鏇存柊褰撳墠鎻掍欢

--
Gitblit v1.8.0