您的当前位置:首页正文

“购物车”页面的制作,实现购物车页面的基本功能,包括勾选商品,改变商品数量、“全选”的功能实现。

2024-11-10 来源:个人技术集锦

素材:

wxml代码:

<view>
  <text class="gwc">购物车</text>
  <text class="gl">管理</text>
</view>
<!-- 生效商品区域 -->
<view class="cart-effect">
    <block wx:for="{{cartEffectList}}" wx:key="key" wx:for-item="item">
        <checkbox-group class="check-group" wx:if="{{item.merchandises.length > 0}}">
            <!-- <checkbox class="check-store-all" data-store="{{item.store}}" bind:tap="checkStoreAll" checked="{{item.checked || item.merchandiseChecked}}">
                <view class="store">{{item.store}}</view>
            </checkbox> -->
            <block wx:for="{{item.merchandises}}" wx:key="key" wx:for-item="merchandise">
                <movable-area class="move-area">
                    <movable-view class="move-view" x="{{merchandise.x}}" data-store="{{item.store}}" data-id="{{merchandise.id}}" direction="horizontal" out-of-bounds="true" damping="50" inertia="true" bind:touchstart="touchStart" bind:touchmove="touchMove" bind:touchend="touchEnd" bindchange="touchChange">
                        <view class="info">
                            <checkbox class="merchandise-check" data-store="{{item.store}}" data-merchandise="{{merchandise}}" bind:tap="checkSingle" checked="{{merchandise.checked}}"></checkbox>
                            <view class="merchandise">
                                <image class="merchandise-img" src="{{merchandise.imgUrl}}"></image>
                                <view class="merchandise-name">{{merchandise.name}}</view>
                                <view class="merchandise-price">¥{{merchandise.price}}</view>
                                <view class="merchandise-amount">
                                    <view class="minus" data-store="{{item.store}}" data-id="{{merchandise.id}}" bind:tap="minusAmount">-</view>
                                    <view class="amount">{{merchandise.amount}}</view>
                                    <view class="plus" data-store="{{item.store}}" data-id="{{merchandise.id}}" bind:tap="plusAmount">+</view>
                                </view>
                            </view>
                        </view>
                    </movable-view>
                    
                </movable-area>
            </block>
        </checkbox-group>
    </block>
</view>
<!-- 结算 -->
<view class="count">
    <checkbox class="check-all" bind:tap="checkAll" checked="{{checkedAll}}">全选</checkbox>
    <view class="grand">卷后合计:<text style="color: red;">¥{{total}}</text></view>
    <button class="lapse {{totalCount > 0 ? 'settle-btn' : ''}}" bind:tap="settleBill" hover-class="settle-bill" disabled="{{totalCount == 0}}" loading="{{showLoading}}">去结算({{totalCount}})</button>
</view>

wxss代码:

page {
  padding: 16rpx;
  padding-bottom: 172rpx;
  box-sizing: border-box;
}
.gwc{
  display: flex;
  margin-top: 120rpx;
  margin-left: 30rpx;
}
.gl{
  display: flex;
  margin-left: 600rpx;
  margin-top: -50rpx;
}
checkbox .wx-checkbox-input{
  width: 40rpx; 
  height: 40rpx; 
  border-radius: 50%;
}
/* 选中后的背景样式 */
checkbox .wx-checkbox-input.wx-checkbox-input-checked{
  background: #b0474c;
}
/* 选中后的勾子样式 */
checkbox .wx-checkbox-input.wx-checkbox-input-checked::before{
  width: 40rpx;
  height: 40rpx;
  line-height: 40rpx;
  border-radius: 50%;
  text-align: center;
  font-size:32rpx; 
  color:#fbfbfd; 
  background: transparent;
  transform:translate(-50%, -50%) scale(1);
  -webkit-transform:translate(-50%, -50%) scale(1);
}
/* 生效商品 */
.cart-effect {
  display: flex;
  flex-direction: column;
}
.cart-effect .check-group {
  padding: 16rpx;
  box-sizing: border-box;
  border-radius: 32rpx;
  margin-top: 16rpx;
  z-index: 11;
}
.cart-effect .check-group .check-store-all {
  display: flex;
  justify-content: flex-start;
  align-items: center;
}
.cart-effect .check-group .store {
  font-size: 36rpx;
  font-weight: bolder;
  margin-left: 8rpx;
}
.cart-effect .check-group .move-area{
  /* 减去删除部分的宽度 */
  width: calc(100% - 128rpx);
  height: 280rpx;
  position: relative;
  display: flex;
}
.cart-effect .check-group .move-area .move-view {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 95%;
  /* 上面减了多少宽度,下面就要加多少,不然无法起到遮挡作用 */
  width: calc(100% + 128rpx);
  border-radius: 3%;
  background-color: #efeff5;
  box-sizing: border-box;
  z-index: 10;
  padding-right: 12rpx;
}
.cart-effect .check-group .move-area .move-view .info {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100vw;
  overflow: hidden;
  box-sizing: border-box;

}

