创建和验证分层定价表



我正在尝试创建一个分层定价表单,允许我们根据客户的使用量更改价格。

我已经创建了一个可以添加和删除层的表单,但我希望能够验证这一点,所以第一个选项应该始终以0开头,最后一个层不应该有最大值,不应该有重叠,层之间也不应该有间隙。

例如:0-5、6-10、11-15、15-20、21+

而不是:2-5、7-11、10-12、13-19、20+

function update_max(){
var pricing_tiers = document.getElementsByClassName("batch_pricing_tier");
for(var i=0; i<pricing_tiers.length; i++){
if(i!=0){
var previous_tier = pricing_tiers.item(i-1);
var previous_cols = previous_tier.children;
var previous_max = parseInt(previous_cols[0].children[0].children[1].value);
}else{
var previous_max = -1;
}
var pricing_tier = pricing_tiers.item(i);
var pricing_cols = pricing_tier.children;
var minimum = parseInt(pricing_cols[0].children[0].children[1].value);
var maximum = parseInt(pricing_cols[1].children[0].children[1].value);
if(minimum <= previous_max){
var new_min = previous_max+2;
pricing_cols[0].children[0].children[1].value = new_min;
minimum = new_min;
}
if(maximum <= minimum){
var new_max = minimum+1;
pricing_cols[1].children[0].children[1].value = new_max;
}
}
}
$(".batch_add").click(function(){
$("#batch_form > div > div:first-child").clone(true).insertBefore("#batch_form > div > div:last-child");
update_max();
});
$(".batch_remove").click(function(){
$(this).parent().parent().remove();
update_max();
});
$(".max_update").change(function(){
update_max();
});
$("#batch_pricing_submit").click(function(){
var pricing_array = [];
var pricing_tiers = document.getElementsByClassName("batch_pricing_tier");
for(var i=0; i<pricing_tiers.length; i++){
pricing_array[i] = {};
var pricing_tier = pricing_tiers.item(i);
var pricing_cols = pricing_tier.children;
var minimum = pricing_cols[0].children[0].children[1].value;
var maximum = pricing_cols[1].children[0].children[1].value;
var price = pricing_cols[2].children[0].children[1].value;
pricing_array[i]['minimum'] = minimum;
pricing_array[i]['maximum'] = maximum;
pricing_array[i]['price'] = price;
}
console.log(pricing_array);
});
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<form class="form m-3" id="batch_form" method="POST">
<div>
<div class="row batch_pricing_tier">
<div class="col">
<div class="form-group">
<label for="minimum">Minimum</label>
<input class="form-control" type="text" value="0" required disabled>
</div>
</div>
<div class="col">
<div class="form-group">
<label for="maximum">Maximum</label>
<input class="form-control max_update" type="text" value="1" required>
</div>
</div>
<div class="col">
<div class="form-group">
<label for="price">Price</label>
<input class="form-control" type="text" placeholder="Price" name="price" id="price" required>
</div>
</div>
<div class="col">
<br /><span class="batch_remove float-right">Remove</span>
</div>
</div>
<div class="row batch_pricing_tier">
<div class="col">
<div class="form-group">
<label for="minimum">Minimum</label>
<input class="form-control" type="text" value="2" required disabled>
</div>
</div>
<div class="col">
<div class="form-group">
<label for="maximum">Maximum</label>
<input class="form-control max_update" type="text" value="inf" required disabled>
</div>
</div>
<div class="col">
<div class="form-group">
<label for="price">Price</label>
<input class="form-control" type="text" placeholder="Price" name="price" id="price" required>
</div>
</div>
<div class="col">
<br /><span class="batch_remove float-right">Remove</span>
</div>
</div>
</div>
<span class="d-block w-100 align-center">
<span class="batch_add float-right">Add fields</span>
<br />
<button class="btn btn-success" type="button" id="batch_pricing_submit" onclick="return false;">Add Batch Pricing</button>
</span>
</form>

编辑

这是一个基于使用情况的定价模型。因此,顾客使用的次数越多,价格就越便宜。例如:

$10/unit for 0 to 5 units.
$9/unit for 6 to 10 units.
$8/unit for 11 to 15 units.

因此,如果用户在一个计费期内使用8个单元,他们将被收取9 x 8个单元的费用,总计72美元。

