Notas práticas do projeto UNIAPP 68 Verificação do carrinho de compras para confirmação do pedido

Notas práticas do projeto UNIAPP 68 Verificação do carrinho de compras para confirmação do pedido

Ideias

Precisa usar vuex
para passar valores entre páginas

Captura de tela do caso

Página de liquidação de pedidos

Página de carrinho de compras Página
Insira a descrição da imagem aqui
de confirmação de pedido
Insira a descrição da imagem aqui
Página de pagamento

código

Página do carrinho de compras com código front-end 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>

Confirme o código da página do 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>

carrinho.js em 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"
            })
        }
    }
}

Estrutura de diretório

Estrutura de diretório front-end
  • Arquivo de configuração manifest.json: appid, logo…

  • Arquivo de configuração pages.json: navegação, barra de guias, roteamento

  • arquivo de entrada de inicialização main.js vue

  • Configuração global do App.vue: estilos, monitoramento global

  • recursos estáticos estáticos: imagens, ícones de fontes

  • página página

    • índice
      • index.vue
    • lista
      • lista.vue
    • meu
      • meu.vue
    • minha-configuração
      • meu-config.vue
    • minha-configuração
      • meu-config.vue
    • meu-adicionar-caminho
      • meu-adicionar-caminho.vue
    • minha lista de caminhos
      • minha-lista de caminhos.vue
    • procurar
      • pesquisa.vue
    • lista de pesquisa
      • lista de pesquisa.vue
    • carrinho de compras
      • carrinho de compras.vue
    • detalhes
      • detalhes.vue
    • meu pedido
      • meu-pedido.vue
    • confirmar pedido
      • confirmar-pedido.vue
    • pagamento
      • pagamento.vue
    • sucesso de pagamento
      • sucesso de pagamento.vue
    • Conecte-se
      • login.vue
    • login-tel
      • login-tel.vue
    • Código de acesso
      • login-code.vue
  • componentes componentes

    • índice
      • banner.view
      • Hot.vue
      • Ícones.vue
      • indexSwiper.vue
      • Recomendar.vue
      • Loja.vue
      • Tabbar.vue
    • comum
      • Cartão.vue
      • Commondidade.vue
      • CommondityList.vue
      • Linha.vue
      • ShopList.vue
    • ordem
      • lista de pedidos.vue
    • uni
      • caixa de número uni
        • uni-number-box.vue
      • uni-ícones
        • uni-icons.vue
      • barra de navegação uni
        • uni-nav-bar.vue
      • mpvue-citypicker
        • mpvueCityPicker.vue
  • arquivos públicos comuns: arquivo css global || arquivo js global

    • API
      • solicitação.js
    • comum.css
    • uni.css
  • armazenar arquivo de máquina de estado vuex

    • módulos
      • carrinho.js
      • caminho.js
      • usuário.js
    • index.js

Acho que você gosta

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