产品详情页配送送信息联动的实现逻辑

功能图如下:


需要实现选择运送国家时,相应的运送方式随着改变,同时运送价格也改变

后台返回的部分数据如下:

{
    "jsonrpc":"2.0",
    "id":null,
    "result":{
        "delivery_info":{
            "1":[//对应的country   id
                {  //  country支持的运送方式
                    "delivery_price":44.5,
                    "delivery_name":"邮政挂号小包"
                }
            ],
      
            "235":[
                {
                    "delivery_price":18.1,
                    "delivery_name":"邮政挂号小包"
                },
                {
                    "delivery_price":31,
                    "delivery_name":"线上e邮宝"
                },
                {
                    "delivery_price":31,
                    "delivery_name":"线下e 邮宝"
                }
            ],
            
        },
        "countries":[
            [
                235,//country id
                "美国" // country 名
            ],
            [
                233,
                "英国"
            ],
            [
                3,
                "Afghanistan, Islamic State of"
            ],
            [
                6,
                "Albania"
            ],
            
        ]
    }
}

国家下拉列表的实现:

     将countries字段循环绑定到下拉列表上,xml对应的如下:

      

<div t-attf-class="form-group col-lg-6 col-md-6 product_shipping"  id="product_shipping" >
     <label class="control-label" for="shipping_country_id">运至</label>
     <button type="button" name="product_shipping_country_id" class="btn btn-default dropdown-toggle country_ul" id="dropdownMenu2"
             data-toggle="dropdown" aria-haspopup="true" aria-expanded="true"  value="United States" ng-click="search()">
        <span class="cty-name" id="s_cty-name">United Status</span>
                                         
        <span class="caret" id="s_caret"></span>
     </button>
     <div class="btn_search btn-default dropdown-toggle search_country">
          <input type="text" id="s_country" style="border:none;" placeholder="搜索(国家名)" ng-model="product_query.value"/>
     </div>
//国家下拉列表
    <ul class="dropdown-menu dp-menu-ul" aria-labelledby="dropdownMenu2" >
         <li ng-repeat="country in countries | filter:product_query.value">
             <a href="javascript:;" value="{{country[0]}}"   data-index= "{{$index}}" data-delivery-fee="{{delivery_info[country[0]]}}" 
                ng-bind="country[1]"></a>
         </li>
    </ul>
</div>
效果图如下:


为了要显示所选择的国家对应的运送方式,可以从后台返回的数据delivery_info中找到当前国家的id对应的运送信息和价格。

$scope.transportInfo = $scope.delivery_info[$scope.countries[$scope.curSelectedIndexTop][0]];
$scope.curSelectedIndexTop记录当前选中的是countries中的第几个国家,之所以需要该字段来记录,是因为在后面改变商品数量,重新获得运送信息和价格时,仍然需要保证是上次所选中的国家。

运送方式对应的xml文件内容如下:

<div class="product_shipping_fee col-lg-6 col-md-6 product_shipping" id="deli-mf">
	   <label class="control-label label-txt" for="">运送方式</label>
	   <div class="shipping_fee_type">
	           <button type="button" class="btn btn-default dropdown-toggle transport_ul"
	                id="dropdownMenu-ship" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true" ng-click="delivultoggle()">
	               <span class="cty-name" id="s_deliv-name">The Poste</span>
	                <span class="caret" id="s_deliv-caret"></span>
	            </button>
	            <ul class="dp-menu-ul dp-ship-ls" aria-labelledby="dropdownMenu-ship" ng-show="showdelivul">
	                <li ng-repeat="delivery in transportInfo">
	                    <a href="javascript:;" ng-bind="delivery.delivery_name" data-price="{{delivery.delivery_price}}" data-index="{{$index}}"></a>
	                </li>
	            </ul>
	    </div>
 </div>

同样需要一个字段来记录当前选中的配送方式,从而获得对应的运送价格

$scope.shipMethodIndex
$scope.ship_price = $scope.transportInfo[$scope.shipMethodIndex].delivery_price;

运送价格对应的xml文件内容如下:

<div class="product_shipping_fee col-lg-6 col-md-6 product_shipping pst-wp">
      <lable class="control-label label-price">运送价格</lable>
      <div class="price">
          <span>¥</span>
          <span ng-bind="ship_price"></span> 
          <a href="#" data-toggle="tooltip" data-placement="top" title="含国内邮费+打包费共计3元"><i class="glyphicon glyphicon-question-sign"></i> </a>
      </div>
