瀏覽代碼

feat(商品): 添加库存状态显示和到货通知功能

- 在商品列表项中添加库存状态遮罩显示
- 实现到货通知功能,包括设置和取消通知
- 修改搜索推荐接口支持关键词参数
- 添加轮播图点击跳转功能
- 更新商品项数据结构包含库存和到货通知状态
ylong 1 周之前
父節點
當前提交
e3986ccd1e

+ 1 - 1
api/modules/mall.js

@@ -57,7 +57,7 @@ export const useMallApi = (Vue, vm) => {
         clearSearchHistoryAjax: () => vm.$u.post('/token/shop/user/clearSearchLog'),
 
         // 搜索推荐
-        getSearchRecommendAjax: () => vm.$u.get('/token/shop/user/searchRecommend'),
+        getSearchRecommendAjax: (keyword) => vm.$u.get('/token/shop/user/searchRecommend?keyword=' + keyword),
 
 		// 根据专题id获取专题下的图书 (带分页)
 		getBookListByCateIdAjax: (params) => vm.$u.get('/token/shop/showIndex/getBookListByCateId', params),

+ 5 - 5
pages-car/pages/index.vue

@@ -289,11 +289,11 @@
                 });
 
                 // 获取推荐列表
-                this.$u.api.getSearchRecommendAjax().then(res => {
-                    if (res.code == 200) {
-                        this.recommendList = res.data || [];
-                    }
-                });
+                // this.$u.api.getSearchRecommendAjax().then(res => {
+                //     if (res.code == 200) {
+                //         this.recommendList = res.data || [];
+                //     }
+                // });
             },
             handleCheck({ id, checked }) {
                 const item = this.cartList.find(i => i.id === id);

+ 32 - 2
pages-sell/components/hot-recommend-item/index.vue

@@ -1,6 +1,12 @@
 <template>
 	<view class="hot-item" @click="navigateToDetail">
-		<image :src="item.cover" class="book-cover" mode="aspectFill"></image>
+		<view class="image-wrapper">
+			<image :src="item.cover" class="book-cover" mode="aspectFill"></image>
+			<!-- 状态遮罩 -->
+			<view class="status-mask" v-if="item.availableStock === 0">
+				<text>暂无库存</text>
+			</view>
+		</view>
 		<view class="info-right">
 			<view class="info-top">
 				<text class="title">{{ item.name || '-' }}</text>
@@ -91,13 +97,37 @@ export default {
 	display: flex;
 	border-radius: 16rpx;
 
-	.book-cover {
+	.image-wrapper {
+		position: relative;
 		width: 140rpx;
 		height: 180rpx;
 		border-radius: 4rpx;
 		background-color: #f5f5f5;
 		margin-right: 20rpx;
 		flex-shrink: 0;
+		overflow: hidden;
+
+		.book-cover {
+			width: 100%;
+			height: 100%;
+		}
+
+		.status-mask {
+			position: absolute;
+			bottom: 0;
+			left: 0;
+			width: 100%;
+			height: 40rpx;
+			background-color: rgba(0, 0, 0, 0.6);
+			display: flex;
+			justify-content: center;
+			align-items: center;
+
+			text {
+				color: #fff;
+				font-size: 20rpx;
+			}
+		}
 	}
 
 	.info-right {

+ 63 - 4
pages-sell/components/hot-sell-item/index.vue

@@ -10,7 +10,13 @@
 
 		<!-- Book Info -->
 		<view class="book-info" @click.stop="navigateToDetail">
-			<image :src="item.bookImg" class="book-cover" mode="aspectFill"></image>
+			<view class="image-wrapper">
+				<image :src="item.bookImg" class="book-cover" mode="aspectFill"></image>
+				<!-- 状态遮罩 -->
+				<view class="status-mask" v-if="item.availableStock === 0">
+					<text>暂无库存</text>
+				</view>
+			</view>
 			
 			<view class="info-right">
 				<text class="title">{{ item.bookName || '-' }}</text>
@@ -23,8 +29,10 @@
 						<text class="original">¥{{ item.bookOriginalPrice }}</text>
 					</view>
 					
-					<view class="cart-btn" @click.stop="handleAddToCart">
-						<text>加入购物车</text>
+					<view class="cart-btn" :class="{ 'gray-btn': item.availableStock === 0 && item.hasArrivalNotice === 1 }" @click.stop="handleAction">
+						<text v-if="item.availableStock === 0 && item.hasArrivalNotice === 1">取消到货通知</text>
+						<text v-else-if="item.availableStock === 0">到货通知</text>
+						<text v-else>加入购物车</text>
 					</view>
 				</view>
 			</view>
@@ -59,6 +67,29 @@ export default {
 				url: '/pages-sell/pages/detail?isbn=' + this.item.bookIsbn || ''
 			});
 		},
+		handleAction() {
+			if (this.item.availableStock === 0) {
+				this.handleNotify();
+			} else {
+				this.handleAddToCart();
+			}
+		},
+		handleNotify() {
+			const isCancel = this.item.hasArrivalNotice === 1;
+			const apiUrl = isCancel ? '/token/shop/user/noticeArrivalCancel' : '/token/shop/user/noticeArrival';
+
+			uni.$u.http.post(apiUrl, {
+				isbn: this.item.bookIsbn,
+			}).then(res => {
+				if (res.code === 200) {
+					const newValue = isCancel ? 0 : 1;
+					this.$emit('update-item', { ...this.item, hasArrivalNotice: newValue });
+					this.$set(this.item, 'hasArrivalNotice', newValue);
+					this.item.hasArrivalNotice = newValue;
+					this.$u.toast(isCancel ? '已取消到货通知' : '到货通知设置成功');
+				}
+			});
+		},
 		handleAddToCart() {
 			this.item.isbn = this.item.bookIsbn || '';
 			this.$refs.popup.open(this.item, 1);
@@ -102,13 +133,37 @@ export default {
 		display: flex;
 		align-items: center;
 
-		.book-cover {
+		.image-wrapper {
+			position: relative;
 			width: 140rpx;
 			height: 180rpx;
 			border-radius: 4rpx;
 			background-color: #f5f5f5;
 			margin-right: 24rpx;
 			flex-shrink: 0;
+			overflow: hidden;
+
+			.book-cover {
+				width: 100%;
+				height: 100%;
+			}
+
+			.status-mask {
+				position: absolute;
+				bottom: 0;
+				left: 0;
+				width: 100%;
+				height: 40rpx;
+				background-color: rgba(0, 0, 0, 0.6);
+				display: flex;
+				justify-content: center;
+				align-items: center;
+
+				text {
+					color: #fff;
+					font-size: 20rpx;
+				}
+			}
 		}
 
 		.info-right {
@@ -175,6 +230,10 @@ export default {
 					align-items: center;
 					justify-content: center;
 
+					&.gray-btn {
+						background: #cccccc;
+					}
+
 					text {
 						font-size: 24rpx;
 						color: #fff;

+ 32 - 2
pages-sell/components/recommend-item/index.vue

@@ -2,7 +2,13 @@
 	<view class="recommend-item" @click.stop="handleClick">
 		<!-- Main Info Row -->
 		<view class="main-info" :style="{ 'margin-bottom': showDesc ? '30rpx' : '0' }">
-			<image :src="item.cover" class="book-cover" mode="aspectFill"></image>
+			<view class="image-wrapper">
+				<image :src="item.cover" class="book-cover" mode="aspectFill"></image>
+				<!-- 状态遮罩 -->
+				<view class="status-mask" v-if="item.availableStock === 0">
+					<text>暂无库存</text>
+				</view>
+			</view>
 
 			<view class="info-right">
 				<view class="title-author">
@@ -129,12 +135,36 @@
 			display: flex;
 			margin-bottom: 30rpx;
 
-			.book-cover {
+			.image-wrapper {
+				position: relative;
 				width: 172rpx;
 				height: 220rpx;
 				border-radius: 8rpx;
 				margin-right: 24rpx;
 				flex-shrink: 0;
+				overflow: hidden;
+
+				.book-cover {
+					width: 100%;
+					height: 100%;
+				}
+
+				.status-mask {
+					position: absolute;
+					bottom: 0;
+					left: 0;
+					width: 100%;
+					height: 40rpx;
+					background-color: rgba(0, 0, 0, 0.6);
+					display: flex;
+					justify-content: center;
+					align-items: center;
+
+					text {
+						color: #fff;
+						font-size: 20rpx;
+					}
+				}
 			}
 
 			.info-right {

+ 11 - 1
pages-sell/components/sell-container/index.vue

@@ -74,7 +74,7 @@
 				<!-- 左侧:推广卖书 -->
 				<view class="card-left">
 					<view class="card-content">
-						<u-swiper :list="swiperList" :autoplay="true" :interval="3000" name="imgUrl"></u-swiper>
+						<u-swiper :list="swiperList" :autoplay="true" :interval="3000" name="imgUrl" @click="handleSwiperClick"></u-swiper>
 					</view>
 				</view>
 
@@ -396,6 +396,16 @@ export default {
 			uni.makePhoneCall({
 				phoneNumber: '400-123-4567'
 			});
+		},
+		// 轮播图点击事件
+		handleSwiperClick(index) {
+			const item = this.swiperList[index];
+			console.log(item,'xxxx')
+			if (item && item.jumpUrl) {
+				uni.navigateTo({
+					url: item.jumpUrl
+				});
+			}
 		}
 	}
 }

+ 4 - 0
pages-sell/pages/hot-sell.vue

@@ -22,6 +22,7 @@
 				:rank="index + 1" 
 				:item="item"
 				@add-cart="addToCart"
+				@update-item="updateBookItem($event, index)"
 			></hot-sell-item>
 		</view>
 	</view>
@@ -66,6 +67,9 @@ export default {
 				uni.hideLoading();
 			});
 		},
+		updateBookItem(updatedItem, index) {
+			this.$set(this.bookList, index, { ...this.bookList[index], ...updatedItem });
+		},
 		addToCart(data) {
 			console.log('add to cart:', data);
 		}

+ 6 - 1
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" :show-desc="cateType != 1"></recommend-item>
+			<recommend-item v-for="(item, index) in bookList" :key="index" :item="item" :show-desc="cateType != 1" @update-item="updateBookItem($event, index)"></recommend-item>
 			<u-loadmore :status="loadStatus" margin-top="30" margin-bottom="30"></u-loadmore>
 		</view>
 	</view>
@@ -122,6 +122,8 @@ export default {
 							originalPrice: item.bookOriginalPrice,
 							cover: item.bookImg,
 							desc: item.bookShortReview,
+							availableStock: item.availableStock,
+							hasArrivalNotice: item.hasArrivalNotice,
 							// Pass other props if needed by item component
 							id: item.bookId || item.id, // Assuming there might be an ID
 							isbn: item.bookIsbn
@@ -143,6 +145,9 @@ export default {
 				this.loadStatus = 'nomore';
 			});
 		},
+		updateBookItem(updatedItem, index) {
+			this.$set(this.bookList, index, { ...this.bookList[index], ...updatedItem });
+		},
 		goBack() {
 			uni.navigateBack();
 		}

+ 1 - 1
pages-sell/pages/search-result.vue

@@ -193,7 +193,7 @@ export default {
             });
 
             if (this.pageNum === 1) {
-                this.$u.api.getSearchRecommendAjax().then(res => {
+                this.$u.api.getSearchRecommendAjax(this.keyword).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 : '';

+ 6 - 1
pages-sell/pages/topic.vue

@@ -16,7 +16,7 @@
 		<!-- List Content -->
 		<view class="list-container">
 			<RecommendItem v-for="(item, index) in bookList" :key="index" :item="item" :show-desc="false"
-				@add-cart="handleAddToCart"></RecommendItem>
+				@add-cart="handleAddToCart" @update-item="updateBookItem($event, index)"></RecommendItem>
 
 			<!-- Change Batch Button -->
 			<view class="refresh-fab" @click="changeBatch" v-if="total > pageSize">
@@ -84,6 +84,8 @@
 								originalPrice: item.bookOriginalPrice,
 								cover: item.bookImg,
 								desc: item.bookShortReview,
+								availableStock: item.availableStock,
+								hasArrivalNotice: item.hasArrivalNotice,
 								id: item.bookId || item.id,
 								isbn: item.bookIsbn
 							}
@@ -108,6 +110,9 @@
 				}
 				this.loadData();
 			},
+			updateBookItem(updatedItem, index) {
+				this.$set(this.bookList, index, { ...this.bookList[index], ...updatedItem });
+			},
 			handleAddToCart(data) {
 				console.log('Add to cart:', data);
 				// Implement actual add to cart logic if needed, or keep toast