305 lines
9.0 KiB
JavaScript
305 lines
9.0 KiB
JavaScript
$(function () {
|
|
const $days = $('.package_list p');
|
|
const $priceTables = $('.country_lists');
|
|
const $showPriceDiv = $('.show_price');
|
|
const $totalPriceSpan = $('.totalPrices');
|
|
let result = [];
|
|
let submitFlag = false;
|
|
|
|
|
|
// tab click
|
|
$days.on('click', function () {
|
|
const targetDay = $(this).data('day');
|
|
$days.removeClass('active');
|
|
$(this).addClass('active');
|
|
$priceTables.hide().filter(`[data-day="${targetDay}"]`).show();
|
|
});
|
|
|
|
// country_lists_detail click
|
|
$priceTables.on('click', '.country_lists_detail', function () {
|
|
const number = $(this).data('num');
|
|
// if(number <1) return messageFn(tipsQuantity);
|
|
$(this).toggleClass('active');
|
|
updateUI();
|
|
});
|
|
|
|
// buy click
|
|
$('.buyNow').on('click', function () {
|
|
const session = localStorage.getItem("session");
|
|
const user = localStorage.getItem("user");
|
|
const selectedItems = getSelectedItems();
|
|
|
|
let lang = $('#language').val();
|
|
var currentUrl = window.location.href;
|
|
var match = currentUrl.match(/\.com(.*)/);
|
|
|
|
if (!session || !user || user == undefined || user == "undefined") {
|
|
let url = "/sign-up/" ;
|
|
if (lang == "zh"){
|
|
url = `/${lang}/sign-up/`
|
|
}
|
|
let r = "";
|
|
if (match && match.length > 1) {
|
|
var contentAfterCom = match[1];
|
|
r = contentAfterCom;
|
|
}
|
|
window.location.href = url +"?r=" + r
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
if (selectedItems.length === 0) {
|
|
messageFn('Please select the purchase quantity');
|
|
return;
|
|
}
|
|
|
|
const transformedData = [];
|
|
selectedItems.forEach(dayObj => {
|
|
const day = dayObj.day;
|
|
dayObj.items.forEach(item => {
|
|
const code = item.code;
|
|
const num = item.count;
|
|
transformedData.push({ day, code, num,lang });
|
|
});
|
|
});
|
|
borderFn(transformedData)
|
|
|
|
});
|
|
|
|
const borderFn = async(orderList) => {
|
|
if(submitFlag) return;
|
|
submitFlag = true;
|
|
$('.loading-mask').show();
|
|
const res = await $POST("/v1/orderStatic", { data: JSON.stringify(orderList) });
|
|
submitFlag = false;
|
|
$('.loading-mask').hide();
|
|
|
|
if(res.code!=0)return messageFn(res.msg);
|
|
window.open(res.data.url);
|
|
}
|
|
|
|
// update info
|
|
const updateUI = () => {
|
|
result = getSelectedItems();
|
|
renderShowPrice(result);
|
|
updateTotalPrice();
|
|
};
|
|
|
|
// 获取选中的项目
|
|
const getSelectedItems = () => {
|
|
return $priceTables.map((_, table) => {
|
|
const day = $(table).data('day');
|
|
const unit = $(table).data('unit');
|
|
const items = $(table).find('div.active').map((_, p) => {
|
|
const code = $(p).data('code');
|
|
const price = $(p).data('price');
|
|
const imgUrl = $(p).data('url');
|
|
const unit = $(p).data('unit');
|
|
const existingItem = findExistingItem(day, code);
|
|
const count = existingItem ? existingItem.count : 1;
|
|
return { code, price, count,imgUrl,unit };
|
|
}).get();
|
|
return items.length ? { day, unit, items } : null;
|
|
}).get().filter(Boolean);
|
|
};
|
|
|
|
// 查找之前存储的项目
|
|
const findExistingItem = (day, code) => {
|
|
return result.find(item => item.day === day)?.items.find(subItem => subItem.code === code);
|
|
};
|
|
|
|
// 渲染选中的项目到页面
|
|
const renderShowPrice = (result) => {
|
|
let PRICE_HTML = "";
|
|
if(result.length >0){
|
|
result.forEach((i) => {
|
|
PRICE_HTML += `
|
|
<div>
|
|
<div class="show_price_header">
|
|
<p>${i.day}${i.unit}</p>
|
|
<p class="clearDay" data-day="${i.day}">
|
|
<i></i>
|
|
</p>
|
|
</div>
|
|
<div class="countrys_cont">`;
|
|
i.items.forEach((item) => {
|
|
PRICE_HTML += `
|
|
<div class="detaile_country" data-price="${item.price}" data-code="${item.code}" data-day="${i.day}" data-count="${item.count}">
|
|
<img src="${item.imgUrl}" alt="" />
|
|
<p class="code">${item.code}</p>
|
|
<p class="unit">$${item.price}/IP</p>
|
|
<div>
|
|
<p class="reduce">-</p>
|
|
<input type="text" value="${item.count}" class="inputCount" oninput="validateInput(this)">
|
|
<p class="add">+</p>
|
|
</div>
|
|
</div>`;
|
|
});
|
|
|
|
PRICE_HTML += `
|
|
</div>
|
|
</div>`;
|
|
});
|
|
}else{
|
|
PRICE_HTML+=`
|
|
<div class="no-message">
|
|
<img src="/static/common/price/img/noData.png" alt="">
|
|
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
|
|
$(".show_price").html(PRICE_HTML);
|
|
};
|
|
|
|
// input
|
|
window.validateInput = function(input) {
|
|
const $input = $(input);
|
|
let v = $input.val();
|
|
if (v.startsWith('-')) {
|
|
v = v.replace(/-/g, '');
|
|
$input.val(v);
|
|
}
|
|
v = v === '' ? 0 : parseInt(v);
|
|
$input.val(v > 9999 ? 9999 : v);
|
|
|
|
const quantity = parseInt($input.val());
|
|
const $parentDiv = $input.parents('.detaile_country');
|
|
const { day, code } = $parentDiv.data();
|
|
const dayEntry = result.find(entry => entry.day === day);
|
|
|
|
if (dayEntry) {
|
|
const itemEntry = dayEntry.items.find(item => item.code === code);
|
|
if (itemEntry) {
|
|
itemEntry.count = quantity;
|
|
}
|
|
}
|
|
|
|
updateTotalPrice();
|
|
};
|
|
|
|
|
|
// updata total price
|
|
const updateTotalPrice = () => {
|
|
const total = $showPriceDiv.find('div[data-price]').get().reduce((sum, div) => {
|
|
const quantity = parseInt($(div).find('input').val());
|
|
const unitPrice = parseFloat($(div).data('price'));
|
|
return sum + quantity * unitPrice;
|
|
}, 0);
|
|
$totalPriceSpan.text(`${total.toFixed(2)}`);
|
|
};
|
|
|
|
// add reduce event listener to inputCount
|
|
$showPriceDiv.on('click', '.reduce, .add', function () {
|
|
const $input = $(this).siblings('input');
|
|
let quantity = parseInt($input.val());
|
|
const $parentDiv = $(this).parents('.detaile_country');
|
|
const isAdd = $(this).hasClass('add');
|
|
|
|
if (isAdd) {
|
|
quantity++;
|
|
} else if (quantity > 1) {
|
|
quantity--;
|
|
} else {
|
|
const { day, code } = $parentDiv.data();
|
|
$(`.country_lists[data-day="${day}"]>div[data-code="${code}"]`).removeClass('active');
|
|
return updateUI();
|
|
}
|
|
|
|
$input.val(quantity);
|
|
$parentDiv.data('count', quantity);
|
|
|
|
// 更新 result 数组里的 count 字段
|
|
const { day, code } = $parentDiv.data();
|
|
const dayEntry = result.find(entry => entry.day === day);
|
|
if (dayEntry) {
|
|
const itemEntry = dayEntry.items.find(item => item.code === code);
|
|
if (itemEntry) {
|
|
itemEntry.count = quantity;
|
|
}
|
|
}
|
|
|
|
updateTotalPrice();
|
|
});
|
|
|
|
// clear day country
|
|
$showPriceDiv.on('click', '.clearDay', function () {
|
|
const day = $(this).data('day');
|
|
$(`.country_lists[data-day="${day}"] .country_lists_detail`).removeClass('active');
|
|
result = result.filter(item => item.day!== day);
|
|
updateUI();
|
|
});
|
|
|
|
updateUI();
|
|
|
|
|
|
couponCuttime();
|
|
$('.c_close').on('click', function(){
|
|
$('.coupon-model').hide();
|
|
})
|
|
});
|
|
|
|
const couponCuttime = async () => {
|
|
|
|
const res = await $POST("/v1/coupons");
|
|
if(res.code!=0)return;
|
|
const coupons = res.data.coupons;
|
|
let HTML = ''
|
|
if(coupons.length > 0){
|
|
coupons.forEach(coupon => {
|
|
HTML += `
|
|
<div>
|
|
<p>
|
|
<span>${coupon.value}</span>
|
|
<span>${coupon.value_tip}</span>
|
|
</p>
|
|
<div>
|
|
<p>${coupon.title}</p>
|
|
<p>${expiredTxt}: <span>${coupon.expired}</span></p>
|
|
</div>
|
|
</div>
|
|
`;
|
|
});
|
|
|
|
$('.counpin-list').html(HTML)
|
|
|
|
|
|
$('.coupon-pop').show();
|
|
const countdown = createCountdown(res.data.surplus_time, '.coupon_countdown');
|
|
countdown.start();
|
|
|
|
$('.coupon-pop').on('click', function(e){
|
|
console.log(444);
|
|
|
|
$(".coupon-model").show();
|
|
})
|
|
|
|
}
|
|
};
|
|
|
|
function createCountdown(totalSeconds, targetSelector) {
|
|
const $target = $(targetSelector);
|
|
let timer;
|
|
|
|
const formatTime = (time) => String(time).padStart(2, '0');
|
|
const update = () => {
|
|
const h = formatTime(Math.floor(totalSeconds / 3600));
|
|
const m = formatTime(Math.floor((totalSeconds % 3600) / 60));
|
|
const s = formatTime(totalSeconds % 60);
|
|
$target.text(`${h}:${m}:${s}`);
|
|
};
|
|
|
|
const start = () => {
|
|
update();
|
|
timer = setInterval(() => {
|
|
totalSeconds > 0 ? (totalSeconds--, update()) : (clearInterval(timer), $target.hide());
|
|
}, 1000);
|
|
};
|
|
|
|
const stop = () => clearInterval(timer);
|
|
|
|
return { start, stop };
|
|
}
|
|
|