</div>

那么当选择不同的国家时,对应的运送信息和价格如何随着改变呢?

我在每个国家对应的a标签中设置了data-index,记录它是第几个国家,同时,将该国家的运送信息绑定到data-delivery-fee上。这样当点击选择不同的国家时,改变transportInfo和curSelectedIndexTop。

<a href="javascript:;" value="{{country[0]}}"   data-index= "{{$index}}" data-delivery-fee="{{delivery_info[country[0]]}}"     ng-bind="country[1]"></a>
scope.transportInfo = $(this).data('delivery-fee');
scope.curSelectedIndexTop = parseInt($(this).data('index'));//记录当前选中的是哪个国家
此外,改变运送国家时,将当前的运输方式默认设置为默认第一个:

$('#s_deliv-name').text(scope.transportInfo[0].delivery_name);
scope.ship_price = scope.transportInfo[0].delivery_price;
当改变运输方式时,让运输价格随着改变,实现逻辑和改变运送国家让运输信息随着改变一样

<a href="javascript:;" ng-bind="delivery.delivery_name" data-price="{{delivery.delivery_price}}" data-index="{{$index}}"></a>

以上便是大致的联动逻辑。那么当改变商品数量时如何使得对应的价格随着更新呢?

触发商品数量改变的点击事件时,重新向后台发送请求取得数据。

$scope.delivery_info = data.delivery_info;
$scope.transportInfo = $scope.delivery_info[$scope.countries[$scope.curSelectedIndexTop][0]];
if($scope.transportInfo.length) {
     $('#s_deliv-name').text($scope.transportInfo[$scope.shipMethodIndex].delivery_name);
     $scope.ship_price = $scope.transportInfo[$scope.shipMethodIndex].delivery_price;
}

这里会利用记录的$scope.curSelectedIndexTop,$scope.shipMethodIndex仍然显示之前选中的国家。

因为在页面中有两个地方需要展示运输信息,所以逻辑相比于单个来说会麻烦一些,之前碰到的问题是,改变其中一个总是时不时的影响另一个,所以需要不同的变量来保存格式的国家和运送信息,
我这里的定义变量如下:

* $scope.delivery_info = data.delivery_info; 商品详情部分 所有国家的运送信息
    * $scope.delivery_info_ship; 运送信息部分 所有国家的运送信息
    * $scope.transportInfo; 商品详情部分 当前所选国家对应运送信息
    * $scope.deliveryDetail; 运送信息部分 当前所选国家对应运送信息
    * $scope.curSelectedIndexTop; 商品详情部分 记录当前选中的country
    * $scope.curSelectedIndex;运送信息部分 记录当前选中的country
    * $scope.shipMethodIndex; 商品详情部分 记录当前选中的运输方式
此外,我利用了index来区分当前到底在改变商品详情部分还是运送信息部分的数量。

//数量改变时的请求处理
//产品详情部分数量改变
if(parseInt($elem.data('index')) === 0) {
$scope.delivery_info = data.delivery_info;
$scope.transportInfo = $scope.delivery_info[$scope.countries[$scope.curSelectedIndexTop][0]];
if($scope.transportInfo.length) {
     $('#s_deliv-name').text($scope.transportInfo[$scope.shipMethodIndex].delivery_name);
     $scope.ship_price = $scope.transportInfo[$scope.shipMethodIndex].delivery_price;
}
}//配送信息部分数量改变
else if(parseInt($elem.data('index')) === 1) {
$scope.delivery_info_ship = data.delivery_info;
$scope.deliveryDetail = $scope.delivery_info_ship[$scope.countries[$scope.curSelectedIndex][0]];
}
完整的js代码如下:

//angular.module('product.description');
/**
    * $scope.delivery_info = data.delivery_info; 商品详情部分 所有国家的运送信息
    * $scope.delivery_info_ship; 运送信息部分 所有国家的运送信息
    * $scope.transportInfo; 商品详情部分 当前所选国家对应运送信息
    * $scope.deliveryDetail; 运送信息部分 当前所选国家对应运送信息
    * $scope.curSelectedIndexTop; 商品详情部分 记录当前选中的country
    * $scope.curSelectedIndex;运送信息部分 记录当前选中的country
    * $scope.shipMethodIndex; 商品详情部分 记录当前选中的运输方式

    页面初始化和每次商品数量改变时发送请求,得到新的数据,将每个国家对应的运输信息绑定到对应的a标签中,
    改变国家时取出对应的信息,然后改变显示的运输方式和价格。
    注意区分 [商品详情部分] 的运送信息  和   [运送信息部分] 的运送信息,改变其中一个的数量时不能影响另一个的运送信息
*/

