Browse Source

feat: 实现购物车商品减价分享功能

新增减价分享弹窗组件及分享逻辑,支持用户邀请好友助力减价
- 在购物车商品项添加倒计时组件,显示减价剩余时间
- 新增减价分享弹窗、二维码弹窗组件
- 扩展API接口,支持减价分享相关功能
- 在首页和购物车页面集成减价分享逻辑
- 修复upsell-book组件中needInviteNum字段名错误
ylong 1 day ago
parent
commit
8775adff49

+ 15 - 0
api/modules/mall.js

@@ -73,5 +73,20 @@ export const useMallApi = (Vue, vm) => {
 
         // 修改退款申请
         refundApplyModifyAjax: (data) => vm.$u.post('/token/shop/order/refundApplyModify', data),
+
+        // 减钱分享信息
+        clickReduceInviteAjax: (params) => vm.$u.get('/token/shop/order/clickReduceInvite', params),
+        
+        // 减钱二维码
+        getReduceQrcodeAjax: (params) => vm.$u.get('/token/shop/order/getReduceQrcode', params),
+        
+        // 减钱助力查询
+        reduceHelpQueryAjax: (reduceCode) => vm.$u.post('/token/shop/order/inviteHelpQuery?reduceCode=' + reduceCode),
+        
+        // 减钱助力点击
+        reduceClickHelpAjax: (data) => vm.$u.post('/token/shop/order/inviteClickHelp', data),
+        
+        // 减钱去分享
+        goToReduceShareAjax: (params) => vm.$u.get('/token/shop/order/goToShare', params),
 	}
 }

+ 26 - 0
pages-car/components/cart-item.vue

@@ -39,6 +39,13 @@
                 <view class="tag orange-tag" v-if="canReduce" @click.stop="handleReduce">
                     <text>可降¥{{ item.reduceMoney }}</text>
                 </view>
+
+                <!-- 倒计时 -->
+                <view class="countdown-wrap" v-if="item.restTime > 0">
+                    <text>减价即将结束</text>
+                    <u-count-down :timestamp="item.restTime" format="HH:mm:ss" autoStart color="#db0702" font-size="24"
+                        separator-color="#db0702" separator-size="24" @finish="onCountdownFinish"></u-count-down>
+                </view>
             </view>
 
             <!-- 底部价格和操作 -->
@@ -106,6 +113,9 @@
             },
             handleSelectCondition() {
                 this.$emit('selectCondition', this.item);
+            },
+            onCountdownFinish() {
+                this.$emit('countdown-finish', this.item);
             }
         }
     };
@@ -193,6 +203,10 @@
             flex-direction: column;
             justify-content: space-between;
 
+            ::v-deep .u-countdown-colon {
+                font-size: 24rpx !important;
+            }
+
             .title-row {
                 display: flex;
                 justify-content: space-between;
@@ -259,6 +273,18 @@
                     margin-right: 10rpx;
                     order: -1; // 移到前面
                 }
