A1/A3/A5/A7/A8 完成员工头像前端、组织架构页与QA回填
这个提交包含在:
+104
-3
@@ -1,6 +1,13 @@
|
||||
import { apiRequestData } from "./http";
|
||||
|
||||
export type EmployeeStatus = "active" | "archived";
|
||||
export type EmployeeContractType = "labor" | "nda" | "non_compete" | "internship";
|
||||
export type EmployeeContractStatus = "active" | "expired" | "terminated";
|
||||
|
||||
export type EmployeeDepartmentSummary = {
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export type EmployeeSummary = {
|
||||
id: string;
|
||||
@@ -12,6 +19,7 @@ export type EmployeeSummary = {
|
||||
departmentId: string;
|
||||
directManagerId: string | null;
|
||||
title: string;
|
||||
avatarUrl: string | null;
|
||||
roleCodes: string[];
|
||||
createdAt: string | null;
|
||||
updatedAt: string | null;
|
||||
@@ -61,7 +69,46 @@ export type EmployeeOrganizationNode = {
|
||||
name: string;
|
||||
title: string;
|
||||
status: EmployeeStatus;
|
||||
department: { id: string; name: string } | null;
|
||||
avatarUrl: string | null;
|
||||
department: EmployeeDepartmentSummary | null;
|
||||
};
|
||||
|
||||
export type EmployeeContract = {
|
||||
id: string;
|
||||
employeeId: string;
|
||||
contractNo: string;
|
||||
contractType: EmployeeContractType;
|
||||
startDate: string | null;
|
||||
endDate: string | null;
|
||||
terminatedDate: string | null;
|
||||
attachmentPath: string | null;
|
||||
status: EmployeeContractStatus;
|
||||
createdAt: string | null;
|
||||
createdBy: string | null;
|
||||
updatedAt: string | null;
|
||||
updatedBy: string | null;
|
||||
};
|
||||
|
||||
export type OrganizationTreeNode = {
|
||||
id: string;
|
||||
employeeNo: string;
|
||||
name: string;
|
||||
title: string;
|
||||
status: EmployeeStatus;
|
||||
avatarUrl: string | null;
|
||||
department: EmployeeDepartmentSummary | null;
|
||||
externalManager: {
|
||||
id: string;
|
||||
employeeNo: string;
|
||||
name: string;
|
||||
department: EmployeeDepartmentSummary | null;
|
||||
} | null;
|
||||
children: OrganizationTreeNode[];
|
||||
};
|
||||
|
||||
export type OrganizationDepartmentSection = {
|
||||
department: EmployeeDepartmentSummary | null;
|
||||
roots: OrganizationTreeNode[];
|
||||
};
|
||||
|
||||
export type EmployeeProfile = {
|
||||
@@ -83,10 +130,11 @@ export type EmployeeProfile = {
|
||||
emergencyContactName: string | null;
|
||||
emergencyContactPhone: string | null;
|
||||
notes: string | null;
|
||||
avatarUrl: string | null;
|
||||
archivedAt: string | null;
|
||||
roleCodes: string[];
|
||||
department: { id: string; name: string } | null;
|
||||
directManager: { id: string; employeeNo: string; name: string } | null;
|
||||
department: EmployeeDepartmentSummary | null;
|
||||
directManager: { id: string; employeeNo: string; name: string; avatarUrl: string | null } | null;
|
||||
};
|
||||
lifecycle: {
|
||||
events: EmployeeLifecycleEvent[];
|
||||
@@ -131,6 +179,16 @@ export async function fetchEmployeeProfile(employeeId: string) {
|
||||
return apiRequestData<EmployeeProfile>(`/api/employees/${employeeId}/profile`);
|
||||
}
|
||||
|
||||
export async function uploadEmployeeAvatar(employeeId: string, file: File) {
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
|
||||
return apiRequestData<{ employeeId: string; avatarUrl: string | null }>(`/api/employees/${employeeId}/avatar`, {
|
||||
method: "PUT",
|
||||
body: formData,
|
||||
});
|
||||
}
|
||||
|
||||
export async function patchEmployeeProfile(
|
||||
employeeId: string,
|
||||
payload: Partial<{
|
||||
@@ -202,6 +260,49 @@ export async function fetchEmployeeLifecycle(employeeId: string) {
|
||||
return apiRequestData<EmployeeProfile["lifecycle"]>(`/api/employees/${employeeId}/lifecycle`);
|
||||
}
|
||||
|
||||
export async function fetchEmployeeOrganization() {
|
||||
return apiRequestData<{ items: OrganizationDepartmentSection[] }>("/api/employees/organization");
|
||||
}
|
||||
|
||||
export async function fetchEmployeeContracts(employeeId: string) {
|
||||
return apiRequestData<{ items: EmployeeContract[] }>(`/api/employees/${employeeId}/contracts`);
|
||||
}
|
||||
|
||||
export async function createEmployeeContract(
|
||||
employeeId: string,
|
||||
payload: {
|
||||
contractNo: string;
|
||||
contractType: EmployeeContractType;
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
terminatedDate?: string | null;
|
||||
attachmentPath?: string | null;
|
||||
},
|
||||
) {
|
||||
return apiRequestData<EmployeeContract>(`/api/employees/${employeeId}/contracts`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
|
||||
export async function patchEmployeeContract(
|
||||
employeeId: string,
|
||||
contractId: string,
|
||||
payload: Partial<{
|
||||
contractNo: string;
|
||||
contractType: EmployeeContractType;
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
terminatedDate: string | null;
|
||||
attachmentPath: string | null;
|
||||
}>,
|
||||
) {
|
||||
return apiRequestData<EmployeeContract>(`/api/employees/${employeeId}/contracts/${contractId}`, {
|
||||
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",
|
||||
|
||||
@@ -21,6 +21,7 @@ export type PresenceEmployee = {
|
||||
employeeNo: string;
|
||||
name: string;
|
||||
title: string;
|
||||
avatarUrl: string | null;
|
||||
employmentStatus: string;
|
||||
department: { id: string; name: string } | null;
|
||||
};
|
||||
|
||||
在新工单中引用
屏蔽一个用户