yiming
2024-03-01 c899ddfe49c5dedf6e78fc136dd0efdbe3951dfd
feat(提交): 代码



BREAKING CHANGE: wad
2个文件已修改
21个文件已添加
1721 ■■■■■ 已修改文件
pages/cart/components/cart-bar/index.js 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/components/cart-bar/index.json 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/components/cart-bar/index.wxml 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/components/cart-bar/index.wxss 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/components/cart-empty/index.js 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/components/cart-empty/index.json 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/components/cart-empty/index.wxml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/components/cart-empty/index.wxss 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/components/cart-group/index.js 166 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/components/cart-group/index.json 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/components/cart-group/index.wxml 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/components/cart-group/index.wxs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/components/cart-group/index.wxss 335 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/components/cart-group/utils.wxs 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/components/goods-card/index.js 243 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/components/goods-card/index.json 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/components/goods-card/index.wxml 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/components/goods-card/index.wxss 260 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/components/specs-popup/index.js 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/components/specs-popup/index.wxml 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/components/specs-popup/index.wxss 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/index.js 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/index.wxml 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/cart/components/cart-bar/index.js
New file
@@ -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');
    },
  },
});
pages/cart/components/cart-bar/index.json
New file
@@ -0,0 +1,7 @@
{
  "component": true,
  "usingComponents": {
    "price": "/components/price/index",
    "t-icon": "tdesign-miniprogram/icon/icon"
  }
}
pages/cart/components/cart-bar/index.wxml
New file
@@ -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>
pages/cart/components/cart-bar/index.wxss
New file
@@ -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;
}
pages/cart/components/cart-empty/index.js
New file
@@ -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');
    },
  },
});
pages/cart/components/cart-empty/index.json
New file
@@ -0,0 +1,6 @@
{
  "component": true,
  "usingComponents": {
    "t-image": "/components/webp-image/index"
  }
}
pages/cart/components/cart-empty/index.wxml
New file
@@ -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>
pages/cart/components/cart-empty/index.wxss
New file
@@ -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;
}
pages/cart/components/cart-group/index.js
New file
@@ -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触发(由于底层goods-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' });
    },
  },
});
pages/cart/components/cart-group/index.json
New file
@@ -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"
  }
}
pages/cart/components/cart-group/index.wxml
New file
@@ -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" />
pages/cart/components/cart-group/index.wxs
New file
@@ -0,0 +1,5 @@
var hasPromotion = function (code) {
  return code && code !== 'EMPTY_PROMOTION';
};
module.exports.hasPromotion = hasPromotion;
pages/cart/components/cart-group/index.wxss
New file
@@ -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;
}
pages/cart/components/cart-group/utils.wxs
New file
@@ -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;
};
pages/cart/components/goods-card/index.js
New file
@@ -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: {
      // 设置为null代表不做类型转换
      type: null,
      value: false,
      observer(hidden) {
        // null就是代表没有设置,没有设置的话不setData,防止祖先组件触发的setHidden操作被覆盖
        if (hidden !== null) {
          this.setHidden(!!hidden);
        }
      },
    },
    id: {
      type: String,
      // `goods-card-88888888`
      // 不能在这里写生成逻辑,如果在这里写,那么假设有多个goods-list时,他们将共享这个值
      value: '',
      observer: (id) => {
        this.genIndependentID(id);
        if (this.properties.thresholds?.length) {
          this.createIntersectionObserverHandle();
        }
      },
    },
    data: {
      type: Object,
      observer(goods) {
        // 有ID的商品才渲染
        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;
      }
    },
  },
});
pages/cart/components/goods-card/index.json
New file
@@ -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"
  }
}
pages/cart/components/goods-card/index.wxml
New file
@@ -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>
pages/cart/components/goods-card/index.wxss
New file
@@ -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;
}
pages/cart/components/specs-popup/index.js
New file
@@ -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');
    },
  },
});
pages/cart/components/specs-popup/index.wxml
New file
@@ -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>
pages/cart/components/specs-popup/index.wxss
New file
@@ -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;
}
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);
    })
  }
})
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>
<text>pages/cart/index.wxml</text>