+
+                .countdown-wrap {
+                    display: flex;
+                    align-items: center;
+                    font-size: 24rpx !important;
+                    color: #db0702;
+                    margin-left: 6rpx;
+
+                    text {
+                        margin-right: 6rpx;
+                    }
+                }
             }
 
             .bottom-row {

+ 299 - 319
pages-car/components/price-reduction-popup.vue

@@ -1,327 +1,307 @@
 <template>
-  <custom-popup
-    v-model="showPopup"
-    mode="center"
-    border-radius="24"
-    width="650rpx"
-    :bg-color="'transparent'"
-  >
-    <view class="popup-container">
-      <!-- 顶部黄色手掌图标和标题 -->
-      <view class="header">
-        <!-- <image src="/static/img/activity/hand.png" class="hand-icon"></image> -->
-        <view class="title-text">你真的太幸运了</view>
-        <view class="title-text">恭喜你获得限时减价权益</view>
-      </view>
-
-      <!-- 绿色价格信息区域 -->
-      <view class="price-section">
-        <view class="price-row">
-          <text class="price-label">此书当前价格</text>
-          <text class="price-value">¥ {{ bookInfo.price || 0 }}</text>
-        </view>
-        <view class="price-row">
-          <text class="price-label">助力成功减至</text>
-          <text class="price-value increased"
-            >¥ {{ bookInfo.reducedPrice || 0 }}</text
-          >
-          <image
-            class="up-icon"
-            src="/static/img/activity/up2.png"
-            mode="widthFix"
-            style="transform: rotate(180deg);" 
-          ></image>
-        </view>
-        <view class="small-text"
-          >实际金额以最终下单为准,活动时间{{
-            formatDate(bookInfo.startTime)
-          }}至{{ formatDate(bookInfo.endTime) }}</view
-        >
-      </view>
-
-      <!-- 分享助力区域 -->
-      <view class="share-section">
-        <view class="share-text">分享{{ inviteUsers.length }}位好友砍价</view>
-        <view class="add-button">
-          <block v-for="(item, index) in inviteUsers" :key="index">
-            <view class="add-item" v-if="item.imgPath">
-              <image
-                class="hand-icon"
-                :src="item.imgPath"
-                mode="widthFix"
-              ></image>
-              <view class="add-text">{{ formatName(item.nickName) }}</view>
-            </view>
-
-            <button v-else open-type="share" class="hand-btn">
-              <image
-              open-type="share"
-                class="hand-icon"
-                src="/static/img/activity/invite.png"
-                mode="widthFix"
-              ></image>
-            </button>
-          </block>
-        </view>
-      </view>
-
-      <!-- 分享按钮 -->
-      <view class="action-buttons">
-        <button class="share-button" @click="shareAction" open-type="share">
-          立即分享
-        </button>
-        <button class="scan-button" @click="scanAction">扫码砍价</button>
-      </view>
-
-      <!-- 关闭按钮 -->
-      <view class="close-button" @click="closePopup">
-        <image src="/static/img/activity/close2.png" mode="widthFix"></image>
-      </view>
-    </view>
-  </custom-popup>
+	<custom-popup v-model="showPopup" mode="center" border-radius="24" width="650rpx" :bg-color="'transparent'">
+		<view class="popup-container">
+			<!-- 顶部黄色手掌图标和标题 -->
+			<view class="header">
+				<!-- <image src="/static/img/activity/hand.png" class="hand-icon"></image> -->
+				<view class="title-text">你真的太幸运了</view>
+				<view class="title-text">恭喜你获得限时减价权益</view>
+			</view>
+
+			<!-- 绿色价格信息区域 -->
+			<view class="price-section">
+				<view class="price-row">
+					<text class="price-label">此书当前价格</text>
+					<text class="price-value">¥ {{ bookInfo.price || 0 }}</text>
+				</view>
+				<view class="price-row">
+					<text class="price-label">助力成功减至</text>
+					<text class="price-value increased">¥ {{ bookInfo.reduceMoney || 0 }}</text>
+					<image class="up-icon" src="/static/img/activity/up2.png" mode="widthFix"
+						style="transform: rotate(180deg);">
+					</image>
+				</view>
+				<view class="small-text">实际金额以最终下单为准,活动时间{{
+					formatDate(bookInfo.startTime)
+				}}至{{ formatDate(bookInfo.endTime) }}</view>
+			</view>
+
+			<!-- 分享助力区域 -->
+			<view class="share-section">
+				<view class="share-text">分享{{ inviteUsers.length }}位好友砍价</view>
+				<view class="add-button">
+					<block v-for="(item, index) in inviteUsers" :key="index">
+						<view class="add-item" v-if="item.imgPath">
+							<image class="hand-icon" :src="item.imgPath" mode="widthFix"></image>
+							<view class="add-text">{{ formatName(item.nickName) }}</view>
+						</view>
+
+						<button v-else open-type="share" class="hand-btn">
+							<image open-type="share" class="hand-icon" src="/static/img/activity/invite.png" mode="widthFix"></image>
+						</button>
+					</block>
+				</view>
+			</view>
+
+			<!-- 分享按钮 -->
+			<view class="action-buttons">
+				<button class="share-button" @click="shareAction" open-type="share">
+					立即分享
+				</button>
+				<button class="scan-button" @click="scanAction">扫码砍价</button>
+			</view>
+
+			<!-- 关闭按钮 -->
+			<view class="close-button" @click="closePopup">
+				<image src="/static/img/activity/close2.png" mode="widthFix"></image>
+			</view>
+		</view>
+	</custom-popup>
 </template>
 
 <script>
-import customPopup from "@/components/custom-popup.vue";
-export default {
-  components: {
-    customPopup,
-  },
-  data() {
-    return {
-      showPopup: false,
-      bookInfo: {},
-      inviteUsers: [],
-    };
-  },
-  methods: {
-    open(data) {
-      this.showPopup = true;
-      this.getIsbnInfo(data.isbn, data.orderId);
-    },
-    //获取信息
-    getIsbnInfo(isbn, orderId) {
-      uni.$u.http
-        .get(`/token/order/clickUpsellInvite?isbn=${isbn}&orderId=${orderId}`)
-        .then((res) => {
-          if (res.code == 200) {
-            this.bookInfo = res.data;
-            let needInviteNum = res.data.needInviteNum;
-            let inviteUsers = res.data.inviteUsers || [];
-            let length = inviteUsers.length;
-            for (let index = 0; index < needInviteNum - length; index++) {
-              inviteUsers.push({
-                nickName: "",
-                imgPath: "",
-              });
-            }
-            this.inviteUsers = inviteUsers;
-            uni.setStorageSync("upsellCodeShare", res.data.upsellCode);
-          } else {
-            uni.$u.toast(res.msg);
-          }
-        });
-    },
-    // 转换时间的方法,将年月日时分秒转换成 3/25 格式
-    formatDate(dateString) {
-      if (!dateString) return "";
-
-      const date = new Date(dateString);
-      const month = date.getMonth() + 1; // 月份从0开始,需要+1
-      const day = date.getDate();
-
-      return `${month}/${day}`;
-    },
-
-    //格式化 name,长度大于 3,只保留第一个和最后一个字,中间最多使用三个 *代替
-    // 长度小于 3,只保留第一个字
-    formatName(name) {
-      if (!name) return "";
-      if (name.length > 2) {
-        return name.slice(0, 1) + "*" + name.slice(-1);
-      } else {
-        return name.slice(0, 1) + "*";
-      }
-    },
-
-    closePopup() {
-      this.showPopup = false;
-    },
-    shareAction() {
-      this.$emit("share", this.bookInfo);
-    },
-    scanAction() {
-      this.$emit("scan", this.bookInfo);
-    },
-  },
-};
+	import customPopup from "@/components/custom-popup.vue";
+	export default {
+		components: {
+			customPopup,
+		},
+		data() {
+			return {
+				showPopup: false,
+				bookInfo: {},
+				inviteUsers: [],
+			};
+		},
+		methods: {
+			open(data) {
+				this.showPopup = true;
+				this.getIsbnInfo(data.isbn);
+			},
+			//获取信息
+			getIsbnInfo(isbn) {
+				this.$u.api.clickReduceInviteAjax({
+					isbn: isbn,
+				}).then((res) => {
+					if (res.code == 200) {
+						this.bookInfo = res.data;
+						let needInviteNum = res.data.maxInviteNum;
+						let inviteUsers = res.data.inviteUsers || [];
+						let length = inviteUsers.length;
+						for (let index = 0; index < needInviteNum - length; index++) {
+							inviteUsers.push({
+								nickName: "",
+								imgPath: "",
+							});
+						}
+						this.inviteUsers = inviteUsers;
+						uni.setStorageSync("reduceCodeShare", res.data.reduceCode);
+					} else {
+						uni.$u.toast(res.msg);
+					}
+				});
+			},
+			// 转换时间的方法,将年月日时分秒转换成 3/25 格式
+			formatDate(dateString) {
+				if (!dateString) return "";
+
+				const date = new Date(dateString);
+				const month = date.getMonth() + 1; // 月份从0开始,需要+1
+				const day = date.getDate();
+
+				return `${month}/${day}`;
+			},
+
+			//格式化 name,长度大于 3,只保留第一个和最后一个字,中间最多使用三个 *代替
+			// 长度小于 3,只保留第一个字
+			formatName(name) {
+				if (!name) return "";
+				if (name.length > 2) {
+					return name.slice(0, 1) + "*" + name.slice(-1);
+				} else {
+					return name.slice(0, 1) + "*";
+				}
+			},
+
+			closePopup() {
+				this.showPopup = false;
+			},
+			shareAction() {
+				this.$emit("share", this.bookInfo);
+			},
+			scanAction() {
+				this.$emit("scan", this.bookInfo);
+			},
+		},
+	};
 </script>
 
 <style lang="scss" scoped>
-.popup-container {
-  position: relative;
-  padding: 30rpx;
-  box-sizing: border-box;
-  padding-bottom: 50rpx;
-  background: url("https://shuhi.oss-cn-qingdao.aliyuncs.com/mini/bg2.png")
-    no-repeat center center;
-  background-size: 100% 100%;
-}
-
-.header {
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  padding: 20rpx 0 10rpx;
-  padding-top: 160rpx;
-
-  .title-text {
-    font-size: 38rpx;
-    font-weight: bold;
-    color: #000;
-    margin-bottom: 10rpx;
-  }
-
-  .subtitle-text {
-    font-size: 32rpx;
-    color: #000;
-  }
-
-  .hand-icon {
-    width: 140rpx;
-    height: 140rpx;
-    position: relative;
-    top: -30rpx;
-  }
-}
-
-.price-section {
-  background-color: #39c248;
-  border-radius: 16rpx;
-  padding: 20rpx 30rpx;
-  margin: 20rpx 0;
-
-  .price-row {
-    display: flex;
-    align-items: center;
-
-    .price-label {
-      color: #ffffff;
-      font-size: 30rpx;
-    }
-
-    .price-value {
-      color: #ffeb3b;
-      font-size: 30rpx;
-      font-weight: bold;
-      margin-left: 10rpx;
-    }
-
-    .increased {
-      font-size: 42rpx;
-    }
-
-    .up-icon {
-      width: 30rpx;
-      height: 30rpx;
-      margin-left: 5rpx;
-    }
-  }
-
-  .small-text {
-    color: #ffffff;
-    font-size: 22rpx;
-    margin-top: 10rpx;
-  }
-}
-
-.share-section {
-  background-color: #e8f8e8;
-  border-radius: 16rpx;
-  padding: 30rpx;
-  margin: 20rpx 0;
-
-  .share-text {
-    color: #39c248;
-    font-size: 32rpx;
-    text-align: center;
-    margin-bottom: 30rpx;
-  }
-
-  .add-button {
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    gap: 10rpx;
-
-    .hand-icon {
-      width: 100rpx;
-      height: 100rpx;
-    }
-  }
-  .hand-btn{
-    display: inline-block;
-    width: 100rpx !important;
-    height: 110rpx;
-    background: transparent;
-    flex: none;
-    padding: 0;
-  }
-
-  .add-item {
-    position: relative;
-    .add-text {
-      position: absolute;
-      bottom: 2rpx;
-      left: 5rpx;
-      font-size: 24rpx;
-      background: #39c248;
-      text-align: center;
-      color: #fff;
-      padding: 0 10rpx;
-      border-radius: 20rpx;
-      display: inline-block;
-      width: 94rpx;
-    }
-  }
-}
-
-.action-buttons {
-  margin-top: 30rpx;
-
-  .share-button {
-    height: 90rpx;
-    background: linear-gradient(to bottom, #47d46c, #24ad3c) !important;
-    margin-bottom: 24rpx;
-    font-size: 32rpx;
-    color: #ffffff;
-    border-radius: 10rpx;
-    line-height: 90rpx;
-  }
-
-  .scan-button {
-    height: 90rpx;
-    font-size: 32rpx;
-    color: #39c248;
-    border: 1rpx solid #39c248;
-    background-color: transparent;
-    border-radius: 10rpx;
-    line-height: 90rpx;
-  }
-  button + button {
-    margin-left: 0;
-  }
-}
-
-.close-button {
-  position: absolute;
-  bottom: -120rpx;
-  left: 50%;
-  transform: translateX(-50%);
-
-  image {
-    width: 70rpx;
-    height: 70rpx;
-  }
-}
+	.popup-container {
+		position: relative;
+		padding: 30rpx;
+		box-sizing: border-box;
+		padding-bottom: 50rpx;
+		background: url("https://shuhi.oss-cn-qingdao.aliyuncs.com/mini/bg2.png") no-repeat center center;
+		background-size: 100% 100%;
+	}
+
+	.header {
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		padding: 20rpx 0 10rpx;
+		padding-top: 160rpx;
+
+		.title-text {
+			font-size: 38rpx;
+			font-weight: bold;
+			color: #000;
+			margin-bottom: 10rpx;
+		}
+
+		.subtitle-text {
+			font-size: 32rpx;
+			color: #000;
+		}
+
+		.hand-icon {
+			width: 140rpx;
+			height: 140rpx;
+			position: relative;
+			top: -30rpx;
+		}
+	}
+
+	.price-section {
+		background-color: #39c248;
+		border-radius: 16rpx;
+		padding: 20rpx 30rpx;
+		margin: 20rpx 0;
+
+		.price-row {
+			display: flex;
+			align-items: center;
+
+			.price-label {
+				color: #ffffff;
+				font-size: 30rpx;
+			}
+
+			.price-value {
+				color: #ffeb3b;
+				font-size: 30rpx;
+				font-weight: bold;
+				margin-left: 10rpx;
+			}
+
+			.increased {
+				font-size: 42rpx;
+			}
+
+			.up-icon {
+				width: 30rpx;
+				height: 30rpx;
+				margin-left: 5rpx;
+			}
+		}
+
+		.small-text {
+			color: #ffffff;
+			font-size: 22rpx;
+			margin-top: 10rpx;
+		}
+	}
+
+	.share-section {
+		background-color: #e8f8e8;
+		border-radius: 16rpx;
+		padding: 30rpx;
+		margin: 20rpx 0;
+
+		.share-text {
+			color: #39c248;
+			font-size: 32rpx;
+			text-align: center;
+			margin-bottom: 30rpx;
+		}
+
+		.add-button {
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			gap: 10rpx;
+
+			.hand-icon {
+				width: 100rpx;
+				height: 100rpx;
+			}
+		}
+
+		.hand-btn {
+			display: inline-block;
+			width: 100rpx !important;
+			height: 110rpx;
+			background: transparent;
+			flex: none;
+			padding: 0;
+		}
+
+		.add-item {
+			position: relative;
+
+			.add-text {
+				position: absolute;
+				bottom: 2rpx;
+				left: 5rpx;
+				font-size: 24rpx;
+				background: #39c248;
+				text-align: center;
+				color: #fff;
+				padding: 0 10rpx;
+				border-radius: 20rpx;
+				display: inline-block;
+				width: 94rpx;
+			}
+		}
+	}
+
+	.action-buttons {
+		margin-top: 30rpx;
+
+		.share-button {
+			height: 90rpx;
+			background: linear-gradient(to bottom, #47d46c, #24ad3c) !important;
+			margin-bottom: 24rpx;
+			font-size: 32rpx;
+			color: #ffffff;
+			border-radius: 10rpx;
+			line-height: 90rpx;
+		}
+
+		.scan-button {
+			height: 90rpx;
+			font-size: 32rpx;
+			color: #39c248;
+			border: 1rpx solid #39c248;
+			background-color: transparent;
+			border-radius: 10rpx;
+			line-height: 90rpx;
+		}
+
+		button+button {
+			margin-left: 0;
+		}
+	}
+
+	.close-button {
+		position: absolute;
+		bottom: -120rpx;
+		left: 50%;
+		transform: translateX(-50%);
+
+		image {
+			width: 70rpx;
+			height: 70rpx;
+		}
+	}
 </style>

+ 132 - 0
pages-car/components/reduce-qrcode.vue

@@ -0,0 +1,132 @@
+<template>
+	<custom-popup v-model="showPopup" mode="center" border-radius="24" width="650rpx" :bg-color="'transparent'">
+		<view class="popup-container">
+			<!-- 顶部标题 -->
+			<view class="header">
+				<view class="title-text">
+					让好友打开
+					<!-- #ifdef MP-WEIXIN -->
+					<text class="green">微信</text>
+					<!-- #endif -->
+					<!-- #ifdef MP-ALIPAY -->
+					<text class="green">支付宝</text>
+					<!-- #endif -->
+					扫一扫
+				</view>
+				<view class="subtitle-text">加油!你就要成功了</view>
+			</view>
+
+			<!-- 二维码区域 -->
+			<view class="qrcode-section">
+				<image class="qrcode-img" :src="qrcode" mode="aspectFit"></image>
+			</view>
+
+			<!-- 关闭按钮 -->
+			<view class="close-button" @click="closePopup">
+				<image src="/static/img/activity/close2.png" mode="widthFix"></image>
+			</view>
+		</view>
+	</custom-popup>
+</template>
+
+<script>
+	import customPopup from '@/components/custom-popup.vue';
+	export default {
+		components: {
+			customPopup,
+		},
+		data() {
+			return {
+				showPopup: false,
+				qrcode: '',
+				// 可扩展为自定义图标
+				wechatIcon: false,
+				scanIcon: false,
+				successIcon: false,
+			};
+		},
+		methods: {
+			open(data) {
+				this.showPopup = true;
+				this.getQrcode(data.reduceCode);
+			},
+			//获取二维码
+			getQrcode(reduceCode) {
+				this.$u.api.getReduceQrcodeAjax({ reduceCode: reduceCode }).then(res => {
+					if (res.code == 200) {
+						this.qrcode = res.data;
+					}
+				})
+			},
+			closePopup() {
+				this.showPopup = false;
+			},
+		},
+	};
+</script>
+
+<style lang="scss" scoped>
+	.popup-container {
+		position: relative;
+		padding: 30rpx 30rpx 80rpx 30rpx;
+		box-sizing: border-box;
+		background: url("https://shuhi.oss-cn-qingdao.aliyuncs.com/mini/upsellbg.png") no-repeat center center;
+		background-size: 100% 100%;
+		height: 1020rpx;
+	}
+
+	.header {
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		padding-top: 20rpx;
+
+		.title-text {
+			font-size: 38rpx;
+			font-weight: bold;
+			color: #222;
+			margin-bottom: 10rpx;
+
+			.green {
+				color: #39c248;
+			}
+		}
+
+		.subtitle-text {
+			font-size: 28rpx;
+			color: #666;
+			margin-bottom: 30rpx;
+		}
+	}
+
+	.qrcode-section {
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		height: 400rpx;
+		width: 400rpx;
+		background: #38c249;
+		margin: 30rpx auto;
+		border-radius: 24rpx;
+
+		.qrcode-img {
+			width: 300rpx;
+			height: 300rpx;
+			border-radius: 24rpx;
+			background: #fff;
+			border: 8rpx solid #fff;
+		}
+	}
+
+	.close-button {
+		position: absolute;
+		bottom: -100rpx;
+		left: 50%;
+		transform: translateX(-50%);
+
+		image {
+			width: 70rpx;
+			height: 70rpx;
+		}
+	}
+</style>

+ 56 - 13
pages-car/pages/index.vue

@@ -18,7 +18,7 @@
         </view>
 
         <!-- 为你推荐 -->
-        <view class="recommend-section" v-if="recommendList.length>0">
+        <view class="recommend-section" v-if="recommendList.length > 0">
             <view class="section-title">
                 <text class="line"></text>
                 <text class="text">为你推荐</text>
@@ -64,6 +64,7 @@
 
         <!-- 减钱弹窗 -->
         <price-reduction-popup ref="reducePopup" @share="handleShare" @scan="handleScan"></price-reduction-popup>
+        <reduce-qrcode ref="reduceQrcode"></reduce-qrcode>
 
         <common-dialog ref="reduceDialog" title="温馨提示" @confirm="onNext">
             <text>购物车中有可减钱的商品,如您提交订单,则失去该资格哦~</text>
@@ -74,6 +75,7 @@
 <script>
     import CartItem from '../components/cart-item.vue';
     import PriceReductionPopup from '../components/price-reduction-popup.vue';
+    import ReduceQrcode from '../components/reduce-qrcode.vue';
     import CommonDialog from '@/components/common-dialog.vue';
     import ConditionPopup from '../components/condition-popup.vue';
 
@@ -81,6 +83,7 @@
         components: {
             CartItem,
             PriceReductionPopup,
+            ReduceQrcode,
             CommonDialog,
             ConditionPopup
         },
@@ -107,6 +110,45 @@
         mounted() {
             this.loadData();
         },
+        // 分享配置
+        onShareAppMessage(res) {
+            console.log(res, '分享');
+            if (res.from === "button") {
+                let reduceCode = uni.getStorageSync("reduceCodeShare");
+                // 调用分享接口
+                this.$u.api.goToReduceShareAjax({ 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: "书嗨",
+                    page: "/pages/home/index",
+                };
+            }
+        },
+        // 分享到朋友圈
+        onShareTimeline(res) {
+            if (res.from === "button") {
+                let reduceCode = uni.getStorageSync("reduceCodeShare");
+                // 调用分享接口
+                this.$u.api.goToReduceShareAjax({ 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: "书嗨",
+                    page: "/pages/home/index",
+                };
+            }
+        },
         computed: {
             selectedItems() {
                 return this.cartList.filter(item => item.checked && item.stockStatus !== 3 && item.availableStock > 0);
@@ -194,16 +236,17 @@
                 }
             },
             handleReduce(item) {
-                const popupData = {
-                    price: item.productPrice,
-                    reducedPrice: (item.productPrice - item.reduceMoney).toFixed(2), // 假设 reduceMoney 是单价减少额
-                    startTime: new Date().getTime(),
-                    endTime: new Date().getTime() + (item.restTime || 0) * 1000, // restTime 单位是秒?
-                    upsellCode: 'mock-code'
-                };
-                this.$refs.reducePopup.bookInfo = popupData;
-                this.$refs.reducePopup.showPopup = true;
-                this.$refs.reducePopup.inviteUsers = [];
+                console.log('handleReduce item:', item);
+                this.$nextTick(() => {
+                    if (this.$refs.reducePopup) {
+                        this.$refs.reducePopup.open({
+                            isbn: item.isbn,
+                            orderId: item.id
+                        });
+                    } else {
+                        console.error('reducePopup ref not found');
+                    }
+                });
             },
             onAllCheckChange(e) {
                 const checked = e.value;
@@ -282,8 +325,8 @@
             handleShare() {
                 console.log('share');
             },
-            handleScan() {
-                console.log('scan');
+            handleScan(bookInfo) {
+                this.$refs.reduceQrcode.open(bookInfo);
             },
             handleDelete(item) {
                 uni.showModal({

+ 69 - 15
pages/cart/index.vue

@@ -5,26 +5,80 @@
 </template>
 
 <script>
-export default {
-    data() {
-        return {
+    export default {
+        data() {
+            return {
 
-        }
-    },
-    onShow() {
-        // 每次显示页面时,调用子组件的刷新方法
-        this.$nextTick(() => {
-            if (this.$refs.cartContainer) {
-                this.$refs.cartContainer.loadData();
             }
-        });
-    },
-    methods: {
+        },
+        onShow() {
+            // 每次显示页面时,调用子组件的刷新方法
+            this.$nextTick(() => {
+                if (this.$refs.cartContainer) {
+                    this.$refs.cartContainer.loadData();
+                }
+            });
+        },
+        // 分享配置
+        onShareAppMessage(res) {
+            console.log(res, '分享');
+            if (res.from === "button") {
+                let reduceCode = uni.getStorageSync("reduceCodeShare");
+                // 调用分享接口
+                // 使用 uni.$u 确保可用性,避免 this.$u 在某些上下文不可用
+                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: "书嗨,专注于书籍交易的平台,提供新书和二手书的买卖服务",
+                };
+            } else {
+                return {
+                    title: "书嗨",
+                    page: "/pages/cart/index",
+                };
+            }
+        },
+        // 分享到朋友圈
+        onShareTimeline(res) {
+            if (res.from === "button") {
+                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: "书嗨,专注于书籍交易的平台,提供新书和二手书的买卖服务",
+                };
+            } else {
+                return {
+                    title: "书嗨",
+                    page: "/pages/cart/index",
+                };
+            }
+        },
+        methods: {
+
+        }
     }
-}
 </script>
 
 <style>
-/* Empty style as content is in the component */
+    /* Empty style as content is in the component */
 </style>

+ 214 - 0
pages/home/components/reduce-share.vue

@@ -0,0 +1,214 @@
+<template>
+    <custom-popup v-model="showPopup" mode="center" border-radius="24" width="540rpx" :bg-color="'transparent'">
+        <view class="share-container">
+            <!-- 标题 -->
+            <view class="title-text">
+                <view>好友邀您助力</view>
+                <view>减少买书消费</view>
+            </view>
+
+            <!-- 活动规则按钮 -->
+            <view class="rules-button-container">
+                <u-button class="rules-button" :custom-style="rulesButtonStyle" @click="viewRules">查看活动规则</u-button>
+            </view>
+
+            <!-- 用户信息区域 -->
+            <view class="user-info">
+                <view class="avatar-container">
+                    <u-avatar :src="avatarUrl" size="140"></u-avatar>
+                </view>
+                <view class="username">{{ username }}</view>
+            </view>
+
+            <!-- 助力按钮 -->
+            <button class="help-button" @click="inviteClickHelp" v-if="inviteDone == 1">
+                点击助力
+            </button>
+
+            <button class="help-button" @click="close" v-if="inviteDone == 0">
+                助力成功
+            </button>
+
+            <!-- 关闭按钮 -->
+            <view class="close-button" @click="close">
+                <image src="/static/img/activity/close2.png" mode="widthFix"></image>
+            </view>
+        </view>
+    </custom-popup>
+</template>
+
+<script>
+import customPopup from "@/components/custom-popup.vue";
+
+export default {
+    components: {
+        customPopup,
+    },
+    data() {
+        return {
+            showPopup: false,
+            avatarUrl: "", // 用户头像URL
+            username: "", // 用户名,带星号
+            // 自定义按钮样式
+            rulesButtonStyle: {
+                backgroundColor: "#39c248",
+                color: "#FFFFFF",
+                fontSize: "28rpx",
+                width: "280rpx",
+                height: "80rpx",
+                borderRadius: "40rpx",
+            },
+            // 邀请可以助力 0-否(完成不能再助力) 1-是
+            inviteDone: 1,
+            reduceCode: "",
+        };
+    },
+    methods: {
+        open(reduceCode) {
+            this.showPopup = true;
+            this.reduceCode = reduceCode;
+            this.getInviteHelpQuery(reduceCode);
+        },
+        //获取分享的邀请人信息
+        getInviteHelpQuery(reduceCode) {
+            this.$u.api.reduceHelpQueryAjax(reduceCode).then((res) => {
+                console.log(res, 'res')
+                if (res.code == 200) {
+                    this.avatarUrl = res.data.imgPath;
+                    this.username = res.data.nickName;
+                    this.inviteDone = res.data.inviteDone;
+                } else {
+                    this.username = res.msg;
+                    uni.showToast({
+                        icon: "none",
+                        title: res.msg,
+                    });
+                }
+            });
+        },
+
+        close() {
+            this.showPopup = false;
+            uni.removeStorageSync("reduceCode");
+        },
+        viewRules() {
+            // 打开活动规则弹窗
+            this.$emit("view-rules");
+        },
+
+        //调用助力接口
+        inviteClickHelp() {
+            let reduceCode = this.reduceCode || uni.getStorageSync("reduceCode");
+            this.$u.api.reduceClickHelpAjax({ reduceCode: reduceCode }).then((res) => {
+                if (res.code == 200) {
+                    this.close();
+                    this.inviteDone = 0;
+                    uni.showToast({
+                        icon: "none",
+                        title: "助力成功",
+                        duration: 2000
+                    });
+                    this.$emit("inviteSuccess");
+                } else {
+                    uni.showToast({
+                        icon: "none",
+                        title: res.msg || "助力失败",
+                        duration: 2000
+                    });
+                }
+            });
+        },
+    },
+};
+</script>
+
+<style lang="scss" scoped>
+.share-container {
+    position: relative;
+    padding: 40rpx;
+    border-radius: 24rpx;
+    text-align: center;
+    background: url("https://shuhi.oss-cn-qingdao.aliyuncs.com/mini/bg.png") no-repeat center center;
+    background-size: 100% 100%;
+}
+
+.title-text view {
+    font-size: 50rpx;
+    font-weight: bold;
+    color: #000;
+}
+
+.rules-button-container {
+    display: flex;
+    justify-content: center;
+    margin: 20rpx 0 40rpx;
+
+    .rules-button {
+        position: relative;
+
+        &::before,
+        &::after {
+            content: "";
+            position: absolute;
+            top: 50%;
+            width: 80rpx;
+            height: 2rpx;
+            background-color: #39c248;
+        }
+
+        &::before {
+            left: -90rpx;
+        }
+
+        &::after {
+            right: -90rpx;
+        }
+    }
+}
+
+.user-info {
+    .avatar-container {
+        margin: 0 auto 20rpx;
+        width: 140rpx;
+        height: 140rpx;
+        border-radius: 50%;
+        overflow: hidden;
+    }
+
+    .username {
+        font-size: 28rpx;
+        color: #333;
+        background: #39c248;
+        padding: 6rpx 20rpx;
+        border-radius: 30rpx;
+        color: #fff;
+        display: inline-block;
+        position: relative;
+        top: -50rpx;
+    }
+}
+
+.help-button {
+    height: 90rpx;
+    background: linear-gradient(to bottom, #47d46c, #24ad3c);
+    font-size: 32rpx;
+    color: #ffffff;
+    border-radius: 10rpx;
+    line-height: 90rpx;
+    width: 100%;
+    margin-top: 20rpx;
+    border: none;
+}
+
+.close-button {
+    position: absolute;
+    bottom: -120rpx;
+    left: 50%;
+    transform: translateX(-50%);
+
+    image {
+        width: 70rpx;
+        height: 70rpx;
+    }
+}
+</style>

+ 1 - 1
pages/home/components/upsell-book.vue

@@ -105,7 +105,7 @@ export default {
         .then((res) => {
           if (res.code == 200) {
             this.bookInfo = res.data;
-            let needInviteNum = res.data.needInviteNum;
+            let needInviteNum = res.data.canInvite;
             let inviteUsers = res.data.inviteUsers || [];
             let length = inviteUsers.length;
             for (let index = 0; index < needInviteNum - length; index++) {

+ 16 - 1
pages/home/index.vue

@@ -118,6 +118,9 @@
 
         <!-- 加价规则弹窗 -->
         <UpsellRules ref="upsellRulesRef" />
+        
+        <!-- 减价分享弹窗 -->
+        <ReduceShare ref="reduceShareRef" @viewRules="handleViewSellRules" />
     </view>
 </template>
 
@@ -134,6 +137,7 @@ import UpsellBook from "./components/upsell-book.vue";
 import UpsellRules from "./components/upsell-rules.vue";
 import UpsellShare from "./components/upsell-share.vue";
 import UpsellQrcode from "./components/upsell-qrcode.vue";
+import ReduceShare from "./components/reduce-share.vue";
 import FloatingDrag from "@/components/floating-drag.vue";
 import { eventBus } from "@/utils/event-bus";
 
@@ -153,6 +157,7 @@ export default {
         UpsellRules,
         UpsellShare,
         UpsellQrcode,
+        ReduceShare,
         FloatingDrag,
     },
     data() {
@@ -303,8 +308,13 @@ export default {
                 this.$refs.shareRef?.open(params.upsellCode);
                 this.getLastOrder();
             }
+            if (params.reduceCode) {
+                this.$refs.reduceShareRef?.open(params.reduceCode);
+            }
         } else if (options.upsellCode) {
             this.$refs.shareRef?.open(options.upsellCode);
+        } else if (options.reduceCode) {
+            this.$refs.reduceShareRef?.open(options.reduceCode);
         } else {
             this.getLastOrder();
         }
@@ -323,12 +333,17 @@ export default {
 
     methods: {
         // 登录成功之后
-        loginSuccess() {
+        loginSuccess(data) {
             let upsellCode = uni.getStorageSync("upsellCode");
             if (upsellCode) {
                 console.log(upsellCode, "登录成功之后助力的 code值:", upsellCode);
                 this.$refs.shareRef?.open(upsellCode);
             }
+            let reduceCode = data.params.reduceCode;
+            if (reduceCode) {
+                console.log(reduceCode, "登录成功之后助力的 code值:", reduceCode);
+                this.$refs.reduceShareRef?.open(reduceCode);
+            }
             this.getLastOrder();
         },