This commit is contained in:
wangziqi
2026-01-08 13:23:09 +08:00
parent 177cfd9b9d
commit 35098f3028
57 changed files with 4725 additions and 55 deletions

View File

@@ -484,19 +484,42 @@ function filterOrders(status) {
// 查看配件详情
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);
const part = allPartsData.find(p => p.partId === id);
if (!part) {
Utils.showToast('配件不存在', 'error');
return;
}
// 填充表单
document.getElementById('partId').value = part.partId;
document.getElementById('partPartNo').value = part.partNo;
document.getElementById('partPartName').value = part.partName;
document.getElementById('partCategory').value = part.category || '';
document.getElementById('partBrand').value = part.brand || '';
document.getElementById('partModel').value = part.model || '';
document.getElementById('partUnit').value = part.unit || '个';
document.getElementById('partUnitPrice').value = part.unitPrice;
document.getElementById('partStockQuantity').value = part.stockQuantity;
document.getElementById('partMinStock').value = part.minStock;
document.getElementById('partSupplier').value = part.supplier || '';
document.getElementById('partWarehouseLocation').value = part.warehouseLocation || '';
document.getElementById('partRemark').value = part.remark || '';
// 禁用表单(只读模式)
document.getElementById('partForm').querySelectorAll('input, select, textarea').forEach(el => {
el.disabled = true;
});
document.getElementById('partModalTitle').textContent = '查看配件详情';
const modal = new bootstrap.Modal(document.getElementById('partModal'));
modal.show();
// 启用表单控件(在关闭时)
document.getElementById('partModal').addEventListener('hidden.bs.modal', function() {
document.getElementById('partForm').querySelectorAll('input, select, textarea').forEach(el => {
el.disabled = false;
});
}, { once: true });
}
// 编辑配件
@@ -507,33 +530,81 @@ async function editPart(id) {
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)
});
// 填充表单
document.getElementById('partId').value = part.partId;
document.getElementById('partPartNo').value = part.partNo;
document.getElementById('partPartName').value = part.partName;
document.getElementById('partCategory').value = part.category || '';
document.getElementById('partBrand').value = part.brand || '';
document.getElementById('partModel').value = part.model || '';
document.getElementById('partUnit').value = part.unit || '个';
document.getElementById('partUnitPrice').value = part.unitPrice;
document.getElementById('partStockQuantity').value = part.stockQuantity;
document.getElementById('partMinStock').value = part.minStock;
document.getElementById('partSupplier').value = part.supplier || '';
document.getElementById('partWarehouseLocation').value = part.warehouseLocation || '';
document.getElementById('partRemark').value = part.remark || '';
if (response.code === 200) {
Utils.showToast('更新成功', 'success');
loadAllParts();
} else {
Utils.showToast(response.message || '更新失败', 'error');
}
} catch (error) {
Utils.showToast('更新失败', 'error');
} finally {
Utils.loading(false);
document.getElementById('partModalTitle').textContent = '编辑配件';
const modal = new bootstrap.Modal(document.getElementById('partModal'));
modal.show();
}
// 保存配件
async function savePart() {
const partId = document.getElementById('partId').value;
const partData = {
partNo: document.getElementById('partPartNo').value,
partName: document.getElementById('partPartName').value,
category: document.getElementById('partCategory').value,
brand: document.getElementById('partBrand').value,
model: document.getElementById('partModel').value,
unit: document.getElementById('partUnit').value,
unitPrice: parseFloat(document.getElementById('partUnitPrice').value),
stockQuantity: parseInt(document.getElementById('partStockQuantity').value),
minStock: parseInt(document.getElementById('partMinStock').value),
supplier: document.getElementById('partSupplier').value,
warehouseLocation: document.getElementById('partWarehouseLocation').value,
remark: document.getElementById('partRemark').value
};
Utils.loading(true);
try {
let response;
if (partId) {
// 更新
response = await http.put(API.PART(partId), partData);
} else {
// 新增
response = await http.post(API.PARTS, partData);
}
if (response.code === 200) {
Utils.showToast(partId ? '更新成功' : '添加成功', 'success');
const modal = bootstrap.Modal.getInstance(document.getElementById('partModal'));
modal.hide();
loadAllParts();
} else {
Utils.showToast(response.message || '保存失败', 'error');
}
} catch (error) {
console.error('保存配件失败:', error);
Utils.showToast('保存失败', 'error');
} finally {
Utils.loading(false);
}
}
// 添加配件
function showAddPartModal() {
Utils.showToast('添加配件功能开发中...', 'info');
// 清空表单
document.getElementById('partForm').reset();
document.getElementById('partId').value = '';
document.getElementById('partUnit').value = '个';
document.getElementById('partModalTitle').textContent = '添加配件';
const modal = new bootstrap.Modal(document.getElementById('partModal'));
modal.show();
}
// ==================== 数据加载函数 ====================
@@ -578,6 +649,9 @@ async function loadAllData() {
// 加载预约数据
await loadAppointments();
// 加载管理员首页统计数据和最近工单
await loadAdminStatsData();
console.log('所有数据加载完成');
} catch (error) {
console.error('加载数据失败:', error);
@@ -587,6 +661,83 @@ async function loadAllData() {
}
}
// 加载管理员首页数据(统计和最近工单)
async function loadAdminStatsData() {
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_LOW_STOCK)
]);
if (usersRes.code === 200) {
updateStat('totalUsers', usersRes.data?.length || 0);
}
if (vehiclesRes.code === 200) {
updateStat('totalVehicles', vehiclesRes.data?.length || 0);
}
if (ordersRes.code === 200) {
updateStat('totalOrders', ordersRes.data?.length || 0);
// 显示最近工单前5条
const recentOrders = ordersRes.data.slice(0, 5);
await displayRecentOrders(recentOrders);
}
if (partsRes.code === 200) {
updateStat('lowStockParts', partsRes.data?.length || 0);
}
} catch (error) {
console.error('加载统计数据失败:', error);
}
}
// 显示最近工单
async function displayRecentOrders(orders) {
const tbody = document.getElementById('recentOrdersTableBody');
if (!tbody) return;
if (orders.length === 0) {
tbody.innerHTML = '<tr><td colspan="6" 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.formatDateTime(o.createTime)}</td>
</tr>
`;
}).join('');
}
// 更新统计数字
function updateStat(id, value) {
const el = document.getElementById(id);
if (el) {
el.textContent = value;
// 添加动画效果
el.style.transition = 'all 0.3s';
el.style.transform = 'scale(1.2)';
setTimeout(() => {
el.style.transform = 'scale(1)';
}, 300);
}
}
// 加载所有配件
async function loadAllParts() {
Utils.loading(true);

View File

@@ -275,17 +275,21 @@ async function loadCustomerData() {
if (!user) return;
try {
// 获取所有用户找到自己的customer_id
const usersRes = await http.get(API.USERS);
if (usersRes.code === 200 && usersRes.data) {
const customers = usersRes.data.filter(u => u.role === 'customer');
const currentUser = customers.find(c => c.userId === user.userId);
// 获取用户信息、客户信息、车辆信息
const [usersRes, customersRes] = await Promise.all([
http.get(API.USERS),
http.get(API.CUSTOMERS)
]);
if (currentUser) {
// 加载车辆、工单、预约数据
loadCustomerVehicles(currentUser.userId);
loadCustomerOrders(currentUser.userId);
loadCustomerAppointments(currentUser.userId);
if (usersRes.code === 200 && customersRes.code === 200) {
// 找到当前用户对应的客户记录
const currentCustomer = customersRes.data.find(c => c.userId === user.userId);
if (currentCustomer) {
// 加载车辆、工单、预约数据使用customer_id而不是user_id
loadCustomerVehicles(currentCustomer.customerId);
loadCustomerOrders(currentCustomer.customerId);
loadCustomerAppointments(currentCustomer.customerId);
}
}
} catch (error) {
@@ -294,13 +298,13 @@ async function loadCustomerData() {
}
// 加载客户车辆
async function loadCustomerVehicles(userId) {
async function loadCustomerVehicles(customerId) {
try {
const response = await http.get(API.VEHICLES);
// 使用专门的API端点获取客户的车辆而不是获取所有车辆再过滤
const response = await http.get(API.VEHICLE_CUSTOMER(customerId));
if (response.code === 200 && response.data) {
const myVehicles = response.data.filter(v => v.customerId === userId);
displayVehicles(myVehicles);
populateVehicleSelect(myVehicles);
displayVehicles(response.data);
populateVehicleSelect(response.data);
}
} catch (error) {
console.error('加载车辆失败:', error);
@@ -352,10 +356,10 @@ function populateVehicleSelect(vehicles) {
}
// 加载客户工单
async function loadCustomerOrders(userId) {
async function loadCustomerOrders(customerId) {
try {
const [ordersRes, vehiclesRes] = await Promise.all([
http.get(API.ORDER_CUSTOMER(userId)),
http.get(API.ORDER_CUSTOMER(customerId)),
http.get(API.VEHICLES)
]);
@@ -394,10 +398,10 @@ function displayOrders(orders, vehicles) {
}
// 加载客户预约
async function loadCustomerAppointments(userId) {
async function loadCustomerAppointments(customerId) {
try {
const [appointmentsRes, vehiclesRes] = await Promise.all([
http.get(API.APPOINTMENT_CUSTOMER(userId)),
http.get(API.APPOINTMENT_CUSTOMER(customerId)),
http.get(API.VEHICLES)
]);
@@ -445,10 +449,16 @@ async function cancelAppointment(id) {
const response = await http.put(API.APPOINTMENT_CANCEL(id), {});
if (response.code === 200) {
Utils.showToast('预约已取消', 'success');
// 重新加载预约列表
// 重新加载预约列表 - 需要获取customer_id
const user = Utils.getCurrentUser();
if (user) {
loadCustomerAppointments(user.userId);
const customersRes = await http.get(API.CUSTOMERS);
if (customersRes.code === 200) {
const currentCustomer = customersRes.data.find(c => c.userId === user.userId);
if (currentCustomer) {
loadCustomerAppointments(currentCustomer.customerId);
}
}
}
} else {
Utils.showToast(response.message || '取消失败', 'error');
@@ -490,8 +500,23 @@ async function submitAppointment() {
Utils.loading(true);
try {
// 获取customer_id
const customersRes = await http.get(API.CUSTOMERS);
if (customersRes.code !== 200) {
Utils.showToast('获取客户信息失败', 'error');
Utils.loading(false);
return;
}
const currentCustomer = customersRes.data.find(c => c.userId === user.userId);
if (!currentCustomer) {
Utils.showToast('未找到客户信息', 'error');
Utils.loading(false);
return;
}
const response = await http.post(API.APPOINTMENTS, {
customerId: user.userId,
customerId: currentCustomer.customerId,
vehicleId: parseInt(vehicleId),
serviceType: serviceType,
appointmentTime: appointmentTime,
@@ -504,7 +529,7 @@ async function submitAppointment() {
// 重置表单
document.getElementById('appointmentForm').reset();
// 重新加载预约列表
loadCustomerAppointments(user.userId);
loadCustomerAppointments(currentCustomer.customerId);
} else {
Utils.showToast(response.message || '预约失败', 'error');
}

View File

@@ -17,6 +17,10 @@ const API = {
USERS_ROLE: (role) => `/users/role/${role}`,
CHANGE_PASSWORD: (id) => `/users/${id}/password`,
// 客户
CUSTOMERS: '/customers',
CUSTOMER: (id) => `/customers/${id}`,
// 车辆
VEHICLES: '/vehicles',
VEHICLE: (id) => `/vehicles/${id}`,