feat: 完成 R13/R14/R15/R16 小团队管理核心能力
这个提交包含在:
@@ -24,6 +24,79 @@ export type EmployeeListResponse = {
|
||||
items: EmployeeSummary[];
|
||||
};
|
||||
|
||||
export type EmployeeLifecycleEvent = {
|
||||
id: string;
|
||||
employeeId: string;
|
||||
eventType: "onboard" | "regularize" | "transfer" | "offboard";
|
||||
effectiveDate: string | null;
|
||||
payloadJson: Record<string, unknown> | null;
|
||||
createdAt: string | null;
|
||||
createdBy: string | null;
|
||||
};
|
||||
|
||||
export type EmployeeChecklistTask = {
|
||||
id: string;
|
||||
employeeId: string;
|
||||
scene: "onboarding" | "offboarding" | "transfer";
|
||||
taskType:
|
||||
| "account_setup"
|
||||
| "asset_issue"
|
||||
| "policy_ack"
|
||||
| "asset_return"
|
||||
| "access_revoke"
|
||||
| "expense_clearance"
|
||||
| "handover_note";
|
||||
title: string;
|
||||
status: "pending" | "completed" | "skipped";
|
||||
dueDate: string | null;
|
||||
completedAt: string | null;
|
||||
completedBy: string | null;
|
||||
payloadJson: Record<string, unknown> | null;
|
||||
createdAt: string | null;
|
||||
};
|
||||
|
||||
export type EmployeeProfile = {
|
||||
employee: {
|
||||
id: string;
|
||||
employeeNo: string;
|
||||
name: string;
|
||||
phone: string;
|
||||
email: string;
|
||||
status: EmployeeStatus;
|
||||
employmentStatus: "onboarding" | "probation" | "active" | "offboarding" | "inactive";
|
||||
departmentId: string;
|
||||
title: string;
|
||||
directManagerId: string | null;
|
||||
hireDate: string | null;
|
||||
probationEndDate: string | null;
|
||||
lastWorkingDate: string | null;
|
||||
workLocation: string | null;
|
||||
emergencyContactName: string | null;
|
||||
emergencyContactPhone: string | null;
|
||||
notes: string | null;
|
||||
archivedAt: string | null;
|
||||
roleCodes: string[];
|
||||
department: { id: string; name: string } | null;
|
||||
directManager: { id: string; employeeNo: string; name: string } | null;
|
||||
};
|
||||
lifecycle: {
|
||||
events: EmployeeLifecycleEvent[];
|
||||
checklistTasks: EmployeeChecklistTask[];
|
||||
blockers: {
|
||||
openAssetCount: number;
|
||||
pendingWorkflowTaskCount: number;
|
||||
canCompleteOffboarding: boolean;
|
||||
};
|
||||
};
|
||||
assignedAssets: Array<{
|
||||
id: string;
|
||||
assetNo: string;
|
||||
name: string;
|
||||
status: string;
|
||||
location: string | null;
|
||||
}>;
|
||||
};
|
||||
|
||||
export async function fetchEmployees(params: {
|
||||
page: number;
|
||||
pageSize: number;
|
||||
@@ -39,3 +112,90 @@ export async function fetchEmployees(params: {
|
||||
return apiRequestData<EmployeeListResponse>(`/api/employees?${search.toString()}`);
|
||||
}
|
||||
|
||||
export async function fetchEmployeeProfile(employeeId: string) {
|
||||
return apiRequestData<EmployeeProfile>(`/api/employees/${employeeId}/profile`);
|
||||
}
|
||||
|
||||
export async function patchEmployeeProfile(
|
||||
employeeId: string,
|
||||
payload: Partial<{
|
||||
departmentId: string;
|
||||
directManagerId: string | null;
|
||||
title: string;
|
||||
probationEndDate: string | null;
|
||||
lastWorkingDate: string | null;
|
||||
workLocation: string | null;
|
||||
emergencyContactName: string | null;
|
||||
emergencyContactPhone: string | null;
|
||||
notes: string | null;
|
||||
}>,
|
||||
) {
|
||||
return apiRequestData<EmployeeProfile>(`/api/employees/${employeeId}/profile`, {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
|
||||
export async function startEmployeeOnboarding(
|
||||
employeeId: string,
|
||||
payload: { effectiveDate?: string; probationEndDate?: string | null; notes?: string | null } = {},
|
||||
) {
|
||||
return apiRequestData<EmployeeProfile>(`/api/employees/${employeeId}/onboarding/start`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
|
||||
export async function regularizeEmployee(
|
||||
employeeId: string,
|
||||
payload: { effectiveDate?: string; notes?: string | null } = {},
|
||||
) {
|
||||
return apiRequestData<EmployeeProfile>(`/api/employees/${employeeId}/regularize`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
|
||||
export async function transferEmployee(
|
||||
employeeId: string,
|
||||
payload: {
|
||||
effectiveDate?: string;
|
||||
departmentId?: string;
|
||||
directManagerId?: string | null;
|
||||
title?: string;
|
||||
notes?: string | null;
|
||||
} = {},
|
||||
) {
|
||||
return apiRequestData<EmployeeProfile>(`/api/employees/${employeeId}/transfer`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
|
||||
export async function startEmployeeOffboarding(
|
||||
employeeId: string,
|
||||
payload: { effectiveDate?: string; lastWorkingDate?: string | null; notes?: string | null } = {},
|
||||
) {
|
||||
return apiRequestData<EmployeeProfile>(`/api/employees/${employeeId}/offboarding/start`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
|
||||
export async function fetchEmployeeLifecycle(employeeId: string) {
|
||||
return apiRequestData<EmployeeProfile["lifecycle"]>(`/api/employees/${employeeId}/lifecycle`);
|
||||
}
|
||||
|
||||
export async function completeEmployeeChecklistTask(employeeId: string, taskId: string) {
|
||||
return apiRequestData<EmployeeProfile["lifecycle"]>(`/api/employees/${employeeId}/checklist-tasks/${taskId}/complete`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
}
|
||||
|
||||
export async function skipEmployeeChecklistTask(employeeId: string, taskId: string) {
|
||||
return apiRequestData<EmployeeProfile["lifecycle"]>(`/api/employees/${employeeId}/checklist-tasks/${taskId}/skip`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
}
|
||||
|
||||
在新工单中引用
屏蔽一个用户