ソースを参照

1.图片预览的样式调整 2.小图用压缩的图片资源,而在预览时切换到大圈

shizhongqi 1 年間 前
コミット
bb727182ac

+ 7 - 6
hdApp/.gitignore

@@ -1,10 +1,11 @@
 .DS_Store
 node_modules/
-/dist/cache
-/dist/dev
-/dist/build/app-plus
-/dist/build/mp-weixin
-/dist/build/.automator
+/dist/*
+#/dist/dev
+#/dist/debug/
+#/dist/build/app-plus
+#/dist/build/mp-weixin
+#/dist/build/.automator
 # local env files
 .env.local
 .env.*.local
@@ -24,4 +25,4 @@ yarn-error.log*
 *.njsproj
 *.sln
 *.sw*
-CLAUDE.md
+CLAUDE.md

+ 667 - 583
hdApp/src/admin/goods/goodsSort.vue

@@ -1,628 +1,712 @@
 <template>
-	<view class="app-content">
-		<view class="list-wrap">
-			<block v-if="!$util.isEmpty(list.data)">
-				<block v-for="(item, index) in list.data" :key="item.id">
-					<view 
-						class="list"
-						:class="{ 
-							'dragging': draggedIndex === index,
-							'target-position': targetIndex === index && isDragging && targetIndex !== draggedIndex
-						}"
-						:style="{ 
-							transform: transformStyle(index), 
-							transition: isDragging ? 'none' : 'transform 0.3s ease', 
-							zIndex: draggedIndex === index ? 999 : (targetIndex === index && isDragging ? 888 : 1)
-						}">
-						<view class="list-img">
-							<view v-if="item.stock <= 0" class="sold-out">
-								<view class="sold-out-xj">已下架</view>
-							</view>
-							<image :src="item.cover" mode="aspectFit" ></image>
-						</view>
-						<view class="list-det" style="position:absolute;top:10upx;left:125upx;">
-							<view class="app-size-28 app-color-0" style="font-size:28upx;font-weight:bold;">{{ item.name || item.goodsName}}</view>						
-						</view>
-
-                        <view class="list-det" style="position:absolute;bottom:10upx;left:122upx;">
-							<view v-if="item.priceType == 1" class="app-size-28 app-color-0" style="font-size:24upx;">¥{{ item.price}}</view>						
-							<view v-else class="app-size-28 app-color-0" style="font-size:24upx;border:1px solid #ccc;border-radius:30upx;padding:3upx 15upx;">无价格</view>						
-						</view>
-						<view v-if="index > 0" style="right:375upx;" class="move-btn move-btn-top" :class="{ 'disabled': isOperating }" @click.stop="topFn(item.id)" title="置顶">
-							<zui-svg-icon icon="general-top-line" color="#fff" :width="22" :height="22" style="margin-top:10upx;"/>
-						</view>
-
-						<view v-if="index < list.data.length - 1" style="right:290upx;" class="move-btn move-btn-bottom" :class="{ 'disabled': isOperating }" @click.stop="bottomFn(item.id)" title="置底">
-							<zui-svg-icon icon="general-bottom-line" color="#fff" :width="22" :height="22" style="margin-top:10upx;"/>
-						</view>
-				
-
-						<text style="right:205upx;" class="move-btn move-btn-up" :class="{ 'disabled': isOperating }" @click.stop="upFn(item.id)" title="上移一位">↑</text>
-						<text style="right:120upx;" class="move-btn move-btn-down" :class="{ 'disabled': isOperating }" @click.stop="downFn(item.id)" title="下移一位">↓</text>
-
-						<view
-						style="position:absolute;top:50upx;right:14upx;cursor:move;"
-						class="drag-handle"
-						:data-index="index" 
-						:data-id="item.id"
-						@touchstart="dragStart" 
-						@touchmove="dragMove" 
-						@touchend="dragEnd">
-							<text style="color:#666666;font-size:48upx;padding:8upx 6upx;line-height:1;">≡</text>
-						</view>
-					</view>
-				</block>
-			</block>
-			<block v-else>
-				<app-wrapper-empty title="暂无数据" :is-empty="$util.isEmpty(list.data)" />
-			</block>
-		</view>
-	</view>
+  <view class="app-content">
+    <view class="list-wrap">
+      <block v-if="!$util.isEmpty(list.data)">
+        <block v-for="(item, index) in list.data" :key="item.id">
+          <view
+            class="list"
+            :class="{
+              dragging: draggedIndex === index,
+              'target-position': targetIndex === index && isDragging && targetIndex !== draggedIndex
+            }"
+            :style="{
+              transform: transformStyle(index),
+              transition: isDragging ? 'none' : 'transform 0.3s ease',
+              zIndex: draggedIndex === index ? 999 : targetIndex === index && isDragging ? 888 : 1
+            }"
+          >
+            <view class="list-img">
+              <view v-if="item.stock <= 0" class="sold-out">
+                <view class="sold-out-xj">已下架</view>
+              </view>
+              <image :src="item.cover" mode="aspectFit"></image>
+            </view>
+            <view class="list-det" style="position: absolute; top: 10upx; left: 125upx">
+              <view class="app-size-28 app-color-0" style="font-size: 28upx; font-weight: bold">{{ item.name || item.goodsName }}</view>
+            </view>
+
+            <view class="list-det" style="position: absolute; bottom: 10upx; left: 122upx">
+              <view v-if="item.priceType == 1" class="app-size-28 app-color-0" style="font-size: 24upx">¥{{ item.price }}</view>
+              <view v-else class="app-size-28 app-color-0" style="font-size: 24upx; border: 1px solid #ccc; border-radius: 30upx; padding: 3upx 15upx"
+                >无价格</view
+              >
+            </view>
+            <view
+              v-if="index > 0"
+              style="right: 375upx"
+              class="move-btn move-btn-top"
+              :class="{ disabled: isOperating }"
+              @click.stop="topFn(item.id)"
+              title="置顶"
+            >
+              <zui-svg-icon icon="general-top-line" color="#fff" :width="22" :height="22" style="margin-top: 10upx" />
+            </view>
+
+            <view
+              v-if="index < list.data.length - 1"
+              style="right: 290upx"
+              class="move-btn move-btn-bottom"
+              :class="{ disabled: isOperating }"
+              @click.stop="bottomFn(item.id)"
+              title="置底"
+            >
+              <zui-svg-icon icon="general-bottom-line" color="#fff" :width="22" :height="22" style="margin-top: 10upx" />
+            </view>
+
+            <text style="right: 205upx" class="move-btn move-btn-up" :class="{ disabled: isOperating }" @click.stop="upFn(item.id)" title="上移一位"
+              >↑</text
+            >
+            <text
+              style="right: 120upx"
+              class="move-btn move-btn-down"
+              :class="{ disabled: isOperating }"
+              @click.stop="downFn(item.id)"
+              title="下移一位"
+              >↓</text
+            >
+
+            <view
+              style="position: absolute; top: 50upx; right: 14upx; cursor: move"
+              class="drag-handle"
+              :data-index="index"
+              :data-id="item.id"
+              @touchstart="dragStart"
+              @touchmove="dragMove"
+              @touchend="dragEnd"
+            >
+              <text style="color: #666666; font-size: 48upx; padding: 8upx 6upx; line-height: 1">≡</text>
+            </view>
+          </view>
+        </block>
+      </block>
+      <block v-else>
+        <app-wrapper-empty title="暂无数据" :is-empty="$util.isEmpty(list.data)" />
+      </block>
+    </view>
+  </view>
 </template>
 <script>
-import AppWrapperEmpty from '@/components/app-wrapper-empty'
-import { list } from '@/mixins'
-import { getListB, sort } from '@/api/goods'
+import AppWrapperEmpty from '@/components/app-wrapper-empty';
+import { list } from '@/mixins';
+import { getListB, sort } from '@/api/goods';
 export default {
-	name: 'goodsSort',
-	components: {
-		AppWrapperEmpty
-	},
-	mixins: [list],
-	data() {
-		return {
-			draggedIndex: -1,
-			draggedItem: null,
-			dragOffsetY: 0,
-			isDragging: false,
-			itemHeight: 160, // 列表项高度,单位upx(与CSS中的height保持一致)
-			startY: 0,
-			scrollTop: 0, // 页面滚动高度
-			originalOrder: [], // 原始顺序,用于拖拽失败时恢复
-			targetIndex: -1, // 目标交换位置的索引
-			isOperating: false, // 防止快速点击操作按钮
-            totalNum: 0, // 总数量
-		}
-	},
-	onPageScroll(e) {
-		// 拖拽期间禁止更新滚动高度
-		if (!this.isDragging) {
-			this.scrollTop = e.scrollTop
-		}
-	},
-	onPullDownRefresh() {
-		this.resetList()
-		this._list().then(res => {
-			uni.stopPullDownRefresh()
-		}).catch(err => {
-			console.error('下拉刷新失败:', err)
-			uni.stopPullDownRefresh()
-		})
-	},
-	onReachBottom() {
-		if (!this.list.finished) {
-			this._list().then(res => {
-				uni.stopPullDownRefresh()
-			})
-		} else {
-			uni.stopPullDownRefresh()
-		}
-	},
-	methods: {
-		async init() {
-			// 确保list.data是数组
-			if (!Array.isArray(this.list.data)) {
-				this.list.data = []
-			}
-			this._list()
-		},
-		_list() {
-			// 传递分类ID参数和分页参数到API
-			const params = {
-				cId: this.option.id,
-				page: this.list.page,
-				pageSize: this.list.pageSize
-			}
-			
-			return getListB(params).then(res => {
-				// 使用mixin提供的completes方法处理分页数据
-				this.completes(res)
-                this.totalNum = Number(res.data.total)
-			}).catch(err => {
-				console.error('API请求失败:', err)
-				this.list.loading = false
-			})
-		},
-		
-		// 拖拽相关方法
-		transformStyle(index) {
-			if (index === this.draggedIndex) {
-				return `translateY(${this.dragOffsetY}upx)`
-			}
-			return 'translateY(0upx)'
-		},
-		
-		dragStart(e) {
-			// 防止重复触发
-			if (this.isDragging) return
-			
-			this.isDragging = true
-			
-			const index = parseInt(e.currentTarget.dataset.index)
-			if (isNaN(index) || index < 0 || index >= this.list.data.length) {
-				this.isDragging = false
-				return
-			}
-			
-			this.draggedIndex = index
-			this.draggedItem = this.list.data[index]
-			this.startY = e.touches[0].clientY
-			this.targetIndex = index // 初始化目标位置为当前位置
-			
-			// 保存原始顺序,用于拖拽失败时恢复
-			this.originalOrder = [...this.list.data]
-			
-			// 添加拖拽模式样式,防止页面滚动
-			this.toggleDragMode(true)
-			
-			// 阻止默认行为,防止页面滚动(兼容微信端与H5)
-			if (e.preventDefault) {
-				e.preventDefault()
-			}
-			if (e.stopPropagation) {
-				e.stopPropagation()
-			}
-			return false
-		},
-		
-		dragMove(e) {
-			if (!this.isDragging || this.draggedIndex === -1) return
-			
-			// 验证触摸点是否存在
-			if (!e.touches || !e.touches[0]) return
-			
-			// 阻止默认行为,防止页面滚动(兼容微信端与H5)
-			if (e.preventDefault) {
-				e.preventDefault()
-			}
-			if (e.stopPropagation) {
-				e.stopPropagation()
-			}
-			
-			const currentY = e.touches[0].clientY
-			const deltaY = currentY - this.startY
-			
-			// 根据设备像素比例转换为upx单位,确保在不同设备上表现一致
-			const systemInfo = uni.getSystemInfoSync()
-			const pixelRatio = 750 / systemInfo.windowWidth
-			const deltaYupx = deltaY * pixelRatio
-			
-			// 限制拖拽范围,防止超出列表边界
-			const maxOffset = (this.list.data.length - 1 - this.draggedIndex) * this.itemHeight
-			const minOffset = -this.draggedIndex * this.itemHeight
-			const limitedOffset = Math.max(minOffset, Math.min(maxOffset, deltaYupx))
-			
-			this.dragOffsetY = limitedOffset
-			
-			// 实时计算目标位置,让用户看到将要交换的元素
-			const moveItems = Math.round(limitedOffset / this.itemHeight)
-			this.targetIndex = Math.max(0, Math.min(this.list.data.length - 1, this.draggedIndex + moveItems))
-		},
-		
-		dragEnd() {
-			if (!this.isDragging) return
-			
-			// 计算最终位置
-			const moveItems = Math.round(this.dragOffsetY / this.itemHeight)
-			const targetIndex = Math.max(0, Math.min(this.list.data.length - 1, this.draggedIndex + moveItems))
-			
-			// 如果位置有变化,则更新数组
-			if (targetIndex !== this.draggedIndex) {
-				const newData = [...this.list.data]
-				const draggedItem = newData[this.draggedIndex]
-				
-				// 移除拖拽项
-				newData.splice(this.draggedIndex, 1)
-				// 插入到新位置
-				newData.splice(targetIndex, 0, draggedItem)
-				
-				this.list.data = newData
-				
-				// 更新排序值并发送到后端
-				this.updateSortOrder()
-			}
-			
-			// 移除拖拽模式样式
-			this.toggleDragMode(false)
-			
-			// 重置拖拽状态
-			this.draggedIndex = -1
-			this.draggedItem = null
-			this.dragOffsetY = 0
-			this.isDragging = false
-			this.startY = 0
-			this.originalOrder = []
-			this.targetIndex = -1 // 重置目标位置
-		},
-		
-		updateSortOrder() {
-			// 更新每个项目的inTurn值,从大到小排序(值越大越靠前)
-			const sortData = this.list.data.map((item, index) => ({
-				id: item.id,
-				inTurn: this.totalNum - index // 反向索引,使第一个项目有最大值
-			}))
-			// console.log('排序数据:', sortData)
-			
-			// 调用API更新排序
-			sort({ cId: this.option.id, items: sortData }).then(res => {
-				if (res.code === 1) {
-					this.$msg('已更新')
-				} else {
-					this.$msg('排序更新失败')
-					// 恢复原始顺序
-					this.list.data = this.originalOrder
-				}
-			}).catch(err => {
-				console.error('更新排序失败:', err)
-				this.$msg('排序更新失败')
-				// 恢复原始顺序
-				this.list.data = this.originalOrder
-			})
-		},
-		
-		// 切换拖拽模式,防止页面滚动
-		toggleDragMode(isDragging) {
-			// #ifdef H5
-			// H5平台:直接操作body样式
-			if (isDragging) {
-				document.body.classList.add('dragging-mode')
-			} else {
-				document.body.classList.remove('dragging-mode')
-			}
-			// #endif
-			
-			// #ifndef H5
-			// 微信小程序、App:使用页面样式和滚动API
-			if (isDragging) {
-				uni.setPageStyle({
-					style: {
-						'overflow': 'hidden',
-						'position': 'fixed',
-						'width': '100%',
-						'top': `-${this.scrollTop}px`,
-						'left': '0',
-						'right': '0'
-					}
-				})
-			} else {
-				uni.setPageStyle({
-					style: {
-						'overflow': '',
-						'position': '',
-						'width': '',
-						'top': '',
-						'left': '',
-						'right': ''
-					}
-				})
-				uni.pageScrollTo({
-					scrollTop: this.scrollTop,
-					duration: 0
-				})
-			}
-			// #endif
-		},
-		
-		// 原有的上移下移方法
-		upFn(id) {
-			if (this.isOperating) return
-			this.isOperating = true
-			const index = this.list.data.findIndex(item => item.id === id)
-			if (index > 0) {
-				const newData = [...this.list.data]
-				const temp = newData[index]
-				newData[index] = newData[index - 1]
-				newData[index - 1] = temp
-				this.list.data = newData
-				this.updateSortOrder()
-			}
-			
-			// 防抖延迟
-			setTimeout(() => {
-				this.isOperating = false
-			}, 300)
-		},
-		
-		downFn(id) {
-			if (this.isOperating) return
-			this.isOperating = true
-			const index = this.list.data.findIndex(item => item.id === id)
-			if (index < this.list.data.length - 1) {
-				const newData = [...this.list.data]
-				const temp = newData[index]
-				newData[index] = newData[index + 1]
-				newData[index + 1] = temp
-				this.list.data = newData
-				this.updateSortOrder()
-			}
-			
-			// 防抖延迟
-			setTimeout(() => {
-				this.isOperating = false
-			}, 300)
-		},
-
-		// 置顶
-		topFn(id) {
-			if (this.isOperating) return
-			this.isOperating = true
-			const index = this.list.data.findIndex(item => item.id === id)
-			if (index > 0) {
-				const newData = [...this.list.data]
-				const targetItem = newData[index]
-				
-				// 将目标项移到第一位
-				newData.splice(index, 1)
-				newData.unshift(targetItem)
-				
-				this.list.data = newData
-				this.updateSortOrder()
-			}
-			
-			// 防抖延迟
-			setTimeout(() => {
-				this.isOperating = false
-			}, 300)
-		},
-		
-		// 置底
-		bottomFn(id) {
-			if (this.isOperating) return
-			this.isOperating = true
-			const index = this.list.data.findIndex(item => item.id === id)
-			if (index < this.list.data.length - 1) {
-				const newData = [...this.list.data]
-				const targetItem = newData[index]
-				
-				// 将目标项移到最后一位
-				newData.splice(index, 1)
-				newData.push(targetItem)
-				
-				this.list.data = newData
-				this.updateSortOrder()
-			}
-			
-			// 防抖延迟
-			setTimeout(() => {
-				this.isOperating = false
-			}, 300)
-		}
-	}
-}
+  name: 'goodsSort',
+  components: {
+    AppWrapperEmpty
+  },
+  mixins: [list],
+  data() {
+    return {
+      draggedIndex: -1,
+      draggedItem: null,
+      dragOffsetY: 0,
+      isDragging: false,
+      itemHeight: 160, // 列表项高度,单位upx(与CSS中的height保持一致)
+      startY: 0,
+      scrollTop: 0, // 页面滚动高度
+      originalOrder: [], // 原始顺序,用于拖拽失败时恢复
+      targetIndex: -1, // 目标交换位置的索引
+      isOperating: false, // 防止快速点击操作按钮
+      totalNum: 0 // 总数量
+    };
+  },
+  onPageScroll(e) {
+    // 拖拽期间禁止更新滚动高度
+    if (!this.isDragging) {
+      this.scrollTop = e.scrollTop;
+    }
+  },
+  onPullDownRefresh() {
+    this.resetList();
+    this._list()
+      .then((res) => {
+        uni.stopPullDownRefresh();
+      })
+      .catch((err) => {
+        console.error('下拉刷新失败:', err);
+        uni.stopPullDownRefresh();
+      });
+  },
+  onReachBottom() {
+    if (!this.list.finished) {
+      this._list().then((res) => {
+        uni.stopPullDownRefresh();
+      });
+    } else {
+      uni.stopPullDownRefresh();
+    }
+  },
+  methods: {
+    async init() {
+      // 确保list.data是数组
+      if (!Array.isArray(this.list.data)) {
+        this.list.data = [];
+      }
+      this._list();
+    },
+    _list() {
+      // 传递分类ID参数和分页参数到API
+      const params = {
+        cId: this.option.id,
+        page: this.list.page,
+        pageSize: this.list.pageSize
+      };
+
+      return getListB(params)
+        .then((res) => {
+          // 使用mixin提供的completes方法处理分页数据
+          this.completes(res);
+          this.totalNum = Number(res.data.total);
+        })
+        .catch((err) => {
+          console.error('API请求失败:', err);
+          this.list.loading = false;
+        });
+    },
+
+    // 响应 touchmove 事件并实时更新 transform 样式
+    transformStyle(index) {
+      if (index === this.draggedIndex) {
+        // #ifdef APP-PLUS
+        // 在 App 端,为与小程序保持一致,拖拽时项目保持原位
+        return 'translateY(0upx)';
+        // #endif
+
+        //return `translateY(${this.dragOffsetY}upx)`;
+        return 'translateY(0upx)';
+      }
+      return 'translateY(0upx)';
+    },
+
+    dragStart(e) {
+      // 防止重复触发
+      if (this.isDragging) return;
+
+      this.isDragging = true;
+
+      const index = parseInt(e.currentTarget.dataset.index);
+      if (isNaN(index) || index < 0 || index >= this.list.data.length) {
+        this.isDragging = false;
+        return;
+      }
+
+      this.draggedIndex = index;
+      this.draggedItem = this.list.data[index];
+      this.startY = e.touches[0].clientY;
+      this.targetIndex = index; // 初始化目标位置为当前位置
+
+      // 保存原始顺序,用于拖拽失败时恢复
+      this.originalOrder = [...this.list.data];
+
+      // 添加拖拽模式样式,防止页面滚动
+      this.toggleDragMode(true);
+
+      // 阻止默认行为,防止页面滚动(兼容微信端与H5)
+      if (e.preventDefault) {
+        e.preventDefault();
+      }
+      if (e.stopPropagation) {
+        e.stopPropagation();
+      }
+      return false;
+    },
+
+    dragMove(e) {
+      if (!this.isDragging || this.draggedIndex === -1) return;
+
+      // 验证触摸点是否存在
+      if (!e.touches || !e.touches[0]) return;
+
+      // 阻止默认行为,防止页面滚动(兼容微信端与H5)
+      if (e.preventDefault) {
+        e.preventDefault();
+      }
+      if (e.stopPropagation) {
+        e.stopPropagation();
+      }
+
+      const currentY = e.touches[0].clientY;
+      const deltaY = currentY - this.startY;
+
+      // 根据设备像素比例转换为upx单位,确保在不同设备上表现一致
+      const systemInfo = uni.getSystemInfoSync();
+      const pixelRatio = 750 / systemInfo.windowWidth;
+      const deltaYupx = deltaY * pixelRatio;
+
+      // 限制拖拽范围,防止超出列表边界
+      const maxOffset = (this.list.data.length - 1 - this.draggedIndex) * this.itemHeight;
+      const minOffset = -this.draggedIndex * this.itemHeight;
+      const limitedOffset = Math.max(minOffset, Math.min(maxOffset, deltaYupx));
+
+      this.dragOffsetY = limitedOffset;
+
+      // 实时计算目标位置,让用户看到将要交换的元素
+      const moveItems = Math.round(limitedOffset / this.itemHeight);
+      this.targetIndex = Math.max(0, Math.min(this.list.data.length - 1, this.draggedIndex + moveItems));
+    },
+
+    dragEnd() {
+      if (!this.isDragging) return;
+
+      // 计算最终位置
+      const moveItems = Math.round(this.dragOffsetY / this.itemHeight);
+      const targetIndex = Math.max(0, Math.min(this.list.data.length - 1, this.draggedIndex + moveItems));
+
+      // 如果位置有变化,则更新数组
+      if (targetIndex !== this.draggedIndex) {
+        const newData = [...this.list.data];
+        const draggedItem = newData[this.draggedIndex];
+
+        // 移除拖拽项
+        newData.splice(this.draggedIndex, 1);
+        // 插入到新位置
+        newData.splice(targetIndex, 0, draggedItem);
+
+        this.list.data = newData;
+
+        // 更新排序值并发送到后端
+        this.updateSortOrder();
+      }
+
+      // 移除拖拽模式样式
+      this.toggleDragMode(false);
+
+      // 重置拖拽状态
+      this.draggedIndex = -1;
+      this.draggedItem = null;
+      this.dragOffsetY = 0;
+      this.isDragging = false;
+      this.startY = 0;
+      this.originalOrder = [];
+      this.targetIndex = -1; // 重置目标位置
+    },
+
+    updateSortOrder() {
+      // 更新每个项目的inTurn值,从大到小排序(值越大越靠前)
+      const sortData = this.list.data.map((item, index) => ({
+        id: item.id,
+        inTurn: this.totalNum - index // 反向索引,使第一个项目有最大值
+      }));
+      // console.log('排序数据:', sortData)
+
+      // 调用API更新排序
+      sort({ cId: this.option.id, items: sortData })
+        .then((res) => {
+          if (res.code === 1) {
+            this.$msg('已更新');
+          } else {
+            this.$msg('排序更新失败');
+            // 恢复原始顺序
+            this.list.data = this.originalOrder;
+          }
+        })
+        .catch((err) => {
+          console.error('更新排序失败:', err);
+          this.$msg('排序更新失败');
+          // 恢复原始顺序
+          this.list.data = this.originalOrder;
+        });
+    },
+
+    // 切换拖拽模式,防止页面滚动
+    toggleDragMode(isDragging) {
+      // #ifdef H5
+      // H5平台:直接操作body样式
+      if (isDragging) {
+        document.body.classList.add('dragging-mode');
+      } else {
+        document.body.classList.remove('dragging-mode');
+      }
+      // #endif
+
+      // #ifdef MP-WEIXIN
+      // 微信小程序:使用页面样式和滚动API
+      if (typeof uni.setPageStyle !== 'function') {
+        console.warn('uni.setPageStyle is not available on this platform.');
+        return;
+      }
+      
+      if (isDragging) {
+        uni.setPageStyle({
+          style: {
+            overflow: 'hidden',
+            position: 'fixed',
+            width: '100%',
+            top: `-${this.scrollTop}px`,
+            left: '0',
+            right: '0'
+          }
+        });
+      } else {
+        uni.setPageStyle({
+          style: {
+            overflow: '',
+            position: '',
+            width: '',
+            top: '',
+            left: '',
+            right: ''
+          }
+        });
+        uni.pageScrollTo({
+          scrollTop: this.scrollTop,
+          duration: 0
+        });
+      }
+      // #endif
+
+      // #ifdef APP-PLUS
+      const systemInfo = uni.getSystemInfoSync();
+      
+        // --- iOS 与 Android App 平台替代方案 ---
+        // 通过操作 webview 内的 body 样式来禁止滚动
+        const webview = this.$scope.$getAppWebview();
+        if (!webview) {
+          console.warn('uni.setPageStyle 在当前环境不可用,且无法获取 webview。');
+          return;
+        }
+
+        if (isDragging) {
+          webview.evalJS(`
+            var body = document.body;
+            body.style.overflow = 'hidden';
+            body.style.position = 'fixed';
+            body.style.width = '100%';
+            body.style.left = '0';
+            body.style.right = '0';
+            body.style.top = '-${this.scrollTop}px';
+          `);
+        } else {
+          webview.evalJS(`
+            var body = document.body;
+            body.style.overflow = '';
+            body.style.position = '';
+            body.style.width = '';
+            body.style.left = '';
+            body.style.right = '';
+            body.style.top = '';
+          `);
+          // 恢复滚动位置
+          uni.pageScrollTo({
+            scrollTop: this.scrollTop,
+            duration: 0
+          });
+        }
+        return; // iOS 平台处理完毕
+      // #endif
+    },
+
+    // 原有的上移下移方法
+    upFn(id) {
+      if (this.isOperating) return;
+      this.isOperating = true;
+      const index = this.list.data.findIndex((item) => item.id === id);
+      if (index > 0) {
+        const newData = [...this.list.data];
+        const temp = newData[index];
+        newData[index] = newData[index - 1];
+        newData[index - 1] = temp;
+        this.list.data = newData;
+        this.updateSortOrder();
+      }
+
+      // 防抖延迟
+      setTimeout(() => {
+        this.isOperating = false;
+      }, 300);
+    },
+
+    downFn(id) {
+      if (this.isOperating) return;
+      this.isOperating = true;
+      const index = this.list.data.findIndex((item) => item.id === id);
+      if (index < this.list.data.length - 1) {
+        const newData = [...this.list.data];
+        const temp = newData[index];
+        newData[index] = newData[index + 1];
+        newData[index + 1] = temp;
+        this.list.data = newData;
+        this.updateSortOrder();
+      }
+
+      // 防抖延迟
+      setTimeout(() => {
+        this.isOperating = false;
+      }, 300);
+    },
+
+    // 置顶
+    topFn(id) {
+      if (this.isOperating) return;
+      this.isOperating = true;
+      const index = this.list.data.findIndex((item) => item.id === id);
+      if (index > 0) {
+        const newData = [...this.list.data];
+        const targetItem = newData[index];
+
+        // 将目标项移到第一位
+        newData.splice(index, 1);
+        newData.unshift(targetItem);
+
+        this.list.data = newData;
+        this.updateSortOrder();
+      }
+
+      // 防抖延迟
+      setTimeout(() => {
+        this.isOperating = false;
+      }, 300);
+    },
+
+    // 置底
+    bottomFn(id) {
+      if (this.isOperating) return;
+      this.isOperating = true;
+      const index = this.list.data.findIndex((item) => item.id === id);
+      if (index < this.list.data.length - 1) {
+        const newData = [...this.list.data];
+        const targetItem = newData[index];
+
+        // 将目标项移到最后一位
+        newData.splice(index, 1);
+        newData.push(targetItem);
+
+        this.list.data = newData;
+        this.updateSortOrder();
+      }
+
+      // 防抖延迟
+      setTimeout(() => {
+        this.isOperating = false;
+      }, 300);
+    }
+  }
+};
 </script>
 <style lang="scss" scoped>
 .app-content {
-	min-height: calc(100vh - 100upx);
-	padding-bottom: 100upx;
+  min-height: calc(100vh - 100upx);
+  padding-bottom: 100upx;
 }
 .list-wrap {
-	position: relative;
-	background-color: #fff;
-	.list {
-		height: 160upx;
-		@include disFlex(center, flex-start);
-		padding: 30upx 0;
-		margin: 0 30upx;
-		color: $fontColor3;
-		border-bottom: 1px solid $borderColor;
-		position:relative;
-		.list-img {
-			width: 130upx;
-			height: 130upx;
-			image {
-				width:130upx;
-				height:130upx;
-				border-radius: 20upx;
-			}
-
-			.sold-out{
-				z-index:10;
-				width:130upx;
-				height:52upx; /* 130 * (2/5) = 52upx */
-				background-color:black;
-				position:absolute;
-				top:92upx;
-				left:0;
-				opacity: 0.48;
-				color:white;
-				text-align:center;
-				border-radius: 0 0 20upx 20upx;
-				.sold-out-xj{
-					line-height:52upx;
-					font-size:24upx;
-					font-weight: bold;
-				}
-			}
-		}
-		.list-det {
-			margin-left: 20upx;
-			& > div {
-				margin-top: 14upx;
-				&:first-child {
-					margin-top: 0;
-				}
-			}
-		}
-	}
+  position: relative;
+  background-color: #fff;
+  .list {
+    height: 160upx;
+    @include disFlex(center, flex-start);
+    padding: 30upx 0;
+    margin: 0 30upx;
+    color: $fontColor3;
+    border-bottom: 1px solid $borderColor;
+    position: relative;
+    .list-img {
+      width: 130upx;
+      height: 130upx;
+      image {
+        width: 130upx;
+        height: 130upx;
+        border-radius: 20upx;
+      }
+
+      .sold-out {
+        z-index: 10;
+        width: 130upx;
+        height: 52upx; /* 130 * (2/5) = 52upx */
+        background-color: black;
+        position: absolute;
+        top: 92upx;
+        left: 0;
+        opacity: 0.48;
+        color: white;
+        text-align: center;
+        border-radius: 0 0 20upx 20upx;
+        .sold-out-xj {
+          line-height: 52upx;
+          font-size: 24upx;
+          font-weight: bold;
+        }
+      }
+    }
+    .list-det {
+      margin-left: 20upx;
+      & > div {
+        margin-top: 14upx;
+        &:first-child {
+          margin-top: 0;
+        }
+      }
+    }
+  }
 }
 .move-btn {
-	position: absolute;
-	top: 60upx;
-	display: inline-flex;
-	align-items: center;
-	justify-content: center;
-	width: 60upx;
-	height: 60upx;
-	color: #fff;
-	background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-	border: 2px solid rgba(255, 255, 255, 0.3);
-	border-radius: 50%;
-	font-size: 28upx; /* 增大20% */
-	font-weight: bold;
-	box-shadow: 0 4upx 12upx rgba(102, 126, 234, 0.3);
-	transition: all 0.2s ease;
-	z-index: 9999;
-	cursor: pointer;
-	
-	/* 触摸反馈 */
-	&:active {
-		transform: scale(0.95);
-		box-shadow: 0 2upx 8upx rgba(102, 126, 234, 0.5);
-	}
-	
-	/* 悬停效果 */
-	&:hover {
-		transform: translateY(-2upx);
-		box-shadow: 0 6upx 20upx rgba(102, 126, 234, 0.4);
-	}
+  position: absolute;
+  top: 60upx;
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  width: 60upx;
+  height: 60upx;
+  color: #fff;
+  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+  border: 2px solid rgba(255, 255, 255, 0.3);
+  border-radius: 50%;
+  font-size: 28upx; /* 增大20% */
+  font-weight: bold;
+  box-shadow: 0 4upx 12upx rgba(102, 126, 234, 0.3);
+  transition: all 0.2s ease;
+  z-index: 9999;
+  cursor: pointer;
+
+  /* 触摸反馈 */
+  &:active {
+    transform: scale(0.95);
+    box-shadow: 0 2upx 8upx rgba(102, 126, 234, 0.5);
+  }
+
+  /* 悬停效果 */
+  &:hover {
+    transform: translateY(-2upx);
+    box-shadow: 0 6upx 20upx rgba(102, 126, 234, 0.4);
+  }
 }
 
 /* 置顶按钮 - 红色渐变 */
 .move-btn-top {
-	// background: linear-gradient(135deg, #ff6b6b 0%, #ee5a24 100%);
-	// box-shadow: 0 4upx 12upx rgba(255, 107, 107, 0.3);
-    background: linear-gradient(135deg, #feca57 0%, #ff9ff3 100%);
-	box-shadow: 0 4upx 12upx rgba(254, 202, 87, 0.3);
-	
-	&:hover {
-		box-shadow: 0 6upx 20upx rgba(255, 107, 107, 0.4);
-	}
-	
-	&:active {
-		box-shadow: 0 2upx 8upx rgba(255, 107, 107, 0.5);
-	}
+  // background: linear-gradient(135deg, #ff6b6b 0%, #ee5a24 100%);
+  // box-shadow: 0 4upx 12upx rgba(255, 107, 107, 0.3);
+  background: linear-gradient(135deg, #feca57 0%, #ff9ff3 100%);
+  box-shadow: 0 4upx 12upx rgba(254, 202, 87, 0.3);
+
+  &:hover {
+    box-shadow: 0 6upx 20upx rgba(255, 107, 107, 0.4);
+  }
+
+  &:active {
+    box-shadow: 0 2upx 8upx rgba(255, 107, 107, 0.5);
+  }
 }
 
 /* 置底按钮 - 橙色渐变 */
 .move-btn-bottom {
-	background: linear-gradient(135deg, #feca57 0%, #ff9ff3 100%);
-	box-shadow: 0 4upx 12upx rgba(254, 202, 87, 0.3);
-	
-	&:hover {
-		box-shadow: 0 6upx 20upx rgba(254, 202, 87, 0.4);
-	}
-	
-	&:active {
-		box-shadow: 0 2upx 8upx rgba(254, 202, 87, 0.5);
-	}
+  background: linear-gradient(135deg, #feca57 0%, #ff9ff3 100%);
+  box-shadow: 0 4upx 12upx rgba(254, 202, 87, 0.3);
+
+  &:hover {
+    box-shadow: 0 6upx 20upx rgba(254, 202, 87, 0.4);
+  }
+
+  &:active {
+    box-shadow: 0 2upx 8upx rgba(254, 202, 87, 0.5);
+  }
 }
 
 /* 上移按钮 - 绿色渐变 */
 .move-btn-up {
-	background: linear-gradient(135deg, #48dbfb 0%, #0abde3 100%);
-	box-shadow: 0 4upx 12upx rgba(72, 219, 251, 0.3);
-	
-	&:hover {
-		box-shadow: 0 6upx 20upx rgba(72, 219, 251, 0.4);
-	}
-	
-	&:active {
-		box-shadow: 0 2upx 8upx rgba(72, 219, 251, 0.5);
-	}
+  background: linear-gradient(135deg, #48dbfb 0%, #0abde3 100%);
+  box-shadow: 0 4upx 12upx rgba(72, 219, 251, 0.3);
+
+  &:hover {
+    box-shadow: 0 6upx 20upx rgba(72, 219, 251, 0.4);
+  }
+
+  &:active {
+    box-shadow: 0 2upx 8upx rgba(72, 219, 251, 0.5);
+  }
 }
 
 /* 下移按钮 - 紫色渐变 */
 .move-btn-down {
-	// background: linear-gradient(135deg, #a55eea 0%, #8854d0 100%);
-	// box-shadow: 0 4upx 12upx rgba(165, 94, 234, 0.3);
-    background: linear-gradient(135deg, #48dbfb 0%, #0abde3 100%);
-	box-shadow: 0 4upx 12upx rgba(72, 219, 251, 0.3);
-	
-	&:hover {
-		box-shadow: 0 6upx 20upx rgba(165, 94, 234, 0.4);
-	}
-	
-	&:active {
-		box-shadow: 0 2upx 8upx rgba(165, 94, 234, 0.5);
-	}
+  // background: linear-gradient(135deg, #a55eea 0%, #8854d0 100%);
+  // box-shadow: 0 4upx 12upx rgba(165, 94, 234, 0.3);
+  background: linear-gradient(135deg, #48dbfb 0%, #0abde3 100%);
+  box-shadow: 0 4upx 12upx rgba(72, 219, 251, 0.3);
+
+  &:hover {
+    box-shadow: 0 6upx 20upx rgba(165, 94, 234, 0.4);
+  }
+
+  &:active {
+    box-shadow: 0 2upx 8upx rgba(165, 94, 234, 0.5);
+  }
 }
 
 /* 按钮禁用状态 */
 .move-btn.disabled {
-	opacity: 0.5;
-	transform: none !important;
-	box-shadow: 0 2upx 6upx rgba(0, 0, 0, 0.1) !important;
-	pointer-events: none;
-	cursor: not-allowed;
-	&:hover, &:active {
-		transform: none !important;
-		box-shadow: 0 2upx 6upx rgba(0, 0, 0, 0.1) !important;
-	}
+  opacity: 0.5;
+  transform: none !important;
+  box-shadow: 0 2upx 6upx rgba(0, 0, 0, 0.1) !important;
+  pointer-events: none;
+  cursor: not-allowed;
+  &:hover,
+  &:active {
+    transform: none !important;
+    box-shadow: 0 2upx 6upx rgba(0, 0, 0, 0.1) !important;
+  }
 }
 // 拖拽相关样式
 .list.dragging {
-	border: 2px dashed #007AFF !important;
-	box-shadow: 0 8upx 40upx rgba(0, 122, 255, 0.25) !important;
-	background-color: rgba(0, 122, 255, 0.08) !important;
-	opacity: 0.9;
-	border-radius: 16upx;
-	transform: scale(1.02);
-	transition: none !important; /* 拖拽时禁用过渡动画 */
+  border: 2px dashed #007aff !important;
+  box-shadow: 0 8upx 40upx rgba(0, 122, 255, 0.25) !important;
+  background-color: rgba(0, 122, 255, 0.08) !important;
+  opacity: 0.9;
+  border-radius: 16upx;
+  transform: scale(1.02);
+  transition: none !important; /* 拖拽时禁用过渡动画 */
 }
 
 .list.target-position {
-	border: 3px solid #52C41A !important; /* 使用绿色边框区别于拖拽元素 */
-	box-shadow: 0 6upx 30upx rgba(82, 196, 26, 0.3) !important;
-	background-color: rgba(82, 196, 26, 0.1) !important;
-	opacity: 0.95;
-	border-radius: 16upx;
-	transform: scale(1.01);
-	transition: all 0.2s ease !important; /* 目标位置保持平滑过渡 */
-	
-	/* 添加一个内部指示器 */
-	&::before {
-		content: '移动到这儿';
-		position: absolute;
-		top: 50%;
-		left: 50%;
-		transform: translate(-50%, -50%);
-		padding: 8upx 22upx;
-		background: linear-gradient(90deg, #52C41A, #73D13D);
-		border-radius: 8upx;
-		color: #fff;
-		font-size: 26upx;
-		font-weight: bold;
-		opacity: 0.9;
-		z-index: 99990;
-	}
+  border: 3px solid #52c41a !important; /* 使用绿色边框区别于拖拽元素 */
+  box-shadow: 0 6upx 30upx rgba(82, 196, 26, 0.3) !important;
+  background-color: rgba(82, 196, 26, 0.1) !important;
+  opacity: 0.95;
+  border-radius: 16upx;
+  transform: scale(1.01);
+  transition: all 0.2s ease !important; /* 目标位置保持平滑过渡 */
+
+  /* 添加一个内部指示器 */
+  &::before {
+    content: '移动到这儿';
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    padding: 8upx 22upx;
+    background: linear-gradient(90deg, #52c41a, #73d13d);
+    border-radius: 8upx;
+    color: #fff;
+    font-size: 26upx;
+    font-weight: bold;
+    opacity: 0.9;
+    z-index: 99990;
+  }
 }
 
 .drag-handle {
-	display: flex;
-	align-items: center;
-	justify-content: center;
-	width: 80upx;
-	height: 75upx;
-	border-radius: 12upx;
-	background-color: rgba(0, 0, 0, 0.03);
-	transition: all 0.2s ease;
-	-webkit-touch-callout: none; /* 禁用长按菜单 */
-	-webkit-user-select: none; /* 禁用文本选择 */
-	user-select: none;
-	touch-action: none; /* 禁用浏览器默认触摸行为 */
-	
-	/* 增加触摸反馈 */
-	&:active {
-		transform: scale(1.1);
-		background-color: rgba(0, 122, 255, 0.1);
-		box-shadow: 0 4upx 16upx rgba(0, 122, 255, 0.2);
-	}
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 80upx;
+  height: 75upx;
+  border-radius: 12upx;
+  background-color: rgba(0, 0, 0, 0.03);
+  transition: all 0.2s ease;
+  -webkit-touch-callout: none; /* 禁用长按菜单 */
+  -webkit-user-select: none; /* 禁用文本选择 */
+  user-select: none;
+  touch-action: none; /* 禁用浏览器默认触摸行为 */
+
+  /* 增加触摸反馈 */
+  &:active {
+    transform: scale(1.1);
+    background-color: rgba(0, 122, 255, 0.1);
+    box-shadow: 0 4upx 16upx rgba(0, 122, 255, 0.2);
+  }
 }
 
 /* 防止拖拽时页面滚动 */
 .dragging-mode {
-	overflow: hidden !important;
-	touch-action: none !important;
-	-webkit-overflow-scrolling: auto !important;
+  overflow: hidden !important;
+  touch-action: none !important;
+  -webkit-overflow-scrolling: auto !important;
 }
-</style>
+</style>

+ 7 - 2
hdApp/src/admin/goods/picTextAdd-Edit.vue

@@ -16,7 +16,12 @@
         </tui-list-cell>
 
         <view class="editor-container">
-          <rich-media-editor ref="richEditor" v-model="form.imageTextVos" @change="onContentChange" :action="getLoginInfo.imgUploadApi" />
+          <rich-media-editor
+            ref="richEditor"
+            v-model="form.imageTextVos"
+            @change="onContentChange"
+            :action="getLoginInfo.imgUploadApi"
+          />
         </view>
 
         <view class="confirm-btn">
@@ -135,7 +140,7 @@ export default {
             } else {
               console.log('找不到richEditor引用');
             }
-          }, 100);
+          }, 50);
         });
         
         return 'edit';

+ 2 - 6
hdApp/src/admin/picText/picTextAdd.vue

@@ -29,7 +29,6 @@
 <script>
 import TuiListCell from "@/components/plugin/list-cell";
 import RichMediaEditor from "@/components/RichMediaEditor/index.vue";
-import { mapGetters } from 'vuex';
 const form = require("@/utils/formValidation.js");
 import { getPicText, createPicText, updatePicText } from "@/api/pic-text";
 
@@ -63,7 +62,8 @@ export default {
     }
   },
   methods: {
-    init(){},
+    init(){
+    },
     // 获取详情
     _getDet() {
       getPicText({ id: this.option.id }).then(res => {
@@ -96,8 +96,6 @@ export default {
           imageTextVos: content
         };
         
-        console.log('图文内容:', this.form.imageTextVos);
-        
         // 触发富文本编辑器内容更新
         this.$nextTick(() => {
           // 确保组件已经更新数据后再触发更新
@@ -149,7 +147,6 @@ export default {
       console.log('全局数据已设置:', app.globalData.previewData);
       
       // 跳转到预览页面
-      console.log('准备跳转到预览页面');
       uni.navigateTo({
         url: './preview',
         success: (res) => {
@@ -178,7 +175,6 @@ export default {
         params.id = this.option.id;
       }
       
-      console.log('提交参数:', params);
       
       apiCall(params).then(res => {
         uni.hideLoading();

+ 7 - 2
hdApp/src/admin/picText/preview.vue

@@ -9,7 +9,12 @@
 
     <!-- 预览内容区域 -->
     <view class="preview-content">
-      <rich-media-viewer ref="richMediaViewer" :content="previewContent" />
+      <rich-media-viewer 
+        ref="richMediaViewer" 
+        :content="previewContent"
+        :startScroll="250"
+        :threshold="450"
+      />
     </view>
   </view>
 </template>
@@ -134,7 +139,7 @@ export default {
 
 .preview-content {
   background-color: #fff;
-  margin: 20rpx;
+  margin: 8rpx;
   border-radius: 12rpx;
   overflow: hidden;
   box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);

+ 6 - 2
hdApp/src/admin/picText/viewerDemo.vue

@@ -5,7 +5,11 @@
     </view>
 
     <view class="viewer-container">
-      <rich-media-viewer :content="demoContent" />
+      <rich-media-viewer 
+      :content="demoContent" 
+      :startScroll="250"
+      :threshold="450"
+    />
     </view>
 
     <view class="action-buttons">
@@ -99,7 +103,7 @@ export default {
 <style lang="scss" scoped>
 .demo-page {
   min-height: 100vh;
-  padding: 20rpx;
+  padding: 8rpx;
   background-color: #f5f5f5;
 }
 

+ 22 - 5
hdApp/src/components/RichMediaEditor/index.vue

@@ -211,18 +211,23 @@ export default {
   data() {
     return {
       contentList: [],
+      oldContentList: [],
       selectedIndex: -1,
       showAddModalFlag: false,
       showImageModalFlag: false,
       currentAddIndex: -1,
       currentImageType: 1, // 1: 大图, 2: 小图
       currentSmallImageIndex: -1, // 当前编辑的小图组索引
-      IMGHOST // 图片基础URL
+      IMGHOST, // 图片基础URL
+      token: uni.getStorageSync('token')
     };
   },
   watch: {
     value: {
       handler(newVal) {
+        if (JSON.stringify(newVal) === JSON.stringify(this.contentList)) {
+          return;
+        }
         this.contentList = JSON.parse(JSON.stringify(newVal || []));
       },
       immediate: true,
@@ -230,6 +235,12 @@ export default {
     },
     contentList: {
       handler(newVal) {
+        const oldVal = this.oldContentList;
+        // console.log('RichMediaEditor contentList: ------ ', newVal, oldVal);
+        if (JSON.stringify(newVal) === JSON.stringify(oldVal)) {
+          return;
+        }
+        this.oldContentList = newVal;
         this.$emit('input', newVal);
         this.$emit('change', newVal);
       },
@@ -239,7 +250,7 @@ export default {
   methods: {
     // 更新内容方法,用于编辑模式
     updateContent(content) {
-      console.log('RichMediaEditor updateContent 接收到的数据:', content);
+      // console.log('RichMediaEditor updateContent 接收到的数据:', content);
       
       if (Array.isArray(content) && content.length > 0) {
         try {
@@ -265,9 +276,11 @@ export default {
             processedContent.push(newItem);
           });
           
-          console.log('处理后的内容:', processedContent);
+          // console.log('处理后的内容:', processedContent);
           this.contentList = processedContent;
-          this.$emit('input', this.contentList);
+
+          // 代码多余注释掉(watch中已经处理了),避免无限循环
+          // this.$emit('input', this.contentList);
           this.$emit('change', this.contentList);
         } catch (e) {
           console.error('更新内容时出错:', e);
@@ -386,6 +399,7 @@ export default {
         content: ''
       };
       this.contentList.push(newItem);
+      console.log('this.contentList', this.contentList);
       this.selectedIndex = this.contentList.length - 1;
     },
 
@@ -542,6 +556,9 @@ export default {
           formData: {
             rootPath: "uploads_pic_text"
           },
+          header: {
+            'token': this.token
+          },
           success: (uploadFileRes) => {
             try {
               const data = JSON.parse(uploadFileRes.data);
@@ -619,7 +636,7 @@ export default {
 
 .big-image-item {
   .big-image-container {
-    max-height: 600rpx;
+    height: auto;
     overflow: hidden;
     border-radius: 10rpx;
   }

+ 161 - 137
hdApp/src/components/RichMediaViewer/index.vue

@@ -16,7 +16,7 @@
             <image
               v-show="item.loaded"
               :src="item.shouldLoad ? getImageUrl(item.content) : ''"
-              mode="aspectFill"
+              mode="widthFix"
               class="big-image"
               @error="onImageError(index)"
               @load="onImageLoad(index)"
@@ -45,7 +45,7 @@
                 <!-- 实际图片 -->
                 <image
                   v-show="item.imageStatus[imgIndex]"
-                  :src="item.shouldLoadImages[imgIndex] ? getImageUrl(img) : ''"
+                  :src="item.shouldLoadImages[imgIndex] ? resizeImage(img, '150') : ''"
                   mode="aspectFill"
                   class="small-image"
                   @error="onSmallImageError(index, imgIndex)"
@@ -58,7 +58,7 @@
 
         <!-- 文本展示 -->
         <view v-else-if="item.type === 3" class="text-block">
-          <text class="text-content">{{ item.content }}</text>
+          <text class="text-content">{{ item.content }}</text>ß
         </view>
       </view>
 
@@ -77,7 +77,7 @@
             <text v-if="currentImageIndex >= 0" class="image-counter"> {{ currentImageIndex + 1 }} / {{ currentImageList.length }} </text>
           </view>
           <view class="close-btn" @click="closeImagePreview">
-            <zui-svg-icon icon="general-close" :width="16" :height="16" color="#fff" style="margin-top: 10rpx;"/>
+            <zui-svg-icon icon="general-close" :width="16" :height="16" color="#fff" style="margin-top: 10rpx" />
           </view>
         </view>
 
@@ -91,7 +91,7 @@
             :indicator-dots="true"
             indicator-color="rgba(255,255,255,0.5)"
             indicator-active-color="#fff"
-            style="height: 100%; width: 100%;"
+            style="height: 100%; width: 100%"
           >
             <swiper-item v-for="(img, index) in currentImageList" :key="index" class="swiper-item">
               <view class="preview-image-wrapper">
@@ -106,7 +106,7 @@
                 <image
                   v-show="previewImageStatus[index]"
                   :src="img"
-                  mode="aspectFit"
+                  mode="widthFix"
                   class="preview-image"
                   @error="onPreviewImageError(index)"
                   @load="onPreviewImageLoad(index)"
@@ -129,7 +129,7 @@
             <image
               v-show="previewImageStatus[0]"
               :src="currentPreviewImage"
-              mode="aspectFit"
+              mode="widthFix"
               class="preview-image single"
               @error="onPreviewImageError(0)"
               @load="onPreviewImageLoad(0)"
@@ -157,15 +157,25 @@
 </template>
 
 <script>
-import { IMGHOST } from '@/config.js'
+import { IMGHOST } from '@/config.js';
 
 export default {
   name: 'RichMediaViewer',
   props: {
     content: {
       type: Array,
-      default: () => [],
+      default: () => []
     },
+    // 开始加载的距离
+    startScroll: {
+      type: Number,
+      default: 0
+    },
+    // 提前开始加载的距离
+    threshold: {
+      type: Number,
+      default: 300
+    }
   },
   data() {
     return {
@@ -176,25 +186,25 @@ export default {
       currentImageIndex: 0,
       previewImageStatus: {}, // 预览图片加载状态
       IMGHOST,
-      throttledCheckVisibility: null,
-    }
+      throttledCheckVisibility: null
+    };
   },
   created() {
     // 在 created 钩子中创建节流函数,确保只创建一次
-    this.throttledCheckVisibility = this.throttle(this.checkImageVisibility, 125)
+    this.throttledCheckVisibility = this.throttle(this.checkImageVisibility, 125);
   },
   watch: {
     content: {
       handler(newVal) {
-        this.contentList = this.initializeContentList(newVal || [])
+        this.contentList = this.initializeContentList(newVal || []);
         // 初始化完成后立即检查一次
         this.$nextTick(() => {
-          this.checkImageVisibility()
-        })
+          this.checkImageVisibility(this.startScroll); // 开始加载
+        });
       },
       immediate: true,
-      deep: true,
-    },
+      deep: true
+    }
   },
   mounted() {
     // 初始化时检查一次
@@ -209,209 +219,232 @@ export default {
     // 公开方法,供父组件在 onPageScroll 中调用
     triggerCheckVisibility() {
       if (this.throttledCheckVisibility) {
-        this.throttledCheckVisibility()
+        this.throttledCheckVisibility();
       }
     },
 
     // 节流函数
     throttle(func, delay) {
-      let lastCall = 0
+      let lastCall = 0;
       return function (...args) {
-        const now = Date.now()
+        const now = Date.now();
         if (now - lastCall >= delay) {
-          lastCall = now
-          func.apply(this, args)
+          lastCall = now;
+          func.apply(this, args);
         }
-      }
+      };
     },
 
     // 初始化内容列表,添加懒加载状态
     initializeContentList(content) {
-      return content.map(item => {
-        const newItem = { ...item }
+      return content.map((item) => {
+        const newItem = { ...item };
 
         if (item.type === 1) {
           // 大图:添加加载状态
-          newItem.loaded = false
-          newItem.shouldLoad = false // 默认不加载
+          newItem.loaded = false;
+          newItem.shouldLoad = false; // 默认不加载
         } else if (item.type === 2) {
           // 小图网格:为每个图片添加加载状态
-          newItem.imageStatus = {}
-          newItem.shouldLoadImages = {} // 为每个小图添加加载状态
+          newItem.imageStatus = {};
+          newItem.shouldLoadImages = {}; // 为每个小图添加加载状态
           if (Array.isArray(item.content)) {
             item.content.forEach((_, imgIndex) => {
-              newItem.imageStatus[imgIndex] = false
-              newItem.shouldLoadImages[imgIndex] = false // 默认不加载
-            })
+              newItem.imageStatus[imgIndex] = false;
+              newItem.shouldLoadImages[imgIndex] = false; // 默认不加载
+            });
           }
         }
 
-        return newItem
-      })
+        return newItem;
+      });
     },
 
     // 检查图片可见性 (重构以提高性能)
-    checkImageVisibility() {
-      let scrollTop = 0
+    checkImageVisibility(startScroll = 0) {
+      // console.log('---------- checkImageVisibility startScroll: ', startScroll);
+      let scrollTop = 0;
       // 获取当前滚动的距离
-      uni.createSelectorQuery().selectViewport().scrollOffset().exec((res) => {
-        scrollTop = res[0].scrollTop
-        // console.log('---------- checkImageVisibility 当前滚动距离:', scrollTop)
-      })
-      const threshold = 280 // 提前300px开始加载
-      const query = uni.createSelectorQuery().in(this)
-      const elementsToWatch = []
+      uni
+        .createSelectorQuery()
+        .selectViewport()
+        .scrollOffset()
+        .exec((res) => {
+          scrollTop = res[0].scrollTop;
+          // console.log('---------- checkImageVisibility 当前滚动距离:', scrollTop);
+          if (startScroll > 0 && startScroll > scrollTop) {
+            scrollTop = startScroll;
+          }
+        });
+      const threshold = this.threshold; // 提前开始加载的距离
+      const query = uni.createSelectorQuery().in(this);
+      const elementsToWatch = [];
 
       this.contentList.forEach((item, index) => {
         if (item.type === 1 && !item.loaded && !item.shouldLoad) {
-          query.select(`#big-image-${index}`).boundingClientRect()
-          elementsToWatch.push({ type: 'big', index })
+          query.select(`#big-image-${index}`).boundingClientRect();
+          elementsToWatch.push({ type: 'big', index });
         } else if (item.type === 2 && Array.isArray(item.content)) {
           item.content.forEach((_, imgIndex) => {
             if (!item.imageStatus[imgIndex] && !item.shouldLoadImages[imgIndex]) {
-              query.select(`#small-image-${index}-${imgIndex}`).boundingClientRect()
-              elementsToWatch.push({ type: 'small', index, imgIndex })
+              query.select(`#small-image-${index}-${imgIndex}`).boundingClientRect();
+              elementsToWatch.push({ type: 'small', index, imgIndex });
             }
-          })
+          });
         }
-      })
+      });
 
       if (elementsToWatch.length === 0) {
-        return
+        return;
       }
 
       query.exec((rects) => {
-        if (!Array.isArray(rects)) return
+        if (!Array.isArray(rects)) return;
         rects.forEach((rect, i) => {
-          // console.log('rect.top ---- scrollTop + threshold: ', rect.top, scrollTop + threshold)
+          // console.log('rect.top ---- scrollTop + threshold: ', rect.top, scrollTop + threshold);
           if (rect && rect.top <= scrollTop + threshold) {
-            // console.log('rect.top <= scrollTop + threshold: ', rect.top, scrollTop + threshold)
-            const element = elementsToWatch[i]
+            // console.log('rect.top <= scrollTop + threshold: ', rect.top, scrollTop + threshold);
+            const element = elementsToWatch[i];
             if (element.type === 'big') {
-              this.contentList[element.index].shouldLoad = true
+              this.contentList[element.index].shouldLoad = true;
             } else if (element.type === 'small') {
-              this.contentList[element.index].shouldLoadImages[element.imgIndex] = true
+              this.contentList[element.index].shouldLoadImages[element.imgIndex] = true;
             }
           }
-        })
-      })
+        });
+      });
     },
 
     // 获取完整图片URL
     getImageUrl(imagePath) {
-      if (!imagePath) return ''
-      return imagePath.startsWith('http') ? imagePath : `${IMGHOST}/${imagePath}`
+      if (!imagePath) return '';
+      return imagePath.startsWith('http') ? imagePath : `${IMGHOST}/${imagePath}`;
+    },
+
+    // 生成不同大小的图片URL
+    resizeImage(imagePath, imageSize = '0') {
+      let url = this.getImageUrl(imagePath);
+      if (imageSize === '0') {
+        return url;
+      } else {
+        // 获取指定宽度、按原比例缩放的图片
+        return `${url}?x-oss-process=image/resize,w_${imageSize}`;
+        // 获取指定固定宽高,并从原图中心裁剪
+        // return `${url}?x-oss-process=image/resize,m_fill,h_${imageSize},w_${imageSize}`;
+      }
     },
 
     // 预览单张大图
     previewImage(imageUrl) {
-      const fullImageUrl = this.getImageUrl(imageUrl)
-      this.currentPreviewImage = fullImageUrl
-      this.currentImageList = [fullImageUrl]
-      this.currentImageIndex = 0
-      this.showImagePreview = true
+      const fullImageUrl = this.getImageUrl(imageUrl);
+      this.currentPreviewImage = fullImageUrl;
+      this.currentImageList = [fullImageUrl];
+      this.currentImageIndex = 0;
+      this.showImagePreview = true;
       // 初始化预览图片状态
-      this.previewImageStatus = { 0: false }
+      this.previewImageStatus = { 0: false };
     },
 
     // 预览小图(支持左右滑动)
     previewSmallImage(selectedImage, index, imageList) {
-      const fullImageUrl = this.getImageUrl(selectedImage)
-      const fullImageList = imageList.map(img => this.getImageUrl(img))
-      this.currentPreviewImage = fullImageUrl
-      this.currentImageList = fullImageList
-      this.currentImageIndex = index
-      this.showImagePreview = true
+      const fullImageUrl = this.getImageUrl(selectedImage);
+      const fullImageList = imageList.map((img) => {
+        return this.resizeImage(img, '800');
+      });
+      this.currentPreviewImage = fullImageUrl;
+      this.currentImageList = fullImageList;
+      this.currentImageIndex = index;
+      this.showImagePreview = true;
       // 初始化预览图片状态
-      const newStatus = {}
+      const newStatus = {};
       fullImageList.forEach((_, imgIndex) => {
-        newStatus[imgIndex] = false
-      })
-      this.previewImageStatus = newStatus
+        newStatus[imgIndex] = false;
+      });
+      this.previewImageStatus = newStatus;
     },
 
     // 关闭图片预览
     closeImagePreview() {
-      this.showImagePreview = false
-      this.currentPreviewImage = ''
-      this.currentImageList = []
-      this.currentImageIndex = 0
-      this.previewImageStatus = {}
+      this.showImagePreview = false;
+      this.currentPreviewImage = '';
+      this.currentImageList = [];
+      this.currentImageIndex = 0;
+      this.previewImageStatus = {};
     },
 
     // swiper变化事件
     onSwiperChange(e) {
-      this.currentImageIndex = e.detail.current
-      this.currentPreviewImage = this.currentImageList[this.currentImageIndex]
+      this.currentImageIndex = e.detail.current;
+      this.currentPreviewImage = this.currentImageList[this.currentImageIndex];
     },
 
     // 上一张图片
     prevImage() {
       if (this.currentImageIndex > 0) {
-        this.currentImageIndex--
-        this.currentPreviewImage = this.currentImageList[this.currentImageIndex]
+        this.currentImageIndex--;
+        this.currentPreviewImage = this.currentImageList[this.currentImageIndex];
       }
     },
 
     // 下一张图片
     nextImage() {
       if (this.currentImageIndex < this.currentImageList.length - 1) {
-        this.currentImageIndex++
-        this.currentPreviewImage = this.currentImageList[this.currentImageIndex]
+        this.currentImageIndex++;
+        this.currentPreviewImage = this.currentImageList[this.currentImageIndex];
       }
     },
 
     // 大图加载错误处理
     onImageError(index) {
-      console.error('大图加载失败:', index)
-      this.contentList[index].loaded = true // 标记图片加载失败,不再重复加载
+      console.error('大图加载失败:', index);
+      this.contentList[index].loaded = true; // 标记图片加载失败,不再重复加载
       uni.showToast({
         title: '图片加载失败',
         icon: 'error',
         duration: 500
-      })
+      });
     },
 
     // 大图加载成功处理
     onImageLoad(index) {
-      this.contentList[index].loaded = true
+      this.contentList[index].loaded = true;
     },
 
     // 小图加载错误处理
     onSmallImageError(index, imgIndex) {
-      console.error('小图加载失败:', index, imgIndex)
-      this.contentList[index].imageStatus[imgIndex] = true // 标记小图加载失败,不再重复加载
+      console.error('小图加载失败:', index, imgIndex);
+      this.contentList[index].imageStatus[imgIndex] = true; // 标记小图加载失败,不再重复加载
       uni.showToast({
         title: '图片加载失败',
         icon: 'error',
         duration: 500
-      })
+      });
     },
 
     // 小图加载成功处理
     onSmallImageLoad(index, imgIndex) {
-      this.contentList[index].imageStatus[imgIndex] = true
+      this.contentList[index].imageStatus[imgIndex] = true;
     },
 
     // 预览图片加载错误处理
     onPreviewImageError(index) {
-      console.error('预览图片加载失败:', index)
-      this.$set(this.previewImageStatus, index, true) // 标记预览图片加载失败,不再重复加载
+      console.error('预览图片加载失败:', index);
+      this.$set(this.previewImageStatus, index, true); // 标记预览图片加载失败,不再重复加载
       uni.showToast({
         title: '图片加载失败',
         icon: 'error',
         duration: 500
-      })
+      });
     },
 
     // 预览图片加载成功处理
     onPreviewImageLoad(index) {
-      this.$set(this.previewImageStatus, index, true)
+      this.$set(this.previewImageStatus, index, true);
     },
 
     // 保存图片到相册(可选功能)
     saveImage() {
-      if (!this.currentPreviewImage) return
+      if (!this.currentPreviewImage) return;
 
       // #ifdef APP-PLUS || H5
       uni.downloadFile({
@@ -421,19 +454,19 @@ export default {
           uni.saveImageToPhotosAlbum({
             filePath: res.tempFilePath,
             success: () => {
-              uni.showToast({ title: '保存成功', icon: 'success' })
+              uni.showToast({ title: '保存成功', icon: 'success' });
             },
             fail: () => {
-              uni.showToast({ title: '保存失败', icon: 'error' })
+              uni.showToast({ title: '保存失败', icon: 'error' });
             }
-          })
+          });
           // #endif
         }
-      })
+      });
       // #endif
-    },
-  },
-}
+    }
+  }
+};
 </script>
 
 <style lang="scss" scoped>
@@ -443,7 +476,7 @@ export default {
 }
 
 .content-container {
-  padding: 20rpx;
+  padding: 12rpx;
 }
 
 .content-block {
@@ -459,25 +492,21 @@ export default {
   .image-wrapper {
     position: relative;
     width: 100%;
-    height: 0;
-    padding-bottom: 66.67%; /* 16:9 宽高比 */
-    border-radius: 12rpx;
+    height: auto;
+    border-radius: 8rpx;
     overflow: hidden;
     box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
   }
 
   .image-placeholder {
-    position: absolute;
-    top: 0;
-    left: 0;
+    position: relative;
     width: 100%;
-    height: 100%;
+    min-height: 280rpx;
     background-color: #f0f0f0;
     display: flex;
     align-items: center;
     justify-content: center;
-    border-radius: 12rpx;
-    z-index: 1;
+    border-radius: 8rpx;
 
     .placeholder-content {
       text-align: center;
@@ -499,12 +528,9 @@ export default {
   }
 
   .big-image {
-    position: absolute;
-    top: 0;
-    left: 0;
     width: 100%;
-    height: 100%;
-    object-fit: cover;
+    height: auto;
+    display: block;
   }
 }
 
@@ -516,9 +542,8 @@ export default {
     gap: 12rpx;
 
     .small-image-item {
-      width: calc(33.333% - 8rpx);
+      width: calc(33% - 8rpx);
       aspect-ratio: 1;
-      border-radius: 8rpx;
       overflow: hidden;
       box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
 
@@ -659,7 +684,7 @@ export default {
     display: flex;
     align-items: center;
     justify-content: center;
-    padding: 20rpx;
+    // padding: 20rpx;
     height: 100%;
     box-sizing: border-box;
   }
@@ -668,9 +693,11 @@ export default {
 .preview-image-wrapper {
   position: relative;
   width: 100%;
-  height: 0;
-  padding-bottom: 66.67%; /* 16:9 宽高比 */
-  border-radius: 12rpx;
+  height: auto;
+  min-height: 200rpx; /* 增加最小高度,避免图片加载前闪烁 */
+  display: flex;
+  align-items: center;
+  justify-content: center;
   overflow: hidden;
   box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
 }
@@ -708,17 +735,14 @@ export default {
 }
 
 .preview-image {
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  object-fit: cover;
-  border-radius: 12rpx;
+  max-width: 100%;
+  max-height: 100%;
+  height: auto;
+  display: block;
 
   &.single {
-    width: calc(100% - 20rpx);
-    height: calc(100% - 20rpx);
+    width: 100%;
+    height: auto;
   }
 }
 

+ 41 - 42
mallApp/src/components/RichMediaViewer/index.vue

@@ -16,7 +16,7 @@
             <image
               v-show="item.loaded"
               :src="item.shouldLoad ? getImageUrl(item.content) : ''"
-              mode="aspectFill"
+              mode="widthFix"
               class="big-image"
               @error="onImageError(index)"
               @load="onImageLoad(index)"
@@ -45,7 +45,7 @@
                 <!-- 实际图片 -->
                 <image
                   v-show="item.imageStatus[imgIndex]"
-                  :src="item.shouldLoadImages[imgIndex] ? getImageUrl(img) : ''"
+                  :src="item.shouldLoadImages[imgIndex] ? resizeImage(img, '150') : ''"
                   mode="aspectFill"
                   class="small-image"
                   @error="onSmallImageError(index, imgIndex)"
@@ -106,11 +106,10 @@
                 <image
                   v-show="previewImageStatus[index]"
                   :src="img"
-                  mode="aspectFit"
+                  mode="widthFix"
                   class="preview-image"
                   @error="onPreviewImageError(index)"
                   @load="onPreviewImageLoad(index)"
-                  @longpress="saveImage"
                 />
               </view>
             </swiper-item>
@@ -129,11 +128,10 @@
             <image
               v-show="previewImageStatus[0]"
               :src="currentPreviewImage"
-              mode="aspectFit"
+              mode="widthFix"
               class="preview-image single"
               @error="onPreviewImageError(0)"
               @load="onPreviewImageLoad(0)"
-              @longpress="saveImage"
             />
           </view>
         </view>
@@ -299,7 +297,9 @@ export default {
     // 预览小图(支持左右滑动)
     previewSmallImage(selectedImage, index, imageList) {
       const fullImageUrl = this.getImageUrl(selectedImage)
-      const fullImageList = imageList.map(img => this.getImageUrl(img))
+      const fullImageList = imageList.map(img => {
+        return this.resizeImage(img, '800');
+      })
       this.currentPreviewImage = fullImageUrl
       this.currentImageList = fullImageList
       this.currentImageIndex = index
@@ -343,6 +343,19 @@ export default {
       }
     },
 
+    // 生成不同大小的图片URL
+    resizeImage(imagePath, imageSize = '0') {
+      let url = this.getImageUrl(imagePath);
+      if (imageSize === '0') {
+        return url;
+      } else {
+        // 获取指定宽度、按原比例缩放的图片
+        return `${url}?x-oss-process=image/resize,w_${imageSize}`;
+        // 获取指定固定宽高,并从原图中心裁剪
+        // return `${url}?x-oss-process=image/resize,m_fill,h_${imageSize},w_${imageSize}`;
+      }
+    },
+
     // 大图加载错误处理
     onImageError(index) {
       console.error('大图加载失败:', index)
@@ -427,7 +440,7 @@ export default {
 }
 
 .content-container {
-  padding: 20rpx;
+  padding: 16rpx;
 }
 
 .content-block {
@@ -443,25 +456,21 @@ export default {
   .image-wrapper {
     position: relative;
     width: 100%;
-    height: 0;
-    padding-bottom: 66.67%; /* 16:9 宽高比 */
-    border-radius: 12rpx;
+    height: auto;
+    border-radius: 8rpx;
     overflow: hidden;
     box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
   }
 
   .image-placeholder {
-    position: absolute;
-    top: 0;
-    left: 0;
+    position: relative;
     width: 100%;
-    height: 100%;
+    min-height: 280rpx;
     background-color: #f0f0f0;
     display: flex;
     align-items: center;
     justify-content: center;
-    border-radius: 12rpx;
-    z-index: 1;
+    border-radius: 8rpx;
 
     .placeholder-content {
       text-align: center;
@@ -483,12 +492,9 @@ export default {
   }
 
   .big-image {
-    position: absolute;
-    top: 0;
-    left: 0;
     width: 100%;
-    height: 100%;
-    object-fit: cover;
+    height: auto;
+    display: block;
   }
 }
 
@@ -500,9 +506,8 @@ export default {
     gap: 12rpx;
 
     .small-image-item {
-      width: calc(33.333% - 8rpx);
+      width: calc(33% - 8rpx);
       aspect-ratio: 1;
-      border-radius: 8rpx;
       overflow: hidden;
       box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
 
@@ -643,7 +648,7 @@ export default {
     display: flex;
     align-items: center;
     justify-content: center;
-    padding: 20rpx;
+    // padding: 20rpx;
     height: 100%;
     box-sizing: border-box;
   }
@@ -652,9 +657,11 @@ export default {
 .preview-image-wrapper {
   position: relative;
   width: 100%;
-  height: 0;
-  padding-bottom: 66.67%; /* 16:9 宽高比 */
-  border-radius: 12rpx;
+  height: auto;
+  min-height: 200rpx; /* 增加最小高度,避免图片加载前闪烁 */
+  display: flex;
+  align-items: center;
+  justify-content: center;
   overflow: hidden;
   box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
 }
@@ -692,17 +699,14 @@ export default {
 }
 
 .preview-image {
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  object-fit: cover;
-  border-radius: 12rpx;
+  max-width: 100%;
+  max-height: 100%;
+  height: auto;
+  display: block;
 
   &.single {
-    width: calc(100% - 20rpx);
-    height: calc(100% - 20rpx);
+    width: 100%;
+    height: auto;
   }
 }
 
@@ -745,11 +749,6 @@ export default {
   .small-images-container {
     .small-image-item {
       width: calc(50% - 6rpx);
-
-      /* gap属性可以处理间距,无需额外设置 */
-      /* &:nth-child(odd) {
-        margin-right: 6rpx;
-      } */
     }
   }
 

+ 1 - 1
mallApp/src/pages/goods/detail.vue

@@ -227,7 +227,7 @@ export default {
     .module-det {
       color: $fontColor2;
       .module-det-text {
-        padding: 24upx;
+        padding: 0upx;
       }
     }
 

+ 1 - 1
mallApp/src/static/svg-icons-lib.js

@@ -6,7 +6,7 @@
  *
  * !!! DO NOT MODIFY MANUALLY !!!
  *
- * @datetime 2025-8-1 16:40:13
+ * @datetime 2025-8-1 17:23:07
  *
  */