您的位置:首页 > 其它

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

2016-01-13 08:38 429 查看

功能图如下:



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

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

{
"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');
})

}
}
});
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: