Преглед изворни кода

feat: 添加客服悬浮按钮并优化分享功能

- 在sell-container组件中添加客服悬浮按钮
- 统一各页面的分享逻辑,支持降价和热销分享
- 优化商品选择弹窗的品相选择逻辑
- 更新物流信息展示样式
- 替换uview的swipe-action为uni-ui版本
- 修复浮动拖拽组件的触摸事件冲突
- 更新.env.dev.js中的API地址
ylong пре 1 недеља
родитељ
комит
3d6cba1365

+ 1 - 1
.env.dev.js

@@ -1,5 +1,5 @@
 export default {
     "NODE_ENV": 'development',
-    "apiUrl":"https://bpi.shuhi.com",
+    "apiUrl":"https://bk.shuhi.com",
     "apiUrlPrefix":"/api",
 };

+ 7 - 1
components/floating-drag.vue

@@ -10,7 +10,7 @@
             display: visible ? 'block' : 'none',
         }"
         @touchstart="touchStart"
-        @touchmove="touchMove"
+        @touchmove.stop.prevent="touchMove"
         @touchend="touchEnd"
         @click="handleClick"
         v-if="visible"
@@ -71,6 +71,8 @@ export default {
             initialBottom: 0,
             // 是否正在更新位置,用于防止频繁更新
             isUpdatingPosition: false,
+            // 是否正在拖动
+            isDragging: false,
         };
     },
     created() {
@@ -130,6 +132,8 @@ export default {
 
         // 触摸开始
         touchStart(e) {
+            this.isDragging = true;
+            this.$emit('drag-start');
             const touch = e.touches[0];
             this.startX = touch.clientX;
             this.startY = touch.clientY;
@@ -205,6 +209,8 @@ export default {
 
         // 触摸结束,实现吸附效果
         touchEnd() {
+            this.isDragging = false;
+            this.$emit('drag-end');
             // 确保不再有待处理的更新
             this.isUpdatingPosition = false;
 

+ 3 - 3
components/price-reduction-popup/price-reduction-popup.vue

@@ -39,8 +39,8 @@
 							<view class="add-text">{{ formatName(item.nickName) }}</view>
 						</view>
 
-						<button v-else open-type="share" class="hand-btn">
-							<image open-type="share" class="invite-icon" src="/static/img/activity/invite.png"
+						<button v-else open-type="share" data-share-type="reduce" class="hand-btn">
+							<image class="invite-icon" src="/static/img/activity/invite.png"
 								mode="widthFix"></image>
 						</button>
 					</block>
@@ -49,7 +49,7 @@
 
 			<!-- 分享按钮 -->
 			<view class="action-buttons">
-				<button class="share-button" @click="shareAction" open-type="share">
+				<button class="share-button" data-share-type="reduce" @click="shareAction" open-type="share">
 					立即分享
 				</button>
 				<button class="scan-button" @click="scanAction">扫码砍价</button>

+ 5 - 4
package.json

@@ -11,9 +11,7 @@
 		"商城"
 	],
 	"dcloudext": {
-		"category": [
-
-		]
+		"category": []
 	},
 	"uni-app": {
 		"scripts": {
@@ -32,5 +30,8 @@
 				}
 			}
 		}
+	},
+	"dependencies": {
+		"@dcloudio/uni-ui": "^1.5.12"
 	}
-}
+}

+ 1 - 12
pages-car/components/buy-order-item.vue

@@ -3,9 +3,7 @@
         <!-- 订单头部:订单号和状态 -->
         <view class="order-header">
             <text class="order-no">订单号:{{ order.orderId }}</text>
-
-            <text class="order-status color-red" v-if="order.refundStatus==3">已退款</text>
-            <text class="order-status" v-else>{{ getStatusText(order) }}</text>
+            <text class="order-status">{{ getStatusText(order) }}</text>
         </view>
 
         <!-- 商品信息 -->
@@ -76,12 +74,6 @@
             <u-button v-if="order.showUrge == 1" size="mini" shape="circle" type="warning" plain
                 :custom-style="btnStyle" @click.stop="handleAction('remind', order)">催发货</u-button>
 
-            <!-- 超时发货 -->
-            <u-button v-if="order.showSendTimeout == 1" size="mini" shape="circle" type="warning" plain
-                :custom-style="btnStyle" @click.stop="handleAction('overtime', order)">超时发货</u-button>
-            <u-button v-if="order.showSendTimeout == 2" size="mini" shape="circle" type="warning" plain
-                :custom-style="btnStyle">超时发货已赔付</u-button>
-
 
             <!-- 申请售后 -->
             <u-button v-if="order.showAfterSales == 1 && order.status != '4' && order.status != '3'" size="mini" shape="circle" type="error"
@@ -221,9 +213,6 @@
         border-radius: 16rpx;
         padding: 30rpx 20rpx;
         margin-bottom: 20rpx;
-        .color-red {
-            color: #FF000C;
-        }
 
         .order-header {
             display: flex;

+ 1 - 10
pages-car/components/order-bottom-bar.vue

@@ -17,10 +17,8 @@
 			@click="emitAction('complaint')">投诉</u-button>
 
 		<!-- 超时发货 -->
-		<u-button v-if="orderInfo.showSendTimeout === 1" size="mini" shape="circle" type="warning" :custom-style="btnStyle"
+		<u-button v-if="orderInfo.showSendTimeout" size="mini" shape="circle" type="warning" :custom-style="btnStyle"
 			@click="emitAction('overtime')">超时发货</u-button>
-		<u-button v-if="orderInfo.showSendTimeout === 2" size="mini" shape="circle" type="warning" plain :custom-style="autoBtnStyle"
-			>超时发货已赔付</u-button>
 
 		<!-- 降价补差 -->
 		<u-button v-if="orderInfo.showCompensation" size="mini" shape="circle" type="primary"
@@ -62,13 +60,6 @@
 					padding: '0',
 					fontSize: '26rpx'
 				},
-				autoBtnStyle: {
-					marginLeft: '20rpx',
-					height: '60rpx',
-					lineHeight: '60rpx',
-					padding: '0 20rpx',
-					fontSize: '26rpx'
-				},
 				themeBtnStyle: {
 					marginLeft: '20rpx',
 					width: '160rpx',

+ 1 - 1
pages-car/pages/confirm-order.vue

@@ -57,7 +57,7 @@
                 <u-cell-item title="优惠详情" :arrow="false" :border-bottom="true"
                     :title-style="{ color: '#333', fontWeight: 'bold' }"></u-cell-item>
                 <template v-if="preOrder.discountList && preOrder.discountList.length > 0">
-                    <u-cell-item v-for="(item, index) in preOrder.discountList" :key="'discount-'+index"
+                    <u-cell-item v-for="(item, index) in preOrder.discountList" :key="index"
                         :title="item.discountActivityMsg" :value="'-¥' + item.discountMoney"
                         :arrow="false" :border-bottom="true"
                         :title-style="{ color: '#666' }" :value-style="{ color: '#ff4500', fontWeight: 'bold' }"></u-cell-item>

+ 49 - 18
pages-car/pages/index.vue

@@ -2,11 +2,17 @@
     <view class="cart-page">
         <!-- 购物车列表 -->
         <view class="cart-list">
-            <u-swipe-action :show="item.show" :index="index" v-for="(item, index) in cartList" :key="item.id"
+            <!-- <u-swipe-action :show="item.show" :index="index" v-for="(item, index) in cartList" :key="item.id"
                 @click="clickAction" @open="openAction" @touchstart="swipeStart" :options="actionOptions">
                 <cart-item :item="item" @check="handleCheck" @changeNum="handleChangeNum" @reduce="handleReduce"
                     @selectCondition="onSelectCondition"></cart-item>
-            </u-swipe-action>
+            </u-swipe-action> -->
+            <uni-swipe-action>
+                <uni-swipe-action-item v-for="(item, index) in cartList" :key="item.id" :right-options="uniActionOptions" @click="uniClickAction($event, index)" @change="uniSwipeChange($event, index)" :show="item.show">
+                    <cart-item :item="item" @check="handleCheck" @changeNum="handleChangeNum" @reduce="handleReduce"
+                        @selectCondition="onSelectCondition"></cart-item>
+                </uni-swipe-action-item>
+            </uni-swipe-action>
         </view>
 
         <!-- 品相切换弹窗 -->
@@ -106,6 +112,14 @@
                         }
                     }
                 ],
+                uniActionOptions: [
+                    {
+                        text: '删除',
+                        style: {
+                            backgroundColor: '#fa3534'
+                        }
+                    }
+                ],
                 recommendList: [],
                 shippingText: ''
             };
@@ -122,15 +136,7 @@
         // 分享配置
         onShareAppMessage(res) {
             console.log(res, '分享');
-            if (res && res.from === 'button' && res.target && res.target.dataset && res.target.dataset.shareType === 'product') {
-                const dataset = res.target.dataset;
-                return {
-                    title: dataset.title || '',
-                    path: `/pages-sell/pages/detail?isbn=${dataset.isbn}`,
-                    imageUrl: dataset.image || ''
-                };
-            }
-            if (res.from === "button") {
+            if (res.from === "button" && res.target && res.target.dataset && res.target.dataset.shareType === "reduce") {
                 let reduceCode = uni.getStorageSync("reduceCodeShare");
                 // 调用分享接口
                 this.$u.api.goToReduceShareAjax({ reduceCode: reduceCode });
@@ -208,11 +214,36 @@
                 console.log('获取运费模版');
             },
             swipeStart(index) {
-                this.cartList.forEach((item, idx) => {
-                    if (index !== idx) {
-                        item.show = false;
-                    }
-                });
+                // this.cartList.forEach((item, idx) => {
+                //     if (index !== idx) {
+                //         item.show = 'none';
+                //     }
+                // });
+            },
+            uniClickAction(e, index) {
+                if (e.content.text === '删除') {
+                    const item = this.cartList[index];
+                    this.handleDelete(item);
+                }
+            },
+            uniSwipeChange(e, index) {
+                // uni-swipe-action-item 改变状态时
+                if (e === 'right' || e === 'left') {
+                    // 当滑动某一项时,手动将其他项的 show 设置为 'none'
+                    this.cartList.forEach((val, idx) => {
+                        if (index !== idx) {
+                            val.show = 'none';
+                        } else {
+                            val.show = e;
+                        }
+                    });
+                } else {
+                    this.cartList.forEach((val, idx) => {
+                        if (index === idx) {
+                            val.show = 'none';
+                        }
+                    });
+                }
             },
             clickAction(index, index1) {
                 if (this.actionOptions[index1].text == '删除') {
@@ -245,7 +276,7 @@
                         return {
                             ...item,
                             checked: checkedIds.includes(item.id),
-                            show: false
+                            show: 'none'
                         };
                     });
 
@@ -406,7 +437,7 @@
                                 }
                             });
                         } else {
-                            item.show = false;
+                            item.show = 'none';
                         }
                     }
                 });

+ 60 - 17
pages-car/pages/order-detail.vue

@@ -27,14 +27,9 @@
         <!-- 地址信息 -->
         <view class="info-card address-card" @click="handleAddressClick">
             <view class="icon-box">
