Notas Prácticas del Proyecto UNIAPP 68 Verificación del carrito de compras para confirmar el pedido

Notas Prácticas del Proyecto UNIAPP 68 Verificación del carrito de compras para confirmar el pedido

Ideas

Necesita usar vuex
para pasar valores entre páginas

Captura de pantalla del caso

Página de liquidación de pedidos

Página de carrito de compras Página
Insertar descripción de la imagen aquí
de confirmación de pedido
Insertar descripción de la imagen aquí
Página de pago

código

Página del carrito de compras del código frontal shopcart.vue

    <template>
        <view class="shop-cart">
            <template v-if=" list.length > 0 ">
                    
                <!-- 自定义导航栏 -->
                <uniNavBar
                    title="购物车"
                    :rightText=" isNavBar ? '完成' : '编辑'"
                    fixed="true"
                    statusBar="true"
                    @clickRight=" isNavBar = !isNavBar"
                ></uniNavBar>
                
                <!-- 商品内容 -->
                <view class="shop-item" v-for="(item,index) in list" :key="index">
                    <label for="" class="radio" @tap="selectedItem(index)">
                        <radio value="" color="#FF3333" :checked="item.checked" /> <text></text>
                    </label>
                    <image class="shop-img" :src="item.imgUrl" mode=""></image>
                    <view class="shop-text">
                        <view class="shop-name">
                            {
    
    {
    
    item.name}}
                        </view>
                        <view class="shop-color f-color">
                            {
    
    {
    
    item.color}}
                        </view>
                        <view class="shop-price">
                            <view class="">{
    
    {
    
    item.pprice}}
                            </view>
                            <template v-if="!isNavBar">
                                <view>x {
    
    {
    
    item.num}}</view>
                            </template>
                            <template v-else>
                                <uniNumberBox
                                    :value="item.num"
                                    :min=1
                                    @change="changeNumber($event,index,item)"
                                ></uniNumberBox>
                            </template>
                        </view>
                    </view>
                </view>
                <!-- 底部 -->
                <view class="shop-foot">
                    <label for="" class="radio foot-radio" @tap='checkedAllFn'>
                        <radio value="" color="#FF3333" :checked="checkedAll"></radio><text>全选</text>
                    </label>
                    <template v-if="!isNavBar">
                        <view class="foot-total">
                            <view class="foot-count">
                                合计:
                                <text class="f-active-color">{
    
    {
    
    totalCount.pprice}}
                                </text>
                            </view>
                            <view class="foot-num" @tap="goConfirmOrder">
                                结算({
    
    {
    
    totalCount.num}})
                            </view>
                        </view>
                    </template>
                    <template v-else>
                        <view class="foot-total">
                            <view class="foot-num" style="background-color: black;">
                                移入收藏夹
                            </view>
                            <view class="foot-num" @tap="delGoodsFn">
                                删除
                            </view>
                        </view>
                    </template>
                </view>
                
            </template>
            <template v-else>
                <uniNavBar 
                    title="购物车"
                    fixed="true"
                    statusBar="true"
                ></uniNavBar>
                <view class="shop-else-list">
                    <text>~ 购物车还是空的~</text>
                </view>
            </template>
            <Tabbar currentPage='shopcart'></Tabbar>
        </view>
    </template>

    <script>
        import $http from '@/common/api/request.js'
        import uniNavBar from '@/components/uni/uni-nav-bar/uni-nav-bar.vue'
        import uniNumberBox from '@/components/uni/uni-number-box/uni-number-box.vue'
        import Tabbar from '@/components/common/Tabbar.vue';//引入
        
        // 状态机引入
        import {
    
    mapState,mapActions,mapGetters,mapMutations} from 'vuex'
        export default {
    
    
            data() {
    
    
                return {
    
    
                    isNavBar:false,
                }
            },
            computed:{
    
    
                // 状态机数据处理
                ...mapState({
    
    
                    list:state=>state.cart.list,
                    selectedList:state=>state.cart.selectedList,
                }),
                ...mapGetters(['checkedAll','totalCount'])
            },
            components:{
    
    
                uniNavBar,uniNumberBox,Tabbar
            },
            onShow() {
    
    
              this.getData();  
            },
            methods: {
    
    
                ...mapActions(['checkedAllFn','delGoodsFn']),
                ...mapMutations(['selectedItem','initGetData']),
                getData(){
    
    
                    $http.request({
    
    
                        url:'/selectCart',
                        method:"POST",
                        header:{
    
    
                            token:true
                        }
                    }).then((res)=>{
    
    
                        this.initGetData(res)
                    }).catch(()=>{
    
    
                        uni.showToast({
    
    
                        title:'请求失败',
                        icon:'none'
                        })
                    })
                },
                changeNumber(value,index,item){
    
    
                    if ( value == item.num ) return;
                    $http.request({
    
    
                        url:'/updateCart',
                        method:"POST",
                        header:{
    
    
                            token:true
                        },
                        data:{
    
    
                            goodsId:item.goods_id,
                            num:value
                        }
                    }).then((res)=>{
    
    
                        this.list[index].num = value;
                    }).catch(()=>{
    
    
                        uni.showToast({
    
    
                        title:'请求失败',
                        icon:'none'
                        })
                    })
                },
                // 进入确认订单
                goConfirmOrder(){
    
    
                    if(this.selectedList.length === 0){
    
    
                        return uni.showToast({
    
    
                            title:"至少选择一件商品",
                            icon:"none"
                        })
                    }
                    uni.navigateTo({
    
    
                        url:`/pages/confirm-order/confirm-order?detail=${
      
      JSON.stringify(this.selectedList)}`
                    })
                }
            }
        }
    </script>

    <style lang="scss">

    .shop-list{
    
    
        padding-bottom: 100rpx;
    }
    .shop-else-list{
    
    
        position: absolute;
        left: 0;
        top: 0;
        right: 0;
        bottom: 0;
        background-color: #f7f7f7;
        display: flex;
        align-items: center;
        justify-content: center;
    }
    .shop-item{
    
    
        display: flex;
        padding: 20rpx;
        align-items: center;
        background-color: #f7f7f7;
        margin-bottom: 10rpx;
    }
    .shop-img{
    
    
        width: 200rpx;
        height: 200rpx;
    }
    .shop-text{
    
    
        flex: 1;
        padding-left: 20rpx;
    }
    .shop-color{
    
    
        font-size: 24rpx;
    }
    .shop-price{
    
    
        display: flex;
        justify-content: space-between;
    }

    .shop-foot{
    
    
        border-top: 2rpx solid #f7f7f7;
        background-color: #FFFFFF;
        position: fixed;
        bottom: 0;
        left: 0;
        width: 100%;
        height: 100rpx;
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 120rpx;
    }
    .foot-radio{
    
    
        padding-left: 20rpx;
    }
    .foot-total{
    
    
        display: flex;
    }
    .foot-count{
    
    
        line-height: 100rpx;
        padding: 0 20rpx;
        font-size: 32rpx;
    }
    .foot-num{
    
    
        background-color: #49bdfb;
        color: #FFFFFF;
        padding: 0 60rpx;
        line-height: 100rpx;
    }
    </style>

