Files
car-maintenance-system/frontend/js/admin.js
wangziqi 7c4be0b7b4 add
2026-01-07 15:39:54 +08:00

700 lines
25 KiB
JavaScript
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.

// 管理员仪表板专用JavaScript
// 全局数据存储
let allUsersData = [];
let allVehiclesData = [];
let allOrdersData = [];
let allPartsData = [];
// ==================== 用户管理 ====================
// 查看用户详情
async function viewUser(id) {
Utils.loading(true);
try {
const response = await http.get(API.USER(id));
if (response.code === 200 && response.data) {
const user = response.data;
// 填充表单(只读模式)
document.getElementById('userId').value = user.userId;
document.getElementById('userUsername').value = user.username;
document.getElementById('userRealName').value = user.realName;
document.getElementById('userPhone').value = user.phone;
document.getElementById('userEmail').value = user.email || '';
document.getElementById('userRole').value = user.role;
document.getElementById('userStatus').value = user.status;
// 禁用表单控件
document.getElementById('userForm').querySelectorAll('input, select').forEach(el => {
el.disabled = true;
});
document.getElementById('userModalTitle').textContent = '查看用户详情';
const modal = new bootstrap.Modal(document.getElementById('userModal'));
modal.show();
// 启用表单控件(在关闭时)
document.getElementById('userModal').addEventListener('hidden.bs.modal', function() {
document.getElementById('userForm').querySelectorAll('input, select').forEach(el => {
el.disabled = false;
});
}, { once: true });
}
} catch (error) {
Utils.showToast('加载用户信息失败', 'error');
} finally {
Utils.loading(false);
}
}
// 编辑用户
async function editUser(id) {
const user = allUsersData.find(u => u.userId === id);
if (!user) {
Utils.showToast('用户不存在', 'error');
return;
}
// 填充表单
document.getElementById('userId').value = user.userId;
document.getElementById('userUsername').value = user.username;
document.getElementById('userRealName').value = user.realName;
document.getElementById('userPhone').value = user.phone;
document.getElementById('userEmail').value = user.email || '';
document.getElementById('userRole').value = user.role;
document.getElementById('userStatus').value = user.status;
document.getElementById('userModalTitle').textContent = '编辑用户';
const modal = new bootstrap.Modal(document.getElementById('userModal'));
modal.show();
}
// 保存用户
async function saveUser() {
const userId = document.getElementById('userId').value;
const userData = {
username: document.getElementById('userUsername').value,
realName: document.getElementById('userRealName').value,
phone: document.getElementById('userPhone').value,
email: document.getElementById('userEmail').value,
role: document.getElementById('userRole').value,
status: parseInt(document.getElementById('userStatus').value)
};
Utils.loading(true);
try {
let response;
if (userId) {
// 更新
response = await http.put(API.USER(userId), userData);
} else {
// 新增
userData.password = '123456'; // 默认密码
response = await http.post(API.USERS, userData);
}
if (response.code === 200) {
Utils.showToast(userId ? '更新成功' : '创建成功', 'success');
const modal = bootstrap.Modal.getInstance(document.getElementById('userModal'));
modal.hide();
loadAllUsers();
} else {
Utils.showToast(response.message || '保存失败', 'error');
}
} catch (error) {
console.error('保存用户失败:', error);
Utils.showToast('保存失败', 'error');
} finally {
Utils.loading(false);
}
}
// 添加用户
function showAddUserModal() {
// 清空表单
document.getElementById('userForm').reset();
document.getElementById('userId').value = '';
document.getElementById('userStatus').value = '1';
document.getElementById('userModalTitle').textContent = '添加用户';
const modal = new bootstrap.Modal(document.getElementById('userModal'));
modal.show();
}
// ==================== 车辆管理 ====================
// 查看车辆详情
async function viewVehicle(id) {
Utils.loading(true);
try {
const response = await http.get(API.VEHICLE(id));
if (response.code === 200 && response.data) {
const vehicle = response.data;
document.getElementById('vehicleId').value = vehicle.vehicleId;
document.getElementById('vehicleLicensePlate').value = vehicle.licensePlate;
document.getElementById('vehicleBrand').value = vehicle.brand;
document.getElementById('vehicleModel').value = vehicle.model;
document.getElementById('vehicleColor').value = vehicle.color || '';
document.getElementById('vehicleMileage').value = vehicle.mileage || 0;
document.getElementById('vehicleStatus').value = vehicle.status;
// 禁用表单
document.getElementById('vehicleForm').querySelectorAll('input, select').forEach(el => {
el.disabled = true;
});
document.getElementById('vehicleModalTitle').textContent = '查看车辆详情';
const modal = new bootstrap.Modal(document.getElementById('vehicleModal'));
modal.show();
document.getElementById('vehicleModal').addEventListener('hidden.bs.modal', function() {
document.getElementById('vehicleForm').querySelectorAll('input, select').forEach(el => {
el.disabled = false;
});
}, { once: true });
}
} catch (error) {
Utils.showToast('加载车辆信息失败', 'error');
} finally {
Utils.loading(false);
}
}
// 编辑车辆
async function editVehicle(id) {
const vehicle = allVehiclesData.find(v => v.vehicleId === id);
if (!vehicle) {
Utils.showToast('车辆不存在', 'error');
return;
}
document.getElementById('vehicleId').value = vehicle.vehicleId;
document.getElementById('vehicleLicensePlate').value = vehicle.licensePlate;
document.getElementById('vehicleBrand').value = vehicle.brand;
document.getElementById('vehicleModel').value = vehicle.model;
document.getElementById('vehicleColor').value = vehicle.color || '';
document.getElementById('vehicleMileage').value = vehicle.mileage || 0;
document.getElementById('vehicleStatus').value = vehicle.status;
document.getElementById('vehicleModalTitle').textContent = '编辑车辆';
const modal = new bootstrap.Modal(document.getElementById('vehicleModal'));
modal.show();
}
// 保存车辆
async function saveVehicle() {
const vehicleId = document.getElementById('vehicleId').value;
const vehicleData = {
licensePlate: document.getElementById('vehicleLicensePlate').value,
brand: document.getElementById('vehicleBrand').value,
model: document.getElementById('vehicleModel').value,
color: document.getElementById('vehicleColor').value,
mileage: parseFloat(document.getElementById('vehicleMileage').value) || 0,
status: document.getElementById('vehicleStatus').value
};
// 获取客户ID这里简化处理实际应该让用户选择
if (!vehicleId) {
vehicleData.customerId = 1; // 默认使用第一个客户
}
Utils.loading(true);
try {
let response;
if (vehicleId) {
response = await http.put(API.VEHICLE(vehicleId), vehicleData);
} else {
response = await http.post(API.VEHICLES, vehicleData);
}
if (response.code === 200) {
Utils.showToast(vehicleId ? '更新成功' : '添加成功', 'success');
const modal = bootstrap.Modal.getInstance(document.getElementById('vehicleModal'));
modal.hide();
loadAllVehicles();
} else {
Utils.showToast(response.message || '保存失败', 'error');
}
} catch (error) {
console.error('保存车辆失败:', error);
Utils.showToast('保存失败', 'error');
} finally {
Utils.loading(false);
}
}
// 添加车辆
function showAddVehicleModal() {
document.getElementById('vehicleForm').reset();
document.getElementById('vehicleId').value = '';
document.getElementById('vehicleMileage').value = 0;
document.getElementById('vehicleModalTitle').textContent = '添加车辆';
const modal = new bootstrap.Modal(document.getElementById('vehicleModal'));
modal.show();
}
// ==================== 工单管理 ====================
// 查看工单详情
async function viewOrder(id) {
Utils.loading(true);
try {
const response = await http.get(API.ORDER(id));
if (response.code === 200 && response.data) {
const order = response.data;
document.getElementById('orderId').value = order.orderId;
document.getElementById('orderServiceType').value = order.serviceType;
document.getElementById('orderFaultDescription').value = order.faultDescription || '';
document.getElementById('orderDiagnosisResult').value = order.diagnosisResult || '';
document.getElementById('orderPartsCost').value = order.partsCost || 0;
document.getElementById('orderLaborCost').value = order.laborCost || 0;
document.getElementById('orderTotalCost').value = order.totalCost || 0;
document.getElementById('orderStatus').value = order.status;
// 禁用表单
document.getElementById('orderForm').querySelectorAll('input, select, textarea').forEach(el => {
el.disabled = true;
});
document.getElementById('orderModalTitle').textContent = '查看工单详情';
const modal = new bootstrap.Modal(document.getElementById('orderModal'));
modal.show();
document.getElementById('orderModal').addEventListener('hidden.bs.modal', function() {
document.getElementById('orderForm').querySelectorAll('input, select, textarea').forEach(el => {
el.disabled = false;
});
}, { once: true });
}
} catch (error) {
Utils.showToast('加载工单信息失败', 'error');
} finally {
Utils.loading(false);
}
}
// 编辑工单
async function editOrder(id) {
const order = allOrdersData.find(o => o.orderId === id);
if (!order) {
Utils.showToast('工单不存在', 'error');
return;
}
document.getElementById('orderId').value = order.orderId;
document.getElementById('orderServiceType').value = order.serviceType;
document.getElementById('orderFaultDescription').value = order.faultDescription || '';
document.getElementById('orderDiagnosisResult').value = order.diagnosisResult || '';
document.getElementById('orderPartsCost').value = order.partsCost || 0;
document.getElementById('orderLaborCost').value = order.laborCost || 0;
document.getElementById('orderTotalCost').value = order.totalCost || 0;
document.getElementById('orderStatus').value = order.status;
document.getElementById('orderModalTitle').textContent = '编辑工单';
const modal = new bootstrap.Modal(document.getElementById('orderModal'));
modal.show();
// 监听费用变化自动计算总额
setupOrderCostCalculation();
}
// 设置工单费用自动计算
function setupOrderCostCalculation() {
const partsCost = document.getElementById('orderPartsCost');
const laborCost = document.getElementById('orderLaborCost');
const totalCost = document.getElementById('orderTotalCost');
function updateTotal() {
const parts = parseFloat(partsCost.value) || 0;
const labor = parseFloat(laborCost.value) || 0;
totalCost.value = (parts + labor).toFixed(2);
}
partsCost.addEventListener('input', updateTotal);
laborCost.addEventListener('input', updateTotal);
}
// 保存工单
async function saveOrder() {
const orderId = document.getElementById('orderId').value;
const orderData = {
serviceType: document.getElementById('orderServiceType').value,
faultDescription: document.getElementById('orderFaultDescription').value,
diagnosisResult: document.getElementById('orderDiagnosisResult').value,
partsCost: parseFloat(document.getElementById('orderPartsCost').value) || 0,
laborCost: parseFloat(document.getElementById('orderLaborCost').value) || 0,
totalCost: parseFloat(document.getElementById('orderTotalCost').value) || 0,
status: document.getElementById('orderStatus').value
};
Utils.loading(true);
try {
// 更新工单
const response = await http.put(API.ORDER(orderId), orderData);
if (response.code === 200) {
Utils.showToast('更新成功', 'success');
const modal = bootstrap.Modal.getInstance(document.getElementById('orderModal'));
modal.hide();
loadAllOrders();
} else {
Utils.showToast(response.message || '保存失败', 'error');
}
} catch (error) {
console.error('保存工单失败:', error);
Utils.showToast('保存失败', 'error');
} finally {
Utils.loading(false);
}
}
// 添加工单
function showAddOrderModal() {
document.getElementById('orderForm').reset();
document.getElementById('orderId').value = '';
document.getElementById('orderPartsCost').value = 0;
document.getElementById('orderLaborCost').value = 0;
document.getElementById('orderTotalCost').value = 0;
document.getElementById('orderModalTitle').textContent = '创建工单';
const modal = new bootstrap.Modal(document.getElementById('orderModal'));
modal.show();
setupOrderCostCalculation();
}
// 过滤工单
function filterOrders(status) {
if (!status) {
displayAllOrders(allOrdersData);
} else {
const filtered = allOrdersData.filter(o => o.status === status);
displayAllOrders(filtered);
}
}
// ==================== 配件管理 ====================
// 查看配件详情
async function viewPart(id) {
Utils.loading(true);
try {
const response = await http.get(API.PART(id));
if (response.code === 200 && response.data) {
const part = response.data;
// 显示配件详情
Utils.showToast('配件名称: ' + part.partName + '\n库存: ' + part.stockQuantity + part.unit, 'info');
}
} catch (error) {
Utils.showToast('加载配件信息失败', 'error');
} finally {
Utils.loading(false);
}
}
// 编辑配件
async function editPart(id) {
const part = allPartsData.find(p => p.partId === id);
if (!part) {
Utils.showToast('配件不存在', 'error');
return;
}
// 简单实现使用prompt编辑
const newStock = prompt('请输入新的库存数量:', part.stockQuantity);
if (newStock !== null && !isNaN(newStock)) {
Utils.loading(true);
try {
const response = await http.put(API.PART(id), {
...part,
stockQuantity: parseInt(newStock)
});
if (response.code === 200) {
Utils.showToast('更新成功', 'success');
loadAllParts();
} else {
Utils.showToast(response.message || '更新失败', 'error');
}
} catch (error) {
Utils.showToast('更新失败', 'error');
} finally {
Utils.loading(false);
}
}
}
// 添加配件
function showAddPartModal() {
Utils.showToast('添加配件功能开发中...', 'info');
}
// ==================== 数据加载函数 ====================
// 加载所有数据
async function loadAllData() {
await Promise.all([
loadAllUsers(),
loadAllVehicles(),
loadAllOrders(),
loadAllParts()
]);
}
// 加载所有配件
async function loadAllParts() {
Utils.loading(true);
try {
const response = await http.get(API.PARTS);
if (response.code === 200) {
allPartsData = response.data || [];
displayAllParts(allPartsData);
}
} catch (error) {
console.error('加载配件失败:', error);
} finally {
Utils.loading(false);
}
}
// 显示所有配件
function displayAllParts(parts) {
const tbody = document.getElementById('partsTableBody');
if (!tbody) return;
if (parts.length === 0) {
tbody.innerHTML = '<tr><td colspan="6" class="text-center text-muted py-4">暂无数据</td></tr>';
return;
}
tbody.innerHTML = parts.map(p => `
<tr>
<td>${p.partNo}</td>
<td>${p.partName}</td>
<td>${p.category || '-'}</td>
<td>
${p.stockQuantity} ${p.unit}
${p.stockQuantity <= p.minStock ? '<span class="badge bg-danger ms-2">库存预警</span>' : ''}
</td>
<td>${Utils.formatMoney(p.unitPrice)}</td>
<td>
<button class="btn btn-sm btn-info" onclick="viewPart(${p.partId})">查看</button>
<button class="btn btn-sm btn-warning" onclick="editPart(${p.partId})">编辑</button>
<button class="btn btn-sm btn-danger" onclick="deletePart(${p.partId})">删除</button>
</td>
</tr>
`).join('');
}
// 删除配件
async function deletePart(id) {
if (!Utils.confirm('确定要删除此配件吗?')) return;
Utils.loading(true);
try {
const response = await http.delete(API.PART(id));
if (response.code === 200) {
Utils.showToast('删除成功', 'success');
loadAllParts();
} else {
Utils.showToast(response.message || '删除失败', 'error');
}
} catch (error) {
Utils.showToast('删除失败', 'error');
} finally {
Utils.loading(false);
}
}
// ==================== 页面初始化 ====================
// 重写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() {
Utils.loading(true);
try {
const [appointmentsRes, vehiclesRes] = await Promise.all([
http.get(API.APPOINTMENTS),
http.get(API.VEHICLES)
]);
if (appointmentsRes.code === 200) {
const vehicles = vehiclesRes.data || [];
displayAppointments(appointmentsRes.data || [], vehicles);
}
} catch (error) {
console.error('加载预约失败:', error);
} finally {
Utils.loading(false);
}
}
// 显示预约列表
function displayAppointments(appointments, vehicles) {
const tbody = document.getElementById('appointmentsTableBody');
if (!tbody) return;
if (appointments.length === 0) {
tbody.innerHTML = '<tr><td colspan="7" class="text-center text-muted py-4">暂无数据</td></tr>';
return;
}
tbody.innerHTML = appointments.map(a => {
const vehicle = vehicles.find(v => v.vehicleId === a.vehicleId);
return `
<tr>
<td>${a.appointmentId}</td>
<td>${Utils.getServiceTypeText(a.serviceType)}</td>
<td>${vehicle ? vehicle.licensePlate : '-'}</td>
<td>${Utils.formatDateTime(a.appointmentTime)}</td>
<td>${a.contactPhone}</td>
<td>${Utils.getStatusBadge(a.status, 'appointment')}</td>
<td>
<button class="btn btn-sm btn-success" onclick="confirmAppointment(${a.appointmentId})">确认</button>
<button class="btn btn-sm btn-danger" onclick="cancelAppointmentAdmin(${a.appointmentId})">取消</button>
</td>
</tr>
`;
}).join('');
}
// 管理员确认预约
async function confirmAppointment(id) {
Utils.loading(true);
try {
const response = await http.put(API.APPOINTMENT(id), { status: 'confirmed' });
if (response.code === 200) {
Utils.showToast('预约已确认', 'success');
loadAppointments();
} else {
Utils.showToast(response.message || '操作失败', 'error');
}
} catch (error) {
Utils.showToast('操作失败', 'error');
} finally {
Utils.loading(false);
}
}
// 管理员取消预约
async function cancelAppointmentAdmin(id) {
if (!Utils.confirm('确定要取消此预约吗?')) return;
Utils.loading(true);
try {
const response = await http.put(API.APPOINTMENT_CANCEL(id), {});
if (response.code === 200) {
Utils.showToast('预约已取消', 'success');
loadAppointments();
} else {
Utils.showToast(response.message || '操作失败', 'error');
}
} catch (error) {
Utils.showToast('操作失败', 'error');
} finally {
Utils.loading(false);
}
}
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', function() {
// 如果是管理员页面,加载所有数据
if (window.location.pathname.includes('admin')) {
loadAllData();
}
});