-                <image src="../static/adderss.png" style="width: 40rpx; height: 40rpx"></image>
+                <image src="/pages-mine/static/adderss.png" style="width: 40rpx; height: 40rpx"></image>
             </view>
             <view class="address-content">
-                <view class="express-row"
-                    v-if="['3', '4', '8', '12', '10'].includes(String(orderInfo.status)) && orderInfo.waybillCode"
-                    @click.stop="viewLogistics">
-                    <view class="express-name">{{ orderInfo.expressName || '快递' }}({{ orderInfo.waybillCode }})</view>
-                </view>
                 <view class="user-info">
                     <text class="name">{{ orderInfo.receiverName }}</text>
                     <text class="mobile">{{ orderInfo.receiverMobile }}</text>
@@ -44,6 +39,20 @@
             <u-icon v-if="orderInfo.showModifyAddress == 1" name="arrow-right" color="#999" size="28"></u-icon>
         </view>
 
+        <!-- 物流信息 -->
+        <view class="info-card express-card" 
+            v-if="['3', '4', '8', '12', '10'].includes(String(orderInfo.status)) && orderInfo.waybillCode" 
+            @click.stop="viewLogistics">
+            <view class="icon-box">
+                <u-icon name="car" color="#38C148" size="48"></u-icon>
+            </view>
+            <view class="express-content">
+                <view class="express-name">{{ orderInfo.expressName || '快递' }}({{ orderInfo.waybillCode }})</view>
+                <view class="express-trace">{{ latestTrace ? (latestTrace.context || latestTrace.status) : '点击查看物流详情' }}</view>
+            </view>
+            <u-icon name="arrow-right" color="#999" size="28"></u-icon>
+        </view>
+
         <!-- 商品列表 -->
         <view class="info-card goods-card">
             <view class="goods-item" v-for="(goods, index) in orderInfo.detailVoList" :key="index">
@@ -158,6 +167,7 @@ export default {
                 payMoney: 0,
                 createTime: ''
             },
+            latestTrace: null,
             isModifyingAddress: false,
         };
     },
@@ -224,6 +234,20 @@ export default {
             }).then((res) => {
                 if (res.code == 200) {
                     this.orderInfo = res.data;
+                    if (['3', '4', '8', '12', '10'].includes(String(this.orderInfo.status)) && this.orderInfo.waybillCode) {
+                        this.getLogisticsData();
+                    }
+                }
+            });
+        },
+        getLogisticsData() {
+            this.$u.api.getOrderTrackingAjax({ orderId: this.orderInfo.orderId }).then(res => {
+                if (res.code == 200 && res.data && res.data.length > 0) {
+                    // 取第一个包裹的最新一条轨迹
+                    const package1 = res.data[0];
+                    if (package1.trackingVoList && package1.trackingVoList.length > 0) {
+                        this.latestTrace = package1.trackingVoList[0];
+                    }
                 }
             });
         },