Confirmar código de página de pedido comfirm-order.vue

<template>
    <view class="confirm-order bg-active-color">
        <Lines></Lines>
        
        <!-- 地址 -->
        <view class="order-map" @tap="goPathList">
            <block v-if="path">
                <view class="map-title">
                    <view class="map-name">收件人:{
    
    {
    
    path.name}}</view>
                    <view class="">{
    
    {
    
    path.tel}}</view>
                </view>
                <view class="map-add">
                    收货地址:{
    
    {
    
    path.city}} {
    
    {
    
    path.detail}}
                </view>
            </block>
            <block v-else>
                <view class="map-title">
                    <view class="map-name">请选择地址</view>
                </view>
            </block>
            
        </view>
        
        <!-- 商品 -->
        <view class="goods-list" v-for="(item,index) in goodsList" :key="index">
                
            <view class="goods-content bg-active-color">
                <image class="goods-img" :src="item.imgUrl" mode=""></image>
                <view class="goods-text">
                    <view class="goods-name">
                        {
    
    {
    
    item.name}}
                    </view>
                    <view class="goods-size f-color">
                        颜色分类:黑色
                    </view>
                    <view class="f-active-color">
                        7天无理由
                    </view>
                </view>
                <view class="">
                    <view class="">{
    
    {
    
    item.pprice}}
                    </view>
                    <view class="goods-size">
                        x {
    
    {
    
    item.num}}
                    </view>
                </view>
            </view>
            
        </view>
    
        <!-- 底部:提交订单 -->
        <view class="order-foot">
            <view class="total-price">
                合计: <text class="f-active-color">${
    
    {
    
    totalCount.pprice}}</text>
            </view>
            <view class="confirm" @tap="goPayment">
                提交订单
            </view>
        </view>
    </view>
