| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- import { get, postJ } from "@/utils/request";
- import Vue from "vue";
- import { onboardStatus } from "@/pages/hr/data/manage-status";
- // 用工类型枚举值 → 中文标签(与后端约定一致)
- export const EMPLOYMENT_TYPE_LABEL = {
- FULL_TIME: "全职",
- INTERN: "实习",
- PART_TIME: "兼职",
- OTHER: "其他",
- };
- function ok(res) {
- return res && Number(res.code) === 0;
- }
- function asList(data) {
- if (Array.isArray(data)) return data;
- if (data && Array.isArray(data.list)) return data.list;
- if (data && Array.isArray(data.records)) return data.records;
- return [];
- }
- function dateOnly(value) {
- if (!value) return "";
- return String(value).slice(0, 10);
- }
- /**
- * 把后端入职记录 VO 归一为前端可用形状。
- */
- export function adaptOnboardingRecord(vo, base = {}) {
- if (!vo || typeof vo !== "object") return null;
- const id = String(vo.onboardingId != null ? vo.onboardingId : vo.id != null ? vo.id : base.id || "");
- const onboardingStatus = vo.onboardingStatus || base.onboardingStatus || "";
- const approvalStatus = vo.approvalStatus || base.approvalStatus || "";
- const status =
- onboardingStatus === "COMPLETED" || approvalStatus === "APPROVED"
- ? "done"
- : onboardingStatus === "SUBMITTED" || approvalStatus === "APPROVING"
- ? "processing"
- : base.status || "pending";
- return {
- id,
- onboardingId: id,
- invitationId: vo.invitationId != null ? vo.invitationId : base.invitationId || "",
- invitationNo: vo.invitationNo || base.invitationNo || "",
- employeeNo: vo.employeeNo || base.employeeNo || id,
- name: vo.employeeName || base.name || "",
- department: vo.deptName || base.department || "",
- deptId: vo.deptId != null ? vo.deptId : base.deptId != null ? base.deptId : null,
- position: vo.positionName || base.position || "",
- positionId: vo.positionId != null ? vo.positionId : base.positionId != null ? base.positionId : null,
- level: vo.level || base.level || "",
- hireDate: dateOnly(vo.plannedJoinDate || base.hireDate || base.expectedEntryDate || ""),
- company: vo.companyName || base.company || "",
- legalId: vo.legalId != null ? vo.legalId : base.legalId != null ? base.legalId : null,
- phone: vo.phone || base.phone || "",
- email: vo.email || base.email || "",
- idNumber: vo.idNumber || base.idNumber || "",
- gender: vo.gender || base.gender || "",
- age: vo.age != null ? vo.age : base.age || "",
- employmentType: vo.employmentType || base.employmentType || "FULL_TIME",
- probationFlag: vo.probationFlag != null ? vo.probationFlag : base.probationFlag != null ? base.probationFlag : 1,
- probationMonths: vo.probationMonths != null ? vo.probationMonths : base.probationMonths != null ? base.probationMonths : 3,
- validDays: vo.validDays != null ? vo.validDays : base.validDays != null ? base.validDays : 7,
- createMode: vo.createMode || base.createMode || "manual",
- status,
- flow: onboardingStatus === "SUBMITTED" ? "档案已完善" : base.flow || "待补充档案",
- offer: vo.offerStatus || base.offer || "未发起",
- contract: vo.contractStatus || base.contract || "未发起",
- assets: vo.assetsStatus || base.assets || "未领用",
- remark: vo.remark || base.remark || "",
- publicPath: vo.publicPath || base.publicPath || "",
- publicToken: vo.publicToken || base.publicToken || "",
- invitationStatus: vo.invitationStatus || base.invitationStatus || "",
- sourceType: vo.sourceType || "API",
- rowType: "record",
- materials: base.materials || {},
- socialSecurity: base.socialSecurity || { status: "未办理", city: "北京", deadline: "" },
- training: base.training || { status: "未开始", name: "新员工入职培训", duration: "2天", deadline: "" },
- workstation: base.workstation || { status: "待分配", location: "" },
- itAccount: base.itAccount || { status: "未开通", items: [] },
- stage: base.stage || "offer",
- entryDate: dateOnly(vo.actualJoinDate || base.entryDate || ""),
- };
- }
- /** 入职记录 → 列表卡片渲染形状 */
- export function mapOnboardingForList(record) {
- if (!record || typeof record !== "object") return null;
- const id = record.id || record.onboardingId || "";
- const name = record.name || record.employeeName || "";
- const department = record.department || record.deptName || "";
- const position = record.position || record.positionName || "";
- const statusInfo = onboardStatus[record.status] || onboardStatus.pending;
- const hireDate = record.hireDate || record.entryDate || record.expectedEntryDate || "";
- const employeeNo = record.employeeNo || id;
- const isEntered = Boolean(record.entryDate);
- const materials = record.materials;
- let materialsLabel = "";
- if (materials && typeof materials === "object") {
- const total = Object.keys(materials).length;
- if (total) {
- const done = Object.values(materials).filter(Boolean).length;
- materialsLabel = `${done}/${total}`;
- }
- }
- return {
- id,
- avatar: record.avatar || String(name).charAt(0) || "",
- name,
- sub: [department, position].filter(Boolean).join(" · "),
- status: statusInfo.label,
- statusClass: statusInfo.class,
- label1: isEntered ? "入职日期" : "预计入职",
- value1: isEntered ? record.entryDate : hireDate,
- label2: isEntered ? "员工编号" : materialsLabel ? "资料进度" : "员工编号",
- value2: isEntered ? employeeNo : materialsLabel || employeeNo,
- };
- }
- /**
- * 员工状态(即岗位性质)枚举:1全职、2兼职、3实习、4正式、5试用
- * 直接办理入职时服务端会从启用岗位回填六项岗位快照,前端只传基础项
- */
- export const USER_STATUS_LABEL = { 1: "全职", 2: "兼职", 3: "实习", 4: "正式", 5: "试用" };
- export const USER_STATUS_OPTIONS = [
- { value: 1, label: "全职" },
- { value: 2, label: "兼职" },
- { value: 3, label: "实习" },
- ];
- /**
- * 入职登记表单 → 人员入职保存参数(POST /main/onboardings)
- * 字段对齐 PC serializeOnboardingCreate:带岗位序列/层级/性质快照;
- * 主键一律原样透传(大整数雪花 id 禁止 Number() 转换,会丢精度),字符串 id 后端可接收。
- */
- export function buildUserOnboardingPayload(form = {}) {
- const toId = (v) => {
- if (v == null || v === "") return undefined;
- if (typeof v === "number") return Number.isSafeInteger(v) ? v : String(v);
- return String(v);
- };
- const text = (v) => {
- const s = String(v == null ? "" : v).trim();
- return s || undefined;
- };
- let attachmentFileIds = form.attachmentIds;
- if (Array.isArray(attachmentFileIds)) attachmentFileIds = attachmentFileIds.filter(Boolean).join(",");
- attachmentFileIds = attachmentFileIds ? String(attachmentFileIds) : undefined;
- const status = Number(form.status) || 1;
- return {
- name: text(form.name),
- joinDate: dateOnly(form.hireDate || form.joinDate) || undefined,
- organizationId: toId(form.legalId),
- targetDepartmentId: toId(form.deptId),
- positionSequenceId: toId(form.positionSequenceId),
- positionSequence: text(form.positionSequence),
- positionId: toId(form.positionId),
- positionLevelId: toId(form.positionLevelId),
- positionLevel: text(form.positionLevel),
- positionType: text(form.positionType),
- positionTypeName: text(form.positionTypeName),
- status,
- phone: text(form.phone),
- idNumber: text(form.idNumber),
- attachmentFileIds,
- };
- }
- /** 新增人员入职(直接办理)POST /main/onboardings,成功返回新员工用户主键 */
- export async function createUserOnboarding(form, loding = true) {
- const res = await postJ(Vue.prototype.apiUrl + "/main/onboardings", buildUserOnboardingPayload(form), loding);
- if (!ok(res)) throw new Error(res.message || "入职办理失败");
- return res.data;
- }
- /** 入职记录列表 GET /hr/ess/admin/onboardings/records */
- export async function getOnboardingRecords(loding = true) {
- const res = await get(Vue.prototype.apiUrl + "/hr/ess/admin/onboardings/records", {}, loding);
- if (!ok(res)) return [];
- return asList(res.data);
- }
- /** 入职邀请列表 GET /hr/ess/admin/onboardings/invitations */
- export async function getOnboardingInvitationsList(loding = true) {
- const res = await get(Vue.prototype.apiUrl + "/hr/ess/admin/onboardings/invitations", {}, loding);
- if (!ok(res)) return [];
- return asList(res.data);
- }
- /** 提交入职审批 POST /hr/ess/admin/onboardings/records/{id}/submit */
- export async function submitOnboardingRecord(onboardingId, loding = true) {
- if (!onboardingId) throw new Error("缺少入职单主键");
- const res = await postJ(
- Vue.prototype.apiUrl + `/hr/ess/admin/onboardings/records/${encodeURIComponent(onboardingId)}/submit`,
- {},
- loding
- );
- if (!ok(res)) throw new Error(res.message || "提交失败");
- return res.data || {};
- }
- /** 入职记录列表(归一化后) */
- export async function loadOnboardingRecords(loding = true) {
- const rows = await getOnboardingRecords(loding);
- return rows.map((vo) => adaptOnboardingRecord(vo) || vo).filter(Boolean);
- }
- /** 入职记录 / 邀请 详情(归一化后) */
- export async function loadOnboardingDetail(id) {
- if (!id) return null;
- try {
- const [records, invitations] = await Promise.all([
- getOnboardingRecords(false).catch(() => []),
- getOnboardingInvitationsList(false).catch(() => []),
- ]);
- const key = String(id);
- const hit =
- records.find((vo) => String(vo.onboardingId != null ? vo.onboardingId : vo.id) === key) ||
- invitations.find(
- (vo) =>
- String(vo.onboardingId != null ? vo.onboardingId : vo.id) === key ||
- String(vo.invitationId != null ? vo.invitationId : "") === key
- );
- if (!hit) return null;
- const record = adaptOnboardingRecord(hit);
- if (record && !record.createMode) record.createMode = "invite";
- return record;
- } catch (error) {
- return null;
- }
- }
|