.cart-effect .check-group .move-area .move-view .info .merchandise {
  display: grid;
  grid-template-columns: 1fr 2fr 2fr;
  grid-template-rows: 110rpx 60rpx;
  grid-column-gap: 12rpx;
  grid-row-gap: 12rpx;
}

.cart-effect .check-group .move-area .move-view .info .merchandise .merchandise-img {
  width: 180rpx;
  height: 180rpx;
  border-radius: 50%;
  grid-column: 1 / 2;
  grid-row: 1 / 3;
}
.cart-effect .check-group .move-area .move-view .info .merchandise .merchandise-name {
  grid-column: 2 / 4;
  grid-row: 1 / 2;
  font-size: 32rpx;
}

.cart-effect .check-group .move-area .move-view .info .merchandise .merchandise-price {
  grid-column: 2 / 3;
  grid-row: 2 / 3;
  font-size: 32rpx;
  font-weight: 550;
}

.cart-effect .check-group .move-area .move-view .merchandise .merchandise-amount {
  grid-column: 3 / 4;
  grid-row: 2 / 3;
  text-align: right;
  

  display: grid;
  grid-template-columns: repeat(3, 1fr);
  align-items: center;
  text-align: center;
  line-height: 50rpx;
}

.cart-effect .check-group .move-area .move-view .merchandise .merchandise-amount .minus {
  font-size: 42rpx;
  background-color: #e5e5e5;
  border-radius: 16rpx;
}

.cart-effect .check-group .move-area .move-view .merchandise .merchandise-amount .amount {
  font-size: 36rpx;
}

.cart-effect .check-group .move-area .move-view .merchandise .merchandise-amount .plus {
  background-color: #e5e5e5;
  border-radius: 16rpx;
  font-size: 42rpx;
}

.cart-lapse .check-group {
  background-color: #fbfbfd;
  padding: 16rpx;
  box-sizing: border-box;
  border-radius: 32rpx;
  margin-top: 16rpx;
  z-index: 11;
}

.cart-lapse .check-group .move-area .move-view {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  /* 上面减了多少宽度,下面就要加多少,不然无法起到遮挡作用 */
  width: calc(100% + 128rpx);
  background-color: #fbfbfd;
  box-sizing: border-box;
  z-index: 10;
  padding-right: 12rpx;
}



.cart-lapse .check-group .move-area .move-view .info {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100vw;
  overflow: hidden;
  box-sizing: border-box;
}

.cart-lapse .check-group .move-area .move-view .info .merchandise {
  display: grid;
  grid-template-columns: 1fr 2fr 2fr;
  grid-template-rows: 110rpx 60rpx;
  grid-column-gap: 12rpx;
  grid-row-gap: 12rpx;
}

.cart-lapse .check-group .move-area .move-view .info .merchandise .sold-out {
  position: relative;
  width: 180rpx;
  height: 180rpx;
  border-radius: 50%;
}

.cart-lapse .check-group .move-area .move-view .info .merchandise .sold-out .merchandise-img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  grid-column: 1 / 2;
  grid-row: 1 / 3;
}

.cart-lapse .check-group .move-area .move-view .info .merchandise .sold-out .status{
  width: 100%;
  height: 100%;
  background-color: #1a1a1a90;
  position: absolute;
  top: 0;
  left: 0;
  text-align: center;
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 50%;
  color: #fbfbfb;
  font-size: 36rpx;
  font-weight: 500;
}

