641 lines
22 KiB
TypeScript
641 lines
22 KiB
TypeScript
import axios from 'axios';
|
|
import type {
|
|
User,
|
|
EmployeeSerial,
|
|
EmployeeSerialResponse,
|
|
AftersalesOrder,
|
|
AftersalesPublicView,
|
|
AftersalesListFilter,
|
|
AftersalesListResponse,
|
|
CreateAftersalesRequest,
|
|
UpdateAftersalesRequest,
|
|
CustomerConfirmRequest,
|
|
ProjectOrder,
|
|
ProjectOrderPublicView,
|
|
ProjectOrderListFilter,
|
|
ProjectOrderListResponse,
|
|
CreateProjectOrderRequest,
|
|
UpdateProjectOrderRequest,
|
|
ProjectEngineerCompleteRequest,
|
|
CreateUserRequest,
|
|
UpdateUserRequest,
|
|
UserListFilter,
|
|
UserListResponse,
|
|
} from '@/types';
|
|
|
|
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || '/api';
|
|
|
|
const apiClient = axios.create({
|
|
baseURL: API_BASE_URL,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
});
|
|
|
|
apiClient.interceptors.request.use((config) => {
|
|
if (config.data instanceof FormData) {
|
|
delete config.headers['Content-Type'];
|
|
}
|
|
const token = localStorage.getItem('authToken');
|
|
if (token) {
|
|
config.headers.Authorization = `Bearer ${token}`;
|
|
}
|
|
return config;
|
|
});
|
|
|
|
apiClient.interceptors.response.use(
|
|
(response) => response,
|
|
(error) => {
|
|
if (error.response?.status === 401) {
|
|
const url = error.config?.url || '';
|
|
if (!url.includes('/auth/login')) {
|
|
localStorage.removeItem('authToken');
|
|
localStorage.removeItem('currentUser');
|
|
window.location.href = '/login';
|
|
}
|
|
}
|
|
if (error.response?.status === 404) {
|
|
const url = error.config?.url || '';
|
|
if (url.includes('/query')) {
|
|
const customError = new Error('未找到该序列号,请检查输入是否正确');
|
|
customError.name = 'NotFoundError';
|
|
return Promise.reject(customError);
|
|
}
|
|
}
|
|
if (error.response?.data?.error) {
|
|
const customError = new Error(error.response.data.error);
|
|
customError.name = 'ApiError';
|
|
return Promise.reject(customError);
|
|
}
|
|
return Promise.reject(error);
|
|
}
|
|
);
|
|
|
|
export const authApi = {
|
|
login: async (username: string, password: string) => {
|
|
const response = await apiClient.post('/auth/login', { username, password });
|
|
// 后端返回的是 accessToken,前端期望的是 token
|
|
const token = response.data.accessToken || response.data.token;
|
|
const user = response.data.user;
|
|
|
|
if (token && user) {
|
|
localStorage.setItem('authToken', token);
|
|
localStorage.setItem('currentUser', JSON.stringify(user));
|
|
return user;
|
|
}
|
|
throw new Error('登录失败');
|
|
},
|
|
|
|
logout: async () => {
|
|
try {
|
|
await apiClient.post('/auth/logout');
|
|
} catch (error) {
|
|
console.error('Logout error:', error);
|
|
}
|
|
localStorage.removeItem('authToken');
|
|
localStorage.removeItem('currentUser');
|
|
},
|
|
|
|
getCurrentUser: (): User | null => {
|
|
const user = localStorage.getItem('currentUser');
|
|
return user ? JSON.parse(user) : null;
|
|
},
|
|
|
|
updateProfile: async (data: { name?: string; email?: string }) => {
|
|
const response = await apiClient.put('/auth/profile', data);
|
|
if (response.data.user) {
|
|
localStorage.setItem('currentUser', JSON.stringify(response.data.user));
|
|
return response.data.user as User;
|
|
}
|
|
throw new Error('更新资料失败');
|
|
},
|
|
|
|
changePassword: async (currentPassword: string, newPassword: string) => {
|
|
const response = await apiClient.post('/auth/change-password', { currentPassword, newPassword });
|
|
if (response.data.message) {
|
|
return true;
|
|
}
|
|
if (response.data.error) {
|
|
throw new Error(response.data.error);
|
|
}
|
|
throw new Error('修改密码失败');
|
|
},
|
|
};
|
|
|
|
export const serialApi = {
|
|
generate: async (data: {
|
|
companyName: string;
|
|
serialOption: 'auto' | 'custom';
|
|
serialPrefix?: string;
|
|
quantity: number;
|
|
validOption: 'days' | 'date';
|
|
validDays?: number;
|
|
validUntil?: string;
|
|
}) => {
|
|
// 根据后端接口调整参数
|
|
const payload = {
|
|
companyName: data.companyName,
|
|
quantity: data.quantity,
|
|
validDays: data.validOption === 'days' ? data.validDays : undefined,
|
|
serialPrefix: data.serialOption === 'custom' ? data.serialPrefix : undefined,
|
|
};
|
|
|
|
const response = await apiClient.post('/serials/generate', payload);
|
|
if (response.data.serials) {
|
|
return response.data;
|
|
}
|
|
throw new Error(response.data.error || '生成序列号失败');
|
|
},
|
|
|
|
query: async (serialNumber: string) => {
|
|
// 后端路径是正确的: /api/serials/:serialNumber/query
|
|
const response = await apiClient.get(`/serials/${encodeURIComponent(serialNumber)}/query`);
|
|
if (response.data.serial) {
|
|
return response.data.serial;
|
|
}
|
|
throw new Error(response.data.error || '查询序列号失败');
|
|
},
|
|
|
|
list: async (companyId?: number) => {
|
|
let url = '/serials';
|
|
if (companyId) url += `?companyId=${companyId}`;
|
|
const response = await apiClient.get(url);
|
|
if (response.data.data) {
|
|
return response.data.data;
|
|
}
|
|
throw new Error('获取序列号列表失败');
|
|
},
|
|
|
|
delete: async (id: number) => {
|
|
// 后端没有单个删除接口,需要使用企业接口下的删除
|
|
const response = await apiClient.delete(`/serials/${id}`);
|
|
if (response.data) {
|
|
return true;
|
|
}
|
|
throw new Error(response.data.error || '删除序列号失败');
|
|
},
|
|
};
|
|
|
|
export const companyApi = {
|
|
list: async (filter?: { search?: string; status?: 'all' | 'active' | 'expired' }) => {
|
|
let url = '/companies';
|
|
if (filter?.search || filter?.status) {
|
|
const params = new URLSearchParams();
|
|
if (filter.search) params.append('search', filter.search);
|
|
if (filter.status && filter.status !== 'all') params.append('status', filter.status);
|
|
url += `?${params.toString()}`;
|
|
}
|
|
const response = await apiClient.get(url);
|
|
if (response.data.data) {
|
|
return response.data.data;
|
|
}
|
|
throw new Error('获取企业列表失败');
|
|
},
|
|
|
|
get: async (companyName: string) => {
|
|
const response = await apiClient.get(`/companies/${encodeURIComponent(companyName)}`);
|
|
if (response.data.data) {
|
|
return response.data.data;
|
|
}
|
|
throw new Error('获取企业详情失败');
|
|
},
|
|
|
|
delete: async (companyName: string) => {
|
|
const response = await apiClient.delete(`/companies/${encodeURIComponent(companyName)}`);
|
|
if (response.data) {
|
|
return true;
|
|
}
|
|
throw new Error(response.data.error || '删除企业失败');
|
|
},
|
|
};
|
|
|
|
export const dashboardApi = {
|
|
getStats: async () => {
|
|
// 后端路径是 /api/companies/stats/overview
|
|
const response = await apiClient.get('/companies/stats/overview');
|
|
if (response.data.data) {
|
|
const data = response.data.data;
|
|
// 转换数据格式以匹配前端期望
|
|
return {
|
|
totalCompanies: data.overview?.totalCompanies || 0,
|
|
totalSerials: data.overview?.totalSerials || 0,
|
|
totalEmployeeSerials: data.overview?.totalEmployeeSerials || 0,
|
|
activeSerials: data.overview?.activeSerials || 0,
|
|
inactiveSerials: data.overview?.inactiveSerials || 0,
|
|
totalAftersales: data.overview?.totalAftersales || 0,
|
|
pendingConfirmation: data.overview?.pendingConfirmation || 0,
|
|
closedAftersales: data.overview?.closedAftersales || 0,
|
|
rejectedAftersales: data.overview?.rejectedAftersales || 0,
|
|
monthlyData: data.monthlyStats || [],
|
|
recentCompanies: data.recentCompanies?.map((c: any) => ({
|
|
id: c.companyName,
|
|
name: c.companyName,
|
|
status: 'active' as const,
|
|
createdAt: c.lastCreated,
|
|
})) || [],
|
|
recentSerials: data.recentSerials?.map((s: any) => ({
|
|
id: s.serialNumber,
|
|
serialNumber: s.serialNumber,
|
|
companyName: s.companyName,
|
|
status: s.isActive ? 'active' : 'inactive',
|
|
createdAt: s.createdAt,
|
|
type: s.type,
|
|
})) || [],
|
|
recentAftersales: data.recentAftersales || [],
|
|
};
|
|
}
|
|
throw new Error('获取统计数据失败');
|
|
},
|
|
};
|
|
|
|
export const employeeSerialApi = {
|
|
generate: async (data: {
|
|
companyName: string;
|
|
position: string;
|
|
employeeName: string;
|
|
quantity: number;
|
|
serialPrefix?: string;
|
|
}) => {
|
|
const response = await apiClient.post('/employee-serials/generate', data);
|
|
if (response.data.serials) {
|
|
return response.data;
|
|
}
|
|
throw new Error(response.data.error || '生成员工序列号失败');
|
|
},
|
|
|
|
list: async (filter?: { page?: number; limit?: number; search?: string }) => {
|
|
let url = '/employee-serials';
|
|
const params = new URLSearchParams();
|
|
if (filter?.page && filter.page > 1) params.append('page', String(filter.page));
|
|
if (filter?.limit && filter.limit !== 20) params.append('limit', String(filter.limit));
|
|
if (filter?.search) params.append('search', filter.search);
|
|
if (params.toString()) url += `?${params.toString()}`;
|
|
|
|
const response = await apiClient.get(url);
|
|
if (response.data) {
|
|
return response.data as EmployeeSerialResponse;
|
|
}
|
|
throw new Error('获取员工序列号列表失败');
|
|
},
|
|
|
|
query: async (serialNumber: string) => {
|
|
const response = await apiClient.get(`/employee-serials/${encodeURIComponent(serialNumber)}/query`);
|
|
if (response.data.serial) {
|
|
return response.data.serial as EmployeeSerial;
|
|
}
|
|
throw new Error(response.data.error || '查询员工序列号失败');
|
|
},
|
|
|
|
queryAll: async (serialNumber: string) => {
|
|
// 先查企业序列号
|
|
try {
|
|
const companyResponse = await apiClient.get(`/serials/${encodeURIComponent(serialNumber)}/query`);
|
|
if (companyResponse.data.serial) {
|
|
return { type: 'company', data: companyResponse.data.serial };
|
|
}
|
|
} catch (e: any) {
|
|
// 企业序列号不存在,继续查员工序列号
|
|
}
|
|
// 再查员工序列号
|
|
try {
|
|
const employeeResponse = await apiClient.get(`/employee-serials/${encodeURIComponent(serialNumber)}/query`);
|
|
if (employeeResponse.data.serial) {
|
|
return { type: 'employee', data: employeeResponse.data.serial };
|
|
}
|
|
} catch (e: any) {
|
|
throw new Error('序列号不存在');
|
|
}
|
|
throw new Error('序列号不存在');
|
|
},
|
|
|
|
generateQrCode: async (serialNumber: string, baseUrl?: string) => {
|
|
const response = await apiClient.post(`/employee-serials/${encodeURIComponent(serialNumber)}/qrcode`, {
|
|
baseUrl,
|
|
});
|
|
if (response.data.qrCodeData) {
|
|
return response.data;
|
|
}
|
|
throw new Error(response.data.error || '生成二维码失败');
|
|
},
|
|
|
|
update: async (serialNumber: string, data: {
|
|
companyName?: string;
|
|
position?: string;
|
|
employeeName?: string;
|
|
isActive?: boolean;
|
|
}) => {
|
|
const response = await apiClient.put(`/employee-serials/${encodeURIComponent(serialNumber)}`, data);
|
|
if (response.data.serial) {
|
|
return response.data.serial as EmployeeSerial;
|
|
}
|
|
throw new Error(response.data.error || '更新员工序列号失败');
|
|
},
|
|
|
|
revoke: async (serialNumber: string) => {
|
|
const response = await apiClient.post(`/employee-serials/${encodeURIComponent(serialNumber)}/revoke`);
|
|
if (response.data.message) {
|
|
return true;
|
|
}
|
|
throw new Error(response.data.error || '吊销员工序列号失败');
|
|
},
|
|
|
|
delete: async (serialNumber: string) => {
|
|
const response = await apiClient.delete(`/employee-serials/${encodeURIComponent(serialNumber)}`);
|
|
if (response.data.message) {
|
|
return true;
|
|
}
|
|
throw new Error(response.data.error || '删除员工序列号失败');
|
|
},
|
|
};
|
|
|
|
export const aftersalesApi = {
|
|
create: async (data: CreateAftersalesRequest) => {
|
|
const response = await apiClient.post('/aftersales', data);
|
|
if (response.data.order) {
|
|
return response.data.order as AftersalesOrder;
|
|
}
|
|
throw new Error(response.data.error || '创建工单失败');
|
|
},
|
|
|
|
list: async (filter?: AftersalesListFilter) => {
|
|
const params = new URLSearchParams();
|
|
if (filter?.page && filter.page > 1) params.append('page', String(filter.page));
|
|
if (filter?.limit && filter.limit !== 20) params.append('limit', String(filter.limit));
|
|
if (filter?.search) params.append('search', filter.search);
|
|
if (filter?.workOrderStatus) params.append('workOrderStatus', filter.workOrderStatus);
|
|
if (filter?.serviceType) params.append('serviceType', filter.serviceType);
|
|
if (filter?.technicianId) params.append('technicianId', String(filter.technicianId));
|
|
if (filter?.mine) params.append('mine', 'true');
|
|
|
|
const url = params.toString() ? `/aftersales?${params.toString()}` : '/aftersales';
|
|
const response = await apiClient.get(url);
|
|
if (response.data) {
|
|
return response.data as AftersalesListResponse;
|
|
}
|
|
throw new Error('获取售后工单列表失败');
|
|
},
|
|
|
|
get: async (serialNumber: string) => {
|
|
const response = await apiClient.get(`/aftersales/${encodeURIComponent(serialNumber)}`);
|
|
if (response.data.order) {
|
|
return response.data.order as AftersalesOrder;
|
|
}
|
|
throw new Error(response.data.error || '查询工单失败');
|
|
},
|
|
|
|
update: async (serialNumber: string, data: UpdateAftersalesRequest) => {
|
|
const response = await apiClient.patch(`/aftersales/${encodeURIComponent(serialNumber)}`, data);
|
|
if (response.data.order) {
|
|
return response.data.order as AftersalesOrder;
|
|
}
|
|
throw new Error(response.data.error || '更新工单失败');
|
|
},
|
|
|
|
submit: async (serialNumber: string, resolutionNote: string) => {
|
|
const response = await apiClient.post(`/aftersales/${encodeURIComponent(serialNumber)}/submit`, {
|
|
resolutionNote,
|
|
});
|
|
if (response.data.order) {
|
|
return response.data.order as AftersalesOrder;
|
|
}
|
|
throw new Error(response.data.error || '提交客户确认失败');
|
|
},
|
|
|
|
generateQrCode: async (serialNumber: string, baseUrl?: string) => {
|
|
const response = await apiClient.post(`/aftersales/${encodeURIComponent(serialNumber)}/qrcode`, {
|
|
baseUrl,
|
|
});
|
|
if (response.data.qrCodeData) {
|
|
return response.data as { qrCodeData: string; queryUrl: string };
|
|
}
|
|
throw new Error(response.data.error || '生成二维码失败');
|
|
},
|
|
|
|
reassign: async (serialNumber: string, technicianId: number) => {
|
|
const response = await apiClient.post(`/aftersales/${encodeURIComponent(serialNumber)}/reassign`, {
|
|
technicianId,
|
|
});
|
|
if (response.data.order) {
|
|
return response.data.order as AftersalesOrder;
|
|
}
|
|
throw new Error(response.data.error || '重新分配失败');
|
|
},
|
|
|
|
forceClose: async (serialNumber: string) => {
|
|
const response = await apiClient.post(`/aftersales/${encodeURIComponent(serialNumber)}/force-close`);
|
|
if (response.data.order) {
|
|
return response.data.order as AftersalesOrder;
|
|
}
|
|
throw new Error(response.data.error || '强制关闭失败');
|
|
},
|
|
|
|
delete: async (serialNumber: string) => {
|
|
const response = await apiClient.delete(`/aftersales/${encodeURIComponent(serialNumber)}`);
|
|
if (response.data.message) {
|
|
return true;
|
|
}
|
|
throw new Error(response.data.error || '删除工单失败');
|
|
},
|
|
|
|
publicQuery: async (serialNumber: string) => {
|
|
const response = await apiClient.get(`/aftersales/${encodeURIComponent(serialNumber)}/query`);
|
|
if (response.data.order) {
|
|
return response.data.order as AftersalesPublicView;
|
|
}
|
|
throw new Error(response.data.error || '查询工单失败');
|
|
},
|
|
|
|
customerConfirm: async (serialNumber: string, data: CustomerConfirmRequest) => {
|
|
const response = await apiClient.post(`/aftersales/${encodeURIComponent(serialNumber)}/confirm`, data);
|
|
if (response.data.order) {
|
|
return response.data.order as AftersalesPublicView;
|
|
}
|
|
throw new Error(response.data.error || '提交确认失败');
|
|
},
|
|
|
|
uploadSiteImages: async (serialNumber: string, files: File[]) => {
|
|
const formData = new FormData();
|
|
files.forEach((file) => formData.append('files', file));
|
|
const response = await apiClient.post(
|
|
`/aftersales/${encodeURIComponent(serialNumber)}/site-images`,
|
|
formData,
|
|
);
|
|
if (response.data.siteImages) {
|
|
return response.data.siteImages as string[];
|
|
}
|
|
throw new Error(response.data.error || '上传现场图片失败');
|
|
},
|
|
};
|
|
|
|
export const projectOrdersApi = {
|
|
create: async (data: CreateProjectOrderRequest) => {
|
|
const response = await apiClient.post('/project-orders', data);
|
|
if (response.data.order) {
|
|
return response.data.order as ProjectOrder;
|
|
}
|
|
throw new Error(response.data.error || '创建项目工单失败');
|
|
},
|
|
|
|
list: async (filter?: ProjectOrderListFilter) => {
|
|
const params = new URLSearchParams();
|
|
if (filter?.page && filter.page > 1) params.append('page', String(filter.page));
|
|
if (filter?.limit && filter.limit !== 20) params.append('limit', String(filter.limit));
|
|
if (filter?.search) params.append('search', filter.search);
|
|
if (filter?.workOrderStatus) params.append('workOrderStatus', filter.workOrderStatus);
|
|
if (filter?.projectType) params.append('serviceType', filter.projectType);
|
|
if (filter?.technicianId) params.append('technicianId', String(filter.technicianId));
|
|
if (filter?.mine) params.append('mine', 'true');
|
|
|
|
const url = params.toString() ? `/project-orders?${params.toString()}` : '/project-orders';
|
|
const response = await apiClient.get(url);
|
|
if (response.data) {
|
|
return response.data as ProjectOrderListResponse;
|
|
}
|
|
throw new Error('获取项目工单列表失败');
|
|
},
|
|
|
|
get: async (serialNumber: string) => {
|
|
const response = await apiClient.get(`/project-orders/${encodeURIComponent(serialNumber)}`);
|
|
if (response.data.order) {
|
|
return response.data.order as ProjectOrder;
|
|
}
|
|
throw new Error(response.data.error || '查询项目工单失败');
|
|
},
|
|
|
|
update: async (serialNumber: string, data: UpdateProjectOrderRequest) => {
|
|
const response = await apiClient.patch(`/project-orders/${encodeURIComponent(serialNumber)}`, data);
|
|
if (response.data.order) {
|
|
return response.data.order as ProjectOrder;
|
|
}
|
|
throw new Error(response.data.error || '更新项目工单失败');
|
|
},
|
|
|
|
submit: async (serialNumber: string, completionNote: string) => {
|
|
const response = await apiClient.post(`/project-orders/${encodeURIComponent(serialNumber)}/submit`, {
|
|
completionNote,
|
|
});
|
|
if (response.data.order) {
|
|
return response.data.order as ProjectOrder;
|
|
}
|
|
throw new Error(response.data.error || '提交完成资料失败');
|
|
},
|
|
|
|
generateQrCode: async (serialNumber: string, baseUrl?: string) => {
|
|
const response = await apiClient.post(`/project-orders/${encodeURIComponent(serialNumber)}/qrcode`, {
|
|
baseUrl,
|
|
});
|
|
if (response.data.qrCodeData) {
|
|
return response.data as { qrCodeData: string; queryUrl: string };
|
|
}
|
|
throw new Error(response.data.error || '生成二维码失败');
|
|
},
|
|
|
|
reassign: async (serialNumber: string, technicianId: number) => {
|
|
const response = await apiClient.post(`/project-orders/${encodeURIComponent(serialNumber)}/reassign`, {
|
|
technicianId,
|
|
});
|
|
if (response.data.order) {
|
|
return response.data.order as ProjectOrder;
|
|
}
|
|
throw new Error(response.data.error || '重新分配失败');
|
|
},
|
|
|
|
forceClose: async (serialNumber: string) => {
|
|
const response = await apiClient.post(`/project-orders/${encodeURIComponent(serialNumber)}/force-close`);
|
|
if (response.data.order) {
|
|
return response.data.order as ProjectOrder;
|
|
}
|
|
throw new Error(response.data.error || '确认完成失败');
|
|
},
|
|
|
|
delete: async (serialNumber: string) => {
|
|
const response = await apiClient.delete(`/project-orders/${encodeURIComponent(serialNumber)}`);
|
|
if (response.data.message) {
|
|
return true;
|
|
}
|
|
throw new Error(response.data.error || '删除项目工单失败');
|
|
},
|
|
|
|
publicQuery: async (serialNumber: string) => {
|
|
const response = await apiClient.get(`/project-orders/${encodeURIComponent(serialNumber)}/query`);
|
|
if (response.data.order) {
|
|
return response.data.order as ProjectOrderPublicView;
|
|
}
|
|
throw new Error(response.data.error || '查询项目工单失败');
|
|
},
|
|
|
|
complete: async (serialNumber: string, data: ProjectEngineerCompleteRequest) => {
|
|
const response = await apiClient.post(`/project-orders/${encodeURIComponent(serialNumber)}/complete`, data);
|
|
if (response.data.order) {
|
|
return response.data.order as ProjectOrderPublicView;
|
|
}
|
|
throw new Error(response.data.error || '提交完成失败');
|
|
},
|
|
|
|
uploadSiteImages: async (serialNumber: string, files: File[]) => {
|
|
const formData = new FormData();
|
|
files.forEach((file) => formData.append('files', file));
|
|
const response = await apiClient.post(
|
|
`/project-orders/${encodeURIComponent(serialNumber)}/site-images`,
|
|
formData,
|
|
);
|
|
if (response.data.siteImages) {
|
|
return response.data.siteImages as string[];
|
|
}
|
|
throw new Error(response.data.error || '上传现场图片失败');
|
|
},
|
|
};
|
|
|
|
export const usersApi = {
|
|
assignable: async () => {
|
|
const response = await apiClient.get('/users/assignable');
|
|
return (response.data?.data || []) as User[];
|
|
},
|
|
};
|
|
|
|
export const employeesApi = {
|
|
list: async (filter?: UserListFilter) => {
|
|
const params = new URLSearchParams();
|
|
if (filter?.page && filter.page > 1) params.append('page', String(filter.page));
|
|
if (filter?.limit && filter.limit !== 20) params.append('limit', String(filter.limit));
|
|
if (filter?.role) params.append('role', filter.role);
|
|
if (filter?.search) params.append('search', filter.search);
|
|
|
|
const url = params.toString() ? `/employees?${params.toString()}` : '/employees';
|
|
const response = await apiClient.get(url);
|
|
return response.data as UserListResponse;
|
|
},
|
|
|
|
create: async (data: CreateUserRequest) => {
|
|
const response = await apiClient.post('/employees', data);
|
|
if (response.data.employee) {
|
|
return response.data.employee as User;
|
|
}
|
|
throw new Error(response.data.error || '创建员工失败');
|
|
},
|
|
|
|
update: async (id: number, data: UpdateUserRequest) => {
|
|
const response = await apiClient.patch(`/employees/${id}`, data);
|
|
if (response.data.employee) {
|
|
return response.data.employee as User;
|
|
}
|
|
throw new Error(response.data.error || '更新员工失败');
|
|
},
|
|
|
|
resetPassword: async (id: number, newPassword: string) => {
|
|
const response = await apiClient.post(`/employees/${id}/reset-password`, { newPassword });
|
|
if (response.data.message) {
|
|
return true;
|
|
}
|
|
throw new Error(response.data.error || '重置密码失败');
|
|
},
|
|
|
|
delete: async (id: number) => {
|
|
const response = await apiClient.delete(`/employees/${id}`);
|
|
if (response.data.message) {
|
|
return true;
|
|
}
|
|
throw new Error(response.data.error || '删除员工失败');
|
|
},
|
|
};
|