Procházet zdrojové kódy

feat(红包): 添加红包分享功能及优化界面交互

- 在销售页面添加红包悬浮按钮
- 实现红包分享页面的微信分享功能
- 优化红包领取页面的交互逻辑
- 调整红包分享页面的样式和布局
ylong před 2 týdny
rodič
revize
60351fb797
3 změnil soubory, kde provedl 653 přidání a 557 odebrání
  1. 41 34
      packet/pages/get.vue
  2. 82 49
      packet/pages/share.vue
  3. 530 474
      pages-sell/components/sell-container/index.vue

+ 41 - 34
packet/pages/get.vue

@@ -15,7 +15,7 @@
                 <!-- Top Amount Row -->
                 <view class="top-amount-row">
                     <text class="received-text">¥{{ redBagData.redPrice || 0 }} 红包已到账</text>
-                    <view class="use-btn-wrapper">
+                    <view class="use-btn-wrapper" @click="handleUse">
                         <text class="use-btn-text">点击使用</text>
                     </view>
                 </view>
@@ -36,9 +36,9 @@
                 </view>
 
                 <!-- Invite Button -->
-                <view class="invite-btn-wrapper">
+                <button class="invite-btn-wrapper" open-type="share" @getuserinfo="handleInvite">
                     <text class="invite-btn-text">立即邀请</text>
-                </view>
+                </button>
 
                 <!-- Red Packet Cards -->
                 <view class="red-packets-section">
@@ -52,14 +52,15 @@
                 <view class="progress-section">
                     <view class="progress-bar-bg">
                         <view class="progress-bar-fill" :style="{ width: progressWidth + '%' }"></view>
-                        <image src="/packet/static/get/circle.png" class="progress-dot" :style="{ left: progressWidth + '%' }" mode="aspectFit"></image>
+                        <image src="/packet/static/get/circle.png" class="progress-dot"
+                            :style="{ left: progressWidth + '%' }" mode="aspectFit"></image>
                     </view>
                     <text class="progress-text">已邀请{{ redBagData.shareNum || 0 }}人,已领{{ redBagData.shareGetNum || 0
-                        }}元,最高还可得¥{{ maxGetPrice }} 元</text>
+                    }}元,最高还可得¥{{ maxGetPrice }} 元</text>
                 </view>
 
                 <!-- Continue Scan Button -->
-                <view class="scan-btn-wrapper">
+                <view class="scan-btn-wrapper" @click="handleScan">
                     <text class="scan-btn-text">继续扫码</text>
                 </view>
 
@@ -96,6 +97,14 @@ export default {
             this.getRedBagDetail();
         }
     },
