| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- import request from "@/utils/request";
- function unwrap(response) {
- const result = response?.data || {};
- if (Number(result.code) === 0) return result.data;
- const error = new Error(result.message || "服务调用失败");
- if (response?.__toastShown) error.__toastShown = true;
- return Promise.reject(error);
- }
- function compact(object = {}) {
- return Object.keys(object).reduce((result, key) => {
- const value = object[key];
- if (value !== "" && value !== null && value !== undefined) result[key] = value;
- return result;
- }, {});
- }
- function dateOnly(value) {
- if (!value) return undefined;
- return String(value).slice(0, 10);
- }
- function toNumber(value) {
- if (value === null || value === undefined || value === "") return undefined;
- if (typeof value === "number" && Number.isFinite(value)) return value;
- const matched = String(value).replace(/,/g, "").match(/(\d+(?:\.\d+)?)/);
- return matched ? Number(matched[1]) : undefined;
- }
- function toProbationMonths(value) {
- if (value === null || value === undefined || value === "") return undefined;
- if (typeof value === "number" && Number.isFinite(value)) return value;
- const matched = String(value).match(/(\d+)/);
- return matched ? Number(matched[1]) : undefined;
- }
- /** 大整数主键保持字符串,避免雪花 ID 精度丢失 */
- function keepBigIntId(value) {
- if (value === undefined || value === null || value === "") return undefined;
- const text = String(value).trim();
- if (!/^-?\d+$/.test(text)) return value;
- if (!Number.isSafeInteger(Number(text))) return text;
- return Number(text);
- }
- /**
- * 录用审批状态(文档:PENDING / APPROVED / REJECTED)
- * 未发起流程、无状态码时前端按草稿展示
- */
- export const HIRING_STATUS_LABELS = {
- DRAFT: "草稿",
- PENDING: "审批中",
- APPROVED: "已通过",
- REJECTED: "已拒绝",
- };
- export const HIRING_STATUS_OPTIONS = Object.entries(HIRING_STATUS_LABELS).map(
- ([value, label]) => ({ value, label }),
- );
- /** 已通过:可发起 Offer */
- export const HIRING_APPROVED_STATUS = new Set(["APPROVED"]);
- /** BPM 流程标识,需与流程定义 code 一致;提交审核弹框按此拉取流程分类/发起流程 */
- export const HIRING_APPROVAL_BUSINESS_KEY = "hr_recruit_hiring_approval";
- export function normalizeHiringStatus(raw = {}) {
- const code = String(raw.approvalStatus || raw.status || "").trim().toUpperCase();
- if (code === "APPROVED" || code === "PASSED") return "APPROVED";
- if (code === "REJECTED" || code === "已拒绝" || code === "已驳回") return "REJECTED";
- if (
- code === "PENDING" ||
- code === "APPROVING" ||
- code === "PENDING_APPROVAL" ||
- code === "WAITING"
- ) {
- return "PENDING";
- }
- if (raw.processInstanceId) return "PENDING";
- if (raw.id) return "DRAFT";
- return "DRAFT";
- }
- /** 适配「录用审批视图」+ 前端展示扩展字段 */
- export function adaptHiringApproval(raw = {}, extras = {}) {
- const statusCode = normalizeHiringStatus(raw);
- const hireDate =
- dateOnly(raw.expectedEntryDate || extras.expectedEntryDate || raw.hireDate) ||
- "";
- const hiringDeptId =
- extras.hiringDeptId ??
- raw.hiringDeptId ??
- extras.departmentId ??
- raw.departmentId;
- const hiringDeptName =
- extras.hiringDeptName ||
- raw.hiringDeptName ||
- extras.departmentName ||
- raw.departmentName ||
- "";
- const deptId = extras.deptId ?? raw.deptId;
- const deptName = extras.deptName || raw.deptName || "";
- const phone =
- extras.phone ||
- extras.mobile ||
- raw.contactMobile ||
- raw.phone ||
- raw.mobile ||
- "";
- return {
- ...raw,
- id: raw.id,
- approvalNo:
- raw.approvalNo ||
- raw.documentCode ||
- (raw.id != null ? `HA${raw.id}` : ""),
- documentCode: raw.documentCode || "",
- applicationId: raw.applicationId ?? extras.applicationId,
- candidateId:
- raw.candidateId ??
- extras.candidateId ??
- raw.userId ??
- extras.userId,
- userId: raw.userId ?? extras.userId ?? raw.candidateId,
- candidateName:
- extras.candidateName || raw.candidateName || raw.name || "",
- positionId: raw.positionId ?? extras.positionId,
- positionName: raw.positionName || extras.positionName || "",
- hiringDeptId,
- hiringDeptName,
- departmentId: hiringDeptId,
- departmentName: hiringDeptName,
- deptId,
- deptName,
- gender: extras.gender || raw.gender || "",
- education: extras.education ?? raw.education ?? "",
- phone,
- mobile: phone,
- contactMobile: raw.contactMobile || phone,
- proposedSalary: raw.proposedSalary ?? extras.proposedSalary,
- workYears:
- extras.workYears ??
- raw.workYears ??
- extras.experienceYears ??
- raw.experienceYears,
- employmentType:
- extras.employmentType ||
- raw.employmentType ||
- raw.staffingType ||
- "",
- staffingType: extras.employmentType || raw.employmentType || raw.staffingType || "",
- probationPeriod: raw.probationPeriod ?? extras.probationPeriod,
- probation:
- (raw.probationPeriod ?? extras.probationPeriod) != null &&
- (raw.probationPeriod ?? extras.probationPeriod) !== ""
- ? `${raw.probationPeriod ?? extras.probationPeriod}个月`
- : extras.probation || raw.probation || "",
- hireDate,
- expectedEntryDate: hireDate,
- workLocation: extras.workLocation || raw.workLocation || "",
- specialTerms: extras.specialTerms || raw.specialTerms || raw.remark || "",
- remark: extras.specialTerms || raw.specialTerms || raw.remark || "",
- specialApprovalReason: raw.specialApprovalReason || "",
- processInstanceId: raw.processInstanceId || "",
- currentNode: extras.currentNode || raw.currentNode || raw.nodeName || "-",
- resumeAttachmentFileIds:
- raw.resumeAttachmentFileIds || extras.resumeAttachmentFileIds || "",
- statusCode,
- status: HIRING_STATUS_LABELS[statusCode] || raw.approvalStatus || "-",
- offerId: raw.offerId,
- offerSent: Boolean(raw.offerId || extras.offerSent),
- createTime: raw.createTime,
- createUserId: raw.createUserId,
- };
- }
- function toEducationValue(value) {
- if (value === null || value === undefined || value === "") return undefined;
- const text = String(value).trim();
- return text || undefined;
- }
- export function parseResumeAttachmentFileIds(value) {
- if (Array.isArray(value)) {
- return value
- .map((item) => String(item ?? "").trim())
- .filter(Boolean);
- }
- if (value == null || value === "") return [];
- return String(value)
- .split(",")
- .map((item) => item.trim())
- .filter(Boolean);
- }
- function joinResumeFileIds(form = {}) {
- const files = Array.isArray(form.attachmentFiles)
- ? form.attachmentFiles
- : Array.isArray(form.attachments)
- ? form.attachments
- : null;
- if (files) {
- const ids = files
- .map((item) => keepBigIntId(item.id || item.fileId))
- .filter((id) => id != null && id !== "");
- return ids.length ? ids.join(",") : undefined;
- }
- if (form.resumeAttachmentFileIds) {
- return (
- parseResumeAttachmentFileIds(form.resumeAttachmentFileIds).join(",") ||
- undefined
- );
- }
- return undefined;
- }
- /**
- * 保存草稿请求体 → 录用审批新增参数
- * 必填:expectedEntryDate、proposedSalary
- * 线下(无 applicationId):name、positionId 必填
- */
- export function serializeHiringApproval(form = {}) {
- const applicationId = keepBigIntId(form.applicationId);
- const name = String(form.name || form.candidateName || "").trim();
- const employmentType = keepBigIntId(form.employmentType ?? form.staffingType);
- const candidateId = keepBigIntId(
- form.candidateId ?? form.userId ?? form.personId,
- );
- const payload = compact({
- id: keepBigIntId(form.id),
- applicationId,
- candidateId,
- contactMobile: String(
- form.contactMobile || form.phone || form.mobile || "",
- ).trim() || undefined,
- demandId: keepBigIntId(form.demandId),
- education: toEducationValue(form.education),
- employmentType,
- expectedEntryDate: dateOnly(form.expectedEntryDate || form.hireDate),
- gender: form.gender || undefined,
- name: name || undefined,
- positionId: keepBigIntId(form.positionId),
- hiringDeptId: keepBigIntId(form.hiringDeptId ?? form.departmentId),
- hiringDeptName:
- String(form.hiringDeptName || form.departmentName || "").trim() ||
- undefined,
- deptId: keepBigIntId(form.deptId),
- deptName: String(form.deptName || "").trim() || undefined,
- probationPeriod: toProbationMonths(form.probationPeriod ?? form.probation),
- proposedLevel: form.proposedLevel || undefined,
- proposedSalary: (() => {
- const amount = toNumber(form.proposedSalary);
- return amount == null ? undefined : Math.round(amount);
- })(),
- resumeAttachmentFileIds: joinResumeFileIds(form),
- workYears: (() => {
- const years = toNumber(form.workYears);
- return years == null ? undefined : Math.round(years);
- })(),
- });
- if (payload.applicationId == null || payload.applicationId === "") {
- delete payload.applicationId;
- }
- payload.workLocation = String(form.workLocation || "").trim();
- payload.specialTerms = String(form.specialTerms || form.remark || "").trim();
- return payload;
- }
- /** 校验保存草稿必填(文档:expectedEntryDate、proposedSalary;线下须 name、positionId) */
- export function validateOfflineHiringDraft(form = {}) {
- const errors = [];
- if (!dateOnly(form.expectedEntryDate || form.hireDate)) {
- errors.push("请选择预计入职日期");
- }
- if (toNumber(form.proposedSalary) == null) {
- errors.push("请输入拟定薪资");
- }
- if (
- !keepBigIntId(form.applicationId) &&
- !String(form.name || form.candidateName || "").trim()
- ) {
- errors.push("请填写姓名");
- }
- if (!keepBigIntId(form.applicationId) && !keepBigIntId(form.positionId)) {
- errors.push("请选择应聘岗位");
- }
- return errors;
- }
- function toQueryInt(value) {
- if (value === null || value === undefined || value === "") return undefined;
- if (typeof value === "number" && Number.isFinite(value)) return value;
- const text = String(value).trim();
- if (!/^-?\d+$/.test(text)) return undefined;
- return keepBigIntId(text);
- }
- /**
- * 分页查询参数(GET /recruit/hiring-approvals)
- * approvalStatus / deptId / keyword / offset / orderBy / pageNum / size / sortName
- */
- export function serializeHiringApprovalQuery(params = {}) {
- return compact({
- approvalStatus: params.approvalStatus || undefined,
- deptId: toQueryInt(params.deptId),
- keyword: params.keyword || undefined,
- offset: toQueryInt(params.offset),
- orderBy: params.orderBy || undefined,
- pageNum: toQueryInt(params.pageNum),
- size: toQueryInt(params.size),
- sortName: params.sortName || undefined,
- });
- }
- // —— 人力资源-录用审批管理 ——
- /** 录用审批分页查询 GET /recruit/hiring-approvals */
- export const getHiringApprovalPage = async (params = {}) =>
- unwrap(
- await request.get("/recruit/hiring-approvals", {
- params: serializeHiringApprovalQuery(params),
- }),
- );
- /** 录用审批详情查询 GET /recruit/hiring-approvals/{id},id 为列表主键 */
- export const getHiringApprovalById = async (id) => {
- const hiringId = keepBigIntId(id);
- if (hiringId == null || hiringId === "") {
- return Promise.reject(new Error("缺少录用审批主键"));
- }
- return adaptHiringApproval(
- await unwrap(await request.get(`/recruit/hiring-approvals/${hiringId}`)),
- );
- };
- /**
- * 保存录用审批草稿 POST /recruit/hiring-approvals
- * 成功返回主键 id;前端发起时再调 BPM create
- */
- export const createHiringApproval = async (data) => {
- const payload = serializeHiringApproval(data || {});
- return unwrap(await request.post("/recruit/hiring-approvals", payload));
- };
- /** 与 create 同一接口(文档无独立修改接口) */
- export const updateHiringApproval = async (id, data) =>
- createHiringApproval({ ...(data || {}), id: id ?? data?.id });
|