349 lines
13 KiB
HTML
349 lines
13 KiB
HTML
<!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>
|