@@ -451,17 +475,6 @@ export default {
                 flex: 1;
                 margin-right: 20rpx;
 
-                .express-row {
-                    display: flex;
-                    align-items: center;
-                    padding-bottom: 15rpx;
-                    .express-name {
-                        font-size: 28rpx;
-                        color: #38C148;
-                        font-weight: 500;
-                    }
-                }
-
                 .user-info {
                     font-size: 30rpx;
                     font-weight: 500;
@@ -480,6 +493,36 @@ export default {
             }
         }
 
+        &.express-card {
+            align-items: center;
+            
+            .icon-box {
+                margin-right: 20rpx;
+            }
+            
+            .express-content {
+                flex: 1;
+                margin-right: 20rpx;
+                
+                .express-name {
+                    color: #38C148;
+                    font-size: 28rpx;
+                    margin-bottom: 10rpx;
+                    font-weight: 500;
+                }
+                
+                .express-trace {
+                    color: #333;
+                    font-size: 26rpx;
+                    line-height: 1.4;
+                    display: -webkit-box;
+                    -webkit-box-orient: vertical;
+                    -webkit-line-clamp: 2;
+                    overflow: hidden;
+                }
+            }
+        }
+
         &.goods-card {
             display: block;
 

+ 1 - 1
pages-mine/pages/partner/order-detail.vue

@@ -17,7 +17,7 @@
         <page-scroll :page-size="12" @updateList="handleUpdateList" ref="pageRef" slotEmpty
             :url="currentUrl" :params="params" :immediate="false">
             <view v-if="orderList.length > 0" class="pad-20">
-                <partner-order-item v-for="order in orderList" :key="order.orderNo || order.orderId" :order="order" :type="currentType"></partner-order-item>
+                <partner-order-item v-for="(order, index) in orderList" :key="index" :order="order" :type="currentType"></partner-order-item>
             </view>
         </page-scroll>
     </view>

+ 1 - 0
pages-sell/components/reduce-rule-popup/index.vue

@@ -6,6 +6,7 @@
             <view class="rule-item">3.助力有效期:用户发起助力后,需在{{ ruleData.inviteExpireHour || 24 }}小时内完成好友助力,超时未完成则本次助力失效,可重新发起邀请,有效期以助力成功时间为准。</view>
             <view class="rule-item">4.助力上限说明:单用户单订单单本图书仅可降价 {{ ruleData.reduceTimesPerIsbn || 1 }} 次,达到次数上限后无法继续通过助力获得优惠;每个用户 ID 每日最多可参与助力 {{ ruleData.assistTimesEveryDay || 1 }} 次,同一好友仅可为同一用户的同一订单助力 1 次,重复助力无效。</view>
             <view class="rule-item">5.若用户存在恶意刷助力、虚假账号、作弊等违规行为,平台有权直接取消其活动资格、收回已获得的降价优惠,并限制其后续参与平台活动的权限。</view>
+            <view class="rule-item">6.助力成功之后需在24小时内提交订单,否则降价失效。</view>
         </view>
     </common-dialog>
 </template>

+ 95 - 73
pages-sell/components/select-good-popup/index.vue

@@ -1,83 +1,86 @@
 <template>
 	<view @click.stop>
-		<u-popup v-model="visible" mode="bottom" border-radius="24" :safe-area-inset-bottom="true" :mask-close-able="true"
-			@close="close">
+		<u-popup v-model="visible" mode="bottom" border-radius="24" :safe-area-inset-bottom="true"
+			:mask-close-able="true" @close="close">
 			<view class="popup-content" @click.stop>
-			<!-- Header -->
-			<view class="header">
-				<text class="title">选择商品品相</text>
-				<image src="/pages-sell/static/select-good/icon-close.png" class="close-icon" @click="close"></image>
-			</view>
+				<!-- Header -->
+				<view class="header">
+					<text class="title">选择商品品相</text>
+					<image src="/pages-sell/static/select-good/icon-close.png" class="close-icon" @click="close">
+					</image>
+				</view>
 
-			<!-- Product Info -->
-			<view class="product-info">
-				<image :src="currentProduct.cover" class="book-cover" mode="aspectFill"></image>
-				<view class="info-right">
-					<view class="price-row">
-						<text class="currency">¥</text>
-						<text class="price">{{ displayUnitPrice }}</text>
-						<view class="drop-tag">
-							<text>↓可降至 ¥{{ displayMinPrice }}</text>
+				<!-- Product Info -->
+				<view class="product-info">
+					<image :src="currentProduct.cover" class="book-cover" mode="aspectFill"></image>
+					<view class="info-right">
+						<view class="price-row">
+							<text class="currency">¥</text>
+							<text class="price">{{ displayUnitPrice }}</text>
+							<view class="drop-tag">
+								<text>↓可降至 ¥{{ displayMinPrice }}</text>
+							</view>
 						</view>
-					</view>
-					<view class="tag-row">
-						<view class="quality-tag">
-							<text>品相{{ currentQualityName }}</text>
+						<view class="tag-row">
+							<view class="quality-tag">
+								<text>品相{{ currentQualityName }}</text>
+							</view>
 						</view>
 					</view>
 				</view>
-			</view>
 
-			<!-- Tips -->
-			<view class="tips-row">
-				<text>不同品相有什么区别</text>
-				<image src="/pages-sell/static/select-good/icon-tips.png" class="tips-icon"></image>
-			</view>
+				<!-- Tips -->
+				<view class="tips-row">
+					<text>不同品相有什么区别</text>
+					<image src="/pages-sell/static/select-good/icon-tips.png" class="tips-icon"></image>
+				</view>
 
-			<!-- Promo Note -->
-			<view class="promo-note">
-				<text>下单时用购书余额支付可享余额价 ( 售价 8 折优惠 )</text>
-			</view>
+				<!-- Promo Note -->
+				<view class="promo-note">
+					<text>下单时用购书余额支付可享余额价 ( 售价 8 折优惠 )</text>
+				</view>
 
-			<!-- Options -->
-			<view class="options-list">
-				<view class="option-item" v-for="(opt, index) in qualityOptions" :key="index"
-					:class="{ active: currentQuality === opt.conditionType, disabled: isOptionDisabled(opt) }"
-					@click="selectQuality(opt)">
-					<image v-if="currentQuality === opt.conditionType && !isOptionDisabled(opt)"
-						src="/pages-sell/static/select-good/selected.png" class="bg-image"></image>
-					<view class="left">
-						<text class="opt-name">{{ opt.conditionType | conditionText }}</text>
-						<view class="opt-discount"
-							:class="{ active: currentQuality === opt.conditionType && !isOptionDisabled(opt) }">
-							<text>{{ opt.discount }}折</text>
+				<!-- Options -->
+				<view class="options-list">
+					<view class="option-item" v-for="(opt, index) in qualityOptions" :key="index"
+						:class="{ active: currentQuality === opt.conditionType, disabled: isOptionDisabled(opt) }"
+						@click="selectQuality(opt)">
+						<image v-if="currentQuality === opt.conditionType && !isOptionDisabled(opt)"
+							src="/pages-sell/static/select-good/selected.png" class="bg-image"></image>
+						<view class="left">
+							<text class="opt-name">{{ opt.conditionType | conditionText }}</text>
+							<view class="opt-discount"
+								:class="{ active: currentQuality === opt.conditionType && !isOptionDisabled(opt) }">
+								<text>{{ opt.discount }}折</text>
+							</view>
+						</view>
+						<view class="right">
+							<text v-if="!isOptionDisabled(opt)">¥{{ opt.price }} ( 余额价 ¥{{ opt.balanceMoney }} )</text>
+							<text v-else>无货</text>
 						</view>
-					</view>
-					<view class="right">
-						<text v-if="!isOptionDisabled(opt)">¥{{ opt.price }} ( 余额价 ¥{{ opt.balanceMoney }} )</text>
-						<text v-else>无货</text>
 					</view>
 				</view>
-			</view>
 
-			<!-- Quantity -->
-			<view class="quantity-row">
-				<text class="label">数量</text>
-				<u-number-box v-model="quantity" :min="1" :max="99"></u-number-box>
-			</view>
+				<!-- Quantity -->
+				<view class="quantity-row">
+					<text class="label">数量</text>
+					<u-number-box v-model="quantity" :min="1" :max="99"></u-number-box>
+				</view>
 
-			<!-- Footer Buttons -->
-			<view class="footer-btns">
-				<button class="btn btn-orange" open-type="share" :data-share-type="'product'" :data-title="currentProduct.bookName" :data-isbn="currentProduct.isbn" :data-image="currentProduct.cover" @click="handleShareAction">
-					<text class="price">¥{{ displayReducePrice }}</text>
-					<text class="desc">分享一人可降 {{ currentProduct.reducePrice }} 元</text>
-				</button>
-				<view class="btn btn-green" @click="handleAction" :class="{ 'btn-gray': !hasStock && currentProduct.hasArrivalNotice === 1 }">
-					<text v-if="hasStock" class="price">¥{{ displayTotalPrice }}</text>
-					<text class="desc" :class="{ 'notice': !hasStock }">{{ hasStock ? '加入购物车' : (currentProduct.hasArrivalNotice === 1 ? '取消到货通知' : '到货通知') }}</text>
+				<!-- Footer Buttons -->
+				<view class="footer-btns">
+					<view class="btn btn-orange" @click="handleShareAction">
+						<text class="price">¥{{ displayReducePrice }}</text>
+						<text class="desc">分享一人可降 {{ currentProduct.reducePrice }} 元</text>
+					</view>
+					<view class="btn btn-green" @click="handleAction"
+						:class="{ 'btn-gray': !hasStock && currentProduct.hasArrivalNotice === 1 }">
+						<text v-if="hasStock" class="price">¥{{ displayTotalPrice }}</text>
+						<text class="desc" :class="{ 'notice': !hasStock }">{{ hasStock ? '加入购物车' :
+							(currentProduct.hasArrivalNotice === 1 ? '取消到货通知' : '到货通知') }}</text>
+					</view>
 				</view>
 			</view>
-			</view>
 		</u-popup>
 
 		<price-reduction-popup ref="reducePopup" @scan="handleScan"></price-reduction-popup>
@@ -152,8 +155,22 @@ export default {
 				if (res.code === 200) {
 					this.currentProduct = res.data || {};
 					this.qualityOptions = res.data.skuList || [];
-					if (this.qualityOptions.length > 1) {
-						this.currentQuality = this.qualityOptions[1].conditionType || 2;
+					if (this.qualityOptions.length > 0) {
+						// 有库存品相优先级:中等(2) > 良品(1) > 次品(3)
+						const middleStock = this.qualityOptions.find(o => o.conditionType === 2);
+						if (middleStock && middleStock.stockNum > 0) {
+							this.currentQuality = middleStock.conditionType;
+						} else {
+							const goodStock = this.qualityOptions.find(o => o.conditionType === 1);
+							if (goodStock && goodStock.stockNum > 0) {
+								this.currentQuality = goodStock.conditionType;
+							} else {
+								const badStock = this.qualityOptions.find(o => o.conditionType === 3);
+								if (badStock && badStock.stockNum > 0) {
+									this.currentQuality = badStock.conditionType;
+								}
+							}
+						}
 					}
 				}
 			});
@@ -185,7 +202,7 @@ export default {
 		handleNotify() {
 			const isCancel = this.currentProduct.hasArrivalNotice === 1;
 			const apiUrl = isCancel ? '/token/shop/user/noticeArrivalCancel' : '/token/shop/user/noticeArrival';
-			
+
 			uni.$u.http.post(apiUrl, {
 				isbn: this.currentProduct.isbn,
 			}).then(res => {
@@ -201,7 +218,7 @@ export default {
 		},
 		handleConfirm() {
 			if (this.isSubmitting) return; // 防止重复提交
-			
+
 			if (!this.currentProduct.isbn) {
 				this.$u.toast('商品信息缺失');
 				return;
@@ -241,7 +258,7 @@ export default {
 		},
 		handleShareAction() {
 			if (this.isSubmitting) return; // 防止重复提交
-			
+
 			if (!this.currentProduct.isbn) {
 				this.$u.toast('商品信息缺失');
 				return;
@@ -265,14 +282,23 @@ export default {
 			}).then(async res => {
 				if (res.code === 200) {
 					await this.$updateCartBadge();
-					// this.$u.toast('加入购物车成功'); // 可选,看是否需要提示
+					this.$u.toast('加入购物车成功');
 					this.$emit('confirm', {
 						product: this.currentProduct,
 						quality: this.currentQuality,
 						quantity: this.quantity
 					});
 					this.close();
-					// 移除降价弹窗逻辑
+
+					// 打开减价弹窗
+					setTimeout(() => {
+						if (this.$refs.reducePopup) {
+							this.$refs.reducePopup.open({
+								isbn: this.currentProduct.isbn,
+								conditionType: conditionType
+							});
+						}
+					}, 300);
 				} else {
 					this.$u.toast(res.msg || '加入购物车失败');
 				}
@@ -538,10 +564,6 @@ export default {
 		margin: 0;
 		-webkit-tap-highlight-color: transparent;
 
-		&::after {
-			border: none;
-		}
-
 		.price {
 			font-size: 38rpx;
 			color: #fff;

+ 121 - 50
pages-sell/components/sell-container/index.vue

@@ -15,7 +15,7 @@
 		<!-- 主要内容区域 -->
 		<view class="main-content" :style="{ paddingTop: (statusBarHeight + 44) + 'px' }">
 			<!-- 顶部固定区域:导航栏背景和搜索框 -->
-			<view class="fixed-header-area" :style="{ 
+			<view class="fixed-header-area" :style="{
 				paddingTop: statusBarHeight + 44 + 'px',
 				backgroundImage: scrollTop > 0 ? 'url(/pages-sell/static/top-bg.png)' : 'none',
 				backgroundPosition: `center top`
@@ -31,24 +31,22 @@
 					</view>
 				</view>
 
-                <!-- 热搜词横向滚动区域 -->
-                <view class="hot-search-wrapper" v-if="hotSearchList.length > 0">
-                    <view class="hot-search-fixed-title">
-                        <view class="hot-tag hot-tag-highlight" @click="navigateTo('/pages-sell/pages/search')">热搜</view>
-                    </view>
-                    <scroll-view class="hot-search-scroll" scroll-x="true" :show-scrollbar="false">
-                        <view class="hot-search-list">
-                            <view 
-                                class="hot-tag" 
-                                v-for="(item, index) in hotSearchList" 
-                                :key="index" 
-                                @click="goSearchResult(item)"
-                            >
-                                {{ item }}
-                            </view>
-                        </view>
-                    </scroll-view>
-                </view>
+				<!-- 热搜词横向滚动区域 -->
+				<view class="hot-search-wrapper" v-if="hotSearchList.length > 0">
+					<view class="hot-search-fixed-title">
+						<view class="hot-tag hot-tag-highlight" @click="navigateTo('/pages-sell/pages/search')">热搜
+						</view>
+						<image src="../../static/select.png" class="select-icon" mode="widthFix" style="width: 30rpx;"></image>
+					</view>
+					<scroll-view class="hot-search-scroll" scroll-x="true" :show-scrollbar="false">
+						<view class="hot-search-list">
+							<view class="hot-tag" v-for="(item, index) in hotSearchList" :key="index"
+								@click="goSearchResult(item)">
+								{{ item }}
+							</view>
+						</view>
+					</scroll-view>
+				</view>
 			</view>
 
 			<!-- 占位,防止内容被 fixed 区域遮挡 -->
@@ -175,6 +173,23 @@
 				</image>
 			</button>
 		</FloatingDrag>
+
+		<!-- 客服悬浮按钮 -->
+		<FloatingDrag :width="126" :height="140" :initial-position="servicePosition"
+			@position-change="handleServicePositionChange"
+			@drag-start="handleDragStart"
+			@drag-end="handleDragEnd">
+			<!-- #ifdef MP-ALIPAY -->
+			<button class="service-btn" @click="navigateToCustomerService">
+				<image src="/static/img/kf.png" class="cs-icon" mode="aspectFit"></image>
+			</button>
+			<!-- #endif -->
+			<!-- #ifndef MP-ALIPAY -->
+			<button class="service-btn" open-type="contact">
+				<image src="/static/img/kf.png" class="cs-icon" mode="aspectFit"></image>
+			</button>
+			<!-- #endif -->
+		</FloatingDrag>
 	</view>
 </template>
 
@@ -194,6 +209,13 @@ export default {
 				right: 0,
 				bottom: '15%',
 			},
+			// 客服悬浮按钮位置
+			servicePosition: {
+				left: 'auto',
+				right: 0,
+				bottom: '30%',
+			},
+			isDragging: false, // 是否正在拖动悬浮按钮
 			barStyle: {
 				backgroundColor: 'transparent',
 				background: "url('/pages-sell/static/tab-selected.png') no-repeat center",
@@ -261,6 +283,7 @@ export default {
 		},
 		// 接收外部传入的页面滚动事件
 		onPageScroll(scrollTop) {
+			if (this.isDragging) return; // 拖动悬浮按钮时禁止滚动
 			this.scrollTop = scrollTop || 0;
 			console.log(this.scrollTop)
 		},
@@ -354,6 +377,24 @@ export default {
 		// 红包按钮位置变化
 		handleRedPacketPositionChange(position) {
 			this.redPacketPosition = position;
+		},
+		// 客服按钮位置变化
+		handleServicePositionChange(position) {
+			this.servicePosition = position;
+		},
+		// 拖动开始
+		handleDragStart() {
+			this.isDragging = true;
+		},
+		// 拖动结束
+		handleDragEnd() {
+			this.isDragging = false;
+		},
+		// 支付宝小程序的客服
+		navigateToCustomerService() {
+			uni.makePhoneCall({
+				phoneNumber: '400-123-4567'
+			});
 		}
 	}
 }
@@ -427,59 +468,67 @@ export default {
 }
 
 .search-placeholder {
-	height: 160rpx; /* 增加高度以容纳热搜词 */
+	height: 160rpx;
+	/* 增加高度以容纳热搜词 */
 }
 
 /* 热搜词横向滚动 */
 .hot-search-wrapper {
-    margin-bottom: 24rpx;
-    width: 100%;
-    display: flex;
-    align-items: center;
+	margin-bottom: 24rpx;
+	width: 100%;
+	display: flex;
+	align-items: center;
 }
 
 .hot-search-fixed-title {
-    flex-shrink: 0;
-    padding-left: 24rpx;
+	flex-shrink: 0;
+	padding-left: 24rpx;
+	position: relative;
+	.select-icon {
+		position: absolute;
+		top: 36rpx;
+		left: 50%;
+		transform: translateX(-50%);
+	}
 }
 
 .hot-search-scroll {
-    flex: 1;
-    white-space: nowrap;
-    overflow: hidden;
+	flex: 1;
+	white-space: nowrap;
+	overflow: hidden;
 }
 
 .hot-search-list {
-    display: inline-flex;
-    align-items: center;
-    padding: 0 20rpx;
+	display: inline-flex;
+	align-items: center;
+	padding: 0 20rpx;
 }
 
 .hot-tag {
-    display: inline-block;
-    margin-right: 30rpx;
-    font-size: 26rpx;
-    color: #666;
-    font-weight: 500;
+	display: inline-block;
+	margin-right: 30rpx;
+	font-size: 26rpx;
+	color: #666;
+	font-weight: 500;
 }
 
 .hot-tag-highlight {
-    color: #38C148;
-    font-weight: bold;
-    padding-right: 20rpx;
-    margin-right: 0;
-    position: relative;
+	color: #38C148;
+	font-weight: bold;
+	padding-right: 20rpx;
+	margin-right: 0;
+	position: relative;
 }
 
 .hot-tag-highlight::after {
-    content: '';
-    position: absolute;
-    right: 0;
-    top: 50%;
-    transform: translateY(-50%);
-    width: 2rpx;
-    height: 24rpx;
-    background-color: #E0E0E0;
+	content: '';
+	position: absolute;
+	right: 0;
+	top: 50%;
+	transform: translateY(-50%);
+	width: 2rpx;
+	height: 24rpx;
+	background-color: #E0E0E0;
 }
 
 /* 搜索框 */
@@ -927,4 +976,26 @@ export default {
 		border: none;
 	}
 }
+
+/* 客服悬浮按钮 */
+.service-btn {
+	width: 126rpx;
+	height: 140rpx;
+	background: transparent;
+	border: none;
+	padding: 0;
+	margin: 0;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+
+	&::after {
+		border: none;
+	}
+
+	.cs-icon {
+		width: 126rpx;
+		height: 140rpx;
+	}
+}
 </style>

+ 2 - 2
pages-sell/components/service-popup/index.vue

@@ -37,7 +37,7 @@ export default {
                 {
                     icon: '/pages-sell/static/service/icon-3.png',
                     title: '24 小时发货',
-                    desc: '订单支付成功后 24 小时内发货,若未在 24 小时内发货可申请补差价到余额,平台将在 24 小时内处理申请。'
+                    desc: '订单支付成功后24小时内发货,若未在24小时内发货,可申请无门槛购书红包,平台将在24小时内处理申请。'
                 },
                 // {
                 //     icon: '/pages-sell/static/service/icon-4.png',
@@ -52,7 +52,7 @@ export default {
                 {
                     icon: '/pages-sell/static/service/icon-6.png',
                     title: '缺货必赔',
-                    desc: '订单付款后,因平台除因无法发货的订单,48 小时后可申请补偿到余额,平台将在 24 小时内处理申请。'
+                    desc: '订单付款后,因平台原因无法发货的订单,48小时后自动发放无门槛购书红包到书嗨卡包'
                 }
             ]
         };

+ 339 - 318
pages-sell/pages/detail.vue

@@ -4,8 +4,8 @@
         <view class="header-bg"></view>
 
         <!-- Custom Navbar -->
-        <Navbar :title="product.bookName || '详情'" :titleSize="32" :title-color="navbarTitleColor" :back-icon-color="navbarIconColor"
-            :background="navbarBackground">
+        <Navbar :title="product.bookName || '详情'" :titleSize="32" :title-color="navbarTitleColor"
+            :back-icon-color="navbarIconColor" :background="navbarBackground">
         </Navbar>
 
         <!-- Notification Bar -->
@@ -37,16 +37,18 @@
             <ServiceCard @click="showReduceRulePopup" :bookInfo="product"></ServiceCard>
 
             <!-- Customer Service Float -->
-            <FloatingDrag :width="120" :height="120" :initial-position="servicePosition"
-                @position-change="handlePositionChange" :z-index="20">
+            <FloatingDrag :width="126" :height="140" :initial-position="servicePosition"
+                @position-change="handlePositionChange"
+                @drag-start="handleDragStart"
+                @drag-end="handleDragEnd">
                 <!-- #ifdef MP-ALIPAY -->
                 <button class="service-btn" @click="navigateToCustomerService">
-                    <image src="/pages-sell/static/goods/icon-kefu.png" class="cs-icon" mode="aspectFit"></image>
+                    <image src="/static/img/kf.png" class="cs-icon" mode="aspectFit"></image>
                 </button>
                 <!-- #endif -->
                 <!-- #ifndef MP-ALIPAY -->
                 <button class="service-btn" open-type="contact">
-                    <image src="/pages-sell/static/goods/icon-kefu.png" class="cs-icon" mode="aspectFit"></image>
+                    <image src="/static/img/kf.png" class="cs-icon" mode="aspectFit"></image>
                 </button>
                 <!-- #endif -->
             </FloatingDrag>
@@ -72,7 +74,8 @@
         </view>
 
         <!-- Footer -->
-        <FooterBar :hasStock="hasStock" :isCollect="product.isCollect" :hasArrivalNotice="product.hasArrivalNotice" @addCart="openSelectPopup" @notify="handleNotify" @collect="handleCollect"></FooterBar>
+        <FooterBar :hasStock="hasStock" :isCollect="product.isCollect" :hasArrivalNotice="product.hasArrivalNotice"
+            @addCart="openSelectPopup" @notify="handleNotify" @collect="handleCollect"></FooterBar>
 
         <!-- Select Popup -->
         <SelectGoodPopup ref="selectPopup" @confirm="onPopupConfirm" @notice-change="onNoticeChange"></SelectGoodPopup>
@@ -86,353 +89,371 @@
 </template>
 
 <script>
-    import Navbar from '@/components/navbar/navbar.vue'
-    import SelectGoodPopup from '../components/select-good-popup/index.vue'
-    import InfoCard from '../components/detail/info-card.vue'
-    import ServiceCard from '../components/detail/service-card.vue'
-    import ProductContent from '../components/detail/product-content.vue'
-    import FooterBar from '../components/detail/footer-bar.vue'
-    import FloatingDrag from "@/components/floating-drag.vue";
-    import SharePopup from '../components/detail/share-popup.vue';
-    import ReduceRulePopup from '../components/reduce-rule-popup/index.vue';
-
-    export default {
-        components: {
-            Navbar,
-            SelectGoodPopup,
-            InfoCard,
-            ServiceCard,
-            ProductContent,
-            FooterBar,
-            FloatingDrag,
-            SharePopup,
-            ReduceRulePopup
+import Navbar from '@/components/navbar/navbar.vue'
+import SelectGoodPopup from '../components/select-good-popup/index.vue'
+import InfoCard from '../components/detail/info-card.vue'
+import ServiceCard from '../components/detail/service-card.vue'
+import ProductContent from '../components/detail/product-content.vue'
+import FooterBar from '../components/detail/footer-bar.vue'
+import FloatingDrag from "@/components/floating-drag.vue";
+import SharePopup from '../components/detail/share-popup.vue';
+import ReduceRulePopup from '../components/reduce-rule-popup/index.vue';
+
+export default {
+    components: {
+        Navbar,
+        SelectGoodPopup,
+        InfoCard,
+        ServiceCard,
+        ProductContent,
+        FooterBar,
+        FloatingDrag,
+        SharePopup,
+        ReduceRulePopup
+    },
+    data() {
+        return {
+            currentTab: 0,
+            hasStock: false, // Toggle this to test stock status
+            navbarBackground: 'transparent',
+            navbarTitleColor: '#ffffff',
+            navbarIconColor: '#ffffff',
+            isDragging: false, // 是否正在拖动悬浮按钮
+            tipsContent: [
+                '印刷版次较多,二手图书封面、版次、原价等信息可能与商品介绍有差异,具体以收到实物为准;',
+                '二手图书性质特殊,不保证随新书赠送的光盘、海报、卡片等内容,仅支持图书质量问题退款,否则将扣除运费成本;',
+                '收到的图书如有质量问题,请于七天内联系客服处理,超出售后时效,不予处理。'
+            ],
+            relatedBooksList: [],
+            product: {},
+            servicePosition: {
+                left: "auto",
+                right: 0,
+                bottom: "300rpx",
+            },
+        }
+    },
+    onLoad(options) {
+        const isbn = options.isbn || options.id; // Support both just in case
+        if (isbn) {
+            this.getBookDetail(isbn);
+        } else {
+            uni.showToast({
+                title: '参数错误',
+                icon: 'none'
+            });
+            setTimeout(() => {
+                uni.navigateBack();
+            }, 1500);
+        }
+    },
+    onPageScroll(e) {
+        if (this.isDragging) return; // 拖动悬浮按钮时禁止滚动
+        if (e.scrollTop > 0) {
+            this.navbarBackground = '#ffffff';
+            this.navbarTitleColor = '#000000';
+            this.navbarIconColor = '#000000';
+        } else {
+            this.navbarBackground = 'transparent';
+            this.navbarTitleColor = '#ffffff';
+            this.navbarIconColor = '#ffffff';
+        }
+    },
+    methods: {
+        getBookDetail(isbn) {
+            uni.showLoading({ title: '加载中' });
+            this.$u.api.getBookDetailAjax({ isbn }).then(res => {
+                uni.hideLoading();
+                if (res.code === 200) {
+                    this.product = res.data;
+                    this.hasStock = res.data.skuList.some(sku => sku.stockNum > 0);
+                    if (res.data.recommendList) {
+                        this.relatedBooksList = res.data.recommendList;
+                    }
+                } else {
+                    uni.showToast({
+                        title: res.msg || '获取详情失败',
+                        icon: 'none'
+                    });
+                }
+            }).catch(() => {
+                uni.hideLoading();
+            });
         },
-        data() {
-            return {
-                currentTab: 0,
-                hasStock: false, // Toggle this to test stock status
-                navbarBackground: 'transparent',
-                navbarTitleColor: '#ffffff',
-                navbarIconColor: '#ffffff',
-                tipsContent: [
-                    '印刷版次较多,二手图书封面、版次、原价等信息可能与商品介绍有差异,具体以收到实物为准;',
-                    '二手图书性质特殊,不保证随新书赠送的光盘、海报、卡片等内容,仅支持图书质量问题退款,否则将扣除运费成本;',
-                    '收到的图书如有质量问题,请于七天内联系客服处理,超出售后时效,不予处理。'
-                ],
-                relatedBooksList: [],
-                product: {},
-                servicePosition: {
-                    left: "auto",
-                    right: 0,
-                    bottom: "300rpx",
-                },
-            }
+        switchTab(index) {
+            this.currentTab = index;
         },
-        onLoad(options) {
-            const isbn = options.isbn || options.id; // Support both just in case
-            if (isbn) {
-                this.getBookDetail(isbn);
-            } else {
-                uni.showToast({
-                    title: '参数错误',
-                    icon: 'none'
-                });
-                setTimeout(() => {
-                    uni.navigateBack();
-                }, 1500);
-            }
+        openSelectPopup(sourceFrom) {
+            this.$refs.selectPopup.open(this.product, sourceFrom);
         },
-        onPageScroll(e) {
-            if (e.scrollTop > 0) {
-                this.navbarBackground = '#ffffff';
-                this.navbarTitleColor = '#000000';
-                this.navbarIconColor = '#000000';
-            } else {
-                this.navbarBackground = 'transparent';
-                this.navbarTitleColor = '#ffffff';
-                this.navbarIconColor = '#ffffff';
-            }
+        onNoticeChange(val) {
+            this.$set(this.product, 'hasArrivalNotice', val);
         },
-        methods: {
-            getBookDetail(isbn) {
-                uni.showLoading({ title: '加载中' });
-                this.$u.api.getBookDetailAjax({ isbn }).then(res => {
-                    uni.hideLoading();
-                    if (res.code === 200) {
-                        this.product = res.data;
-                        this.hasStock = res.data.skuList.some(sku => sku.stockNum > 0);
-                        if (res.data.recommendList) {
-                            this.relatedBooksList = res.data.recommendList;
-                        }
-                    } else {
-                        uni.showToast({
-                            title: res.msg || '获取详情失败',
-                            icon: 'none'
-                        });
-                    }
-                }).catch(() => {
-                    uni.hideLoading();
-                });
-            },
-            switchTab(index) {
-                this.currentTab = index;
-            },
-            openSelectPopup(sourceFrom) {
-                this.$refs.selectPopup.open(this.product, sourceFrom);
-            },
-            onNoticeChange(val) {
-                this.$set(this.product, 'hasArrivalNotice', val);
-            },
-            handleNotify() {
-                const isCancel = this.product.hasArrivalNotice === 1;
-                const apiUrl = isCancel ? '/token/shop/user/noticeArrivalCancel' : '/token/shop/user/noticeArrival';
-                
-                uni.showLoading({ mask: true });
-                uni.$u.http.post(apiUrl, { isbn: this.product.isbn }).then(res => {
-                    uni.hideLoading();
-                    if (res.code === 200) {
-                        this.$set(this.product, 'hasArrivalNotice', isCancel ? 0 : 1);
-                        uni.showToast({
-                            title: isCancel ? '已取消到货通知' : '已订阅到货通知',
-                            icon: 'success'
-                        });
-                    } else {
-                        uni.showToast({
-                            title: res.msg || '操作失败',
-                            icon: 'none'
-                        });
-                    }
-                }).catch(() => {
-                    uni.hideLoading();
-                });
-            },
-            async onPopupConfirm(data) {
-                console.log('Added to cart:', data);
-                await this.$updateCartBadge();
-                uni.showToast({
-                    title: '已加入购物车',
-                    icon: 'success',
-                    duration: 3000
-                });
-            },
-            handleCollect() {
-                if (!this.product || !this.product.isbn) {
-                    return this.$u.toast('商品信息不完整');
+        handleNotify() {
+            const isCancel = this.product.hasArrivalNotice === 1;
+            const apiUrl = isCancel ? '/token/shop/user/noticeArrivalCancel' : '/token/shop/user/noticeArrival';
+
+            uni.showLoading({ mask: true });
+            uni.$u.http.post(apiUrl, { isbn: this.product.isbn }).then(res => {
+                uni.hideLoading();
+                if (res.code === 200) {
+                    this.$set(this.product, 'hasArrivalNotice', isCancel ? 0 : 1);
+                    uni.showToast({
+                        title: isCancel ? '已取消到货通知' : '已订阅到货通知',
+                        icon: 'success'
+                    });
+                } else {
+                    uni.showToast({
+                        title: res.msg || '操作失败',
+                        icon: 'none'
+                    });
                 }
-                const isCollect = this.product.isCollect;
-                const api = isCollect ? this.$u.api.removeCollectAjax : this.$u.api.addCollectAjax;
-                const params = isCollect ? [this.product.isbn] : this.product.isbn;
-
-                uni.showLoading({ mask: true });
-                api(params).then(res => {
-                    uni.hideLoading();
-                    if (res.code === 200) {
-                        this.$set(this.product, 'isCollect', !isCollect);
-                        this.$u.toast(isCollect ? '已取消收藏' : '收藏成功');
-                    } else {
-                        this.$u.toast(res.msg);
-                    }
-                }).catch(() => {
-                    uni.hideLoading();
-                });
-            },
-            showReduceRulePopup() {
-                this.$refs.reduceRulePopup.open();
-            },
-            onBookClick(book) {
-                console.log('Book clicked:', book);
-                uni.navigateTo({
-                    url: '/pages-sell/pages/detail?id=' + encodeURIComponent(book.title)
-                });
-            },
-            openSharePopup() {
-                this.$refs.sharePopup.open();
-            },
-            // 处理位置变更
-            handlePositionChange(position) {
-                this.servicePosition = position;
-            },
-            //支付宝小程序的客服
-            navigateToCustomerService() {
-                uni.navigateTo({
-                    url: "/pages-mine/pages/customer-service",
-                });
-            },
+            }).catch(() => {
+                uni.hideLoading();
+            });
+        },
+        async onPopupConfirm(data) {
+            console.log('Added to cart:', data);
+            await this.$updateCartBadge();
+            uni.showToast({
+                title: '已加入购物车',
+                icon: 'success',
+                duration: 3000
+            });
         },
-        onShareAppMessage(res) {
-            if (res && res.from === 'button' && res.target && res.target.dataset && res.target.dataset.shareType === 'product') {
-                const dataset = res.target.dataset;
-                return {
-                    title: dataset.title || '',
-                    path: `/pages-sell/pages/detail?isbn=${dataset.isbn}`,
-                    imageUrl: dataset.image || ''
-                };
+        handleCollect() {
+            if (!this.product || !this.product.isbn) {
+                return this.$u.toast('商品信息不完整');
             }
+            const isCollect = this.product.isCollect;
+            const api = isCollect ? this.$u.api.removeCollectAjax : this.$u.api.addCollectAjax;
+            const params = isCollect ? [this.product.isbn] : this.product.isbn;
+
+            uni.showLoading({ mask: true });
+            api(params).then(res => {
+                uni.hideLoading();
+                if (res.code === 200) {
+                    this.$set(this.product, 'isCollect', !isCollect);
+                    this.$u.toast(isCollect ? '已取消收藏' : '收藏成功');
+                } else {
+                    this.$u.toast(res.msg);
+                }
+            }).catch(() => {
+                uni.hideLoading();
+            });
+        },
+        showReduceRulePopup() {
+            this.$refs.reduceRulePopup.open();
+        },
+        onBookClick(book) {
+            console.log('Book clicked:', book);
+            uni.navigateTo({
+                url: '/pages-sell/pages/detail?id=' + encodeURIComponent(book.title)
+            });
+        },
+        openSharePopup() {
+            this.$refs.sharePopup.open();
+        },
+        // 处理位置变更
+        handlePositionChange(position) {
+            this.servicePosition = position;
+        },
+        // 拖动开始
+        handleDragStart() {
+            this.isDragging = true;
+        },
+        // 拖动结束
+        handleDragEnd() {
+            this.isDragging = false;
+        },
+        //支付宝小程序的客服
+        navigateToCustomerService() {
+            uni.navigateTo({
+                url: "/pages-mine/pages/customer-service",
+            });
+        },
+    },
+    onShareAppMessage(res) {
+        if (res.from === "button" && res.target && res.target.dataset && res.target.dataset.shareType === "reduce") {
+            let reduceCode = uni.getStorageSync("reduceCodeShare");
+            // 调用分享接口
+            if (this.$u && this.$u.api && this.$u.api.goToReduceShareAjax) {
+                this.$u.api.goToReduceShareAjax({
+                    reduceCode: reduceCode
+                });
+            } else {
+                uni.$u && uni.$u.http && uni.$u.http.get('/token/shop/order/goToShare', { reduceCode: reduceCode });
+            }
+
             return {
-                title: `${this.product.bookName}`,
-                path: `/pages-sell/pages/detail?isbn=${this.product.isbn}`,
-                imageUrl: this.product.cover
+                title: "快来帮我减钱买书吧!",
+                path: "/pages/home/index?reduceCode=" + reduceCode,
+                imageUrl: "https://shuhi.oss-cn-qingdao.aliyuncs.com/mini/share.jpg",
+                desc: "书嗨,专注于书籍交易的平台,提供新书和二手书的买卖服务",
             };
         }
+        return {
+            title: `${this.product.bookName}`,
+            path: `/pages-sell/pages/detail?isbn=${this.product.isbn}`,
+            imageUrl: this.product.cover
+        };
     }
+}
 </script>
 
 <style lang="scss" scoped>
-    .detail-page {
-        min-height: 100vh;
-        background-color: #f5f5f5;
-        position: relative;
-        padding-bottom: 100rpx;
+.detail-page {
+    min-height: 100vh;
+    background-color: #f5f5f5;
+    position: relative;
+    padding-bottom: 100rpx;
+}
+
+.header-bg {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 664rpx;
+    background: linear-gradient(0deg, #4ED868 0%, #D1FFE5 100%);
+    z-index: 0;
+}
+
+.notification-bar {
+    position: fixed;
+    top: 180rpx;
+    /* Adjust based on navbar height */
+    left: 30rpx;
+    z-index: 10;
+    background: rgba(0, 0, 0, 0.3);
+    border-radius: 30rpx;
+    padding: 6rpx 20rpx 6rpx 6rpx;
+    display: flex;
+    align-items: center;
+
+    .notif-text {
+        font-size: 24rpx;
+        color: #fff;
+        margin-left: 10rpx;
     }
-
-    .header-bg {
-        position: absolute;
-        top: 0;
-        left: 0;
-        width: 100%;
-        height: 664rpx;
-        background: linear-gradient(0deg, #4ED868 0%, #D1FFE5 100%);
-        z-index: 0;
+}
+
+.content-scroll {
+    position: relative;
+    z-index: 1;
+    height: 100vh;
+}
+
+.cover-area {
+    position: relative;
+    display: flex;
+    justify-content: center;
+    padding-top: 60rpx;
+    padding-bottom: 40rpx;
+
+    .book-cover {
+        width: 360rpx;
+        height: 360rpx;
+        box-shadow: 0 10rpx 20rpx rgba(0, 0, 0, 0.1);
     }
 
-    .notification-bar {
-        position: fixed;
-        top: 180rpx;
-        /* Adjust based on navbar height */
-        left: 30rpx;
-        z-index: 10;
-        background: rgba(0, 0, 0, 0.3);
-        border-radius: 30rpx;
-        padding: 6rpx 20rpx 6rpx 6rpx;
+    .share-btn {
+        position: absolute;
+        right: 50rpx;
+        top: 50rpx;
         display: flex;
+        flex-direction: column;
         align-items: center;
+        z-index: 10; // Ensure it's clickable
 
-        .notif-text {
-            font-size: 24rpx;
-            color: #fff;
-            margin-left: 10rpx;
+        .share-icon {
+            width: 40rpx;
+            height: 40rpx;
+            margin-bottom: 4rpx;
         }
-    }
 
-    .content-scroll {
-        position: relative;
-        z-index: 1;
-        height: 100vh;
-    }
-
-    .cover-area {
-        position: relative;
-        display: flex;
-        justify-content: center;
-        padding-top: 60rpx;
-        padding-bottom: 40rpx;
-
-        .book-cover {
-            width: 360rpx;
-            height: 360rpx;
-            box-shadow: 0 10rpx 20rpx rgba(0, 0, 0, 0.1);
-        }
-
-        .share-btn {
-            position: absolute;
-            right: 50rpx;
-            top: 50rpx;
-            display: flex;
-            flex-direction: column;
-            align-items: center;
-            z-index: 10; // Ensure it's clickable
-
-            .share-icon {
-                width: 40rpx;
-                height: 40rpx;
-                margin-bottom: 4rpx;
-            }
-
-            text {
-                font-size: 20rpx;
-                color: #333;
-            }
+        text {
+            font-size: 20rpx;
+            color: #333;
         }
     }
+}
 
-    .banner-area {
-        background: #f5f5f5;
-        padding: 20rpx;
-
-        .banner-img {
-            width: 100%;
-            border-radius: 20rpx;
-        }
-    }
+.banner-area {
+    background: #f5f5f5;
+    padding: 20rpx;
 
-    .service-btn {
+    .banner-img {
         width: 100%;
-        height: 100%;
-        display: flex;
-        justify-content: center;
-        align-items: center;
-        padding: 0;
-        margin: 0;
-        background-color: transparent;
-        line-height: 1;
-        border-radius: 0;
-
-        &::after {
-            border: none;
-        }
-
-        .cs-icon {
-            width: 100rpx;
-            height: 100rpx;
-        }
+        border-radius: 20rpx;
+    }
+}
+
+.service-btn {
+    width: 100%;
+    height: 100%;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    padding: 0;
+    margin: 0;
+    background-color: transparent;
+    line-height: 1;
+    border-radius: 0;
+
+    &::after {
+        border: none;
     }
 
-    .tabs-header {
-        display: flex;
-        justify-content: center;
-        /* Center the tabs */
-        background: #F8F8F8;
-        padding: 20rpx 0;
-        /* Remove horizontal padding as we center items */
+    .cs-icon {
+        width: 100rpx;
+        height: 100rpx;
+    }
+}
+
+.tabs-header {
+    display: flex;
+    justify-content: center;
+    /* Center the tabs */
+    background: #F8F8F8;
+    padding: 20rpx 0;
+    /* Remove horizontal padding as we center items */
+
+    .tab-item {
+        padding: 0 30rpx;
+        /* Add internal padding for hit area */
+        position: relative;
 
-        .tab-item {
-            padding: 0 30rpx;
-            /* Add internal padding for hit area */
-            position: relative;
+        text {
+            font-family: 'Source Han Sans SC';
+            font-size: 30rpx;
+            /* Assuming 30px from design tool = 30rpx */
+            color: #666666;
+            transition: all 0.3s;
+        }
 
+        &.active {
             text {
-                font-family: 'Source Han Sans SC';
                 font-size: 30rpx;
-                /* Assuming 30px from design tool = 30rpx */
-                color: #666666;
-                transition: all 0.3s;
+                /* Keep consistent size or adjust if 'big' effect needed, user said 30px */
+                font-weight: bold;
+                color: #333333;
             }
 
-            &.active {
-                text {
-                    font-size: 30rpx;
-                    /* Keep consistent size or adjust if 'big' effect needed, user said 30px */
-                    font-weight: bold;
-                    color: #333333;
-                }
-
-                .indicator {
-                    position: absolute;
-                    bottom: 2rpx;
-                    /* Adjust vertical position */
-                    left: 50%;
-                    transform: translateX(-50%);
-                    width: 120rpx;
-                    /* Make it wider or relative to text? Usually fixed or text width. Let's try matching text width visually or a fixed width */
-                    height: 8rpx;
-                    /* Slightly thicker for gradient visibility */
-                    background: linear-gradient(90deg, rgba(78, 217, 100, 0.1) 0%, #4ED964 100%);
-                    border-radius: 4rpx;
-                }
+            .indicator {
+                position: absolute;
+                bottom: 2rpx;
+                /* Adjust vertical position */
+                left: 50%;
+                transform: translateX(-50%);
+                width: 120rpx;
+                /* Make it wider or relative to text? Usually fixed or text width. Let's try matching text width visually or a fixed width */
+                height: 8rpx;
+                /* Slightly thicker for gradient visibility */
+                background: linear-gradient(90deg, rgba(78, 217, 100, 0.1) 0%, #4ED964 100%);
+                border-radius: 4rpx;
             }
         }
     }
-
-
+}
 </style>

+ 15 - 7
pages-sell/pages/recommend.vue

@@ -23,7 +23,7 @@
 
 		<!-- List Content -->
 		<view class="list-container">
-			<recommend-item v-for="(item, index) in bookList" :key="index" :item="item"></recommend-item>
+			<recommend-item v-for="(item, index) in bookList" :key="index" :item="item" :show-desc="cateType != 1"></recommend-item>
 			<u-loadmore :status="loadStatus" margin-top="30" margin-bottom="30"></u-loadmore>
 		</view>
 	</view>
@@ -48,7 +48,8 @@ export default {
 			imageUrl: "",
 			showName: "",
 			remark: "",
-			bookList: []
+			bookList: [],
+			cateType: ''
 		}
 	},
 	onLoad(options) {
@@ -63,12 +64,18 @@ export default {
 		}
 	},
 	onShareAppMessage(res) {
-		if (res && res.from === 'button' && res.target && res.target.dataset && res.target.dataset.shareType === 'product') {
-			const dataset = res.target.dataset;
+		if (res.from === "button" && res.target && res.target.dataset && res.target.dataset.shareType === "reduce") {
+			let reduceCode = uni.getStorageSync("reduceCodeShare");
+			if (this.$u && this.$u.api && this.$u.api.goToReduceShareAjax) {
+				this.$u.api.goToReduceShareAjax({ reduceCode: reduceCode });
+			} else {
+				uni.$u && uni.$u.http && uni.$u.http.get('/token/shop/order/goToShare', { reduceCode: reduceCode });
+			}
 			return {
-				title: dataset.title || '',
-				path: `/pages-sell/pages/detail?isbn=${dataset.isbn}`,
-				imageUrl: dataset.image || ''
+				title: "快来帮我减钱买书吧!",
+				path: "/pages/home/index?reduceCode=" + reduceCode,
+				imageUrl: "https://shuhi.oss-cn-qingdao.aliyuncs.com/mini/share.jpg",
+				desc: "书嗨,专注于书籍交易的平台,提供新书和二手书的买卖服务",
 			};
 		}
 		return {
@@ -94,6 +101,7 @@ export default {
 			}).then(res => {
 				if(res.code == 200) {
 					const data = res.data;
+					this.cateType = data.cateType;
 					// Update header info (only needed on first page, but safe to update every time or check pageNum)
 					if(this.pageNum == 1) {
 						this.imageUrl = data.imgUrl;

+ 344 - 324
pages-sell/pages/search-result.vue

@@ -96,390 +96,410 @@
 </template>
 
 <script>
-    import RecommendItem from '../components/recommend-item/index.vue';
-    import HotRecommendItem from '../components/hot-recommend-item/index.vue';
-    import Navbar from '@/components/navbar/navbar.vue';
-    import PacketDialog from '@/pages-sell/components/packet-dialog/index.vue';
-
-    export default {
-        components: {
-            RecommendItem,
-            HotRecommendItem,
-            Navbar,
-            PacketDialog
-        },
-        data() {
-            return {
-                keyword: '',
-                pageNum: 1,
-                pageSize: 10,
-                hotBook: {},
-                bookList: [],
-                loadStatus: 'loadmore',
-                navbarBackground: 'transparent',
-                navbarTitleColor: '#ffffff',
-                navbarIconColor: '#ffffff',
-                sort: 1, // 1-综合 2-价格升序 3-价格降序 4-销量升序 5-销量降序
-                showFilter: false,
-                tempMinPrice: '',
-                tempMaxPrice: '',
-                minPrice: '',
-                maxPrice: '',
-                timestamp: 86400, // 24 hours countdown
+import RecommendItem from '../components/recommend-item/index.vue';
+import HotRecommendItem from '../components/hot-recommend-item/index.vue';
+import Navbar from '@/components/navbar/navbar.vue';
+import PacketDialog from '@/pages-sell/components/packet-dialog/index.vue';
+
+export default {
+    components: {
+        RecommendItem,
+        HotRecommendItem,
+        Navbar,
+        PacketDialog
+    },
+    data() {
+        return {
+            keyword: '',
+            pageNum: 1,
+            pageSize: 10,
+            hotBook: {},
+            bookList: [],
+            loadStatus: 'loadmore',
+            navbarBackground: 'transparent',
+            navbarTitleColor: '#ffffff',
+            navbarIconColor: '#ffffff',
+            sort: 1, // 1-综合 2-价格升序 3-价格降序 4-销量升序 5-销量降序
+            showFilter: false,
+            tempMinPrice: '',
+            tempMaxPrice: '',
+            minPrice: '',
+            maxPrice: '',
+            timestamp: 86400, // 24 hours countdown
+        }
+    },
+    onPullDownRefresh() {
+        this.pageNum = 1;
+        this.loadStatus = 'loading';
+        this.loadData();
+    },
+    onReachBottom() {
+        if (this.loadStatus === 'nomore') return;
+        this.pageNum++;
+        this.loadStatus = 'loading';
+        this.loadData();
+    },
+    onPageScroll(e) {
+        if (e.scrollTop > 50) {
+            this.navbarBackground = '#ffffff';
+            this.navbarTitleColor = '#000000';
+            this.navbarIconColor = '#000000';
+        } else {
+            this.navbarBackground = 'transparent';
+            this.navbarTitleColor = '#ffffff';
+            this.navbarIconColor = '#ffffff';
+        }
+    },
+    onLoad(options) {
+        this.keyword = options.keyword ? decodeURIComponent(options.keyword) : '';
+        this.loadData();
+    },
+    methods: {
+        loadData() {
+            const params = {
+                keyword: this.keyword,
+                pageNum: this.pageNum,
+                pageSize: this.pageSize,
+                sort: this.sort
+            };
+            if (this.minPrice) params.minPrice = this.minPrice;
+            if (this.maxPrice) params.maxPrice = this.maxPrice;
+
+            this.$u.api.getSearchKeywordAjax(params).then(res => {
+                uni.stopPullDownRefresh();
+                const rows = res.data.rows || [];
+                if (this.pageNum === 1) {
+                    this.bookList = rows;
+                } else {
+                    this.bookList = [...this.bookList, ...rows];
+                }
+
+                if (rows.length < this.pageSize) {
+                    this.loadStatus = 'nomore';
+                } else {
+                    this.loadStatus = 'loadmore';
+                }
+
+                if (res.data.couponName) {
+                    this.openPacket({
+                        couponName: res.data.couponName,
+                        faceMoney: res.data.faceMoney,
+                        thresholdMoney: res.data.thresholdMoney,
+                    });
+                }
+            }).catch(() => {
+                uni.stopPullDownRefresh();
+                this.loadStatus = 'loadmore';
+            });
+
+            if (this.pageNum === 1) {
+                this.$u.api.getSearchRecommendAjax().then(res => {
+                    if (res.code == 200) {
+                        res.data.discountDesc = res.data.productPrice ? ((res.data.productPrice / res.data.price) * 10).toFixed(2) + '折' : '';
+                        res.data.discountPrice = res.data.productPrice ? res.data.price - res.data.productPrice : '';
+                        this.hotBook = res.data;
+                    }
+                });
             }
         },
-        onPullDownRefresh() {
+        handleSort(type) {
+            if (type === 1) {
+                if (this.sort === 1) return;
+                this.sort = 1;
+            } else if (type === 'price') {
+                if (this.sort === 2) {
+                    this.sort = 3;
+                } else {
+                    this.sort = 2;
+                }
+            } else if (type === 'sales') {
+                if (this.sort === 5) {
+                    this.sort = 4;
+                } else {
+                    this.sort = 5;
+                }
+            }
             this.pageNum = 1;
             this.loadStatus = 'loading';
             this.loadData();
         },
-        onReachBottom() {
-            if (this.loadStatus === 'nomore') return;
-            this.pageNum++;
+        resetFilter() {
+            this.tempMinPrice = '';
+            this.tempMaxPrice = '';
+        },
+        confirmFilter() {
+            this.minPrice = this.tempMinPrice;
+            this.maxPrice = this.tempMaxPrice;
+            this.showFilter = false;
+            this.pageNum = 1;
             this.loadStatus = 'loading';
             this.loadData();
         },
-        onPageScroll(e) {
-            if (e.scrollTop > 50) {
-                this.navbarBackground = '#ffffff';
-                this.navbarTitleColor = '#000000';
-                this.navbarIconColor = '#000000';
-            } else {
-                this.navbarBackground = 'transparent';
-                this.navbarTitleColor = '#ffffff';
-                this.navbarIconColor = '#ffffff';
-            }
+        goBack() {
+            uni.navigateBack();
         },
-        onLoad(options) {
-            this.keyword = options.keyword ? decodeURIComponent(options.keyword) : '';
+        toFeedback() {
+            uni.navigateTo({
+                url: '/pages-sell/pages/feedback'
+            });
+        },
+        onSearch(val) {
+            console.log('Search:', val);
+            this.keyword = val;
+            this.pageNum = 1;
             this.loadData();
         },
-        methods: {
-            loadData() {
-                const params = {
-                    keyword: this.keyword,
-                    pageNum: this.pageNum,
-                    pageSize: this.pageSize,
-                    sort: this.sort
-                };
-                if (this.minPrice) params.minPrice = this.minPrice;
-                if (this.maxPrice) params.maxPrice = this.maxPrice;
-
-                this.$u.api.getSearchKeywordAjax(params).then(res => {
-                    uni.stopPullDownRefresh();
-                    const rows = res.data.rows || [];
-                    if (this.pageNum === 1) {
-                        this.bookList = rows;
-                    } else {
-                        this.bookList = [...this.bookList, ...rows];
-                    }
-
-                    if (rows.length < this.pageSize) {
-                        this.loadStatus = 'nomore';
-                    } else {
-                        this.loadStatus = 'loadmore';
-                    }
-
-                    if(res.data.couponName){
-                        this.openPacket({
-                            couponName: res.data.couponName,
-                            faceMoney: res.data.faceMoney,
-                            thresholdMoney: res.data.thresholdMoney,
-                        });
-                    }
-                }).catch(() => {
-                    uni.stopPullDownRefresh();
-                    this.loadStatus = 'loadmore';
-                });
-
-                if (this.pageNum === 1) {
-                    this.$u.api.getSearchRecommendAjax().then(res => {
-                        if (res.code == 200) {
-                            res.data.discountDesc = res.data.productPrice ? ((res.data.productPrice / res.data.price) * 10).toFixed(2) + '折' : '';
-                            res.data.discountPrice = res.data.productPrice ? res.data.price - res.data.productPrice : '';
-                            this.hotBook = res.data;
-                        }
-                    });
-                }
-            },
-            handleSort(type) {
-                if (type === 1) {
-                    if (this.sort === 1) return;
-                    this.sort = 1;
-                } else if (type === 'price') {
-                    if (this.sort === 2) {
-                        this.sort = 3;
-                    } else {
-                        this.sort = 2;
-                    }
-                } else if (type === 'sales') {
-                    if (this.sort === 5) {
-                        this.sort = 4;
-                    } else {
-                        this.sort = 5;
-                    }
-                }
-                this.pageNum = 1;
-                this.loadStatus = 'loading';
-                this.loadData();
-            },
-            resetFilter() {
-                this.tempMinPrice = '';
-                this.tempMaxPrice = '';
-            },
-            confirmFilter() {
-                this.minPrice = this.tempMinPrice;
-                this.maxPrice = this.tempMaxPrice;
-                this.showFilter = false;
-                this.pageNum = 1;
-                this.loadStatus = 'loading';
-                this.loadData();
-            },
-            goBack() {
-                uni.navigateBack();
-            },
-            toFeedback() {
-                uni.navigateTo({
-                    url: '/pages-sell/pages/feedback'
-                });
-            },
-            onSearch(val) {
-                console.log('Search:', val);
-                this.keyword = val;
-                this.pageNum = 1;
-                this.loadData();
-            },
-            addToCart(data) {
-                // data now contains { product, quality, quantity } from the popup
-                console.log('Added to cart:', data);
-                uni.showToast({
-                    title: '已加入购物车',
-                    icon: 'success',
-                    duration: 3000
-                });
-            },
-            openPacket(data) {
-                this.$refs.packetDialog.open(data);
-            },
-            closePacket() {
-                this.$refs.packetDialog.close();
+        addToCart(data) {
+            // data now contains { product, quality, quantity } from the popup
+            console.log('Added to cart:', data);
+            uni.showToast({
+                title: '已加入购物车',
+                icon: 'success',
+                duration: 3000
+            });
+        },
+        openPacket(data) {
+            this.$refs.packetDialog.open(data);
+        },
+        closePacket() {
+            this.$refs.packetDialog.close();
+        }
+    },
+    onShareAppMessage(res) {
+        if (res.from === "button" && res.target && res.target.dataset && res.target.dataset.shareType === "reduce") {
+            let reduceCode = uni.getStorageSync("reduceCodeShare");
+            if (this.$u && this.$u.api && this.$u.api.goToReduceShareAjax) {
+                this.$u.api.goToReduceShareAjax({ reduceCode: reduceCode });
+            } else {
+                uni.$u && uni.$u.http && uni.$u.http.get('/token/shop/order/goToShare', { reduceCode: reduceCode });
             }
+            return {
+                title: "快来帮我减钱买书吧!",
+                path: "/pages/home/index?reduceCode=" + reduceCode,
+                imageUrl: "https://shuhi.oss-cn-qingdao.aliyuncs.com/mini/share.jpg",
+                desc: "书嗨,专注于书籍交易的平台,提供新书和二手书的买卖服务",
+            };
         }
+        return {
+            title: "书嗨",
+            path: "/pages-sell/pages/search-result?keyword=" + (this.keyword || ""),
+        };
     }
+}
 </script>
 
 <style lang="scss" scoped>
-    .search-result-page {
-        min-height: 100vh;
-        background-color: #F6F6F6;
-        font-family: 'Source Han Sans SC', sans-serif;
-        position: relative;
-    }
-
-    /* 顶部大背景图 */
-    .top-bg-image {
-        position: fixed;
-        top: 0;
-        left: 0;
+.search-result-page {
+    min-height: 100vh;
+    background-color: #F6F6F6;
+    font-family: 'Source Han Sans SC', sans-serif;
+    position: relative;
+}
+
+/* 顶部大背景图 */
+.top-bg-image {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    z-index: 0;
+    display: block;
+}
+
+.search-bar-wrapper {
+    position: relative;
+    z-index: 2;
+    display: flex;
+    align-items: center;
+    padding: 0 30rpx;
+    height: 88rpx;
+    width: 100%;
+}
+
+.banner-section {
+    position: relative;
+    width: 100%;
+    z-index: 1;
+    padding: 10rpx 30rpx;
+
+    .top-banner {
         width: 100%;
-        z-index: 0;
         display: block;
     }
+}
 
-    .search-bar-wrapper {
-        position: relative;
-        z-index: 2;
-        display: flex;
-        align-items: center;
-        padding: 0 30rpx;
-        height: 88rpx;
-        width: 100%;
-    }
+.content-area {
+    position: relative;
+    z-index: 2;
+    padding: 30rpx 30rpx;
+    border-radius: 30rpx 30rpx 0 0;
+    min-height: 500rpx;
 
-    .banner-section {
-        position: relative;
-        width: 100%;
-        z-index: 1;
-        padding: 10rpx 30rpx;
+    .section-block {
+        margin-bottom: 30rpx;
+        background-color: #fff;
+        padding: 30rpx 24rpx;
+        border-radius: 20rpx;
 
-        .top-banner {
-            width: 100%;
+        .section-title {
+            font-size: 32rpx;
+            font-weight: bold;
+            color: #333;
+            margin-bottom: 20rpx;
             display: block;
         }
     }
+}
 
-    .content-area {
-        position: relative;
-        z-index: 2;
-        padding: 30rpx 30rpx;
-        border-radius: 30rpx 30rpx 0 0;
-        min-height: 500rpx;
-
-        .section-block {
-            margin-bottom: 30rpx;
-            background-color: #fff;
-            padding: 30rpx 24rpx;
-            border-radius: 20rpx;
-
-            .section-title {
-                font-size: 32rpx;
-                font-weight: bold;
-                color: #333;
-                margin-bottom: 20rpx;
-                display: block;
-            }
-        }
-    }
+.filter-bar {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 20rpx;
 
-    .filter-bar {
+    .filter-item {
         display: flex;
-        justify-content: space-between;
         align-items: center;
-        margin-bottom: 20rpx;
-
-        .filter-item {
-            display: flex;
-            align-items: center;
-            font-size: 28rpx;
-            color: #666;
-
-            &.active {
-                color: #333;
-                font-weight: bold;
-
-                .triangle-icon {
-                    border-top-color: #333;
-                }
-            }
+        font-size: 28rpx;
+        color: #666;
 
-            text {
-                margin-right: 6rpx;
-            }
+        &.active {
+            color: #333;
+            font-weight: bold;
 
             .triangle-icon {
-                width: 0;
-                height: 0;
-                border-left: 8rpx solid transparent;
-                border-right: 8rpx solid transparent;
-                border-top: 10rpx solid #666;
-            }
-
-            .sort-icons {
-                display: flex;
-                flex-direction: column;
-                margin-left: 4rpx;
-                justify-content: center;
-                gap: 4rpx;
-                
-                u-icon {
-                    margin: -2rpx 0;
-                }
-            }
-
-            .icon-filter {
-                width: 24rpx;
-                height: 24rpx;
-                margin-left: 4rpx;
+                border-top-color: #333;
             }
         }
-    }
 
-    .book-list {
-        background: #fff;
-        border-radius: 20rpx;
-        padding: 0 24rpx;
-        padding-bottom: 40rpx;
-    }
+        text {
+            margin-right: 6rpx;
+        }
 
-    .filter-popup {
-        background-color: #fff;
-        height: 100%;
-        display: flex;
-        flex-direction: column;
+        .triangle-icon {
+            width: 0;
+            height: 0;
+            border-left: 8rpx solid transparent;
+            border-right: 8rpx solid transparent;
+            border-top: 10rpx solid #666;
+        }
 
-        .filter-content {
-            flex: 1;
-            padding: 30rpx;
+        .sort-icons {
+            display: flex;
+            flex-direction: column;
+            margin-left: 4rpx;
+            justify-content: center;
+            gap: 4rpx;
 
-            .filter-title {
-                font-size: 30rpx;
-                font-weight: bold;
-                color: #333;
-                margin-bottom: 30rpx;
+            u-icon {
+                margin: -2rpx 0;
             }
+        }
 
-            .price-inputs {
-                display: flex;
-                align-items: center;
-                justify-content: space-between;
-
-                u-input {
-                    flex: 1;
-                }
-
-                .divider {
-                    margin: 0 20rpx;
-                    color: #999;
-                }
-            }
+        .icon-filter {
+            width: 24rpx;
+            height: 24rpx;
+            margin-left: 4rpx;
+        }
+    }
+}
+
+.book-list {
+    background: #fff;
+    border-radius: 20rpx;
+    padding: 0 24rpx;
+    padding-bottom: 40rpx;
+}
+
+.filter-popup {
+    background-color: #fff;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+
+    .filter-content {
+        flex: 1;
+        padding: 30rpx;
+
+        .filter-title {
+            font-size: 30rpx;
+            font-weight: bold;
+            color: #333;
+            margin-bottom: 30rpx;
         }
 
-        .filter-footer {
+        .price-inputs {
             display: flex;
-            height: 100rpx;
+            align-items: center;
+            justify-content: space-between;
 
-            .btn {
+            u-input {
                 flex: 1;
-                display: flex;
-                align-items: center;
-                justify-content: center;
-                font-size: 32rpx;
-
-                &.reset {
-                    background-color: #fff;
-                    color: #666;
-                    border-top: 1rpx solid #eee;
-                }
+            }
 
-                &.confirm {
-                    background-color: #38C148;
-                    color: #fff;
-                }
+            .divider {
+                margin: 0 20rpx;
+                color: #999;
             }
         }
     }
 
-    .red-packet-float {
-        position: fixed;
-        bottom: 200rpx;
-        right: 40rpx;
-        z-index: 100;
+    .filter-footer {
         display: flex;
-        flex-direction: column;
-        align-items: center;
+        height: 100rpx;
 
-        .time-badge {
-            background: #FFE173;
-            color: #DF1407;
-            font-size: 18rpx;
-            padding: 4rpx 10rpx;
-            border-radius: 10rpx;
-            position: absolute;
-            top: -40rpx;
-            right: -20rpx;
-            white-space: nowrap;
-            z-index: 2;
+        .btn {
+            flex: 1;
             display: flex;
             align-items: center;
+            justify-content: center;
+            font-size: 32rpx;
+
+            &.reset {
+                background-color: #fff;
+                color: #666;
+                border-top: 1rpx solid #eee;
+            }
 
-            text {
-                margin-right: 4rpx;
+            &.confirm {
+                background-color: #38C148;
+                color: #fff;
             }
         }
+    }
+}
+
+.red-packet-float {
+    position: fixed;
+    bottom: 200rpx;
+    right: 40rpx;
+    z-index: 100;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+
+    .time-badge {
+        background: #FFE173;
+        color: #DF1407;
+        font-size: 18rpx;
+        padding: 4rpx 10rpx;
+        border-radius: 10rpx;
+        position: absolute;
+        top: -40rpx;
+        right: -20rpx;
+        white-space: nowrap;
+        z-index: 2;
+        display: flex;
+        align-items: center;
 
-        .packet-img {
-            width: 100rpx;
-            height: 120rpx;
+        text {
+            margin-right: 4rpx;
         }
     }
+
+    .packet-img {
+        width: 100rpx;
+        height: 120rpx;
+    }
+}
 </style>

+ 21 - 0
pages-sell/pages/topic.vue

@@ -121,6 +121,27 @@
 					}
 				});
 			}
+		},
+		onShareAppMessage(res) {
+			if (res.from === "button" && res.target && res.target.dataset && res.target.dataset.shareType === "reduce") {
+				let reduceCode = uni.getStorageSync("reduceCodeShare");
+				if (this.$u && this.$u.api && this.$u.api.goToReduceShareAjax) {
+					this.$u.api.goToReduceShareAjax({ reduceCode: reduceCode });
+				} else {
+					uni.$u && uni.$u.http && uni.$u.http.get('/token/shop/order/goToShare', { reduceCode: reduceCode });
+				}
+				return {
+					title: "快来帮我减钱买书吧!",
+					path: "/pages/home/index?reduceCode=" + reduceCode,
+					imageUrl: "https://shuhi.oss-cn-qingdao.aliyuncs.com/mini/share.jpg",
+					desc: "书嗨,专注于书籍交易的平台,提供新书和二手书的买卖服务",
+				};
+			}
+			return {
+				title: this.showName || '图书专题',
+				path: `/pages-sell/pages/topic?cateId=${this.cateId}`,
+				imageUrl: this.imageUrl || ''
+			};
 		}
 	}
 </script>

BIN
pages-sell/static/select.png


+ 2 - 1
pages.json

@@ -1,6 +1,7 @@
 {
     "easycom": {
-        "^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue"
+        "^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue",
+        "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
     },
     "pages": [
         {

+ 1 - 9
pages/cart/index.vue

@@ -34,15 +34,7 @@
         // 分享配置
         onShareAppMessage(res) {
             console.log(res, '分享');
-            if (res && res.from === 'button' && res.target && res.target.dataset && res.target.dataset.shareType === 'product') {
-                const dataset = res.target.dataset;
-                return {
-                    title: dataset.title || '',
-                    path: `/pages-sell/pages/detail?isbn=${dataset.isbn}`,
-                    imageUrl: dataset.image || ''
-                };
-            }
-            if (res.from === "button") {
+            if (res.from === "button" && res.target && res.target.dataset && res.target.dataset.shareType === "reduce") {
                 let reduceCode = uni.getStorageSync("reduceCodeShare");
                 // 调用分享接口
                 // 使用 uni.$u 确保可用性,避免 this.$u 在某些上下文不可用

+ 2 - 3
pages/home/components/upsell-book.vue

@@ -52,9 +52,8 @@
               <view class="add-text">{{ formatName(item.nickName) }}</view>
             </view>
 
-            <button v-else open-type="share" class="hand-btn">
+            <button v-else open-type="share" data-share-type="upsell" class="hand-btn">
               <image
-              open-type="share"
                 class="hand-icon"
                 src="/static/img/activity/invite.png"
                 mode="widthFix"
@@ -66,7 +65,7 @@
 
       <!-- 分享按钮 -->
       <view class="action-buttons">
-        <button class="share-button" @click="shareAction" open-type="share">
+        <button class="share-button" data-share-type="upsell" @click="shareAction" open-type="share">
           立即分享
         </button>
         <button class="scan-button" @click="scanAction">扫码助力</button>

+ 29 - 11
pages/home/index.vue

@@ -227,16 +227,8 @@ export default {
         });
     },
     // 分享配置
-        onShareAppMessage(res) {
-            if (res && res.from === 'button' && res.target && res.target.dataset && res.target.dataset.shareType === 'product') {
-                const dataset = res.target.dataset;
-                return {
-                    title: dataset.title || '',
-                    path: `/pages-sell/pages/detail?isbn=${dataset.isbn}`,
-                    imageUrl: dataset.image || ''
-                };
-            }
-            if (res.from === "button") {
+    onShareAppMessage(res) {
+        if (res.from === "button" && res.target && res.target.dataset && res.target.dataset.shareType === "upsell") {
             let upsellCode = uni.getStorageSync("upsellCodeShare");
             console.log(upsellCode, "分享");
             // 调用分享接口
@@ -247,6 +239,19 @@ export default {
                 imageUrl: "https://shuhi.oss-cn-qingdao.aliyuncs.com/mini/share.jpg",
                 desc: "书嗨,专注于书籍交易的平台,提供新书和二手书的买卖服务",
             };
+        } else if (res.from === "button" && res.target && res.target.dataset && res.target.dataset.shareType === "reduce") {
+            let reduceCode = uni.getStorageSync("reduceCodeShare");
+            if (uni.$u && uni.$u.api && uni.$u.api.goToReduceShareAjax) {
+                uni.$u.api.goToReduceShareAjax({ reduceCode: reduceCode });
+            } else {
+                uni.$u && uni.$u.http && uni.$u.http.get('/token/shop/order/goToShare', { reduceCode: reduceCode });
+            }
+            return {
+                title: "快来帮我减钱买书吧!",
+                path: "/pages/home/index?reduceCode=" + reduceCode,
+                imageUrl: "https://shuhi.oss-cn-qingdao.aliyuncs.com/mini/share.jpg",
+                desc: "书嗨,专注于书籍交易的平台,提供新书和二手书的买卖服务",
+            };
         } else {
             return {
                 title: "书嗨",
@@ -257,7 +262,7 @@ export default {
 
     // 分享到朋友圈
     onShareTimeline(res) {
-        if (res.from === "button") {
+        if (res.from === "button" && res.target && res.target.dataset && res.target.dataset.shareType === "upsell") {
             let upsellCode = uni.getStorageSync("upsellCodeShare");
             // 调用分享接口
             uni.$u.http.get("/token/order/goToShare?upsellCode=" + upsellCode);
@@ -267,6 +272,19 @@ export default {
                 imageUrl: "https://shuhi.oss-cn-qingdao.aliyuncs.com/mini/share.jpg",
                 desc: "书嗨,专注于书籍交易的平台,提供新书和二手书的买卖服务",
             };
+        } else if (res.from === "button" && res.target && res.target.dataset && res.target.dataset.shareType === "reduce") {
+            let reduceCode = uni.getStorageSync("reduceCodeShare");
+            if (uni.$u && uni.$u.api && uni.$u.api.goToReduceShareAjax) {
+                uni.$u.api.goToReduceShareAjax({ reduceCode: reduceCode });
+            } else {
+                uni.$u && uni.$u.http && uni.$u.http.get('/token/shop/order/goToShare', { reduceCode: reduceCode });
+            }
+            return {
+                title: "快来帮我减钱买书吧!",
+                path: "/pages/home/index?reduceCode=" + reduceCode,
+                imageUrl: "https://shuhi.oss-cn-qingdao.aliyuncs.com/mini/share.jpg",
+                desc: "书嗨,专注于书籍交易的平台,提供新书和二手书的买卖服务",
+            };
         } else {
             return {
                 title: "书嗨",

+ 2 - 2
pages/sell/index.vue

@@ -28,8 +28,8 @@ export default {
 	},
 	onPageScroll(e) {
 		const comp = this.$refs.sellContainer;
-		if (!comp) return;
-		comp.scrollTop = e.scrollTop;
+		if (!comp || !comp.onPageScroll) return;
+		comp.onPageScroll(e.scrollTop);
 	},
 	methods: {
 		

+ 1 - 9
uview-ui/libs/mixin/mpShare.js

@@ -7,15 +7,7 @@ module.exports = {
 			imageUrl: '' // 默认为当前页面的截图
 		}
 	},
-	onShareAppMessage(res) {
-		if (res && res.from === 'button' && res.target && res.target.dataset && res.target.dataset.shareType === 'product') {
-			const dataset = res.target.dataset;
-			return {
-				title: dataset.title || '',
-				path: `/pages-sell/pages/detail?isbn=${dataset.isbn}`,
-				imageUrl: dataset.image || ''
-			}
-		}
+	onShareAppMessage() {
 		return this.$u.mpShare
 	},
 	// #ifdef MP-WEIXIN