Browse Source

购物车更新

yuhongqi 2 weeks ago
parent
commit
c3f143b50d
1 changed files with 618 additions and 457 deletions
  1. 618 457
      pages/shopping/cart.vue

+ 618 - 457
pages/shopping/cart.vue

@@ -1,465 +1,626 @@
 <template>
-	<view class="content">
-		<!-- 商品列表 -->
-		<view class="goods-list">
-			<view class="item" v-for="(item,index) in carts" :key="index">
-				<label style="margin-right: 30upx;">
-					<checkbox :value="item.checked"  :checked="item.checked" @click="checkChange(item)" />
-				</label>
-				<image class="goods-img" :src="item.productAttrImage==null||item.productAttrImage==''?item.productImage:item.productAttrImage" mode="aspectFit"></image>
-				<view class="info-box">
-					<view>
-						<view class="title-box">
-							<view class="tag">{{utils.getDictLabelName("storeProductType",item.productType)}}</view>
-							<view class="title ellipsis">{{ item.productName }}</view>
-						</view>
-						<view class="intro ellipsis">{{item.productAttrName}}</view>
-					</view>
-					<view class="price-num">
-						<view class="price">
-							<text class="unit">¥</text>
-							<text class="text">{{item.price}}</text>
-						</view>
-						<view class="num-box">
-							<view class="img-box" @click="delNum(item)">
-								<image v-if="item.cartNum <= 1" src="../../static/images/jian.png" mode=""></image>
-								<image v-else src="../../static/images/jian2.png" mode=""></image>
-							</view>
-							<input  type="number" @change="changeNum($event,item)" :value="item.cartNum"   />
-							<view class="img-box" @click="addNum(item)">
-								<image src="../../static/images/add.png" mode=""></image>
-							</view>
-						</view>
-					</view>
-				</view>
-			</view>
-		</view>
-	 
-		<view v-if="carts.length == 0" class="no-data-box">
-			<image src="../../static/images/no_data.png" mode="aspectFit"></image>
-			<view class="empty-title">暂无数据</view>
-		</view>
-		<!-- 猜你喜欢 -->
-		 
-		<view class="like-product">
-			<likeProduct  ref="product" />
-		</view>
-		<!-- 底部按钮 -->
-		<view class="btn-foot">
-			<view class="left">
-				<label>
-					<checkbox  :checked="checkAll" @click="handleCheckAll()" />
-				</label>
-				<text class="text">全选</text>
-				<text class="text" @click="delCart()">删除</text>
-			</view>
-			<view class="right">
-				<view class="total">
-					<text class="label">合计:</text>
-					<view class="price">
-						<text class="unit">¥</text>
-						<text class="num">{{totalMoney.toFixed(2)}}</text>
-					</view>
-				</view>
-				<view class="btn" @click="submit">结算</view>
-			</view>
-		</view>
-		
-	</view>
+  <view class="content">
+    <!-- 商品列表:按仓库分组展示 -->
+    <view class="goods-list">
+      <block v-for="(group, gIndex) in cartsByWarehouse" :key="gIndex">
+        <view class="warehouse-header">{{ group.warehouseName || '默认仓库' }}</view>
+        <view class="item" v-for="(item, index) in group.list" :key="item.id">
+          <!-- 🔥 替换原生checkbox为自定义样式,解决渲染隔离 -->
+          <view
+              class="checkbox-wrap"
+              style="margin-right: 30upx;"
+              :data-id="item && item.id"
+              @tap.stop="onItemCheckTap($event)"
+          >
+            <view class="custom-checkbox" :class="{checked: item.checked}">
+              <text v-if="item.checked" class="check-icon">✓</text>
+            </view>
+          </view>
+          <image class="goods-img" :src="item.productAttrImage||item.productImage" mode="aspectFit"></image>
+          <view class="info-box">
+            <view>
+              <view class="title-box">
+                <view class="tag">{{utils.getDictLabelName("storeProductType",item.productType)}}</view>
+                <view class="title ellipsis">{{ item.productName }}</view>
+              </view>
+              <view class="intro ellipsis">{{item.productAttrName}}</view>
+            </view>
+            <view class="price-num">
+              <view class="price">
+                <text class="unit">¥</text>
+                <text class="text">{{item.price}}</text>
+              </view>
+              <view class="num-box">
+                <view class="img-box" @click="delNum(item)">
+                  <image v-if="item.cartNum <= 1" src="../../static/images/jian.png" mode=""></image>
+                  <image v-else src="../../static/images/jian2.png" mode=""></image>
+                </view>
+                <input  type="number" @change="changeNum($event,item)" :value="item.cartNum"   />
+                <view class="img-box" @click="addNum(item)">
+                  <image src="../../static/images/add.png" mode=""></image>
+                </view>
+              </view>
+            </view>
+          </view>
+        </view>
+      </block>
+    </view>
+
+    <view v-if="carts.length == 0" class="no-data-box">
+      <image src="../../static/images/no_data.png" mode="aspectFit"></image>
+      <view class="empty-title">暂无数据</view>
+    </view>
+    <!-- 猜你喜欢 -->
+    <view class="like-product">
+      <likeProduct  ref="product" />
+    </view>
+    <!-- 底部按钮 -->
+    <view class="btn-foot">
+      <view class="left">
+        <!-- 🔥 全选也替换为自定义checkbox -->
+        <view class="checkbox-wrap" @tap.stop="onCheckAllTap()">
+          <view class="custom-checkbox" :class="{checked: checkAll}">
+            <text v-if="checkAll" class="check-icon">✓</text>
+          </view>
+        </view>
+        <text class="text">全选</text>
+        <text class="text" @click="delCart()">删除</text>
+      </view>
+      <view class="right">
+        <view class="total">
+          <text class="label">合计:</text>
+          <view class="price">
+            <text class="unit">¥</text>
+            <text class="num">{{totalMoney.toFixed(2)}}</text>
+          </view>
+        </view>
+        <view class="btn" @click="submit">结算</view>
+      </view>
+    </view>
+  </view>
 </template>
 
 <script>