var app= angular.module('product.description', ["ui.bootstrap", "ngSanitize","highcharts-ng"]);
app.controller('desController', function ($scope, $sce, $log, $http, $location) {

    $scope.product_template_id = parseInt($('#product_comments_li').data('id'), 10);
    $scope.product_description_images = [];
    $scope.curSelectedIndexTop = 0;
    $scope.curSelectedIndex = 0;
    $scope.shipMethodIndex = 0;
    $scope.init = true;
    $scope.description_html ='';
    $scope.extractCountry = function($elem){
        var jsonp = {
            jsonrpc: "2.0",
            method: "call",
            params: {
                quantity: parseInt($elem.val())
            }
        };
        if(jsonp.params.quantity <= 0) {
            jsonp.params.quantity = 1;
            $elem.val(1);
        }
        $http.post('/shop/product/country/'+ $scope.product_template_id ,jsonp)
            .success(function(data){
                data = data.result;
                $scope.countries = data.countries;
                
                //页面初始化
                if($scope.init) {
                    //产品详情部分的delivery_info,包含所有国家的运送信息
                    $scope.delivery_info = data.delivery_info;
                    //配送信息部分的delivery_info,包含所有国家的运送信息
                    $scope.delivery_info_ship = data.delivery_info;

                    //当前所选国家对应的运输信息
                    $scope.transportInfo = $scope.delivery_info[$scope.countries[$scope.curSelectedIndexTop][0]];
                    $scope.deliveryDetail = $scope.delivery_info_ship[$scope.countries[$scope.curSelectedIndex][0]];
                    //初始化选中的国家,运输方式,价格
                    $('#s_deliv-name').text($scope.transportInfo[$scope.shipMethodIndex].delivery_name);
                    $('#s_cty-name_btm').text($scope.countries[$scope.curSelectedIndex][1]);
                    $('#s_cty-name').text($scope.countries[$scope.curSelectedIndexTop][1]);
                    $scope.ship_price = $scope.transportInfo[$scope.shipMethodIndex].delivery_price;
                    $scope.init = false;
                }else {
                    //数量改变时的请求处理
                    //产品详情部分数量改变
                    if(parseInt($elem.data('index')) === 0) {
                        $scope.delivery_info = data.delivery_info;
                        $scope.transportInfo = $scope.delivery_info[$scope.countries[$scope.curSelectedIndexTop][0]];
                        if($scope.transportInfo.length) {
                             $('#s_deliv-name').text($scope.transportInfo[$scope.shipMethodIndex].delivery_name);
                             $scope.ship_price = $scope.transportInfo[$scope.shipMethodIndex].delivery_price;
                        }
                    }//配送信息部分数量改变
                    else if(parseInt($elem.data('index')) === 1) {
                        $scope.delivery_info_ship = data.delivery_info;
                        $scope.deliveryDetail = $scope.delivery_info_ship[$scope.countries[$scope.curSelectedIndex][0]];
                    }
                }

            })
    };
    if($scope.product_template_id && $scope.product_template_id > 0) {
        // $('.search_country').css('display','block');
        // $('.dropdown-menu').css('display','block');
        $('.dp-ship-ls').css('display','block');
        $scope.extractCountry($('#product_quantity'));
    }

    $scope.extractDescription = function(){
        var $description = $('#product_full_description'),
            url;
        if($description.data('add-need-desc')){
            url = $description.data('url');
            $http.post("/desc/", {
                'url' : url
            }).success(function (data) {
                if(data.status == 200){
                    $description.html('<div class="description_table">'+data.table+'</div>');
                    $description.append(data.desc);
                }
            });
        }
    };
    
    
    $scope.zip_dataPackage = function(){
        var uuid=$('#epic-buy').data('uuid');
        //console.log(uuid);
        var form2 = document.createElement("form"),
            input = document.createElement("input");
        form2.id = "data_package_form";
        form2.name = "data_package_form";

        // 添加到 body 中
        document.body.appendChild(form2);

        // 创建一个输入

        // 设置相应参数
        input.type = "text";
        input.name = "uuid";
        input.value = uuid;

        // 将该输入框插入到 form 中
        form2.appendChild(input);



        // form 的提交方式
        form2.method = "GET";
        // form 提交路径
        form2.action = "/tornado/get/packet";
        //event.preventDefault()
        // 对该 form 执行提交
        form2.submit();
        // 删除该 form
        document.body.removeChild(form2);
    };
    $scope.comments = [];
    $scope.comments_count = 0;
    $scope.currentPage = 2;
    $scope.totalItems = 100;
    $scope.itemsPerPage = 5;
    $scope.showProductDetail=true;
    $scope.showComments=false;
    $scope.showShippingInfo=false;
    $scope.showTrend=false;
    $scope.text = "";
    $scope.currentPage = 1;
    $scope.items_per_page = 5;
    $scope.extractDescription();
    $scope.get_comments();
    //$scope.zip_images();

    $scope.toProductDetail = function() {
        $scope.showProductDetail=true;
        $scope.showComments=false;
        $scope.showShippingInfo=false;
        $scope.showTrend=false;
    };
    $scope.toComments = function() {
        $scope.showProductDetail=false;
        $scope.showComments=true;
        $scope.showShippingInfo=false;
        $scope.showTrend=false;
    };
    $scope.toShippingInfo = function() {
        $('.shipping_info').css('display','block');
        $scope.showProductDetail=false;
        $scope.showComments=false;
        $scope.showShippingInfo=true;
        $scope.showTrend=false;
    };
    $scope.toTrend = function() {
        $scope.showProductDetail=false;
        $scope.showComments=false;
        $scope.showShippingInfo=false;
        $scope.showTrend=true;
    };
   
    $scope.get_trend = function () {
        if(document.getElementById('product_trend_li'))
        {
            trend = JSON.parse(document.getElementById('product_trend_li').dataset['trend']);
            var sales_trend = trend;
            $scope.chartConfig.series[0].data = sales_trend.measures.sales_quantity;
            $scope.chartConfig.xAxis[0].categories = sales_trend.dimension;
            $scope.chartConfig.title.text = trend.name;
            $scope.chartConfig.subtitle.text = "该产品过去三个月的销量趋势(wish平台目前只能抓取评价数目趋势)" ;
        }

    };
    $scope.get_trend();
    $scope.product_query = {
        value : ''
    };
    $scope.showCtyMenu = false;
    $scope.search = function(){
        var state = $('.product_shipping .search_country').css('display');
        if(state == "none")
        {
            $('.product_shipping .search_country').css('display', 'block');
            $('.product_shipping .dropdown-menu').show();
        }
        else
        {
            $('.product_shipping .search_country').css('display', 'none');
            $('.product_shipping .dropdown-menu').hide();
        }
        $scope.product_query.value = "";//每次点击下拉时重置query的值
    };

    $scope.visible = false;
    $scope.showdelivul = false;
    $scope.showtoggle = function() {
        $scope.visible = !$scope.visible;
        $scope.product_query.value = "";
    };
    $scope.delivultoggle = function() {
        $scope.showdelivul  = !$scope.showdelivul;
    };

   
});
app.directive('wrapDirective',function() {
    return {
        restrict: 'AE',
        scope: false,
        link: function(scope,elements) {
            $(elements[0]).on('click',function(ev) {
                if(ev.toElement !=$('#dropdownMenu2')[0]&&ev.toElement !=$('#s_country')[0]
                    &&ev.toElement !=$('#s_cty-name')[0]&&ev.toElement !=$('#s_caret')[0]){
                    $('.product_shipping .search_country').css('display', 'none');
                    $('.product_shipping .dropdown-menu').hide();
                     scope.$apply();
                    
                }
                if(ev.toElement !== $('#dropdownMenu3')[0] && ev.toElement !== $('#s_country_btm')[0] 
                    && ev.toElement !== $('#s_cty-name_btm')[0]&&ev.toElement !== $('#s_caret_btm')[0]){
                    scope.visible = false;
                    scope.$apply();
                }

                if(ev.toElement !== $('#dropdownMenu-ship')[0] && ev.toElement !== $('#s_deliv-name')[0]
                    &&ev.toElement !== $('#s_deliv-caret')[0]) {
                    scope.showdelivul = false;
                    scope.$apply();
                 }
            })
            //商品详情部分  监听商品数量变化
            .on('change','#product_quantity', function() {
                if(scope.product_template_id && scope.product_template_id > 0) {
                    scope.extractCountry($(this));
                }
            }) 
            // 商品详情部分  监听改变商品数量的按钮点击事件
            .on('click', 'span.change_product_number', function (ev) {
                ev.preventDefault();
                var $link = $(ev.currentTarget);
                var $input = $link.parent().find("input");
                var min = parseFloat($input.data("min") || 1);
                var max = parseFloat($input.data("max") || Infinity);
                var quantity = ($link.has(".fa-minus").length ? -1 : 1) + parseFloat($input.val(),10);
                $input.val(quantity > min ? (quantity < max ? quantity : max) : min);
                $('input[name="'+$input.attr("name")+'"]').val(quantity > min ? (quantity < max ? quantity : max) : min);
                if(scope.product_template_id && scope.product_template_id > 0) {
                    scope.extractCountry($('#product_quantity'));
                }
                return false;
            })
        }
    }
})
.directive('shippingCountry', function() {
    return {
        restrict: 'AE',
        scope: false,
        link: function(scope,elements) { //运送信息部分 国家选择事件
            $(elements[0]).on('click','.dp-menu-wp li a',function() {
                var ctyname = $.trim($(this).text());
                scope.curSelectedIndex = parseInt($(this).data('index'));
                $('#s_cty-name_btm').text(ctyname);
                scope.visible = false;
                scope.deliveryDetail = $(this).data('delivery-fee');
                 //检查数据有没有更新
                scope.$apply();
            })
        }

    }
})
.directive('numChange',function() {
    return {
        restrict: 'AE',
        scope: false,
        link: function(scope,elements) { //运送信息部分,商品数量改变事件
            $(elements[0]).on('change', function() {
                if(scope.product_template_id && scope.product_template_id > 0) {
                    scope.extractCountry($(this));
                    
                    //若在这里执行更新,每次获得的是上一次请求的数据
                    //scope.deliveryDetail = scope.delivery_info[scope.countries[scope.curSelectedIndex][0]];
                    //scope.$apply();
                }
            })
        }
    }
})

