feat: 前端-接入gbs用户信息
parent
07d8816010
commit
984fc3c64a
|
|
@ -1,10 +1,13 @@
|
||||||
/** 企业信息管理:前后端字段与分页格式适配 */
|
/** 企业信息管理:前后端字段与分页格式适配 */
|
||||||
|
|
||||||
import { formatDate, formatDateTime, toApiDate, toApiDateTime } from "../../utils/dateFormat";
|
import { formatDate, formatDateTime, toApiDate, toApiDateTime } from "../../utils/dateFormat";
|
||||||
|
import { asId, isIdFieldName, normalizeQueryIds } from "./idUtil";
|
||||||
|
import { withOrgId } from "./orgContext";
|
||||||
|
|
||||||
const GENDER_NAME = { 1: "男", 2: "女" };
|
const GENDER_NAME = { 1: "男", 2: "女" };
|
||||||
const RESIGN_AUDIT_STATUS_NAME = { 0: "未审核", 1: "已审核", 2: "已退回" };
|
const RESIGN_AUDIT_STATUS_NAME = { 0: "未审核", 1: "已审核", 2: "已退回" };
|
||||||
|
|
||||||
|
/** 分页查询参数:子表 org_id → org_info.id;机构信息管理 getInfo 不走此方法 */
|
||||||
export function toPageQuery(params = {}, fieldMap = {}) {
|
export function toPageQuery(params = {}, fieldMap = {}) {
|
||||||
const query = {
|
const query = {
|
||||||
current: params.pageIndex ?? params.current ?? 1,
|
current: params.pageIndex ?? params.current ?? 1,
|
||||||
|
|
@ -13,10 +16,10 @@ export function toPageQuery(params = {}, fieldMap = {}) {
|
||||||
Object.entries(fieldMap).forEach(([from, to]) => {
|
Object.entries(fieldMap).forEach(([from, to]) => {
|
||||||
const value = params[from];
|
const value = params[from];
|
||||||
if (value !== undefined && value !== null && value !== "") {
|
if (value !== undefined && value !== null && value !== "") {
|
||||||
query[to] = value;
|
query[to] = isIdFieldName(to) ? asId(value) : value;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return query;
|
return withOrgId(normalizeQueryIds(query));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fromPageResponse(res, mapItem) {
|
export function fromPageResponse(res, mapItem) {
|
||||||
|
|
@ -45,7 +48,7 @@ function pick(obj, keys) {
|
||||||
const next = {};
|
const next = {};
|
||||||
keys.forEach((key) => {
|
keys.forEach((key) => {
|
||||||
if (obj[key] !== undefined) {
|
if (obj[key] !== undefined) {
|
||||||
next[key] = obj[key];
|
next[key] = isIdFieldName(key) ? asId(obj[key]) : obj[key];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return next;
|
return next;
|
||||||
|
|
@ -55,7 +58,7 @@ function pick(obj, keys) {
|
||||||
|
|
||||||
export function toOrgInfoForm(data = {}) {
|
export function toOrgInfoForm(data = {}) {
|
||||||
return {
|
return {
|
||||||
id: data.id,
|
id: asId(data.id),
|
||||||
orgName: data.unitName,
|
orgName: data.unitName,
|
||||||
creditCode: data.creditCode,
|
creditCode: data.creditCode,
|
||||||
safetyIndustryCategory: data.safetyIndustryCategoryName,
|
safetyIndustryCategory: data.safetyIndustryCategoryName,
|
||||||
|
|
@ -125,8 +128,8 @@ export function fromOrgInfoForm(values = {}, options = {}) {
|
||||||
|
|
||||||
export function toDepartmentForm(data = {}) {
|
export function toDepartmentForm(data = {}) {
|
||||||
return {
|
return {
|
||||||
id: data.id,
|
id: asId(data.id),
|
||||||
parentId: data.parentId,
|
parentId: asId(data.parentId),
|
||||||
deptName: data.deptName,
|
deptName: data.deptName,
|
||||||
leaderName: data.managerName,
|
leaderName: data.managerName,
|
||||||
leaderAccount: data.managerAccount,
|
leaderAccount: data.managerAccount,
|
||||||
|
|
@ -148,13 +151,14 @@ export function fromDepartmentForm(values = {}) {
|
||||||
export function buildDepartmentTree(departments = []) {
|
export function buildDepartmentTree(departments = []) {
|
||||||
const map = new Map();
|
const map = new Map();
|
||||||
departments.forEach((item) => {
|
departments.forEach((item) => {
|
||||||
map.set(item.id, { ...toDepartmentForm(item), children: [] });
|
map.set(asId(item.id), { ...toDepartmentForm(item), children: [] });
|
||||||
});
|
});
|
||||||
const roots = [];
|
const roots = [];
|
||||||
departments.forEach((item) => {
|
departments.forEach((item) => {
|
||||||
const node = map.get(item.id);
|
const node = map.get(asId(item.id));
|
||||||
if (item.parentId != null && item.parentId !== 0 && map.has(item.parentId)) {
|
const parentId = asId(item.parentId);
|
||||||
map.get(item.parentId).children.push(node);
|
if (parentId != null && parentId !== "0" && map.has(parentId)) {
|
||||||
|
map.get(parentId).children.push(node);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
roots.push(node);
|
roots.push(node);
|
||||||
|
|
@ -165,8 +169,8 @@ export function buildDepartmentTree(departments = []) {
|
||||||
|
|
||||||
export function toPositionForm(data = {}) {
|
export function toPositionForm(data = {}) {
|
||||||
return {
|
return {
|
||||||
id: data.id,
|
id: asId(data.id),
|
||||||
deptId: data.deptId,
|
deptId: asId(data.deptId),
|
||||||
deptName: data.deptName,
|
deptName: data.deptName,
|
||||||
positionName: data.positionName,
|
positionName: data.positionName,
|
||||||
dutyDesc: data.dutyDesc,
|
dutyDesc: data.dutyDesc,
|
||||||
|
|
@ -175,10 +179,9 @@ export function toPositionForm(data = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fromPositionForm(values = {}) {
|
export function fromPositionForm(values = {}) {
|
||||||
const deptId = values.deptId != null && values.deptId !== "" ? Number(values.deptId) : undefined;
|
|
||||||
return {
|
return {
|
||||||
...pick(values, ["id", "tenantId"]),
|
...pick(values, ["id", "tenantId"]),
|
||||||
deptId,
|
deptId: asId(values.deptId),
|
||||||
positionName: values.positionName,
|
positionName: values.positionName,
|
||||||
dutyDesc: values.dutyDesc,
|
dutyDesc: values.dutyDesc,
|
||||||
remark: values.remark,
|
remark: values.remark,
|
||||||
|
|
@ -189,13 +192,13 @@ export function fromPositionForm(values = {}) {
|
||||||
|
|
||||||
export function toStaffForm(data = {}) {
|
export function toStaffForm(data = {}) {
|
||||||
return {
|
return {
|
||||||
id: data.id,
|
id: asId(data.id),
|
||||||
staffName: data.userName,
|
staffName: data.userName,
|
||||||
account: data.account,
|
account: data.account,
|
||||||
gender: data.genderCode,
|
gender: data.genderCode,
|
||||||
birthDate: data.birthDate,
|
birthDate: data.birthDate,
|
||||||
deptId: data.deptId,
|
deptId: asId(data.deptId),
|
||||||
positionId: data.postId,
|
positionId: asId(data.postId),
|
||||||
idCardNo: data.idCardNo,
|
idCardNo: data.idCardNo,
|
||||||
homeAddress: data.currentAddress,
|
homeAddress: data.currentAddress,
|
||||||
officeAddress: data.officeAddress,
|
officeAddress: data.officeAddress,
|
||||||
|
|
@ -212,13 +215,14 @@ export function toStaffForm(data = {}) {
|
||||||
export function fromStaffForm(values = {}) {
|
export function fromStaffForm(values = {}) {
|
||||||
const genderCode = values.gender;
|
const genderCode = values.gender;
|
||||||
return {
|
return {
|
||||||
...pick(values, ["id", "tenantId", "deptId", "postId"]),
|
...pick(values, ["id", "tenantId"]),
|
||||||
userName: values.staffName,
|
userName: values.staffName,
|
||||||
account: values.account,
|
account: values.account,
|
||||||
genderCode,
|
genderCode,
|
||||||
genderName: GENDER_NAME[genderCode] ?? values.genderName,
|
genderName: GENDER_NAME[genderCode] ?? values.genderName,
|
||||||
birthDate: toApiDate(values.birthDate),
|
birthDate: toApiDate(values.birthDate),
|
||||||
postId: values.positionId ?? values.postId,
|
deptId: asId(values.deptId),
|
||||||
|
postId: asId(values.positionId ?? values.postId),
|
||||||
idCardNo: values.idCardNo,
|
idCardNo: values.idCardNo,
|
||||||
currentAddress: values.homeAddress,
|
currentAddress: values.homeAddress,
|
||||||
officeAddress: values.officeAddress,
|
officeAddress: values.officeAddress,
|
||||||
|
|
@ -238,8 +242,8 @@ export function toStaffCertForm(data = {}) {
|
||||||
? [{ url: data.certAttachmentUrl, fileName: data.certName }]
|
? [{ url: data.certAttachmentUrl, fileName: data.certName }]
|
||||||
: data.certImgFiles || [];
|
: data.certImgFiles || [];
|
||||||
return {
|
return {
|
||||||
id: data.id,
|
id: asId(data.id),
|
||||||
staffId: data.personnelId,
|
staffId: asId(data.personnelId),
|
||||||
certName: data.certName,
|
certName: data.certName,
|
||||||
certCategory: data.certCategoryName ?? data.certCategoryCode,
|
certCategory: data.certCategoryName ?? data.certCategoryCode,
|
||||||
certWorkCategory: data.operationCategoryName ?? data.operationCategoryCode,
|
certWorkCategory: data.operationCategoryName ?? data.operationCategoryCode,
|
||||||
|
|
@ -259,7 +263,7 @@ export function fromStaffCertForm(values = {}) {
|
||||||
|| values.certImgFiles?.[0]?.url;
|
|| values.certImgFiles?.[0]?.url;
|
||||||
return {
|
return {
|
||||||
...pick(values, ["id", "tenantId"]),
|
...pick(values, ["id", "tenantId"]),
|
||||||
personnelId: values.staffId,
|
personnelId: asId(values.staffId),
|
||||||
certName: values.certName,
|
certName: values.certName,
|
||||||
certCategoryName: values.certCategory,
|
certCategoryName: values.certCategory,
|
||||||
certCategoryCode: values.certCategory,
|
certCategoryCode: values.certCategory,
|
||||||
|
|
@ -281,7 +285,7 @@ export function toQualificationForm(data = {}) {
|
||||||
? [{ url: data.certImageUrl, fileName: data.certName }]
|
? [{ url: data.certImageUrl, fileName: data.certName }]
|
||||||
: data.certImgFiles || [];
|
: data.certImgFiles || [];
|
||||||
return {
|
return {
|
||||||
id: data.id,
|
id: asId(data.id),
|
||||||
certType: data.licenseTypeName ?? data.licenseTypeCode,
|
certType: data.licenseTypeName ?? data.licenseTypeCode,
|
||||||
certName: data.certName,
|
certName: data.certName,
|
||||||
certNo: data.certNo,
|
certNo: data.certNo,
|
||||||
|
|
@ -324,8 +328,7 @@ export function fromQualificationForm(values = {}) {
|
||||||
export function toEquipForm(data = {}) {
|
export function toEquipForm(data = {}) {
|
||||||
const instrumentType = data.instrumentTypeName ?? data.instrumentTypeCode;
|
const instrumentType = data.instrumentTypeName ?? data.instrumentTypeCode;
|
||||||
return {
|
return {
|
||||||
id: data.id,
|
id: asId(data.id),
|
||||||
instrumentCategory: instrumentType,
|
|
||||||
instrumentType,
|
instrumentType,
|
||||||
deviceType: data.deviceTypeName ?? data.deviceTypeCode,
|
deviceType: data.deviceTypeName ?? data.deviceTypeCode,
|
||||||
deviceName: data.deviceName,
|
deviceName: data.deviceName,
|
||||||
|
|
@ -368,8 +371,8 @@ export function fromEquipForm(values = {}) {
|
||||||
|
|
||||||
export function toChangeLogForm(data = {}) {
|
export function toChangeLogForm(data = {}) {
|
||||||
return {
|
return {
|
||||||
id: data.id,
|
id: asId(data.id),
|
||||||
staffId: data.personnelId,
|
staffId: asId(data.personnelId),
|
||||||
changeItem: data.changeItem,
|
changeItem: data.changeItem,
|
||||||
changeTime: formatDateTime(data.changeTime),
|
changeTime: formatDateTime(data.changeTime),
|
||||||
createBy: data.operatorName,
|
createBy: data.operatorName,
|
||||||
|
|
@ -379,8 +382,8 @@ export function toChangeLogForm(data = {}) {
|
||||||
export function toResignApplyForm(data = {}) {
|
export function toResignApplyForm(data = {}) {
|
||||||
const auditStatus = data.auditStatusCode ?? data.auditStatus ?? 0;
|
const auditStatus = data.auditStatusCode ?? data.auditStatus ?? 0;
|
||||||
return {
|
return {
|
||||||
id: data.id,
|
id: asId(data.id),
|
||||||
personnelId: data.personnelId,
|
personnelId: asId(data.personnelId),
|
||||||
applicantName: data.applicantName,
|
applicantName: data.applicantName,
|
||||||
applyTime: formatDateTime(data.applyTime),
|
applyTime: formatDateTime(data.applyTime),
|
||||||
expectedLeaveDate: formatDate(data.expectedResignDate),
|
expectedLeaveDate: formatDate(data.expectedResignDate),
|
||||||
|
|
@ -396,10 +399,9 @@ export function toResignApplyForm(data = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fromResignApplyForm(values = {}) {
|
export function fromResignApplyForm(values = {}) {
|
||||||
const personnelId = values.personnelId;
|
|
||||||
return {
|
return {
|
||||||
...pick(values, ["id", "tenantId"]),
|
...pick(values, ["id", "tenantId"]),
|
||||||
personnelId: personnelId != null && personnelId !== "" ? Number(personnelId) : undefined,
|
personnelId: asId(values.personnelId),
|
||||||
applicantName: values.applicantName,
|
applicantName: values.applicantName,
|
||||||
applyTime: toApiDateTime(values.applyTime),
|
applyTime: toApiDateTime(values.applyTime),
|
||||||
expectedResignDate: toApiDate(values.expectedLeaveDate),
|
expectedResignDate: toApiDate(values.expectedLeaveDate),
|
||||||
|
|
@ -414,8 +416,8 @@ export function fromResignApplyForm(values = {}) {
|
||||||
export function fromResignAuditForm(values = {}) {
|
export function fromResignAuditForm(values = {}) {
|
||||||
const auditStatus = values.auditStatus;
|
const auditStatus = values.auditStatus;
|
||||||
return {
|
return {
|
||||||
id: values.id,
|
id: asId(values.id),
|
||||||
personnelId: values.personnelId,
|
personnelId: asId(values.personnelId),
|
||||||
auditStatusCode: auditStatus,
|
auditStatusCode: auditStatus,
|
||||||
auditStatusName: auditStatus === 1 ? "已审核" : auditStatus === 2 ? "已退回" : "未审核",
|
auditStatusName: auditStatus === 1 ? "已审核" : auditStatus === 2 ? "已退回" : "未审核",
|
||||||
rejectReason: values.rejectReason,
|
rejectReason: values.rejectReason,
|
||||||
|
|
@ -433,8 +435,8 @@ export function toStaffChangeSummary(personnel = {}) {
|
||||||
: Number(resignStatusRaw);
|
: Number(resignStatusRaw);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
id: personnel.id,
|
id: asId(personnel.id),
|
||||||
staffId: personnel.id,
|
staffId: asId(personnel.id),
|
||||||
account: personnel.account,
|
account: personnel.account,
|
||||||
staffName: personnel.userName ?? personnel.staffName,
|
staffName: personnel.userName ?? personnel.staffName,
|
||||||
deptName: personnel.deptName || "",
|
deptName: personnel.deptName || "",
|
||||||
|
|
@ -443,7 +445,7 @@ export function toStaffChangeSummary(personnel = {}) {
|
||||||
employmentStatusName: personnel.employmentStatusName
|
employmentStatusName: personnel.employmentStatusName
|
||||||
|| (employmentCode === 2 ? "离职" : "在职"),
|
|| (employmentCode === 2 ? "离职" : "在职"),
|
||||||
changeCount: Number(personnel.changeCount ?? 0),
|
changeCount: Number(personnel.changeCount ?? 0),
|
||||||
resignApplyId: personnel.resignApplyId,
|
resignApplyId: asId(personnel.resignApplyId),
|
||||||
resignAuditStatus: resignStatus,
|
resignAuditStatus: resignStatus,
|
||||||
resignAuditStatusName: personnel.resignAuditStatusName
|
resignAuditStatusName: personnel.resignAuditStatusName
|
||||||
?? (resignStatus !== null ? RESIGN_AUDIT_STATUS_NAME[resignStatus] : undefined),
|
?? (resignStatus !== null ? RESIGN_AUDIT_STATUS_NAME[resignStatus] : undefined),
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,25 @@
|
||||||
import { Get, Post } from "@cqsjjb/jjb-common-lib/http";
|
import { Get, Post } from "@cqsjjb/jjb-common-lib/http";
|
||||||
|
import { normalizeQueryIds, withIds, asId } from "./idUtil";
|
||||||
|
import { buildOrgInfoHeaders } from "./orgContext";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jjb-common-lib 在 jjbCommonHttpConfig.header 存在时会完全替换请求头、不再读 sessionStorage。
|
||||||
|
* 因此 token / orgInfoId 都通过每次请求的 headers 参数显式传入。
|
||||||
|
*
|
||||||
|
* @param options.includeOrgContext 默认 true;机构 getInfo 查询应传 false(不带 orgInfoId)
|
||||||
|
*/
|
||||||
|
function buildRequestHeaders(extraHeaders = {}, options = {}) {
|
||||||
|
const { includeOrgContext = true } = options;
|
||||||
|
const headers = { ...extraHeaders };
|
||||||
|
const token = sessionStorage.getItem("token");
|
||||||
|
if (token && !headers.token) {
|
||||||
|
headers.token = token;
|
||||||
|
}
|
||||||
|
if (!includeOrgContext) {
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
return buildOrgInfoHeaders(headers);
|
||||||
|
}
|
||||||
|
|
||||||
function parseHttpError(err) {
|
function parseHttpError(err) {
|
||||||
const data = err?.response?.data;
|
const data = err?.response?.data;
|
||||||
|
|
@ -14,9 +35,9 @@ function parseHttpError(err) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 底层 HTTP,供 adapter 层组合调用(不可嵌套 declareRequest) */
|
/** 底层 HTTP,供 adapter 层组合调用(不可嵌套 declareRequest) */
|
||||||
export async function apiGet(path, params = {}) {
|
export async function apiGet(path, params = {}, headers = {}, options = {}) {
|
||||||
try {
|
try {
|
||||||
return await Get(path, params);
|
return await Get(path, normalizeQueryIds(params), buildRequestHeaders(headers, options));
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
return parseHttpError(err);
|
return parseHttpError(err);
|
||||||
|
|
@ -24,10 +45,10 @@ export async function apiGet(path, params = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @ 前缀表示 Post 请求体不包裹 request 字段 */
|
/** @ 前缀表示 Post 请求体不包裹 request 字段 */
|
||||||
export async function apiPost(path, data = {}) {
|
export async function apiPost(path, data = {}, headers = {}) {
|
||||||
const url = path.startsWith("@") ? path : `@${path}`;
|
const url = path.startsWith("@") ? path : `@${path}`;
|
||||||
try {
|
try {
|
||||||
return await Post(url, data);
|
return await Post(url, withIds(data), buildRequestHeaders(headers));
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
return parseHttpError(err);
|
return parseHttpError(err);
|
||||||
|
|
@ -35,9 +56,9 @@ export async function apiPost(path, data = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function apiPostDelete(path, id) {
|
export async function apiPostDelete(path, id) {
|
||||||
const url = `${path}?id=${encodeURIComponent(id)}`;
|
const url = `${path}?id=${encodeURIComponent(asId(id) ?? "")}`;
|
||||||
try {
|
try {
|
||||||
return await Post(url, {});
|
return await Post(url, {}, buildRequestHeaders());
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
return parseHttpError(err);
|
return parseHttpError(err);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
/**
|
||||||
|
* 雪花 ID 全局处理:禁止 Number(),统一字符串传递。
|
||||||
|
* JS Number.MAX_SAFE_INTEGER = 9007199254740991,雪花 id 超出后会精度丢失。
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function asId(value) {
|
||||||
|
if (value == null || value === "") {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return String(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 是否像主键/外键字段名 */
|
||||||
|
export function isIdFieldName(key) {
|
||||||
|
return key === "id" || key.endsWith("Id");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 对象内所有 *Id / id 字段转字符串 */
|
||||||
|
export function withIds(obj = {}) {
|
||||||
|
if (!obj || typeof obj !== "object") {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
const next = { ...obj };
|
||||||
|
Object.keys(next).forEach((key) => {
|
||||||
|
if (isIdFieldName(key) && next[key] != null && next[key] !== "") {
|
||||||
|
next[key] = asId(next[key]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 分页/查询参数中的 id 字段转字符串 */
|
||||||
|
export function normalizeQueryIds(query = {}) {
|
||||||
|
const next = { ...query };
|
||||||
|
Object.keys(next).forEach((key) => {
|
||||||
|
if (isIdFieldName(key) && next[key] != null && next[key] !== "") {
|
||||||
|
next[key] = asId(next[key]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 兼容历史 Number() 精度丢失:比较雪花 id 前 16 位 */
|
||||||
|
export function sameId(a, b) {
|
||||||
|
const sa = asId(a);
|
||||||
|
const sb = asId(b);
|
||||||
|
if (!sa || !sb) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (sa === sb) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return sa.slice(0, 16) === sb.slice(0, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @deprecated 使用 sameId */
|
||||||
|
export const sameDeptId = sameId;
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
/**
|
||||||
|
* 企业信息模块初始化与下拉数据拉取(绕过 DVA,避免 loading 状态导致页面重渲染死循环)
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
fromPageResponse,
|
||||||
|
fromSingleResponse,
|
||||||
|
toDepartmentForm,
|
||||||
|
toOrgInfoForm,
|
||||||
|
toPageQuery,
|
||||||
|
toPositionForm,
|
||||||
|
} from "./adapter";
|
||||||
|
import { apiGet } from "./http";
|
||||||
|
import { getOrgInfoId, setOrgInfoId } from "./orgContext";
|
||||||
|
|
||||||
|
let ensureOrgPromise = null;
|
||||||
|
|
||||||
|
/** 确保已缓存机构 id(全局只发起一次 getInfo) */
|
||||||
|
export function ensureOrgContext() {
|
||||||
|
const cached = getOrgInfoId();
|
||||||
|
if (cached) {
|
||||||
|
return Promise.resolve(cached);
|
||||||
|
}
|
||||||
|
if (!ensureOrgPromise) {
|
||||||
|
ensureOrgPromise = apiGet("/safety-eval/org-info/getInfo", {}, {}, { includeOrgContext: false })
|
||||||
|
.then((res) => {
|
||||||
|
const result = fromSingleResponse(res, toOrgInfoForm);
|
||||||
|
const id = result?.data?.id ?? res?.data?.id;
|
||||||
|
if (id) {
|
||||||
|
setOrgInfoId(id);
|
||||||
|
}
|
||||||
|
return getOrgInfoId();
|
||||||
|
})
|
||||||
|
.catch(() => null)
|
||||||
|
.finally(() => {
|
||||||
|
ensureOrgPromise = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return ensureOrgPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchOrgDepartmentPage(params = {}) {
|
||||||
|
await ensureOrgContext();
|
||||||
|
const query = toPageQuery(params, { likeDeptName: "deptName" });
|
||||||
|
const res = await apiGet("/safety-eval/org-department/page", query);
|
||||||
|
return fromPageResponse(res, toDepartmentForm);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchOrgPositionPage(params = {}) {
|
||||||
|
await ensureOrgContext();
|
||||||
|
const query = toPageQuery(params, {
|
||||||
|
eqDeptId: "deptId",
|
||||||
|
likePositionName: "positionName",
|
||||||
|
});
|
||||||
|
const res = await apiGet("/safety-eval/org-position/page", query);
|
||||||
|
return fromPageResponse(res, toPositionForm);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
/** 当前登录用户关联的机构 id,供企业信息模块接口请求头 orgInfoId 使用 */
|
||||||
|
|
||||||
|
const ORG_INFO_ID_KEY = "orgInfoId";
|
||||||
|
|
||||||
|
let memoryOrgInfoId = null;
|
||||||
|
|
||||||
|
export function getOrgInfoId() {
|
||||||
|
return memoryOrgInfoId || sessionStorage.getItem(ORG_INFO_ID_KEY) || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setOrgInfoId(id) {
|
||||||
|
if (id != null && id !== "") {
|
||||||
|
memoryOrgInfoId = String(id);
|
||||||
|
sessionStorage.setItem(ORG_INFO_ID_KEY, memoryOrgInfoId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clearOrgInfoId() {
|
||||||
|
memoryOrgInfoId = null;
|
||||||
|
sessionStorage.removeItem(ORG_INFO_ID_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 分页/查询参数:前端缓存 orgInfoId → 后端字段 orgId */
|
||||||
|
export function withOrgId(params = {}) {
|
||||||
|
if (params.orgId != null && params.orgId !== "") {
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
const orgInfoId = getOrgInfoId();
|
||||||
|
if (orgInfoId) {
|
||||||
|
return { ...params, orgId: orgInfoId };
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 合并业务请求头,仅通过每次请求的 headers 参数传递,不写入 jjbCommonHttpConfig */
|
||||||
|
export function buildOrgInfoHeaders(extraHeaders = {}) {
|
||||||
|
const id = extraHeaders.orgInfoId || getOrgInfoId();
|
||||||
|
if (!id) {
|
||||||
|
return extraHeaders;
|
||||||
|
}
|
||||||
|
return { ...extraHeaders, orgInfoId: String(id) };
|
||||||
|
}
|
||||||
|
|
||||||
|
// 页面刷新后从 sessionStorage 恢复
|
||||||
|
const storedOrgInfoId = sessionStorage.getItem(ORG_INFO_ID_KEY);
|
||||||
|
if (storedOrgInfoId) {
|
||||||
|
memoryOrgInfoId = storedOrgInfoId;
|
||||||
|
}
|
||||||
|
|
@ -15,7 +15,7 @@ export const orgDepartmentGet = declareRequest("orgDepartmentLoading", safeActio
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const orgDepartmentTree = declareRequest("orgDepartmentLoading", safeAction(async () => {
|
export const orgDepartmentTree = declareRequest("orgDepartmentLoading", safeAction(async () => {
|
||||||
const res = await apiGet("/safety-eval/org-department/page", { current: 1, size: 500 });
|
const res = await apiGet("/safety-eval/org-department/page", toPageQuery({ current: 1, size: 500 }));
|
||||||
const pageData = fromPageResponse(res, toDepartmentForm);
|
const pageData = fromPageResponse(res, toDepartmentForm);
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,52 @@
|
||||||
import { declareRequest } from "@cqsjjb/jjb-dva-runtime";
|
import { declareRequest } from "@cqsjjb/jjb-dva-runtime";
|
||||||
import {
|
import {
|
||||||
fromOrgInfoForm,
|
fromOrgInfoForm,
|
||||||
fromPageResponse,
|
|
||||||
fromSingleResponse,
|
fromSingleResponse,
|
||||||
toOrgInfoForm,
|
toOrgInfoForm,
|
||||||
} from "../enterpriseInfo/adapter";
|
} from "../enterpriseInfo/adapter";
|
||||||
import { apiGet, apiPost, safeAction } from "../enterpriseInfo/http";
|
import { apiGet, apiPost, safeAction } from "../enterpriseInfo/http";
|
||||||
|
import { setOrgInfoId } from "../enterpriseInfo/orgContext";
|
||||||
|
|
||||||
|
function persistOrgInfoId(result, rawData) {
|
||||||
|
const id = result?.data?.id ?? rawData?.id;
|
||||||
|
if (id) {
|
||||||
|
setOrgInfoId(id);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildSaveHeaders(payload) {
|
||||||
|
if (payload?.id) {
|
||||||
|
setOrgInfoId(payload.id);
|
||||||
|
return { orgInfoId: String(payload.id) };
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
export const orgInfoGet = declareRequest("orgInfoLoading", safeAction(async () => {
|
export const orgInfoGet = declareRequest("orgInfoLoading", safeAction(async () => {
|
||||||
const pageRes = await apiGet("/safety-eval/org-info/page", { current: 1, size: 1 });
|
const res = await apiGet("/safety-eval/org-info/getInfo", {}, {}, { includeOrgContext: false });
|
||||||
const pageData = fromPageResponse(pageRes, toOrgInfoForm);
|
const result = fromSingleResponse(res, toOrgInfoForm);
|
||||||
const first = pageData.data?.[0];
|
return persistOrgInfoId(result, res?.data);
|
||||||
if (!first?.id) {
|
|
||||||
return { success: true, data: null };
|
|
||||||
}
|
|
||||||
const detailRes = await apiGet("/safety-eval/org-info/get", { id: first.id });
|
|
||||||
return fromSingleResponse(detailRes, toOrgInfoForm);
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const orgInfoSave = declareRequest("orgInfoLoading", safeAction(async (values) => {
|
export const orgInfoSave = declareRequest("orgInfoLoading", safeAction(async (values) => {
|
||||||
const payload = fromOrgInfoForm(values, { isDraft: false });
|
const payload = fromOrgInfoForm(values, { isDraft: false });
|
||||||
|
const headers = buildSaveHeaders(payload);
|
||||||
const res = payload.id
|
const res = payload.id
|
||||||
? await apiPost("/safety-eval/org-info/modify", payload)
|
? await apiPost("/safety-eval/org-info/modify", payload, headers)
|
||||||
: await apiPost("/safety-eval/org-info/save", payload);
|
: await apiPost("/safety-eval/org-info/save", payload, headers);
|
||||||
return fromSingleResponse(res, toOrgInfoForm);
|
const result = fromSingleResponse(res, toOrgInfoForm);
|
||||||
|
persistOrgInfoId(result, res?.data);
|
||||||
|
return result;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const orgInfoDraft = declareRequest("orgInfoLoading", safeAction(async (values) => {
|
export const orgInfoDraft = declareRequest("orgInfoLoading", safeAction(async (values) => {
|
||||||
const payload = fromOrgInfoForm(values, { isDraft: true });
|
const payload = fromOrgInfoForm(values, { isDraft: true });
|
||||||
|
const headers = buildSaveHeaders(payload);
|
||||||
const res = payload.id
|
const res = payload.id
|
||||||
? await apiPost("/safety-eval/org-info/modify", payload)
|
? await apiPost("/safety-eval/org-info/modify", payload, headers)
|
||||||
: await apiPost("/safety-eval/org-info/save", payload);
|
: await apiPost("/safety-eval/org-info/save", payload, headers);
|
||||||
return fromSingleResponse(res, toOrgInfoForm);
|
const result = fromSingleResponse(res, toOrgInfoForm);
|
||||||
|
persistOrgInfoId(result, res?.data);
|
||||||
|
return result;
|
||||||
}));
|
}));
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ if (!window.__POWERED_BY_QIANKUN__) {
|
||||||
// 本地开发时注入 Token,使 API 请求可携带认证信息
|
// 本地开发时注入 Token,使 API 请求可携带认证信息
|
||||||
sessionStorage.setItem(
|
sessionStorage.setItem(
|
||||||
"token",
|
"token",
|
||||||
"jjb-saas-auth:oauth:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ7XCJjbGllbnRJZFwiOlwiWlFBUVBKXCIsXCJhY2NvdW50SWRcIjoyMDY5Njc0MjM3ODc0MDEyMTYwLFwidXNlclR5cGVFbnVtXCI6XCJQTEFURk9STVwiLFwidXNlcklkXCI6MjA2OTY3NDIzNzE3MzQzNjQxNixcInRlbmFudElkXCI6MjA2OTU5NjM5NzkyMDg0OTkyMCxcInRlbmFudE5hbWVcIjpcIumHjeW6huWuieWFqOivhOS7t1wiLFwidGVuYW50UGFyZW50SWRzXCI6XCIwLDIwNjk1OTYzOTc5MjA4NDk5MjBcIixcIm5hbWVcIjpcInRlc3QwMVwiLFwiYWNjZXNzVGlja2V0XCI6XCJ2VnVmZjB1ck4xN21yT1BHTHFLcHBDV3BoRXAxTk96eTc5elp4THV1T3VLTUc5M1c4cENNd0NQZTN3MmlcIixcInJlZnJlc2hUaWNrZXRcIjpcIlhIeTRLZjJITXNYVjJCVHdnaWxUU0JXbDMxRGpObnVYVTBhUmRCZTlYRHpVTHVub2RMdnRveFpBeUFHclwiLFwiZXhwaXJlSW5cIjo2MDQ4MDAsXCJyZWZyZXNoRXhwaXJlc0luXCI6NjA0ODAwLFwib3JnSWRcIjoyMDY5NTk2Mzk3OTIwODQ5OTIwLFwib3JnTmFtZVwiOlwi6YeN5bqG5a6J5YWo6K-E5Lu3XCIsXCJvcmdJZHNcIjpbMjA2OTU5NjM5NzkyMDg0OTkyMF0sXCJyb2xlc1R5cGVzXCI6W1wiR0xZSlNcIl0sXCJyb2xlSWRzXCI6WzIwNjk2NzEzMDc1OTg4OTMwNThdLFwic2NvcGVzXCI6W10sXCJycGNUeXBlRW51bVwiOlwiSFRUUFwiLFwiYmluZE1vYmlsZVNpZ25cIjpcIkZBTFNFXCJ9IiwiaXNzIjoicHJvLXNlcnZlciIsImV4cCI6MTc4Mjg4ODYwNH0.Rypiw0-5EWQ8V_r7dr2A6ZHd82lwBcICX2t4WqybcJ0"
|
"jjb-saas-auth:oauth:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ7XCJjbGllbnRJZFwiOlwiWlFBUVBKXCIsXCJhY2NvdW50SWRcIjoyMDY5Njc0MjM3ODc0MDEyMTYwLFwidXNlclR5cGVFbnVtXCI6XCJQTEFURk9STVwiLFwidXNlcklkXCI6MjA2OTY3NDIzNzE3MzQzNjQxNixcInRlbmFudElkXCI6MjA2OTU5NjM5NzkyMDg0OTkyMCxcInRlbmFudE5hbWVcIjpcIumHjeW6huWuieWFqOivhOS7t1wiLFwidGVuYW50UGFyZW50SWRzXCI6XCIwLDIwNjk1OTYzOTc5MjA4NDk5MjBcIixcIm5hbWVcIjpcInRlc3QwMVwiLFwiYWNjZXNzVGlja2V0XCI6XCJ2Umg1RHRlNWJWcnc3NGxoZVgzRVVGYlVUV2l0MVJFbkVIc2ZWZnlGYnJwWDd1bmNsMGdsSmtJMWhvWWVcIixcInJlZnJlc2hUaWNrZXRcIjpcIlJva2VKeEcwYmIwYk1pMm8xUG53MjJpRkh6V21FSHVtWkFwSFI5dmptYmUyYm9DYkoyNnE3UmxIbUNlUFwiLFwiZXhwaXJlSW5cIjo2MDQ4MDAsXCJyZWZyZXNoRXhwaXJlc0luXCI6NjA0ODAwLFwib3JnSWRcIjoyMDY5NTk2Mzk3OTIwODQ5OTIwLFwib3JnTmFtZVwiOlwi6YeN5bqG5a6J5YWo6K-E5Lu3XCIsXCJvcmdJZHNcIjpbMjA2OTU5NjM5NzkyMDg0OTkyMF0sXCJyb2xlc1R5cGVzXCI6W1wiR0xZSlNcIl0sXCJyb2xlSWRzXCI6WzIwNjk2NzEzMDc1OTg4OTMwNThdLFwic2NvcGVzXCI6W10sXCJycGNUeXBlRW51bVwiOlwiSFRUUFwiLFwiYmluZE1vYmlsZVNpZ25cIjpcIkZBTFNFXCJ9IiwiaXNzIjoicHJvLXNlcnZlciIsImV4cCI6MTc4Mjk3MTE5Nn0.TagXXQBNyBioQQqhRFHwfgStlQmLi1s5StPOp-gSyzw"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,13 @@ import Search from "zy-react-library/components/Search";
|
||||||
import Table from "zy-react-library/components/Table";
|
import Table from "zy-react-library/components/Table";
|
||||||
import useTable from "zy-react-library/hooks/useTable";
|
import useTable from "zy-react-library/hooks/useTable";
|
||||||
import { NS_ORG_DEPARTMENT, NS_ORG_POSITION, NS_STAFF_INFO } from "~/enumerate/namespace";
|
import { NS_ORG_DEPARTMENT, NS_ORG_POSITION, NS_STAFF_INFO } from "~/enumerate/namespace";
|
||||||
|
import { asId, sameId } from "~/api/enterpriseInfo/idUtil";
|
||||||
import { safeListRequest, safeRequest } from "~/utils";
|
import { safeListRequest, safeRequest } from "~/utils";
|
||||||
import PageHeader from "../components/PageHeader";
|
import PageHeader from "../components/PageHeader";
|
||||||
|
|
||||||
function findDeptNode(nodes = [], id) {
|
function findDeptNode(nodes = [], id) {
|
||||||
for (const node of nodes) {
|
for (const node of nodes) {
|
||||||
if (String(node.id) === String(id)) {
|
if (sameId(node.id, id)) {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
if (node.children?.length) {
|
if (node.children?.length) {
|
||||||
|
|
@ -30,7 +31,7 @@ function toSelectedDept(node) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
id: node.id,
|
id: asId(node.id),
|
||||||
deptName: node.deptName || node.title,
|
deptName: node.deptName || node.title,
|
||||||
leaderAccount: node.leaderAccount,
|
leaderAccount: node.leaderAccount,
|
||||||
leaderName: node.leaderName,
|
leaderName: node.leaderName,
|
||||||
|
|
@ -71,7 +72,7 @@ function DepartmentPositionPage(props) {
|
||||||
form: positionForm,
|
form: positionForm,
|
||||||
transform: (formData) => ({
|
transform: (formData) => ({
|
||||||
...formData,
|
...formData,
|
||||||
eqDeptId: selectedDept?.id != null ? Number(selectedDept.id) : undefined,
|
eqDeptId: asId(selectedDept?.id),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
@ -136,7 +137,7 @@ function DepartmentPositionPage(props) {
|
||||||
const res = await props.orgDepartmentRemove({ id });
|
const res = await props.orgDepartmentRemove({ id });
|
||||||
if (res?.success !== false) {
|
if (res?.success !== false) {
|
||||||
message.success("删除成功");
|
message.success("删除成功");
|
||||||
if (String(selectedDept?.id) === String(id)) {
|
if (sameId(selectedDept?.id, id)) {
|
||||||
setSelectedDept(null);
|
setSelectedDept(null);
|
||||||
}
|
}
|
||||||
loadTree();
|
loadTree();
|
||||||
|
|
@ -174,7 +175,7 @@ function DepartmentPositionPage(props) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const openDeptModal = (record) => {
|
const openDeptModal = (record) => {
|
||||||
setCurrentId(record?.id || "");
|
setCurrentId(asId(record?.id) || "");
|
||||||
setDeptModalOpen(true);
|
setDeptModalOpen(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -183,17 +184,17 @@ function DepartmentPositionPage(props) {
|
||||||
message.warning("请先选择部门");
|
message.warning("请先选择部门");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setCurrentId(record?.id || "");
|
setCurrentId(asId(record?.id) || "");
|
||||||
modalForm.resetFields();
|
modalForm.resetFields();
|
||||||
if (record) {
|
if (record) {
|
||||||
modalForm.setFieldsValue({
|
modalForm.setFieldsValue({
|
||||||
...record,
|
...record,
|
||||||
deptId: record.deptId || selectedDept.id,
|
deptId: asId(record.deptId || selectedDept.id),
|
||||||
deptName: record.deptName || selectedDept.deptName,
|
deptName: record.deptName || selectedDept.deptName,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
modalForm.setFieldsValue({ deptId: selectedDept.id, deptName: selectedDept.deptName });
|
modalForm.setFieldsValue({ deptId: asId(selectedDept.id), deptName: selectedDept.deptName });
|
||||||
}
|
}
|
||||||
setPositionModalOpen(true);
|
setPositionModalOpen(true);
|
||||||
};
|
};
|
||||||
|
|
@ -204,7 +205,7 @@ function DepartmentPositionPage(props) {
|
||||||
if (currentId) {
|
if (currentId) {
|
||||||
payload.id = currentId;
|
payload.id = currentId;
|
||||||
}
|
}
|
||||||
payload.deptId = values.deptId || selectedDept?.id;
|
payload.deptId = asId(values.deptId || selectedDept?.id);
|
||||||
const res = await request(payload);
|
const res = await request(payload);
|
||||||
if (res?.success !== false) {
|
if (res?.success !== false) {
|
||||||
message.success(currentId ? "编辑成功" : "添加成功");
|
message.success(currentId ? "编辑成功" : "添加成功");
|
||||||
|
|
@ -232,7 +233,7 @@ function DepartmentPositionPage(props) {
|
||||||
/>
|
/>
|
||||||
</Space>
|
</Space>
|
||||||
<Tree
|
<Tree
|
||||||
selectedKeys={selectedDept?.id ? [selectedDept.id] : []}
|
selectedKeys={selectedDept?.id ? [asId(selectedDept.id)] : []}
|
||||||
treeData={filteredTree}
|
treeData={filteredTree}
|
||||||
fieldNames={{ title: "deptName", key: "id", children: "children" }}
|
fieldNames={{ title: "deptName", key: "id", children: "children" }}
|
||||||
onSelect={(_, { node }) => {
|
onSelect={(_, { node }) => {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||||
import { Button, DatePicker, Descriptions, Form, Input, message, Modal, Row, Col, Select, Space } from "antd";
|
import { Button, DatePicker, Descriptions, Form, Input, message, Modal, Row, Col, Select, Space } from "antd";
|
||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import AddIcon from "zy-react-library/components/Icon/AddIcon";
|
import AddIcon from "zy-react-library/components/Icon/AddIcon";
|
||||||
import Page from "zy-react-library/components/Page";
|
import Page from "zy-react-library/components/Page";
|
||||||
import Search from "zy-react-library/components/Search";
|
import Search from "zy-react-library/components/Search";
|
||||||
import Table from "zy-react-library/components/Table";
|
import Table from "zy-react-library/components/Table";
|
||||||
import useTable from "zy-react-library/hooks/useTable";
|
import useTable from "zy-react-library/hooks/useTable";
|
||||||
import { NS_ORG_DEPARTMENT, NS_ORG_POSITION, NS_STAFF_INFO } from "~/enumerate/namespace";
|
import { NS_ORG_DEPARTMENT, NS_ORG_POSITION, NS_STAFF_INFO } from "~/enumerate/namespace";
|
||||||
|
import { ensureOrgContext, fetchOrgDepartmentPage, fetchOrgPositionPage } from "~/api/enterpriseInfo/orgBootstrap";
|
||||||
|
import { asId, sameId } from "~/api/enterpriseInfo/idUtil";
|
||||||
import { getBirthDateFromIdCard, safeListRequest, safeRequest } from "~/utils";
|
import { getBirthDateFromIdCard, safeListRequest, safeRequest } from "~/utils";
|
||||||
import { toDayjs } from "~/utils/dateFormat";
|
import { toDayjs } from "~/utils/dateFormat";
|
||||||
import { formSelectField } from "~/utils/enterpriseForm";
|
import { formSelectField } from "~/utils/enterpriseForm";
|
||||||
|
|
@ -15,6 +17,14 @@ import PageHeader from "../../components/PageHeader";
|
||||||
|
|
||||||
const GENDER_MAP = { 1: "男", 2: "女" };
|
const GENDER_MAP = { 1: "男", 2: "女" };
|
||||||
|
|
||||||
|
function mapPositionOptions(list = []) {
|
||||||
|
return list.map((p) => ({
|
||||||
|
label: p.positionName,
|
||||||
|
value: asId(p.id),
|
||||||
|
deptId: asId(p.deptId),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
function PersonnelInfoPage(props) {
|
function PersonnelInfoPage(props) {
|
||||||
const [formModalOpen, setFormModalOpen] = useState(false);
|
const [formModalOpen, setFormModalOpen] = useState(false);
|
||||||
const [viewModalOpen, setViewModalOpen] = useState(false);
|
const [viewModalOpen, setViewModalOpen] = useState(false);
|
||||||
|
|
@ -24,23 +34,27 @@ function PersonnelInfoPage(props) {
|
||||||
const [positionOptions, setPositionOptions] = useState([]);
|
const [positionOptions, setPositionOptions] = useState([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
let cancelled = false;
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
|
await ensureOrgContext();
|
||||||
const [deptRes, posRes] = await Promise.all([
|
const [deptRes, posRes] = await Promise.all([
|
||||||
props.orgDepartmentList?.({ pageIndex: 1, pageSize: 200 }),
|
fetchOrgDepartmentPage({ pageIndex: 1, pageSize: 200 }),
|
||||||
props.orgPositionList?.({ pageIndex: 1, pageSize: 200 }),
|
fetchOrgPositionPage({ pageIndex: 1, pageSize: 200 }),
|
||||||
]);
|
]);
|
||||||
setDeptOptions((deptRes?.data || []).map((d) => ({ label: d.deptName, value: d.id })));
|
if (cancelled) {
|
||||||
setPositionOptions((posRes?.data || []).map((p) => ({
|
return;
|
||||||
label: p.positionName,
|
}
|
||||||
value: p.id,
|
setDeptOptions((deptRes?.data || []).map((d) => ({ label: d.deptName, value: asId(d.id) })));
|
||||||
deptId: p.deptId,
|
setPositionOptions(mapPositionOptions(posRes?.data));
|
||||||
})));
|
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
console.warn("[PersonnelInfo] load dept/position options failed:", err);
|
console.warn("[PersonnelInfo] load dept/position options failed:", err);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
return () => {
|
||||||
|
cancelled = true;
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const { tableProps, getData } = useTable(safeListRequest(props.staffInfoList), {
|
const { tableProps, getData } = useTable(safeListRequest(props.staffInfoList), {
|
||||||
|
|
@ -132,17 +146,17 @@ function PersonnelInfoPage(props) {
|
||||||
width: 320,
|
width: 320,
|
||||||
render: (_, record) => (
|
render: (_, record) => (
|
||||||
<Space wrap>
|
<Space wrap>
|
||||||
<Button type="link" onClick={() => { setCurrentId(record.id); setViewModalOpen(true); }}>
|
<Button type="link" onClick={() => { setCurrentId(asId(record.id)); setViewModalOpen(true); }}>
|
||||||
查看
|
查看
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="link" onClick={() => { setCurrentId(record.id); setFormModalOpen(true); }}>
|
<Button type="link" onClick={() => { setCurrentId(asId(record.id)); setFormModalOpen(true); }}>
|
||||||
编辑
|
编辑
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="link" onClick={() => goCertificate(record.id, record.staffName)}>
|
<Button type="link" onClick={() => goCertificate(asId(record.id), record.staffName)}>
|
||||||
证书
|
证书
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="link" onClick={() => onResetPassword(record.id)}>重置密码</Button>
|
<Button type="link" onClick={() => onResetPassword(asId(record.id))}>重置密码</Button>
|
||||||
<Button danger type="link" onClick={() => onDelete(record.id)}>删除</Button>
|
<Button danger type="link" onClick={() => onDelete(asId(record.id))}>删除</Button>
|
||||||
</Space>
|
</Space>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
@ -158,7 +172,6 @@ function PersonnelInfoPage(props) {
|
||||||
requestEdit={props.staffInfoEdit}
|
requestEdit={props.staffInfoEdit}
|
||||||
requestDetails={props.staffInfoGet}
|
requestDetails={props.staffInfoGet}
|
||||||
deptOptions={deptOptions}
|
deptOptions={deptOptions}
|
||||||
positionOptions={positionOptions}
|
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
setFormModalOpen(false);
|
setFormModalOpen(false);
|
||||||
setCurrentId("");
|
setCurrentId("");
|
||||||
|
|
@ -182,36 +195,83 @@ function PersonnelInfoPage(props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function StaffFormModal({
|
function StaffFormModal({
|
||||||
open, currentId, requestAdd, requestEdit, requestDetails, deptOptions, positionOptions, onCancel, onSuccess,
|
open, currentId, requestAdd, requestEdit, requestDetails, deptOptions, onCancel, onSuccess,
|
||||||
}) {
|
}) {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [submitting, setSubmitting] = useState(false);
|
const [submitting, setSubmitting] = useState(false);
|
||||||
const [detailLoading, setDetailLoading] = useState(false);
|
const [detailLoading, setDetailLoading] = useState(false);
|
||||||
|
const [deptPositionOptions, setDeptPositionOptions] = useState([]);
|
||||||
|
const [positionLoading, setPositionLoading] = useState(false);
|
||||||
const watchedDeptId = Form.useWatch("deptId", form);
|
const watchedDeptId = Form.useWatch("deptId", form);
|
||||||
|
const wasOpenRef = useRef(false);
|
||||||
|
const inflightDeptRef = useRef(null);
|
||||||
|
const requestDetailsRef = useRef(requestDetails);
|
||||||
|
requestDetailsRef.current = requestDetails;
|
||||||
|
|
||||||
const filteredPositionOptions = useMemo(() => {
|
const loadPositionsByDept = async (deptId) => {
|
||||||
if (!watchedDeptId) {
|
const id = asId(deptId);
|
||||||
return positionOptions;
|
if (!id) {
|
||||||
}
|
setDeptPositionOptions([]);
|
||||||
return positionOptions.filter((p) => p.deptId === watchedDeptId);
|
|
||||||
}, [positionOptions, watchedDeptId]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!open) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const key = id;
|
||||||
|
if (inflightDeptRef.current === key) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
inflightDeptRef.current = key;
|
||||||
|
setPositionLoading(true);
|
||||||
|
try {
|
||||||
|
let res = await fetchOrgPositionPage({
|
||||||
|
pageIndex: 1,
|
||||||
|
pageSize: 200,
|
||||||
|
eqDeptId: id,
|
||||||
|
});
|
||||||
|
let options = mapPositionOptions(res?.data);
|
||||||
|
// 兼容历史岗位 dept_id 因 Number() 精度丢失与部门 id 不完全一致
|
||||||
|
if (!options.length) {
|
||||||
|
const allRes = await fetchOrgPositionPage({ pageIndex: 1, pageSize: 500 });
|
||||||
|
options = mapPositionOptions(allRes?.data).filter((p) => sameId(p.deptId, id));
|
||||||
|
}
|
||||||
|
setDeptPositionOptions(options);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
console.warn("[PersonnelInfo] load positions by dept failed:", err);
|
||||||
|
setDeptPositionOptions([]);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if (inflightDeptRef.current === key) {
|
||||||
|
inflightDeptRef.current = null;
|
||||||
|
}
|
||||||
|
setPositionLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (open && !wasOpenRef.current) {
|
||||||
if (!currentId) {
|
if (!currentId) {
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
|
setDeptPositionOptions([]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!open) {
|
||||||
|
setDeptPositionOptions([]);
|
||||||
|
}
|
||||||
|
wasOpenRef.current = open;
|
||||||
|
}, [open, currentId, form]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!open || !currentId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
setDetailLoading(true);
|
setDetailLoading(true);
|
||||||
safeRequest(requestDetails, { id: currentId }).then((res) => {
|
safeRequest(requestDetailsRef.current, { id: currentId }).then((res) => {
|
||||||
if (!cancelled && res?.data) {
|
if (!cancelled && res?.data) {
|
||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
...res.data,
|
...res.data,
|
||||||
birthDate: toDayjs(res.data.birthDate),
|
birthDate: toDayjs(res.data.birthDate),
|
||||||
});
|
});
|
||||||
|
loadPositionsByDept(res.data.deptId);
|
||||||
}
|
}
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
if (!cancelled) {
|
if (!cancelled) {
|
||||||
|
|
@ -225,6 +285,7 @@ function StaffFormModal({
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
|
setDeptPositionOptions([]);
|
||||||
onCancel();
|
onCancel();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -236,11 +297,8 @@ function StaffFormModal({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ("deptId" in changed) {
|
if ("deptId" in changed) {
|
||||||
const posId = form.getFieldValue("positionId");
|
|
||||||
const stillValid = positionOptions.some((p) => p.value === posId && p.deptId === changed.deptId);
|
|
||||||
if (!stillValid) {
|
|
||||||
form.setFieldValue("positionId", undefined);
|
form.setFieldValue("positionId", undefined);
|
||||||
}
|
loadPositionsByDept(changed.deptId);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -316,7 +374,9 @@ function StaffFormModal({
|
||||||
<Form.Item name="positionId" label="岗位" rules={[{ required: true, message: "请选择岗位" }]}>
|
<Form.Item name="positionId" label="岗位" rules={[{ required: true, message: "请选择岗位" }]}>
|
||||||
<Select
|
<Select
|
||||||
placeholder="请选择岗位"
|
placeholder="请选择岗位"
|
||||||
options={filteredPositionOptions}
|
options={deptPositionOptions}
|
||||||
|
loading={positionLoading}
|
||||||
|
disabled={!watchedDeptId}
|
||||||
allowClear
|
allowClear
|
||||||
showSearch
|
showSearch
|
||||||
optionFilterProp="label"
|
optionFilterProp="label"
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import Search from "zy-react-library/components/Search";
|
||||||
import Table from "zy-react-library/components/Table";
|
import Table from "zy-react-library/components/Table";
|
||||||
import Upload from "zy-react-library/components/Upload";
|
import Upload from "zy-react-library/components/Upload";
|
||||||
import useTable from "zy-react-library/hooks/useTable";
|
import useTable from "zy-react-library/hooks/useTable";
|
||||||
|
import { asId } from "~/api/enterpriseInfo/idUtil";
|
||||||
import { NS_STAFF_INFO, NS_STAFF_RESIGNATION_APPLY } from "~/enumerate/namespace";
|
import { NS_STAFF_INFO, NS_STAFF_RESIGNATION_APPLY } from "~/enumerate/namespace";
|
||||||
import { safeListRequest, safeRequest } from "~/utils";
|
import { safeListRequest, safeRequest } from "~/utils";
|
||||||
import { formSelectField, getResignAuditStatusLabel } from "~/utils/enterpriseForm";
|
import { formSelectField, getResignAuditStatusLabel } from "~/utils/enterpriseForm";
|
||||||
|
|
@ -34,7 +35,7 @@ function ResignationApplyPage(props) {
|
||||||
if (!cancelled) {
|
if (!cancelled) {
|
||||||
setStaffOptions((res?.data || []).map((s) => ({
|
setStaffOptions((res?.data || []).map((s) => ({
|
||||||
label: `${s.staffName}(${s.account})`,
|
label: `${s.staffName}(${s.account})`,
|
||||||
value: String(s.id),
|
value: asId(s.id),
|
||||||
staffName: s.staffName,
|
staffName: s.staffName,
|
||||||
account: s.account,
|
account: s.account,
|
||||||
})));
|
})));
|
||||||
|
|
@ -96,7 +97,7 @@ function ResignationApplyPage(props) {
|
||||||
<Button
|
<Button
|
||||||
type="link"
|
type="link"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setCurrentId(record.id);
|
setCurrentId(asId(record.id));
|
||||||
setViewModalOpen(true);
|
setViewModalOpen(true);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,12 @@
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import { ensureOrgContext } from "~/api/enterpriseInfo/orgBootstrap";
|
||||||
|
|
||||||
|
/** 进入企业信息模块时缓存机构 id,供子表分页携带 orgId */
|
||||||
function EnterpriseInfo(props) {
|
function EnterpriseInfo(props) {
|
||||||
|
useEffect(() => {
|
||||||
|
ensureOrgContext().catch(() => null);
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{props.children}
|
{props.children}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue