Files
car-maintenance-system/frontend/js/api.js
wangziqi ea9c94dfeb add
2026-01-07 16:18:56 +08:00

263 lines
7.9 KiB
JavaScript

// HTTP请求类
class HttpClient {
constructor() {
this.baseURL = API_CONFIG.BASE_URL;
this.timeout = API_CONFIG.TIMEOUT;
}
// 获取请求头
getHeaders() {
const headers = {
'Content-Type': 'application/json'
};
const token = localStorage.getItem(STORAGE.TOKEN);
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
return headers;
}
// 通用请求方法
async request(url, options = {}) {
const config = {
method: options.method || 'GET',
headers: this.getHeaders(),
...options
};
if (options.body && typeof options.body === 'object') {
config.body = JSON.stringify(options.body);
}
try {
const response = await fetch(this.baseURL + url, config);
const data = await response.json();
if (data.code === 401) {
this.handleUnauthorized();
throw new Error('未授权,请重新登录');
}
return data;
} catch (error) {
console.error('API请求错误:', error);
throw error;
}
}
// GET请求
get(url) {
return this.request(url, { method: 'GET' });
}
// POST请求
post(url, body) {
return this.request(url, { method: 'POST', body });
}
// PUT请求
put(url, body) {
return this.request(url, { method: 'PUT', body });
}
// DELETE请求
delete(url) {
return this.request(url, { method: 'DELETE' });
}
// 处理未授权
handleUnauthorized() {
localStorage.removeItem(STORAGE.TOKEN);
localStorage.removeItem(STORAGE.USER);
window.location.href = 'login.html';
}
}
// 创建HTTP客户端实例
const http = new HttpClient();
// 工具函数类
const Utils = {
// 显示Toast消息
showToast(message, type = 'info') {
const toastEl = document.getElementById('liveToast');
const toast = new bootstrap.Toast(toastEl);
const toastIcon = document.getElementById('toastIcon');
const toastTitle = document.getElementById('toastTitle');
const toastMessage = document.getElementById('toastMessage');
// 设置图标和样式
toastEl.className = 'toast';
toastIcon.className = 'bi me-2';
switch(type) {
case 'success':
toastEl.classList.add('success');
toastIcon.classList.add('bi-check-circle-fill');
toastIcon.style.color = '#198754';
toastTitle.textContent = '成功';
break;
case 'error':
toastEl.classList.add('error');
toastIcon.classList.add('bi-x-circle-fill');
toastIcon.style.color = '#dc3545';
toastTitle.textContent = '错误';
break;
case 'warning':
toastEl.classList.add('warning');
toastIcon.classList.add('bi-exclamation-triangle-fill');
toastIcon.style.color = '#ffc107';
toastTitle.textContent = '警告';
break;
default:
toastEl.classList.add('info');
toastIcon.classList.add('bi-info-circle-fill');
toastIcon.style.color = '#0dcaf0';
toastTitle.textContent = '提示';
}
toastMessage.textContent = message;
toast.show();
},
// 显示/隐藏Loading
loading(show = true) {
const overlay = document.getElementById('loadingOverlay');
if (overlay) {
if (show) {
overlay.classList.remove('d-none');
overlay.classList.add('loading');
} else {
overlay.classList.add('d-none');
overlay.classList.remove('loading');
}
}
},
// 确认对话框
confirm(message) {
return window.confirm(message);
},
// 格式化日期
formatDate(dateString) {
if (!dateString) return '-';
const date = new Date(dateString);
return date.toLocaleDateString('zh-CN');
},
// 格式化日期时间
formatDateTime(dateString) {
if (!dateString) return '-';
const date = new Date(dateString);
return date.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
});
},
// 格式化金额
formatMoney(amount) {
if (amount === null || amount === undefined) return '-';
return '¥' + parseFloat(amount).toFixed(2);
},
// 获取当前用户
getCurrentUser() {
const userStr = localStorage.getItem(STORAGE.USER);
return userStr ? JSON.parse(userStr) : null;
},
// 检查用户角色
hasRole(role) {
const user = this.getCurrentUser();
return user && user.role === role;
},
// 退出登录
logout() {
if (this.confirm('确定要退出登录吗?')) {
localStorage.removeItem(STORAGE.TOKEN);
localStorage.removeItem(STORAGE.USER);
window.location.href = '/login.html';
}
},
// 检查登录状态
checkAuth() {
const token = localStorage.getItem(STORAGE.TOKEN);
if (!token) {
window.location.href = 'login.html';
return false;
}
return true;
},
// 获取状态徽章HTML
getStatusBadge(status, type = 'order') {
const badges = {
order: {
pending: '<span class="badge badge-status pending">待处理</span>',
appointed: '<span class="badge badge-status appointed">已预约</span>',
in_progress: '<span class="badge badge-status in_progress">进行中</span>',
completed: '<span class="badge badge-status completed">已完成</span>',
cancelled: '<span class="badge badge-status cancelled">已取消</span>'
},
payment: {
unpaid: '<span class="badge badge-status unpaid">未支付</span>',
paid: '<span class="badge badge-status paid">已支付</span>',
refunded: '<span class="badge badge-status cancelled">已退款</span>'
},
appointment: {
pending: '<span class="badge badge-status pending">待确认</span>',
confirmed: '<span class="badge badge-status completed">已确认</span>',
completed: '<span class="badge badge-status completed">已完成</span>',
cancelled: '<span class="badge badge-status cancelled">已取消</span>'
}
};
return badges[type]?.[status] || `<span class="badge bg-secondary">${status}</span>`;
},
// 获取服务类型文本
getServiceTypeText(type) {
const types = {
maintenance: '<span class="badge bg-primary">保养维护</span>',
repair: '<span class="badge bg-warning">维修服务</span>',
beauty: '<span class="badge bg-info">美容服务</span>',
insurance: '<span class="badge bg-success">保险代理</span>'
};
return types[type] || type;
},
// 获取角色文本
getRoleText(role) {
const roles = {
admin: '管理员',
staff: '工作人员',
customer: '客户'
};
return roles[role] || role;
},
// 根据角色跳转
redirectToDashboard(role) {
const roleMap = {
'admin': 'admin/dashboard.html',
'staff': 'staff/dashboard.html',
'customer': 'customer/dashboard.html'
};
const url = roleMap[role];
if (url) {
window.location.href = url;
} else {
this.showToast('未知的用户角色', 'error');
}
}
};