204 lines
5.3 KiB
JavaScript
204 lines
5.3 KiB
JavaScript
// 基础JavaScript功能
|
|
|
|
// 返回顶部功能
|
|
window.addEventListener('scroll', function() {
|
|
const backToTop = document.getElementById('backToTop');
|
|
if (backToTop) {
|
|
if (window.pageYOffset > 300) {
|
|
backToTop.style.display = 'block';
|
|
} else {
|
|
backToTop.style.display = 'none';
|
|
}
|
|
}
|
|
});
|
|
|
|
function scrollToTop() {
|
|
window.scrollTo({
|
|
top: 0,
|
|
behavior: 'smooth'
|
|
});
|
|
}
|
|
|
|
// 购物车数量更新
|
|
function updateCartBadge(count) {
|
|
const badge = document.getElementById('cartBadge');
|
|
if (badge) {
|
|
if (count > 0) {
|
|
badge.textContent = count;
|
|
badge.style.display = 'inline-block';
|
|
} else {
|
|
badge.style.display = 'none';
|
|
}
|
|
}
|
|
}
|
|
|
|
// 通用提示函数
|
|
function showAlert(message, type = 'info', duration = 3000) {
|
|
// 移除现有的提示框
|
|
const existingAlerts = document.querySelectorAll('.custom-alert');
|
|
existingAlerts.forEach(alert => alert.remove());
|
|
|
|
// 创建新的提示框
|
|
const alertDiv = document.createElement('div');
|
|
alertDiv.className = `alert alert-${getBootstrapAlertType(type)} alert-dismissible fade show custom-alert`;
|
|
alertDiv.style.cssText = `
|
|
position: fixed;
|
|
top: 20px;
|
|
right: 20px;
|
|
z-index: 9999;
|
|
min-width: 300px;
|
|
max-width: 500px;
|
|
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
|
`;
|
|
|
|
const icon = getAlertIcon(type);
|
|
alertDiv.innerHTML = `
|
|
<div class="d-flex align-items-center">
|
|
<i class="bi ${icon} me-2"></i>
|
|
<div class="flex-grow-1">${message}</div>
|
|
<button type="button" class="btn-close" onclick="this.parentElement.parentElement.remove()"></button>
|
|
</div>
|
|
`;
|
|
|
|
document.body.appendChild(alertDiv);
|
|
|
|
// 自动消失
|
|
if (duration > 0) {
|
|
setTimeout(() => {
|
|
if (alertDiv.parentNode) {
|
|
alertDiv.classList.remove('show');
|
|
setTimeout(() => {
|
|
if (alertDiv.parentNode) {
|
|
alertDiv.remove();
|
|
}
|
|
}, 150);
|
|
}
|
|
}, duration);
|
|
}
|
|
|
|
return alertDiv;
|
|
}
|
|
|
|
// 获取Bootstrap警告类型
|
|
function getBootstrapAlertType(type) {
|
|
const typeMap = {
|
|
'success': 'success',
|
|
'error': 'danger',
|
|
'warning': 'warning',
|
|
'info': 'info'
|
|
};
|
|
return typeMap[type] || 'info';
|
|
}
|
|
|
|
// 获取警告图标
|
|
function getAlertIcon(type) {
|
|
const iconMap = {
|
|
'success': 'bi-check-circle-fill',
|
|
'error': 'bi-exclamation-triangle-fill',
|
|
'warning': 'bi-exclamation-triangle-fill',
|
|
'info': 'bi-info-circle-fill'
|
|
};
|
|
return iconMap[type] || 'bi-info-circle-fill';
|
|
}
|
|
|
|
// 确认对话框
|
|
function showConfirm(message, callback) {
|
|
if (confirm(message)) {
|
|
if (typeof callback === 'function') {
|
|
callback();
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// 页面加载完成后的初始化
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// 当前页面高亮
|
|
const currentPath = window.location.pathname;
|
|
const navLinks = document.querySelectorAll('.navbar-nav .nav-link');
|
|
|
|
navLinks.forEach(link => {
|
|
if (link.getAttribute('href') === currentPath) {
|
|
link.classList.add('active');
|
|
}
|
|
});
|
|
|
|
// 初始化购物车数量
|
|
updateCartCount();
|
|
});
|
|
|
|
// 通用AJAX错误处理
|
|
function handleAjaxError(xhr, defaultMessage = '操作失败,请稍后再试') {
|
|
if (xhr.status === 401) {
|
|
showAlert('请先登录', 'warning');
|
|
setTimeout(() => {
|
|
window.location.href = '/auth/login';
|
|
}, 1500);
|
|
} else if (xhr.status === 403) {
|
|
showAlert('没有权限执行此操作', 'error');
|
|
} else if (xhr.status === 404) {
|
|
showAlert('请求的资源不存在', 'error');
|
|
} else if (xhr.status >= 500) {
|
|
showAlert('服务器错误,请稍后再试', 'error');
|
|
} else {
|
|
showAlert(defaultMessage, 'error');
|
|
}
|
|
}
|
|
|
|
// 通用成功提示(保持向后兼容)
|
|
function showSuccessMessage(message) {
|
|
showAlert(message, 'success');
|
|
}
|
|
|
|
// 更新购物车数量
|
|
function updateCartCount() {
|
|
fetch('/cart/count')
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
updateCartBadge(data.count);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.log('获取购物车数量失败:', error);
|
|
});
|
|
}
|
|
|
|
// 格式化价格
|
|
function formatPrice(price) {
|
|
return '¥' + parseFloat(price).toFixed(2);
|
|
}
|
|
|
|
// 格式化数字
|
|
function formatNumber(num) {
|
|
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
}
|
|
|
|
// 防抖函数
|
|
function debounce(func, wait) {
|
|
let timeout;
|
|
return function executedFunction(...args) {
|
|
const later = () => {
|
|
clearTimeout(timeout);
|
|
func(...args);
|
|
};
|
|
clearTimeout(timeout);
|
|
timeout = setTimeout(later, wait);
|
|
};
|
|
}
|
|
|
|
// 节流函数
|
|
function throttle(func, limit) {
|
|
let inThrottle;
|
|
return function() {
|
|
const args = arguments;
|
|
const context = this;
|
|
if (!inThrottle) {
|
|
func.apply(context, args);
|
|
inThrottle = true;
|
|
setTimeout(() => inThrottle = false, limit);
|
|
}
|
|
}
|
|
}
|