// 通用工具函数和全局配置
// API配置
const API_BASE_URL = 'http://localhost:8080/api';
// 工具函数
const utils = {
// 格式化价格
// 注:如果price已经是元单位,直接传入;如果是后端返回的分单位,请使用 PriceUtils.formatPrice()
formatPrice(price, currency = '¥') {
return `${currency}${parseFloat(price).toFixed(2)}`;
},
// 格式化日期
formatDate(date) {
const d = new Date(date);
const year = d.getFullYear();
const month = String(d.getMonth() + 1).padStart(2, '0');
const day = String(d.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
},
// 防抖函数
debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
},
// 节流函数
throttle(func, limit) {
let inThrottle;
return function(...args) {
if (!inThrottle) {
func.apply(this, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
},
// 显示提示消息
showMessage(message, type = 'info') {
// 移除已存在的消息
$('.message-toast').remove();
const colors = {
success: '#51cf66',
error: '#ff6b6b',
warning: '#ffd43b',
info: '#4ecdc4'
};
const $toast = $(`
${message}
`);
$('body').append($toast);
setTimeout(() => {
$toast.fadeOut(300, function() {
$(this).remove();
});
}, 3000);
},
// 加载中状态
showLoading(container) {
const $loading = $(`
`);
$(container).html($loading);
},
// 获取URL参数
getUrlParams() {
const params = {};
const searchParams = new URLSearchParams(window.location.search);
for (const [key, value] of searchParams) {
params[key] = value;
}
return params;
},
// 设置URL参数(不刷新页面)
setUrlParam(key, value) {
const url = new URL(window.location);
if (value === null || value === undefined || value === '') {
url.searchParams.delete(key);
} else {
url.searchParams.set(key, value);
}
window.history.pushState({}, '', url);
}
};
// 购物车管理 - 使用真实API
const cart = {
// 检查用户是否登录
isLoggedIn() {
const user = localStorage.getItem('currentUser');
if (!user) return false;
try {
const userData = JSON.parse(user);
return !!userData.token;
} catch (e) {
return false;
}
},
// 加载购物车数据(从后端)
loadCart() {
// 未登录时不请求购物车,直接返回空
if (!this.isLoggedIn()) {
console.log('[Cart] 用户未登录,跳过购物车查询');
this.updateCartCount(0);
return Promise.resolve([]);
}
console.log('[Cart] 用户已登录,请求购物车数据');
return API.get('/cart')
.then(data => {
console.log('[Cart] 购物车数据:', data);
const items = data.items || [];
// 后端返回的是 count 字段,不是 total_quantity
const totalQuantity = data.count || 0;
console.log('[Cart] 商品总数:', totalQuantity);
this.updateCartCount(totalQuantity);
return items;
})
.catch(error => {
console.error('加载购物车失败:', error);
this.updateCartCount(0);
return [];
});
},
// 更新购物车数量显示
updateCartCount(count) {
console.log('[Cart] updateCartCount 被调用,count =', count);
if (count === undefined) {
// 如果没有传入count,从API获取
console.log('[Cart] count 未定义,调用 loadCart()');
this.loadCart();
} else {
console.log('[Cart] 更新购物车数量显示:', count);
$('.cart-count').text(count);
}
},
// 打开购物车抽屉
openDrawer() {
console.log('=== cart.openDrawer() 被调用 ===');
// 每次打开时先移除旧的抽屉(如果存在)
if ($('#cartDrawer').length > 0) {
console.log('移除旧的购物车抽屉');
$('#cartDrawer').remove();
}
// 创建新的抽屉
console.log('创建新的购物车抽屉');
this.createDrawer();
// 加载购物车数据
console.log('加载购物车数据');
this.loadCartData();
// 显示抽屉(需要小延迟以确保 DOM 渲染完成)
setTimeout(() => {
console.log('显示购物车抽屉');
$('#cartDrawer').addClass('active');
}, 10);
$('body').css('overflow', 'hidden');
console.log('=== openDrawer() 执行完成 ===');
},
// 关闭购物车抽屉
closeDrawer() {
$('#cartDrawer').removeClass('active');
$('body').css('overflow', '');
// 延迟移除遵罩层,等待动画完成
setTimeout(() => {
$('#cartDrawer').remove();
}, 300);
},
// 创建购物车抽屉HTML
createDrawer() {
const drawerHtml = `
`;
$('body').append(drawerHtml);
// 添加必要的CSS
if (!$('#cart-drawer-styles').length) {
$('head').append(`
cursor: pointer;
font-size: 12px;
}
.cart-footer {
padding: 20px 0;
border-top: 2px solid #e0e0e0;
}
.cart-total {
display: flex;
justify-content: space-between;
font-size: 18px;
font-weight: 600;
margin-bottom: 15px;
}
.recommendation-item {
margin-bottom: 15px;
cursor: pointer;
}
.recommendation-item img {
width: 100%;
border-radius: 4px;
margin-bottom: 8px;
}
.recommendation-item-name {
font-size: 14px;
margin-bottom: 5px;
}
.recommendation-item-price {
font-weight: 600;
color: var(--primary-color);
}
@media (max-width: 768px) {
.recommendations-column {
display: none;
}
.cart-column {
padding-left: 0;
}
}
`);
}
// 绑定事件
this.bindDrawerEvents();
},
// 绑定抽屉事件
bindDrawerEvents() {
// 关闭按钮
$(document).on('click', '.cart-drawer-close, .cart-drawer-overlay', () => {
this.closeDrawer();
});
// 删除商品
$(document).on('click', '.cart-item-remove', (e) => {
e.stopPropagation();
const productId = $(e.currentTarget).data('product-id');
const skuId = $(e.currentTarget).data('sku-id');
this.removeItem(productId, skuId);
});
// 增加数量
$(document).on('click', '.quantity-increase', (e) => {
e.stopPropagation();
const productId = $(e.currentTarget).data('product-id');
const skuId = $(e.currentTarget).data('sku-id');
const $input = $(e.currentTarget).siblings('.quantity-input');
const currentQty = parseInt($input.val()) || 1;
this.updateQuantity(productId, skuId, currentQty + 1);
});
// 减少数量
$(document).on('click', '.quantity-decrease', (e) => {
e.stopPropagation();
const productId = $(e.currentTarget).data('product-id');
const skuId = $(e.currentTarget).data('sku-id');
const $input = $(e.currentTarget).siblings('.quantity-input');
const currentQty = parseInt($input.val()) || 1;
if (currentQty > 1) {
this.updateQuantity(productId, skuId, currentQty - 1);
}
});
// 推荐商品点击
$(document).on('click', '.recommendation-item', (e) => {
const productId = $(e.currentTarget).data('product-id');
window.location.href = `product-detail.html?id=${productId}`;
});
// 购物车商品图片和名称点击跳转
$(document).on('click', '.cart-item-image, .cart-item-name', (e) => {
e.stopPropagation();
const productId = $(e.currentTarget).data('product-id');
if (productId) {
window.location.href = `product-detail.html?id=${productId}`;
}
});
},
// 加载购物车数据到抽屉
loadCartData() {
// 未登录时提示需要登录
if (!this.isLoggedIn()) {
$('#cartItemsList').html('请先登录查看购物车
');
return;
}
API.get('/cart')
.then(data => {
const items = data.items || [];
this.renderCartItems(items);
this.updateCartTotal(items);
this.loadRecommendations();
})
.catch(error => {
console.error('加载购物车数据失败:', error);
$('#cartItemsList').html('加载失败,请重试
');
});
},
// 渲染购物车商品
renderCartItems(items) {
if (items.length === 0) {
$('#cartItemsList').html('购物车是空的
');
return;
}
const itemsHtml = items.map(item => {
const product = item.product || {};
const sku = item.sku || {};
const itemName = product.name || '未知商品';
const itemImage = product.main_image || product.image || 'https://picsum.photos/80/80?random=default';
const itemPrice = PriceUtils.fenToYuan(sku.price || product.price || 0);
const productId = item.product_id || product.id;
// 规格信息
let specHtml = '';
if (sku.spec_values && Object.keys(sku.spec_values).length > 0) {
const specs = Object.entries(sku.spec_values).map(([key, value]) => `${key}: ${value}`).join(', ');
specHtml = `${specs}
`;
}
return `
`;
}).join('');
$('#cartItemsList').html(itemsHtml);
},
// 更新购物车总计
updateCartTotal(items) {
const total = items.reduce((sum, item) => {
const price = (item.sku && item.sku.price) || (item.product && item.product.price) || 0;
return sum + (price * item.quantity);
}, 0);
$('#cartTotalAmount').text(`¥${PriceUtils.fenToYuan(total).toFixed(2)}`);
},
// 删除购物车商品
removeItem(productId, skuId) {
let url = `/cart/${productId}`;
if (skuId && skuId != 0) {
url += `?sku_id=${skuId}`;
}
API.delete(url)
.then(() => {
Toast.success('已删除');
this.loadCartData();
this.updateCartCount();
})
.catch(error => {
Toast.error(error.message || '删除失败');
});
},
// 更新商品数量
updateQuantity(productId, skuId, newQuantity) {
const data = {
quantity: newQuantity
};
if (skuId && skuId != 0) {
data.sku_id = parseInt(skuId);
}
API.put(`/cart/${productId}`, data)
.then(() => {
Toast.success('已更新数量');
this.loadCartData();
this.updateCartCount();
})
.catch(error => {
Toast.error(error.message || '更新失败');
this.loadCartData(); // 失败后重新加载恢复原数量
});
},
// 加载推荐商品
loadRecommendations() {
API.get('/products', { page: 1, page_size: 4 })
.then(data => {
const products = data.list || [];
this.renderRecommendations(products.slice(0, 4));
})
.catch(error => {
console.error('加载推荐商品失败:', error);
});
},
// 渲染推荐商品
renderRecommendations(products) {
if (products.length === 0) {
$('#recommendationsList').html('暂无推荐
');
return;
}
const recommendationsHtml = products.map(product => {
const productName = product.name || '未知商品';
const productImage = product.main_image || 'https://picsum.photos/260/260?random=' + product.id;
const price = PriceUtils.fenToYuan(product.price || 0);
return `
${productName}
¥${price.toFixed(2)}
`;
}).join('');
$('#recommendationsList').html(recommendationsHtml);
}
};
// 全局函数供其他页面调用
window.openCartDrawer = function() {
cart.openDrawer();
};
// 更新用户图标和显示
function updateUserIcon() {
const user = localStorage.getItem('currentUser');
const $userIcon = $('.user-icon');
if (user) {
try {
const userData = JSON.parse(user);
if (userData.token) {
// 已登录:修改链接和显示用户名
$userIcon.attr('href', 'user-center.html');
// 获取用户名
const displayName = userData.nickname || userData.email?.split('@')[0] || '用户';
// 如果还没有用户名显示,添加一个
if (!$userIcon.find('.user-name-display').length) {
$userIcon.append(`${displayName}`);
} else {
$userIcon.find('.user-name-display').text(displayName);
}
// 添加下拉菜单(作为子元素,确保定位正确)
if (!$userIcon.find('.user-dropdown-menu').length) {
const dropdownHtml = `
`;
$userIcon.append(dropdownHtml);
}
} else {
// Token无效,清除登录状态
localStorage.removeItem('currentUser');
$userIcon.attr('href', 'login.html');
$userIcon.find('.user-name-display').remove();
$userIcon.find('.user-dropdown-menu').remove();
}
} catch (e) {
// 解析失败,清除登录状态
localStorage.removeItem('currentUser');
$userIcon.attr('href', 'login.html');
$userIcon.find('.user-name-display').remove();
$userIcon.find('.user-dropdown-menu').remove();
}
} else {
// 未登录:链接指向登录页
$userIcon.attr('href', 'login.html');
$userIcon.find('.user-name-display').remove();
$userIcon.find('.user-dropdown-menu').remove();
}
}
// 将 updateUserIcon 暴露为全局函数,供其他页面调用
window.updateUserIcon = updateUserIcon;
// 头部退出登录处理
function handleHeaderLogout() {
if (typeof Toast !== 'undefined' && Toast.confirm) {
Toast.confirm({
title: i18n?.t('logout_confirm_title') || '退出登录',
message: i18n?.t('logout_confirm_message') || '确定要退出当前账号吗?',
confirmText: i18n?.t('confirm') || '确定',
cancelText: i18n?.t('cancel') || '取消'
}).then(confirmed => {
if (confirmed) {
// 清除登录状态和重定向URL
localStorage.removeItem('currentUser');
localStorage.removeItem('redirectUrl');
// 更新用户图标显示
updateUserIcon();
Toast.success(i18n?.t('logout_success') || '已退出登录');
setTimeout(() => {
window.location.href = 'login.html';
}, 500);
}
});
} else {
// 降级处理:使用原生confirm
if (confirm('确定要退出当前账号吗?')) {
localStorage.removeItem('currentUser');
localStorage.removeItem('redirectUrl');
updateUserIcon();
window.location.href = 'login.html';
}
}
}
// 页面初始化
$(document).ready(function() {
// 更新用户图标显示
updateUserIcon();
// 更新购物车计数(已内置登录检查,未登录会自动显示0)
cart.updateCartCount();
// 用户下拉菜单交互
$(document).on('mouseenter', '.user-icon', function() {
if ($(this).find('.user-dropdown-menu').length) {
$(this).find('.user-dropdown-menu').addClass('show');
}
});
$(document).on('mouseleave', '.user-icon', function() {
setTimeout(() => {
if (!$('.user-dropdown-menu:hover').length) {
$('.user-dropdown-menu').removeClass('show');
}
}, 100);
});
$(document).on('mouseenter', '.user-dropdown-menu', function() {
$(this).addClass('show');
});
$(document).on('mouseleave', '.user-dropdown-menu', function() {
$(this).removeClass('show');
});
// 头部退出登录按钮
$(document).on('click', '#headerLogoutBtn', function(e) {
e.preventDefault();
handleHeaderLogout();
});
// 购物车按钮点击事件 - 使用事件委托阻止跳转,打开抽屉
$(document).on('click', '.cart-icon', function(e) {
console.log('=== 点击了购物车图标 ===');
e.preventDefault();
e.stopPropagation();
// 打开购物车抽屉
if (cart && cart.openDrawer) {
console.log('调用 cart.openDrawer()');
cart.openDrawer();
} else {
console.error('cart.openDrawer 不存在');
}
return false;
});
// 搜索功能
$('.search-btn').on('click', function() {
const keyword = $('.search-box input').val().trim();
if (keyword) {
window.location.href = `search.html?q=${encodeURIComponent(keyword)}`;
}
});
$('.search-box input').on('keypress', function(e) {
if (e.which === 13) { // Enter键
const keyword = $(this).val().trim();
if (keyword) {
window.location.href = `search.html?q=${encodeURIComponent(keyword)}`;
}
}
});
// 添加CSS动画
if (!$('#custom-animations').length) {
$('head').append(`
`);
}
// 将 cart 对象暴露到全局
window.cart = cart;
});