381 lines
14 KiB
HTML
381 lines
14 KiB
HTML
{% extends "base.html" %}
|
||
|
||
{% block title %}订单管理 - {{ config.SITE_NAME or '软件授权管理系统' }}{% endblock %}
|
||
|
||
{% block extra_css %}
|
||
<style>
|
||
.order-status-0 { color: #ffc107; } /* 待支付 */
|
||
.order-status-1 { color: #28a745; } /* 已支付 */
|
||
.order-status-2 { color: #dc3545; } /* 已取消 */
|
||
.order-status-3 { color: #6c757d; } /* 已完成 */
|
||
|
||
.order-item {
|
||
border-left: 3px solid #dee2e6;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.order-item:hover {
|
||
border-left-color: #667eea;
|
||
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
||
}
|
||
|
||
.search-filters .form-control, .search-filters .form-select {
|
||
min-width: 150px;
|
||
}
|
||
</style>
|
||
{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="container-fluid">
|
||
<!-- 页面标题 -->
|
||
<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">
|
||
<button type="button" class="btn btn-sm btn-outline-secondary me-2" onclick="refreshOrders()">
|
||
<i class="fas fa-sync-alt me-1"></i>刷新
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 搜索和筛选 -->
|
||
<div class="card shadow-sm mb-4">
|
||
<div class="card-body">
|
||
<form id="searchForm" class="row g-3 search-filters">
|
||
<div class="col-md-3">
|
||
<label for="searchKeyword" class="form-label">搜索</label>
|
||
<input type="text" class="form-control" id="searchKeyword" placeholder="订单号/联系人/手机号">
|
||
</div>
|
||
<div class="col-md-2">
|
||
<label for="statusFilter" class="form-label">状态</label>
|
||
<select class="form-select" id="statusFilter">
|
||
<option value="">全部</option>
|
||
<option value="0">待支付</option>
|
||
<option value="1">已支付</option>
|
||
<option value="2">已取消</option>
|
||
<option value="3">已完成</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-2">
|
||
<label for="productFilter" class="form-label">产品</label>
|
||
<select class="form-select" id="productFilter">
|
||
<option value="">全部产品</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="dateRange" class="form-label">日期范围</label>
|
||
<input type="text" class="form-control" id="dateRange" placeholder="选择日期范围">
|
||
</div>
|
||
<div class="col-md-2 d-flex align-items-end">
|
||
<button type="button" class="btn btn-primary w-100" onclick="loadOrders()">
|
||
<i class="fas fa-search me-1"></i>搜索
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 订单列表 -->
|
||
<div class="card shadow-sm">
|
||
<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>
|
||
<th>操作</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="ordersTableBody">
|
||
<!-- 订单数据将通过JavaScript动态加载 -->
|
||
<tr>
|
||
<td colspan="9" class="text-center">
|
||
<div class="spinner-border text-primary" role="status">
|
||
<span class="visually-hidden">加载中...</span>
|
||
</div>
|
||
<p class="mt-2">正在加载订单数据...</p>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<!-- 分页 -->
|
||
<nav aria-label="订单分页" id="paginationContainer">
|
||
<ul class="pagination justify-content-center">
|
||
<!-- 分页控件将通过JavaScript动态生成 -->
|
||
</ul>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endblock %}
|
||
|
||
{% block extra_js %}
|
||
<script>
|
||
// 页面加载完成后初始化
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
console.log('订单管理页面加载完成');
|
||
|
||
// 初始化日期选择器
|
||
initDateRangePicker();
|
||
|
||
// 初始化产品筛选下拉框
|
||
loadProducts();
|
||
|
||
// 加载订单列表
|
||
loadOrders();
|
||
});
|
||
|
||
// 初始化日期选择器
|
||
function initDateRangePicker() {
|
||
// 这里可以集成日期选择插件,如daterangepicker
|
||
// 暂时使用普通文本输入框
|
||
}
|
||
|
||
// 加载产品列表
|
||
function loadProducts() {
|
||
apiRequest('/api/v1/products')
|
||
.then(data => {
|
||
if (data.success) {
|
||
const select = document.getElementById('productFilter');
|
||
select.innerHTML = '<option value="">全部产品</option>';
|
||
|
||
data.data.products.forEach(product => {
|
||
const option = document.createElement('option');
|
||
option.value = product.product_id;
|
||
option.textContent = product.product_name;
|
||
select.appendChild(option);
|
||
});
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('加载产品列表失败:', error);
|
||
});
|
||
}
|
||
|
||
// 加载订单列表
|
||
function loadOrders(page = 1) {
|
||
const params = new URLSearchParams();
|
||
params.append('page', page);
|
||
|
||
const keyword = document.getElementById('searchKeyword').value.trim();
|
||
const status = document.getElementById('statusFilter').value;
|
||
const product = document.getElementById('productFilter').value;
|
||
const dateRange = document.getElementById('dateRange').value;
|
||
|
||
if (keyword) params.append('keyword', keyword);
|
||
if (status) params.append('status', status);
|
||
if (product) params.append('product_id', product);
|
||
if (dateRange) params.append('date_range', dateRange);
|
||
|
||
// 显示加载状态
|
||
document.getElementById('ordersTableBody').innerHTML = `
|
||
<tr>
|
||
<td colspan="9" class="text-center">
|
||
<div class="spinner-border text-primary" role="status">
|
||
<span class="visually-hidden">加载中...</span>
|
||
</div>
|
||
<p class="mt-2">正在加载订单数据...</p>
|
||
</td>
|
||
</tr>
|
||
`;
|
||
|
||
apiRequest(`/api/v1/orders?${params.toString()}`)
|
||
.then(data => {
|
||
if (data.success) {
|
||
renderOrders(data.data.orders, data.data.pagination);
|
||
} else {
|
||
showNotification('加载订单列表失败: ' + data.message, 'error');
|
||
}
|
||
})
|
||
.catch(error => {
|
||
showNotification('加载订单列表失败,请稍后重试', 'error');
|
||
console.error('加载订单列表失败:', error);
|
||
});
|
||
}
|
||
|
||
// 渲染订单列表
|
||
function renderOrders(orders, pagination) {
|
||
const tbody = document.getElementById('ordersTableBody');
|
||
|
||
if (orders.length === 0) {
|
||
tbody.innerHTML = `
|
||
<tr>
|
||
<td colspan="9" class="text-center py-5">
|
||
<i class="fas fa-file-invoice fa-3x text-muted mb-3"></i>
|
||
<h4 class="text-muted">暂无订单</h4>
|
||
<p class="text-muted">当前没有符合条件的订单记录</p>
|
||
</td>
|
||
</tr>
|
||
`;
|
||
document.getElementById('paginationContainer').innerHTML = '';
|
||
return;
|
||
}
|
||
|
||
let ordersHtml = '';
|
||
orders.forEach(order => {
|
||
ordersHtml += `
|
||
<tr>
|
||
<td>${order.order_number}</td>
|
||
<td>${order.product_name || '未知产品'}</td>
|
||
<td>${order.contact_person}</td>
|
||
<td>${order.phone}</td>
|
||
<td>${order.quantity}</td>
|
||
<td>¥${order.amount.toFixed(2)}</td>
|
||
<td>
|
||
<span class="badge bg-${getStatusClass(order.status)} order-status-${order.status}">
|
||
${order.status_name}
|
||
</span>
|
||
</td>
|
||
<td>${formatDate(order.create_time)}</td>
|
||
<td>
|
||
<div class="btn-group btn-group-sm" role="group">
|
||
<button type="button" class="btn btn-outline-primary" onclick="viewOrder('${order.order_id}')">
|
||
<i class="fas fa-eye me-1"></i>查看
|
||
</button>
|
||
${order.status === 0 ? `
|
||
<button type="button" class="btn btn-outline-success" onclick="confirmPayment('${order.order_id}')">
|
||
<i class="fas fa-check me-1"></i>确认支付
|
||
</button>
|
||
` : ''}
|
||
${order.status === 1 ? `
|
||
<button type="button" class="btn btn-outline-secondary" onclick="completeOrder('${order.order_id}')">
|
||
<i class="fas fa-check-circle me-1"></i>完成
|
||
</button>
|
||
` : ''}
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
`;
|
||
});
|
||
|
||
tbody.innerHTML = ordersHtml;
|
||
|
||
// 渲染分页
|
||
renderPagination(pagination);
|
||
}
|
||
|
||
// 获取状态样式类
|
||
function getStatusClass(status) {
|
||
const classMap = {
|
||
0: 'warning',
|
||
1: 'success',
|
||
2: 'danger',
|
||
3: 'secondary'
|
||
};
|
||
return classMap[status] || 'secondary';
|
||
}
|
||
|
||
// 渲染分页
|
||
function renderPagination(pagination) {
|
||
const paginationContainer = document.getElementById('paginationContainer');
|
||
|
||
if (pagination.total_pages <= 1) {
|
||
paginationContainer.innerHTML = '';
|
||
return;
|
||
}
|
||
|
||
let paginationHtml = '<ul class="pagination justify-content-center">';
|
||
|
||
// 上一页
|
||
if (pagination.current_page > 1) {
|
||
paginationHtml += `
|
||
<li class="page-item">
|
||
<a class="page-link" href="#" onclick="loadOrders(${pagination.current_page - 1}); return false;">
|
||
<i class="fas fa-chevron-left"></i>
|
||
</a>
|
||
</li>
|
||
`;
|
||
}
|
||
|
||
// 页码
|
||
for (let i = Math.max(1, pagination.current_page - 2);
|
||
i <= Math.min(pagination.total_pages, pagination.current_page + 2);
|
||
i++) {
|
||
paginationHtml += `
|
||
<li class="page-item ${i === pagination.current_page ? 'active' : ''}">
|
||
<a class="page-link" href="#" onclick="loadOrders(${i}); return false;">${i}</a>
|
||
</li>
|
||
`;
|
||
}
|
||
|
||
// 下一页
|
||
if (pagination.current_page < pagination.total_pages) {
|
||
paginationHtml += `
|
||
<li class="page-item">
|
||
<a class="page-link" href="#" onclick="loadOrders(${pagination.current_page + 1}); return false;">
|
||
<i class="fas fa-chevron-right"></i>
|
||
</a>
|
||
</li>
|
||
`;
|
||
}
|
||
|
||
paginationHtml += '</ul>';
|
||
paginationContainer.innerHTML = paginationHtml;
|
||
}
|
||
|
||
// 查看订单详情
|
||
function viewOrder(orderId) {
|
||
showNotification('查看订单详情功能待实现', 'info');
|
||
// 这里可以跳转到订单详情页面或显示模态框
|
||
}
|
||
|
||
// 确认支付
|
||
function confirmPayment(orderId) {
|
||
if (!confirm('确定要确认该订单已支付吗?')) {
|
||
return;
|
||
}
|
||
|
||
apiRequest(`/api/v1/orders/${orderId}/confirm-payment`, {
|
||
method: 'POST'
|
||
})
|
||
.then(data => {
|
||
if (data.success) {
|
||
showNotification('订单支付确认成功', 'success');
|
||
loadOrders(); // 重新加载订单列表
|
||
} else {
|
||
showNotification('订单支付确认失败: ' + data.message, 'error');
|
||
}
|
||
})
|
||
.catch(error => {
|
||
showNotification('订单支付确认失败,请稍后重试', 'error');
|
||
console.error('订单支付确认失败:', error);
|
||
});
|
||
}
|
||
|
||
// 完成订单
|
||
function completeOrder(orderId) {
|
||
if (!confirm('确定要将该订单标记为已完成吗?')) {
|
||
return;
|
||
}
|
||
|
||
apiRequest(`/api/v1/orders/${orderId}/complete`, {
|
||
method: 'POST'
|
||
})
|
||
.then(data => {
|
||
if (data.success) {
|
||
showNotification('订单完成操作成功', 'success');
|
||
loadOrders(); // 重新加载订单列表
|
||
} else {
|
||
showNotification('订单完成操作失败: ' + data.message, 'error');
|
||
}
|
||
})
|
||
.catch(error => {
|
||
showNotification('订单完成操作失败,请稍后重试', 'error');
|
||
console.error('订单完成操作失败:', error);
|
||
});
|
||
}
|
||
|
||
// 刷新订单列表
|
||
function refreshOrders() {
|
||
loadOrders();
|
||
}
|
||
</script>
|
||
{% endblock %} |