每个产品都是不同的,所以会有不同层次的不同单位数量,所以我需要验证这一点。我需要第一层最低值才能从0开始。任何层的最大值都应大于最小值。下一层的最小值应大于上一层的最大值。各层之间不应存在间隙。各层之间不应存在重叠。

您可以编写update_max函数,使其能够按照您的意愿更新字段。

function update_max() {
let previous_max = -1;
let previous_min = 0;
$(".batch_pricing_tier").each(function(i, el) {
const minimumInput = $(el).find(".min_update")[0];
const maximumInput = $(el).find(".max_update")[0];
let minimum = previous_max + 1;
let maximum = Math.max(Number(maximumInput.value), minimum + 1);
previous_min = minimumInput.value = minimum;
if (!maximumInput.classList.contains("last_max"))
previous_max = maximumInput.value = maximum;
});
}
$(".batch_add").click(function() {
$("#batch_form > div > div:first-child").clone(true).insertBefore("#batch_form > div > div:last-child");
update_max();
});
$(".batch_remove").click(function() {
$(this).parent().parent().remove();
update_max();
});
$(".max_update").change(update_max);
$("#batch_pricing_submit").click(function() {
var pricing_array = [];
$(".batch_pricing_tier").each(function(i, el) {
const minimumInput = $(el).find(".min_update")[0];
const maximumInput = $(el).find(".max_update")[0];
const priceInput = $(el).find(".price")[0];
pricing_array.push({
maximum: Number(minimumInput.value),
minimum: Number(maximumInput.value),
price: Number(priceInput.value),
});
});
console.log(pricing_array);
});
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<form class="form m-3" id="batch_form" method="POST">
<div>
<div class="row batch_pricing_tier">
<div class="col">
<div class="form-group">
<label>Minimum
<input class="form-control min_update" type="number" value="0" required disabled>
</label>
</div>
</div>
<div class="col">
<div class="form-group">
<label>Maximum
<input class="form-control max_update" type="number" value="1" required>
</label>
</div>
</div>
<div class="col">
<div class="form-group">
<label>Price
<input class="form-control price" type="text" placeholder="Price" name="price" id="price" required>
</label>
</div>
</div>
<div class="col">
<br /><span class="batch_remove float-right">Remove</span>
</div>
</div>
<div class="row batch_pricing_tier">
<div class="col">
<div class="form-group">
<label>Minimum
<input class="form-control min_update" type="number" value="2" required disabled>
</label>
</div>
</div>
<div class="col">
<div class="form-group">
<label>Maximum
<input class="form-control max_update last_max" type="text" value="inf" required disabled>
</label>
</div>
</div>
<div class="col">
<div class="form-group">
<label>Price
<input class="form-control price" type="text" placeholder="Price" name="price" id="price" required>
</label>
</div>
</div>
<div class="col">
<br /><span class="batch_remove float-right">Remove</span>
</div>
</div>
</div>
<span class="d-block w-100 align-center">
<span class="batch_add float-right">Add fields</span>
<br />
<button class="btn btn-success" type="button" id="batch_pricing_submit" onclick="return false;">Add Batch Pricing</button>
</span>
</form>

