R44 A2-A8 完成员工高级筛选批量操作与统计页

这个提交包含在:
2026-03-29 12:27:44 +08:00
父节点 c3873999c2
当前提交 d11f5593d1
共修改 17 个文件,包含 1640 行新增和 337 行删除
+101 -3
查看文件
@@ -1,6 +1,7 @@
import { apiRequestData } 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";
@@ -17,8 +18,12 @@ export type EmployeeSummary = {
email: string;
status: EmployeeStatus;
departmentId: string;
department: EmployeeDepartmentSummary | null;
directManagerId: string | null;
directManager: { id: string; employeeNo: string; name: string } | null;
title: string;
employmentStatus: EmployeeEmploymentStatus | null;
hireDate: string | null;
avatarUrl: string | null;
roleCodes: string[];
createdAt: string | null;
@@ -119,7 +124,7 @@ export type EmployeeProfile = {
phone: string;
email: string;
status: EmployeeStatus;
employmentStatus: "onboarding" | "probation" | "active" | "offboarding" | "inactive";
employmentStatus: EmployeeEmploymentStatus;
departmentId: string;
title: string;
directManagerId: string | null;
@@ -158,19 +163,80 @@ export type EmployeeProfile = {
};
};
export async function fetchEmployees(params: {
export type FetchEmployeesParams = {
page: number;
pageSize: number;
status?: EmployeeStatus;
departmentId?: string;
q?: string;
}) {
title?: string;
managerId?: string;
hireDateFrom?: string;
hireDateTo?: string;
employmentStatus?: EmployeeEmploymentStatus;
};
export type BatchOperationResult = {
summary: {
total: number;
updated: number;
};
employeeIds: string[];
};
export type EmployeeStatsResponse = {
asOfDate: string;
employmentStatusSummary: {
total: number;
items: Array<{
status: EmployeeEmploymentStatus;
count: number;
}>;
};
departmentHeadcount: Array<{
departmentId: string;
departmentName: string;
count: number;
}>;
recentMovements: {
dateFrom: string;
dateTo: string;
hires: number;
departures: number;
};
expiringContracts: {
dateFrom: string;
dateTo: string;
count: number;
};
};
export type BatchTransferDepartmentPayload = {
employeeIds: string[];
departmentId: string;
};
export type BatchToggleUsersPayload = {
employeeIds: string[];
};
export type BatchSetManagerPayload = {
employeeIds: string[];
managerId: string;
};
export async function fetchEmployees(params: FetchEmployeesParams) {
const search = new URLSearchParams();
search.set("page", String(params.page));
search.set("pageSize", String(params.pageSize));
if (params.status) search.set("status", params.status);
if (params.departmentId) search.set("departmentId", params.departmentId);
if (params.q) search.set("q", params.q);
if (params.title) search.set("title", params.title);
if (params.managerId) search.set("managerId", params.managerId);
if (params.hireDateFrom) search.set("hireDateFrom", params.hireDateFrom);
if (params.hireDateTo) search.set("hireDateTo", params.hireDateTo);
if (params.employmentStatus) search.set("employmentStatus", params.employmentStatus);
return apiRequestData<EmployeeListResponse>(`/api/employees?${search.toString()}`);
}
@@ -264,6 +330,10 @@ export async function fetchEmployeeOrganization() {
return apiRequestData<{ items: OrganizationDepartmentSection[] }>("/api/employees/organization");
}
export async function fetchEmployeeStats() {
return apiRequestData<EmployeeStatsResponse>("/api/employees/stats");
}
export async function fetchEmployeeContracts(employeeId: string) {
return apiRequestData<{ items: EmployeeContract[] }>(`/api/employees/${employeeId}/contracts`);
}
@@ -316,3 +386,31 @@ export async function skipEmployeeChecklistTask(employeeId: string, taskId: stri
body: JSON.stringify({}),
});
}
export async function batchTransferEmployeesDepartment(payload: BatchTransferDepartmentPayload) {
return apiRequestData<BatchOperationResult>("/api/users/batch/transfer-department", {
method: "POST",
body: JSON.stringify(payload),
});
}
export async function batchEnableUsers(payload: BatchToggleUsersPayload) {
return apiRequestData<BatchOperationResult>("/api/users/batch/enable", {
method: "POST",
body: JSON.stringify(payload),
});
}
export async function batchDisableUsers(payload: BatchToggleUsersPayload) {
return apiRequestData<BatchOperationResult>("/api/users/batch/disable", {
method: "POST",
body: JSON.stringify(payload),
});
}
export async function batchSetEmployeesManager(payload: BatchSetManagerPayload) {
return apiRequestData<BatchOperationResult>("/api/users/batch/set-manager", {
method: "POST",
body: JSON.stringify(payload),
});
}
+10
查看文件
@@ -61,6 +61,11 @@ export async function exportEmployees(params: {
status?: "active" | "archived";
departmentId?: string;
q?: string;
title?: string;
managerId?: string;
hireDateFrom?: string;
hireDateTo?: string;
employmentStatus?: "onboarding" | "probation" | "active" | "offboarding" | "inactive";
limit?: number;
}) {
const qs = new URLSearchParams();
@@ -68,6 +73,11 @@ export async function exportEmployees(params: {
if (params.status) qs.set("status", params.status);
if (params.departmentId) qs.set("departmentId", params.departmentId);
if (params.q) qs.set("q", params.q);
if (params.title) qs.set("title", params.title);
if (params.managerId) qs.set("managerId", params.managerId);
if (params.hireDateFrom) qs.set("hireDateFrom", params.hireDateFrom);
if (params.hireDateTo) qs.set("hireDateTo", params.hireDateTo);
if (params.employmentStatus) qs.set("employmentStatus", params.employmentStatus);
if (typeof params.limit === "number") qs.set("limit", String(params.limit));
return apiRequestBlob(`/api/exports/employees?${qs.toString()}`);