From c899ddfe49c5dedf6e78fc136dd0efdbe3951dfd Mon Sep 17 00:00:00 2001
From: yiming <m13691596795@163.com>
Date: 星期五, 01 三月 2024 09:38:20 +0800
Subject: [PATCH] feat(提交): 代码

---
 pages/cart/components/cart-bar/index.wxss    |   80 ++
 pages/cart/components/cart-group/index.json  |   10 
 pages/cart/components/cart-bar/index.wxml    |   31 +
 pages/cart/components/specs-popup/index.js   |   72 ++
 pages/cart/components/cart-empty/index.json  |    6 
 pages/cart/components/cart-empty/index.js    |   23 
 pages/cart/components/cart-group/utils.wxs   |   20 
 pages/cart/components/goods-card/index.json  |    9 
 pages/cart/components/goods-card/index.wxml  |   75 ++
 pages/cart/components/cart-group/index.wxs   |    5 
 pages/cart/components/cart-group/index.js    |  166 +++++
 pages/cart/components/cart-group/index.wxml  |  152 +++++
 pages/cart/components/cart-group/index.wxss  |  335 +++++++++++
 pages/cart/components/goods-card/index.wxss  |  260 ++++++++
 pages/cart/index.js                          |   29 
 pages/cart/components/cart-bar/index.json    |    7 
 pages/cart/components/cart-empty/index.wxss  |   33 +
 pages/cart/components/cart-empty/index.wxml  |    6 
 pages/cart/components/goods-card/index.js    |  243 ++++++++
 pages/cart/components/specs-popup/index.wxml |   26 
 pages/cart/components/specs-popup/index.wxss |   68 ++
 pages/cart/components/cart-bar/index.js      |   59 ++
 pages/cart/index.wxml                        |    6 
 23 files changed, 1,690 insertions(+), 31 deletions(-)

