微信小程序-购物车

155 阅读2分钟

思路

需求

  • 根据菜品类型筛选菜品
  • 每个菜品数量变化都需计算总价和实际支付价格
  • 点击购物车,显示已选的菜品及数量,改变购物车菜品数量,列表中数量也要变化

实现思路

  • 获取所有菜品dishListCopy
  • 点击类型,筛选菜品,dishList
  • 购物车,展示菜品,chooseDishArr
  • 改变列表中菜品数量,改变dishList
  • 改变购物车的菜品数量,改变dishListCopy-dishCount

代码实现

.wxml

 <view class="mlr-32" wx:if="{{serviceObjectId}}">
    <van-row gutter="10">
      <van-col span="5">
        <view class="radius-20 bg-white">
          <view class="dish-type center {{selectedIndex==index?'line-shorter bg':''}}" wx:for="{{dishTypeArr}}" wx:key="index" data-index="{{index}}" data-value="{{item.dictValue}}" bindtap="getOrderList">{{item.dictLabel}}</view>
        </view>
      </van-col>
      <van-col span="18">
        <view class="bg-white radius-20">
          <view class="flex_l pd-20 mtb-20" wx:for="{{dishList}}" wx:key="index">
            <image style="width:140rpx;height:140rpx;border-radius: 10rpx;" src="{{item.dishPicture?pictureURL+item.dishPicture:'/assets/imgs/dishes.png'}}" />
            <view class="ml-20 flex-1">
              <view class="line-2">{{item.dishName}}</view>
              <view class="flex mt-10">
                <view class="red mr-10">¥{{item.dishPrice}}</view>
                <van-stepper value="{{ item.dishCount }}" data-item="{{item}}" bind:change="onChange" data-type="1" min="0" />
              </view>
            </view>
          </view>
        </view>
      </van-col>
    </van-row>
  </view>
  <!-- 购物车 -->
  <van-popup show="{{ catShow }}" bind:close="catClose" round position="bottom">
    <view class="bg-white radius-20">
      <view class="bold pt-30 pl-30">已选</view>
      <view class="flex_l pd-20 mtb-20" wx:for="{{chooseDishArr}}" wx:key="index">
        <image style="width:140rpx;height:140rpx;border-radius: 10rpx;" src="{{item.dishPicture?pictureURL+item.dishPicture:'/assets/imgs/dishes.png'}}" />
        <view class="ml-20 flex-1">
          <view class="line-2">{{item.dishName}}</view>
          <view class="flex mt-10">
            <view class="red mr-10">¥{{item.dishPrice}}</view>
            <van-stepper value="{{ item.dishCount }}" data-item="{{item}}" bind:change="onChange" data-type="2" min="0" />
          </view>
        </view>
      </view>
    </view>
  </van-popup>
  <van-toast id="van-toast" />

.js


