Files
OnboardXFront/src/api/modules/biz/onboarding.ts
T
2026-09-08 17:48:42 +08:00

915 lines
23 KiB
TypeScript

import { moduleRequest } from "@/api/request";
import type { ReqId, ResPage } from "@/api/interface";
const taskHttp = moduleRequest("/biz/onboarding/task/");
const auditHttp = moduleRequest("/biz/onboarding/audit/");
const contractDocumentHttp = moduleRequest("/biz/onboarding/contract-document/");
const electronicSignHttp = moduleRequest("/biz/onboarding/electronic-sign/");
const fileHttp = moduleRequest("/sys/dev/file/");
/**
* 下载创建任务前的合同预览,并将统一响应中的 JSON 错误转换成可读异常。
*/
async function requestContractPreview(
action: string,
params: Record<string, unknown>,
fallbackMessage: string
) {
let response: any;
try {
response = await contractDocumentHttp.post<any>(
action,
params,
{ responseType: "blob", loading: false, cancel: false }
);
} catch (error: any) {
const errorBlob = error?.response?.data;
if (errorBlob instanceof Blob) {
try {
const result = JSON.parse(await errorBlob.text());
throw new Error(result?.msg || fallbackMessage);
} catch (parseError) {
if (!(parseError instanceof SyntaxError)) throw parseError;
}
}
throw error;
}
const blob = response?.data;
const contentType = String(
response?.headers?.["content-type"] || blob?.type || ""
);
if (
blob instanceof Blob &&
contentType.toLowerCase().includes("application/json")
) {
try {
const result = JSON.parse(await blob.text());
throw new Error(result?.msg || fallbackMessage);
} catch (error) {
if (error instanceof SyntaxError) {
throw new Error(fallbackMessage);
}
throw error;
}
}
return response;
}
export interface OnboardingTask {
id: number;
taskNo: string;
companyId: number;
companyName?: string;
departmentId?: number;
departmentName?: string;
positionId: number;
positionName?: string;
onboardingTemplateId?: number;
onboardingTemplateName?: string;
taskStatus: string;
rejectReason?: string;
linkExpireAt?: string;
submitCount: number;
createTime: string;
remark?: string;
}
/** 当前查询条件下、不受状态筛选影响的任务统计。 */
export interface OnboardingTaskStatistics {
pendingFill: number;
reviewing: number;
rejected: number;
approved: number;
}
/** 带状态统计的入职任务分页结果。 */
export interface OnboardingTaskPage extends ResPage<OnboardingTask> {
statistics: OnboardingTaskStatistics;
}
/** 批量复制任务返回的单条新任务链接。 */
export interface OnboardingTaskCreatedResult {
taskId: number;
taskNo: string;
linkToken: string;
expiresAt: string;
}
/** 批量复制任务结果。 */
export interface OnboardingTaskCopyResult {
tasks: OnboardingTaskCreatedResult[];
}
/** 员工端完成合同准备后返回的当前文件版本。 */
export interface OnboardingPreparedContract {
/** 当前生成合同对应的系统文件 Id,同时作为下载缓存版本。 */
fileId: number;
/** 当前合同文件生成时间。 */
generatedAt?: string;
}
/** 一次电子签流程中的单份合同文件。 */
export interface OnboardingElectronicSignDocument {
id: number;
taskContractId: number;
providerDocumentId?: string;
documentName: string;
documentSort: number;
originalDocxFileId?: number;
signedPdfFileId?: number;
employeeSignedPreviewed: boolean;
}
/** 员工已签、企业未盖章文件的契约锁只读预览。 */
export interface OnboardingElectronicSignPreview {
signDocumentId: number;
previewUrl: string;
}
/** 管理端查看的入职电子签流程详情。 */
export interface OnboardingElectronicSignDetail {
taskId: number;
taskNo: string;
canInitiate: boolean;
cannotInitiateReason?: string;
canReinitiate: boolean;
cannotReinitiateReason?: string;
hasProcess: boolean;
processId?: number;
providerContractId?: string;
bizId?: string;
subject?: string;
signStatus?: string;
providerStatus?: string;
employeeName?: string;
employeeMobile?: string;
signUrl?: string;
signUrlExpireAt?: string;
signUrlValid: boolean;
startedAt?: string;
sentAt?: string;
completedAt?: string;
archivedAt?: string;
archiveFileId?: number;
lastError?: string;
documents: OnboardingElectronicSignDocument[];
historyProcesses: OnboardingElectronicSignHistory[];
}
/** 已被新流程替代的电子签历史记录。 */
export interface OnboardingElectronicSignHistory {
processId: number;
bizId: string;
providerContractId?: string;
signStatus?: string;
providerStatus?: string;
employeeName?: string;
employeeMobile?: string;
startedAt?: string;
reissuedAt?: string;
reissueReason?: string;
lastError?: string;
}
export interface OnboardingCompanyOption {
id: number;
companyName: string;
}
export interface OnboardingDepartmentOption {
id: number;
departmentName: string;
}
export interface OnboardingPositionOption {
id: number;
positionName: string;
}
export interface OnboardingCompany extends OnboardingCompanyOption {
companyCode: string;
legalName: string;
unifiedSocialCreditCode?: string;
legalRepresentative?: string;
registeredAddress?: string;
contactPhone?: string;
qiyuesuoCategoryId?: string;
qiyuesuoSealId?: string;
remark?: string;
status: string;
}
export interface OnboardingDepartment extends OnboardingDepartmentOption {
companyId: number;
companyName?: string;
departmentCode: string;
sortCode: number;
remark?: string;
status: string;
createTime?: string;
}
export interface OnboardingPosition extends OnboardingPositionOption {
companyId: number;
companyName?: string;
departmentId?: number;
departmentName?: string;
positionCode: string;
defaultContractYears?: number;
defaultProbationMonths?: number;
remark?: string;
status: string;
}
export interface OnboardingContractTemplate {
id: number;
companyId?: number;
companyName?: string;
departmentId?: number;
departmentName?: string;
positionIds: number[];
positionNames?: string[];
templateCode: string;
templateName: string;
contractType: string;
description?: string;
status: string;
}
export interface OnboardingContractVersion {
id: number;
templateId: number;
versionNo: string;
sourceDocxFileId: number;
effectiveDate?: string;
expiryDate?: string;
versionStatus: string;
remark?: string;
}
export interface OnboardingTemplateVariable {
id: number;
templateVersionId: number;
variableCode: string;
variableName: string;
variableType: string;
dataType: string;
employeeField?: string;
defaultValue?: string;
required: boolean;
hrEditable: boolean;
sortCode?: number;
remark?: string;
}
export interface OnboardingTaskContractVariableItem {
id: number;
variableCode: string;
variableName: string;
variableType: string;
dataType: string;
sortCode: number;
variableValue?: string | number;
required: boolean;
hrEditable: boolean;
editable: boolean;
}
export interface OnboardingTaskContractVariableGroup {
taskContractId: number;
contractName: string;
contractType: string;
variables: OnboardingTaskContractVariableItem[];
}
export interface OnboardingEmployee {
id: number;
employeeNo?: string;
employeeName: string;
companyId: number;
companyName?: string;
departmentId?: number;
departmentName?: string;
positionId: number;
positionName?: string;
phone: string;
idCardNumber: string;
entryDate?: string;
createTime?: string;
}
export interface OnboardingFormField {
id: number;
fieldCode: string;
fieldName: string;
dataType: string;
optionsJson?: string;
validationRule?: string;
placeholder?: string;
status: string;
}
export interface OnboardingMaterialType {
id: number;
materialCode: string;
materialName: string;
allowedExtensions?: string;
maxFileCount: number;
maxFileSizeMb?: number;
status: string;
}
export interface OnboardingTemplateContractConfig {
contractTemplateId: number;
contractTemplateVersionId: number;
required: boolean;
printCopies: number;
sortCode?: number;
}
export interface OnboardingTemplateFieldConfig {
fieldId: number;
required: boolean;
sortCode?: number;
}
export interface OnboardingTemplateMaterialConfig {
materialTypeId: number;
required: boolean;
sortCode?: number;
}
export interface OnboardingTemplate {
id: number;
templateCode: string;
templateName: string;
companyId: number;
companyName?: string;
departmentId: number;
departmentName?: string;
positionIds: number[];
positionNames?: string[];
contracts: OnboardingTemplateContractConfig[];
formFields: OnboardingTemplateFieldConfig[];
materials: OnboardingTemplateMaterialConfig[];
contractCount?: number;
formFieldCount?: number;
materialCount?: number;
status: string;
description?: string;
}
export const onboardingTaskApi = {
page(params: Record<string, unknown>) {
return taskHttp.get<OnboardingTaskPage>("page", params);
},
detail(params: ReqId) {
return taskHttp.get("detail", params);
},
getTaskLink(params: ReqId) {
return taskHttp.get<any>("get-link", params);
},
/** 使用后台登录令牌读取文件流,供入职材料下载和图片预览使用。 */
async downloadFile(fileId: number) {
const response: any = await fileHttp.get<any>(
"download",
{ id: fileId },
{ responseType: "blob", loading: false, cancel: false }
);
const blob = response?.data;
const contentType = String(response?.headers?.["content-type"] || blob?.type || "");
if (blob instanceof Blob && contentType.toLowerCase().includes("application/json")) {
try {
const result = JSON.parse(await blob.text());
throw new Error(result?.msg || "文件下载失败");
} catch (error) {
if (error instanceof SyntaxError) {
throw new Error("文件下载失败");
}
throw error;
}
}
return response;
},
/** 创建任务前生成并下载指定的一份临时 DOCX 合同预览。 */
async previewContractBeforeCreate(params: Record<string, unknown>) {
return requestContractPreview(
"preview-before-create",
params,
"合同预览生成失败"
);
},
/** 创建任务前生成全部临时 DOCX 合同预览,并以 ZIP 下载。 */
async previewAllContractsBeforeCreate(params: Record<string, unknown>) {
return requestContractPreview(
"preview-all-before-create",
params,
"合同预览打包生成失败"
);
},
create(params: Record<string, unknown>) {
return taskHttp.post("create", params);
},
copy(params: {
sourceTaskId: number;
count: number;
items: Array<{ remark: string }>;
}) {
return taskHttp.post<OnboardingTaskCopyResult>("copy", params);
},
approve(params: {
taskId: number;
auditOpinion?: string;
}) {
return auditHttp.post("approve", params);
},
reject(params: {
taskId: number;
auditOpinion: string;
}) {
return auditHttp.post("reject", params);
},
generateContract(taskContractId: number) {
return moduleRequest("/biz/onboarding/contract-document/").post(
"generate",
{ taskContractId }
);
},
/** 查询任务当前电子签流程和全部合同文件。 */
electronicSignDetail(taskId: number) {
return electronicSignHttp.get<OnboardingElectronicSignDetail>("detail", {
id: taskId
});
},
/** 手动发起;失败流程会从已保存的本地断点继续。 */
initiateElectronicSign(taskId: number) {
return electronicSignHttp.post<OnboardingElectronicSignDetail>("initiate", {
taskId
});
},
/** 保留旧流程记录,并以新的业务编号重新发起一次签约。 */
reinitiateElectronicSign(taskId: number, reason: string) {
return electronicSignHttp.post<OnboardingElectronicSignDetail>("reinitiate", {
taskId,
reason
});
},
/** 主动同步签署状态,完成时后端自动执行归档。 */
syncElectronicSign(taskId: number) {
return electronicSignHttp.post<OnboardingElectronicSignDetail>("sync", {
taskId
});
},
/** 获取有效的员工签署链接,旧链接失效时由后端重新生成。 */
getElectronicSignLink(taskId: number) {
return electronicSignHttp.post<OnboardingElectronicSignDetail>("get-link", {
taskId
});
},
/** 获取一份员工已签合同的契约锁只读浏览页面。 */
previewEmployeeSignedDocument(taskId: number, signDocumentId: number) {
return electronicSignHttp.post<OnboardingElectronicSignPreview>(
"preview-employee-signed",
{ taskId, signDocumentId }
);
},
/** 全部合同核对完成后,由后台管理员确认企业盖章。 */
companySealElectronicSign(taskId: number) {
return electronicSignHttp.post<OnboardingElectronicSignDetail>("company-seal", {
taskId
});
},
/** 催办当前待签员工。 */
noticeElectronicSign(taskId: number) {
return electronicSignHttp.post("notice", { taskId });
},
/** 作废尚未完成的电子签流程。 */
invalidElectronicSign(taskId: number, reason: string) {
return electronicSignHttp.post("invalid", { taskId, reason });
},
archive(params: {
taskId: number;
auditOpinion?: string;
}) {
return taskHttp.post("archive", params);
},
revoke(params: {
taskId: number;
auditOpinion?: string;
}) {
return taskHttp.post("revoke", params);
},
deleteTask(id: number) {
return taskHttp.post("delete", { id });
},
reviewMaterial(params: {
taskMaterialId: number;
reviewStatus: string;
reviewRemark?: string;
}) {
return moduleRequest("/biz/onboarding/material/").post(
"review",
params
);
},
listCompanies() {
return moduleRequest("/biz/onboarding/company/").get<
OnboardingCompanyOption[]
>("list-enabled");
},
listDepartments(companyId: number) {
return moduleRequest("/biz/onboarding/department/").get<
OnboardingDepartmentOption[]
>("list-enabled", { companyId });
},
listPositions(companyId: number) {
return moduleRequest("/biz/onboarding/position/").get<
OnboardingPositionOption[]
>("list-enabled", { companyId });
},
companyPage(params: Record<string, unknown>) {
return moduleRequest("/biz/onboarding/company/").get<
ResPage<OnboardingCompany>
>("page", params);
},
companyDetail(params: ReqId) {
return moduleRequest("/biz/onboarding/company/").get<OnboardingCompany>(
"detail",
params
);
},
saveCompany(
params: Partial<OnboardingCompany>,
edit = false
) {
return moduleRequest("/biz/onboarding/company/").post(
edit ? "edit" : "add",
params
);
},
deleteCompany(ids: number[]) {
return moduleRequest("/biz/onboarding/company/").post(
"delete",
{ ids }
);
},
departmentPage(params: Record<string, unknown>) {
return moduleRequest("/biz/onboarding/department/").get<
ResPage<OnboardingDepartment>
>("page", params);
},
departmentDetail(params: ReqId) {
return moduleRequest("/biz/onboarding/department/").get<OnboardingDepartment>(
"detail",
params
);
},
saveDepartment(
params: Partial<OnboardingDepartment>,
edit = false
) {
return moduleRequest("/biz/onboarding/department/").post(
edit ? "edit" : "add",
params
);
},
deleteDepartment(ids: number[]) {
return moduleRequest("/biz/onboarding/department/").post(
"delete",
{ ids }
);
},
positionPage(params: Record<string, unknown>) {
return moduleRequest("/biz/onboarding/position/").get<
ResPage<OnboardingPosition>
>("page", params);
},
listPositionsByDepartment(departmentId: number) {
return moduleRequest("/biz/onboarding/position/").get<
OnboardingPosition[]
>("list-by-department", { departmentId });
},
positionDetail(params: ReqId) {
return moduleRequest("/biz/onboarding/position/").get<OnboardingPosition>(
"detail",
params
);
},
savePosition(
params: Partial<OnboardingPosition>,
edit = false
) {
return moduleRequest("/biz/onboarding/position/").post(
edit ? "edit" : "add",
params
);
},
deletePosition(ids: number[]) {
return moduleRequest("/biz/onboarding/position/").post(
"delete",
{ ids }
);
},
onboardingTemplatePage(params: Record<string, unknown>) {
return moduleRequest("/biz/onboarding/template/").get<
ResPage<OnboardingTemplate>
>("page", params);
},
onboardingTemplateDetail(params: ReqId) {
return moduleRequest("/biz/onboarding/template/").get<OnboardingTemplate>(
"detail",
params
);
},
saveOnboardingTemplate(params: Partial<OnboardingTemplate>) {
return moduleRequest("/biz/onboarding/template/").post<number>(
"save",
params
);
},
deleteOnboardingTemplate(ids: number[]) {
return moduleRequest("/biz/onboarding/template/").post(
"delete",
{ ids }
);
},
listEnabledOnboardingTemplates(
companyId: number,
departmentId: number,
positionId: number
) {
return moduleRequest("/biz/onboarding/template/").get<OnboardingTemplate[]>(
"list-enabled",
{ companyId, departmentId, positionId }
);
},
listAvailableContractTemplates(params: {
companyId: number;
departmentId: number;
positionIds: number[];
}) {
return moduleRequest("/biz/onboarding/contract-template/").post<
OnboardingContractTemplate[]
>("list-available", params);
},
templatePage(params: Record<string, unknown>) {
return moduleRequest("/biz/onboarding/contract-template/").get<
ResPage<OnboardingContractTemplate>
>("page", params);
},
templateDetail(params: ReqId) {
return moduleRequest("/biz/onboarding/contract-template/").get<
OnboardingContractTemplate
>("detail", params);
},
saveTemplate(
params: Partial<OnboardingContractTemplate>,
edit = false
) {
return moduleRequest("/biz/onboarding/contract-template/").post(
edit ? "edit" : "add",
params
);
},
deleteTemplate(ids: number[]) {
return moduleRequest("/biz/onboarding/contract-template/").post(
"delete",
{ ids }
);
},
versionPage(params: {
templateId: number;
pageNum: number;
pageSize: number;
}) {
return moduleRequest("/biz/onboarding/contract-template/").get<
ResPage<OnboardingContractVersion>
>("version/page", params);
},
addVersion(params: Partial<OnboardingContractVersion>) {
return moduleRequest("/biz/onboarding/contract-template/").post(
"version/add",
params
);
},
setVersionStatus(params: {
id: number;
versionStatus: string;
}) {
return moduleRequest("/biz/onboarding/contract-template/").post(
"version/set-status",
params
);
},
deleteVersion(id: number) {
return moduleRequest("/biz/onboarding/contract-template/").post(
"version/delete",
{ id }
);
},
variablePage(params: {
templateVersionId: number;
pageNum: number;
pageSize: number;
}) {
return moduleRequest("/biz/onboarding/contract-template/").get<
ResPage<OnboardingTemplateVariable>
>("variable/page", params);
},
editVariable(params: Partial<OnboardingTemplateVariable>) {
return moduleRequest("/biz/onboarding/contract-template/").post(
"variable/edit",
params
);
},
uploadDocx(params: FormData) {
return moduleRequest("/biz/onboarding/contract-template/").post<number>(
"file/upload-docx",
params
);
},
taskContractVariables(taskId: number) {
return moduleRequest("/biz/onboarding/task-contract-variable/").get<
OnboardingTaskContractVariableGroup[]
>("list", { taskId });
},
saveTaskContractVariables(params: {
taskContractId: number;
values: Array<{
id: number;
variableValue?: string;
}>;
}) {
return moduleRequest("/biz/onboarding/task-contract-variable/").post(
"save",
params
);
},
employeePage(params: Record<string, unknown>) {
return moduleRequest("/biz/onboarding/employee/").get<
ResPage<OnboardingEmployee>
>("page", params);
},
employeeDetail(params: ReqId) {
return moduleRequest("/biz/onboarding/employee/").get(
"detail",
params
);
},
listFormFields() {
return moduleRequest("/biz/onboarding/entry-config/").get<
OnboardingFormField[]
>("form-field/list");
},
saveFormField(params: Partial<OnboardingFormField>) {
return moduleRequest("/biz/onboarding/entry-config/").post(
"form-field/save",
params
);
},
deleteFormFields(ids: number[]) {
return moduleRequest("/biz/onboarding/entry-config/").post(
"form-field/delete",
{ ids }
);
},
listMaterialTypes() {
return moduleRequest("/biz/onboarding/entry-config/").get<
OnboardingMaterialType[]
>("material-type/list");
},
saveMaterialType(params: Partial<OnboardingMaterialType>) {
return moduleRequest("/biz/onboarding/entry-config/").post(
"material-type/save",
params
);
},
deleteMaterialTypes(ids: number[]) {
return moduleRequest("/biz/onboarding/entry-config/").post(
"material-type/delete",
{ ids }
);
},
// 合同变量字典定义
variableDefinitionPage(params: { keyword?: string; variableCategory?: string; pageNum: number; pageSize: number }) {
return moduleRequest("/biz/onboarding/variable-definition/").get<ResPage<any>>("page", params);
},
variableDefinitionList() {
return moduleRequest("/biz/onboarding/variable-definition/").get<any[]>("list");
},
addVariableDefinition(params: Record<string, unknown>) {
return moduleRequest("/biz/onboarding/variable-definition/").post("add", params);
},
editVariableDefinition(params: Record<string, unknown>) {
return moduleRequest("/biz/onboarding/variable-definition/").post("edit", params);
},
deleteVariableDefinitions(ids: number[]) {
return moduleRequest("/biz/onboarding/variable-definition/").post("delete", { ids });
}
};
const publicHttp = moduleRequest("/open/onboarding/");
export const onboardingPublicApi = {
detail(params: { token: string }) {
return publicHttp.post<any>("detail", params);
},
saveEmployeeInfo(params: Record<string, unknown>) {
return publicHttp.post("save-employee-info", params);
},
confirmContract(params: { token: string; taskContractId: number }) {
return publicHttp.post("confirm-contract", params);
},
submit(params: { token: string }) {
return publicHttp.post("submit", params);
},
prepareContract(params: { token: string; taskContractId: number }) {
return publicHttp.post<OnboardingPreparedContract>("prepare-contract", params);
},
contractSourceUrl(params: { token: string; taskContractId: number; fileVersion?: number }) {
const version = params.fileVersion ? `&version=${params.fileVersion}` : `&_t=${Date.now()}`;
return `/api/open/onboarding/contract-source?token=${encodeURIComponent(params.token)}&taskContractId=${params.taskContractId}${version}`;
},
materialSourceUrl(params: { token: string; taskMaterialId: number; fileId?: number }) {
const version = params.fileId ? `&v=${params.fileId}` : "";
return `/api/open/onboarding/material-source?token=${encodeURIComponent(params.token)}&taskMaterialId=${params.taskMaterialId}${version}`;
},
deleteMaterial(params: { token: string; taskMaterialId: number }) {
return publicHttp.post("delete-material", params);
}
};