有两个验证条件(以0开始,以inf结束(位于已知位置。所有其他(例如,没有间隙和重叠(都是关于将每一层与下一层进行比较。因此,从开始到倒数第二层,对它们进行循环,比较第i层和第i + 1层。这使您能够检查这些情况,并准确地找出错误的地方。如果没有发现任何问题,那么它是有效的。

function update_max() {
var pricing_tiers = document.getElementsByClassName("batch_pricing_tier");
for (var i = 0; i < pricing_tiers.length; i++) {
if (i != 0) {
var previous_tier = pricing_tiers.item(i - 1);
var previous_cols = previous_tier.children;
var previous_max = parseInt(previous_cols[0].children[0].children[1].value);
} else {
var previous_max = -1;
}
var pricing_tier = pricing_tiers.item(i);
var pricing_cols = pricing_tier.children;
var minimum = parseInt(pricing_cols[0].children[0].children[1].value);
var maximum = parseInt(pricing_cols[1].children[0].children[1].value);
if (minimum <= previous_max) {
var new_min = previous_max + 2;
pricing_cols[0].children[0].children[1].value = new_min;
minimum = new_min;
}
if (maximum <= minimum) {
var new_max = minimum + 1;
pricing_cols[1].children[0].children[1].value = new_max;
}
}
}
$(".batch_add").click(function() {
$("#batch_form > div > div:first-child").clone(true).insertBefore("#batch_form > div > div:last-child");
update_max();
});
$(".batch_remove").click(function() {
$(this).parent().parent().remove();
update_max();
});
$(".max_update").change(function() {
update_max();
});
$("#batch_pricing_submit").click(function() {
var pricing_array = [];
var pricing_tiers = document.getElementsByClassName("batch_pricing_tier");
for (var i = 0; i < pricing_tiers.length; i++) {
pricing_array[i] = {};
var pricing_tier = pricing_tiers.item(i);
var pricing_cols = pricing_tier.children;
var minimum = pricing_cols[0].children[0].children[1].value;
var maximum = pricing_cols[1].children[0].children[1].value;
var price = pricing_cols[2].children[0].children[1].value;
pricing_array[i]['minimum'] = minimum;
pricing_array[i]['maximum'] = maximum;
pricing_array[i]['price'] = price;
}
console.log(pricing_array);
console.log(validate(pricing_array));
});
function validate(pricing_array) {
var i = 0;
var min = null;
var max = null;
var price = null;
var nextMin = null;
var nextPrice = null;
//Does the first option start with 0?
if (parseInt(pricing_array[0].minimum) !== 0) {
return "First option does not start with 0";
};
//No max on last tier
if (typeof getInt(pricing_array[pricing_array.length - 1].maximum) === "number") {
return "The last tier must not have a maximum";
};
if (0 < pricing_array.length) {
for (i = 0; i < pricing_array.length - 1; i++) {
//Check data types
min = getInt(pricing_array[i].minimum);
max = getInt(pricing_array[i].maximum);
price = getInt(pricing_array[i].price);
nextMin = getInt(pricing_array[i + 1].minimum);
nextPrice = getInt(pricing_array[i + 1].price);
if (typeof max !== "number") {
return "The Maximum entered on Tier " + (i + 1) + " is not a number.";
};
if (typeof price !== "number") {
return "The Price entered on Tier " + (i + 1) + " is not a number.";
};
if (typeof nextMin !== "number") {
return "The Minimum entered on Tier " + (i + 2) + " is not a number.";
};
if (typeof nextPrice !== "number") {
return "The Price entered on Tier " + (i + 2) + " is not a number.";
};
//Check max and min
if (max < min) {
return "The Maximum on Tier " + (i + 1) + " is less than the Minimum.";
};
//Check no overlap - must be larger
if (nextMin <= max) {
return "Tier " + (i + 1) + " overlaps with Tier " + (i + 2) + ".";
};
//Check no gaps
if (1 < (nextMin - max)) {
return "There is a gap between Tier " + (i + 1) + " and Tier " + (i + 2) + ".";
};
//Does the price get cheaper?
if (nextPrice <= price) {
return "The Price does not get cheaper between Tier " + (i + 1) + " and Tier " + (i + 2) + ".";
};
};
};
return "OK";
};
function getInt(val) {
return parseInt(val) || val;
};
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<form class="form m-3" id="batch_form" method="POST">
<div>
<div class="row batch_pricing_tier">
<div class="col">
<div class="form-group">
<label for="minimum">Minimum</label>
<input class="form-control" type="text" value="0" required disabled>
</div>
</div>
<div class="col">
<div class="form-group">
<label for="maximum">Maximum</label>
<input class="form-control max_update" type="text" value="1" required>
</div>
</div>
<div class="col">
<div class="form-group">
<label for="price">Price</label>
<input class="form-control" type="text" placeholder="Price" name="price" id="price" required>
</div>
</div>
<div class="col">
<br /><span class="batch_remove float-right">Remove</span>
</div>
</div>
<div class="row batch_pricing_tier">
<div class="col">
<div class="form-group">
<label for="minimum">Minimum</label>
<input class="form-control" type="text" value="2" required disabled>
</div>
</div>
<div class="col">
<div class="form-group">
<label for="maximum">Maximum</label>
<input class="form-control max_update" type="text" value="inf" required disabled>
</div>
</div>
<div class="col">
<div class="form-group">
<label for="price">Price</label>
<input class="form-control" type="text" placeholder="Price" name="price" id="price" required>
</div>
</div>
<div class="col">
<br /><span class="batch_remove float-right">Remove</span>
</div>
</div>
</div>
<span class="d-block w-100 align-center">
<span class="batch_add float-right">Add fields</span>
<br />
<button class="btn btn-success" type="button" id="batch_pricing_submit" onclick="return false;">Add Batch Pricing</button>
</span>
</form>

检查以下代码段。您的原始代码有一些更改,但一般来说,需要这样的东西。

function update_max(index,quantity=1) {
if (index >= 0) {
let val = (index == 0 ? 0 : $(document).find('.row.batch_pricing_tier[data-row="' + index + '"] input.max_update').val());
$.each($(document).find('.row.batch_pricing_tier'), (k, x) => {
let row = parseInt($(x).attr('data-row'));
if (row > index) {
let items = $(x).find('input.form-control:not(.price)');
$.each(items, (i, y) => {
if ($(y).hasClass('max_update')) {
$(y).val(parseInt($(items[i - 1]).val()) + quantity);
} else {
if (index == 0 && row == 1) {
$(y).val(index);
} else {
$(y).val(parseInt($(document).find('.row.batch_pricing_tier[data-row="' + (row - 1 < index ? index : row - 1) + '"] input.max_update').val()) + 1);
}
}
});
}
});
}
}
$(".batch_add").click(function() {
let clone = $("#batch_form > div > div:first-child").clone(true);
$("#batch_form > div").append(clone);
let tiers = $(document).find('.row.batch_pricing_tier');
$("#batch_form > div > div:last-child").attr('data-row', tiers.length)
//update_max(tiers.length - 1); // default quantity 1
update_max(tiers.length - 1,4);
});
$(".batch_remove").click(function() {
let tiers = $(document).find('.row.batch_pricing_tier');
if (tiers.length > 1) {
let index = $(this).parents('.row.batch_pricing_tier').attr('data-row');
$(this).parents('.row.batch_pricing_tier').remove();
$.each($(document).find('.row.batch_pricing_tier'), (k, x) => {
$(x).attr('data-row', k + 1);
});
//update_max(index - 1); // default quantity 1
update_max(index - 1,4);
}
});
$(document).on("change", ".max_update", function() {
let index = $(this).parents('.row.batch_pricing_tier').attr('data-row');
//update_max(index); // default quantity 1
update_max(index,4);
});
$("#batch_pricing_submit").click(function() {
var pricing_array = [];
var pricing_tiers = document.getElementsByClassName("batch_pricing_tier");
for (var i = 0; i < pricing_tiers.length; i++) {
pricing_array[i] = {};
var pricing_tier = pricing_tiers.item(i);
var pricing_cols = pricing_tier.children;
var minimum = pricing_cols[0].children[0].children[1].value;
var maximum = pricing_cols[1].children[0].children[1].value;
var price = pricing_cols[2].children[0].children[1].value;
pricing_array[i]['minimum'] = minimum;
pricing_array[i]['maximum'] = maximum;
pricing_array[i]['price'] = price;
}
console.log(pricing_array);
});
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<form class="form m-3" id="batch_form" method="POST">
<div>
<div class="row batch_pricing_tier" data-row="1">
<div class="col">
<div class="form-group">
<label for="minimum">Minimum</label>
<input class="form-control" type="text" pattern="[0-9]" value="0" required disabled>
</div>
</div>
<div class="col">
<div class="form-group">
<label for="maximum">Maximum</label>
<input class="form-control max_update" pattern="[0-9]" type="text" value="5" required>
</div>
</div>
<div class="col">
<div class="form-group">
<label for="price">Price</label>
<input class="form-control price" type="text" placeholder="Price" name="price" required>
</div>
</div>
<div class="col">
<br /><span class="batch_remove float-right">Remove</span>
</div>
</div>
</div>
<span class="d-block w-100 align-center">
<span class="batch_add float-right">Add fields</span>
<br />
<button class="btn btn-success" type="button" id="batch_pricing_submit" onclick="return false;">Add Batch Pricing</button>
</span>
</form>

最新更新