-	import {getCarts,cartNum,delCart} from '@/api/product'
-	import likeProduct from '@/components/likeProduct.vue'
-	export default {
-		components: {
-			likeProduct
-		},	
-		data() {
-			return {
-				 
-				totalMoney:0.00,
-				carts:[],
-				checkAll:false,
-			}	
-		},
-		onLoad() {
-			// this.getCarts();
-		},
-		onShow() {
-			if(uni.getStorageSync('AppToken')){
-				this.getCarts();
-			}
-		},
-		onReachBottom() {
-			this.$refs.product.getGoodsProducts();
-		},
-		methods: {
-			delCart(){
-				var selectCarts=this.carts.filter(ele => ele.checked==true).map(ele => {
-				  return ele.id
-				});
-				if(selectCarts.length==0){
-					uni.showToast({
-						icon:'none',
-						title: "请选择商品删除",
-					});
-					return;
-				}
-				let data = {ids:selectCarts};
-				delCart(data).then(
-					res => {
-						if(res.code==200){
-							uni.showToast({
-								icon:'success',
-								title: "操作成功",
-							});
-							this.getCarts()
-						}else{
-							
-							uni.showToast({
-								icon:'none',
-								title: res.msg,
-							});
-						}
-					},
-					rej => {}
-				);
-				console.log(selectCarts)
-			},
-			computedMoney(){
-				var money=0;
-				var that=this;
-				this.carts.forEach((item,index,arr)=>{
-					 if(item.checked){
-						 money+=item.price*item.cartNum;
-					 }
-				})
-				console.log(money);
-				this.totalMoney=money;
-			},
-			handleCheckAll(){
-				this.checkAll=!this.checkAll;
-				var that=this;
-				this.carts.forEach((item,index,arr)=>{
-				     item.checked=that.checkAll;
-				})
-				this.computedMoney();
-			},
-			checkChange(item){
-				item.checked=!item.checked;
-				this.computedMoney();
-			},
-			changeNum(e,item) {
-				item.cartNum = e.detail.value.replace(/\D/g, '')
-				if (item.cartNum <= 1) {
-				  uni.showToast({
-				    title: "已经是底线啦!",
-				    icon: "none",
-				    duration: 2000
-				  });
-				  return;
-				}
-				if(item.cartNum < 1) {
-					item.cartNum = 1
-				}
-				if(item.cartNum>=item.stock){
-					item.cartNum=item.stock;
-				}
-				this.changeCartNum(item)
-			},
-			changeCartNum(item){
-				let data = {number:item.cartNum,id:item.id};
-				cartNum(data).then(
-					res => {
-						if(res.code==200){
-							uni.showToast({
-								icon:'none',
-								title: "操作成功",
-							});
-							this.computedMoney();
-							
-						}else{
-							
-							uni.showToast({
-								icon:'none',
-								title: res.msg,
-							});
-						}
-					},
-					rej => {}
-				);
-			},
-			getCarts(){
-				getCarts().then(
-					res => {
-						if(res.code==200){
-							 this.carts=res.carts;
-							 this.carts.forEach((item,index,arr)=>{
-							      item.checked=false;
-							 })
-							 this.computedMoney();
-						}else{
-							uni.showToast({
-								icon:'none',
-								title: "请求失败",
-							});
-						}
-					},
-					rej => {}
-				);
-			},
-			// 购物车减法
-			delNum(item) {
-				if (item.cartNum <= 1) {
-				  uni.showToast({
-				    title: "已经是底线啦!",
-				    icon: "none",
-				    duration: 2000
-				  });
-				  return;
-				}
-				item.cartNum --
-				if(item.cartNum < 1) {
-					item.cartNum = 1
-				}
-				 
-				this.changeCartNum(item)
-			},
-			// 购物车加法
-			addNum(item) {
-				console.log(item)
-				item.cartNum++
-				if(item.cartNum>=item.stock){
-					item.cartNum=item.stock;
-				}
-				this.changeCartNum(item)
-			},
-			// 结算
-			submit() {
-				var selectCarts=this.carts.filter(ele => ele.checked==true).map(ele => {
-				  return ele.id
-				});
-				if(selectCarts.length==0){
-					uni.showToast({
-						icon:'none',
-						title: "请选择商品",
-					});
-					return;
-				}
-				uni.navigateTo({
-					url: '/pages_shopping/shopping/confirmOrder?type=cart&cartIds='+selectCarts.toString()
-				})
-			},
-			showProduct(item){
-				uni.navigateTo({
-					url: '/pages_shopping/shopping/productDetails?productId='+item.productId
-				})
-			},
-		}
-	}
+import {getCarts,cartNum,delCart} from '@/api/product'
+import likeProduct from '@/components/likeProduct.vue'
+export default {
+  components: {
+    likeProduct
+  },
+  data() {
+    return {
+      carts:[],
+      cartsByWarehouse: [],
+    }
+  },
+  onLoad() {
+    // this.getCarts();
+  },
+  onShow() {
+    if(uni.getStorageSync('AppToken')){
+      this.getCarts();
+    }
+  },
+  onReachBottom() {
+    this.$refs.product.getGoodsProducts();
+  },
+  watch: {
+    carts: {
+      deep: true,
+      handler() {
+        this.formatCartsByWarehouse();
+      }
+    }
+  },
+  computed: {
+    totalMoney() {
+      let money = 0;
+      (this.carts || []).forEach(item => {
+        if (item.checked) {
+          money += (Number(item.price) || 0) * (Number(item.cartNum) || 0);
+        }
+      });
+      return money;
+    },
+    checkAll() {
+      if (!this.carts || this.carts.length === 0) return false;
+      return this.carts.every(item => item.checked);
+    }
+  },
+  methods: {
+    formatCartsByWarehouse() {
+      const map = {};
+      (this.carts || []).filter(item => !!item).forEach(item => {
+        const code = item.warehouseCode || '_default_';
+        const name = item.warehouseName || '默认仓库';
+        if (!map[code]) {
+          map[code] = { warehouseCode: code, warehouseName: name, list: [] };
+        }
+        map[code].list.push({ ...item });
+      });
+      // 🔥 强制替换数组,触发视图刷新
+      this.cartsByWarehouse = Object.values(map);
+    },
+    getSelectedWarehouseCount() {
+      const codes = new Set();
+      this.carts.forEach(item => {
+        if (item.checked) {
+          const code = item.warehouseCode || '_default_';
+          codes.add(code);
+        }
+      });
+      return codes.size;
+    },
+    delCart(){
+      var selectCarts=this.carts.filter(ele => ele.checked==true).map(ele => ele.id);
+      if(selectCarts.length==0){
+        uni.showToast({
+          icon:'none',
+          title: "请选择商品删除",
+        });
+        return;
+      }
+      let data = {ids:selectCarts};
+      delCart(data).then(
+          res => {
+            if(res.code==200){
+              uni.showToast({
+                icon:'success',
+                title: "操作成功",
+              });
+              this.getCarts();
+            }else{
+              uni.showToast({
+                icon:'none',
+                title: res.msg,
+              });
+            }
+          },
+          rej => {}
+      );
+    },
+    wouldHaveMultiWarehouseIfItemChecked(item) {
+      if (!item) return false;
+      const code = item.warehouseCode || '_default_';
+      const selectedCodes = new Set();
+      this.carts.forEach(c => {
+        if (c && c.checked) {
+          selectedCodes.add(c.warehouseCode || '_default_');
+        }
+      });
+      selectedCodes.add(code);
+      return selectedCodes.size > 1;
+    },
+    wouldHaveMultiWarehouseIfCheckAll() {
+      const codes = new Set();
+      this.carts.forEach(c => {
+        if (c) codes.add(c.warehouseCode || '_default_');
+      });
+      return codes.size > 1;
+    },
+    // 🔥 修复全选方法:统一用数组索引替换元素
+    onCheckAllTap() {
+      const newVal = !this.checkAll;
+      if (newVal && this.wouldHaveMultiWarehouseIfCheckAll()) {
+        uni.showToast({
+          icon: 'none',
+          title: '暂不支持多仓库购买,请选择同仓库商品',
+          duration: 2500
+        });
+        return;
+      }
+      // 深拷贝数组,批量替换元素
+      let newCarts = [...this.carts];
+      newCarts = newCarts.map(item => ({...item, checked: newVal}));
+      // 响应式替换整个carts数组
+      this.carts = newCarts;
+      // 手动触发分组 + 强制刷新
+      this.formatCartsByWarehouse();
+      this.$nextTick(() => {
+        this.$forceUpdate();
+      });
+    },
+    onItemCheckTap(e) {
+      const id = e?.currentTarget?.dataset?.id;
+      if (!id) return false;
+
+      const itemIndex = this.carts.findIndex(c => c?.id === id);
+      if (itemIndex === -1) return false;
+      const oldItem = this.carts[itemIndex];
+      const willBeChecked = !oldItem.checked;
+
+      // 多仓库校验失败
+      if (willBeChecked && this.wouldHaveMultiWarehouseIfItemChecked(oldItem)) {
+        // 响应式替换元素
+        this.$set(this.carts, itemIndex, {
+          ...oldItem,
+          checked: false
+        });
+        // 强制更新分组和视图
+        this.formatCartsByWarehouse();
+        this.$nextTick(() => {
+          this.$forceUpdate();
+        });
+        uni.showToast({
+          icon: 'none',
+          title: '暂不支持多仓库购买,请选择同仓库商品',
+          duration: 2500
+        });
+        return false;
+      }
+
+      // 正常勾选
+      this.$set(this.carts, itemIndex, {
+        ...oldItem,
+        checked: willBeChecked
+      });
+      this.formatCartsByWarehouse();
+      this.$nextTick(() => {
+        this.$forceUpdate();
+      });
+    },
+    findCartItemIndex(id) {
+      return this.carts.findIndex(c => c && c.id === id);
+    },
+    changeNum(e,item) {
+      // 🔥 修复:先找索引,再替换元素
+      const idx = this.carts.findIndex(c => c.id === item.id);
+      if(idx === -1) return;
+      let newNum = e.detail.value.replace(/\D/g, '') || 1;
+      newNum = Number(newNum);
+      if (newNum <= 1) {
+        newNum = 1;
+        uni.showToast({
+          title: "已经是底线啦!",
+          icon: "none",
+          duration: 2000
+        });
+      }
+      if(newNum >= item.stock){
+        newNum = item.stock;
+      }
+      // 响应式更新
+      this.$set(this.carts, idx, {
+        ...item,
+        cartNum: newNum
+      });
+      this.changeCartNum(this.carts[idx]);
+    },
+    changeCartNum(item){
+      let data = {number:item.cartNum,id:item.id};
+      cartNum(data).then(
+          res => {
+            if(res.code==200){
+              uni.showToast({
+                icon:'none',
+                title: "操作成功",
+              });
+            }else{
+              uni.showToast({
+                icon:'none',
+                title: res.msg,
+              });
+            }
+          },
+          rej => {}
+      );
+    },
+    // 🔥 修复初始化:响应式赋值 + 批量替换元素
+    getCarts(){
+      getCarts().then(
+          res => {
+            if(res.code==200){
+              // 深拷贝并初始化checked为false
+              let newCarts = (res.carts || []).map(item => ({
+                ...item,
+                checked: false
+              }));
+              // 响应式赋值
+              this.carts = newCarts;
+              // 初始化分组
+              this.formatCartsByWarehouse();
+            }else{
+              uni.showToast({
+                icon:'none',
+                title: "请求失败",
+              });
+            }
+          },
+          rej => {}
+      );
+    },
+    delNum(item) {
+      const idx = this.carts.findIndex(c => c.id === item.id);
+      if(idx === -1) return;
+      let newNum = item.cartNum - 1;
+      if (newNum <= 1) {
+        newNum = 1;
+        uni.showToast({
+          title: "已经是底线啦!",
+          icon: "none",
+          duration: 2000
+        });
+        return;
+      }
+      // 响应式更新
+      this.$set(this.carts, idx, {
+        ...item,
+        cartNum: newNum
+      });
+      this.changeCartNum(this.carts[idx]);
+    },
+    addNum(item) {
+      const idx = this.carts.findIndex(c => c.id === item.id);
+      if(idx === -1) return;
+      let newNum = item.cartNum + 1;
+      if(newNum >= item.stock){
+        newNum = item.stock;
+      }
+      // 响应式更新
+      this.$set(this.carts, idx, {
+        ...item,
+        cartNum: newNum
+      });
+      this.changeCartNum(this.carts[idx]);
+    },
+    submit() {
+      var selectCarts = this.carts.filter(ele => ele.checked === true);
+      if (selectCarts.length === 0) {
+        uni.showToast({
+          icon: 'none',
+          title: '请选择商品'
+        });
+        return;
+      }
+      if (this.getSelectedWarehouseCount() > 1) {
+        uni.showToast({
+          icon: 'none',
+          title: '暂不支持多仓库购买,请选择同仓库商品',
+          duration: 2500
+        });
+        return;
+      }
+      var cartIds = selectCarts.map(ele => ele.id).join(',');
+      uni.navigateTo({
+        url: '/pages_shopping/shopping/confirmOrder?type=cart&cartIds=' + cartIds
+      });
+    },
+    showProduct(item){
+      uni.navigateTo({
+        url: '/pages_shopping/shopping/productDetails?productId='+item.productId
+      })
+    },
+  }
+}
 </script>
 
 <style lang="scss">
-	page {
-		height: 100%;
-	}
-	.content{
-		height: 100%;
-		padding: 20upx;
-		.goods-list{
-			.item{
-				box-sizing: border-box;
-				height: 221upx;
-				background: #FFFFFF;
-				border-radius: 16upx;
-				margin-bottom: 20upx;
-				padding: 30upx;
-				display: flex;
-				align-items: center;
-				&:last-child{
-					margin-bottom: 0;
-				}
-				.goods-img{
-					width: 160upx;
-					height: 160upx;
-					background: #FFFFFF;
-					margin-right: 30upx;
-					flex-shrink: 0;
-				}
-				.info-box{
-					height: 160upx;
-					display: flex;
-					flex-direction: column;
-					justify-content: space-between;
-					width: calc(100% - 255upx);
-					.title-box{
-						width: 100%;
-						display: flex;
-						align-items: center;
-						.tag{
-							padding: 0 6upx;
-							height: 30upx;
-							line-height: 30upx;
-							font-size: 22upx;
-							font-family: PingFang SC;
-							font-weight: bold;
-							color: #FFFFFF;
-							background: linear-gradient(90deg, #2BC7B9 0%, #77cbf3 100%);
-							border-radius: 4upx;
-							margin-right: 10upx;
-							flex-shrink: 0;
-						}
-						.title{
-							flex: 1;
-							font-size: 28upx;
-							font-family: PingFang SC;
-							font-weight: 500;
-							color: #111111;
-							line-height: 1;
-						}
-					}
-					.intro{
-						font-size: 24upx;
-						font-family: PingFang SC;
-						font-weight: 500;
-						color: #999999;
-						margin-top: 22upx;
-						line-height: 1;
-					}
-					.price-num{
-						display: flex;
-						align-items: center;
-						justify-content: space-between;
-						.price{
-							display: flex;
-							align-items: flex-end;
-							.unit{
-								font-size: 24upx;
-								font-family: PingFang SC;
-								font-weight: 500;
-								color: #FF6633;
-								line-height: 1.2;
-								margin-right: 4upx;
-							}
-							.text{
-								font-size: 32upx;
-								font-family: PingFang SC;
-								font-weight: bold;
-								color: #FF6633;
-								line-height: 1;
-							}
-						}
-						.num-box{
-							display: flex;
-							align-items: center;
-							.img-box{
-								width: 60upx;
-								height: 60upx;
-								// border-radius: 4upx;
-								border: 1px solid #dddddd;
-								display: flex;
-								align-items: center;
-								justify-content: center;
-								image{
-									width: 25rpx;
-									height: 25rpx;
-								}
-							}
-							input{
-								width: 60upx;
-								height: 60upx;
-								line-height: 60upx;
-								font-size: 28upx;
-								font-family: PingFang SC;
-								font-weight: 500;
-								color: #111111;
-								// border-radius: 4upx;
-								border-top: 1px solid #dddddd;
-								border-bottom: 1px solid #dddddd;
-								text-align: center;
-								// margin: 0 16upx;
-							}
-						}
-					}
-				}
-			}
-		}
-		.like-product{
-			padding-bottom: 120upx;
-		}
-		.btn-foot{
-			box-sizing: border-box;
-			width: 100%;
-			height: 121upx;
-			background: #FFFFFF;
-			padding: 16upx 30upx 16upx 60upx;
-			display: flex;
-			align-items: center;
-			justify-content: space-between;
-			position: fixed;
-			left: 0;
-			bottom: 0rpx;
-			z-index: 99;
-			.left{
-				display: flex;
-				align-items: center;
-				.text{
-					margin-left: 14upx;
-					font-size: 28upx;
-					font-family: PingFang SC;
-					font-weight: 500;
-					color: #666666;
-					line-height: 1;
-				}
-			}
-			.right{
-				display: flex;
-				align-items: center;
-				.total{
-					display: flex;
-					align-items: flex-end;
-					margin-right: 36upx;
-					.label{
-						font-size: 26upx;
-						font-family: PingFang SC;
-						font-weight: 500;
-						color: #999999;
-						line-height: 1.5;
-					}
-					.price{
-						display: flex;
-						align-items: flex-end;
-						.unit{
-							font-size: 32upx;
-							font-family: PingFang SC;
-							font-weight: bold;
-							color: #FF6633;
-							line-height: 1.2;
-							margin-right: 10upx;
-						}
-						.num{
-							font-size: 30upx;
-							font-family: PingFang SC;
-							font-weight: bold;
-							color: #FF6633;
-							line-height: 1;
-						}
-					}
-				}
-				.btn{
-					width: 200upx;
-					height: 88upx;
-					line-height: 88upx;
-					text-align: center;
-					font-size: 30upx;
-					font-family: PingFang SC;
-					font-weight: bold;
-					color: #FFFFFF;
-					background: #2BC7B9;
-					border-radius: 44upx;
-				}
-			}
-		}
-	}
+page {
+  height: 100%;
+}
+.content{
+  height: 100%;
+  padding: 20upx;
+  // 🔥 自定义checkbox样式
+  .custom-checkbox {
+    width: 40upx;
+    height: 40upx;
+    border: 2px solid #ddd;
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    &.checked {
+      background: #2BC7B9;
+      border-color: #2BC7B9;
+      .check-icon {
+        color: #fff;
+        font-size: 24upx;
+        font-weight: bold;
+      }
+    }
+  }
+  .goods-list{
+    .warehouse-header{
+      font-size: 28upx;
+      font-weight: 600;
+      color: #333;
+      padding: 16upx 0 12upx 0;
+      border-bottom: 1px solid #eee;
+      margin-bottom: 12upx;
+    }
+    .item{
+      box-sizing: border-box;
+      height: 221upx;
+      background: #FFFFFF;
+      border-radius: 16upx;
+      margin-bottom: 20upx;
+      padding: 30upx;
+      display: flex;
+      align-items: center;
+      &:last-child{
+        margin-bottom: 0;
+      }
+      .goods-img{
+        width: 160upx;
+        height: 160upx;
+        background: #FFFFFF;
+        margin-right: 30upx;
+        flex-shrink: 0;
+      }
+      .info-box{
+        height: 160upx;
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+        width: calc(100% - 255upx);
+        .title-box{
+          width: 100%;
+          display: flex;
+          align-items: center;
+          .tag{
+            padding: 0 6upx;
+            height: 30upx;
+            line-height: 30upx;
+            font-size: 22upx;
+            font-family: PingFang SC;
+            font-weight: bold;
+            color: #FFFFFF;
+            background: linear-gradient(90deg, #2BC7B9 0%, #77cbf3 100%);
+            border-radius: 4upx;
+            margin-right: 10upx;
+            flex-shrink: 0;
+          }
+          .title{
+            flex: 1;
+            font-size: 28upx;
+            font-family: PingFang SC;
+            font-weight: 500;
+            color: #111111;
+            line-height: 1;
+          }
+        }
+        .intro{
+          font-size: 24upx;
+          font-family: PingFang SC;
+          font-weight: 500;
+          color: #999999;
+          margin-top: 22upx;
+          line-height: 1;
+        }
+        .price-num{
+          display: flex;
+          align-items: center;
+          justify-content: space-between;
+          .price{
+            display: flex;
+            align-items: flex-end;
+            .unit{
+              font-size: 24upx;
+              font-family: PingFang SC;
+              font-weight: 500;
+              color: #FF6633;
+              line-height: 1.2;
+              margin-right: 4upx;
+            }
+            .text{
+              font-size: 32upx;
+              font-family: PingFang SC;
+              font-weight: bold;
+              color: #FF6633;
+              line-height: 1;
+            }
+          }
+          .num-box{
+            display: flex;
+            align-items: center;
+            .img-box{
+              width: 60upx;
+              height: 60upx;
+              // border-radius: 4upx;
+              border: 1px solid #dddddd;
+              display: flex;
+              align-items: center;
+              justify-content: center;
+              image{
+                width: 25rpx;
+                height: 25rpx;
+              }
+            }
+            input{
+              width: 60upx;
+              height: 60upx;
+              line-height: 60upx;
+              font-size: 28upx;
+              font-family: PingFang SC;
+              font-weight: 500;
+              color: #111111;
+              // border-radius: 4upx;
+              border-top: 1px solid #dddddd;
+              border-bottom: 1px solid #dddddd;
+              text-align: center;
+              // margin: 0 16upx;
+            }
+          }
+        }
+      }
+    }
+  }
+  .like-product{
+    padding-bottom: 120upx;
+  }
+  .btn-foot{
+    box-sizing: border-box;
+    width: 100%;
+    height: 121upx;
+    background: #FFFFFF;
+    padding: 16upx 30upx 16upx 60upx;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    position: fixed;
+    left: 0;
+    bottom: 0rpx;
+    z-index: 99;
+    .left{
+      display: flex;
+      align-items: center;
+      .text{
+        margin-left: 14upx;
+        font-size: 28upx;
+        font-family: PingFang SC;
+        font-weight: 500;
+        color: #666666;
+        line-height: 1;
+      }
+    }
+    .right{
+      display: flex;
+      align-items: center;
+      .total{
+        display: flex;
+        align-items: flex-end;
+        margin-right: 36upx;
+        .label{
+          font-size: 26upx;
+          font-family: PingFang SC;
+          font-weight: 500;
+          color: #999999;
+          line-height: 1.5;
+        }
+        .price{
+          display: flex;
+          align-items: flex-end;
+          .unit{
+            font-size: 32upx;
+            font-family: PingFang SC;
+            font-weight: bold;
+            color: #FF6633;
+            line-height: 1.2;
+            margin-right: 10upx;
+          }
+          .num{
+            font-size: 30upx;
+            font-family: PingFang SC;
+            font-weight: bold;
+            color: #FF6633;
+            line-height: 1;
+          }
+        }
+      }
+      .btn{
+        width: 200upx;
+        height: 88upx;
+        line-height: 88upx;
+        text-align: center;
+        font-size: 30upx;
+        font-family: PingFang SC;
+        font-weight: bold;
+        color: #FFFFFF;
+        background: #2BC7B9;
+        border-radius: 44upx;
+      }
+    }
+  }
+}
 </style>