瀏覽代碼

购物车

yangc 7 年之前
父節點
當前提交
6d5f9e5325

+ 2 - 1
assets/scss/mobileCommon.scss

@@ -116,7 +116,8 @@ html {
     color: #01a44e;
   }
 
-  input {
+  input[type="text"],
+  input[type="number"]{
     -webkit-appearance: none;
     -moz-appearance: none;
     appearance: none;

+ 3 - 7
components/mobile/MobileHeader.vue

@@ -135,13 +135,6 @@
         window.history.back(-1)
       },
       initHeader: function (val, query) {
-//        if (val !== '/' || !val || val === '') {
-//          this.showHeader = true
-//          this.showSearch = !val.startsWith('/mobile/search')
-//        } else {
-//          this.showHeader = false
-//          this.showSearch = false
-//        }
         this.showSearchIcon = false
         this.showHeader = val && val !== '/' && val !== '/mobile/applyPurchase/list' && !this.startWith(val, '/mobile/supplier')
 //        this.showSearch = val !== '/' && !this.startWith(val, '/mobile/search')
@@ -203,6 +196,9 @@
         } else if (this.startWith(val, '/mobile/store')) {
           this.showSearchIcon = false
           title = '开店申请'
+        } else if (val === '/mobile/center/user/cart') {
+          this.showSearchIcon = false
+          title = '购物车'
         } else {
           this.showSearchIcon = true
           title = '优软商城'

+ 452 - 0
pages/mobile/center/user/cart.vue

@@ -0,0 +1,452 @@
+<template>
+  <div class="mobile-fix-content mobile-centerfix-content mobile-cart" id="mobileFixContent">
+    <ul class="store-list">
+      <li class="store-item" v-for="(item, storeIndex) in cartList">
+        <div class="store-info">
+          <label class="mobile-cart-check" :class="{'active': item.$active}">
+            <input type="checkbox" @change="setActive('store', storeIndex)">
+          </label>
+          <span class="store-tag inline-block">{{baseUtils.storeTypeFilter(item.storeType)}}</span>
+          <p class="store-name inline-block text-ellipse">{{item.storeName}}</p>
+        </div>
+        <ul class="goods-list">
+          <li class="goods-item" v-for="(goods, goodsIndex) in item.goods">
+            <label class="mobile-cart-check" :class="{'active': goods.$active}">
+              <input type="checkbox" @change="setActive('goods', storeIndex, goodsIndex)">
+            </label>
+            <div class="params inline-block">
+              <p class="param text-ellipse"><span>品牌:</span>{{goods.goods.brandNameEn || '-'}}</p>
+              <p class="param text-ellipse"><span>类目:</span>{{goods.kiName || '-'}}</p>
+              <p class="param text-ellipse"><span>型号:</span>{{goods.code || '-'}}</p>
+              <p class="param text-ellipse"><span>规格:</span>{{goods.spec || '-'}}</p>
+            </div>
+            <div class="fr">
+              <!--<p class="goods-tag">{{goods.goods.tag || '-'}}</p>-->
+              <div class="input-line">
+                <span class="inline-block" @click="setGoods('sub', goods)">-</span>
+                <input type="number" v-model="goods.goods.purchaseNumber" @input="onPurchaseNumberInput(goods)" @blur="setGoods('set', goods)">
+                <span class="inline-block" @click="setGoods('add', goods)">+</span>
+              </div>
+              <div class="price-line">
+                <span>{{goods.currencyName === 'RMB' ? '¥' : '$'}}</span>{{goods.goods.currentPrice}}
+              </div>
+            </div>
+          </li>
+        </ul>
+      </li>
+    </ul>
+    <div class="buy-wrap">
+      <label class="mobile-cart-check" :class="{'active': isAllChecked}">
+        <input type="checkbox" @change="setActive('all')">
+        <span>全选</span>
+      </label>
+      <div class="fr">
+        <i class="fare">不含运费</i>
+        <span class="title">合计:</span><span class="price"><span>¥</span>{{allPrice}}</span>
+        <button class="buy-btn" @click="submit">结算({{allCount}})</button>
+      </div>
+    </div>
+    <remind-box :title="remindText" :timeoutCount="timeoutCount"></remind-box>
+    <pull-up :fixId="'mobileFixContent'" :searchMore="fetching" :allPage="allPage" :page="page" @pullUpAction="onPullUpAction"></pull-up>
+  </div>
+</template>
+<script>
+  import {RemindBox, PullUp} from '~components/mobile/common'
+  export default {
+    layout: 'mobile',
+    middleware: 'authenticated',
+    data () {
+      return {
+        cartList: [],
+        remindText: '',
+        timeoutCount: '',
+        isAllChecked: false,
+        page: 1,
+        count: 10
+      }
+    },
+    components: {
+      RemindBox,
+      PullUp
+    },
+    fetch ({ store }) {
+      return Promise.all([
+        store.dispatch('userCenter/loadCartList', {page: 1, count: 10})
+      ])
+    },
+    watch: {
+      '$store.state.userCenter.list.cart.data': {
+        handler: function (val) {
+          let tmpVal = this.baseUtils.deepCopy(val)
+          tmpVal.content.forEach(item => {
+            let current = this.cartList.find(objItem => {
+              return objItem.storeUuid === item.storeUuid
+            })
+            item.$active = false
+            // 初始化购买数量及状态
+            let goodsItem = item.goods
+            let pack = goodsItem.perQty || goodsItem.minPackQty
+            if (goodsItem.breakUp) {
+              goodsItem.purchaseNumber = goodsItem.minBuyQty
+              goodsItem.canSub = false
+              goodsItem.canAdd = goodsItem.purchaseNumber < goodsItem.reserve
+            } else {
+              if (pack >= goodsItem.minBuyQty) {
+                goodsItem.purchaseNumber = pack
+              } else {
+                let max = Math.max(pack, goodsItem.minBuyQty)
+                goodsItem.purchaseNumber = max + max % pack
+              }
+              goodsItem.canSub = false
+              goodsItem.canAdd = goodsItem.purchaseNumber + goodsItem.minPackQty <= goodsItem.reserve
+            }
+            goodsItem.currentPrice = Number((this.baseUtils.getPriceByLevel(goodsItem.prices, goodsItem.purchaseNumber, goodsItem.currencyName) * goodsItem.purchaseNumber).toFixed(6))
+            if (!current) {
+              this.cartList.push({
+                storeName: item.storeName,
+                storeType: item.storeType,
+                storeUuid: item.storeUuid,
+                goods: [item],
+                $active: false
+              })
+            } else {
+              current.goods.push(item)
+            }
+          })
+        },
+        immediate: true
+      }
+    },
+    computed: {
+      cartData () {
+        return this.$store.state.userCenter.list.cart.data
+      },
+      fetching () {
+        return this.$store.state.userCenter.list.cart.fetching
+      },
+      allPage () {
+        return this.cartData.totalPages
+      },
+      allActiveObj () {
+        let arr = []
+        this.cartList.forEach(item => {
+          item.goods.forEach(goodsItem => {
+            if (goodsItem.$active) {
+              arr.push(goodsItem)
+            }
+          })
+        })
+        return arr
+      },
+      allPrice () {
+        let price = 0
+        this.allActiveObj.forEach(item => {
+          price += Number(item.goods.currentPrice)
+        })
+        return price
+      },
+      allCount () {
+        return this.allActiveObj.length
+      }
+    },
+    methods: {
+      setRemindText: function (str) {
+        this.remindText = str
+        this.timeoutCount++
+      },
+      setActive: function (type, storeIndex, goodsIndex) {
+        if (type === 'store') {
+          this.cartList[storeIndex].goods.forEach(item => {
+            item.$active = !this.cartList[storeIndex].$active
+          })
+          this.cartList[storeIndex].$active = !this.cartList[storeIndex].$active
+          this.checkAll()
+        } else if (type === 'goods') {
+          this.cartList[storeIndex].goods[goodsIndex].$active = !this.cartList[storeIndex].goods[goodsIndex].$active
+          this.cartList[storeIndex].$active = !this.cartList[storeIndex].goods.find(item => {
+            return !item.$active
+          })
+          this.checkAll()
+        } else if (type === 'all') {
+          let activeFlag = true
+          this.cartList.forEach(item => {
+            item.goods.forEach(goodsItem => {
+              if (!goodsItem.$active) {
+                activeFlag = false
+              }
+            })
+          })
+          for (let i = 0; i < this.cartList.length; i++) {
+            this.cartList[i].$active = activeFlag
+            this.setActive('store', i)
+          }
+          this.isAllChecked = !activeFlag
+        }
+      },
+      // 总勾选校验
+      checkAll: function () {
+        let activeFlag = true
+        this.cartList.forEach(item => {
+          item.goods.forEach(goodsItem => {
+            if (!goodsItem.$active) {
+              activeFlag = false
+            }
+          })
+        })
+        this.isAllChecked = activeFlag
+      },
+      onPurchaseNumberInput: function (goods) {
+        let showPrice = this.baseUtils.getPriceByLevel(goods.goods.prices, goods.goods.purchaseNumber, goods.goods.currencyName)
+        goods.goods.currentPrice = Number(((showPrice || goods.goods.currentPrice) * goods.goods.purchaseNumber).toFixed(6))
+      },
+      checkPurchaseNumber: function (goods) {
+        if ((/^[\d]*$/).test(goods.goods.purchaseNumber)) {
+          this.changeNum(goods.goods.purchaseNumber, goods)
+        } else {
+          this.setRemindText('请输入整数')
+          goods.goods.purchaseNumber = goods.goods.minBuyQty
+        }
+      },
+      setGoods: function (type, goods) {
+        if (type === 'set') {
+          this.checkPurchaseNumber(goods)
+        } else {
+          let isAdd = type === 'add'
+          let pack = goods.goods.perQty || goods.goods.minPackQty
+          let newNum = 0
+          if (goods.goods.breakUp) {
+            newNum = isAdd ? goods.goods.purchaseNumber + 1 : goods.goods.purchaseNumber - 1
+          } else {
+            newNum = isAdd ? goods.goods.purchaseNumber + pack : goods.goods.purchaseNumber - pack
+          }
+          this.changeNum(newNum, goods)
+          this.onPurchaseNumberInput(goods)
+        }
+      },
+      changeNum: function (newNum, goods) {
+        let pack = goods.goods.perQty || goods.goods.minPackQty
+        let buy = goods.goods.minBuyQty
+        let reserve = goods.goods.reserve
+        let breakUp = goods.goods.breakUp
+        if (!newNum && newNum !== 0) {
+          goods.goods.purchaseNumber = buy
+        } else {
+          newNum = parseInt(newNum)
+          if (breakUp) {
+            if (newNum < buy) {
+              this.setRemindText('最小起订量为' + buy)
+              goods.goods.purchaseNumber = buy
+              goods.goods.canSub = false
+              goods.goods.canAdd = true
+            } else if (newNum > reserve) {
+              this.setRemindText('库存不足')
+              goods.goods.purchaseNumber = reserve
+              goods.goods.canAdd = false
+              goods.goods.canSub = true
+            } else {
+              goods.goods.canSub = true
+              goods.goods.canAdd = true
+              goods.goods.purchaseNumber = newNum
+              newNum === buy && (goods.goods.canSub = false)
+              newNum === reserve && (goods.goods.canAdd = false)
+            }
+          } else {
+            if (newNum < buy) {
+              this.setRemindText('最小起订量为' + buy)
+              goods.goods.purchaseNumber = buy
+              goods.goods.canSub = false
+              if (newNum > reserve) {
+                this.setRemindText('库存不足')
+                goods.goods.purchaseNumber = reserve - (reserve % pack)
+                goods.goods.canAdd = false
+              }
+            } else if (newNum > reserve) {
+              goods.goods.canSub = true
+              goods.goods.canAdd = false
+              this.setRemindText('库存不足')
+              goods.goods.purchaseNumber = reserve - (reserve % pack)
+            } else {
+              goods.goods.canSub = true
+              goods.goods.canAdd = true
+              let remainder = newNum % pack
+              if (remainder !== 0) {
+//                console.log(this.fragment.num)
+                this.setRemindText('不支持拆包且包装量为' + pack)
+                // 这个直接赋值的,应该给这个值进行判断(Math.floor(newNum / pack) + 1) * pack
+                let res = (Math.floor(newNum / pack) + 1) * pack
+                goods.goods.purchaseNumber = res > reserve ? Math.floor(newNum / pack) * pack : res
+              } else {
+                goods.goods.purchaseNumber = newNum
+              }
+              newNum === buy && (goods.goods.canSub = false)
+              newNum === reserve && (goods.goods.canAdd = false)
+            }
+          }
+        }
+      },
+      onPullUpAction: function () {
+//        this.page++
+//        this.reloadList()
+      },
+      reloadList: function () {
+        this.$store.dispatch('userCenter/loadCartList', {page: this.page, count: this.count})
+      },
+      submit: function () {
+        if (!this.allCount) {
+          this.setRemindText('请勾选要生成订单的批次')
+          return
+        }
+      }
+    }
+  }
+</script>
+<style lang="scss" scoped>
+  .mobile-cart {
+    bottom: 2rem;
+    .store-list {
+      margin: .19rem 0;
+      background: #fff;
+      .store-item {
+        padding: 0 .25rem;
+        .store-info {
+          height: .9rem;
+          line-height: .9rem;
+          .store-tag {
+            width: .54rem;
+            height: .3rem;
+            line-height: .3rem;
+            text-align: center;
+            font-size: .24rem;
+            color: #fff;
+            background: #15b262;
+            border-radius: .04rem;
+            margin-left: .18rem;
+          }
+          .store-name {
+            font-size: .28rem;
+            margin-left: .08rem;
+            max-width: 5.7rem;
+          }
+        }
+        .goods-list {
+          .goods-item {
+            padding: .32rem 0;
+            border-top: 1px solid #e4e4e4;
+            .params {
+              margin-left: .17rem;
+              .param {
+                width: 3.65rem;
+                span {
+                  color: #666;
+                }
+              }
+            }
+            .fr {
+              width: 2.6rem;
+              text-align: center;
+              .input-line {
+                $group-height: .35rem;
+                margin-top: .52rem;
+                input {
+                  width: 1.31rem;
+                  height: .35rem;
+                  border-top: 1px solid #ddd;
+                  border-bottom: 1px solid #ddd;
+                  vertical-align: middle;
+                  border-radius: 0;
+                  padding: 0 .05rem;
+                  text-align: center;
+                  position: relative;
+                  top: .01rem;
+                }
+                span {
+                  width: .5rem;
+                  height: $group-height;
+                  line-height: $group-height;
+                  text-align: center;
+                  border: 1px solid #ddd;
+                }
+              }
+              .price-line {
+                font-size: .32rem;
+                color: #f43938;
+                margin-top: .2rem;
+                span {
+                  font-size: .24rem;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    .buy-wrap {
+      position: fixed;
+      bottom: .98rem;
+      height: 1.02rem;
+      line-height: 1.02rem;
+      padding-left: .27rem;
+      background: #fff;
+      width: 100%;
+      border-top: .02rem solid #ccc;
+      .fr {
+        .fare {
+          font-size: .18rem;
+          color: #999;
+          margin-right: .15rem;
+          font-style: normal;
+        }
+        .title {
+          font-size: .28rem;
+          margin-right: .38rem;
+        }
+        .price {
+          font-size: .28rem;
+          color: #fc2706;
+          display: inline-block;
+          max-width: 1.6rem;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+          vertical-align: middle;
+          span {
+            font-size: .24rem;
+            margin-right: .08rem;
+          }
+          margin-right: .25rem;
+        }
+        .buy-btn {
+          width: 2.08rem;
+          height: 1.02rem;
+          line-height: 1.02rem;
+          text-align: center;
+          font-size: .28rem;
+          color: #fff;
+          background: #fc2706;
+        }
+      }
+    }
+  }
+  .mobile-cart-check {
+    min-width: .36rem;
+    height: .36rem;
+    background: url('/images/mobile/center/user/car-noChecked.png') no-repeat;
+    background-size: contain;
+    &.active {
+      background-image: url('/images/mobile/center/user/car-checked.png');
+    }
+    vertical-align: middle;
+    margin-bottom: .02rem;
+    input {
+      display: none;
+    }
+    span {
+      font-size: .26rem;
+      margin-left: .15rem;
+      position: absolute;
+      left: .6rem;
+      top: .02rem;
+      font-weight: normal;
+    }
+  }
+</style>

+ 5 - 0
pages/mobile/center/user/index.vue

@@ -27,6 +27,11 @@
         </ul>
       </div>
       <div class="block-wrap collect-block">
+        <nuxt-link tag="div" to="/mobile/center/user/cart" class="content-line">
+          <img src="/images/mobile/center/user/comp-collect.png" alt="">
+          <span>购物车<span class="text">(0)</span></span>
+          <i class="iconfont icon-xiangyou"></i>
+        </nuxt-link>
         <nuxt-link tag="div" to="/mobile/center/user/collect/component" class="content-line">
           <img src="/images/mobile/center/user/comp-collect.png" alt="">
           <span>器件收藏<span class="text">({{compCount.data || 0}})</span></span>

二進制
static/images/mobile/center/user/car-checked.png


二進制
static/images/mobile/center/user/car-noChecked.png


+ 14 - 0
store/userCenter.js

@@ -0,0 +1,14 @@
+import axios from '~plugins/axios'
+
+export const actions = {
+  // app获取购物车列表
+  loadCartList({ commit }, params = {}) {
+    commit('list/REQUEST_CART')
+    return axios.get('/trade/cart/pageInfo', {params: params})
+      .then(response => {
+        commit('list/GET_CART_SUCCESS', response.data)
+      }, err => {
+        commit('list/GET_CART_FAILURE', err)
+      })
+  }
+}

+ 19 - 0
store/userCenter/list.js

@@ -0,0 +1,19 @@
+export const state = () => ({
+  cart: {
+    fetching: false,
+    data: []
+  }
+})
+
+export const mutations = {
+  REQUEST_CART (state) {
+    state.cart.fetching = true
+  },
+  GET_CART_FAILURE (state) {
+    state.cart.fetching = false
+  },
+  GET_CART_SUCCESS (state, result) {
+    state.cart.fetching = false
+    state.cart.data = result
+  }
+}

+ 45 - 1
utils/baseUtils.js

@@ -347,6 +347,11 @@ const _filterStringEllipsis = (str, len) => {
   return str ? _getRealLen(str) > len ? _cutOutString(str, len) + '...' : str : null
 }
 
+/*
+* @$this 上下文
+* @str 提示信息
+* @isMobile 是否移动端
+* */
 const _setMessage = ($this, str = '系统错误', isMobile) => {
   if (isMobile) {
     $this.setRemindText(str)
@@ -355,6 +360,12 @@ const _setMessage = ($this, str = '系统错误', isMobile) => {
   }
 }
 
+/*
+* @$this 上下文
+* @url 权限链接
+* @callBack 回调
+* @isMobile 是否移动端
+* */
 const _getAuthority = ($this, url, callBack, isMobile) => {
   return $this.$http.get('/user/authentication/isauthority', {params: {resUrl: url}}).then(res => {
     if (res.data.status === 'fail') {
@@ -368,6 +379,35 @@ const _getAuthority = ($this, url, callBack, isMobile) => {
   })
 }
 
+// 店铺类型筛选
+const _storeTypeFilter = (type) => {
+  let tmp = ''
+  switch (type) {
+    case 'CONSIGNMENT':
+      tmp = '寄售'
+      break
+    case 'DISTRIBUTION':
+      tmp = '经销'
+      break
+    case 'AGENCY':
+      tmp = '代理'
+      break
+    case 'ORIGIN_FACTORY':
+      tmp = '原厂'
+      break
+  }
+  return tmp
+}
+
+const _getPriceByLevel = (prices, number, currency) => {
+  let prName = currency === 'RMB' ? 'rMBPrice' : 'uSDPrice'
+  for (let i = 0; i < prices.length; i++) {
+    if (number >= prices[i].start && number <= prices[i].end) {
+      return prices[i][prName]
+    }
+  }
+}
+
 export default {
   // 获取字符串字符长度
   getRealLen: _getRealLen,
@@ -395,5 +435,9 @@ export default {
   // 截取字符长度并补充省略号
   filterStringEllipsis: _filterStringEllipsis,
   // 获取url权限
-  getAuthority: _getAuthority
+  getAuthority: _getAuthority,
+  // 获得店铺类型中文名
+  storeTypeFilter: _storeTypeFilter,
+  // 通过分段数量获取分段价格
+  getPriceByLevel: _getPriceByLevel
 }