This commit is contained in:
wangziqi
2026-01-07 16:18:56 +08:00
parent 7c4be0b7b4
commit ea9c94dfeb
13 changed files with 2243 additions and 148 deletions

View File

@@ -4,8 +4,8 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>管理员仪表板 - 车管家4S店车辆维保管理系统</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css" rel="stylesheet">
<link href="/lib/bootstrap.min.css" rel="stylesheet">
<link href="/lib/bootstrap-icons.css" rel="stylesheet">
<link rel="stylesheet" href="../css/style.css">
</head>
<body>
@@ -56,7 +56,7 @@
</div>
<div class="d-flex align-items-center gap-3">
<div class="dropdown">
<button class="btn btn-outline-light dropdown-toggle" type="button" data-bs-toggle="dropdown">
<button class="btn btn-outline-light dropdown-toggle" style="color: black;" type="button" data-bs-toggle="dropdown">
<i class="bi bi-person-circle"></i>
<span id="userName">管理员</span>
</button>
@@ -508,10 +508,10 @@
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="/lib/bootstrap.bundle.min.js"></script>
<script src="../js/config.js"></script>
<script src="../js/api.js"></script>
<script src="../js/admin.js"></script>
<script src="../js/app.js"></script>
<script src="../js/admin.js"></script>
</body>
</html>

View File

@@ -227,8 +227,7 @@ body {
/* 模态框 */
.modal-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #fff;
color: black;
border-radius: 10px 10px 0 0;
}

View File

@@ -4,8 +4,8 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>客户中心 - 车管家4S店车辆维保管理系统</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css" rel="stylesheet">
<link href="/lib/bootstrap.min.css" rel="stylesheet">
<link href="/lib/bootstrap-icons.css" rel="stylesheet">
<link rel="stylesheet" href="../css/style.css">
</head>
<body>
@@ -231,7 +231,7 @@
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="/lib/bootstrap.bundle.min.js"></script>
<script src="../js/config.js"></script>
<script src="../js/api.js"></script>
<script src="../js/app.js"></script>

View File

