feat(提交): 代码
好
BREAKING CHANGE: wad
New file |
| | |
| | | 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'); |
| | | }, |
| | | }, |
| | | }); |
New file |
| | |
| | | { |
| | | "component": true, |
| | | "usingComponents": { |
| | | "price": "/components/price/index", |
| | | "t-icon": "tdesign-miniprogram/icon/icon" |
| | | } |
| | | } |
New file |
| | |
| | | <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> |
| | | |
New file |
| | |
| | | .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; |
| | | } |
New file |
| | |
| | | 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'); |
| | | }, |
| | | }, |
| | | }); |
New file |
| | |
| | | { |
| | | "component": true, |
| | | "usingComponents": { |
| | | "t-image": "/components/webp-image/index" |
| | | } |
| | | } |
New file |
| | |
| | | <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> |
| | | |
New file |
| | |
| | | .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; |
| | | } |
New file |
| | |
| | | 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' }); |
| | | }, |
| | | }, |
| | | }); |
New file |
| | |
| | | { |
| | | "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" |
| | | } |
| | | } |
New file |
| | |
| | | <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" /> |
New file |
| | |
| | | var hasPromotion = function (code) { |
| | | return code && code !== 'EMPTY_PROMOTION'; |
| | | }; |
| | | |
| | | module.exports.hasPromotion = hasPromotion; |
New file |
| | |
| | | .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; |
| | | } |
New file |
| | |
| | | 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; |
| | | }; |
New file |
| | |
| | | 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; |
| | | } |
| | | }, |
| | | }, |
| | | }); |
New file |
| | |
| | | { |
| | | "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" |
| | | } |
| | | } |
New file |
| | |
| | | <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> |
| | | |
New file |
| | |
| | | .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; |
| | | } |
New file |
| | |
| | | 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'); |
| | | }, |
| | | }, |
| | | }); |
New file |
| | |
| | | <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> |
| | | |
New file |
| | |
| | | .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 |
| | | 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() |
| | | |
| | | }, |
| | | |
| | | /** |
| | |
| | | */ |
| | | onShareAppMessage() { |
| | | |
| | | }, |
| | | shoppingCartGet() { |
| | | |
| | | app.MG.store.getShoppingCartProductList({ |
| | | start: 0, |
| | | size: 999, |
| | | filterList: [], |
| | | searchList: [] |
| | | }).then(res => { |
| | | console.log(res); |
| | | }) |
| | | } |
| | | }) |
| | |
| | | <!--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> |