后台完成修复,初始化项目
This commit is contained in:
549
src/main/webapp/WEB-INF/views/admin/orders.jsp
Normal file
549
src/main/webapp/WEB-INF/views/admin/orders.jsp
Normal file
@@ -0,0 +1,549 @@
|
||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
<%@ taglib prefix="fn" uri="http://flashsale.org/functions" %>
|
||||
|
||||
<c:set var="pageTitle" value="订单管理"/>
|
||||
<%@ include file="../common/header.jsp" %>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<!-- 侧边栏 -->
|
||||
<nav class="col-md-3 col-lg-2 d-md-block bg-light sidebar">
|
||||
<div class="position-sticky pt-3">
|
||||
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
|
||||
<span>管理功能</span>
|
||||
</h6>
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="${pageContext.request.contextPath}/admin">
|
||||
<i class="fas fa-tachometer-alt"></i> 仪表盘
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="${pageContext.request.contextPath}/admin/products">
|
||||
<i class="fas fa-box"></i> 商品管理
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="${pageContext.request.contextPath}/admin/flashsales">
|
||||
<i class="fas fa-bolt"></i> 秒杀管理
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="${pageContext.request.contextPath}/admin/orders">
|
||||
<i class="fas fa-shopping-cart"></i> 订单管理
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="${pageContext.request.contextPath}/admin/users">
|
||||
<i class="fas fa-users"></i> 用户管理
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="${pageContext.request.contextPath}/admin/monitor">
|
||||
<i class="fas fa-chart-line"></i> 系统监控
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- 主内容区域 -->
|
||||
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
|
||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||
<h1 class="h2">订单管理</h1>
|
||||
<div class="btn-toolbar mb-2 mb-md-0">
|
||||
<div class="btn-group me-2">
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="refreshOrders()">
|
||||
<i class="fas fa-sync-alt"></i> 刷新
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-success" onclick="exportOrders()">
|
||||
<i class="fas fa-download"></i> 导出
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 筛选和搜索 -->
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-3">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" id="searchInput" placeholder="搜索订单号/用户...">
|
||||
<button class="btn btn-outline-secondary" type="button" onclick="searchOrders()">
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<select class="form-select" id="statusFilter" onchange="filterOrders()">
|
||||
<option value="">全部状态</option>
|
||||
<option value="pending">待支付</option>
|
||||
<option value="paid">已支付</option>
|
||||
<option value="shipped">已发货</option>
|
||||
<option value="completed">已完成</option>
|
||||
<option value="cancelled">已取消</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<input type="date" class="form-control" id="dateFilter" onchange="filterOrders()">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<select class="form-select" id="sortBy" onchange="sortOrders()">
|
||||
<option value="created_at">按创建时间</option>
|
||||
<option value="total_amount">按订单金额</option>
|
||||
<option value="status">按订单状态</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 订单统计 -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-primary" id="totalOrders">0</h5>
|
||||
<p class="card-text">总订单数</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-success" id="paidOrders">0</h5>
|
||||
<p class="card-text">已支付订单</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-warning" id="pendingOrders">0</h5>
|
||||
<p class="card-text">待处理订单</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-info" id="totalAmount">¥0</h5>
|
||||
<p class="card-text">总交易额</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 订单列表 -->
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>订单号</th>
|
||||
<th>用户</th>
|
||||
<th>商品信息</th>
|
||||
<th>数量</th>
|
||||
<th>总金额</th>
|
||||
<th>状态</th>
|
||||
<th>创建时间</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="ordersTableBody">
|
||||
<tr>
|
||||
<td colspan="8" class="text-center">
|
||||
<i class="fas fa-spinner fa-spin"></i> 加载中...
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- 分页 -->
|
||||
<nav aria-label="订单分页">
|
||||
<ul class="pagination justify-content-center" id="pagination">
|
||||
<!-- 分页按钮将通过JavaScript生成 -->
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 订单详情模态框 -->
|
||||
<div class="modal fade" id="orderDetailModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">订单详情</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body" id="orderDetailContent">
|
||||
<!-- 订单详情内容 -->
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.sidebar {
|
||||
position: fixed;
|
||||
top: 56px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 100;
|
||||
padding: 48px 0 0;
|
||||
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1);
|
||||
}
|
||||
|
||||
.sidebar .nav-link {
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.sidebar .nav-link.active {
|
||||
color: #007bff;
|
||||
}
|
||||
|
||||
main {
|
||||
margin-left: 240px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
main {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
position: relative;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
let currentPage = 1;
|
||||
let pageSize = 10;
|
||||
let totalPages = 1;
|
||||
|
||||
$(document).ready(function () {
|
||||
loadOrders();
|
||||
loadOrderStats();
|
||||
});
|
||||
|
||||
function loadOrders(page = 1) {
|
||||
currentPage = page;
|
||||
|
||||
// 显示加载状态
|
||||
$('#orderTableBody').html('<tr><td colspan="8" class="text-center"><i class="fas fa-spinner fa-spin"></i> 加载中...</td></tr>');
|
||||
|
||||
// 构建请求参数
|
||||
let params = {
|
||||
page: page,
|
||||
size: 10
|
||||
};
|
||||
|
||||
const keyword = $('#searchKeyword').val();
|
||||
const status = $('#statusFilter').val();
|
||||
|
||||
if (keyword && keyword.trim()) {
|
||||
params.keyword = keyword.trim();
|
||||
}
|
||||
|
||||
if (status && status !== '') {
|
||||
params.status = status;
|
||||
}
|
||||
|
||||
// 调用真实API
|
||||
$.get('${pageContext.request.contextPath}/api/admin/orders', params)
|
||||
.done(function (response) {
|
||||
if (response.success) {
|
||||
renderOrdersTable(response.data.orders);
|
||||
renderPagination(response.data.currentPage, response.data.totalPages);
|
||||
} else {
|
||||
$('#orderTableBody').html('<tr><td colspan="8" class="text-center text-danger">获取订单数据失败: ' + response.message + '</td></tr>');
|
||||
}
|
||||
})
|
||||
.fail(function () {
|
||||
$('#orderTableBody').html('<tr><td colspan="8" class="text-center text-danger">网络请求失败,请稍后重试</td></tr>');
|
||||
});
|
||||
}
|
||||
|
||||
function loadOrderStats() {
|
||||
// 调用真实API获取订单统计数据
|
||||
$.get('${pageContext.request.contextPath}/api/admin/orders/stats')
|
||||
.done(function (response) {
|
||||
if (response.success) {
|
||||
updateOrderStats(response.data);
|
||||
} else {
|
||||
console.error('获取订单统计数据失败:', response.message);
|
||||
// 显示默认值
|
||||
updateOrderStats({});
|
||||
}
|
||||
})
|
||||
.fail(function () {
|
||||
console.error('获取订单统计数据请求失败');
|
||||
// 显示默认值
|
||||
updateOrderStats({});
|
||||
});
|
||||
}
|
||||
|
||||
// 更新订单统计数据
|
||||
function updateOrderStats(stats) {
|
||||
$('#totalOrders').text(formatNumber(stats.totalOrders || 0));
|
||||
$('#paidOrders').text(formatNumber(stats.paidOrders || 0));
|
||||
$('#pendingOrders').text(formatNumber(stats.pendingOrders || 0));
|
||||
$('#totalAmount').text('¥' + formatNumber(stats.totalAmount || 0));
|
||||
}
|
||||
|
||||
function renderOrdersTable(orders) {
|
||||
let html = '';
|
||||
|
||||
if (orders.length === 0) {
|
||||
html = '<tr><td colspan="8" class="text-center">暂无订单数据</td></tr>';
|
||||
} else {
|
||||
orders.forEach(order => {
|
||||
const statusText = getOrderStatusText(order.status);
|
||||
const statusClass = getOrderStatusClass(order.status);
|
||||
|
||||
html += `
|
||||
<tr>
|
||||
<td>
|
||||
<div class="fw-bold">` + order.id + `</div>
|
||||
` + (order.isFlashSale ? '<small class="text-danger"><i class="fas fa-bolt"></i> 秒杀订单</small>' : '') + `
|
||||
</td>
|
||||
<td>` + order.username + `</td>
|
||||
<td>` + order.productName + `</td>
|
||||
<td>` + order.quantity + `</td>
|
||||
<td class="fw-bold">¥` + formatNumber(order.totalAmount || 0) + `</td>
|
||||
<td>
|
||||
<span class="badge ` + statusClass + `">
|
||||
` + statusText + `
|
||||
</span>
|
||||
</td>
|
||||
<td>` + formatDateTime(order.createdAt) + `</td>
|
||||
<td>
|
||||
<div class="btn-group btn-group-sm">
|
||||
<button class="btn btn-outline-primary" onclick="viewOrderDetail('` + order.id + `')" title="查看详情">
|
||||
<i class="fas fa-eye"></i>
|
||||
</button>
|
||||
` + (order.status === 2 ?
|
||||
'<button class="btn btn-outline-success" onclick="shipOrder(\'' + order.id + '\')" title="发货"><i class="fas fa-shipping-fast"></i></button>' : '') + `
|
||||
` + (order.status === 1 ?
|
||||
'<button class="btn btn-outline-danger" onclick="cancelOrder(\'' + order.id + '\')" title="取消"><i class="fas fa-times"></i></button>' : '') + `
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
});
|
||||
}
|
||||
|
||||
$('#ordersTableBody').html(html);
|
||||
}
|
||||
|
||||
function getOrderStatusText(status) {
|
||||
switch (status) {
|
||||
case 'pending':
|
||||
return '待支付';
|
||||
case 'paid':
|
||||
return '已支付';
|
||||
case 'shipped':
|
||||
return '已发货';
|
||||
case 'completed':
|
||||
return '已完成';
|
||||
case 'cancelled':
|
||||
return '已取消';
|
||||
default:
|
||||
return '未知';
|
||||
}
|
||||
}
|
||||
|
||||
function getOrderStatusClass(status) {
|
||||
switch (status) {
|
||||
case 'pending':
|
||||
return 'bg-warning';
|
||||
case 'paid':
|
||||
return 'bg-success';
|
||||
case 'shipped':
|
||||
return 'bg-info';
|
||||
case 'completed':
|
||||
return 'bg-primary';
|
||||
case 'cancelled':
|
||||
return 'bg-secondary';
|
||||
default:
|
||||
return 'bg-light';
|
||||
}
|
||||
}
|
||||
|
||||
function renderPagination(total, pageSize) {
|
||||
totalPages = Math.ceil(total / pageSize);
|
||||
let html = '';
|
||||
|
||||
// 上一页
|
||||
html += `
|
||||
<li class="page-item ` + (currentPage === 1 ? 'disabled' : '') + `">
|
||||
<a class="page-link" href="#" onclick="loadOrders(` + (currentPage - 1) + `)">上一页</a>
|
||||
</li>
|
||||
`;
|
||||
|
||||
// 页码
|
||||
for (let i = 1; i <= totalPages; i++) {
|
||||
html += `
|
||||
<li class="page-item ` + (i === currentPage ? 'active' : '') + `">
|
||||
<a class="page-link" href="#" onclick="loadOrders(` + i + `)">` + i + `</a>
|
||||
</li>
|
||||
`;
|
||||
}
|
||||
|
||||
// 下一页
|
||||
html += `
|
||||
<li class="page-item ` + (currentPage === totalPages ? 'disabled' : '') + `">
|
||||
<a class="page-link" href="#" onclick="loadOrders(` + (currentPage + 1) + `)">下一页</a>
|
||||
</li>
|
||||
`;
|
||||
|
||||
$('#pagination').html(html);
|
||||
}
|
||||
|
||||
function refreshOrders() {
|
||||
$('#ordersTableBody').html('<tr><td colspan="8" class="text-center"><i class="fas fa-spinner fa-spin"></i> 加载中...</td></tr>');
|
||||
loadOrders(currentPage);
|
||||
loadOrderStats();
|
||||
}
|
||||
|
||||
function searchOrders() {
|
||||
const keyword = $('#searchInput').val();
|
||||
console.log('搜索订单:', keyword);
|
||||
loadOrders(1);
|
||||
}
|
||||
|
||||
function filterOrders() {
|
||||
const status = $('#statusFilter').val();
|
||||
const date = $('#dateFilter').val();
|
||||
console.log('筛选订单:', {status, date});
|
||||
loadOrders(1);
|
||||
}
|
||||
|
||||
function sortOrders() {
|
||||
const sortBy = $('#sortBy').val();
|
||||
console.log('排序方式:', sortBy);
|
||||
loadOrders(1);
|
||||
}
|
||||
|
||||
function viewOrderDetail(orderId) {
|
||||
console.log('查看订单详情:', orderId);
|
||||
|
||||
// 模拟获取订单详情
|
||||
const orderDetail = `
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h6>订单信息</h6>
|
||||
<table class="table table-sm">
|
||||
<tr><td>订单号:</td><td>` + orderId + `</td></tr>
|
||||
<tr><td>用户:</td><td>demo1</td></tr>
|
||||
<tr><td>状态:</td><td><span class="badge bg-success">已支付</span></td></tr>
|
||||
<tr><td>创建时间:</td><td>2025-06-29 10:30:15</td></tr>
|
||||
<tr><td>支付时间:</td><td>2025-06-29 10:31:20</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h6>商品信息</h6>
|
||||
<table class="table table-sm">
|
||||
<tr><td>商品名称:</td><td>iPhone 15 Pro Max</td></tr>
|
||||
<tr><td>单价:</td><td>¥8,888.00</td></tr>
|
||||
<tr><td>数量:</td><td>1</td></tr>
|
||||
<tr><td>总金额:</td><td class="fw-bold">¥8,888.00</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col-12">
|
||||
<h6>收货地址</h6>
|
||||
<p>北京市朝阳区xxx街道xxx号xxx小区xxx楼xxx室<br>
|
||||
收货人: 张三 13800138001</p>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
$('#orderDetailContent').html(orderDetail);
|
||||
$('#orderDetailModal').modal('show');
|
||||
}
|
||||
|
||||
function shipOrder(orderId) {
|
||||
if (confirm('确定要将此订单标记为已发货吗?')) {
|
||||
console.log('发货订单:', orderId);
|
||||
|
||||
setTimeout(function () {
|
||||
alert('订单已标记为已发货!');
|
||||
refreshOrders();
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
function cancelOrder(orderId) {
|
||||
if (confirm('确定要取消此订单吗?此操作不可恢复。')) {
|
||||
console.log('取消订单:', orderId);
|
||||
|
||||
setTimeout(function () {
|
||||
alert('订单已取消!');
|
||||
refreshOrders();
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
function exportOrders() {
|
||||
console.log('导出订单数据');
|
||||
alert('订单数据导出功能开发中...');
|
||||
}
|
||||
|
||||
// 工具函数
|
||||
function formatNumber(num) {
|
||||
if (num === null || num === undefined) return '0';
|
||||
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
}
|
||||
|
||||
function formatDateTime(dateTime) {
|
||||
if (!dateTime) return '';
|
||||
return new Date(dateTime).toLocaleString('zh-CN');
|
||||
}
|
||||
|
||||
function getOrderStatusClass(status) {
|
||||
switch (status) {
|
||||
case 1:
|
||||
return 'bg-warning'; // 待支付
|
||||
case 2:
|
||||
return 'bg-success'; // 已支付
|
||||
case 3:
|
||||
return 'bg-info'; // 已发货
|
||||
case 4:
|
||||
return 'bg-primary'; // 已完成
|
||||
case 5:
|
||||
return 'bg-danger'; // 已取消
|
||||
default:
|
||||
return 'bg-secondary';
|
||||
}
|
||||
}
|
||||
|
||||
function getOrderStatusText(status) {
|
||||
switch (status) {
|
||||
case 1:
|
||||
return '待支付';
|
||||
case 2:
|
||||
return '已支付';
|
||||
case 3:
|
||||
return '已发货';
|
||||
case 4:
|
||||
return '已完成';
|
||||
case 5:
|
||||
return '已取消';
|
||||
default:
|
||||
return '未知';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<%@ include file="../common/footer.jsp" %>
|
||||
Reference in New Issue
Block a user