| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929 |
- import request from "@/utils/request";
- import { contractStatusLabel, contractSigningStatusLabel } from "@/api/hr/contractStatus";
- function unwrap(response) {
- const result = response.data;
- if (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 !== undefined && value !== null && value !== "") result[key] = value;
- return result;
- }, {});
- }
- function formatDate(value) {
- if (!value) return "";
- const text = String(value);
- if (/^\d{4}-\d{2}-\d{2}/.test(text)) return text.slice(0, 10);
- const date = new Date(value);
- if (Number.isNaN(date.getTime())) return text;
- const y = date.getFullYear();
- const m = String(date.getMonth() + 1).padStart(2, "0");
- const d = String(date.getDate()).padStart(2, "0");
- return `${y}-${m}-${d}`;
- }
- function downloadBlob(response, fallbackName) {
- const blob = new Blob([response.data], {
- type: response.headers["content-type"] || "application/octet-stream",
- });
- const disposition = response.headers["content-disposition"] || "";
- const matched = disposition.match(/filename\*?=(?:UTF-8''|")?([^";]+)/i);
- const fileName = matched
- ? decodeURIComponent(matched[1].replace(/"/g, ""))
- : fallbackName;
- const url = URL.createObjectURL(blob);
- const link = document.createElement("a");
- link.href = url;
- link.download = fileName;
- document.body.appendChild(link);
- link.click();
- document.body.removeChild(link);
- URL.revokeObjectURL(url);
- }
- export async function listOrganizations(params) {
- return unwrap(await request.get("/main/group/getGroupList", { params }));
- }
- /** 工厂区域分页:type=1 工厂 */
- export async function getFactoryAreaPage(params = {}) {
- return unwrap(
- await request.get("/main/factoryarea/page", {
- params: {
- pageNum: 1,
- size: 999,
- type: 1,
- ...params,
- },
- }),
- );
- }
- export async function getOrganizationTree(params) {
- return unwrap(await request.get("/main/group/getGroupTree", { params }));
- }
- export async function getGroupUserTree(params) {
- return unwrap(await request.get("/main/group/getGroupUserTree", { params }));
- }
- export async function getOrganization(id) {
- return unwrap(await request.get("/main/group/getById/" + id));
- }
- export async function getOrganizationCode() {
- return unwrap(await request.get("/main/codemanage/getCode/group_code"));
- }
- export async function addOrganization(data) {
- const response = await request.post("/main/group/save", data);
- if (response.data.code == 0) {
- return response.data.data ?? response.data.message;
- }
- return Promise.reject(new Error(response.data.message || "新增失败"));
- }
- export async function updateOrganization(data) {
- const response = await request.put("/main/group/update", data);
- if (response.data.code == 0) {
- return response.data.data ?? response.data.message;
- }
- return Promise.reject(new Error(response.data.message || "修改失败"));
- }
- export async function updateDepartmentPosition(data) {
- return unwrap(await request.put("/fm/tmaindepartmentposition/updateBatch", data));
- }
- export async function saveBatchDepartmentPosition(data) {
- return unwrap(await request.post("/fm/tmaindepartmentposition/saveBatch", data));
- }
- export async function pageDepartmentPosition(params) {
- return unwrap(await request.post("/fm/tmaindepartmentposition/page", params));
- }
- export async function removeOrganization(ids) {
- const response = await request.post("/main/group/delete", ids);
- if (response.data.code == 0) {
- return response.data.message;
- }
- return Promise.reject(new Error(response.data.message || "删除失败"));
- }
- export async function getUserPage(params) {
- return unwrap(
- await request.get("/main/user/getUserPage", {
- params,
- }),
- );
- }
- /** 分页拉全量(有上限,避免一次性打爆接口) */
- export async function fetchAllUsers(params = {}, options = {}) {
- const pageSize = options.pageSize || 200;
- const maxPages = options.maxPages || 50;
- const list = [];
- let pageNum = 1;
- let total = Infinity;
- while (pageNum <= maxPages && list.length < total) {
- const data = await getUserPage({
- ...params,
- pageNum,
- size: pageSize,
- });
- const chunk = Array.isArray(data?.list) ? data.list : [];
- total = Number(data?.count ?? list.length + chunk.length);
- list.push(...chunk);
- if (!chunk.length || chunk.length < pageSize) break;
- pageNum += 1;
- }
- return { list, count: total === Infinity ? list.length : total };
- }
- /**
- * 关键词联合检索:并行 name / phone / jobNumber,再按 id 去重
- * (后端 getUserPage 无统一 keyword 字段)
- */
- export async function searchUsersByKeyword(keyword, baseParams = {}) {
- const text = String(keyword || "").trim();
- if (!text) {
- return getUserPage(baseParams);
- }
- const queries = [{ ...baseParams, name: text }];
- if (/^\d+$/.test(text) || /[A-Za-z]/.test(text)) {
- queries.push({ ...baseParams, jobNumber: text });
- }
- if (/^1\d{10}$/.test(text) || text.includes("*")) {
- queries.push({ ...baseParams, phone: text });
- }
- const results = await Promise.all(queries.map((params) => getUserPage(params).catch(() => ({ list: [], count: 0 }))));
- const map = new Map();
- results.forEach((data) => {
- (Array.isArray(data?.list) ? data.list : []).forEach((item) => {
- if (item?.id != null) map.set(String(item.id), item);
- });
- });
- const list = Array.from(map.values());
- return { list, count: list.length, pageNum: 1, size: list.length };
- }
- export async function getEmployeeById(id) {
- return unwrap(
- await request.get(`/main/user/getById/${encodeURIComponent(String(id))}`),
- );
- }
- /** 360 度员工人事档案聚合视图 */
- export async function getEmployeeProfile(userId) {
- return unwrap(await request.get(`/main/users/${userId}/profile`));
- }
- export async function getEmployeeHistory(userId) {
- return unwrap(await request.get(`/main/users/${userId}/history`));
- }
- export async function saveEmployee(data) {
- return unwrap(await request.post("/main/user/saveNew", data));
- }
- /**
- * 员工信息首次入库归档后创建个人文档区。
- * 仅可调用一次:详情已有 jobNumber 时说明已归档,不可再调。
- */
- export async function createPersonalDirectory(userId) {
- const id = String(userId ?? "").trim();
- if (!id) return null;
- return unwrap(
- await request.post(`/fm/directory/createPersonal/${encodeURIComponent(id)}`),
- );
- }
- export function hasJobNumber(record = {}) {
- const jobNumber = record.jobNumber ?? record.user?.jobNumber ?? "";
- return Boolean(String(jobNumber).trim());
- }
- export async function removeEmployee(ids) {
- return unwrap(await request.post("/main/user/removeById", ids));
- }
- export async function exportUsers(payload = {}) {
- const response = await request.post("/main/user/exportUsers", payload, {
- responseType: "blob",
- });
- downloadBlob(response, `员工档案_${formatDate(new Date())}.xlsx`);
- }
- export async function downloadUserTemplate() {
- const response = await request.post(
- "/main/user/downLoadTemplate",
- {},
- { responseType: "blob" },
- );
- downloadBlob(response, "人员信息导入模板.xlsx");
- }
- export async function importUsers(file) {
- const formData = new FormData();
- formData.append("file", file);
- const response = await request.post("/main/excelUpload/importUser", formData);
- if (response.data?.code == 0 || typeof response.data === "string") {
- return response.data?.data ?? response.data?.message ?? response.data;
- }
- return Promise.reject(new Error(response.data?.message || "导入失败"));
- }
- export async function listWorkExperiences(userId) {
- return unwrap(await request.get(`/main/users/${userId}/work-experiences`));
- }
- export async function saveWorkExperience(userId, data) {
- return unwrap(await request.post(`/main/users/${userId}/work-experiences`, data));
- }
- export async function updateWorkExperience(userId, workExperienceId, data) {
- return unwrap(
- await request.put(
- `/main/users/${userId}/work-experiences/${workExperienceId}`,
- data,
- ),
- );
- }
- export async function removeWorkExperience(userId, workExperienceId) {
- return unwrap(
- await request.delete(
- `/main/users/${userId}/work-experiences/${workExperienceId}`,
- ),
- );
- }
- export async function exportOrganizations() {
- const response = await request.post(
- "/main/group/exportGroups",
- {},
- { responseType: "blob" },
- );
- downloadBlob(response, "组织机构列表.xlsx");
- }
- /** 后端 status → 列表展示态 */
- export const EMPLOYEE_STATUS_CODE = {
- 1: "全职",
- 2: "兼职",
- 3: "实习",
- 4: "正式",
- 5: "试用",
- 6: "离职",
- };
- const EMPLOYEE_STATUS = {
- 全职: 1,
- 兼职: 2,
- 实习: 3,
- 正式: 4,
- 试用: 5,
- 试用期: 5,
- 劳务: 4,
- 离职: 6,
- };
- const EMPLOYEE_SEX = { 男: 1, 女: 2, 未知: 0 };
- const SEX_LABEL = { 0: "未知", 1: "男", 2: "女" };
- const REWARD_STATUS = { 生效: 2, 已撤销: 4, 已过期: 3, 未生效: 0, 审核中: 1 };
- const CERT_TYPE = {
- 身份证: 1,
- 驾驶证: 2,
- 军官证: 3,
- 护照: 4,
- 特种作业证: 4,
- 职称证: 4,
- 职业资格证: 4,
- 其他: 4,
- };
- const CERT_LEVEL = { 初级: "1", 中级: "2", 高级: "3" };
- const CERT_LEVEL_LABEL = { 1: "初级", 2: "中级", 3: "高级", 初级: "初级", 中级: "中级", 高级: "高级" };
- /** 列表/详情统一展示状态:active | probation | inactive | disabled */
- export function toListStatus(raw = {}) {
- if (Number(raw.isEnabled) === 0) return "disabled";
- const code = Number(raw.status);
- if (code === 6) return "inactive";
- if (code === 5) return "probation";
- return "active";
- }
- export function toFormStatus(raw = {}) {
- if (Number(raw.isEnabled) === 0) return "离职";
- return EMPLOYEE_STATUS_CODE[Number(raw.status)] || "全职";
- }
- function emptyLeaveInfo() {
- return {
- enabled: false,
- position: "",
- department: "",
- leaveDate: "",
- leaveType: "",
- leaveReason: "",
- serviceYears: "",
- handoverStatus: "",
- };
- }
- function adaptContract(raw) {
- const first = Array.isArray(raw?.contracts) ? raw.contracts[0] : null;
- if (!first) {
- return { category: "", name: "", number: "", signDate: "", startDate: "", endDate: "", files: [], status: "待签署", remark: "" };
- }
- return {
- category: first.contractType || "",
- name: first.contractNo || "",
- number: first.contractNo || "",
- signDate: formatDate(first.effectiveDate || first.startDate),
- startDate: formatDate(first.startDate),
- endDate: formatDate(first.endDate),
- files: [],
- status:
- contractStatusLabel(first.contractStatus, "") ||
- contractSigningStatusLabel(first.signingStatus, "") ||
- "生效",
- remark: "",
- };
- }
- function adaptBanks(raw) {
- if (Array.isArray(raw?.bankCardList) && raw.bankCardList.length) {
- return raw.bankCardList.map((item) => ({
- id: item.id,
- bankName: item.openingBank || "",
- bankAccount: item.cardNumber || "",
- bankAccountName: item.accountName || raw.name || "",
- }));
- }
- if (raw?.openingBank || raw?.cardNumber) {
- return [
- {
- bankName: raw.openingBank || "",
- bankAccount: raw.cardNumber || "",
- bankAccountName: raw.name || "",
- },
- ];
- }
- return [];
- }
- function adaptSocial(raw) {
- if (Array.isArray(raw?.socialSecurityList) && raw.socialSecurityList.length) {
- return raw.socialSecurityList.map((item) => ({
- id: item.id,
- type: item.socialType || "",
- base: item.socialBase ?? 0,
- insuredDate: formatDate(item.insuredDate),
- stopDate: formatDate(item.stopDate),
- stopReason: item.stopRecord || "",
- }));
- }
- return [];
- }
- function adaptSkills(list = []) {
- return (list || []).map((item) => ({
- id: item.id,
- category: "",
- name: item.name || "",
- level: item.level || "",
- years: item.years ?? 0,
- attachment: [],
- remark: item.remark || "",
- }));
- }
- function adaptTrainings(list = []) {
- const statusMap = { 0: "未开始", 1: "进行中", 2: "已完成", 4: "取消" };
- return (list || []).map((item) => ({
- id: item.id,
- name: item.title || "",
- description: item.desce || "",
- startTime: formatDate(item.startTime),
- endTime: formatDate(item.endTime),
- dateRange: [formatDate(item.startTime), formatDate(item.endTime)].filter(Boolean),
- status: statusMap[item.status] || "已完成",
- organization: "",
- hours: "",
- result: "",
- certificate: "",
- remark: item.remark || "",
- }));
- }
- function adaptRewards(list = []) {
- const statusMap = { 0: "未生效", 1: "审核中", 2: "生效", 3: "已过期", 4: "已撤销" };
- return (list || []).map((item) => ({
- id: item.id,
- type: Number(item.type) === 2 ? "惩罚" : "奖励",
- date: formatDate(item.startTime),
- name: item.desce || "",
- description: item.desce || "",
- startDate: formatDate(item.startTime),
- endDate: formatDate(item.endTime),
- status: statusMap[item.status] || "生效",
- level: "",
- issuer: "",
- orderNo: "",
- remark: item.remark || "",
- }));
- }
- function adaptCertificates(list = []) {
- const typeMap = { 1: "身份证", 2: "驾驶证", 3: "军官证", 4: "护照" };
- return (list || []).map((item) => ({
- id: item.id,
- type: typeMap[item.type] || "其他",
- number: item.code || "",
- level: CERT_LEVEL_LABEL[item.level] || item.level || "",
- status: Number(item.status) === 0 ? "失效" : "有效",
- startDate: formatDate(item.validityStartTime),
- endDate: formatDate(item.validityEndTime),
- issueDate: formatDate(item.enactorTime),
- attachment: [],
- remark: item.remark || "",
- }));
- }
- function adaptWorkTypes(list = []) {
- return (list || []).map((item) => ({
- id: item.id,
- type: item.type || "",
- code: item.code || "",
- name: item.name || "",
- level: item.level || "",
- hourCost: item.hourCost ?? 0,
- unit: item.unit || "",
- hourlyWage: item.hourCost ?? 0,
- wageUnit: item.unit || "",
- userId: item.userId || item.relatedUserId || "",
- userName: item.userName || item.relatedUserName || "",
- }));
- }
- function adaptWorkExperiences(list = []) {
- return (list || []).map((item) => ({
- id: item.id,
- startDate: formatDate(item.workStartDate),
- endDate: formatDate(item.workEndDate),
- dateRange: [formatDate(item.workStartDate), formatDate(item.workEndDate)].filter(Boolean),
- company: item.formerCompanyName || "",
- position: item.formerPosition || "",
- department: item.formerDepartment || "",
- leaveReason: item.resignationReason || "",
- description: item.workDescription || "",
- }));
- }
- function adaptHistory(list = []) {
- return (list || []).map((item) => ({
- date: formatDate(item.eventTime || item.occurTime || item.createTime),
- title: item.eventTitle || item.title || item.eventType || "人事事件",
- detail: item.eventDesc || item.description || item.summary || "",
- orderNo: item.bizNo || item.orderNo || "",
- }));
- }
- /** 兼容 positionList;无名称时用 postName 按序补齐;positionId 支持逗号串 */
- function adaptPositionBindings(raw = {}) {
- const fallbackNames = String(raw.postName || "")
- .split(/[,,、]/)
- .map((item) => item.trim())
- .filter(Boolean);
- if (Array.isArray(raw.positionList) && raw.positionList.length) {
- return raw.positionList
- .filter((item) => item && (item.positionId != null || item.positionName))
- .flatMap((item, index) => {
- const rawId = item.positionId != null ? String(item.positionId) : "";
- const idParts = rawId
- .split(/[,,]/)
- .map((part) => part.trim())
- .filter(Boolean);
- const ids = idParts.length ? idParts : rawId ? [rawId] : [];
- if (!ids.length && item.positionName) {
- return [
- {
- id: item.id != null ? String(item.id) : undefined,
- positionId: "",
- positionName: item.positionName || fallbackNames[index] || "",
- positionLevelId:
- item.positionLevelId != null ? String(item.positionLevelId) : "",
- positionLevelName: item.positionLevelName || "",
- positionSequenceId:
- item.positionSequenceId != null
- ? String(item.positionSequenceId)
- : "",
- positionSequenceName: item.positionSequenceName || "",
- positionType: item.positionType || "",
- primaryFlag: Number(item.primaryFlag) === 1 ? 1 : 0,
- },
- ];
- }
- return ids.map((positionId, partIndex) => ({
- id: item.id != null ? String(item.id) : undefined,
- positionId: String(positionId),
- positionName:
- item.positionName ||
- fallbackNames[index + partIndex] ||
- fallbackNames[index] ||
- "",
- positionLevelId:
- item.positionLevelId != null ? String(item.positionLevelId) : "",
- positionLevelName: item.positionLevelName || "",
- positionSequenceId:
- item.positionSequenceId != null
- ? String(item.positionSequenceId)
- : "",
- positionSequenceName: item.positionSequenceName || "",
- positionType: item.positionType || "",
- primaryFlag:
- partIndex === 0 && Number(item.primaryFlag) === 1 ? 1 : 0,
- }));
- })
- .sort((a, b) => Number(b.primaryFlag || 0) - Number(a.primaryFlag || 0));
- }
- const ids = String(raw.postId || "")
- .split(/[,,]/)
- .map((item) => item.trim())
- .filter(Boolean);
- return ids.map((positionId, index) => ({
- positionId: String(positionId),
- positionName: fallbackNames[index] || "",
- positionLevelId: "",
- positionLevelName: "",
- positionSequenceId: "",
- positionSequenceName: "",
- positionType: "",
- primaryFlag: index === 0 ? 1 : 0,
- }));
- }
- function toApiId(value) {
- if (value == null || value === "") return undefined;
- const text = String(value);
- if (/^\d+$/.test(text) && text.length <= 15) return Number(text);
- return text;
- }
- /**
- * 后端「用户」→ 员工档案页面模型
- * @param {object} raw 用户详情或分页行
- * @param {object} [extras] profile / workExperiences 等补充数据
- */
- export function adaptEmployee(raw = {}, extras = {}) {
- const deptIds = Array.from(
- new Set(
- (Array.isArray(raw.deptIds)
- ? raw.deptIds
- : raw.deptId != null && raw.deptId !== ""
- ? [raw.deptId]
- : []
- )
- .map((id) => String(id).trim())
- .filter(Boolean),
- ),
- );
- const deptId = deptIds[0] || "";
- const listStatus = toListStatus(raw);
- const leaveDate = formatDate(raw.leaveDate);
- const positionBindings = adaptPositionBindings(raw);
- const primaryPosition =
- positionBindings.find((item) => Number(item.primaryFlag) === 1) || positionBindings[0] || null;
- const positionIds = positionBindings.map((item) => item.positionId).filter(Boolean);
- const positionNames = positionBindings
- .map((item) => item.positionName)
- .filter(Boolean);
- const banks = adaptBanks(raw);
- const avatar =
- typeof raw.pic === "string"
- ? raw.pic
- : Array.isArray(raw.avatar) && raw.avatar[0]
- ? raw.avatar[0].url || raw.avatar[0].fileUrl || ""
- : "";
- return {
- id: raw.id,
- avatar,
- name: raw.name || "",
- employeeNo: raw.jobNumber || "",
- account: raw.loginName || "",
- gender: SEX_LABEL[raw.sex] || "未知",
- birthDate: formatDate(raw.birthday),
- age: raw.age ?? null,
- idCard: raw.idCard || raw.idNumber || "",
- ethnic: raw.ethnic || "",
- politicalStatus: raw.politicsStatus || "",
- maritalStatus: raw.maritalStatus || "",
- nativePlace: raw.birthplace || "",
- education: raw.educationBackground || "",
- school: raw.school || "",
- major: raw.major || "",
- graduationDate: formatDate(raw.graduateDate),
- registeredAddress: raw.censusAddress || "",
- currentAddress: raw.currentAddress || "",
- workAddress: raw.address || "",
- phone: raw.phone || "",
- email: raw.email || "",
- wechat: raw.wxId || "",
- emergencyContact: raw.secondLinkName || "",
- emergencyPhone: raw.secondLinkPhone || "",
- emergencyRelation: raw.secondLinkRelation || "",
- groupId: raw.groupId != null && raw.groupId !== "" ? String(raw.groupId) : null,
- company: raw.groupName || "",
- legalEntity: raw.groupName || "",
- factory: raw.factoryName || "",
- factoryId: raw.factoryId || raw.factoriesId || null,
- deptIds,
- deptId: deptId ? String(deptId) : "",
- deptName: raw.deptName || raw.deptNames || "",
- position: positionNames.join("、") || raw.postName || "",
- positionIds,
- positionBindings,
- positionId: primaryPosition?.positionId || null,
- level: primaryPosition?.positionLevelName || "",
- managerId:
- raw.managerUserId != null && raw.managerUserId !== ""
- ? String(raw.managerUserId)
- : null,
- manager: raw.managerUserName || "",
- managerJobNumber: raw.managerJobNumber || "",
- employmentType: EMPLOYEE_STATUS_CODE[Number(raw.status)] || "全职",
- status: listStatus,
- formStatus: toFormStatus(raw),
- hireDate: formatDate(raw.joinDate || raw.hireDate || raw.entryDate),
- regularDate: formatDate(raw.positiveDate),
- enabled: Number(raw.isEnabled) !== 0,
- keyProcess:
- raw.criticalTaskIds ||
- (Array.isArray(raw.criticalTaskList)
- ? raw.criticalTaskList
- .map((item) => item.taskName || item.taskId)
- .filter(Boolean)
- .join(",")
- : "") ||
- "",
- remarks: raw.remark || "",
- bankName: banks[0]?.bankName || "",
- bankAccount: banks[0]?.bankAccount || "",
- bankAccountName: banks[0]?.bankAccountName || raw.name || "",
- bankAccounts: banks,
- socialSecurityRecords: adaptSocial(raw),
- skills: adaptSkills(raw.skills),
- trainingRecords: adaptTrainings(raw.trainRecords),
- rewardPunishmentRecords: adaptRewards(raw.rewardsPunishments),
- certificates: adaptCertificates(raw.identityPhotos),
- workTypes: adaptWorkTypes(raw.professions),
- previousJobs: adaptWorkExperiences(extras.workExperiences || []),
- educations: raw.educationBackground
- ? [
- {
- education: raw.educationBackground || "",
- degree: "",
- graduationDate: formatDate(raw.graduateDate),
- school: raw.school || "",
- major: raw.major || "",
- },
- ]
- : [],
- contract: adaptContract(raw),
- workHistory: adaptHistory(extras.history || []),
- attendanceRecords: [],
- performanceRecords: (extras.performanceRecords || []).map((item) => ({
- dateRange: [formatDate(item.periodStart), formatDate(item.periodEnd)].filter(Boolean),
- cycle: item.cycleName || item.cycle || "",
- result: item.resultLabel || item.result || "",
- achievementRate: item.score ?? item.achievementRate,
- assessmentDate: formatDate(item.publishTime || item.assessmentDate),
- standard: item.standard || "",
- remark: item.remark || "",
- })),
- awards: [],
- positionTransfers: (extras.changes || []).map((item) => ({
- date: formatDate(item.effectiveDate || item.createTime),
- originalPosition: item.fromPositionName || "",
- newPosition: item.toPositionName || "",
- originalDepartment: item.fromDeptName || "",
- newDepartment: item.toDeptName || "",
- orderNo: item.bizNo || item.id || "",
- })),
- contractChanges: [],
- familyMembers: [],
- files: [],
- leaveInfo: {
- ...emptyLeaveInfo(),
- enabled: listStatus === "inactive",
- position: positionNames[0] || raw.postName || "",
- department: raw.deptName || "",
- leaveDate,
- },
- raw,
- };
- }
- /** 合并 profile 聚合视图 */
- export function adaptEmployeeProfile(profile = {}) {
- const user = profile.user || {};
- return adaptEmployee(user, {
- workExperiences: profile.workExperiences || [],
- history: profile.history || [],
- performanceRecords: profile.performanceRecords || [],
- changes: profile.changes || [],
- });
- }
- /**
- * 员工档案表单 → 后端「员工新增或修改参数」
- * 合同 contracts 已废弃,不提交;工作履历走独立接口
- */
- export function serializeEmployee(form = {}) {
- const statusText = form.formStatus || form.status;
- const statusCode =
- EMPLOYEE_STATUS[statusText] ??
- (statusText === "inactive" || statusText === "disabled"
- ? 6
- : statusText === "probation"
- ? 5
- : Number(statusText) || 1);
- const education = form.educations?.[0] || {};
- const bankAccounts = form.bankAccounts || [];
- const firstBank = bankAccounts[0] || {};
- const positionIds = (
- form.positionId
- ? [form.positionId]
- : Array.isArray(form.positionIds)
- ? form.positionIds
- : []
- )
- .filter(Boolean)
- .map(String)
- .slice(0, 1);
- const professionIds = (form.workTypes || [])
- .map((item) => item.id)
- .filter((id) => id != null && id !== "");
- const avatarUrl =
- typeof form.avatar === "string" && /^https?:\/\//i.test(form.avatar)
- ? form.avatar
- : undefined;
- return compact({
- id: form.id || undefined,
- name: form.name || "",
- jobNumber: form.employeeNo || "",
- sex: EMPLOYEE_SEX[form.gender] ?? form.gender,
- birthday: form.birthDate || "",
- age: Number(form.age) || undefined,
- idCard: form.idCard || "",
- idNumber: form.idCard || "",
- ethnic: form.ethnic || "",
- politicsStatus: form.politicalStatus || "",
- maritalStatus: form.maritalStatus || "",
- birthplace: form.nativePlace || "",
- censusAddress: form.registeredAddress || "",
- currentAddress: form.currentAddress || "",
- address: form.workAddress || "",
- educationBackground: education.education || form.education || "",
- school: education.school || form.school || "",
- major: education.major || form.major || "",
- graduateDate: education.graduationDate || form.graduationDate || "",
- phone: form.phone || "",
- email: form.email || "",
- wxId: form.wechat || "",
- status: statusCode,
- joinDate: form.hireDate || "",
- positiveDate: form.regularDate || "",
- leaveDate: form.leaveInfo?.leaveDate || "",
- isEnabled: form.enabled === false || statusText === "disabled" ? 0 : 1,
- openingBank: firstBank.bankName || form.bankName || "",
- cardNumber: firstBank.bankAccount || form.bankAccount || "",
- bankCardList: bankAccounts.length
- ? bankAccounts
- .filter((item) => item.bankAccount || item.bankName)
- .map((item) => ({
- openingBank: item.bankName || "",
- cardNumber: item.bankAccount || "",
- accountName: item.bankAccountName || form.name || "",
- }))
- : undefined,
- secondLinkName: form.emergencyContact || "",
- secondLinkPhone: form.emergencyPhone || "",
- secondLinkRelation: form.emergencyRelation || "",
- pic: avatarUrl,
- professionId: professionIds.length ? professionIds.map(String).join(",") : undefined,
- workTypeId: professionIds.length ? toApiId(professionIds[0]) : undefined,
- remark: form.remarks || "",
- groupId: form.groupId || undefined,
- deptIds: (Array.isArray(form.deptIds) && form.deptIds.length
- ? form.deptIds
- : form.deptId
- ? [form.deptId]
- : []
- )
- .map((id) => toApiId(id))
- .filter((id) => id != null),
- deptName: form.deptName || "",
- managerUserId: toApiId(form.managerId || form.managerUserId),
- // 岗位:界面只选岗位;提交仍需 positionList 必填的层级/序列主键(由前端按岗位档案解析)
- postId: positionIds.length ? positionIds.join(",") : undefined,
- postName: form.position || undefined,
- positionList: positionIds.length
- ? [
- (() => {
- const id = positionIds[0];
- const binding =
- (Array.isArray(form.positionBindings) ? form.positionBindings : []).find(
- (item) => String(item.positionId) === String(id),
- ) || {};
- return {
- positionId: toApiId(id),
- positionLevelId: toApiId(binding.positionLevelId),
- positionSequenceId: toApiId(binding.positionSequenceId),
- primaryFlag: 1,
- };
- })(),
- ]
- : [],
- factoryId: form.factoryId ? toApiId(form.factoryId) : undefined,
- socialSecurityList: (form.socialSecurityRecords || [])
- .filter((item) => item.type || item.insuredDate)
- .map((item) => ({
- socialType: item.type || "",
- socialBase: Number(item.base) || 0,
- insuredDate: item.insuredDate || "",
- stopDate: item.stopDate || "",
- stopRecord: item.stopReason || "",
- })),
- // skills / trainRecords 已废弃:非空提交会被后端拒绝,技能/培训走独立 HR / EHS 接口
- rewardsPunishments: (form.rewardPunishmentRecords || []).map((item) => ({
- id: item.id || undefined,
- type: /惩罚|处分|警告/.test(item.type) ? 2 : 1,
- desce: item.description || item.name || "",
- startTime: item.startDate || item.date || "",
- endTime: item.endDate || "",
- status: REWARD_STATUS[item.status] ?? 2,
- remark: item.remark || "",
- })),
- identityPhotos: (form.certificates || [])
- .filter((item) => item.type || item.number)
- .map((item) => ({
- id: item.id || undefined,
- type: CERT_TYPE[item.type] ?? 4,
- code: item.number || "",
- level: CERT_LEVEL[item.level] || item.level || "",
- status: item.status === "失效" ? 0 : 1,
- validityStartTime: item.startDate || "",
- validityEndTime: item.endDate || "",
- enactorTime: item.issueDate || "",
- remark: item.remark || "",
- holderType: "1",
- holder: form.name || "",
- })),
- });
- }
- export function serializeWorkExperience(item = {}) {
- return compact({
- formerCompanyName: item.company || "",
- formerDepartment: item.department || "",
- formerPosition: item.position || "",
- resignationReason: item.leaveReason || "",
- workDescription: item.description || "",
- workStartDate: item.startDate || item.dateRange?.[0] || "",
- workEndDate: item.endDate || item.dateRange?.[1] || "",
- });
- }
- /** 保存员工后同步入职前工作履历(独立接口) */
- export async function syncWorkExperiences(userId, jobs = [], existing = []) {
- if (!userId) return;
- const next = (jobs || []).filter((item) => item.company && item.startDate && item.endDate);
- const keptIds = new Set(next.map((item) => item.id).filter(Boolean).map(String));
- const removals = (existing || [])
- .filter((item) => item.id && !keptIds.has(String(item.id)))
- .map((item) => removeWorkExperience(userId, item.id));
- await Promise.all(removals);
- await Promise.all(
- next.map((item) => {
- const payload = serializeWorkExperience(item);
- if (item.id) return updateWorkExperience(userId, item.id, payload);
- return saveWorkExperience(userId, payload);
- }),
- );
- }
|