</template>

<script>
    import Lines from '@/components/common/Lines.vue'
    import {
    
    mapGetters,mapState} from 'vuex'
    export default {
    
    
        data() {
    
    
            return {
    
    
                path:false
            };
        },
        computed:{
    
    
            ...mapState({
    
    
                list:state=>state.cart.list
            }),
            ...mapGetters(['defaultPath','totalCount']),
            // 根据商品列表找到对应的e.detail 数据的 id 最终返回商品数据
            goodsList(){
    
    
                return this.item.map(id=>{
    
    
                    return this.list.find(v=>v.id == id)
                })
            }
        },
        onLoad(e) {
    
    
            console.log(e.detail,this.list);
            // 选中的商品id集合 [1,3]
            this.item = JSON.parse(e.detail);
            
            // 如果默认地址的一个赋值
            if(this.defaultPath.length){
    
    
                this.path = this.defaultPath[0];
            }
            
            // 如果出发自定义事件,on去接收值
            uni.$on('selectPathItem',(res)=>{
    
    
                // console.log(res);
                this.path = res;
            })
        },
        onUnload() {
    
    
          uni.$off('selectPathItem',()=>{
    
    
              console.log('移除了selectPathItem');
          })  
        },
        components:{
    
    
            Lines
        },
        methods:{
    
    
            // 跳转到地址管理页面
            goPathList(){
    
    
                uni.navigateTo({
    
    
                    url:'/pages/my-path-list/my-path-list?type=selectedPath'
                })
            },
            // 确认支付
            goPayment(){
    
    
                uni.navigateTo({
    
    
                    url:'/pages/payment/payment'
                })
            }
        }
    }
</script>

<style lang="less">
.confirm-order{
    
    
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    height: 100%;
}
.order-map{
    
    
    margin-bottom: 10rpx;
    padding: 20rpx;
    background-color: #fff;
    line-height: 50rpx;
}
.map-title{
    
    
    display: flex;
    justify-content: space-between;
}
.map-name{
    
    
    font-weight: bold;
}
.goods-list{
    
    
    background-color: #fff;
    padding: 10rpx 0;
}

.goods-content{
    
    
    padding: 10rpx 20rpx;
    display: flex;
    justify-content: space-between;
    align-items: center;
}
.goods-text{
    
    
    width: 360rpx;
    padding: 0 10rpx;
    font-size: 26rpx;
}
.goods-img{
    
    
    width: 160rpx;
    height: 160rpx;
}
.goods-size{
    
    
    font-size: 24rpx;
}

.order-foot{
    
    
    width: 100%;
    height: 80rpx;
    position: fixed;
    bottom: 0;
    left: 0;
    background-color: #fff;
    display: flex;
    justify-content: flex-end;
    align-items: center;
}
.confirm{
    
    
    color: #fff;
    background-color: #49bdfb;
    padding: 10rpx 30rpx;
}
.total-price{
    
    
    padding: 0 20rpx;
}


</style>

cart.js bajo vuex