import Toast from '@vant/weapp/toast/toast';
Page({

  /**
   * 页面的初始数据
   */
  data() {
    return {
      diningStyle: '',//1:,2:
      // 选择服务对象
      serviceObjectId: '',
      isShowCamera: false,

      // 下单
      enterOrderInfo: {},//下单对象信息
      dishTypeArr: [],//菜品类型-字典
      dishType: '',//菜品类型
      dishList: [],//菜品列表
      dishListCopy: [],//菜品列表Copy
      selectedIndex: null,// 用于标记被选中的项目索引

      chooseDishArr: [],// 已选的菜品
      subvention: 0,//补助金额
      actualPayment: 0,//实付金额
      sumPayment: 0,// 总价格

      // 购物车
      catShow: false,

    }
  },
  onShow: function () {
  },
  onLoad(options) {
    this.getList()
    this.setData({
      pictureURL: pictureURL,
      enterOrderInfo: wx.getStorageSync('enterOrderInfo'),
      serviceObjectId: wx.getStorageSync('enterOrderInfo').serviceObjectId,
      selectedIndex: 0,
      diningStyle: options.diningStyle
    })
  },
  onServiceObjectFinish(e) {
    const {
      selectedOptions,
      value
    } = e.detail;
    const text = selectedOptions[0].text
    // 查对象详情
    wx.http('/', { serviceObjectId: value }).then(res => {
      this.setData({
        enterOrderInfo: res.data,
        serviceObjectName: text,
        serviceObjectId: value,
        serviceObjectShow: false
      })
    })
  },
  // 改变菜品数量
  onChange(e) {
    // type 1列表 2购物车
    let { item, type } = e.currentTarget.dataset
    let { serviceObjectId, enterOrderInfo } = this.data
    let newCount = e.detail; // 获取新的count值
    if (serviceObjectId) {
      let chooseDish = this.data.chooseDishArr || []
      // 数字不为0则push chooseDishArr
      if (newCount > 0) {
        const dishWithId1 = chooseDish ? chooseDish.find(dish => dish.dishId === item.dishId) : false;
        if (dishWithId1) {
          dishWithId1.dishCount = newCount;
        } else {
          // 如果不存在,向数组中添加新对象
          const findObj = item
          findObj.dishCount = newCount
          chooseDish.push(findObj);
        }
      } else {
        // 移除dishCount为0的项目
        chooseDish = chooseDish.filter(dish => dish.dishCount !== 0);
      }
      let newCopy = this.data.dishListCopy ? this.data.dishListCopy.map(dish => {
        if (dish.dishId === item.dishId) {
          return { ...dish, dishCount: newCount };
        }
        return dish;
      }) : []
      let filterChoose = chooseDish ? chooseDish.map(dish => {
        if (dish.dishId === item.dishId) {
          return { ...dish, dishCount: newCount };
        }
        return { ...dish };
      }) : []
      this.setData({
        dishListCopy: newCopy,
        chooseDishArr: filterChoose,
      }, () => {
        // 在这里计算总和
        let sum = this.data.dishListCopy.reduce((total, dish) => {
          return total + (dish.dishCount * dish.dishPrice);
        }, 0);
        let actual = sum - enterOrderInfo.subsidyAmount * 1
        this.setData({
          // 注意chooseDishArr要先赋值(上面先赋值),再filter  (否则会出现 两个count1 对象A变为0 前端对象B也变为0 实际数字还是1)
          chooseDishArr: filterChoose.filter(dish => dish.dishCount !== 0),
          sumPayment: sum,
          actualPayment: actual < 0 ? 0 : actual,
        });
      });
    }
    let newList = this.data.dishListCopy.filter(dish => dish.dishType == this.data.dishType)
    this.setData({
      dishList: newList
    })
    // 若购物车中无菜品则关闭
    if (type == 2 && this.data.chooseDishArr.length == 0) {
      this.setData({
        catShow: false
      })
    }
  },
  // 字典
  getDicts() {
    let that = this
    return new Promise((resolve, reject) => {
      wx.http('/type/' + 'dish_type').then(res => {
        // 将套餐移到数组的第一个位置
        res.data.sort((a, b) => {
          if (a.dictValue == 4) {
            return -1;
          } else if (b.dictValue == 4) {
            return 1;
          }
          return 0;
        });
        that.setData({
          dishTypeArr: res.data,
          selectedIndex: 0,
        })
        resolve({
          code: 200,
          dishTypeArr: res.data,
        })
      })
    })
  },
  // 点击菜品类型
  getOrderList(e) {
    let { dishListCopy } = this.data
    let { value, index } = e.currentTarget.dataset
    // 合并两个数组
    let arr1 = this.data.dishListCopy || []
    let arr2 = this.data.chooseDishArr || []
    let arr = arr1.concat(arr2)
    // 创建一个 Map 来存储处理后的结果
    let dishesMap = new Map();
    arr.forEach(dish => {
      if (dishesMap.has(dish.dishId)) {
        // 如果 dishId 已经存在
        let existingDish = dishesMap.get(dish.dishId);
        if (dish.dishCount > 0) {
          // 如果当前 dish 的 dishCount 不为 0,更新原有对象的 dishCount
          existingDish.dishCount = dish.dishCount;
        }
      } else {
        // 如果 dishId 不存在,添加该项到 Map
        dishesMap.set(dish.dishId, dish);
      }
    });
    // 将 Map 转换回数组
    let finalDishes = Array.from(dishesMap.values());
    this.setData({
      chooseDishArr: finalDishes.filter(item => item.dishCount != 0),
      dishType: value,
      dishList: dishListCopy.filter(dish => dish.dishType == value),
      selectedIndex: index
    });
    console.log(this.data.chooseDishArr, 'finalDishes')
  },
  getList() {
    this.getDicts().then(res1 => {
      wx.http('/xx/list').then(res => {
        let dishes = res.rows.map(dish => {
          return {
            ...dish,
            dishCount: 0
          };
        });
        let arr = res1.dishTypeArr || []
        this.setData({
          dishType: arr[0].dictValue,
          dishListCopy: dishes,
          dishList: res.rows.filter(dish => dish.dishType == arr[0].dictValue)
        })
      })
    })
  },
  // 展开购物车
  openShoppingCart() {
    let { chooseDishArr } = this.data
    if (chooseDishArr.length != 0) {
      this.setData({
        catShow: true
      })
    } else {
      Toast.fail('请选择菜品');
    }
  },
  catClose() {
    let { dishType, dishListCopy } = this.data
    let newList = dishListCopy.filter(dish => dish.dishType == dishType)
    this.setData({
      dishList: newList,
      catShow: false
    }, () => {
      console.log('关闭', dishType, this.data.dishList);
    });
  },
 
  onUnload() {
    wx.removeStorageSync('enterOrderInfo');
  },
})