diff --git a/pages/cart/components/cart-bar/index.js b/pages/cart/components/cart-bar/index.js
new file mode 100644
index 0000000..db7736c
--- /dev/null
+++ b/pages/cart/components/cart-bar/index.js
@@ -0,0 +1,59 @@
+Component({
+  options: {
+    addGlobalClass: true,
+  },
+  /**
+   * 缁勪欢鐨勫睘鎬у垪琛�
+   */
+  properties: {
+    isAllSelected: {
+      type: Boolean,
+      value: false,
+    },
+    totalAmount: {
+      type: Number,
+      value: 1,
+    },
+    totalGoodsNum: {
+      type: Number,
+      value: 0,
+      observer(num) {
+        const isDisabled = num == 0;
+        setTimeout(() => {
+          this.setData({
+            isDisabled,
+          });
+        });
+      },
+    },
+    totalDiscountAmount: {
+      type: Number,
+      value: 0,
+    },
+    bottomHeight: {
+      type: Number,
+      value: 100,
+    },
+    fixed: Boolean,
+  },
+  data: {
+    isDisabled: false,
+  },
+
+  methods: {
+    handleSelectAll() {
+      const { isAllSelected } = this.data;
+      this.setData({
+        isAllSelected: !isAllSelected,
+      });
+      this.triggerEvent('handleSelectAll', {
+        isAllSelected: isAllSelected,
+      });
+    },
+
+    handleToSettle() {
+      if (this.data.isDisabled) return;
+      this.triggerEvent('handleToSettle');
+    },
+  },
+});
diff --git a/pages/cart/components/cart-bar/index.json b/pages/cart/components/cart-bar/index.json
new file mode 100644
index 0000000..c6c4351
--- /dev/null
+++ b/pages/cart/components/cart-bar/index.json
@@ -0,0 +1,7 @@
+{
+  "component": true,
+  "usingComponents": {
+    "price": "/components/price/index",
+    "t-icon": "tdesign-miniprogram/icon/icon"
+  }
+}
\ No newline at end of file
diff --git a/pages/cart/components/cart-bar/index.wxml b/pages/cart/components/cart-bar/index.wxml
new file mode 100644
index 0000000..486a0d5
--- /dev/null
+++ b/pages/cart/components/cart-bar/index.wxml
@@ -0,0 +1,31 @@
+<view class="cart-bar__placeholder" wx:if="{{fixed}}" />
+<view class="cart-bar {{fixed ? 'cart-bar--fixed' : ''}} flex flex-v-center" style="bottom: {{fixed ? 'calc(' + bottomHeight + 'rpx + env(safe-area-inset-bottom))' : ''}};">
+	<t-icon
+	 size="40rpx"
+	 color="{{isAllSelected ? '#FA4126' : '#BBBBBB'}}"
+	 name="{{isAllSelected ? 'check-circle-filled' : 'circle'}}"
+	 class="cart-bar__check"
+	 catchtap="handleSelectAll"
+	/>
+	<text>鍏ㄩ��</text>
+	<view class="cart-bar__total flex1">
+		<view>
+			<text class="cart-bar__total--bold text-padding-right">鎬昏</text>
+			<price
+			 price="{{totalAmount || '0'}}"
+			 fill="{{false}}"
+			 decimalSmaller
+			 class="cart-bar__total--bold cart-bar__total--price"
+			/>
+			<text class="cart-bar__total--normal">锛堜笉鍚繍璐癸級</text>
+		</view>
+		<view wx:if="{{totalDiscountAmount}}">
+			<text class="cart-bar__total--normal text-padding-right">宸蹭紭鎯�</text>
+			<price class="cart-bar__total--normal" price="{{totalDiscountAmount || '0'}}" fill="{{false}}" />
+		</view>
+	</view>
+	<view catchtap="handleToSettle" class="{{!isDisabled ? '' : 'disabled-btn'}} account-btn" hover-class="{{!isDisabled ? '' : 'hover-btn'}}">
+		鍘荤粨绠�({{totalGoodsNum}})
+	</view>
+</view>
+
diff --git a/pages/cart/components/cart-bar/index.wxss b/pages/cart/components/cart-bar/index.wxss
new file mode 100644
index 0000000..0e63f60
--- /dev/null
+++ b/pages/cart/components/cart-bar/index.wxss
@@ -0,0 +1,80 @@
+.cart-bar__placeholder {
+  height: 100rpx;
+}
+.flex {
+  display: flex;
+}
+.flex-v-center {
+  align-items: center;
+}
+.flex1 {
+  flex: 1;
+}
+.algin-bottom {
+  text-align: end;
+}
+.cart-bar--fixed {
+  position: fixed;
+  left: 0;
+  right: 0;
+  z-index: 99;
+  bottom: calc(100rpx + env(safe-area-inset-bottom));
+}
+
+.cart-bar {
+  height: 112rpx;
+  background-color: #fff;
+  border-top: 1rpx solid #e5e5e5;
+  padding: 16rpx 32rpx;
+  box-sizing: border-box;
+  font-size: 24rpx;
+  line-height: 36rpx;
+  color: #333;
+}
+
+.cart-bar .cart-bar__check {
+  margin-right: 12rpx;
+}
+
+.cart-bar .cart-bar__total {
+  margin-left: 24rpx;
+}
+
+.cart-bar .account-btn {
+  width: 192rpx;
+  height: 80rpx;
+  border-radius: 40rpx;
+  background-color: #fa4126;
+  font-size: 28rpx;
+  font-weight: bold;
+  line-height: 80rpx;
+  color: #ffffff;
+  text-align: center;
+}
+.cart-bar .disabled-btn {
+  background-color: #cccccc !important;
+}
+.cart-bar .hover-btn {
+  opacity: 0.5;
+}
+
+.cart-bar__total .cart-bar__total--bold {
+  font-size: 28rpx;
+  line-height: 40rpx;
+  color: #333;
+  font-weight: bold;
+}
+.cart-bar__total .cart-bar__total--normal {
+  font-size: 24rpx;
+  line-height: 32rpx;
+  color: #999;
+}
+
+.cart-bar__total .cart-bar__total--price {
+  color: #fa4126;
+  font-weight: bold;
+}
+
+.text-padding-right {
+  padding-right: 4rpx;
+}
diff --git a/pages/cart/components/cart-empty/index.js b/pages/cart/components/cart-empty/index.js
new file mode 100644
index 0000000..01cf9c3
--- /dev/null
+++ b/pages/cart/components/cart-empty/index.js
@@ -0,0 +1,23 @@
+Component({
+  properties: {
+    imgUrl: {
+      type: String,
+      value:
+        'https://cdn-we-retail.ym.tencent.com/miniapp/template/empty-cart.png',
+    },
+    tip: {
+      type: String,
+      value: '璐墿杞︽槸绌虹殑',
+    },
+    btnText: {
+      type: String,
+      value: '鍘婚椤�',
+    },
+  },
+  data: {},
+  methods: {
+    handleClick() {
+      this.triggerEvent('handleClick');
+    },
+  },
+});
diff --git a/pages/cart/components/cart-empty/index.json b/pages/cart/components/cart-empty/index.json
new file mode 100644
index 0000000..b659310
--- /dev/null
+++ b/pages/cart/components/cart-empty/index.json
@@ -0,0 +1,6 @@
+{
+  "component": true,
+  "usingComponents": {
+    "t-image": "/components/webp-image/index"
+  }
+}
\ No newline at end of file
diff --git a/pages/cart/components/cart-empty/index.wxml b/pages/cart/components/cart-empty/index.wxml
new file mode 100644
index 0000000..d0cdd43
--- /dev/null
+++ b/pages/cart/components/cart-empty/index.wxml
@@ -0,0 +1,6 @@
+<view class="cart-empty">
+	<t-image t-class="cart-img" src="{{imgUrl}}" />
+	<view class="tip">{{tip}}</view>
+	<view class="btn" bind:tap="handleClick">{{btnText}}</view>
+</view>
+
diff --git a/pages/cart/components/cart-empty/index.wxss b/pages/cart/components/cart-empty/index.wxss
new file mode 100644
index 0000000..d074bc3
--- /dev/null
+++ b/pages/cart/components/cart-empty/index.wxss
@@ -0,0 +1,33 @@
+.cart-empty {
+  padding: 64rpx 0rpx;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  box-sizing: border-box;
+  height: calc(100vh - 100rpx);
+  background-color: #f5f5f5;
+}
+.cart-empty .cart-img {
+  width: 160rpx;
+  height: 160rpx;
+  margin-bottom: 24rpx;
+}
+
+.cart-empty .tip {
+  font-size: 28rpx;
+  line-height: 40rpx;
+  color: #999;
+  margin-bottom: 24rpx;
+}
+.cart-empty .btn {
+  width: 240rpx;
+  height: 72rpx;
+  border-radius: 36rpx;
+  text-align: center;
+  line-height: 72rpx;
+  border: 2rpx solid #fa4126;
+  color: #fa4126;
+  background-color: transparent;
+  font-size: 28rpx;
+  font-weight: bold;
+}
diff --git a/pages/cart/components/cart-group/index.js b/pages/cart/components/cart-group/index.js
new file mode 100644
index 0000000..99a908d
--- /dev/null
+++ b/pages/cart/components/cart-group/index.js
@@ -0,0 +1,166 @@
+import Toast from 'tdesign-miniprogram/toast/index';
+
+const shortageImg =
+  'https://cdn-we-retail.ym.tencent.com/miniapp/cart/shortage.png';
+
+Component({
+  isSpecsTap: false, // 鏍囪鏈鐐瑰嚮浜嬩欢鏄惁鍥犱负鐐瑰嚮specs瑙﹀彂锛堢敱浜庡簳灞俫oods-card缁勪欢娌℃湁catch specs鐐瑰嚮浜嬩欢锛屽彧鑳藉湪姝ゅ鍔犵姸鎬佹潵閬垮厤鐐瑰嚮specs鏃惰Е鍙戣烦杞晢鍝佽鎯咃級
+  externalClasses: ['wr-class'],
+  properties: {
+    storeGoods: {
+      type: Array,
+      observer(storeGoods) {
+        for (const store of storeGoods) {
+          for (const activity of store.promotionGoodsList) {
+            for (const goods of activity.goodsPromotionList) {
+              goods.specs = goods.specInfo.map((item) => item.specValue); // 鐩墠浠呭睍绀哄晢鍝佸凡閫夎鏍肩殑鍊�
+            }
+          }
+          for (const goods of store.shortageGoodsList) {
+            goods.specs = goods.specInfo.map((item) => item.specValue); // 鐩墠浠呭睍绀哄晢鍝佸凡閫夎鏍肩殑鍊�
+          }
+        }
+
+        this.setData({ _storeGoods: storeGoods });
+      },
+    },
+    invalidGoodItems: {
+      type: Array,
+      observer(invalidGoodItems) {
+        invalidGoodItems.forEach((goods) => {
+          goods.specs = goods.specInfo.map((item) => item.specValue); // 鐩墠浠呭睍绀哄晢鍝佸凡閫夎鏍肩殑鍊�
+        });
+        this.setData({ _invalidGoodItems: invalidGoodItems });
+      },
+    },
+    thumbWidth: { type: null },
+    thumbHeight: { type: null },
+  },
+
+  data: {
+    shortageImg,
+    isShowSpecs: false,
+    currentGoods: {},
+    isShowToggle: false,
+    _storeGoods: [],
+    _invalidGoodItems: [],
+  },
+
+  methods: {
+    // 鍒犻櫎鍟嗗搧
+    deleteGoods(e) {
+      const { goods } = e.currentTarget.dataset;
+      this.triggerEvent('delete', { goods });
+    },
+
+    // 娓呯┖澶辨晥鍟嗗搧
+    clearInvalidGoods() {
+      this.triggerEvent('clearinvalidgoods');
+    },
+
+    // 閫変腑鍟嗗搧
+    selectGoods(e) {
+      const { goods } = e.currentTarget.dataset;
+      this.triggerEvent('selectgoods', {
+        goods,
+        isSelected: !goods.isSelected,
+      });
+    },
+
+    changeQuantity(num, goods) {
+      this.triggerEvent('changequantity', {
+        goods,
+        quantity: num,
+      });
+    },
+    changeStepper(e) {
+      const { value } = e.detail;
+      const { goods } = e.currentTarget.dataset;
+      let num = value;
+      if (value > goods.stack) {
+        num = goods.stack;
+      }
+      this.changeQuantity(num, goods);
+    },
+
+    input(e) {
+      const { value } = e.detail;
+      const { goods } = e.currentTarget.dataset;
+      const num = value;
+      this.changeQuantity(num, goods);
+    },
+
+    overlimit(e) {
+      const text =
+        e.detail.type === 'minus'
+          ? '璇ュ晢鍝佹暟閲忎笉鑳藉噺灏戜簡鍝�'
+          : '鍚屼竴鍟嗗搧鏈�澶氳喘涔�999浠�';
+      Toast({
+        context: this,
+        selector: '#t-toast',
+        message: text,
+      });
+    },
+
+    // 鍘诲噾鍗�/鍐嶉�涢��
+    gotoBuyMore(e) {
+      const { promotion, storeId = '' } = e.currentTarget.dataset;
+      this.triggerEvent('gocollect', { promotion, storeId });
+    },
+
+    // 閫変腑闂ㄥ簵
+    selectStore(e) {
+      const { storeIndex } = e.currentTarget.dataset;
+      const store = this.data.storeGoods[storeIndex];
+      const isSelected = !store.isSelected;
+      if (store.storeStockShortage && isSelected) {
+        Toast({
+          context: this,
+          selector: '#t-toast',
+          message: '閮ㄥ垎鍟嗗搧搴撳瓨涓嶈冻',
+        });
+        return;
+      }
+      this.triggerEvent('selectstore', {
+        store,
+        isSelected,
+      });
+    },
+
+    // 灞曞紑/鏀惰捣鍒囨崲
+    showToggle() {
+      this.setData({
+        isShowToggle: !this.data.isShowToggle,
+      });
+    },
+
+    // 灞曠ず瑙勬牸popup
+    specsTap(e) {
+      this.isSpecsTap = true;
+      const { goods } = e.currentTarget.dataset;
+      this.setData({
+        isShowSpecs: true,
+        currentGoods: goods,
+      });
+    },
+
+    hideSpecsPopup() {
+      this.setData({
+        isShowSpecs: false,
+      });
+    },
+
+    goGoodsDetail(e) {
+      if (this.isSpecsTap) {
+        this.isSpecsTap = false;
+        return;
+      }
+      const { goods } = e.currentTarget.dataset;
+      this.triggerEvent('goodsclick', { goods });
+    },
+
+    gotoCoupons() {
+      wx.navigateTo({ url: '/pages/coupon/coupon-list/index' });
+    },
+  },
+});
diff --git a/pages/cart/components/cart-group/index.json b/pages/cart/components/cart-group/index.json
new file mode 100644
index 0000000..74081a3
--- /dev/null
+++ b/pages/cart/components/cart-group/index.json
@@ -0,0 +1,10 @@
+{
+  "component": true,
+  "usingComponents": {
+    "t-toast": "tdesign-miniprogram/toast/toast",
+    "t-icon": "tdesign-miniprogram/icon/icon",
+    "t-stepper": "tdesign-miniprogram/stepper/stepper",
+    "swipeout": "/components/swipeout/index",
+    "goods-card": "../../components/goods-card/index"
+  }
+}
\ No newline at end of file
diff --git a/pages/cart/components/cart-group/index.wxml b/pages/cart/components/cart-group/index.wxml
new file mode 100644
index 0000000..9e3c1d9
--- /dev/null
+++ b/pages/cart/components/cart-group/index.wxml
@@ -0,0 +1,152 @@
+<wxs src="./index.wxs" module="handlePromotion" />
+<wxs src="./utils.wxs" module="utils" />
+
+<view class="cart-group">
+  <view class="goods-wrap" wx:for="{{_storeGoods}}" wx:for-item="store" wx:for-index="si" wx:key="storeId">
+    <view class="cart-store">
+      <t-icon
+        size="40rpx"
+        color="{{store.isSelected ? '#FA4126' : '#BBBBBB'}}"
+        name="{{store.isSelected ? 'check-circle-filled' : 'circle'}}"
+        class="cart-store__check"
+        bindtap="selectStore"
+        data-store-index="{{si}}"
+      />
+      <view class="cart-store__content">
+        <view class="store-title">
+          <t-icon prefix="wr" size="40rpx" color="#333333" name="store" />
+          <view class="store-name">{{store.storeName}}</view>
+        </view>
+        <view class="get-coupon" catch:tap="gotoCoupons">浼樻儬鍒�</view>
+      </view>
+    </view>
+    <block wx:for="{{store.promotionGoodsList}}" wx:for-item="promotion" wx:for-index="promoindex" wx:key="promoindex">
+      <view
+        class="promotion-wrap"
+        wx:if="{{handlePromotion.hasPromotion(promotion.promotionCode)}}"
+        bindtap="gotoBuyMore"
+        data-promotion="{{promotion}}"
+        data-store-id="{{store.storeId}}"
+      >
+        <view class="promotion-title">
+          <view class="promotion-icon">{{promotion.tag}}</view>
+          <view class="promotion-text">{{promotion.description}}</view>
+        </view>
+        <view class="promotion-action action-btn" hover-class="action-btn--active">
+          <view class="promotion-action-label"> {{promotion.isNeedAddOnShop == 1 ? '鍘诲噾鍗�' : '鍐嶉�涢��'}} </view>
+          <t-icon name="chevron-right" size="32rpx" color="#BBBBBB" />
+        </view>
+      </view>
+      <view
+        class="goods-item"
+        wx:for="{{promotion.goodsPromotionList}}"
+        wx:for-item="goods"
+        wx:for-index="gi"
+        wx:key="extKey"
+      >
+        <swipeout right-width="{{ 72 }}">
+          <view class="goods-item-info">
+            <view class="check-wrap" catchtap="selectGoods" data-goods="{{goods}}">
+              <t-icon
+                size="40rpx"
+                color="{{goods.isSelected ? '#FA4126' : '#BBBBBB'}}"
+                name="{{goods.isSelected ? 'check-circle-filled' : 'circle'}}"
+                class="check"
+              />
+            </view>
+            <view class="goods-sku-info">
+              <goods-card
+                layout="horizontal-wrap"
+                thumb-width="{{thumbWidth}}"
+                thumb-height="{{thumbHeight}}"
+                centered="{{true}}"
+                data="{{goods}}"
+                data-goods="{{goods}}"
+                catchspecs="specsTap"
+                catchclick="goGoodsDetail"
+              >
+                <view slot="thumb-cover" class="stock-mask" wx:if="{{goods.shortageStock || goods.stockQuantity <= 3}}">
+                  浠呭墿{{goods.stockQuantity}}浠�
+                </view>
+                <view slot="append-body" class="goods-stepper">
+                  <view class="stepper-tip" wx:if="{{goods.shortageStock}}">搴撳瓨涓嶈冻</view>
+                  <t-stepper
+                    classname="stepper-info"
+                    value="{{goods.quantity}}"
+                    min="{{1}}"
+                    max="{{999}}"
+                    data-goods="{{goods}}"
+                    data-gi="{{gi}}"
+                    data-si="{{si}}"
+                    catchchange="changeStepper"
+                    catchblur="input"
+                    catchoverlimit="overlimit"
+                    theme="filled"
+                  />
+                </view>
+              </goods-card>
+            </view>
+          </view>
+          <view slot="right" class="swiper-right-del" bindtap="deleteGoods" data-goods="{{goods}}"> 鍒犻櫎 </view>
+        </swipeout>
+      </view>
+      <view
+        class="promotion-line-wrap"
+        wx:if="{{handlePromotion.hasPromotion(promotion.promotionCode) && promoindex != (store.promotionGoodsList.length - 2)}}"
+      >
+        <view class="promotion-line" />
+      </view>
+    </block>
+    <block wx:if="{{store.shortageGoodsList.length>0}}">
+      <view
+        class="goods-item"
+        wx:for="{{store.shortageGoodsList}}"
+        wx:for-item="goods"
+        wx:for-index="gi"
+        wx:key="extKey"
+      >
+        <swipeout right-width="{{ 72 }}">
+          <view class="goods-item-info">
+            <view class="check-wrap">
+              <view class="unCheck-icon" />
+            </view>
+            <view class="goods-sku-info">
+              <goods-card
+                layout="horizontal-wrap"
+                thumb-width="{{thumbWidth}}"
+                thumb-height="{{thumbHeight}}"
+                centered="{{true}}"
+                data="{{goods}}"
+                data-goods="{{goods}}"
+                catchspecs="specsTap"
+                catchclick="goGoodsDetail"
+              >
+                <view slot="thumb-cover" class="no-storage-mask" wx:if="{{goods.stockQuantity <=0}}">
+                  <view class="no-storage-content">鏃犺揣</view>
+                </view>
+              </goods-card>
+            </view>
+          </view>
+          <view slot="right" class="swiper-right-del" bindtap="deleteGoods" data-goods="{{goods}}"> 鍒犻櫎 </view>
+        </swipeout>
+      </view>
+      <view
+        class="promotion-line-wrap"
+        wx:if="{{handlePromotion.hasPromotion(promotion.promotionCode) && promoindex != (store.promotionGoodsList.length - 2)}}"
+      >
+        <view class="promotion-line" />
+      </view>
+    </block>
+  </view>
+</view>
+<specs-popup
+  show="{{isShowSpecs}}"
+  title="{{currentGoods.title || ''}}"
+  price="{{currentGoods.price || ''}}"
+  thumb="{{utils.imgCut(currentGoods.thumb, 180, 180)}}"
+  specs="{{currentGoods.specs || []}}"
+  zIndex="{{999}}"
+  bindclose="hideSpecsPopup"
+/>
+
+<t-toast id="t-toast" />
diff --git a/pages/cart/components/cart-group/index.wxs b/pages/cart/components/cart-group/index.wxs
new file mode 100644
index 0000000..39f1e0b
--- /dev/null
+++ b/pages/cart/components/cart-group/index.wxs
@@ -0,0 +1,5 @@
+var hasPromotion = function (code) {
+  return code && code !== 'EMPTY_PROMOTION';
+};
+
+module.exports.hasPromotion = hasPromotion;
diff --git a/pages/cart/components/cart-group/index.wxss b/pages/cart/components/cart-group/index.wxss
new file mode 100644
index 0000000..641101f
--- /dev/null
+++ b/pages/cart/components/cart-group/index.wxss
@@ -0,0 +1,335 @@
+.cart-group {
+  border-radius: 8rpx;
+}
+.cart-group .goods-wrap {
+  margin-top: 40rpx;
+  background-color: #fff;
+  border-radius: 8rpx;
+  overflow: hidden;
+}
+.cart-group .goods-wrap:first-of-type {
+  margin-top: 0;
+}
+.cart-group .cart-store {
+  height: 96rpx;
+  background-color: #fff;
+  box-sizing: border-box;
+  display: flex;
+  align-items: center;
+  padding: 0rpx 24rpx 0rpx 36rpx;
+}
+.cart-group .cart-store .cart-store__check {
+  padding: 28rpx 32rpx 28rpx 0rpx;
+}
+.cart-group .cart-store__content {
+  box-sizing: border-box;
+  flex: auto;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+.cart-group .cart-store__content .store-title {
+  flex: auto;
+  font-size: 28rpx;
+  line-height: 40rpx;
+  color: #333333;
+  display: flex;
+  align-items: center;
+  font-weight: bold;
+  overflow: hidden;
+}
+
+.cart-group .cart-store__content .store-title .wr-store {
+  font-size: 32rpx;
+}
+.cart-group .cart-store__content .store-title .store-name {
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  margin-left: 12rpx;
+}
+.cart-group .cart-store__content .get-coupon {
+  width: 112rpx;
+  height: 40rpx;
+  border-radius: 20rpx;
+  background-color: #ffecf9;
+  line-height: 40rpx;
+  text-align: center;
+  font-size: 26rpx;
+  color: #fa4126;
+}
+
+.cart-group .promotion-wrap {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 0rpx 24rpx 32rpx 36rpx;
+  background-color: #ffffff;
+  font-size: 24rpx;
+  line-height: 36rpx;
+  color: #222427;
+}
+.cart-group .promotion-wrap .promotion-title {
+  font-weight: bold;
+  flex: auto;
+  overflow: hidden;
+  margin-right: 20rpx;
+  display: flex;
+  align-items: center;
+}
+.cart-group .promotion-wrap .promotion-title .promotion-icon {
+  flex: none;
+  font-weight: normal;
+  display: inline-block;
+  padding: 0 8rpx;
+  color: #ffffff;
+  background: #fa4126;
+  font-size: 20rpx;
+  height: 32rpx;
+  line-height: 32rpx;
+  margin-right: 16rpx;
+  border-radius: 16rpx;
+}
+.cart-group .promotion-wrap .promotion-title .promotion-text {
+  flex: auto;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+.cart-group .promotion-wrap .promotion-action {
+  flex: none;
+  color: #333333;
+}
+.cart-group .promotion-line-wrap {
+  background-color: #fff;
+  height: 2rpx;
+  display: flex;
+  justify-content: flex-end;
+}
+.cart-group .promotion-line-wrap .promotion-line {
+  width: 684rpx;
+  height: 2rpx;
+  background-color: #e6e6e6;
+}
+.cart-group .goods-item-info {
+  display: flex;
+  background-color: #fff;
+  align-items: flex-start;
+}
+.cart-group .goods-item-info .check-wrap {
+  margin-top: 56rpx;
+  padding: 20rpx 28rpx 20rpx 36rpx;
+}
+
+.cart-group .goods-item-info .check-wrap .unCheck-icon {
+  box-sizing: border-box;
+  width: 36rpx;
+  height: 36rpx;
+  border-radius: 20rpx;
+  background: #f5f5f5;
+  border: 2rpx solid #bbbbbb;
+}
+
+.cart-group .goods-item-info .goods-sku-info {
+  padding: 0rpx 32rpx 40rpx 0;
+  flex-grow: 1;
+}
+.cart-group .goods-item-info .goods-sku-info .stock-mask {
+  position: absolute;
+  color: #fff;
+  font-size: 24rpx;
+  bottom: 0rpx;
+  background-color: rgba(0, 0, 0, 0.5);
+  width: 100%;
+  height: 40rpx;
+  line-height: 40rpx;
+  text-align: center;
+}
+.cart-group .goods-item-info .goods-sku-info .goods-stepper {
+  position: absolute;
+  right: 0;
+  bottom: 8rpx;
+}
+.cart-group .goods-item-info .goods-sku-info .goods-stepper .stepper-tip {
+  position: absolute;
+  top: -36rpx;
+  right: 0;
+  height: 28rpx;
+  color: #ff2525;
+  font-size: 20rpx;
+  line-height: 28rpx;
+}
+
+.cart-group .shortage-line {
+  width: 662rpx;
+  height: 2rpx;
+  background-color: #e6e6e6;
+  margin: 0 auto;
+}
+.cart-group .shortage-goods-wrap {
+  background-color: #fff;
+}
+.cart-group .shortage-goods-wrap .shortage-tip-title {
+  height: 72rpx;
+  line-height: 72rpx;
+  padding-left: 28rpx;
+  font-size: 24rpx;
+  color: #999;
+}
+.stepper-info {
+  margin-left: auto;
+}
+.invalid-goods-wrap {
+  background-color: #fff;
+  border-radius: 8rpx;
+  margin-top: 40rpx;
+}
+.invalid-goods-wrap .invalid-head {
+  display: flex;
+  justify-content: space-between;
+  padding: 30rpx 20rpx;
+  font-size: 24rpx;
+  border-bottom: 2rpx solid #f6f6f6;
+}
+.invalid-goods-wrap .invalid-head .invalid-title {
+  color: #333;
+  font-size: 28rpx;
+  font-weight: 600;
+}
+.invalid-goods-wrap .invalid-head .invalid-clear {
+  color: #fa4126;
+}
+.invalid-goods-wrap .toggle {
+  display: flex;
+  height: 80rpx;
+  justify-content: center;
+  align-items: center;
+  font-size: 24rpx;
+  color: #fa4126;
+}
+.invalid-goods-wrap .toggle .m-r-6 {
+  margin-right: 6rpx;
+}
+.invalid-goods-wrap .toggle .top-icon {
+  display: inline-block;
+  width: 0;
+  height: 0;
+  border-left: 10rpx solid transparent;
+  border-right: 10rpx solid transparent;
+  border-bottom: 10rpx solid #fa4126;
+}
+.invalid-goods-wrap .toggle .down-icon {
+  display: inline-block;
+  width: 0;
+  height: 0;
+  border-left: 10rpx solid transparent;
+  border-right: 10rpx solid transparent;
+  border-top: 10rpx solid #fa4126;
+}
+.action-btn {
+  display: flex;
+  align-items: center;
+}
+.action-btn .action-btn-arrow {
+  font-size: 20rpx;
+  margin-left: 8rpx;
+}
+.action-btn--active {
+  opacity: 0.5;
+}
+
+.swiper-right-del {
+  height: calc(100% - 40rpx);
+  width: 144rpx;
+  background-color: #fa4126;
+  font-size: 28rpx;
+  color: white;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.goods-stepper .stepper {
+  border: none;
+  border-radius: 0;
+  height: auto;
+  width: 168rpx;
+  overflow: visible;
+}
+.goods-stepper .stepper .stepper__minus,
+.goods-stepper .stepper .stepper__plus {
+  width: 44rpx;
+  height: 44rpx;
+  background-color: #f5f5f5;
+}
+.goods-stepper .stepper .stepper__minus--hover,
+.goods-stepper .stepper .stepper__plus--hover {
+  background-color: #f5f5f5;
+}
+.goods-stepper .stepper .stepper__minus .wr-icon,
+.goods-stepper .stepper .stepper__plus .wr-icon {
+  font-size: 24rpx;
+}
+.goods-stepper .stepper .stepper__minus {
+  position: relative;
+}
+.goods-stepper .stepper .stepper__minus::after {
+  position: absolute;
+  display: block;
+  content: ' ';
+  left: -20rpx;
+  right: -5rpx;
+  top: -20rpx;
+  bottom: -20rpx;
+  background-color: transparent;
+}
+.goods-stepper .stepper .stepper__plus {
+  position: relative;
+}
+.goods-stepper .stepper .stepper__plus::after {
+  position: absolute;
+  display: block;
+  content: ' ';
+  left: -5rpx;
+  right: -20rpx;
+  top: -20rpx;
+  bottom: -20rpx;
+  background-color: transparent;
+}
+.goods-stepper .stepper .stepper__input {
+  width: 72rpx;
+  height: 44rpx;
+  background-color: #f5f5f5;
+  font-size: 24rpx;
+  color: #222427;
+  font-weight: 600;
+  border-left: none;
+  border-right: none;
+  min-height: 40rpx;
+  margin: 0 4rpx;
+  display: flex;
+  align-items: center;
+}
+
+.goods-sku-info .no-storage-mask {
+  position: absolute;
+  color: #fff;
+  bottom: 0rpx;
+  left: 0rpx;
+  background-color: rgba(0, 0, 0, 0.1);
+  height: 192rpx;
+  width: 192rpx;
+  border-radius: 8rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.no-storage-mask .no-storage-content {
+  width: 128rpx;
+  height: 128rpx;
+  border-radius: 64rpx;
+  background-color: rgba(0, 0, 0, 0.4);
+  text-align: center;
+  line-height: 128rpx;
+  font-size: 28rpx;
+}
diff --git a/pages/cart/components/cart-group/utils.wxs b/pages/cart/components/cart-group/utils.wxs
new file mode 100644
index 0000000..f887eba
--- /dev/null
+++ b/pages/cart/components/cart-group/utils.wxs
@@ -0,0 +1,20 @@
+module.exports.slice = function(arr) {
+  return arr.slice(0, 2);
+};
+module.exports.imgCut = function(url, width, height) {
+  if (url && (url.slice(0, 5) === 'http:' || url.slice(0, 6) === 'https:' || url.slice(0, 2) === '//')) {
+    var argsStr = 'imageMogr2/thumbnail/!' + width +  'x' + height + 'r';
+    if (url.indexOf('?') > -1) {
+      url = url + '&' + argsStr;
+    } else {
+      url = url + '?' + argsStr;
+    }
+    if (url.slice(0, 5) === 'http:') {
+      url = 'https://' + url.slice(5)
+    }
+    if (url.slice(0, 2) === '//') {
+      url = 'https:' + url
+    }
+  }
+  return url;
+};
diff --git a/pages/cart/components/goods-card/index.js b/pages/cart/components/goods-card/index.js
new file mode 100644
index 0000000..c59658c
--- /dev/null
+++ b/pages/cart/components/goods-card/index.js
@@ -0,0 +1,243 @@
+Component({
+  options: {
+    multipleSlots: true, // 鍦ㄧ粍浠跺畾涔夋椂鐨勯�夐」涓惎鐢ㄥslot鏀寔
+    addGlobalClass: true,
+  },
+  intersectionObserverContext: null,
+
+  externalClasses: [
+    'card-class',
+    'title-class',
+    'desc-class',
+    'num-class',
+    'thumb-class',
+    'specs-class',
+    'price-class',
+    'origin-price-class',
+    'price-prefix-class',
+  ],
+
+  properties: {
+    hidden: {
+      // 璁剧疆涓簄ull浠h〃涓嶅仛绫诲瀷杞崲
+      type: null,
+      value: false,
+      observer(hidden) {
+        // null灏辨槸浠h〃娌℃湁璁剧疆锛屾病鏈夎缃殑璇濅笉setData锛岄槻姝㈢鍏堢粍浠惰Е鍙戠殑setHidden鎿嶄綔琚鐩�
+        if (hidden !== null) {
+          this.setHidden(!!hidden);
+        }
+      },
+    },
+    id: {
+      type: String,
+      // `goods-card-88888888`
+      // 涓嶈兘鍦ㄨ繖閲屽啓鐢熸垚閫昏緫锛屽鏋滃湪杩欓噷鍐欙紝閭d箞鍋囪鏈夊涓猤oods-list鏃讹紝浠栦滑灏嗗叡浜繖涓��
+      value: '',
+      observer: (id) => {
+        this.genIndependentID(id);
+        if (this.properties.thresholds?.length) {
+          this.createIntersectionObserverHandle();
+        }
+      },
+    },
+    data: {
+      type: Object,
+      observer(goods) {
+        // 鏈塈D鐨勫晢鍝佹墠娓叉煋
+        if (!goods) {
+          return;
+        }
+
+        /** 鍒掔嚎浠锋槸鍚︽湁鏁� */
+        let isValidityLinePrice = true;
+        // 鍒ゆ柇涓�娆″垝绾夸环鏍兼槸鍚﹀悎鐞�
+        if (
+          goods.originPrice &&
+          goods.price &&
+          goods.originPrice < goods.price
+        ) {
+          isValidityLinePrice = false;
+        }
+
+        // 鏁插畾鎹㈣鏁伴噺榛樿鍊�
+        if (goods.lineClamp === undefined || goods.lineClamp <= 0) {
+          // tag鏁扮粍闀垮害 澶т簬0 涓� 鍙
+          // 鎸囧畾鎹㈣涓�1琛�
+          if ((goods.tags?.length || 0) > 0 && !goods.hideKey?.tags) {
+            goods.lineClamp = 1;
+          } else {
+            goods.lineClamp = 2;
+          }
+        }
+
+        this.setData({ goods, isValidityLinePrice });
+      },
+    },
+    layout: {
+      type: String,
+      value: 'horizontal',
+    },
+    thumbMode: {
+      type: String,
+      value: 'aspectFill',
+    },
+    priceFill: {
+      type: Boolean,
+      value: true,
+    },
+    currency: {
+      type: String,
+      value: '楼',
+    },
+    lazyLoad: {
+      type: Boolean,
+      value: false,
+    },
+    centered: {
+      type: Boolean,
+      value: false,
+    },
+    pricePrefix: {
+      type: String,
+      value: '',
+    },
+    /** 鍏冪礌鍙鐩戞帶闃堝��, 鏁扮粍闀垮害澶т簬0灏卞垱寤� */
+    thresholds: {
+      type: Array,
+      value: [],
+      observer(current) {
+        if (current && current.length) {
+          this.createIntersectionObserverHandle();
+        } else {
+          this.clearIntersectionObserverHandle();
+        }
+      },
+    },
+    specsIconClassPrefix: {
+      type: String,
+      value: 'wr',
+    },
+    specsIcon: {
+      type: String,
+      value: 'expand_more',
+    },
+    addCartIconClassPrefix: {
+      type: String,
+      value: 'wr',
+    },
+    addCartIcon: {
+      type: String,
+      value: 'cart',
+    },
+  },
+
+  data: {
+    hiddenInData: false,
+    independentID: '',
+    goods: { id: '' },
+    /** 淇濊瘉鍒掔嚎浠锋牸涓嶅皬浜庡師浠凤紝鍚﹀垯涓嶆覆鏌撳垝绾夸环 */
+    isValidityLinePrice: false,
+  },
+
+  lifetimes: {
+    ready() {
+      this.init();
+    },
+    detached() {
+      this.clear();
+    },
+  },
+
+  methods: {
+    clickHandle() {
+      this.triggerEvent('click', { goods: this.data.goods });
+    },
+    clickThumbHandle() {
+      this.triggerEvent('thumb', { goods: this.data.goods });
+    },
+    clickSpecsHandle() {
+      this.triggerEvent('specs', { goods: this.data.goods });
+    },
+    clickTagHandle(evt) {
+      const { index } = evt.currentTarget.dataset;
+      this.triggerEvent('tag', { goods: this.data.goods, index });
+    },
+    // 鍔犲叆璐墿杞�
+    addCartHandle(e) {
+      const { id } = e.currentTarget;
+      const { id: cardID } = e.currentTarget.dataset;
+      this.triggerEvent('add-cart', {
+        ...e.detail,
+        id,
+        cardID,
+        goods: this.data.goods,
+      });
+    },
+    genIndependentID(id, cb) {
+      let independentID;
+      if (id) {
+        independentID = id;
+      } else {
+        independentID = `goods-card-${~~(Math.random() * 10 ** 8)}`;
+      }
+      this.setData({ independentID }, cb);
+    },
+
+    init() {
+      const { thresholds, id, hidden } = this.properties;
+      if (hidden !== null) {
+        this.setHidden(!!hidden);
+      }
+
+      this.genIndependentID(id || '', () => {
+        if (thresholds && thresholds.length) {
+          this.createIntersectionObserverHandle();
+        }
+      });
+    },
+
+    clear() {
+      this.clearIntersectionObserverHandle();
+    },
+
+    setHidden(hidden) {
+      this.setData({ hiddenInData: !!hidden });
+    },
+
+    createIntersectionObserverHandle() {
+      if (this.intersectionObserverContext || !this.data.independentID) {
+        return;
+      }
+
+      this.intersectionObserverContext = wx
+        .createIntersectionObserver(this, {
+          thresholds: this.properties.thresholds,
+        })
+        .relativeToViewport();
+
+      this.intersectionObserverContext.observe(
+        `#${this.data.independentID}`,
+        (res) => {
+          this.intersectionObserverCB(res);
+        },
+      );
+    },
+    intersectionObserverCB(ob) {
+      this.triggerEvent('ob', {
+        goods: this.data.goods,
+        context: this.intersectionObserverContext,
+        ob,
+      });
+    },
+    clearIntersectionObserverHandle() {
+      if (this.intersectionObserverContext) {
+        try {
+          this.intersectionObserverContext.disconnect();
+        } catch (e) {}
+
+        this.intersectionObserverContext = null;
+      }
+    },
+  },
+});
diff --git a/pages/cart/components/goods-card/index.json b/pages/cart/components/goods-card/index.json
new file mode 100644
index 0000000..d76303b
--- /dev/null
+++ b/pages/cart/components/goods-card/index.json
@@ -0,0 +1,9 @@
+{
+  "component": true,
+  "usingComponents": {
+    "price": "/components/price/index",
+    "t-tag": "tdesign-miniprogram/tag/tag",
+    "t-image": "/components/webp-image/index",
+    "t-icon": "tdesign-miniprogram/icon/icon"
+  }
+}
\ No newline at end of file
diff --git a/pages/cart/components/goods-card/index.wxml b/pages/cart/components/goods-card/index.wxml
new file mode 100644
index 0000000..df4111f
--- /dev/null
+++ b/pages/cart/components/goods-card/index.wxml
@@ -0,0 +1,75 @@
+<view
+  id="{{independentID}}"
+  class="wr-goods-card card-class {{ layout }} {{ centered ? 'center' : ''}}"
+  bind:tap="clickHandle"
+  data-goods="{{ goods }}"
+  hidden="{{hiddenInData}}"
+>
+	<view class="wr-goods-card__main">
+		<view class="wr-goods-card__thumb thumb-class" bind:tap="clickThumbHandle">
+			<!-- data-src 鏄柟渚垮姞璐姩鐢昏鍙栧浘鐗囩敤鐨� -->
+			<t-image
+			  t-class="wr-goods-card__thumb-com"
+			  wx:if="{{ !!goods.thumb && !goods.hideKey.thumb }}"
+			  src="{{ goods.thumb }}"
+			  mode="{{ thumbMode }}"
+			  lazy-load="{{ lazyLoad }}"
+			/>
+			<slot name="thumb-cover" />
+		</view>
+		<view class="wr-goods-card__body">
+			<view class="wr-goods-card__long_content">
+				<view wx:if="{{ goods.title && !goods.hideKey.title }}" class="wr-goods-card__title title-class" style="-webkit-line-clamp: {{ goods.lineClamp }};">
+					<slot name="before-title" />
+					{{ goods.title }}
+				</view>
+				<slot name="after-title" />
+				<view wx:if="{{ goods.desc && !goods.hideKey.desc }}" class="wr-goods-card__desc desc-class">{{ goods.desc }}</view>
+				<slot name="after-desc" />
+				<view wx:if="{{ goods.specs && goods.specs.length > 0 && !goods.hideKey.specs }}" class="wr-goods-card__specs__desc specs-class" bind:tap="clickSpecsHandle">
+					<view class="wr-goods-card__specs__desc-text">{{ goods.specs }}</view>
+					<t-icon name="chevron-down" size="32rpx" color="#999999" />
+				</view>
+				<view class="goods_tips" wx:if="{{goods.stockQuantity !== 0 && goods.quantity >= goods.stockQuantity}}">搴撳瓨涓嶈冻</view>
+			</view>
+			<view class="wr-goods-card__short_content">
+				<block wx:if="{{goods.stockQuantity !== 0}}">
+					<view wx:if="{{ pricePrefix }}" class="wr-goods-card__price__prefix price-prefix-class">{{ pricePrefix }}</view>
+					<slot name="price-prefix" />
+					<view wx:if="{{ goods.price && !goods.hideKey.price }}" class="wr-goods-card__price">
+						<price
+						  wr-class="price-class"
+						  symbol="{{currency}}"
+						  price="{{goods.price}}"
+						  fill="{{priceFill}}"
+						  decimalSmaller
+						/>
+					</view>
+					<view wx:if="{{ goods.originPrice && !goods.hideKey.originPrice && isValidityLinePrice }}" class="wr-goods-card__origin-price">
+						<price
+						  wr-class="origin-price-class"
+						  symbol="{{currency}}"
+						  price="{{goods.originPrice}}"
+						  fill="{{priceFill}}"
+						/>
+					</view>
+					<slot name="origin-price" />
+					<view wx:if="{{goods.num && !goods.hideKey.num}}" class="wr-goods-card__num num-class">
+						<text class="wr-goods-card__num__prefix">x </text>
+						{{ goods.num }}
+					</view>
+				</block>
+				<block wx:else>
+					<view class="no_storage">
+						<view>璇烽噸鏂伴�夋嫨鍟嗗搧瑙勬牸</view>
+						<view class="no_storage__right">閲嶉��</view>
+					</view>
+				</block>
+			</view>
+			<slot name="append-body" />
+		</view>
+		<slot name="footer" />
+	</view>
+	<slot name="append-card" />
+</view>
+
diff --git a/pages/cart/components/goods-card/index.wxss b/pages/cart/components/goods-card/index.wxss
new file mode 100644
index 0000000..6a7a4da
--- /dev/null
+++ b/pages/cart/components/goods-card/index.wxss
@@ -0,0 +1,260 @@
+.wr-goods-card {
+  box-sizing: border-box;
+  font-size: 24rpx;
+}
+/*  */
+.wr-goods-card__main {
+  position: relative;
+  display: flex;
+  padding: 0;
+  background: transparent;
+}
+
+.wr-goods-card.center .wr-goods-card__main {
+  align-items: flex-start;
+  justify-content: center;
+}
+
+.wr-goods-card__thumb {
+  flex-shrink: 0;
+  position: relative;
+  width: 140rpx;
+  height: 140rpx;
+}
+
+.wr-goods-card__thumb-com {
+  width: 192rpx;
+  height: 192rpx;
+  border-radius: 8rpx;
+  overflow: hidden;
+}
+.wr-goods-card__thumb:empty {
+  display: none;
+  margin: 0;
+}
+
+.wr-goods-card__body {
+  display: flex;
+  margin: 0 0 0 20rpx;
+  flex-direction: row;
+  flex: 1 1 auto;
+  min-height: 192rpx;
+}
+
+.wr-goods-card__long_content {
+  display: flex;
+  flex-direction: column;
+  overflow: hidden;
+  flex: 1 1 auto;
+}
+.wr-goods-card__long_content .goods_tips {
+  width: 100%;
+  margin-top: 16rpx;
+  text-align: right;
+  color: #fa4126;
+  font-size: 24rpx;
+  line-height: 32rpx;
+  font-weight: bold;
+}
+.wr-goods-card__title {
+  flex-shrink: 0;
+  font-size: 28rpx;
+  color: #333;
+  line-height: 40rpx;
+  font-weight: 400;
+  display: -webkit-box;
+  -webkit-box-orient: vertical;
+  overflow: hidden;
+  word-break: break-word;
+}
+.wr-goods-card__title__prefix-tags {
+  display: inline-flex;
+}
+.wr-goods-card__title__prefix-tags .prefix-tag {
+  margin: 0 8rpx 0 0;
+}
+.wr-goods-card__desc {
+  font-size: 24rpx;
+  color: #f5f5f5;
+  line-height: 40rpx;
+  display: -webkit-box;
+  -webkit-box-orient: vertical;
+  -webkit-line-clamp: 2;
+  overflow: hidden;
+}
+.wr-goods-card__specs__desc,
+.wr-goods-card__specs__text {
+  font-size: 24rpx;
+  height: 32rpx;
+  line-height: 32rpx;
+  color: #999999;
+  margin: 8rpx 0;
+}
+.wr-goods-card__specs__desc {
+  display: flex;
+  align-self: flex-start;
+  flex-direction: row;
+  background: #f5f5f5;
+  border-radius: 8rpx;
+  padding: 4rpx 8rpx;
+}
+.wr-goods-card__specs__desc-text {
+  height: 100%;
+  max-width: 380rpx;
+  word-break: break-all;
+  overflow: hidden;
+  display: -webkit-box;
+  -webkit-box-orient: vertical;
+  -webkit-line-clamp: 1;
+}
+.wr-goods-card__specs__desc-icon {
+  line-height: inherit;
+  margin-left: 8rpx;
+  font-size: 24rpx;
+  color: #bbb;
+}
+.wr-goods-card__specs__text {
+  display: -webkit-box;
+  -webkit-box-orient: vertical;
+  -webkit-line-clamp: 1;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  word-break: break-all;
+}
+.wr-goods-card__tags {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+  margin: 16rpx 0 0 0;
+}
+.wr-goods-card__tag {
+  color: #fa550f;
+  background: transparent;
+  font-size: 20rpx;
+  border: 1rpx solid #fa550f;
+  padding: 0 8rpx;
+  height: 30rpx;
+  line-height: 30rpx;
+  margin: 0 8rpx 8rpx 0;
+  display: block;
+  overflow: hidden;
+  white-space: nowrap;
+  word-break: keep-all;
+  text-overflow: ellipsis;
+}
+.wr-goods-card__short_content {
+  display: flex;
+  flex-direction: column;
+  justify-content: flex-start;
+  align-items: flex-end;
+  margin: 0 0 0 46rpx;
+}
+.wr-goods-card__price__prefix {
+  order: 0;
+  color: #666;
+  margin: 0;
+}
+.wr-goods-card__price {
+  white-space: nowrap;
+  font-weight: bold;
+  order: 1;
+  color: #fa4126;
+  font-size: 36rpx;
+  margin: 0;
+  line-height: 48rpx;
+}
+.wr-goods-card__origin-price {
+  white-space: nowrap;
+  font-weight: normal;
+  order: 2;
+  color: #aaaaaa;
+  font-size: 24rpx;
+  margin: 0;
+}
+.wr-goods-card__num {
+  white-space: nowrap;
+  order: 4;
+  font-size: 24rpx;
+  color: #999;
+  margin: 20rpx 0 0 auto;
+}
+.wr-goods-card__num__prefix {
+  color: inherit;
+}
+.wr-goods-card__add-cart {
+  order: 3;
+  margin: auto 0 0 auto;
+}
+.wr-goods-card.horizontal-wrap .wr-goods-card__thumb {
+  width: 192rpx;
+  height: 192rpx;
+  border-radius: 8rpx;
+  overflow: hidden;
+}
+.wr-goods-card.horizontal-wrap .wr-goods-card__body {
+  flex-direction: column;
+}
+.wr-goods-card.horizontal-wrap .wr-goods-card__short_content {
+  flex-direction: row;
+  align-items: center;
+  margin: 16rpx 0 0 0;
+}
+
+.wr-goods-card.horizontal-wrap .wr-goods-card__num {
+  margin: 0 0 0 auto;
+}
+.wr-goods-card.vertical .wr-goods-card__main {
+  padding: 0 0 22rpx 0;
+  flex-direction: column;
+}
+.wr-goods-card.vertical .wr-goods-card__thumb {
+  width: 340rpx;
+  height: 340rpx;
+}
+.wr-goods-card.vertical .wr-goods-card__body {
+  margin: 20rpx 20rpx 0 20rpx;
+  flex-direction: column;
+}
+.wr-goods-card.vertical .wr-goods-card__long_content {
+  overflow: hidden;
+}
+.wr-goods-card.vertical .wr-goods-card__title {
+  line-height: 36rpx;
+}
+.wr-goods-card.vertical .wr-goods-card__short_content {
+  margin: 20rpx 0 0 0;
+}
+.wr-goods-card.vertical .wr-goods-card__price {
+  order: 2;
+  color: #fa4126;
+  margin: 20rpx 0 0 0;
+}
+.wr-goods-card.vertical .wr-goods-card__origin-price {
+  order: 1;
+}
+.wr-goods-card.vertical .wr-goods-card__add-cart {
+  position: absolute;
+  bottom: 20rpx;
+  right: 20rpx;
+}
+
+.wr-goods-card__short_content .no_storage {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  height: 40rpx;
+  color: #333;
+  font-size: 24rpx;
+  line-height: 32rpx;
+  width: 100%;
+}
+
+.no_storage .no_storage__right {
+  width: 80rpx;
+  height: 40rpx;
+  border-radius: 20rpx;
+  border: 2rpx solid #fa4126;
+  line-height: 40rpx;
+  text-align: center;
+  color: #fa4126;
+}
diff --git a/pages/cart/components/specs-popup/index.js b/pages/cart/components/specs-popup/index.js
new file mode 100644
index 0000000..650d2aa
--- /dev/null
+++ b/pages/cart/components/specs-popup/index.js
@@ -0,0 +1,72 @@
+Component({
+  options: {
+    addGlobalClass: true,
+    multipleSlots: true, // 鍦ㄧ粍浠跺畾涔夋椂鐨勯�夐」涓惎鐢ㄥslot鏀寔
+  },
+
+  properties: {
+    show: {
+      type: Boolean,
+      value: false,
+    },
+    value: {
+      type: String,
+      value: '',
+    },
+    title: {
+      type: String,
+      observer(newVal) {
+        this.setData({ 'goods.title': newVal });
+      },
+    },
+    price: {
+      type: String,
+      value: '',
+      observer(newVal) {
+        this.setData({ 'goods.price': newVal });
+      },
+    },
+    thumb: {
+      type: String,
+      value: '',
+      observer(newVal) {
+        this.setData({ 'goods.thumb': newVal });
+      },
+    },
+    thumbMode: {
+      type: String,
+      value: 'aspectFit',
+    },
+    zIndex: {
+      type: Number,
+      value: 99,
+    },
+    specs: {
+      type: Array,
+      value: [],
+    },
+  },
+
+  data: {
+    goods: {
+      title: '',
+      thumb: '',
+      price: '',
+      hideKey: {
+        originPrice: true,
+        tags: true,
+        specs: true,
+        num: true,
+      },
+    },
+  },
+  methods: {
+    onClose() {
+      this.triggerEvent('close');
+    },
+
+    onCloseOver() {
+      this.triggerEvent('closeover');
+    },
+  },
+});
diff --git a/pages/cart/components/specs-popup/index.wxml b/pages/cart/components/specs-popup/index.wxml
new file mode 100644
index 0000000..4ddcb43
--- /dev/null
+++ b/pages/cart/components/specs-popup/index.wxml
@@ -0,0 +1,26 @@
+<t-popup
+  close-on-overlay-click="{{true}}"
+  visible="{{show}}"
+  placement="bottom"
+  z-index="{{zIndex}}"
+>
+	<view class="specs-popup">
+		<view>
+			<goods-card data="{{goods}}" layout="horizontal-wrap" thumb-mode="{{thumbMode}}" />
+			<view class="section">
+				<view class="title">宸查�夎鏍�</view>
+				<view class="options">
+					<view
+					  wx:for="{{specs}}"
+					  wx:for-item="spec"
+					  wx:key="spec"
+					  class="option"
+					>{{spec}}
+					</view>
+				</view>
+			</view>
+		</view>
+		<view class="bottom-btn" hover-class="bottom-btn--active" bindtap="onClose">鎴戠煡閬撲簡</view>
+	</view>
+</t-popup>
+
diff --git a/pages/cart/components/specs-popup/index.wxss b/pages/cart/components/specs-popup/index.wxss
new file mode 100644
index 0000000..359c185
--- /dev/null
+++ b/pages/cart/components/specs-popup/index.wxss
@@ -0,0 +1,68 @@
+.specs-popup {
+  width: 100vw;
+  box-sizing: border-box;
+  padding: 32rpx 32rpx calc(20rpx + env(safe-area-inset-bottom)) 32rpx;
+  max-height: 80vh;
+  display: flex;
+  flex-direction: column;
+  background-color: white;
+  border-radius: 20rpx 20rpx 0 0;
+}
+.specs-popup .section {
+  margin-top: 44rpx;
+  flex: auto;
+  overflow-y: scroll;
+  overflow-x: hidden;
+  -webkit-overflow-scrolling: touch;
+}
+.specs-popup .section .title {
+  font-size: 26rpx;
+  color: #4f5356;
+}
+.specs-popup .section .options {
+  color: #333333;
+  font-size: 24rpx;
+  margin-right: -26rpx;
+}
+.specs-popup .section .options .option {
+  display: inline-block;
+  margin-top: 24rpx;
+  height: 56rpx;
+  line-height: 56rpx;
+  padding: 0 16rpx;
+  border-radius: 8rpx;
+  background-color: #f5f5f5;
+  max-width: 100%;
+  box-sizing: border-box;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+.specs-popup .section .options .option:not(:last-child) {
+  margin-right: 26rpx;
+}
+.specs-popup .bottom-btn {
+  margin-top: 42rpx;
+  position: relative;
+  height: 80rpx;
+  line-height: 80rpx;
+  text-align: center;
+  background-color: white;
+  color: #fa4126;
+}
+.specs-popup .bottom-btn--active {
+  opacity: 0.5;
+}
+.specs-popup .bottom-btn::after {
+  display: block;
+  content: ' ';
+  position: absolute;
+  left: 0;
+  top: 0;
+  width: 200%;
+  height: 200%;
+  border: 1px solid #fa4126;
+  border-radius: 80rpx;
+  transform: scale(0.5);
+  transform-origin: left top;
+}
diff --git a/pages/cart/index.js b/pages/cart/index.js
index 41fcea5..7622fcd 100644
--- a/pages/cart/index.js
+++ b/pages/cart/index.js
@@ -1,30 +1,18 @@
 // pages/cart/index.js
-const app = getApp()
 Page({
 
   /**
    * 椤甸潰鐨勫垵濮嬫暟鎹�
    */
   data: {
-    right: [
-      {
-        text: '缂栬緫',
-        className: 'btn edit-btn',
-      },
-      {
-        text: '鍒犻櫎',
-        className: 'btn delete-btn',
-      },
-    ],
+
   },
-  onDelete() {
-    wx.showToast({ title: '浣犵偣鍑讳簡鍒犻櫎', icon: 'none' });
-  },
+
   /**
    * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰鍔犺浇
    */
   onLoad(options) {
-    this.shoppingCartGet()
+
   },
 
   /**
@@ -74,16 +62,5 @@
    */
   onShareAppMessage() {
 
-  },
-  shoppingCartGet() {
-
-    app.MG.store.getShoppingCartProductList({
-      start: 0,
-      size: 999,
-      filterList: [],
-      searchList: []
-    }).then(res => {
-      console.log(res);
-    })
   }
 })
\ No newline at end of file
diff --git a/pages/cart/index.wxml b/pages/cart/index.wxml
index 8ffcb80..c533dd9 100644
--- a/pages/cart/index.wxml
+++ b/pages/cart/index.wxml
@@ -1,6 +1,2 @@
 <!--pages/cart/index.wxml-->
-<text>璐墿杞�</text>
-<t-swipe-cell>
-  <t-cell bordered="{{false}}" title="宸︽粦澶у垪琛�" description="涓�娈靛緢闀垮緢闀跨殑鍐呭鏂囧瓧" note="杈呭姪淇℃伅" image="https://tdesign.gtimg.com/mobile/demos/avatar1.png" />
-  <view slot="right" class="btn delete-btn" bind:tap="onDelete">鍒犻櫎</view>
-</t-swipe-cell>
\ No newline at end of file
+<text>pages/cart/index.wxml</text>

--
Gitblit v1.9.1