.cart-lapse .check-group .move-area .move-view .info .merchandise .merchandise-name {
  grid-column: 2 / 4;
  grid-row: 1 / 2;
  font-size: 32rpx;
}

.cart-lapse .check-group .move-area .move-view .info .merchandise .merchandise-price {
  grid-column: 2 / 3;
  grid-row: 2 / 3;
  font-size: 32rpx;
  font-weight: 550;
}

.cart-lapse .check-group .move-area .move-view .merchandise .merchandise-amount {
  grid-column: 3 / 4;
  grid-row: 2 / 3;
  text-align: right;

  display: grid;
  grid-template-columns: repeat(3, 1fr);
  align-items: center;
  text-align: center;
  line-height: 60rpx;
}

.cart-lapse .check-group .move-area .move-view .merchandise .merchandise-amount .minus {
  font-size: 42rpx;
  background-color: #e5e5e5;
  border-radius: 16rpx;
}

.cart-lapse .check-group .move-area .move-view .merchandise .merchandise-amount .amount {
  font-size: 36rpx;
}

.cart-lapse .check-group .move-area .move-view .merchandise .merchandise-amount .plus {
  background-color: #e5e5e5;
  border-radius: 16rpx;
  font-size: 42rpx;
}

.count {
  width: calc(100% - 32rpx);
  box-sizing: border-box;
  margin-top: 16rpx;
  padding: 16rpx;
  background-color: #fbfbfd;
  border-radius: 120rpx;
  position: fixed;
  bottom: 42rpx;
  z-index: 99;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border: 1rpx solid #e5e5e5;
}

.count .check-all{
  font-size: 34rpx;
  font-weight: 550;
}

.count .grand {
  width: 50%;
  text-align: right;
  font-size: 32rpx;
  font-weight: 550;
}

.count .lapse {
  width: 200rpx;
  height: 80rpx;
  color: #fdfdfd;
  border-radius: 120rpx;
  font-size: 33rpx;
  margin: 0;
  text-align: center;
  background-color: #65dd6b;
  padding: 0;
  line-height: 80rpx;
}

.count .settle-btn {
  background-color: #65dd6b;
}

.count .settle-bill {
  background-color: #d1362f80
}

js代码:

