R45 A2-A7 员工附件与培训证书管理
这个提交包含在:
+146
-1
@@ -1,9 +1,12 @@
|
||||
import { apiRequestData } from "./http";
|
||||
import { apiRequestBlob, apiRequestData, type ApiBlobResponse } from "./http";
|
||||
|
||||
export type EmployeeStatus = "active" | "archived";
|
||||
export type EmployeeEmploymentStatus = "onboarding" | "probation" | "active" | "offboarding" | "inactive";
|
||||
export type EmployeeContractType = "labor" | "nda" | "non_compete" | "internship";
|
||||
export type EmployeeContractStatus = "active" | "expired" | "terminated";
|
||||
export type EmployeeTrainingType = "internal" | "external" | "online";
|
||||
export type EmployeeTrainingStatus = "planned" | "in_progress" | "completed" | "cancelled";
|
||||
export type EmployeeCertificateStatus = "valid" | "expired";
|
||||
|
||||
export type EmployeeDepartmentSummary = {
|
||||
id: string;
|
||||
@@ -87,6 +90,7 @@ export type EmployeeContract = {
|
||||
endDate: string | null;
|
||||
terminatedDate: string | null;
|
||||
attachmentPath: string | null;
|
||||
attachmentUrl: string | null;
|
||||
status: EmployeeContractStatus;
|
||||
createdAt: string | null;
|
||||
createdBy: string | null;
|
||||
@@ -94,6 +98,37 @@ export type EmployeeContract = {
|
||||
updatedBy: string | null;
|
||||
};
|
||||
|
||||
export type EmployeeTraining = {
|
||||
id: string;
|
||||
employeeId: string;
|
||||
name: string;
|
||||
trainingType: EmployeeTrainingType;
|
||||
startDate: string | null;
|
||||
endDate: string | null;
|
||||
status: EmployeeTrainingStatus;
|
||||
notes: string | null;
|
||||
createdAt: string | null;
|
||||
createdBy: string | null;
|
||||
updatedAt: string | null;
|
||||
updatedBy: string | null;
|
||||
};
|
||||
|
||||
export type EmployeeCertificate = {
|
||||
id: string;
|
||||
employeeId: string;
|
||||
name: string;
|
||||
issuer: string;
|
||||
obtainedDate: string | null;
|
||||
expiryDate: string | null;
|
||||
certificateNo: string | null;
|
||||
attachmentPath: string | null;
|
||||
status: EmployeeCertificateStatus;
|
||||
createdAt: string | null;
|
||||
createdBy: string | null;
|
||||
updatedAt: string | null;
|
||||
updatedBy: string | null;
|
||||
};
|
||||
|
||||
export type OrganizationTreeNode = {
|
||||
id: string;
|
||||
employeeNo: string;
|
||||
@@ -209,6 +244,12 @@ export type EmployeeStatsResponse = {
|
||||
dateTo: string;
|
||||
count: number;
|
||||
};
|
||||
certificateSummary: {
|
||||
dateFrom: string;
|
||||
dateTo: string;
|
||||
validHolderCount: number;
|
||||
expiringSoonCount: number;
|
||||
};
|
||||
};
|
||||
|
||||
export type BatchTransferDepartmentPayload = {
|
||||
@@ -255,6 +296,12 @@ export async function uploadEmployeeAvatar(employeeId: string, file: File) {
|
||||
});
|
||||
}
|
||||
|
||||
export async function deleteEmployeeAvatar(employeeId: string) {
|
||||
return apiRequestData<{ employeeId: string; avatarUrl: string | null }>(`/api/employees/${employeeId}/avatar`, {
|
||||
method: "DELETE",
|
||||
});
|
||||
}
|
||||
|
||||
export async function patchEmployeeProfile(
|
||||
employeeId: string,
|
||||
payload: Partial<{
|
||||
@@ -373,6 +420,104 @@ export async function patchEmployeeContract(
|
||||
});
|
||||
}
|
||||
|
||||
export async function uploadEmployeeContractAttachment(employeeId: string, contractId: string, file: File) {
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
|
||||
return apiRequestData<EmployeeContract>(`/api/employees/${employeeId}/contracts/${contractId}/attachment`, {
|
||||
method: "PUT",
|
||||
body: formData,
|
||||
});
|
||||
}
|
||||
|
||||
export async function downloadEmployeeContractAttachment(attachmentUrl: string): Promise<ApiBlobResponse> {
|
||||
return apiRequestBlob(attachmentUrl);
|
||||
}
|
||||
|
||||
export async function deleteEmployeeContract(employeeId: string, contractId: string) {
|
||||
return apiRequestData<{ contractId: string; deleted: boolean }>(`/api/employees/${employeeId}/contracts/${contractId}`, {
|
||||
method: "DELETE",
|
||||
});
|
||||
}
|
||||
|
||||
export async function fetchEmployeeTrainings(employeeId: string) {
|
||||
return apiRequestData<{ items: EmployeeTraining[] }>(`/api/employees/${employeeId}/trainings`);
|
||||
}
|
||||
|
||||
export async function createEmployeeTraining(
|
||||
employeeId: string,
|
||||
payload: {
|
||||
name: string;
|
||||
trainingType: EmployeeTrainingType;
|
||||
startDate: string;
|
||||
endDate?: string | null;
|
||||
status: EmployeeTrainingStatus;
|
||||
notes?: string | null;
|
||||
},
|
||||
) {
|
||||
return apiRequestData<EmployeeTraining>(`/api/employees/${employeeId}/trainings`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
|
||||
export async function patchEmployeeTraining(
|
||||
employeeId: string,
|
||||
trainingId: string,
|
||||
payload: Partial<{
|
||||
name: string;
|
||||
trainingType: EmployeeTrainingType;
|
||||
startDate: string;
|
||||
endDate: string | null;
|
||||
status: EmployeeTrainingStatus;
|
||||
notes: string | null;
|
||||
}>,
|
||||
) {
|
||||
return apiRequestData<EmployeeTraining>(`/api/employees/${employeeId}/trainings/${trainingId}`, {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
|
||||
export async function fetchEmployeeCertificates(employeeId: string) {
|
||||
return apiRequestData<{ items: EmployeeCertificate[] }>(`/api/employees/${employeeId}/certificates`);
|
||||
}
|
||||
|
||||
export async function createEmployeeCertificate(
|
||||
employeeId: string,
|
||||
payload: {
|
||||
name: string;
|
||||
issuer: string;
|
||||
obtainedDate: string;
|
||||
expiryDate?: string | null;
|
||||
certificateNo?: string | null;
|
||||
attachmentPath?: string | null;
|
||||
},
|
||||
) {
|
||||
return apiRequestData<EmployeeCertificate>(`/api/employees/${employeeId}/certificates`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
|
||||
export async function patchEmployeeCertificate(
|
||||
employeeId: string,
|
||||
certificateId: string,
|
||||
payload: Partial<{
|
||||
name: string;
|
||||
issuer: string;
|
||||
obtainedDate: string;
|
||||
expiryDate: string | null;
|
||||
certificateNo: string | null;
|
||||
attachmentPath: string | null;
|
||||
}>,
|
||||
) {
|
||||
return apiRequestData<EmployeeCertificate>(`/api/employees/${employeeId}/certificates/${certificateId}`, {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
|
||||
export async function completeEmployeeChecklistTask(employeeId: string, taskId: string) {
|
||||
return apiRequestData<EmployeeProfile["lifecycle"]>(`/api/employees/${employeeId}/checklist-tasks/${taskId}/complete`, {
|
||||
method: "POST",
|
||||
|
||||
在新工单中引用
屏蔽一个用户