Files
2026-01-11 18:14:42 +08:00

349 lines
13 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>支付订单</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css">
<style>
:root {
--bg-body: #f8fafc;
--primary: #0f172a;
--accent: #3b82f6;
}
body {
background: var(--bg-body);
padding-bottom: 120px;
font-family: -apple-system, sans-serif;
color: #334155;
}
/* 顶部导航 */
.nav-header {
position: fixed; top: 0; left: 0; right: 0; height: 50px;
background: #fff; display: flex; align-items: center; justify-content: space-between;
padding: 0 16px; z-index: 1000; box-shadow: 0 1px 0 rgba(0,0,0,0.05);
}
.nav-title { font-size: 16px; font-weight: 600; }
.btn-back { border: none; background: transparent; font-size: 20px; padding: 0; }
/* 通用卡片 */
.section-card {
background: #fff; margin: 16px; padding: 16px; border-radius: 16px;
box-shadow: 0 1px 2px rgba(0,0,0,0.02);
}
.card-header {
font-size: 14px; font-weight: 700; margin-bottom: 12px; display: flex; align-items: center;
}
.card-header i { margin-right: 6px; color: #64748b; font-size: 16px; }
/* 订单金额 */
.amount-display {
text-align: center; padding: 24px 0;
}
.amount-label {
font-size: 13px; color: #94a3b8; margin-bottom: 8px;
}
.amount-value {
font-size: 36px; font-weight: 800; color: var(--primary);
}
/* 商品简要信息 */
.product-summary {
display: flex; align-items: center; margin-bottom: 12px;
}
.product-summary:last-child { margin-bottom: 0; }
.summary-img {
width: 50px; height: 50px; border-radius: 8px; object-fit: cover;
background: #f1f5f9; margin-right: 12px; flex-shrink: 0;
}
.summary-info { flex: 1; }
.summary-name {
font-size: 14px; font-weight: 600; color: var(--primary);
margin-bottom: 2px;
}
.summary-detail {
font-size: 12px; color: #94a3b8;
}
.summary-price {
font-size: 14px; font-weight: 600; color: var(--primary);
}
/* 支付方式 */
.pay-option {
display: flex; align-items: center; padding: 16px; border-radius: 12px;
border: 2px solid #f1f5f9; margin-bottom: 12px; cursor: pointer;
transition: all 0.2s; background: #fff;
}
.pay-option:last-child { margin-bottom: 0; }
.pay-option:hover {
border-color: var(--accent);
background: #f8fafc;
}
.pay-option.selected {
border-color: var(--primary);
background: #f8fafc;
}
.pay-icon {
font-size: 32px; margin-right: 16px; width: 40px; text-align: center;
}
.pay-wechat { color: #07c160; }
.pay-alipay { color: #1677ff; }
.pay-info { flex: 1; }
.pay-name {
font-size: 15px; font-weight: 600; color: var(--primary);
margin-bottom: 2px;
}
.pay-desc {
font-size: 12px; color: #94a3b8;
}
.pay-radio {
width: 20px; height: 20px; accent-color: var(--primary);
}
/* 底部操作栏 */
.bottom-bar {
position: fixed; bottom: 0; left: 0; right: 0;
background: #fff; padding: 12px 20px 30px;
box-shadow: 0 -4px 16px rgba(0,0,0,0.05);
display: flex; justify-content: space-between; align-items: center; z-index: 100;
}
.total-area { display: flex; flex-direction: column; align-items: flex-end; }
.total-label { font-size: 12px; color: #64748b; }
.total-val { font-size: 24px; font-weight: 800; color: var(--primary); }
.btn-pay {
background: var(--primary); color: #fff; border: none;
padding: 14px 40px; border-radius: 12px; font-weight: 600; font-size: 16px;
}
.btn-pay:active { transform: scale(0.98); opacity: 0.9; }
.btn-pay:disabled { background: #cbd5e1; }
</style>
</head>
<body>
<!-- 顶部导航 -->
<div class="nav-header">
<button class="btn-back" onclick="history.back()"><i class="bi bi-arrow-left"></i></button>
<span class="nav-title">支付订单</span>
<div style="width: 24px;"></div>
</div>
<div style="height: 50px;"></div>
<!-- 订单金额 -->
<div class="section-card">
<div class="amount-display">
<div class="amount-label">需支付</div>
<div class="amount-value" id="totalAmount">¥0.00</div>
</div>
</div>
<!-- 商品简要信息 -->
<div class="section-card">
<div class="card-header"><i class="bi bi-bag-fill"></i> 订单商品</div>
<div id="productList"></div>
</div>
<!-- 支付方式 -->
<div class="section-card">
<div class="card-header"><i class="bi bi-credit-card-fill"></i> 选择支付方式</div>
<label class="pay-option" id="payWechat">
<i class="bi bi-wechat pay-icon pay-wechat"></i>
<div class="pay-info">
<div class="pay-name">微信支付</div>
<div class="pay-desc">推荐使用微信支付</div>
</div>
<input type="radio" name="payMethod" value="wechat" class="pay-radio" checked>
</label>
<label class="pay-option" id="payAlipay">
<i class="bi bi-alipay pay-icon pay-alipay"></i>
<div class="pay-info">
<div class="pay-name">支付宝</div>
<div class="pay-desc">安全便捷的支付方式</div>
</div>
<input type="radio" name="payMethod" value="alipay" class="pay-radio">
</label>
</div>
<!-- 底部操作栏 -->
<div class="bottom-bar">
<div class="total-area">
<span class="total-label">合计</span>
<span class="total-val" id="bottomTotal">¥0.00</span>
</div>
<button class="btn-pay" onclick="submitPayment()">立即支付</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="/static/js/ui-enhancements.js"></script>
<script src="/static/js/custom-modal.js"></script>
<script>
let orderId = null;
let orderData = null;
// 初始化
(async () => {
// 从URL获取订单ID
const params = new URLSearchParams(location.search);
orderId = params.get('orderId');
if (!orderId) {
alert('订单ID不存在');
history.back();
return;
}
try {
await loadOrderDetail();
} catch(e) {
console.error('初始化失败:', e);
alert('页面加载失败,请刷新重试');
}
})();
// 加载订单详情
async function loadOrderDetail() {
try {
const res = await fetch(`/order/orders/${orderId}`, { credentials: 'include' });
if (!res.ok) {
throw new Error(`HTTP错误: ${res.status}`);
}
const data = await res.json();
console.log('订单详情响应:', data);
if (data.code === 200 && data.data) {
orderData = data.data;
console.log('订单数据:', orderData);
renderOrder();
} else {
const errorMsg = data.message || '加载订单失败';
console.error('加载订单失败:', errorMsg, data);
alert(errorMsg);
history.back();
}
} catch(e) {
console.error('加载订单详情失败:', e);
alert('加载失败: ' + (e.message || '网络错误'));
history.back();
}
}
function renderOrder() {
if (!orderData || !orderData.order) {
alert('订单数据异常');
history.back();
return;
}
const order = orderData.order;
const items = orderData.items || [];
const productImages = orderData.productImages || {};
// 显示金额
const totalAmount = order.totalAmount || 0;
document.getElementById('totalAmount').textContent = '¥' + totalAmount.toFixed(2);
document.getElementById('bottomTotal').textContent = '¥' + totalAmount.toFixed(2);
// 显示商品列表最多显示3个超过显示"等X件商品"
if (items.length === 0) {
document.getElementById('productList').innerHTML = '<div class="text-center text-muted small py-2">暂无商品信息</div>';
} else {
const displayItems = items.slice(0, 3);
const moreCount = items.length - 3;
let html = '';
displayItems.forEach(item => {
if (!item) return;
const productId = item.productId || item.id;
const image = (productImages && productImages[productId]) || '/static/images/default.jpg';
const productName = item.productName || '商品';
const specName = item.specName || '';
const quantity = item.quantity || 1;
const price = item.price || 0;
html += `
<div class="product-summary">
<img src="${image}" class="summary-img" alt="${productName}">
<div class="summary-info">
<div class="summary-name">${productName}</div>
<div class="summary-detail">${specName ? specName + ' ' : ''}x${quantity}</div>
</div>
<div class="summary-price">¥${parseFloat(price).toFixed(2)}</div>
</div>
`;
});
if (moreCount > 0) {
html += `<div class="text-center text-muted small mt-2">等${items.length}件商品</div>`;
}
document.getElementById('productList').innerHTML = html;
}
// 绑定支付方式选择
document.querySelectorAll('input[name="payMethod"]').forEach(radio => {
radio.addEventListener('change', function() {
document.querySelectorAll('.pay-option').forEach(opt => {
opt.classList.remove('selected');
});
if (this.value === 'wechat') {
document.getElementById('payWechat').classList.add('selected');
} else {
document.getElementById('payAlipay').classList.add('selected');
}
});
});
// 默认选中微信支付
document.getElementById('payWechat').classList.add('selected');
}
// 提交支付
async function submitPayment() {
const payMethod = document.querySelector('input[name="payMethod"]:checked').value;
const btn = document.querySelector('.btn-pay');
// 确认支付
const confirmed = await new Promise((resolve) => {
if (typeof confirmAction !== 'undefined') {
confirmAction('确认支付?', '确认支付', '确认', '取消').then(resolve);
} else {
resolve(confirm('确认支付?'));
}
});
if (!confirmed) return;
btn.disabled = true;
btn.textContent = '支付中...';
try {
const res = await fetch(`/order/${orderId}/pay`, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ paymentMethod: payMethod }),
credentials: 'include'
});
const d = await res.json();
if (d.code === 200) {
// 跳转到支付成功页面
const order = orderData && orderData.order ? orderData.order : {};
const orderNo = order.orderNo || '';
const amount = order.totalAmount || 0;
window.location.href = `/payment-success.html?orderId=${orderId}&orderNo=${orderNo}&amount=${amount}`;
} else {
alert(d.message || '支付失败');
btn.disabled = false;
btn.textContent = '立即支付';
}
} catch(e) {
console.error(e);
alert('支付失败,请重试');
btn.disabled = false;
btn.textContent = '立即支付';
}
}
</script>
</body>
</html>