@@ -6,6 +6,112 @@ let allVehiclesData = [];
let allOrdersData = [];
let allPartsData = [];
// ==================== 函数覆盖 ====================
// 立即覆盖app.js中的显示函数不等待DOMContentLoaded
// 覆盖displayAllUsers
const originalDisplayAllUsers = (typeof displayAllUsers !== 'undefined') ? displayAllUsers : function() {};
displayAllUsers = function(users) {
allUsersData = users || [];
const tbody = document.getElementById('allUsersTableBody');
if (!tbody) {
// 如果不是管理员页面,调用原始函数
return originalDisplayAllUsers(users);
}
if (users.length === 0) {
tbody.innerHTML = '<tr><td colspan="7" class="text-center text-muted py-4">暂无数据</td></tr>';
return;
}
tbody.innerHTML = users.map(u => `
<tr>
<td>${u.userId}</td>
<td>${u.username}</td>
<td>${u.realName}</td>
<td>${u.phone}</td>
<td>${Utils.getRoleText(u.role)}</td>
<td>${u.status === 1 ? '<span class="badge bg-success">启用</span>' : '<span class="badge bg-secondary">禁用</span>'}</td>
<td>
<button class="btn btn-sm btn-info" onclick="viewUser(${u.userId})">查看</button>
<button class="btn btn-sm btn-warning" onclick="editUser(${u.userId})">编辑</button>
<button class="btn btn-sm btn-danger" onclick="deleteUser(${u.userId})">删除</button>
</td>
</tr>
`).join('');
};
// 覆盖displayAllVehicles
const originalDisplayAllVehicles = (typeof displayAllVehicles !== 'undefined') ? displayAllVehicles : function() {};
displayAllVehicles = function(vehicles) {
allVehiclesData = vehicles || [];
const tbody = document.getElementById('allVehiclesTableBody');
if (!tbody) {
// 如果不是管理员页面,调用原始函数
return originalDisplayAllVehicles(vehicles);
}
if (vehicles.length === 0) {
tbody.innerHTML = '<tr><td colspan="6" class="text-center text-muted py-4">暂无数据</td></tr>';
return;
}
tbody.innerHTML = vehicles.map(v => `
<tr>
<td>${v.licensePlate}</td>
<td>${v.brand} ${v.model}</td>
<td>${v.color || '-'}</td>
<td>${v.mileage || 0}</td>
<td>${Utils.getStatusBadge(v.status)}</td>
<td>
<button class="btn btn-sm btn-info" onclick="viewVehicle(${v.vehicleId})">查看</button>
<button class="btn btn-sm btn-warning" onclick="editVehicle(${v.vehicleId})">编辑</button>
<button class="btn btn-sm btn-danger" onclick="deleteVehicle(${v.vehicleId})">删除</button>
</td>
</tr>
`).join('');
};
// 覆盖displayAllOrders
const originalDisplayAllOrders = (typeof displayAllOrders !== 'undefined') ? displayAllOrders : function() {};
displayAllOrders = async function(orders) {
allOrdersData = orders || [];
const tbody = document.getElementById('allOrdersTableBody');
if (!tbody) {
// 如果不是管理员页面,调用原始函数
return await originalDisplayAllOrders(orders);
}
if (orders.length === 0) {
tbody.innerHTML = '<tr><td colspan="8" class="text-center text-muted py-4">暂无数据</td></tr>';
return;
}
// 获取所有车辆信息
const vehiclesRes = await http.get(API.VEHICLES);
const vehicles = vehiclesRes.data || [];
tbody.innerHTML = orders.map(o => {
const vehicle = vehicles.find(v => v.vehicleId === o.vehicleId);
return `
<tr>
<td>${o.orderNo}</td>
<td>${Utils.getServiceTypeText(o.serviceType)}</td>
<td>${vehicle ? vehicle.licensePlate : '-'}</td>
<td>${Utils.formatMoney(o.totalCost)}</td>
<td>${Utils.getStatusBadge(o.status)}</td>
<td>${Utils.getStatusBadge(o.paymentStatus, 'payment')}</td>
<td>${Utils.formatDateTime(o.createTime)}</td>
<td>
<button class="btn btn-sm btn-info" onclick="viewOrder(${o.orderId})">查看</button>
<button class="btn btn-sm btn-warning" onclick="editOrder(${o.orderId})">编辑</button>
<button class="btn btn-sm btn-danger" onclick="deleteOrder(${o.orderId})">删除</button>
</td>
</tr>
`;
}).join('');
};
// ==================== 用户管理 ====================
// 查看用户详情
@@ -434,12 +540,51 @@ function showAddPartModal() {
// 加载所有数据
async function loadAllData() {
await Promise.all([
loadAllUsers(),
loadAllVehicles(),
loadAllOrders(),
loadAllParts()
]);
console.log('开始加载所有数据...');
Utils.loading(true);
try {
// 并行加载所有数据
const [usersRes, vehiclesRes, ordersRes, partsRes] = await Promise.all([
http.get(API.USERS),
http.get(API.VEHICLES),
http.get(API.ORDERS),
http.get(API.PARTS)
]);
// 显示用户数据
if (usersRes.code === 200) {
allUsersData = usersRes.data || [];
displayAllUsers(allUsersData);
}
// 显示车辆数据
if (vehiclesRes.code === 200) {
allVehiclesData = vehiclesRes.data || [];
displayAllVehicles(allVehiclesData);
}
// 显示工单数据
if (ordersRes.code === 200) {
allOrdersData = ordersRes.data || [];
await displayAllOrders(allOrdersData);
}
// 显示配件数据
if (partsRes.code === 200) {
allPartsData = partsRes.data || [];
displayAllParts(allPartsData);
}
// 加载预约数据
await loadAppointments();
console.log('所有数据加载完成');
} catch (error) {
console.error('加载数据失败:', error);
Utils.showToast('加载数据失败', 'error');
} finally {
Utils.loading(false);
}
}
// 加载所有配件
@@ -507,101 +652,7 @@ async function deletePart(id) {
}
}
// ==================== 页面初始化 ====================
// 重写displayAllUsers以存储数据
const originalDisplayAllUsers = displayAllUsers;
displayAllUsers = function(users) {
allUsersData = users || [];
const tbody = document.getElementById('allUsersTableBody');
if (!tbody) return;
if (users.length === 0) {
tbody.innerHTML = '<tr><td colspan="7" class="text-center text-muted py-4">暂无数据</td></tr>';
return;
}
tbody.innerHTML = users.map(u => `
<tr>
<td>${u.userId}</td>
<td>${u.username}</td>
<td>${u.realName}</td>
<td>${u.phone}</td>
<td>${Utils.getRoleText(u.role)}</td>
<td>${u.status === 1 ? '<span class="badge bg-success">启用</span>' : '<span class="badge bg-secondary">禁用</span>'}</td>
<td>
<button class="btn btn-sm btn-info" onclick="viewUser(${u.userId})">查看</button>
<button class="btn btn-sm btn-warning" onclick="editUser(${u.userId})">编辑</button>
<button class="btn btn-sm btn-danger" onclick="deleteUser(${u.userId})">删除</button>
</td>
</tr>
`).join('');
};
// 重写displayAllVehicles以存储数据
const originalDisplayAllVehicles = displayAllVehicles;
displayAllVehicles = function(vehicles) {
allVehiclesData = vehicles || [];
const tbody = document.getElementById('allVehiclesTableBody');
if (!tbody) return;
if (vehicles.length === 0) {
tbody.innerHTML = '<tr><td colspan="6" class="text-center text-muted py-4">暂无数据</td></tr>';
return;
}
tbody.innerHTML = vehicles.map(v => `
<tr>
<td>${v.licensePlate}</td>
<td>${v.brand} ${v.model}</td>
<td>${v.color || '-'}</td>
<td>${v.mileage || 0}</td>
<td>${Utils.getStatusBadge(v.status)}</td>
<td>
<button class="btn btn-sm btn-info" onclick="viewVehicle(${v.vehicleId})">查看</button>
<button class="btn btn-sm btn-warning" onclick="editVehicle(${v.vehicleId})">编辑</button>
<button class="btn btn-sm btn-danger" onclick="deleteVehicle(${v.vehicleId})">删除</button>
</td>
</tr>
`).join('');
};
// 重写displayAllOrders以存储数据
const originalDisplayAllOrders = displayAllOrders;
displayAllOrders = async function(orders) {
allOrdersData = orders || [];
const tbody = document.getElementById('allOrdersTableBody');
if (!tbody) return;
if (orders.length === 0) {
tbody.innerHTML = '<tr><td colspan="8" class="text-center text-muted py-4">暂无数据</td></tr>';
return;
}
// 获取所有车辆信息
const vehiclesRes = await http.get(API.VEHICLES);
const vehicles = vehiclesRes.data || [];
tbody.innerHTML = orders.map(o => {
const vehicle = vehicles.find(v => v.vehicleId === o.vehicleId);
return `
<tr>
<td>${o.orderNo}</td>
<td>${Utils.getServiceTypeText(o.serviceType)}</td>
<td>${vehicle ? vehicle.licensePlate : '-'}</td>
<td>${Utils.formatMoney(o.totalCost)}</td>
<td>${Utils.getStatusBadge(o.status)}</td>
<td>${Utils.getStatusBadge(o.paymentStatus, 'payment')}</td>
<td>${Utils.formatDateTime(o.createTime)}</td>
<td>
<button class="btn btn-sm btn-info" onclick="viewOrder(${o.orderId})">查看</button>
<button class="btn btn-sm btn-warning" onclick="editOrder(${o.orderId})">编辑</button>
<button class="btn btn-sm btn-danger" onclick="deleteOrder(${o.orderId})">删除</button>
</td>
</tr>
`;
}).join('');
};
// ==================== 预约管理 ====================
// 加载预约数据
async function loadAppointments() {
@@ -692,8 +743,11 @@ async function cancelAppointmentAdmin(id) {
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', function() {
// 如果是管理员页面,加载所有数据
// 如果是管理员页面,等待一小段时间确保所有脚本加载完成
if (window.location.pathname.includes('admin')) {
loadAllData();
console.log('检测到管理员页面,准备加载数据');
setTimeout(() => {
loadAllData();
}, 100);
}
});

