• .NET经销商实战(十五)——购物车界面改造,全选功能实现与完善


    一.购物车数量前端数据渲染

    1.ShoppingCart.vue代码如下:

    点击查看代码
    <template>
      <div>
        <div class="cart-list">
          <ul>
            <li v-for="type in types" :key="type.typeNo">
              <p>
                <i></i>
                <span>{{ transTypeWhenNull(type.typeName) }}</span>
              </p>
              <template v-for="cart in carts" :key="cart.cartGuid">
                <div v-if="cart.productDto?.typeNo == type.typeNo">
                  <i></i>
                  <img src="" alt="" />
                  <p class="p-name">{{ cart.productDto?.productName }}</p>
                  <p class="p-price">&yen;{{}}</p>
                  <p class="p-num">
                    <span class="sub-num" @click="onSubNum(cart)">-</span>
                    <input v-model="cart.productNum" @change="onChangeNum(cart)" />
                    <span class="add0num" @click="onAddNum(cart)">+</span>
                    <b>块</b>
                  </p>
                </div>
              </template>
            </li>
          </ul>
        </div>
        <div class="total-pad">
          <i></i>
          <span>全选</span>
          <span>
            合计:&yen; <b>{{ totalPrice | price }}</b>
          </span>
          <button>确定下单</button>
        </div>
      </div>
    </template>
    
    <script>
    import { reactive, toRefs, onMounted } from 'vue'
    import { getCarts } from '@/httpRequests/ShoppingCartRequest'
    export default {
      // mounted() {
      //   this.$store.comm
      //   this.$store.dispatch('setFootMenuIndexAsync', 2)
      // },
      setup() {
        //数据发生改变时,这个方式不能及时获取变化后的数据
        //const productNumRef = ref()
        const shoppingCartInfo = reactive({
          carts: [],
          types: [],
          // buyNum: 1,
          totalPrice: 6888,
          onAddNum(cart) {
            cart.productNum++
          },
          onSubNum(cart) {
            if (cart.productNum > 1) {
              cart.productNum--
            }
          },
          onChangeNum(cart) {
            var currNum = event.target.value
            if (!isNaN(currNum) && currNum > 0) {
              cart.productNum = currNum
            } else {
              event.target.value = cart.productNum
            }
          },
          onGetShoppingCarts: async () => {
            var customerNo = localStorage['customerNo']
            var res = await getCarts(customerNo)
            shoppingCartInfo.carts = res.carts
            shoppingCartInfo.types = res.types
            console.log(res)
          },
          transTypeWhenNull: (typeName) => typeName ?? '未分类产品',
        })
        onMounted(() => {
          shoppingCartInfo.onGetShoppingCarts()
        })
        return { ...toRefs(shoppingCartInfo) }
      },
    }
    </script>
    
    <style lang="scss" scoped>
    .cart-list {
      text-align: left;
      ul {
        margin-bottom: 108px;
    
        li {
          background-color: #fff;
          margin-bottom: 12px;
    
          > p {
            padding-left: 46px;
            position: relative;
            height: 46px;
            border-bottom: 1px solid #ddd;
    
            i {
              border: 1px solid #a9a9a9;
               18px;
              height: 18px;
              line-height: 18px;
              border-radius: 18px;
              position: absolute;
              left: 13px;
              top: 13px;
              text-align: center;
              font-size: 12px;
              color: #fff;
              font-style: normal;
            }
    
            i.cart-select {
              background-color: crimson;
              border: 1px solid crimson;
            }
    
            span {
              display: inline-block;
              border-left: 3px solid crimson;
              height: 28px;
              margin: 9px 0;
              padding-left: 8px;
              line-height: 30px;
            }
          }
    
          div {
            padding-left: 46px;
            position: relative;
            height: 98px;
            padding: 8px 14px 8px 148px;
    
            i {
              border: 1px solid #a9a9a9;
               18px;
              height: 18px;
              line-height: 18px;
              border-radius: 18px;
              position: absolute;
              left: 13px;
              top: 28px;
              text-align: center;
              font-size: 12px;
              color: #fff;
              font-style: normal;
            }
    
            i.cart-select {
              background-color: crimson;
              border: 1px solid crimson;
            }
    
            img {
               68px;
              height: 68px;
              background-color: #ccc;
              position: absolute;
              left: 58px;
              top: 20px;
            }
    
            p.p-name {
              font-size: 13px;
              margin-top: 10px;
              height: 30px;
            }
            p.p-price {
              font-size: 13px;
              height: 20px;
              color: crimson;
            }
            p.p-num {
              text-align: right;
              padding-right: 20px;
    
              span {
                display: inline-block;
                 18px;
                height: 18px;
                border: 1px solid crimson;
                color: crimson;
                border-radius: 9px;
                text-align: center;
                line-height: 18px;
              }
    
              input {
                 28px;
                border: none 0px;
                outline: none;
                text-align: center;
              }
    
              b {
                font-weight: normal;
                margin-left: 10px;
                font-size: 13px;
              }
            }
          }
        }
      }
    }
    
    .total-pad {
      height: 58px;
       100%;
      background-color: #383838;
      position: fixed;
      left: 0;
      bottom: 40px;
    
      i {
        display: inline-block;
        border: 1px solid #a9a9a9;
         18px;
        height: 18px;
        line-height: 18px;
        border-radius: 18px;
        background-color: #fff;
        margin-left: 13px;
        margin-top: 20px;
        vertical-align: bottom;
        height: 18px;
        text-align: center;
        font-size: 12px;
        color: #fff;
        font-style: italic;
      }
    
      i.cart-select {
        background-color: crimson;
        border: 1px solid crimson;
      }
    
      span {
        color: #fff;
        margin-left: 6px;
        font-size: 13px;
    
        b {
          font-size: 15px;
        }
      }
    
      button {
        float: right;
        height: 58px;
         120px;
        border: 0 none;
        background-color: #ddd;
        color: #aaa;
        font-size: 15px;
        font-weight: bold;
      }
    }
    </style>
    
    

    2.后端ShoppingCartController控制器中修改GetShoppingCartDtos方法

    增加一个返回值TypeSeleted,默认赋值为false,这里我只是为了偷懒,所有用了dynamic,公司开发中最好不要用dynamic,否则会被人喷死

    3.shoppingCart前端全选功能实现

    点击查看代码
    <template>
      <div>
        <div class="cart-list">
          <ul>
            <li v-for="type in types" :key="type.typeNo">
              <p>
                <i :class="{ 'cart-select': type.typeSelected }">√</i>
                <span>{{ transTypeWhenNull(type.typeName) }}</span>
              </p>
              <template v-for="cart in carts" :key="cart.cartGuid">
                <div v-if="cart.productDto?.typeNo == type.typeNo">
                  <i
                    :class="{ 'cart-select': cart.cartSelected }"
                    @click="onSelectCart(cart)"
                    >√</i
                  >
                  <img src="" alt="" />
                  <p class="p-name">{{ cart.productDto?.productName }}</p>
                  <p class="p-price">&yen;{{}}</p>
                  <p class="p-num">
                    <span class="sub-num" @click="onSubNum(cart)">-</span>
                    <input v-model="cart.productNum" @change="onChangeNum(cart)" />
                    <span class="add0num" @click="onAddNum(cart)">+</span>
                    <b>块</b>
                  </p>
                </div>
              </template>
            </li>
          </ul>
        </div>
        <div class="total-pad">
          <i></i>
          <span>全选</span>
          <span>
            合计:&yen; <b>{{ totalPrice | price }}</b>
          </span>
          <button>确定下单</button>
        </div>
      </div>
    </template>
    
    <script>
    import { reactive, toRefs, onMounted } from 'vue'
    import { getCarts } from '@/httpRequests/ShoppingCartRequest'
    export default {
      // mounted() {
      //   this.$store.comm
      //   this.$store.dispatch('setFootMenuIndexAsync', 2)
      // },
      setup() {
        //数据发生改变时,这个方式不能及时获取变化后的数据
        //const productNumRef = ref()
        const shoppingCartInfo = reactive({
          carts: [],
          types: [],
          // buyNum: 1,
          totalPrice: 6888,
          onAddNum(cart) {
            cart.productNum++
          },
          onSubNum(cart) {
            if (cart.productNum > 1) {
              cart.productNum--
            }
          },
          onChangeNum(cart) {
            var currNum = event.target.value
            if (!isNaN(currNum) && currNum > 0) {
              cart.productNum = currNum
            } else {
              event.target.value = cart.productNum
            }
          },
          onGetShoppingCarts: async () => {
            var customerNo = localStorage['customerNo']
            var res = await getCarts(customerNo)
            shoppingCartInfo.carts = res.carts
            shoppingCartInfo.types = res.types
            // console.log(res)
          },
          onSelectCart: (cart) => {
            cart.cartSelected = !cart.cartSelected
            //找到类型中对应设置物品的类型
            var type = shoppingCartInfo.types.filter(
              (m) => m.typeNo == cart.productDto?.typeNo
            )[0]
            var cartsOfType = shoppingCartInfo.carts.filter(
              (s) => s.productDto?.typeNo == type?.typeNo
            )
            if (cartsOfType.every((m) => m.cartSelected)) {
              type.typeSelected = true
            } else {
              type.typeSelected = false
            }
          },
          transTypeWhenNull: (typeName) => typeName ?? '未分类产品',
        })
        onMounted(() => {
          shoppingCartInfo.onGetShoppingCarts()
        })
        return { ...toRefs(shoppingCartInfo) }
      },
    }
    </script>
    
    <style lang="scss" scoped>
    .cart-list {
      text-align: left;
      ul {
        margin-bottom: 108px;
    
        li {
          background-color: #fff;
          margin-bottom: 12px;
    
          > p {
            padding-left: 46px;
            position: relative;
            height: 46px;
            border-bottom: 1px solid #ddd;
    
            i {
              border: 1px solid #a9a9a9;
               18px;
              height: 18px;
              line-height: 18px;
              border-radius: 18px;
              position: absolute;
              left: 13px;
              top: 13px;
              text-align: center;
              font-size: 12px;
              color: #fff;
              font-style: normal;
            }
    
            i.cart-select {
              background-color: crimson;
              border: 1px solid crimson;
            }
    
            span {
              display: inline-block;
              border-left: 3px solid crimson;
              height: 28px;
              margin: 9px 0;
              padding-left: 8px;
              line-height: 30px;
            }
          }
    
          div {
            padding-left: 46px;
            position: relative;
            height: 98px;
            padding: 8px 14px 8px 148px;
    
            i {
              border: 1px solid #a9a9a9;
               18px;
              height: 18px;
              line-height: 18px;
              border-radius: 18px;
              position: absolute;
              left: 13px;
              top: 28px;
              text-align: center;
              font-size: 12px;
              color: #fff;
              font-style: normal;
            }
    
            i.cart-select {
              background-color: crimson;
              border: 1px solid crimson;
            }
    
            img {
               68px;
              height: 68px;
              background-color: #ccc;
              position: absolute;
              left: 58px;
              top: 20px;
            }
    
            p.p-name {
              font-size: 13px;
              margin-top: 10px;
              height: 30px;
            }
            p.p-price {
              font-size: 13px;
              height: 20px;
              color: crimson;
            }
            p.p-num {
              text-align: right;
              padding-right: 20px;
    
              span {
                display: inline-block;
                 18px;
                height: 18px;
                border: 1px solid crimson;
                color: crimson;
                border-radius: 9px;
                text-align: center;
                line-height: 18px;
              }
    
              input {
                 28px;
                border: none 0px;
                outline: none;
                text-align: center;
              }
    
              b {
                font-weight: normal;
                margin-left: 10px;
                font-size: 13px;
              }
            }
          }
        }
      }
    }
    
    .total-pad {
      height: 58px;
       100%;
      background-color: #383838;
      position: fixed;
      left: 0;
      bottom: 40px;
    
      i {
        display: inline-block;
        border: 1px solid #a9a9a9;
         18px;
        height: 18px;
        line-height: 18px;
        border-radius: 18px;
        background-color: #fff;
        margin-left: 13px;
        margin-top: 20px;
        vertical-align: bottom;
        height: 18px;
        text-align: center;
        font-size: 12px;
        color: #fff;
        font-style: italic;
      }
    
      i.cart-select {
        background-color: crimson;
        border: 1px solid crimson;
      }
    
      span {
        color: #fff;
        margin-left: 6px;
        font-size: 13px;
    
        b {
          font-size: 15px;
        }
      }
    
      button {
        float: right;
        height: 58px;
         120px;
        border: 0 none;
        background-color: #ddd;
        color: #aaa;
        font-size: 15px;
        font-weight: bold;
      }
    }
    </style>
    
    

    4.全选功能完善

    购物车界面

    点击查看代码
    <template>
      <div>
        <div class="cart-list">
          <ul>
            <li v-for="type in types" :key="type.typeNo">
              <p>
                <i
                  :class="{ 'cart-select': type.typeSelected }"
                  @click="onSelectType(type)"
                  >√</i
                >
                <span>{{ transTypeWhenNull(type.typeName) }}</span>
              </p>
              <template v-for="cart in carts" :key="cart.cartGuid">
                <div v-if="cart.productDto?.typeNo == type.typeNo">
                  <i
                    :class="{ 'cart-select': cart.cartSelected }"
                    @click="onSelectCart(cart)"
                    >√</i
                  >
                  <img src="" alt="" />
                  <p class="p-name">{{ cart.productDto?.productName }}</p>
                  <p class="p-price">&yen;{{}}</p>
                  <p class="p-num">
                    <span class="sub-num" @click="onSubNum(cart)">-</span>
                    <input v-model="cart.productNum" @change="onChangeNum(cart)" />
                    <span class="add0num" @click="onAddNum(cart)">+</span>
                    <b>块</b>
                  </p>
                </div>
              </template>
            </li>
          </ul>
        </div>
        <div class="total-pad">
          <i :class="{ 'cart-select': isAllSelected }">√</i>
          <span>全选</span>
          <span>
            合计:&yen; <b>{{ totalPrice | price }}</b>
          </span>
          <button>确定下单</button>
        </div>
      </div>
    </template>
    
    <script>
    import { reactive, toRefs, onMounted } from 'vue'
    import { getCarts } from '@/httpRequests/ShoppingCartRequest'
    export default {
      // mounted() {
      //   this.$store.comm
      //   this.$store.dispatch('setFootMenuIndexAsync', 2)
      // },
      setup() {
        //数据发生改变时,这个方式不能及时获取变化后的数据
        //const productNumRef = ref()
        const shoppingCartInfo = reactive({
          carts: [],
          types: [],
          isAllSelected: true,
          // buyNum: 1,
          totalPrice: 6888,
          onAddNum(cart) {
            cart.productNum++
          },
          onSubNum(cart) {
            if (cart.productNum > 1) {
              cart.productNum--
            }
          },
          onChangeNum(cart) {
            var currNum = event.target.value
            if (!isNaN(currNum) && currNum > 0) {
              cart.productNum = currNum
            } else {
              event.target.value = cart.productNum
            }
          },
          /**
           * 获取购物车信息
           */
          onGetShoppingCarts: async () => {
            var customerNo = localStorage['customerNo']
            var res = await getCarts(customerNo)
            shoppingCartInfo.carts = res.carts
            shoppingCartInfo.types = res.types
            // console.log(res)
          },
          /**
           * 点击选择购物车时触发
           */
          onSelectCart: (cart) => {
            cart.cartSelected = !cart.cartSelected
            //找到类型中对应设置物品的类型
            // var type = shoppingCartInfo.types.filter(
            //   (m) => m.typeNo == cart.productDto?.typeNo
            // )[0]
            // var cartsOfType = shoppingCartInfo.carts.filter(
            //   (s) => s.productDto?.typeNo == type?.typeNo
            // )
            shoppingCartInfo.checkTypeSelected()
          },
          /**
           * 选择类型时触发
           */
          onSelectType: (type) => {
            type.typeSelected = !type.typeSelected
            shoppingCartInfo.carts
              .filter((s) => s.productDto?.typeNo == type?.typeNo)
              .forEach((s) => {
                s.cartSelected = type.typeSelected
              })
            shoppingCartInfo.checkAllSelected()
          },
          checkTypeSelected: () => {
            shoppingCartInfo.types.forEach((type) => {
              var cartsOfType = shoppingCartInfo.carts.filter(
                (s) => s.productDto?.typeNo == type?.typeNo
              )
              //查看当前类型下的物品是否都被选择,是则将属于类型选中
              //否则不选中
              if (cartsOfType.every((m) => m.cartSelected)) {
                type.typeSelected = true
              } else {
                type.typeSelected = false
              }
            })
            shoppingCartInfo.checkAllSelected()
          },
          //全选 合计
          checkAllSelected: () => {
            if (shoppingCartInfo.carts.every((m) => m.cartSelected)) {
              shoppingCartInfo.isAllSelected = true
            } else {
              shoppingCartInfo.isAllSelected = false
            }
          },
          transTypeWhenNull: (typeName) => typeName ?? '未分类产品',
        })
        onMounted(() => {
          shoppingCartInfo.onGetShoppingCarts()
          shoppingCartInfo.checkTypeSelected()
        })
        return { ...toRefs(shoppingCartInfo) }
      },
    }
    </script>
    
    <style lang="scss" scoped>
    .cart-list {
      text-align: left;
      ul {
        margin-bottom: 108px;
    
        li {
          background-color: #fff;
          margin-bottom: 12px;
    
          > p {
            padding-left: 46px;
            position: relative;
            height: 46px;
            border-bottom: 1px solid #ddd;
    
            i {
              border: 1px solid #a9a9a9;
               18px;
              height: 18px;
              line-height: 18px;
              border-radius: 18px;
              position: absolute;
              left: 13px;
              top: 13px;
              text-align: center;
              font-size: 12px;
              color: #fff;
              font-style: normal;
            }
    
            i.cart-select {
              background-color: crimson;
              border: 1px solid crimson;
            }
    
            span {
              display: inline-block;
              border-left: 3px solid crimson;
              height: 28px;
              margin: 9px 0;
              padding-left: 8px;
              line-height: 30px;
            }
          }
    
          div {
            padding-left: 46px;
            position: relative;
            height: 98px;
            padding: 8px 14px 8px 148px;
    
            i {
              border: 1px solid #a9a9a9;
               18px;
              height: 18px;
              line-height: 18px;
              border-radius: 18px;
              position: absolute;
              left: 13px;
              top: 28px;
              text-align: center;
              font-size: 12px;
              color: #fff;
              font-style: normal;
            }
    
            i.cart-select {
              background-color: crimson;
              border: 1px solid crimson;
            }
    
            img {
               68px;
              height: 68px;
              background-color: #ccc;
              position: absolute;
              left: 58px;
              top: 20px;
            }
    
            p.p-name {
              font-size: 13px;
              margin-top: 10px;
              height: 30px;
            }
            p.p-price {
              font-size: 13px;
              height: 20px;
              color: crimson;
            }
            p.p-num {
              text-align: right;
              padding-right: 20px;
    
              span {
                display: inline-block;
                 18px;
                height: 18px;
                border: 1px solid crimson;
                color: crimson;
                border-radius: 9px;
                text-align: center;
                line-height: 18px;
              }
    
              input {
                 28px;
                border: none 0px;
                outline: none;
                text-align: center;
              }
    
              b {
                font-weight: normal;
                margin-left: 10px;
                font-size: 13px;
              }
            }
          }
        }
      }
    }
    
    .total-pad {
      height: 58px;
       100%;
      background-color: #383838;
      position: fixed;
      left: 0;
      bottom: 40px;
    
      i {
        display: inline-block;
        border: 1px solid #a9a9a9;
         18px;
        height: 18px;
        line-height: 18px;
        border-radius: 18px;
        background-color: #fff;
        margin-left: 13px;
        margin-top: 20px;
        vertical-align: bottom;
        height: 18px;
        text-align: center;
        font-size: 12px;
        color: #fff;
        font-style: normal;
      }
    
      i.cart-select {
        background-color: crimson;
        border: 1px solid crimson;
      }
    
      span {
        color: #fff;
        margin-left: 6px;
        font-size: 13px;
    
        b {
          font-size: 15px;
        }
      }
    
      button {
        float: right;
        height: 58px;
         120px;
        border: 0 none;
        background-color: #ddd;
        color: #aaa;
        font-size: 15px;
        font-weight: bold;
      }
    }
    </style>
    
    
  • 相关阅读:
    Codeforces G. Ciel the Commander
    点分治模板
    Codeforces I. Vessels(跳转标记)
    Codeforces C. Maximum Value(枚举二分)
    Codeforces D. Little Elephant and Interval(思维找规律数位dp)
    [USACO15DEC]最大流Max Flow(树上差分)
    Codeforces E. Alyona and a tree(二分树上差分)
    一致性Hash算法
    零拷贝
    Maven 指定范围依赖
  • 原文地址:https://www.cnblogs.com/humblexwang/p/16343909.html
Copyright © 2020-2023  润新知