.directive('prodetailDir',function() {
    return {
        restrict: 'AE',
        scope: false,
        link: function(scope,elements) { //商品详情部分  选择国家事件
            $(elements[0]).on('click','.dropdown-menu li a', function() {
                $('.dp-ship-ls').css('display','block');
                scope.transportInfo = $(this).data('delivery-fee');
                scope.curSelectedIndexTop = parseInt($(this).data('index'));
                //改变运送国家时,将当前的运输方式设置为默认第一个
                if(scope.transportInfo.length) {
                    $('#s_deliv-name').text(scope.transportInfo[0].delivery_name);
                    scope.ship_price = scope.transportInfo[0].delivery_price;
                } else {
                    $('#s_deliv-name').text('暂不支持运送');
                    $('.dp-ship-ls').css('display','none');
                    scope.ship_price = 0.00;
                }
                
                scope.shipMethodIndex = 0;

                $('#dropdownMenu2').find('.cty-name').text($.trim($(this).text()));


                if($(this).attr('delivery-fee')){
                    $('#dropdownMenu2').attr('delivery-fee', parseFloat($(this).attr('delivery-fee')));

                } else {
                    $('#dropdownMenu2').attr('delivery-fee', 0);

                }

                $('#dropdownMenu2').val($.trim($(this).text())).change();
                $('.product_shipping .search_country').css('display', 'none');
                $('.product_shipping .dropdown-menu').hide();


                if($(this).attr('delivery-fee')){
                    $('#dropdownMenu2').attr('delivery-fee', parseFloat($(this).attr('delivery-fee')));
                } else {
                    $('#dropdownMenu2').attr('delivery-fee', 0);
                }
                $('#dropdownMenu2').val($.trim($(this).text())).change();
                // $('.product_shipping .search_country').css('display', 'none');
                // $('.product_shipping .dropdown-menu').hide();
                // $scope.showCtyMenu = false;
                scope.$apply();
            })
            //商品详情部分  选择运输方式事件
            .on('click','.dp-ship-ls li a', function() {
                scope.visible = false;
                var shipname = $.trim($(this).text());
                scope.shipMethodIndex = parseInt($(this).data('index'));
                $('#s_deliv-name').text(shipname);
                scope.ship_price = $(this).data('price');
            })

        }
    }
});






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值