View File

@@ -185,7 +185,7 @@ const Utils = {
if (this.confirm('确定要退出登录吗?')) {
localStorage.removeItem(STORAGE.TOKEN);
localStorage.removeItem(STORAGE.USER);
window.location.href = 'login.html';
window.location.href = '/login.html';
}
},
@@ -238,9 +238,9 @@ const Utils = {
// 获取角色文本
getRoleText(role) {
const roles = {
admin: '<span class="badge bg-danger">管理员</span>',
staff: '<span class="badge bg-success">工作人员</span>',
customer: '<span class="badge bg-info">客户</span>'
admin: '管理员',
staff: '工作人员',
customer: '客户'
};
return roles[role] || role;
},

View File

@@ -558,21 +558,31 @@ function showSection(sectionId) {
case 'users':
loadAllUsers();
break;
case 'parts':
if (typeof loadAllParts === 'function') {
loadAllParts();
}
break;
case 'appointments':
if (typeof loadAppointments === 'function') {
loadAppointments();
}
break;
}
}
// 加载所有车辆(管理员页面使用)
async function loadAllVehicles() {
// 如果是管理员页面调用admin.js中的函数
if (typeof loadAllData === 'function') {
return;
}
Utils.loading(true);
try {
const response = await http.get(API.VEHICLES);
if (response.code === 200) {
displayAllVehicles(response.data || []);
// 如果是管理员页面让admin.js的displayAllVehicles处理
if (typeof displayAllVehicles === 'function' && document.getElementById('allVehiclesTableBody')) {
displayAllVehicles(response.data || []);
} else {
displayAllVehicles(response.data || []);
}
}
} catch (error) {
console.error('加载车辆失败:', error);
@@ -584,11 +594,6 @@ async function loadAllVehicles() {
// 显示所有车辆(客户页面使用)
function displayAllVehicles(vehicles) {
// 如果是管理员页面,不执行
if (document.getElementById('allVehiclesTableBody')) {
return;
}
const container = document.getElementById('vehiclesContainer');
if (!container) return;
@@ -624,16 +629,16 @@ function displayAllVehicles(vehicles) {
// 加载所有工单
async function loadAllOrders() {
// 如果是管理员页面跳过由admin.js处理
if (document.getElementById('allOrdersTableBody')) {
return;
}
Utils.loading(true);
try {
const response = await http.get(API.ORDERS);
if (response.code === 200) {
displayAllOrders(response.data || []);
// 如果是管理员页面让admin.js的displayAllOrders处理
if (typeof displayAllOrders === 'function' && document.getElementById('allOrdersTableBody')) {
await displayAllOrders(response.data || []);
} else {
await displayAllOrders(response.data || []);
}
}
} catch (error) {
console.error('加载工单失败:', error);
@@ -645,11 +650,6 @@ async function loadAllOrders() {
// 显示所有工单(客户页面使用)
async function displayAllOrders(orders) {
// 如果是管理员页面,不执行
if (document.getElementById('allOrdersTableBody')) {
return;
}
const tbody = document.getElementById('ordersTableBody');
if (!tbody) return;
@@ -679,9 +679,20 @@ async function displayAllOrders(orders) {
// 加载所有用户
async function loadAllUsers() {
// 管理员页面由admin.js处理
if (document.getElementById('allUsersTableBody')) {
return;
Utils.loading(true);
try {
const response = await http.get(API.USERS);
if (response.code === 200) {
// 如果是管理员页面让admin.js的displayAllUsers处理
if (typeof displayAllUsers === 'function' && document.getElementById('allUsersTableBody')) {
displayAllUsers(response.data || []);
}
}
} catch (error) {
console.error('加载用户失败:', error);
Utils.showToast('加载失败', 'error');
} finally {
Utils.loading(false);
}
}

2018
frontend/lib/bootstrap-icons.css vendored Normal file

File diff suppressed because it is too large Load Diff

7
frontend/lib/bootstrap.bundle.min.js vendored Normal file

File diff suppressed because one or more lines are too long

6
frontend/lib/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

View File

@@ -4,8 +4,8 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>车管家4S店车辆维保管理系统 - 登录</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css" rel="stylesheet">
<link href="/lib/bootstrap.min.css" rel="stylesheet">
<link href="/lib/bootstrap-icons.css" rel="stylesheet">
<link rel="stylesheet" href="css/style.css">
</head>
<body class="bg-light">
@@ -96,7 +96,7 @@
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="/lib/bootstrap.bundle.min.js"></script>
<script src="js/config.js"></script>
<script src="js/api.js"></script>
<script src="js/app.js"></script>

View File

@@ -4,8 +4,8 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>工作人员仪表板 - 车管家4S店车辆维保管理系统</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css" rel="stylesheet">
<link href="/lib/bootstrap.min.css" rel="stylesheet">
<link href="/lib/bootstrap-icons.css" rel="stylesheet">
<link rel="stylesheet" href="../css/style.css">
</head>
<body>
@@ -228,7 +228,7 @@
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="/lib/bootstrap.bundle.min.js"></script>
<script src="../js/config.js"></script>
<script src="../js/api.js"></script>
<script>