export default{
    
    
    state:{
    
    
        list:[
                /* {
                    id:1,
                    name:"332经济法能聚聚会技能大赛 经济法能聚聚会技能大赛",
                    color:"颜色:嘿嘿嘿激活",
                    imgUrl:"../../static/logo.png",
                    pprice:"27",
                    num:1,
                    checked:false
                },{
                    id:2,
                    name:"032经济法能聚聚会技能大赛 经济法能聚聚会技能大赛",
                    color:"颜色:嘿嘿嘿激活",
                    imgUrl:"../../static/logo.png",
                    pprice:"48",
                    num:6,
                    checked:false
                } */
            ],
        selectedList:[]
        
    },
    getters:{
    
    
        // 判断是否 全选
        checkedAll(state){
    
    
            return state.list.length === state.selectedList.length;
        },
        // 合计 结算数量
        totalCount(state){
    
    
            let total = {
    
    
                pprice:0,
                num:0
            }
            state.list.forEach(v=>{
    
    
                // 是否选中
                if(state.selectedList.indexOf(v.id) > -1){
    
    
                    // 合计
                    total.pprice += v.pprice*v.num;
                    // 结算数量
                    total.num = state.selectedList.length;
                }
            })            
            
            return total;
        }
    },
    mutations:{
    
    
        // 请求到数据赋值操作
        initGetData(state,list){
    
    
            state.list = list;
        },
        // 全选
        checkAll(state){
    
    
            state.selectedList = state.list.map(v=>{
    
    
                v.checked = true;
                return v.id;
            })
        },
        // 全不选
        unCheckAll(state){
    
    
            state.list.forEach(v=>{
    
    
                v.checked = false;
            })
            state.selectedList = [];
        },
        // 单选
        selectedItem(state,index){
    
    
            let id = state.list[index].id;
            let i = state.selectedList.indexOf(id);
            // 如果selectList已经存在就代表他之前的选中状态,checked=false,并且在selectedList删除
            if (i>-1) {
    
    
                state.list[index].checked = false;
                return state.selectedList.splice(i,1);
            }
            // 如果之前没有选中,checked=true,把当前的id添加到selectedList
            state.list[index].checked = true;
            state.selectedList.push(id);
        },
        // 
        delGoods(state){
    
    
            state.list = state.list.filter(v=>{
    
    
                return state.selectedList.indexOf(v.id) === -1;
            })
        },
        // 加入购物车
        addShopCart(state, goods){
    
    
            state.list.push(goods);
        }
    },
    actions:{
    
    
        checkedAllFn({
     
     commit,getters}){
    
    
            getters.checkedAll ? commit("unCheckAll") : commit("checkAll")
        },
        delGoodsFn({
     
     commit}){
    
    
            commit('delGoods');
            commit("unCheckAll");
            uni.showToast({
    
    
                title:'删除成功',
                icon:"none"
            })
        }
    }
}

Estructura de directorios

Estructura del directorio front-end
  • Archivo de configuración manifest.json: appid, logo…

  • Archivo de configuración pages.json: navegación, barra de pestañas, enrutamiento

  • Archivo de entrada de inicialización de main.js vue

  • Configuración global de App.vue: estilos, monitoreo global

  • recursos estáticos estáticos: imágenes, iconos de fuentes

  • página página

    • índice
      • index.vue
    • lista
      • lista.vue
    • mi
      • mi.vue
    • mi-configuración
      • mi-config.vue
    • mi-configuración
      • mi-config.vue
    • mi-agregar-ruta
      • mi-agregar-ruta.vue
    • mi-lista-de-rutas
      • mi-lista-de-rutas.vue
    • buscar
      • buscar.vue
    • lista de búsqueda
      • lista de búsqueda.vue
    • carrito de compras
      • carrito de compras.vue
    • detalles
      • detalles.vue
    • mi pedido
      • mi-pedido.vue
    • confirmar pedido
      • confirmar-pedido.vue
    • pago
      • pago.vue
    • pago exitoso
      • pago-éxito.vue
    • acceso
      • iniciar sesión.vue
    • iniciar sesión-tel
      • login-tel.vue
    • código de inicio de sesión
      • login-code.vue
  • componentes componentes

    • índice
      • banner.vista
      • Caliente.vue
      • Iconos.vue
      • indexSwiper.vue
      • Recomendar.vue
      • Tienda.vue
      • Tabbar.vue
    • común
      • tarjeta.vue
      • Común.vue
      • CommondityList.vue
      • línea.vue
      • ShopList.vue
    • orden
      • lista de pedidos.vue
    • uni
      • caja uni-numérica
        • uni-number-box.vue
      • uni-iconos
        • uni-iconos.vue
      • barra de navegación uni
        • uni-nav-bar.vue
      • mpvue-citypicker
        • mpvueCityPicker.vue
  • archivos públicos comunes: archivo css global || archivo js global

    • API
      • solicitud.js
    • común.css
    • uni.css
  • almacenar el archivo de la máquina de estado vuex

    • módulos
      • carrito.js
      • ruta.js
      • usuario.js
    • index.js

Supongo que te gusta

Origin blog.csdn.net/gixome/article/details/130635087
Recomendado
Clasificación