1369 lines
48 KiB
JavaScript
1369 lines
48 KiB
JavaScript
// User Center JavaScript
|
||
|
||
$(document).ready(function() {
|
||
initUserCenter();
|
||
});
|
||
|
||
function initUserCenter() {
|
||
// 清除旧版本的本地订单数据(确保使用新的状态码和价格格式)
|
||
const user = JSON.parse(localStorage.getItem('currentUser'));
|
||
if (user && user.email) {
|
||
const oldOrders = localStorage.getItem('orders_' + user.email);
|
||
if (oldOrders) {
|
||
try {
|
||
const orders = JSON.parse(oldOrders);
|
||
// 检查第一个订单的price,如果小于1000则认为是旧版本(元单位)
|
||
if (orders.length > 0 && orders[0].items && orders[0].items[0]) {
|
||
const firstPrice = orders[0].items[0].price;
|
||
if (firstPrice < 1000) {
|
||
console.log('[用户中心] 检测到旧版本订单数据,清除以使用新格式');
|
||
localStorage.removeItem('orders_' + user.email);
|
||
}
|
||
}
|
||
} catch (e) {
|
||
console.error('[用户中心] 检查订单数据版本失败:', e);
|
||
}
|
||
}
|
||
}
|
||
|
||
checkLoginStatus();
|
||
loadUserInfo();
|
||
loadOrderHistory();
|
||
bindUserCenterEvents();
|
||
|
||
// i18n初始化后重新更新显示
|
||
setTimeout(() => {
|
||
const user = JSON.parse(localStorage.getItem('currentUser'));
|
||
if (user) {
|
||
updateAccountDetails(user);
|
||
}
|
||
}, 100);
|
||
}
|
||
|
||
// 检查登录状态
|
||
function checkLoginStatus() {
|
||
const user = localStorage.getItem('currentUser');
|
||
if (!user) {
|
||
// 未登录,跳转到登录页
|
||
window.location.href = 'login.html';
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
// 加载用户信息
|
||
function loadUserInfo() {
|
||
const user = JSON.parse(localStorage.getItem('currentUser'));
|
||
if (user) {
|
||
// 侧边栏显示
|
||
const displayName = user.nickname || user.email?.split('@')[0] || '用户';
|
||
$('#userName').text(displayName);
|
||
$('#userEmail').text(user.email || '');
|
||
|
||
// 账户详情显示
|
||
updateAccountDetails(user);
|
||
}
|
||
}
|
||
|
||
// 更新账户详情
|
||
function updateAccountDetails(user) {
|
||
// 用户名
|
||
if (user.nickname) {
|
||
$('#nicknameValue').text(user.nickname).removeClass('not-set');
|
||
$('#editNickname').attr('data-i18n', 'edit_btn').text(i18n.t('edit_btn') || '编辑');
|
||
} else {
|
||
$('#nicknameValue').addClass('not-set').attr('data-i18n', 'not_set').text(i18n.t('not_set') || '未设置');
|
||
$('#editNickname').attr('data-i18n', 'set_btn').text(i18n.t('set_btn') || '设置');
|
||
}
|
||
|
||
// 邮箱
|
||
if (user.email) {
|
||
$('#emailValue').text(user.email).removeClass('not-set');
|
||
$('#editEmail').attr('data-i18n', 'edit_btn').text(i18n.t('edit_btn') || '编辑');
|
||
} else {
|
||
$('#emailValue').addClass('not-set').attr('data-i18n', 'not_set').text(i18n.t('not_set') || '未设置');
|
||
$('#editEmail').attr('data-i18n', 'set_btn').text(i18n.t('set_btn') || '设置');
|
||
}
|
||
|
||
// 手机号
|
||
if (user.phone) {
|
||
$('#phoneValue').text(user.phone).removeClass('not-set');
|
||
$('#editPhone').attr('data-i18n', 'edit_btn').text(i18n.t('edit_btn') || '编辑');
|
||
} else {
|
||
$('#phoneValue').addClass('not-set').attr('data-i18n', 'not_set').text(i18n.t('not_set') || '未设置');
|
||
$('#editPhone').attr('data-i18n', 'set_btn').text(i18n.t('set_btn') || '设置');
|
||
}
|
||
}
|
||
|
||
// 绑定事件
|
||
function bindUserCenterEvents() {
|
||
console.log('Binding user center events...');
|
||
|
||
// 退出登录
|
||
$('#logoutLink').on('click', function(e) {
|
||
e.preventDefault();
|
||
console.log('Logout clicked');
|
||
handleLogout();
|
||
});
|
||
|
||
// 设置用户名
|
||
$('#editNickname').on('click', function(e) {
|
||
e.preventDefault();
|
||
console.log('Edit nickname clicked');
|
||
showEditDialog('nickname');
|
||
});
|
||
|
||
// 设置邮箱
|
||
$('#editEmail').on('click', function(e) {
|
||
e.preventDefault();
|
||
console.log('Edit email clicked');
|
||
showEditDialog('email');
|
||
});
|
||
|
||
// 设置手机号
|
||
$('#editPhone').on('click', function(e) {
|
||
e.preventDefault();
|
||
console.log('Edit phone clicked');
|
||
showEditDialog('phone');
|
||
});
|
||
|
||
console.log('Event binding complete. Buttons found:', {
|
||
nickname: $('#editNickname').length,
|
||
email: $('#editEmail').length,
|
||
phone: $('#editPhone').length
|
||
});
|
||
}
|
||
|
||
// 加载订单历史
|
||
function loadOrderHistory() {
|
||
const user = JSON.parse(localStorage.getItem('currentUser'));
|
||
if (!user) return;
|
||
|
||
const $container = $('#orderHistorySection');
|
||
const $emptyMessage = $container.find('.empty-message');
|
||
|
||
// 显示加载状态
|
||
$emptyMessage.html('<p>加载中...</p>');
|
||
|
||
// 调用API获取订单列表
|
||
OrderAPI.getList({
|
||
page: 1,
|
||
page_size: 10
|
||
})
|
||
.then(function(data) {
|
||
console.log('订单数据:', data);
|
||
|
||
// 检查是否有订单
|
||
if (data && data.list && data.list.length > 0) {
|
||
// 移除空状态消息
|
||
$emptyMessage.remove();
|
||
// 渲染订单列表
|
||
renderOrders(data.list);
|
||
} else {
|
||
// 显示空状态
|
||
$emptyMessage.html(`<p data-i18n="no_orders_placed">${i18n.t('no_orders_placed') || '您还没有下过任何订单。'}</p>`);
|
||
}
|
||
})
|
||
.catch(function(error) {
|
||
console.error('获取订单失败:', error);
|
||
|
||
// 如果API调用失败,使用本地模拟数据作为降级方案
|
||
const orders = getLocalOrders(user.email);
|
||
if (orders && orders.length > 0) {
|
||
$emptyMessage.remove();
|
||
renderOrders(orders);
|
||
} else {
|
||
$emptyMessage.html(`<p data-i18n="no_orders_placed">${i18n.t('no_orders_placed') || '您还没有下过任何订单。'}</p>`);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 获取本地模拟订单数据(降级方案)
|
||
function getLocalOrders(email) {
|
||
let orders = JSON.parse(localStorage.getItem('orders_' + email) || 'null');
|
||
|
||
if (!orders) {
|
||
// 创建模拟订单数据(使用与后端一致的状态码和字段名)
|
||
orders = [
|
||
{
|
||
id: 'ORD-2024-001',
|
||
order_no: 'ORD-2024-001',
|
||
created_at: '2024-11-15',
|
||
status: 6, // 已完成
|
||
total_amount: 29999, // 分为单位:299.99元
|
||
items: [
|
||
{
|
||
product_name: '手工陶艺套装',
|
||
quantity: 1,
|
||
price: 29999, // 分为单位
|
||
product_image: 'https://picsum.photos/200/200?random=1'
|
||
}
|
||
]
|
||
},
|
||
{
|
||
id: 'ORD-2024-002',
|
||
order_no: 'ORD-2024-002',
|
||
created_at: '2024-11-10',
|
||
status: 4, // 已发货
|
||
total_amount: 45998, // 分为单位:459.98元
|
||
items: [
|
||
{
|
||
product_name: '1000片拼图 - 星空',
|
||
quantity: 2,
|
||
price: 22999, // 分为单位
|
||
product_image: 'https://picsum.photos/200/200?random=2'
|
||
}
|
||
]
|
||
},
|
||
{
|
||
id: 'ORD-2024-003',
|
||
order_no: 'ORD-2024-003',
|
||
created_at: '2024-11-05',
|
||
status: 1, // 未付款
|
||
total_amount: 18999, // 分为单位:189.99元
|
||
items: [
|
||
{
|
||
product_name: '水彩画套装',
|
||
quantity: 1,
|
||
price: 18999, // 分为单位
|
||
product_image: 'https://picsum.photos/200/200?random=3'
|
||
}
|
||
]
|
||
}
|
||
];
|
||
|
||
localStorage.setItem('orders_' + email, JSON.stringify(orders));
|
||
}
|
||
|
||
return orders;
|
||
}
|
||
|
||
// 渲染订单
|
||
function renderOrders(orders) {
|
||
const $container = $('#orderHistorySection');
|
||
|
||
if (!orders || orders.length === 0) {
|
||
return;
|
||
}
|
||
|
||
// 移除空状态消息
|
||
$container.find('.empty-message').remove();
|
||
|
||
// 清空现有的订单列表,避免重复显示
|
||
$container.find('.orders-list').remove();
|
||
|
||
// 创建订单列表
|
||
const ordersHtml = orders.map(order => {
|
||
// 处理订单状态(兼容API返回的数字状态和本地模拟的字符串状态)
|
||
let statusCode = order.status;
|
||
let statusStr = '';
|
||
|
||
// 如果是字符串状态,转换为数字
|
||
if (typeof statusCode === 'string') {
|
||
const statusMap = {
|
||
'pending': 1,
|
||
'processing': 1,
|
||
'paid': 2,
|
||
'shipped': 3,
|
||
'delivered': 4,
|
||
'completed': 4,
|
||
'cancelled': 5
|
||
};
|
||
statusCode = statusMap[statusCode] || 1;
|
||
}
|
||
|
||
// 根据数字状态码获取显示文本和CSS类
|
||
const statusInfo = getOrderStatusInfo(statusCode);
|
||
|
||
// 处理订单字段(兼容不同命名)
|
||
const orderNo = order.order_no || order.id;
|
||
const orderDate = order.created_at || order.date || '';
|
||
|
||
// 价格转换:后端返回的是分,需要转换为元
|
||
const orderTotal = PriceUtils.fenToYuan(order.total_amount || order.total || 0);
|
||
const orderItems = order.items || [];
|
||
|
||
const itemsHtml = orderItems.map(item => {
|
||
const itemName = item.product_name || item.name || '未知商品';
|
||
// 修复:后端返回的字段是 product_image
|
||
const itemImage = item.product_image || item.image_url || item.image || 'https://picsum.photos/200/200?random=default';
|
||
|
||
// 价格转换:分 → 元
|
||
const itemPrice = PriceUtils.fenToYuan(item.price || 0);
|
||
const itemQuantity = item.quantity || 1;
|
||
|
||
return `
|
||
<div class="order-item">
|
||
<img src="${itemImage}" alt="${itemName}" class="order-item-image">
|
||
<div class="order-item-info">
|
||
<div class="order-item-name">${itemName}</div>
|
||
<div class="order-item-quantity">数量: ${itemQuantity}</div>
|
||
</div>
|
||
<div class="order-item-price">¥${itemPrice.toFixed(2)}</div>
|
||
</div>
|
||
`;
|
||
}).join('');
|
||
|
||
// 生成操作按钮(参考小程序逻辑)
|
||
const buttons = order.buttonVOs || order.button_vos || getOrderListButtons(statusCode);
|
||
const buttonsHtml = buttons.map(btn => {
|
||
const btnClass = (btn.is_primary || btn.isPrimary) ? 'btn-primary' : 'btn-secondary';
|
||
const btnType = btn.type;
|
||
const btnText = btn.text || btn.name || '操作';
|
||
return `<button class="btn ${btnClass} btn-sm order-list-action" data-type="${btnType}" data-order-no="${orderNo}">${btnText}</button>`;
|
||
}).join('');
|
||
|
||
return `
|
||
<div class="order-card" data-order-no="${orderNo}">
|
||
<div class="order-header">
|
||
<div class="order-id">
|
||
<span class="order-label" data-i18n="order_number">订单号:</span>
|
||
<span>${orderNo}</span>
|
||
</div>
|
||
<div class="order-date">${orderDate}</div>
|
||
<div class="order-status ${statusInfo.className}">${statusInfo.text}</div>
|
||
</div>
|
||
<div class="order-items">
|
||
${itemsHtml}
|
||
</div>
|
||
<div class="order-footer">
|
||
<div class="order-total">
|
||
<span data-i18n="order_total">总计:</span>
|
||
<span class="order-total-amount">¥${orderTotal.toFixed(2)}</span>
|
||
</div>
|
||
<div class="order-actions">
|
||
${buttonsHtml}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
`;
|
||
}).join('');
|
||
|
||
$container.append(`<div class="orders-list">${ordersHtml}</div>`);
|
||
|
||
// 绑定操作按钮事件
|
||
$('.order-list-action').on('click', function(e) {
|
||
e.preventDefault();
|
||
e.stopPropagation(); // 阻止事件冒泡
|
||
const btnType = parseInt($(this).data('type'));
|
||
const orderNo = $(this).data('order-no');
|
||
console.log('订单列表操作按钮点击:', btnType, orderNo);
|
||
handleOrderListAction(btnType, orderNo);
|
||
});
|
||
|
||
// 绑定订单卡片点击事件,打开详情弹窗
|
||
$('.order-card').on('click', function(e) {
|
||
// 如果点击的是按钮,不触发卡片点击
|
||
if ($(e.target).hasClass('order-list-action') || $(e.target).closest('.order-list-action').length > 0) {
|
||
return;
|
||
}
|
||
const orderNo = $(this).data('order-no');
|
||
console.log('订单卡片点击,打开详情:', orderNo);
|
||
showOrderDetail(orderNo);
|
||
});
|
||
}
|
||
|
||
// 获取订单列表按钮(参考小程序逻辑)
|
||
function getOrderListButtons(status) {
|
||
switch (status) {
|
||
case 1: // 未付款
|
||
return [
|
||
{ type: 1, name: '取消订单', is_primary: false },
|
||
{ type: 2, name: '立即付款', is_primary: true }
|
||
];
|
||
case 2: // 待发货
|
||
case 3:
|
||
return [
|
||
{ type: 7, name: '申请退款', is_primary: false },
|
||
{ type: 3, name: '提醒发货', is_primary: true }
|
||
];
|
||
case 4: // 已发货
|
||
case 5: // 待收货
|
||
return [
|
||
{ type: 4, name: '确认收货', is_primary: true }
|
||
];
|
||
case 6: // 已完成
|
||
return [
|
||
{ type: 6, name: '评价', is_primary: true }
|
||
];
|
||
case 8: // 退货中
|
||
case 9: // 已退款
|
||
return [];
|
||
default:
|
||
return [];
|
||
}
|
||
}
|
||
|
||
// 处理订单列表操作按钮点击
|
||
function handleOrderListAction(btnType, orderId) {
|
||
console.log('处理订单列表操作:', btnType, orderId);
|
||
|
||
switch (btnType) {
|
||
case 1: // 取消订单
|
||
handleCancelOrderFromList(orderId);
|
||
break;
|
||
case 2: // 立即付款
|
||
handlePayOrderFromList(orderId);
|
||
break;
|
||
case 3: // 提醒发货
|
||
handleRemindShipFromList(orderId);
|
||
break;
|
||
case 4: // 确认收货
|
||
handleConfirmReceiveFromList(orderId);
|
||
break;
|
||
case 6: // 评价
|
||
Toast.info('评价功能开发中');
|
||
break;
|
||
case 7: // 申请退款
|
||
handleApplyRefundFromList(orderId);
|
||
break;
|
||
default:
|
||
console.log('未知按钮类型:', btnType);
|
||
}
|
||
}
|
||
|
||
// 获取订单状态信息
|
||
function getOrderStatusInfo(statusCode) {
|
||
const lang = i18n.currentLang;
|
||
|
||
// 状态映射:与小程序和后端保持一致
|
||
// 1=未付款, 2=待发货, 3=待发货, 4=已发货, 5=待收货, 6=已完成, 7=已取消, 8=退货中, 9=已退款
|
||
const statusMap = {
|
||
'zh-CN': {
|
||
1: { text: '未付款', className: 'status-processing' },
|
||
2: { text: '待发货', className: 'status-processing' },
|
||
3: { text: '待发货', className: 'status-processing' },
|
||
4: { text: '已发货', className: 'status-shipped' },
|
||
5: { text: '待收货', className: 'status-shipped' },
|
||
6: { text: '已完成', className: 'status-delivered' },
|
||
7: { text: '已取消', className: 'status-cancelled' },
|
||
8: { text: '退货中', className: 'status-cancelled' },
|
||
9: { text: '已退款', className: 'status-cancelled' }
|
||
},
|
||
'en-US': {
|
||
1: { text: 'Unpaid', className: 'status-processing' },
|
||
2: { text: 'To be shipped', className: 'status-processing' },
|
||
3: { text: 'To be shipped', className: 'status-processing' },
|
||
4: { text: 'Shipped', className: 'status-shipped' },
|
||
5: { text: 'To be received', className: 'status-shipped' },
|
||
6: { text: 'Completed', className: 'status-delivered' },
|
||
7: { text: 'Cancelled', className: 'status-cancelled' },
|
||
8: { text: 'Returning', className: 'status-cancelled' },
|
||
9: { text: 'Refunded', className: 'status-cancelled' }
|
||
},
|
||
'ja-JP': {
|
||
1: { text: '未払い', className: 'status-processing' },
|
||
2: { text: '発送待ち', className: 'status-processing' },
|
||
3: { text: '発送待ち', className: 'status-processing' },
|
||
4: { text: '発送済み', className: 'status-shipped' },
|
||
5: { text: '受け取り待ち', className: 'status-shipped' },
|
||
6: { text: '完了', className: 'status-delivered' },
|
||
7: { text: 'キャンセル済み', className: 'status-cancelled' },
|
||
8: { text: '返品中', className: 'status-cancelled' },
|
||
9: { text: '返金済み', className: 'status-cancelled' }
|
||
}
|
||
};
|
||
|
||
return statusMap[lang]?.[statusCode] || { text: '未知状态', className: 'status-processing' };
|
||
}
|
||
|
||
// 显示订单详情
|
||
function showOrderDetail(orderId) {
|
||
console.log('获取订单详情:', orderId);
|
||
|
||
// 调用API获取订单详情
|
||
OrderAPI.getDetail(orderId)
|
||
.then(function(data) {
|
||
console.log('订单详情数据:', data);
|
||
renderOrderDetailModal(data);
|
||
})
|
||
.catch(function(error) {
|
||
console.error('获取订单详情失败:', error);
|
||
Toast.error(error.message || '获取订单详情失败');
|
||
});
|
||
}
|
||
|
||
// 渲染订单详情弹窗
|
||
function renderOrderDetailModal(order) {
|
||
// 创建遗罩层
|
||
const overlay = document.createElement('div');
|
||
overlay.className = 'order-detail-overlay';
|
||
|
||
// 处理订单状态(优先使用orderStatus)
|
||
const statusInfo = getOrderStatusInfo(order.orderStatus || order.order_status || order.status);
|
||
|
||
// 处理价格(后端返回的是分为单位)
|
||
const totalAmount = PriceUtils.fenToYuan(order.totalAmount || order.total_amount || 0);
|
||
const payAmount = PriceUtils.fenToYuan(order.payAmount || order.pay_amount || order.paymentAmount || order.payment_amount || 0);
|
||
|
||
// 构建订单项HTML(优先使用orderItemVOs)
|
||
const orderItems = order.orderItemVOs || order.order_item_vos || order.items || [];
|
||
const itemsHtml = orderItems.map(item => {
|
||
const itemName = item.goodsName || item.goods_name || item.product_name || '未知商品';
|
||
const itemImage = item.goodsPictureUrl || item.goods_picture_url || item.product_image || 'https://picsum.photos/200/200?random=default';
|
||
const itemPrice = PriceUtils.fenToYuan(item.actualPrice || item.actual_price || item.price || 0);
|
||
const itemQuantity = item.buyQuantity || item.buy_quantity || item.quantity || 1;
|
||
|
||
// 处理规格信息
|
||
let specsHtml = '';
|
||
if (item.specifications && item.specifications.length > 0) {
|
||
specsHtml = item.specifications.map(spec =>
|
||
`<div class="item-spec">${spec.specTitle || spec.spec_title}: ${spec.specValue || spec.spec_value}</div>`
|
||
).join('');
|
||
}
|
||
|
||
return `
|
||
<div class="detail-order-item">
|
||
<img src="${itemImage}" alt="${itemName}" class="detail-item-image">
|
||
<div class="detail-item-info">
|
||
<div class="detail-item-name">${itemName}</div>
|
||
${specsHtml}
|
||
<div class="detail-item-quantity">数量: ${itemQuantity}</div>
|
||
</div>
|
||
<div class="detail-item-price">¥${itemPrice.toFixed(2)}</div>
|
||
</div>
|
||
`;
|
||
}).join('');
|
||
|
||
// 构建收货地址HTML(优先使用logisticsVO)
|
||
const logistics = order.logisticsVO || order.logistics_vo || {};
|
||
const addressHtml = logistics.receiverAddress || logistics.receiver_address ? `
|
||
<div class="detail-section">
|
||
<h3>收货信息</h3>
|
||
<div class="detail-address">
|
||
<div class="address-info">
|
||
<div><strong>${logistics.receiverName || logistics.receiver_name || ''}</strong> ${logistics.receiverPhone || logistics.receiver_phone || ''}</div>
|
||
<div>${logistics.receiverAddress || logistics.receiver_address || ''}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
` : '';
|
||
|
||
// 构建操作按钮HTML(使用后端返回的buttonVOs)
|
||
const buttons = order.buttonVOs || order.button_vos || [];
|
||
const buttonsHtml = buttons.length > 0 ? `
|
||
<div class="detail-section">
|
||
<div class="detail-actions">
|
||
${buttons.map(btn => {
|
||
const btnClass = (btn.is_primary || btn.isPrimary) ? 'btn-primary' : 'btn-secondary';
|
||
const btnType = btn.type;
|
||
const btnText = btn.text || btn.name || '操作';
|
||
return `<button class="btn ${btnClass} btn-action" data-type="${btnType}" data-order-id="${order.orderNo || order.order_no}">${btnText}</button>`;
|
||
}).join('')}
|
||
</div>
|
||
</div>
|
||
` : '';
|
||
|
||
// 构建订单详情HTML
|
||
const detailHtml = `
|
||
<div class="order-detail-modal">
|
||
<div class="order-detail-header">
|
||
<h2 data-i18n="order_detail_title">订单详情</h2>
|
||
<button class="close-detail-btn" aria-label="Close">×</button>
|
||
</div>
|
||
|
||
<div class="order-detail-content">
|
||
<div class="detail-section">
|
||
<div class="detail-status">
|
||
<span class="status-badge ${statusInfo.className}">${statusInfo.text}</span>
|
||
</div>
|
||
<div class="detail-info-grid">
|
||
<div class="info-item">
|
||
<span class="info-label" data-i18n="order_number">订单号:</span>
|
||
<span class="info-value">${order.orderNo || order.order_no || ''}</span>
|
||
</div>
|
||
<div class="info-item">
|
||
<span class="info-label" data-i18n="order_time">下单时间:</span>
|
||
<span class="info-value">${order.createdAt || order.created_at || ''}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="detail-section">
|
||
<h3 data-i18n="order_items">商品信息</h3>
|
||
<div class="detail-items-list">
|
||
${itemsHtml}
|
||
</div>
|
||
</div>
|
||
|
||
${addressHtml}
|
||
|
||
<div class="detail-section">
|
||
<h3 data-i18n="order_summary">订单金额</h3>
|
||
<div class="detail-summary">
|
||
<div class="summary-row">
|
||
<span data-i18n="goods_amount">商品总额:</span>
|
||
<span>¥${totalAmount.toFixed(2)}</span>
|
||
</div>
|
||
<div class="summary-row summary-total">
|
||
<span data-i18n="order_total">实付金额:</span>
|
||
<span class="total-amount">¥${payAmount.toFixed(2)}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
${buttonsHtml}
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
overlay.innerHTML = detailHtml;
|
||
document.body.appendChild(overlay);
|
||
|
||
// 显示动画
|
||
setTimeout(() => {
|
||
overlay.classList.add('active');
|
||
}, 10);
|
||
|
||
// 绑定关闭事件
|
||
const closeBtn = overlay.querySelector('.close-detail-btn');
|
||
closeBtn.addEventListener('click', () => {
|
||
closeOrderDetail(overlay);
|
||
});
|
||
|
||
// 绑定操作按钮事件
|
||
const actionBtns = overlay.querySelectorAll('.btn-action');
|
||
actionBtns.forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
const btnType = parseInt(btn.getAttribute('data-type'));
|
||
const orderId = btn.getAttribute('data-order-id');
|
||
handleOrderAction(btnType, orderId, overlay);
|
||
});
|
||
});
|
||
|
||
// 点击遗罩层关闭
|
||
overlay.addEventListener('click', (e) => {
|
||
if (e.target === overlay) {
|
||
closeOrderDetail(overlay);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 关闭订单详情弹窗
|
||
function closeOrderDetail(overlay) {
|
||
overlay.classList.remove('active');
|
||
setTimeout(() => {
|
||
overlay.remove();
|
||
}, 300);
|
||
}
|
||
|
||
// 处理订单操作按钮
|
||
function handleOrderAction(actionType, orderId, overlay) {
|
||
console.log('订单操作:', { actionType, orderId });
|
||
|
||
// 按钮类型定义(与小程序保持一致)
|
||
// 1: 取消订单
|
||
// 2: 立即付款
|
||
// 3: 提醒发货
|
||
// 4: 确认收货
|
||
// 5: 申请售后
|
||
// 6: 评价
|
||
// 7: 申请退款
|
||
|
||
switch (actionType) {
|
||
case 1: // 取消订单
|
||
handleCancelOrder(orderId, overlay);
|
||
break;
|
||
case 2: // 立即付款
|
||
handlePayOrder(orderId, overlay);
|
||
break;
|
||
case 3: // 提醒发货
|
||
handleRemindShip(orderId, overlay);
|
||
break;
|
||
case 4: // 确认收货
|
||
handleConfirmReceive(orderId, overlay);
|
||
break;
|
||
case 5: // 申请售后
|
||
handleApplyAfterSale(orderId, overlay);
|
||
break;
|
||
case 6: // 评价
|
||
handleComment(orderId, overlay);
|
||
break;
|
||
case 7: // 申请退款
|
||
handleApplyRefund(orderId, overlay);
|
||
break;
|
||
default:
|
||
Toast.warning('未知操作类型');
|
||
}
|
||
}
|
||
|
||
// 取消订单
|
||
function handleCancelOrder(orderId, overlay) {
|
||
Toast.confirm({
|
||
title: '取消订单',
|
||
message: '确定要取消该订单吗?取消后无法恢复。',
|
||
confirmText: '确认取消',
|
||
cancelText: '我再想想'
|
||
}).then(confirmed => {
|
||
if (confirmed) {
|
||
// 调用取消订单API
|
||
API.put('/orders/' + orderId + '/cancel', {
|
||
order_no: orderId
|
||
})
|
||
.then(() => {
|
||
Toast.success('订单已取消');
|
||
|
||
// 关闭当前详情弹窗
|
||
closeOrderDetail(overlay);
|
||
|
||
// 刷新订单列表
|
||
setTimeout(() => {
|
||
// 清空现有订单列表
|
||
$('#orderHistorySection .orders-list').remove();
|
||
// 重新加载订单
|
||
loadOrderHistory();
|
||
}, 500);
|
||
})
|
||
.catch(error => {
|
||
Toast.error(error.message || '取消失败');
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
// 立即付款
|
||
function handlePayOrder(orderId, overlay) {
|
||
// 调用创建支付订单API
|
||
API.post('/payments/orders/' + orderId)
|
||
.then(data => {
|
||
console.log('支付数据:', data);
|
||
// Web端支付逻辑:显示支付二维码或跳转支付页面
|
||
if (data.payInfo) {
|
||
// 有支付参数,显示支付二维码(Web端需要生成二维码扫码支付)
|
||
Toast.info('请扫码完成支付');
|
||
// 这里可以显示支付二维码弹窗
|
||
} else {
|
||
// 沙盒环境或模拟支付成功
|
||
Toast.success('支付成功');
|
||
closeOrderDetail(overlay);
|
||
setTimeout(() => {
|
||
loadOrderHistory();
|
||
}, 1000);
|
||
}
|
||
})
|
||
.catch(error => {
|
||
Toast.error(error.message || '创建支付订单失败');
|
||
});
|
||
}
|
||
|
||
// 提醒发货
|
||
function handleRemindShip(orderId, overlay) {
|
||
Toast.confirm({
|
||
title: '提醒发货',
|
||
message: '确定要提醒商家尽快发货吗?提醒后商家会收到通知。',
|
||
confirmText: '确定提醒',
|
||
cancelText: '取消'
|
||
}).then(confirmed => {
|
||
if (confirmed) {
|
||
// 调用提醒发货API
|
||
API.put('/orders/' + orderId + '/remind-ship')
|
||
.then(() => {
|
||
Toast.success('提醒发货成功,商家已收到通知');
|
||
})
|
||
.catch(error => {
|
||
let errorMessage = '提醒失败';
|
||
if (error.message) {
|
||
if (error.message.includes('订单不存在')) {
|
||
errorMessage = '订单信息异常,请刷新页面重试';
|
||
} else if (error.message.includes('状态')) {
|
||
errorMessage = '订单状态不支持提醒发货';
|
||
} else {
|
||
errorMessage = error.message;
|
||
}
|
||
}
|
||
Toast.error(errorMessage);
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
// 确认收货
|
||
function handleConfirmReceive(orderId, overlay) {
|
||
Toast.confirm({
|
||
title: '确认收货',
|
||
message: '确定已收到商品吗?确认后将无法撤销。',
|
||
confirmText: '确认收货',
|
||
cancelText: '取消'
|
||
}).then(confirmed => {
|
||
if (confirmed) {
|
||
// 调用确认收货API
|
||
API.post('/orders/' + orderId + '/confirm', {
|
||
order_no: orderId
|
||
})
|
||
.then(() => {
|
||
Toast.success('确认收货成功');
|
||
|
||
// 关闭当前详情弹窗
|
||
closeOrderDetail(overlay);
|
||
|
||
// 刷新订单列表
|
||
setTimeout(() => {
|
||
// 清空现有订单列表
|
||
$('#orderHistorySection .orders-list').remove();
|
||
// 重新加载订单
|
||
loadOrderHistory();
|
||
}, 500);
|
||
})
|
||
.catch(error => {
|
||
Toast.error(error.message || '确认收货失败');
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
// 申请售后
|
||
function handleApplyAfterSale(orderId, overlay) {
|
||
// 跳转到售后申请页面
|
||
Toast.info('跳转到售后申请页面...');
|
||
// window.location.href = 'after-sale.html?order_id=' + orderId;
|
||
}
|
||
|
||
// 评价
|
||
function handleComment(orderId, overlay) {
|
||
// 跳转到评价页面
|
||
Toast.info('跳转到评价页面...');
|
||
// window.location.href = 'comment.html?order_id=' + orderId;
|
||
}
|
||
|
||
// 申请退款
|
||
function handleApplyRefund(orderId, overlay) {
|
||
Toast.confirm({
|
||
title: '申请退款',
|
||
message: '确定要申请退款吗?',
|
||
confirmText: '确定',
|
||
cancelText: '取消'
|
||
}).then(confirmed => {
|
||
if (confirmed) {
|
||
// 先获取订单详情,获取order_id和退款金额
|
||
OrderAPI.getDetail(orderId)
|
||
.then(orderData => {
|
||
// 调用申请退款API
|
||
API.post('/refunds', {
|
||
order_id: parseInt(orderData.orderId || orderData.order_id),
|
||
refund_amount: (orderData.payAmount || orderData.pay_amount || orderData.paymentAmount || orderData.payment_amount) / 100, // 分转元
|
||
refund_reason: '用户主动申请退款',
|
||
refund_type: 1 // 1=仅退款
|
||
})
|
||
.then(() => {
|
||
Toast.success('退款申请已提交');
|
||
|
||
// 关闭当前详情弹窗
|
||
closeOrderDetail(overlay);
|
||
|
||
// 刷新订单列表
|
||
setTimeout(() => {
|
||
// 清空现有订单列表
|
||
$('#orderHistorySection .orders-list').remove();
|
||
// 重新加载订单
|
||
loadOrderHistory();
|
||
}, 500);
|
||
})
|
||
.catch(error => {
|
||
Toast.error(error.message || '申请退款失败');
|
||
});
|
||
})
|
||
.catch(error => {
|
||
Toast.error(error.message || '获取订单信息失败');
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
// ========== 订单列表操作函数 ==========
|
||
|
||
// 从列表取消订单
|
||
function handleCancelOrderFromList(orderId) {
|
||
Toast.confirm({
|
||
title: '取消订单',
|
||
message: '确定要取消该订单吗?取消后无法恢复。',
|
||
confirmText: '确认取消',
|
||
cancelText: '我再想想'
|
||
}).then(confirmed => {
|
||
if (confirmed) {
|
||
API.put('/orders/' + orderId + '/cancel', {
|
||
order_no: orderId
|
||
})
|
||
.then(() => {
|
||
Toast.success('订单已取消');
|
||
refreshOrderList();
|
||
})
|
||
.catch(error => {
|
||
Toast.error(error.message || '取消失败');
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
// 从列表立即付款
|
||
function handlePayOrderFromList(orderId) {
|
||
API.post('/payments/orders/' + orderId)
|
||
.then(data => {
|
||
if (data.payInfo) {
|
||
Toast.info('请扫码完成支付');
|
||
} else {
|
||
Toast.success('支付成功');
|
||
setTimeout(() => {
|
||
refreshOrderList();
|
||
}, 1000);
|
||
}
|
||
})
|
||
.catch(error => {
|
||
Toast.error(error.message || '创建支付订单失败');
|
||
});
|
||
}
|
||
|
||
// 从列表提醒发货
|
||
function handleRemindShipFromList(orderId) {
|
||
Toast.confirm({
|
||
title: '提醒发货',
|
||
message: '确定要提醒商家尽快发货吗?提醒后商家会收到通知。',
|
||
confirmText: '确定提醒',
|
||
cancelText: '取消'
|
||
}).then(confirmed => {
|
||
if (confirmed) {
|
||
API.put('/orders/' + orderId + '/remind-ship')
|
||
.then(() => {
|
||
Toast.success('提醒发货成功,商家已收到通知');
|
||
})
|
||
.catch(error => {
|
||
let errorMessage = '提醒失败';
|
||
if (error.message) {
|
||
if (error.message.includes('订单不存在')) {
|
||
errorMessage = '订单信息异常,请刷新页面重试';
|
||
} else if (error.message.includes('状态')) {
|
||
errorMessage = '订单状态不支持提醒发货';
|
||
} else {
|
||
errorMessage = error.message;
|
||
}
|
||
}
|
||
Toast.error(errorMessage);
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
// 从列表确认收货
|
||
function handleConfirmReceiveFromList(orderId) {
|
||
Toast.confirm({
|
||
title: '确认收货',
|
||
message: '确定已收到商品吗?确认后将无法撤销。',
|
||
confirmText: '确认收货',
|
||
cancelText: '取消'
|
||
}).then(confirmed => {
|
||
if (confirmed) {
|
||
API.post('/orders/' + orderId + '/confirm', {
|
||
order_no: orderId
|
||
})
|
||
.then(() => {
|
||
Toast.success('确认收货成功');
|
||
refreshOrderList();
|
||
})
|
||
.catch(error => {
|
||
Toast.error(error.message || '确认收货失败');
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
// 从列表申请退款
|
||
function handleApplyRefundFromList(orderId) {
|
||
Toast.confirm({
|
||
title: '申请退款',
|
||
message: '确定要申请退款吗?',
|
||
confirmText: '确定',
|
||
cancelText: '取消'
|
||
}).then(confirmed => {
|
||
if (confirmed) {
|
||
OrderAPI.getDetail(orderId)
|
||
.then(orderData => {
|
||
API.post('/refunds', {
|
||
order_id: parseInt(orderData.orderId || orderData.order_id),
|
||
refund_amount: (orderData.payAmount || orderData.pay_amount || orderData.paymentAmount || orderData.payment_amount) / 100,
|
||
refund_reason: '用户主动申请退款',
|
||
refund_type: 1
|
||
})
|
||
.then(() => {
|
||
Toast.success('退款申请已提交');
|
||
refreshOrderList();
|
||
})
|
||
.catch(error => {
|
||
Toast.error(error.message || '申请退款失败');
|
||
});
|
||
})
|
||
.catch(error => {
|
||
Toast.error(error.message || '获取订单信息失败');
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
// 刷新订单列表
|
||
function refreshOrderList() {
|
||
setTimeout(() => {
|
||
$('#orderHistorySection .orders-list').remove();
|
||
loadOrderHistory();
|
||
}, 500);
|
||
}
|
||
|
||
// 显示编辑对话框
|
||
function showEditDialog(field) {
|
||
console.log('showEditDialog called with field:', field);
|
||
const user = JSON.parse(localStorage.getItem('currentUser'));
|
||
console.log('Current user:', user);
|
||
|
||
const fieldMap = {
|
||
'nickname': {
|
||
title: i18n.t('edit_nickname_title') || '设置用户名',
|
||
placeholder: i18n.t('nickname_placeholder') || '请输入用户名',
|
||
currentValue: user.nickname || '',
|
||
maxLength: 20,
|
||
validate: (value) => {
|
||
if (!value || value.trim() === '') {
|
||
return i18n.t('nickname_required') || '请输入用户名';
|
||
}
|
||
if (value.length < 2 || value.length > 20) {
|
||
return i18n.t('nickname_length_error') || '用户名长度2-20个字符';
|
||
}
|
||
return null;
|
||
}
|
||
},
|
||
'email': {
|
||
title: i18n.t('edit_email_title') || '设置邮箱',
|
||
placeholder: i18n.t('email_placeholder') || '请输入邮箱',
|
||
currentValue: user.email || '',
|
||
inputType: 'email',
|
||
validate: (value) => {
|
||
if (!value || value.trim() === '') {
|
||
return i18n.t('email_required') || '请输入邮箱';
|
||
}
|
||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||
if (!emailRegex.test(value)) {
|
||
return i18n.t('invalid_email') || '请输入有效的邮箱地址';
|
||
}
|
||
return null;
|
||
}
|
||
},
|
||
'phone': {
|
||
title: i18n.t('edit_phone_title') || '设置手机号',
|
||
placeholder: i18n.t('phone_placeholder') || '请输入手机号',
|
||
currentValue: user.phone || '',
|
||
inputType: 'tel',
|
||
maxLength: 11,
|
||
validate: (value) => {
|
||
if (!value || value.trim() === '') {
|
||
return i18n.t('phone_required') || '请输入手机号';
|
||
}
|
||
const phoneRegex = /^1[3-9]\d{9}$/;
|
||
if (!phoneRegex.test(value)) {
|
||
return i18n.t('invalid_phone') || '请输入有效的手机号';
|
||
}
|
||
return null;
|
||
}
|
||
}
|
||
};
|
||
|
||
const config = fieldMap[field];
|
||
if (!config) {
|
||
console.error('Invalid field:', field);
|
||
return;
|
||
}
|
||
|
||
console.log('Config:', config);
|
||
|
||
// 使用Toast.prompt替代原生prompt
|
||
Toast.prompt({
|
||
title: config.title,
|
||
placeholder: config.placeholder,
|
||
defaultValue: config.currentValue,
|
||
inputType: config.inputType || 'text',
|
||
maxLength: config.maxLength,
|
||
confirmText: i18n.t('confirm') || '确定',
|
||
cancelText: i18n.t('cancel') || '取消'
|
||
}).then(newValue => {
|
||
console.log('New value:', newValue);
|
||
|
||
if (newValue !== null && newValue !== config.currentValue) {
|
||
// 验证
|
||
const error = config.validate(newValue);
|
||
if (error) {
|
||
Toast.error(error);
|
||
return;
|
||
}
|
||
|
||
// 调用API更新后端数据
|
||
const updateData = {};
|
||
updateData[field] = newValue;
|
||
|
||
console.log('Calling API to update:', field, '=', newValue);
|
||
|
||
UserAPI.updateProfile(updateData)
|
||
.then(function(updatedUser) {
|
||
console.log('API response:', updatedUser);
|
||
|
||
// API更新成功,同步更新localStorage
|
||
user[field] = newValue;
|
||
// 如果API返回了其他字段,也一并更新
|
||
if (updatedUser) {
|
||
Object.assign(user, updatedUser);
|
||
}
|
||
localStorage.setItem('currentUser', JSON.stringify(user));
|
||
console.log('User updated:', user);
|
||
|
||
// 刷新显示
|
||
updateAccountDetails(user);
|
||
|
||
Toast.success(i18n.t('update_success') || '修改成功');
|
||
})
|
||
.catch(function(error) {
|
||
// API调用失败
|
||
console.error('更新用户信息失败:', error);
|
||
Toast.error(error.message || i18n.t('update_failed') || '更新失败,请稍后重试');
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
// 退出登录
|
||
function handleLogout() {
|
||
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');
|
||
|
||
// 更新用户图标显示
|
||
if (typeof window.updateUserIcon === 'function') {
|
||
window.updateUserIcon();
|
||
}
|
||
|
||
Toast.success(i18n.t('logout_success') || '已退出登录');
|
||
setTimeout(() => {
|
||
window.location.href = 'login.html';
|
||
}, 500);
|
||
}
|
||
});
|
||
}
|
||
|
||
// ===================== 支付相关 =====================
|
||
|
||
// 全局支付状态
|
||
const paymentState = {
|
||
paymentTimer: null,
|
||
countdownTimer: null,
|
||
currentOrderId: null,
|
||
countdownEndTime: null // 倒计时结束时间戳
|
||
};
|
||
|
||
// 处理订单列表的立即付款
|
||
function handlePayOrderFromList(orderId) {
|
||
// 获取订单详情以获取金额
|
||
OrderAPI.getDetail(orderId)
|
||
.then(data => {
|
||
const order = data.data || data;
|
||
|
||
// 尝试多种可能的字段名
|
||
const totalAmount = order.total_amount || order.totalAmount || order.total || order.amount || 0;
|
||
|
||
// 显示支付弹窗
|
||
showWechatPayment(orderId, totalAmount);
|
||
})
|
||
.catch(error => {
|
||
console.error('获取订单详情失败:', error);
|
||
Toast.error('获取订单信息失败');
|
||
});
|
||
}
|
||
|
||
// 显示微信支付弹窗
|
||
function showWechatPayment(orderId, totalAmount) {
|
||
paymentState.currentOrderId = orderId;
|
||
|
||
// 显示支付金额(后端返回的是分,需要转换为元)
|
||
const amountInYuan = (totalAmount / 100).toFixed(2);
|
||
$('#paymentAmount').text(`¥${amountInYuan}`);
|
||
|
||
// 显示弹窗
|
||
$('#paymentModal').addClass('show');
|
||
|
||
// 绑定关闭事件
|
||
$('#closePaymentModal').off('click').on('click', function() {
|
||
hidePaymentModal();
|
||
});
|
||
|
||
// 调用支付 API 获取二维码
|
||
API.put(`/orders/${orderId}/pay`, {
|
||
payment_method: 'wechat'
|
||
})
|
||
.then(data => {
|
||
// 支持多种数据格式
|
||
const paymentData = data.data || data;
|
||
const qrcodeUrl = paymentData.qrcode_url || paymentData.qrcodeUrl || paymentData.code_url || paymentData.codeUrl;
|
||
|
||
if (qrcodeUrl) {
|
||
// 显示二维码
|
||
displayQRCode(qrcodeUrl);
|
||
|
||
// 开始轮询支付状态
|
||
startPaymentPolling(orderId);
|
||
|
||
// 开始倒计时(5分钟)
|
||
startCountdown(300);
|
||
} else {
|
||
Toast.error('获取支付二维码失败');
|
||
hidePaymentModal();
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('创建支付失败:', error);
|
||
Toast.error(error.message || '创建支付失败');
|
||
hidePaymentModal();
|
||
});
|
||
}
|
||
|
||
// 显示二维码
|
||
function displayQRCode(url) {
|
||
// 清空容器
|
||
const container = document.getElementById('qrcodeContainer');
|
||
container.innerHTML = '';
|
||
|
||
// 使用 QRCode.js 生成二维码
|
||
new QRCode(container, {
|
||
text: url,
|
||
width: 256,
|
||
height: 256,
|
||
colorDark: '#000000',
|
||
colorLight: '#ffffff',
|
||
correctLevel: QRCode.CorrectLevel.H
|
||
});
|
||
}
|
||
|
||
// 开始轮询支付状态
|
||
function startPaymentPolling(orderId) {
|
||
if (paymentState.paymentTimer) {
|
||
clearInterval(paymentState.paymentTimer);
|
||
}
|
||
|
||
paymentState.paymentTimer = setInterval(() => {
|
||
checkPaymentStatus(orderId);
|
||
}, 2000);
|
||
}
|
||
|
||
// 检查支付状态
|
||
function checkPaymentStatus(orderId) {
|
||
API.get(`/orders/${orderId}/payment/status`)
|
||
.then(data => {
|
||
const status = data.data?.status || data.status;
|
||
|
||
if (status === 'paid' || status === 'success') {
|
||
handlePaymentSuccess();
|
||
} else if (status === 'failed' || status === 'cancelled') {
|
||
handlePaymentFailure();
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('查询支付状态失败:', error);
|
||
});
|
||
}
|
||
|
||
// 支付成功处理
|
||
function handlePaymentSuccess() {
|
||
clearInterval(paymentState.paymentTimer);
|
||
clearInterval(paymentState.countdownTimer);
|
||
|
||
Toast.success('支付成功!');
|
||
hidePaymentModal();
|
||
|
||
// 刷新订单列表
|
||
setTimeout(() => {
|
||
loadOrderHistory();
|
||
}, 1000);
|
||
}
|
||
|
||
// 支付失败处理
|
||
function handlePaymentFailure() {
|
||
clearInterval(paymentState.paymentTimer);
|
||
clearInterval(paymentState.countdownTimer);
|
||
|
||
Toast.error('支付失败,请重试');
|
||
hidePaymentModal();
|
||
}
|
||
|
||
// 开始倒计时(使用时间戳避免切换标签页时间不准)
|
||
function startCountdown(seconds) {
|
||
if (paymentState.countdownTimer) {
|
||
clearInterval(paymentState.countdownTimer);
|
||
}
|
||
|
||
// 记录倒计时结束的绝对时间戳
|
||
paymentState.countdownEndTime = Date.now() + (seconds * 1000);
|
||
|
||
// 更新显示
|
||
updateCountdownDisplay();
|
||
|
||
// 每秒更新一次
|
||
paymentState.countdownTimer = setInterval(() => {
|
||
updateCountdownDisplay();
|
||
}, 1000);
|
||
}
|
||
|
||
// 更新倒计时显示(基于时间戳计算)
|
||
function updateCountdownDisplay() {
|
||
if (!paymentState.countdownEndTime) {
|
||
return;
|
||
}
|
||
|
||
const now = Date.now();
|
||
const remainingMs = paymentState.countdownEndTime - now;
|
||
|
||
// 倒计时结束
|
||
if (remainingMs <= 0) {
|
||
clearInterval(paymentState.countdownTimer);
|
||
clearInterval(paymentState.paymentTimer);
|
||
paymentState.countdownTimer = null;
|
||
paymentState.countdownEndTime = null;
|
||
|
||
$('#countdownTime').text('0:00');
|
||
Toast.warning('二维码已过期,请重新生成');
|
||
hidePaymentModal();
|
||
return;
|
||
}
|
||
|
||
// 计算剩余秒数
|
||
const remainingSeconds = Math.ceil(remainingMs / 1000);
|
||
const minutes = Math.floor(remainingSeconds / 60);
|
||
const secs = remainingSeconds % 60;
|
||
|
||
$('#countdownTime').text(`${minutes}:${String(secs).padStart(2, '0')}`);
|
||
}
|
||
|
||
// 隐藏支付弹窗
|
||
function hidePaymentModal() {
|
||
if (paymentState.paymentTimer) {
|
||
clearInterval(paymentState.paymentTimer);
|
||
paymentState.paymentTimer = null;
|
||
}
|
||
|
||
if (paymentState.countdownTimer) {
|
||
clearInterval(paymentState.countdownTimer);
|
||
paymentState.countdownTimer = null;
|
||
}
|
||
|
||
// 清除倒计时时间戳
|
||
paymentState.countdownEndTime = null;
|
||
|
||
$('#paymentModal').removeClass('show');
|
||
|
||
$('#qrcodeContainer').html(`
|
||
<div class="qrcode-loading">
|
||
<div class="spinner"></div>
|
||
<p>正在生成二维码...</p>
|
||
</div>
|
||
`);
|
||
|
||
paymentState.currentOrderId = null;
|
||
}
|