+    onShareAppMessage() {
+        // 设置分享内容
+        return {
+            title: '好友助力解锁最高' + (this.redBagData?.shareSumPrice) + '元红包',
+            path: '/packet/pages/index?bianhao=' + this.bianhao,
+            imageUrl: '' // 使用默认分享图
+        };
+    },
     methods: {
         // 获取红包详情
         async getRedBagDetail() {
@@ -127,42 +136,31 @@ export default {
             }
         },
         handleUse() {
-            // 使用红包逻辑
-            uni.showToast({
-                title: '即将跳转到使用页面',
-                icon: 'none'
+            // 跳转到商城页面
+            uni.switchTab({
+                url: '/pages/sell/index'
             });
         },
         handleInvite() {
-            // 邀请好友逻辑
-            if (this.redBagData && this.redBagData.shareRedLink) {
-                // 分享红包链接
-                uni.showModal({
-                    title: '分享红包',
-                    content: '请复制链接分享给好友:' + this.redBagData.shareRedLink,
-                    confirmText: '复制链接',
-                    success: (res) => {
-                        if (res.confirm) {
-                            uni.setClipboardData({
-                                data: this.redBagData.shareRedLink
-                            });
-                        }
-                    }
-                });
-            } else {
-                uni.showToast({
-                    title: '暂无分享链接',
-                    icon: 'none'
-                });
-            }
+            // 邀请好友逻辑 - 此方法会在用户点击分享按钮时触发
+            // 实际分享内容由 onShareAppMessage 控制
         },
         handleScan() {
             // 继续扫码逻辑
             uni.scanCode({
                 success: (scanRes) => {
+                    //获取扫描结果中 bianhao 参数
+                    const bianhao = scanRes.result.split('=')[1];
+                    if (!bianhao) {
+                        uni.showToast({
+                            title: '扫描结果格式错误',
+                            icon: 'none'
+                        });
+                        return;
+                    }
                     // 扫描到新红包,跳转到 index 页面
                     uni.redirectTo({
-                        url: '/packet/pages/index?bianhao=' + scanRes.result
+                        url: '/packet/pages/index?bianhao=' + bianhao
                     });
                 }
             });
@@ -322,6 +320,14 @@ export default {
                 display: flex;
                 align-items: center;
                 justify-content: center;
+                border: none;
+                padding: 0;
+                line-height: normal;
+                font-size: 0;
+
+                &::after {
+                    border: none;
+                }
 
                 .invite-btn-text {
                     font-family: Adobe Heiti Std;
@@ -360,6 +366,7 @@ export default {
             .progress-section {
                 margin-bottom: 30rpx;
                 padding: 0 30rpx;
+
                 .progress-bar-bg {
                     position: relative;
                     width: 100%;
@@ -381,8 +388,8 @@ export default {
                         position: absolute;
                         top: 50%;
                         transform: translateX(-50%) translateY(-50%);
-                        width: 32rpx;
-                        height: 32rpx;
+                        width: 40rpx;
+                        height: 40rpx;
                     }
                 }
 

+ 82 - 49
packet/pages/share.vue

@@ -9,21 +9,20 @@
             <view class="card" v-for="(item, index) in shareList" :key="index">
                 <!-- Header -->
                 <view class="card-header">
-                    <text class="card-title">邀请好友同享最高可得{{ item.shareSumPrice || 15 }}元红包</text>
-                    <text class="card-time">{{ formatExpireTime(item.shareRedBagExpire) }}</text>
+                    <text class="card-title">邀请好友同享最高可得{{ item.shareSumPrice }}元红包</text>
+                    <text class="card-time">{{ item.shareRedBagExpire }}</text>
                 </view>
 
                 <!-- Progress Section -->
                 <view class="progress-section">
                     <!-- Left Icon -->
-                    <image src="/packet/static/share/invite-text.png" class="left-icon" mode="widthFix"></image>
+                    <image src="/packet/static/share/invite-text.png" class="left-icon" mode="heightFix"></image>
 
                     <!-- Center Content -->
                     <view class="center-content">
                         <!-- Progress Bubble -->
                         <view class="progress-bubble">
-                            <text>已领{{ item.shareGetNum || 0 }}元,最高还可得{{ (item.shareSumPrice || 0) - (item.shareGetNum
-                                || 0) }}元</text>
+                            <text>已领{{ item.shareGetNum || 0 }}元,最高还可得{{ (item.shareSumPrice || 0) - (item.shareGetNum || 0) }}元</text>
                         </view>
 
                         <!-- Progress Bar -->
@@ -41,14 +40,13 @@
                     </view>
 
                     <!-- Right Packet Icon -->
-                    <image src="/packet/static/share/red-packet.png" class="right-packet" mode="widthFix"></image>
+                    <image src="/packet/static/share/red-packet.png" class="right-packet" mode="heightFix"></image>
                 </view>
 
                 <!-- Share/Detail Button -->
-                <view class="btn-wrapper">
-                    <image src="/packet/static/share/share-btn.png" class="btn-image" mode="widthFix"></image>
-                    <text class="btn-text">{{ index === 0 ? '立即分享' : '查看详情' }}</text>
-                </view>
+                <button class="btn-wrapper" open-type="share" :data-index="index" @getuserinfo="handleShare">
+                    <text class="btn-text">立即分享</text>
+                </button>
             </view>
         </view>
     </view>
@@ -65,6 +63,19 @@ export default {
         // 获取分享列表
         this.getShareList();
     },
+    onShareAppMessage(options) {
+        console.log(options);
+        // 从 options 中获取卡片索引
+        const index = options?.target?.dataset?.index || 0;
+        const item = this.shareList[index] || this.shareList[0];
+        
+        // 设置分享内容 - 使用对应卡片的数据
+        return {
+            title: '邀请好友同享最高可得' + (item?.shareSumPrice) + '元红包',
+            path: '/packet/pages/share',
+            imageUrl: '' // 使用默认分享图
+        };
+    },
     methods: {
         // 获取分享列表
         async getShareList() {
@@ -131,13 +142,14 @@ export default {
 
 <style lang="scss" scoped>
 .share-page {
-    min-height: 100vh;
+    height: 100vh;
     position: relative;
     display: flex;
     flex-direction: column;
     align-items: center;
     padding: 40rpx 30rpx;
     box-sizing: border-box;
+    padding-top: 0;
 
     .bg-image {
         position: fixed;
@@ -153,21 +165,23 @@ export default {
         z-index: 1;
         width: 100%;
         max-width: 700rpx;
-        padding-top: 60rpx;
+        padding: 60rpx 0;
+        margin-top: 350rpx;
 
         .card {
             background: #fff;
             border-radius: 24rpx;
             overflow: hidden;
             margin-bottom: 40rpx;
-            box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
 
             .card-header {
-                background: linear-gradient(135deg, #4CAF50 0%, #66BB6A 100%);
+                background: #03A65F;
                 padding: 24rpx 30rpx;
                 display: flex;
                 justify-content: space-between;
                 align-items: center;
+                height: 79rpx;
+                box-sizing: border-box;
 
                 .card-title {
                     font-size: 28rpx;
@@ -185,15 +199,19 @@ export default {
             }
 
             .progress-section {
-                padding: 40rpx 30rpx;
+                padding: 30rpx 50rpx;
                 display: flex;
-                align-items: flex-start;
+                align-items: center;
                 gap: 20rpx;
+                position: relative;
 
                 .left-icon {
                     width: 80rpx;
                     height: 80rpx;
                     flex-shrink: 0;
+                    position: absolute;
+                    top: 20%;
+                    left: 40rpx;
                 }
 
                 .center-content {
@@ -201,12 +219,14 @@ export default {
                     display: flex;
                     flex-direction: column;
                     align-items: center;
+                    margin-top: 40rpx;
 
                     .progress-bubble {
-                        background: linear-gradient(135deg, #4CAF50 0%, #66BB6A 100%);
+                        background: #18B94E;
                         padding: 12rpx 28rpx;
-                        border-radius: 24rpx;
-                        margin-bottom: 24rpx;
+                        border-radius: 30rpx;
+                        margin-bottom: 30rpx;
+                        margin-left: 10rpx;
 
                         text {
                             font-size: 24rpx;
@@ -218,31 +238,40 @@ export default {
                     .progress-bar-container {
                         position: relative;
                         width: 100%;
-                        height: 8rpx;
-                        background: linear-gradient(90deg, #E8F5E9 0%, #C8E6C9 100%);
-                        border-radius: 4rpx;
-                        margin-bottom: 20rpx;
+                        height: 15rpx;
+                        background: #BDFAAD;
+                        border-radius: 6rpx;
+                        margin-bottom: 16rpx;
 
                         .progress-line {
                             position: absolute;
                             left: 0;
                             top: 0;
                             height: 100%;
-                            width: 100%;
                             background: linear-gradient(90deg, #4CAF50 0%, #8BC34A 100%);
-                            border-radius: 4rpx;
+                            border-radius: 6rpx;
                         }
 
                         .progress-dot {
                             position: absolute;
                             top: 50%;
                             transform: translate(-50%, -50%);
-                            width: 36rpx;
-                            height: 36rpx;
-                            background: linear-gradient(135deg, #4CAF50 0%, #66BB6A 100%);
+                            width: 32rpx;
+                            height: 32rpx;
+                            background: #fff;
                             border-radius: 50%;
-                            box-shadow: 0 4rpx 12rpx rgba(76, 175, 80, 0.4);
-                            border: 4rpx solid #fff;
+                            box-shadow: 0 2rpx 8rpx rgba(76, 175, 80, 0.3);
+                            display: flex;
+                            align-items: center;
+                            justify-content: center;
+
+                            &::after {
+                                content: '';
+                                width: 24rpx;
+                                height: 24rpx;
+                                background: linear-gradient(135deg, #4CAF50 0%, #66BB6A 100%);
+                                border-radius: 50%;
+                            }
                         }
                     }
 
@@ -252,45 +281,49 @@ export default {
                         width: 100%;
 
                         .label {
-                            font-size: 24rpx;
-                            color: #666;
+                            font-size: 26rpx;
+                            color: #333;
                             text-align: center;
+                            font-weight: 600;
                             flex: 1;
                         }
                     }
                 }
 
                 .right-packet {
-                    width: 90rpx;
-                    height: 90rpx;
+                    width: 60rpx;
+                    height: 80rpx;
                     flex-shrink: 0;
+                    position: absolute;
+                    top: 20%;
+                    right: 40rpx;
                 }
             }
 
             .btn-wrapper {
                 position: relative;
+                width: 300rpx;
+                height: 90rpx;
+                margin: 0 auto 30rpx;
+                background: url('/packet/static/share/share-btn.png') no-repeat center center;
+                background-size: 100% 100%;
                 display: flex;
+                align-items: center;
                 justify-content: center;
-                padding: 0 30rpx 40rpx;
+                border: none;
+                padding: 0;
+                line-height: normal;
+                font-size: 0;
 
-                .btn-image {
-                    width: 320rpx;
-                    height: 88rpx;
-                    display: block;
+                &::after {
+                    border: none;
                 }
 
                 .btn-text {
-                    position: absolute;
-                    top: 0;
-                    left: 50%;
-                    transform: translateX(-50%);
-                    width: 320rpx;
+                    font-family: Adobe Heiti Std;
+                    font-size: 42rpx;
+                    color: #FFFFFF;
                     text-align: center;
-                    line-height: 88rpx;
-                    font-size: 32rpx;
-                    color: #fff;
-                    font-weight: 600;
-                    letter-spacing: 2rpx;
                 }
             }
         }

+ 530 - 474
pages-sell/components/sell-container/index.vue

@@ -145,597 +145,653 @@
 			<!-- 底部留白,防止遮挡 -->
 			<view class="bottom-safe-area"></view>
 		</view>
+
+		<!-- 分享红包悬浮按钮 -->
+		<FloatingDrag :width="126" :height="140" :initial-position="redPacketPosition"
+			@position-change="handleRedPacketPositionChange" v-if="shareList.length > 0">
+			<button class="red-packet-btn" @click="navigateToRedPacket">
+				<image src="/packet/static/index/btn_share.png" mode="widthFix" style="width: 126rpx; height: 140rpx">
+				</image>
+			</button>
+		</FloatingDrag>
 	</view>
 </template>
 
 <script>
-	export default {
-		name: 'SellContainer',
-		data() {
-			return {
-				barStyle: {
-					backgroundColor: 'transparent',
-					background: "url('/pages-sell/static/tab-selected.png') no-repeat center",
-					backgroundSize: '100% 100%',
-					position: 'relative',
-					top: '-6rpx',
-				},
-				swiperList: [],
-				statusBarHeight: 20,
-				keyword: '',
-				// u-tabs 需要对象数组 [{name: 'xxx'}]
-				hotTagList: [
-					{ name: '热搜' },
-					{ name: '励志' },
-					{ name: '绘本' },
-					{ name: '诺贝尔文学奖' },
-					{ name: '茅盾奖' },
-					{ name: '童书' }
-				],
-				currentHotTag: 0,
-				// 临时的网络书封面图片
-				bookCoverUrl: 'https://img.yzcdn.cn/vant/cat.jpeg',
-				categoryList: [], //金刚区
-				bookList: [], // 右侧推荐书籍
-				recommendBooks: [
-					{ title: '山河岁月', price: '6.80', original: '36.80', cover: 'https://img.yzcdn.cn/vant/cat.jpeg' },
-					{ title: '山河岁月', price: '6.80', original: '36.80', cover: 'https://img.yzcdn.cn/vant/cat.jpeg' },
-					{ title: '山河岁月', price: '6.80', original: '36.80', cover: 'https://img.yzcdn.cn/vant/cat.jpeg' }
-				],
-				topicList: [], //专题推荐 
-				leftBookList: [], // 左侧推荐书籍
-				rightBookList: [] // 右侧推荐书籍
+import FloatingDrag from "@/components/floating-drag.vue";
+
+export default {
+	name: 'SellContainer',
+	components: {
+		FloatingDrag
+	},
+	data() {
+		return {
+			// 红包悬浮按钮位置
+			redPacketPosition: {
+				left: 'auto',
+				right: 0,
+				bottom: '15%',
+			},
+			barStyle: {
+				backgroundColor: 'transparent',
+				background: "url('/pages-sell/static/tab-selected.png') no-repeat center",
+				backgroundSize: '100% 100%',
+				position: 'relative',
+				top: '-6rpx',
+			},
+			swiperList: [],
+			statusBarHeight: 20,
+			keyword: '',
+			// u-tabs 需要对象数组 [{name: 'xxx'}]
+			hotTagList: [
+				{ name: '热搜' },
+				{ name: '励志' },
+				{ name: '绘本' },
+				{ name: '诺贝尔文学奖' },
+				{ name: '茅盾奖' },
+				{ name: '童书' }
+			],
+			currentHotTag: 0,
+			// 临时的网络书封面图片
+			bookCoverUrl: 'https://img.yzcdn.cn/vant/cat.jpeg',
+			categoryList: [], //金刚区
+			bookList: [], // 右侧推荐书籍
+			recommendBooks: [
+				{ title: '山河岁月', price: '6.80', original: '36.80', cover: 'https://img.yzcdn.cn/vant/cat.jpeg' },
+				{ title: '山河岁月', price: '6.80', original: '36.80', cover: 'https://img.yzcdn.cn/vant/cat.jpeg' },
+				{ title: '山河岁月', price: '6.80', original: '36.80', cover: 'https://img.yzcdn.cn/vant/cat.jpeg' }
+			],
+			topicList: [], //专题推荐 
+			leftBookList: [], // 左侧推荐书籍
+			rightBookList: [], // 右侧推荐书籍
+			shareList: [], // 分享列表
+		}
+	},
+	created() {
+		const systemInfo = uni.getSystemInfoSync();
+		this.statusBarHeight = systemInfo.statusBarHeight || 20;
+		this.hasShareList()
+
+		this.getIndexCateInfo()
+	},
+	methods: {
+		//是否有分享列表数据
+		async hasShareList() {
+			const res = await this.$u.api.getShareRedBagListAjax();
+			if (res.code === 200 || res.code === 0) {
+				this.shareList = res.data || [];
 			}
 		},
-		created() {
-			const systemInfo = uni.getSystemInfoSync();
-			this.statusBarHeight = systemInfo.statusBarHeight || 20;
 
-			this.getIndexCateInfo()
+		handleCategory(item) {
+			if (!item.jumpUrl) return
+			this.navigateTo(item.jumpUrl)
 		},
-		methods: {
-			handleCategory(item) {
-				if (!item.jumpUrl) return
-				this.navigateTo(item.jumpUrl)
-			},
-			changeHotTag(index) {
-				this.currentHotTag = index;
-				console.log('切换标签:', index);
-			},
-			//跳转 URL
-			navigateTo(url) {
-				if (!url) return
-				console.log(url)
-				uni.navigateTo({
-					url: url
-				});
-			},
-			navigateToOfficialAccount() {
-				// 打开公众号
-				uni.getProvider({
-					service: "oauth",
-					success: function (res) {
-						if (res.provider.includes("weixin")) {
-							// 调用微信小程序的 wx.openOfficialAccountProfile
-							wx.openOfficialAccountProfile({
-								username: "bookersea",
-								success: function (res) {
-									console.log("打开公众号资料页成功", res);
-								},
-								fail: function (err) {
-									console.log("打开公众号资料页失败", err);
-								},
-								complete: function () {
-									console.log("接口调用结束");
-								},
-							});
-						}
-					},
-				});
-			},
-
-			goRecommend() {
-				uni.navigateTo({
-					url: '/pages-sell/pages/recommend'
-				});
-			},
-			goHotSell() {
-				uni.navigateTo({
-					url: '/pages-sell/pages/hot-sell'
-				});
-			},
-			//获取首页装修信息
-			getIndexCateInfo() {
-				uni.$u.http.get('/token/shop/showIndex/getIndexCateInfo').then(res => {
-					console.log(res)
-					if (res.code == 200) {
-						console.log(res.data)
-						this.categoryList = res.data.find(item => item.position == 'diamond_area')?.shopIndexCateVo || []
-						this.swiperList = res.data.find(item => item.position == 'left_banner')?.shopIndexCateVo || []
-						this.bookList = res.data.find(item => item.position == 'right_banner')?.shopIndexCateVo || []
-						this.leftBookList = res.data.find(item => item.position == 'left_book_list')?.shopIndexCateVo || []
-						this.rightBookList = res.data.find(item => item.position == 'right_book_list')?.shopIndexCateVo || []
-						//获取专题推荐
-						this.topicList = res.data.find(item => item.position == 'topic')?.shopIndexCateVo || []
+		changeHotTag(index) {
+			this.currentHotTag = index;
+			console.log('切换标签:', index);
+		},
+		//跳转 URL
+		navigateTo(url) {
+			if (!url) return
+			console.log(url)
+			uni.navigateTo({
+				url: url
+			});
+		},
+		navigateToOfficialAccount() {
+			// 打开公众号
+			uni.getProvider({
+				service: "oauth",
+				success: function (res) {
+					if (res.provider.includes("weixin")) {
+						// 调用微信小程序的 wx.openOfficialAccountProfile
+						wx.openOfficialAccountProfile({
+							username: "bookersea",
+							success: function (res) {
+								console.log("打开公众号资料页成功", res);
+							},
+							fail: function (err) {
+								console.log("打开公众号资料页失败", err);
+							},
+							complete: function () {
+								console.log("接口调用结束");
+							},
+						});
 					}
-				})
-			},
-			getDisplayBooks(item) {
-				if (!item.bookInfoList) return []
-				let limit = 3
-				if (item.topicType === 2) {
-					limit = 6
+				},
+			});
+		},
+
+		goRecommend() {
+			uni.navigateTo({
+				url: '/pages-sell/pages/recommend'
+			});
+		},
+		goHotSell() {
+			uni.navigateTo({
+				url: '/pages-sell/pages/hot-sell'
+			});
+		},
+		//获取首页装修信息
+		getIndexCateInfo() {
+			uni.$u.http.get('/token/shop/showIndex/getIndexCateInfo').then(res => {
+				console.log(res)
+				if (res.code == 200) {
+					console.log(res.data)
+					this.categoryList = res.data.find(item => item.position == 'diamond_area')?.shopIndexCateVo || []
+					this.swiperList = res.data.find(item => item.position == 'left_banner')?.shopIndexCateVo || []
+					this.bookList = res.data.find(item => item.position == 'right_banner')?.shopIndexCateVo || []
+					this.leftBookList = res.data.find(item => item.position == 'left_book_list')?.shopIndexCateVo || []
+					this.rightBookList = res.data.find(item => item.position == 'right_book_list')?.shopIndexCateVo || []
+					//获取专题推荐
+					this.topicList = res.data.find(item => item.position == 'topic')?.shopIndexCateVo || []
 				}
-				return item.bookInfoList.slice(0, limit)
+			})
+		},
+		getDisplayBooks(item) {
+			if (!item.bookInfoList) return []
+			let limit = 3
+			if (item.topicType === 2) {
+				limit = 6
 			}
+			return item.bookInfoList.slice(0, limit)
+		},
+		// 跳转到红包分享页面
+		navigateToRedPacket() {
+			uni.navigateTo({
+				url: '/packet/pages/share'
+			});
+		},
+		// 红包按钮位置变化
+		handleRedPacketPositionChange(position) {
+			this.redPacketPosition = position;
 		}
 	}
+}
 </script>
 
 <style lang="scss" scoped>
-	.sell-container {
+.sell-container {
+	position: relative;
+	min-height: 100vh;
+	background-color: #F6F6F6;
+	overflow-x: hidden;
+}
+
+/* 顶部大背景图 */
+.top-bg-image {
+	position: absolute;
+	top: 0;
+	left: 0;
+	width: 100%;
+	z-index: 0;
+	display: block;
+}
+
+/* 导航栏 */
+.custom-navbar {
+	position: fixed;
+	top: 0;
+	left: 0;
+	width: 100%;
+	z-index: 100;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+
+	.navbar-content {
+		height: 44px;
+		width: 100%;
+		display: flex;
+		align-items: center;
+		justify-content: center;
 		position: relative;
-		min-height: 100vh;
-		background-color: #F6F6F6;
-		overflow-x: hidden;
-	}
 
-	/* 顶部大背景图 */
-	.top-bg-image {
-		position: absolute;
-		top: 0;
-		left: 0;
-		width: 100%;
-		z-index: 0;
-		display: block;
+		.navbar-title {
+			color: #fff;
+			font-size: 36rpx;
+			font-weight: 600;
+		}
 	}
+}
 
-	/* 导航栏 */
-	.custom-navbar {
-		position: fixed;
-		top: 0;
-		left: 0;
-		width: 100%;
-		z-index: 100;
+.main-content {
+	position: relative;
+	z-index: 1;
+	padding: 0 24rpx;
+}
+
+/* 搜索框 */
+.search-wrapper {
+	margin-top: 10rpx;
+	margin-bottom: 20rpx;
+
+	.search-box-uview {
+		height: 80rpx;
+		background-color: #fff;
+		border-radius: 40rpx;
 		display: flex;
 		align-items: center;
-		justify-content: center;
+		padding: 0 10rpx 0 16rpx;
+		position: relative;
 
-		.navbar-content {
-			height: 44px;
-			width: 100%;
+		/* 覆盖 u-search 的 padding 以适配 */
+		::v-deep .u-search {
+			flex: 1;
+			/* 让输入框不遮挡右侧按钮 */
+			padding-right: 140rpx !important;
+		}
+
+		.search-btn-overlay {
+			position: absolute;
+			right: 8rpx;
+			top: 50%;
+			transform: translateY(-50%);
+			width: 140rpx;
+			height: 64rpx;
+			background: linear-gradient(0deg, #37C148 0%, #6ADD83 100%);
+			border-radius: 32rpx;
 			display: flex;
 			align-items: center;
 			justify-content: center;
-			position: relative;
+			z-index: 2;
 
-			.navbar-title {
+			text {
 				color: #fff;
-				font-size: 36rpx;
-				font-weight: 600;
+				font-size: 28rpx;
+				font-weight: 500;
 			}
 		}
 	}
+}
 
-	.main-content {
-		position: relative;
-		z-index: 1;
-		padding: 0 24rpx;
+/* 顶部横幅 */
+.top-banner-wrapper {
+	width: 100%;
+	margin-bottom: 30rpx;
+	position: relative;
+
+	.top-banner-img {
+		width: 100%;
+		border-radius: 40rpx;
+		display: block;
 	}
+}
 
-	/* 搜索框 */
-	.search-wrapper {
-		margin-top: 10rpx;
-		margin-bottom: 20rpx;
+/* 分类图标 */
+.category-grid {
+	display: flex;
+	flex-wrap: wrap;
+	margin-bottom: 10rpx;
 
-		.search-box-uview {
-			height: 80rpx;
-			background-color: #fff;
-			border-radius: 40rpx;
+	.grid-item {
+		width: 20%;
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		margin-bottom: 30rpx;
+
+		.icon-circle {
+			width: 96rpx;
+			height: 96rpx;
 			display: flex;
 			align-items: center;
-			padding: 0 10rpx 0 16rpx;
-			position: relative;
+			justify-content: center;
+			margin-bottom: 12rpx;
 
-			/* 覆盖 u-search 的 padding 以适配 */
-			::v-deep .u-search {
-				flex: 1;
-				/* 让输入框不遮挡右侧按钮 */
-				padding-right: 140rpx !important;
+			.cat-icon {
+				width: 100%;
+				height: 100%;
 			}
+		}
 
-			.search-btn-overlay {
-				position: absolute;
-				right: 8rpx;
-				top: 50%;
-				transform: translateY(-50%);
-				width: 140rpx;
-				height: 64rpx;
-				background: linear-gradient(0deg, #37C148 0%, #6ADD83 100%);
-				border-radius: 32rpx;
-				display: flex;
-				align-items: center;
-				justify-content: center;
-				z-index: 2;
-
-				text {
-					color: #fff;
-					font-size: 28rpx;
-					font-weight: 500;
-				}
-			}
+		.cat-name {
+			font-size: 24rpx;
+			color: #333;
+			font-weight: 500;
 		}
 	}
+}
 
-	/* 顶部横幅 */
-	.top-banner-wrapper {
-		width: 100%;
-		margin-bottom: 30rpx;
-		position: relative;
+/* 推广双卡片 */
+.promo-dual-card {
+	display: flex;
+	justify-content: space-between;
+	margin-bottom: 24rpx;
 
-		.top-banner-img {
-			width: 100%;
-			border-radius: 40rpx;
-			display: block;
-		}
+	.card-left {
+		width: 48%;
+		height: 252rpx;
+		border-radius: 20rpx;
+		position: relative;
+		overflow: hidden;
 	}
 
-	/* 分类图标 */
-	.category-grid {
-		display: flex;
-		flex-wrap: wrap;
-		margin-bottom: 10rpx;
+	.card-right {
+		width: 48%;
+		height: 252rpx;
+		/* Updated background per request */
+		background: linear-gradient(to bottom, #FFD7C3 0%, #FFFFFF 32%);
+		border-radius: 20rpx;
+		padding: 20rpx;
+		box-sizing: border-box;
 
-		.grid-item {
-			width: 20%;
+		.right-header {
 			display: flex;
-			flex-direction: column;
 			align-items: center;
-			margin-bottom: 30rpx;
-
-			.icon-circle {
-				width: 96rpx;
-				height: 96rpx;
-				display: flex;
-				align-items: center;
-				justify-content: center;
-				margin-bottom: 12rpx;
-
-				.cat-icon {
-					width: 100%;
-					height: 100%;
-				}
-			}
+			justify-content: center;
+			margin-bottom: 20rpx;
 
-			.cat-name {
-				font-size: 24rpx;
+			.right-title {
+				font-size: 30rpx;
+				font-weight: bold;
 				color: #333;
-				font-weight: 500;
+				margin: 0 10rpx;
 			}
-		}
-	}
 
-	/* 推广双卡片 */
-	.promo-dual-card {
-		display: flex;
-		justify-content: space-between;
-		margin-bottom: 24rpx;
-
-		.card-left {
-			width: 48%;
-			height: 252rpx;
-			border-radius: 20rpx;
-			position: relative;
-			overflow: hidden;
-		}
-
-		.card-right {
-			width: 48%;
-			height: 252rpx;
-			/* Updated background per request */
-			background: linear-gradient(to bottom, #FFD7C3 0%, #FFFFFF 32%);
-			border-radius: 20rpx;
-			padding: 20rpx;
-			box-sizing: border-box;
-
-			.right-header {
-				display: flex;
-				align-items: center;
-				justify-content: center;
-				margin-bottom: 20rpx;
-
-				.right-title {
-					font-size: 30rpx;
-					font-weight: bold;
-					color: #333;
-					margin: 0 10rpx;
-				}
-
-				.fire-icon {
-					width: 30rpx;
-					height: 30rpx;
-				}
+			.fire-icon {
+				width: 30rpx;
+				height: 30rpx;
+			}
 
-				.flip {
-					transform: scaleX(-1);
-				}
+			.flip {
+				transform: scaleX(-1);
 			}
+		}
 
-			.products-container {
-				display: flex;
-				justify-content: space-between;
-				gap: 20rpx;
+		.products-container {
+			display: flex;
+			justify-content: space-between;
+			gap: 20rpx;
 
-				.product-cover {
-					flex: 1;
-					height: 160rpx;
-					border-radius: 12rpx;
-					background-color: #f0f0f0;
-				}
+			.product-cover {
+				flex: 1;
+				height: 160rpx;
+				border-radius: 12rpx;
+				background-color: #f0f0f0;
 			}
 		}
 	}
+}
+
+/* 信息双卡片 */
+.info-dual-card {
+	display: flex;
+	justify-content: space-between;
+	margin-bottom: 24rpx;
+
+	.info-card-swiper {
+		width: 48%;
+		height: 140rpx;
+		border-radius: 12px;
+		overflow: hidden;
+	}
 
-	/* 信息双卡片 */
-	.info-dual-card {
+	.info-card {
+		width: 100%;
+		padding: 24rpx;
+		border-radius: 12px;
+		/* Updated radius */
 		display: flex;
 		justify-content: space-between;
-		margin-bottom: 24rpx;
+		align-items: center;
+		height: 140rpx;
+		box-sizing: border-box;
+		position: relative;
+		/* For absolute icon */
+		overflow: hidden;
 
-		.info-card-swiper {
-			width: 48%;
-			height: 140rpx;
-			border-radius: 12px;
-			overflow: hidden;
+		&.bg-orange {
+			background: #FFF3E0;
+			border: 1px solid #FFB72A;
 		}
 
-		.info-card {
-			width: 100%;
-			padding: 24rpx;
-			border-radius: 12px;
-			/* Updated radius */
-			display: flex;
-			justify-content: space-between;
-			align-items: center;
-			height: 140rpx;
-			box-sizing: border-box;
-			position: relative;
-			/* For absolute icon */
-			overflow: hidden;
+		&.bg-green {
+			background: #D4F1D8;
+			border: 1px solid #54A94E;
+		}
 
-			&.bg-orange {
-				background: #FFF3E0;
-				border: 1px solid #FFB72A;
-			}
+		.info-text-group {
+			flex: 1;
+			z-index: 1;
+			/* Ensure text is above */
 
-			&.bg-green {
-				background: #D4F1D8;
-				border: 1px solid #54A94E;
+			.info-title {
+				font-size: 28rpx;
+				font-weight: bold;
+				display: block;
+				margin-bottom: 6rpx;
 			}
 
-			.info-text-group {
-				flex: 1;
-				z-index: 1;
-				/* Ensure text is above */
-
-				.info-title {
-					font-size: 28rpx;
-					font-weight: bold;
-					display: block;
-					margin-bottom: 6rpx;
-				}
-
-				.info-desc {
-					font-size: 22rpx;
-					line-height: 1.2;
-				}
-
-				.text-orange {
-					color: #DB832D;
-				}
+			.info-desc {
+				font-size: 22rpx;
+				line-height: 1.2;
+			}
 
-				.text-orange-light {
-					color: #DB832D;
-				}
+			.text-orange {
+				color: #DB832D;
+			}
 
-				.text-green {
-					color: #1F8049;
-				}
+			.text-orange-light {
+				color: #DB832D;
+			}
 
-				.text-green-light {
-					color: #1F8049;
-				}
+			.text-green {
+				color: #1F8049;
 			}
 
-			.info-icon {
-				width: 100rpx;
-				/* Slightly larger maybe */
-				height: 100rpx;
-				position: absolute;
-				right: 0;
-				bottom: 0;
-				z-index: 0;
-				opacity: 0.8;
+			.text-green-light {
+				color: #1F8049;
 			}
 		}
+
+		.info-icon {
+			width: 100rpx;
+			/* Slightly larger maybe */
+			height: 100rpx;
+			position: absolute;
+			right: 0;
+			bottom: 0;
+			z-index: 0;
+			opacity: 0.8;
+		}
 	}
+}
 
-	/* 公众号 */
-	.gzh-section {
-		margin-bottom: 30rpx;
-		height: 180rpx;
-		/* Fixed height for consistency */
-		border-radius: 20rpx;
-		overflow: hidden;
+/* 公众号 */
+.gzh-section {
+	margin-bottom: 30rpx;
+	height: 180rpx;
+	/* Fixed height for consistency */
+	border-radius: 20rpx;
+	overflow: hidden;
 
-		.gzh-bg-wrapper {
+	.gzh-bg-wrapper {
+		width: 100%;
+		height: 100%;
+		position: relative;
+
+		.gzh-img-bg {
 			width: 100%;
 			height: 100%;
-			position: relative;
+			position: absolute;
+			top: 0;
+			left: 0;
+		}
 
-			.gzh-img-bg {
-				width: 100%;
-				height: 100%;
-				position: absolute;
-				top: 0;
-				left: 0;
+		.gzh-content-overlay {
+			position: absolute;
+			top: 0;
+			left: 0;
+			width: 60%;
+			/* Only cover left side */
+			height: 100%;
+			padding: 30rpx;
+			display: flex;
+			flex-direction: column;
+			justify-content: center;
+
+			.gzh-title {
+				font-size: 32rpx;
+				font-weight: bold;
+				color: #134E13;
+				/* Dark green */
+				margin-bottom: 16rpx;
 			}
 
-			.gzh-content-overlay {
-				position: absolute;
-				top: 0;
-				left: 0;
-				width: 60%;
-				/* Only cover left side */
-				height: 100%;
-				padding: 30rpx;
-				display: flex;
-				flex-direction: column;
-				justify-content: center;
-
-				.gzh-title {
-					font-size: 32rpx;
-					font-weight: bold;
-					color: #134E13;
-					/* Dark green */
-					margin-bottom: 16rpx;
-				}
+			.gzh-subtitle-pill {
+				background: #FFF;
+				border-radius: 24rpx;
+				padding: 0 14rpx;
+				line-height: 1.4;
+				align-self: flex-start;
 
-				.gzh-subtitle-pill {
-					background: #FFF;
-					border-radius: 24rpx;
-					padding: 0 14rpx;
-					line-height: 1.4;
-					align-self: flex-start;
-
-					.gzh-subtitle {
-						font-size: 22rpx;
-						color: #134E13;
-						font-weight: 500;
-					}
+				.gzh-subtitle {
+					font-size: 22rpx;
+					color: #134E13;
+					font-weight: 500;
 				}
 			}
 		}
 	}
+}
 
-	/* 书嗨推荐 */
-	.recommend-section {
-		background-color: #fff;
-		border-radius: 20rpx;
-		padding: 30rpx;
+/* 书嗨推荐 */
+.recommend-section {
+	background-color: #fff;
+	border-radius: 20rpx;
+	padding: 30rpx;
+	margin-bottom: 24rpx;
+
+	.section-header {
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
 		margin-bottom: 24rpx;
 
-		.section-header {
+		.section-title {
+			font-size: 32rpx;
+			font-weight: bold;
+			color: #333;
+		}
+
+		.view-more {
 			display: flex;
-			justify-content: space-between;
 			align-items: center;
-			margin-bottom: 24rpx;
+			font-size: 24rpx;
+			color: #8D8D8D;
 
-			.section-title {
-				font-size: 32rpx;
-				font-weight: bold;
-				color: #333;
+			.arrow-icon {
+				width: 12rpx;
+				margin-left: 6rpx;
 			}
+		}
+	}
+
+	.book-list {
+		display: flex;
+		flex-wrap: wrap;
+		justify-content: space-between;
+	}
 
-			.view-more {
-				display: flex;
-				align-items: center;
-				font-size: 24rpx;
-				color: #8D8D8D;
+	.book-item {
+		width: 200rpx;
+		margin-bottom: 24rpx;
+		display: flex;
+		flex-direction: column;
 
-				.arrow-icon {
-					width: 12rpx;
-					margin-left: 6rpx;
-				}
-			}
+		.book-image {
+			width: 200rpx;
+			height: 255rpx;
+			border-radius: 2rpx;
+			margin-bottom: 16rpx;
+			background-color: #f9f9f9;
 		}
 
-		.book-list {
-			display: flex;
-			flex-wrap: wrap;
-			justify-content: space-between;
+		.book-name {
+			font-family: 'Source Han Sans SC';
+			font-weight: bold;
+			font-size: 28rpx;
+			color: #303030;
+			margin-bottom: 10rpx;
+			overflow: hidden;
+			text-overflow: ellipsis;
+			white-space: nowrap;
 		}
 
-		.book-item {
-			width: 200rpx;
-			margin-bottom: 24rpx;
+		.price-row {
 			display: flex;
-			flex-direction: column;
+			align-items: baseline;
+			margin-bottom: 12rpx;
 
-			.book-image {
-				width: 200rpx;
-				height: 255rpx;
-				border-radius: 2rpx;
-				margin-bottom: 16rpx;
-				background-color: #f9f9f9;
+			.currency {
+				font-family: 'Source Han Sans SC';
+				font-weight: 500;
+				font-size: 22rpx;
+				color: #D81A00;
 			}
 
-			.book-name {
+			.price-val {
 				font-family: 'Source Han Sans SC';
-				font-weight: bold;
+				font-weight: 500;
 				font-size: 28rpx;
-				color: #303030;
-				margin-bottom: 10rpx;
-				overflow: hidden;
-				text-overflow: ellipsis;
-				white-space: nowrap;
+				color: #D81A00;
+				margin-right: 12rpx;
 			}
 
-			.price-row {
-				display: flex;
-				align-items: baseline;
-				margin-bottom: 12rpx;
-
-				.currency {
-					font-family: 'Source Han Sans SC';
-					font-weight: 500;
-					font-size: 22rpx;
-					color: #D81A00;
-				}
+			.price-old {
+				font-family: 'Source Han Sans SC';
+				font-weight: 500;
+				font-size: 22rpx;
+				color: #999999;
+				text-decoration: line-through;
+			}
+		}
 
-				.price-val {
-					font-family: 'Source Han Sans SC';
-					font-weight: 500;
-					font-size: 28rpx;
-					color: #D81A00;
-					margin-right: 12rpx;
-				}
+		.add-btn {
+			width: fit-content;
+			height: 36rpx;
+			line-height: 36rpx;
+			background: linear-gradient(0deg, #4ED964 0%, #4ED964 100%);
+			border-radius: 18rpx;
+			padding: 0 20rpx;
+			display: flex;
+			align-items: center;
+			justify-content: center;
 
-				.price-old {
-					font-family: 'Source Han Sans SC';
-					font-weight: 500;
-					font-size: 22rpx;
-					color: #999999;
-					text-decoration: line-through;
-				}
+			text {
+				font-size: 22rpx;
+				color: #fff;
 			}
 
-			.add-btn {
-				width: fit-content;
-				height: 36rpx;
-				line-height: 36rpx;
-				background: linear-gradient(0deg, #4ED964 0%, #4ED964 100%);
-				border-radius: 18rpx;
-				padding: 0 20rpx;
-				display: flex;
-				align-items: center;
-				justify-content: center;
-
-				text {
-					font-size: 22rpx;
-					color: #fff;
-				}
-
-				.cart-symbol {
-					width: 24rpx;
-					height: 24rpx;
-					margin-left: 6rpx;
-				}
+			.cart-symbol {
+				width: 24rpx;
+				height: 24rpx;
+				margin-left: 6rpx;
 			}
 		}
 	}
-
-	.bottom-safe-area {
-		height: 30rpx
+}
+
+.bottom-safe-area {
+	height: 30rpx
+}
+
+.red-packet-btn {
+	width: 126rpx;
+	height: 140rpx;
+	background: transparent;
+	border: none;
+	padding: 0;
+	margin: 0;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+
+	&::after {
+		border: none;
 	}
+}
 </style>