Kamixitong/app/web/templates/order/list.html
2025-12-12 11:35:14 +08:00

381 lines
14 KiB
HTML
Raw 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.

{% 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 %}