Page({
  /**
   * 页面的初始数据
   */
  data: {
      cartEffectList: [],
      // 生效商品
      example: [
          {
              store: "龙门客栈",
              checked: false,
              merchandiseChecked: false,
              merchandises: [
                  {
                      id: "1",
                      imgUrl: "../../images/pic1.jpg",
                      name: "车厘茄1kg/盒",
                      price: 17.9,
                      amount: 1,
                      status: 0,
                      x: 0,
                      checked: false,
                  },
                  {
                      id: "2",
                      imgUrl: "../../images/pic2.jpg",
                      name: "小鸡干脆面烧烤鸡肉味16g*12包",
                      price: 13.9,
                      amount: 1,
                      status: 1,
                      x: 0,
                      checked: false,
                  },         
              ]
          },   
      ],
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
      this.getCartList();
  },
  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {
  },
  /**
   * 获取用户购物车
   */
  getCartList() {
      let cartEffectList = this.data.example;
      wx.setStorageSync('cartEffectList', cartEffectList);
      this.setData({
          cartEffectList: cartEffectList,
      });
  },
  /**
   * 店铺全选
   * @param {*} e 
   */
  checkStoreAll(e) {
      let storeName = e.currentTarget.dataset.store;
      let cartEffectList = this.data.cartEffectList;
      let updatedCart = cartEffectList.map(store => {
          if (store.store === storeName) {
              // 切换商店的已勾选标记
              store.checked = !store.checked;
              // 重置商店的商品已勾选标记
              store.merchandiseChecked = false;
              store.merchandises = store.merchandises.map(merch => {
                  // 根据商店的已检查标记更新商品的已选择标记
                  merch.checked = store.checked;
                  return merch;
              });
          }
          return store;
      });
      this.setData({
          cartEffectList: updatedCart
      });
      this.grand();
  },
  /**
   * 单个选择
   * @param {*} e 
   */
  checkSingle(e) {
      let storeName = e.currentTarget.dataset.store;
      let merchandiseData = e.currentTarget.dataset.merchandise;
      let cartEffectList = this.data.cartEffectList;
      let updatedCart = cartEffectList.map(store => {
          if (store.store === storeName) {
              store.merchandises = store.merchandises.map(merch => {
                  if (merch.id === merchandiseData.id) {
                      // 更改商品的选择状态
                      merch.checked = !merch.checked;
                      // 更改店铺的选中状态
                      store.merchandiseChecked = merch.checked;
                  }
                  return merch;
              });
          }
          return store;
      });
      this.setData({
          cartEffectList: updatedCart
      });
      this.grand();
  },
  /**
   * 全选
   */
  checkAll() {
      let cartEffectList = this.data.cartEffectList;
      let checkedAll = this.data.checkedAll;
      // 使用map方法更新每个商店和商品的选中状态
      let updatedCart = cartEffectList.map(store => {
          return {
              ...store,
              checked: !checkedAll,
              merchandiseChecked: !checkedAll,
              merchandises: store.merchandises.map(merch => ({
                  ...merch,
                  checked: !checkedAll
              }))
          };
      });
      this.setData({
          cartEffectList: updatedCart,
          checkedAll: !checkedAll,
      });
      this.grand();
  },
  /**
   * 合计
   */
  grand() {
      let cartEffectList = this.data.cartEffectList;
      // 初始化总价和总数量
      let total = 0;
      let totalCount = 0;
      cartEffectList.forEach(store => {
          store.merchandises.forEach(merch => {
              if (merch.checked) {
                  total += merch.amount * merch.price;
                  totalCount += merch.amount;
              }
          });
      });
      this.setData({
          total: total,
          totalCount: totalCount,
      });
  },
     /**
     * 减少数量,下限为1
     * @param {*} e 
     */
    minusAmount(e) {
      let storeName = e.currentTarget.dataset.store;
      let id = e.currentTarget.dataset.id;
      let cartEffectList = this.data.cartEffectList;
      let updatedCart = cartEffectList.map(store => {
          if (store.store === storeName) {
              // 更新商店的已选择商品标记
              store.merchandiseChecked = true;
              store.merchandises = store.merchandises.map(merch => {
                  if (merch.id === id) {
                      // 更新商品的选择状态
                      merch.checked = true;
                      if (merch.amount > 1) {
                          merch.amount--;
                      } else {
                          wx.showModal({
                              content: '宝贝数量不能再减少了',
                              showCancel: false,
                          });
                      }
                  }
                  return merch;
              });
          }
          return store;
      });
      this.setData({
          cartEffectList: updatedCart
      });
      this.grand();
  },
  /**
   * 增加数量,上限为99
   * @param {*} e 
   */
  plusAmount(e) {
      let storeName = e.currentTarget.dataset.store;
      let id = e.currentTarget.dataset.id;
      let cartEffectList = this.data.cartEffectList;
      let updatedCart = cartEffectList.map(store => {
          if (store.store === storeName) {
              // 更新店铺的选中状态
              store.merchandiseChecked = true;
              store.merchandises = store.merchandises.map(merch => {
                  if (merch.id === id) {
                      // 更新商品的选择状态
                      merch.checked = true; 
                      if (merch.amount < 99) {
                          merch.amount++;
                      } else {
                          wx.showModal({
                              content: '宝贝数量不能再增加了',
                              showCancel: false,
                          });
                      }
                  }
                  return merch;
              });
          }
          return store;
      });
      this.setData({
          cartEffectList: updatedCart
      });
      this.grand();
  },
  /**
   * 结算
   */
  settleBill() {
      this.setData({
          showLoading: true,
      });
      // 进行深拷贝
      let cartEffectList = JSON.parse(JSON.stringify(this.data.cartEffectList));
      // 筛选出未选中的商店或没有选中商品的商店
      let filteredStores = cartEffectList.filter(store => {
          if (store.checked) {
              // 如果商店被选中,保留它
              return true; 
          }
          // 从商店中筛选出未选中的商品
          store.merchandises = store.merchandises.filter(merch => merch.checked);
          // 如果筛选后,商店有选中的商品,保留该商店
          return store.merchandises.length > 0;
      });
      wx.navigateTo({
          url: `/pages/index/settle-bill/settle-bill?chosenList=${JSON.stringify(filteredStores)}`,
          complete: () => {
              this.setData({
                  showLoading: false,
              });
          }
      });
  },


})

显示全文