|
@@ -28,6 +28,7 @@ const QUALIFICATION_STATUS_TO_BACK: Record<
|
|
|
const postLabelByCode = new Map<string, string>();
|
|
const postLabelByCode = new Map<string, string>();
|
|
|
const postCodeByLabel = new Map<string, string>();
|
|
const postCodeByLabel = new Map<string, string>();
|
|
|
const certLabelByCode = new Map<string, string>();
|
|
const certLabelByCode = new Map<string, string>();
|
|
|
|
|
+const certCodeByLabel = new Map<string, string>();
|
|
|
|
|
|
|
|
export function syncEmployeePostDict(
|
|
export function syncEmployeePostDict(
|
|
|
items: Array<{ dictName: string; dictValue: number | string }>,
|
|
items: Array<{ dictName: string; dictValue: number | string }>,
|
|
@@ -47,11 +48,13 @@ export function syncEmployeeCertDict(
|
|
|
items: Array<{ dictName: string; dictValue: number | string }>,
|
|
items: Array<{ dictName: string; dictValue: number | string }>,
|
|
|
) {
|
|
) {
|
|
|
certLabelByCode.clear();
|
|
certLabelByCode.clear();
|
|
|
|
|
+ certCodeByLabel.clear();
|
|
|
for (const item of items) {
|
|
for (const item of items) {
|
|
|
const code = String(item.dictValue);
|
|
const code = String(item.dictValue);
|
|
|
const label = item.dictName;
|
|
const label = item.dictName;
|
|
|
if (!code || !label) continue;
|
|
if (!code || !label) continue;
|
|
|
certLabelByCode.set(code, label);
|
|
certLabelByCode.set(code, label);
|
|
|
|
|
+ certCodeByLabel.set(label, code);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -96,6 +99,34 @@ function resolveCertNameLabel(raw?: unknown): string {
|
|
|
return certLabelByCode.get(code) ?? code;
|
|
return certLabelByCode.get(code) ?? code;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+function resolveCertNameCode(raw?: unknown): string | undefined {
|
|
|
|
|
+ if (raw === undefined || raw === null || raw === '') return undefined;
|
|
|
|
|
+ const value = String(raw).trim();
|
|
|
|
|
+ if (certLabelByCode.has(value)) return value;
|
|
|
|
|
+ return certCodeByLabel.get(value) ?? value;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 编辑表单回显:岗位中文名/编码 → 下拉 dictValue */
|
|
|
|
|
+export function resolvePostValuesForForm(positions?: string[]): string[] {
|
|
|
|
|
+ if (!positions?.length) return [];
|
|
|
|
|
+ return positions
|
|
|
|
|
+ .map((value) => {
|
|
|
|
|
+ const normalized = String(value).trim();
|
|
|
|
|
+ if (!normalized) return '';
|
|
|
|
|
+ if (postLabelByCode.has(normalized)) return normalized;
|
|
|
|
|
+ return postCodeByLabel.get(normalized) ?? normalized;
|
|
|
|
|
+ })
|
|
|
|
|
+ .filter(Boolean);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** 编辑表单回显:证书中文名/编码 → 下拉 dictValue */
|
|
|
|
|
+export function resolveCertNameValueForForm(name?: string): string {
|
|
|
|
|
+ if (!name?.trim()) return '';
|
|
|
|
|
+ const normalized = name.trim();
|
|
|
|
|
+ if (certLabelByCode.has(normalized)) return normalized;
|
|
|
|
|
+ return certCodeByLabel.get(normalized) ?? normalized;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
function resolveEnterpriseName(data?: TransformData): string {
|
|
function resolveEnterpriseName(data?: TransformData): string {
|
|
|
const medCenterName = String(data?.medCenterName ?? '').trim();
|
|
const medCenterName = String(data?.medCenterName ?? '').trim();
|
|
|
const hospitalName = String(data?.hospitalName ?? '').trim();
|
|
const hospitalName = String(data?.hospitalName ?? '').trim();
|
|
@@ -108,11 +139,43 @@ function resolveEnterpriseName(data?: TransformData): string {
|
|
|
function resolvePostCodes(positions?: string[]): string | undefined {
|
|
function resolvePostCodes(positions?: string[]): string | undefined {
|
|
|
if (!positions?.length) return undefined;
|
|
if (!positions?.length) return undefined;
|
|
|
const codes = positions
|
|
const codes = positions
|
|
|
- .map((label) => postCodeByLabel.get(label) ?? label)
|
|
|
|
|
|
|
+ .map((value) => {
|
|
|
|
|
+ const normalized = String(value).trim();
|
|
|
|
|
+ if (!normalized) return '';
|
|
|
|
|
+ if (postLabelByCode.has(normalized)) return normalized;
|
|
|
|
|
+ return postCodeByLabel.get(normalized) ?? normalized;
|
|
|
|
|
+ })
|
|
|
.filter(Boolean);
|
|
.filter(Boolean);
|
|
|
return codes.length ? codes.join('|') : undefined;
|
|
return codes.length ? codes.join('|') : undefined;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+function normalizeEndDate(value?: string): string | undefined {
|
|
|
|
|
+ if (!value?.trim()) return undefined;
|
|
|
|
|
+ const trimmed = value.trim();
|
|
|
|
|
+ const match = trimmed.match(/^(\d{4})[-/](\d{1,2})[-/](\d{1,2})/);
|
|
|
|
|
+ if (!match?.[1] || !match[2] || !match[3]) return trimmed;
|
|
|
|
|
+ const [, year, month, day] = match;
|
|
|
|
|
+ return `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function toBackendLong(value?: string): number | string | undefined {
|
|
|
|
|
+ const trimmed = value?.trim();
|
|
|
|
|
+ if (!trimmed) return undefined;
|
|
|
|
|
+ if (!/^\d+$/.test(trimmed)) return trimmed;
|
|
|
|
|
+ if (trimmed.length > 15) return trimmed;
|
|
|
|
|
+ const num = Number(trimmed);
|
|
|
|
|
+ return Number.isFinite(num) ? num : trimmed;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function isPersistedQualificationId(id?: string): boolean {
|
|
|
|
|
+ if (!id?.trim()) return false;
|
|
|
|
|
+ return (
|
|
|
|
|
+ !id.startsWith('cert-') &&
|
|
|
|
|
+ !id.startsWith('file-') &&
|
|
|
|
|
+ !id.startsWith('upload-')
|
|
|
|
|
+ );
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
function parseAttachmentList(
|
|
function parseAttachmentList(
|
|
|
raw?: unknown,
|
|
raw?: unknown,
|
|
|
): PersonnelQualificationModel.CertificateAttachment[] {
|
|
): PersonnelQualificationModel.CertificateAttachment[] {
|
|
@@ -187,11 +250,7 @@ function fromEmployeeQualification(
|
|
|
? `cert-${index + 1}`
|
|
? `cert-${index + 1}`
|
|
|
: String(data.id);
|
|
: String(data.id);
|
|
|
const name = resolveCertNameLabel(
|
|
const name = resolveCertNameLabel(
|
|
|
- data?.qualificationName ??
|
|
|
|
|
- data?.certName ??
|
|
|
|
|
- data?.certificateName ??
|
|
|
|
|
- data?.name ??
|
|
|
|
|
- '',
|
|
|
|
|
|
|
+ data?.certificateName ?? data?.certName ?? data?.name ?? '',
|
|
|
);
|
|
);
|
|
|
const longTerm =
|
|
const longTerm =
|
|
|
data?.isLongTerm === 1 ||
|
|
data?.isLongTerm === 1 ||
|
|
@@ -213,7 +272,11 @@ function fromEmployeeQualification(
|
|
|
id,
|
|
id,
|
|
|
name,
|
|
name,
|
|
|
type: String(
|
|
type: String(
|
|
|
- data?.qualificationType ?? data?.qualType ?? data?.type ?? '',
|
|
|
|
|
|
|
+ data?.qualificationName ??
|
|
|
|
|
+ data?.qualificationType ??
|
|
|
|
|
+ data?.qualType ??
|
|
|
|
|
+ data?.type ??
|
|
|
|
|
+ '',
|
|
|
),
|
|
),
|
|
|
number: String(
|
|
number: String(
|
|
|
data?.certificateNumber ??
|
|
data?.certificateNumber ??
|
|
@@ -234,7 +297,8 @@ function fromEmployeeQualification(
|
|
|
data?.files ??
|
|
data?.files ??
|
|
|
data?.fileList ??
|
|
data?.fileList ??
|
|
|
data?.fileUrl ??
|
|
data?.fileUrl ??
|
|
|
- data?.fileUrls,
|
|
|
|
|
|
|
+ data?.fileUrls ??
|
|
|
|
|
+ data?.picturePath,
|
|
|
),
|
|
),
|
|
|
};
|
|
};
|
|
|
}
|
|
}
|
|
@@ -247,10 +311,16 @@ function resolveWorstStatus(
|
|
|
return 'valid';
|
|
return 'valid';
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/** 雪花 id 等超长整数统一转字符串,避免 query 传参精度丢失 */
|
|
|
|
|
+export function toEmployeeRecordId(id?: unknown): string {
|
|
|
|
|
+ if (id === undefined || id === null || id === '') return '';
|
|
|
|
|
+ return String(id);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
export function fromEmployee(
|
|
export function fromEmployee(
|
|
|
data?: TransformData,
|
|
data?: TransformData,
|
|
|
): PersonnelQualificationModel.Personnel {
|
|
): PersonnelQualificationModel.Personnel {
|
|
|
- const id = data?.id === undefined || data?.id === null ? '' : String(data.id);
|
|
|
|
|
|
|
+ const id = toEmployeeRecordId(data?.id);
|
|
|
const organizationType = resolveOrganizationType(data);
|
|
const organizationType = resolveOrganizationType(data);
|
|
|
const certificates = (
|
|
const certificates = (
|
|
|
Array.isArray(data?.qualifications) ? data.qualifications : []
|
|
Array.isArray(data?.qualifications) ? data.qualifications : []
|
|
@@ -275,6 +345,12 @@ export function fromEmployee(
|
|
|
? String(data?.hospitalCode ?? '')
|
|
? String(data?.hospitalCode ?? '')
|
|
|
: String(data?.medCenterId ?? data?.enterpriseId ?? ''),
|
|
: String(data?.medCenterId ?? data?.enterpriseId ?? ''),
|
|
|
enterpriseName: resolveEnterpriseName(data),
|
|
enterpriseName: resolveEnterpriseName(data),
|
|
|
|
|
+ hospitalCode: String(data?.hospitalCode ?? ''),
|
|
|
|
|
+ hospitalName: String(data?.hospitalName ?? ''),
|
|
|
|
|
+ yardCode: String(data?.yardCode ?? ''),
|
|
|
|
|
+ yardName: String(data?.yardName ?? ''),
|
|
|
|
|
+ medCenterId: String(data?.medCenterId ?? ''),
|
|
|
|
|
+ medCenterName: String(data?.medCenterName ?? ''),
|
|
|
decoctionCenterId: String(
|
|
decoctionCenterId: String(
|
|
|
data?.decoctionCenterCode ?? data?.decoctionCenterId ?? '',
|
|
data?.decoctionCenterCode ?? data?.decoctionCenterId ?? '',
|
|
|
),
|
|
),
|
|
@@ -297,22 +373,25 @@ function toEmployeeQualification(
|
|
|
.map((item) => item.url)
|
|
.map((item) => item.url)
|
|
|
.filter(Boolean)
|
|
.filter(Boolean)
|
|
|
.join(',');
|
|
.join(',');
|
|
|
|
|
+ const endDate = cert.longTerm ? void 0 : normalizeEndDate(cert.expiryDate);
|
|
|
|
|
|
|
|
- return {
|
|
|
|
|
- id: cert.id || void 0,
|
|
|
|
|
- qualificationName: cert.name,
|
|
|
|
|
- qualificationType: cert.type || void 0,
|
|
|
|
|
- qualificationNo: cert.number,
|
|
|
|
|
- expiryDate: cert.longTerm ? void 0 : cert.expiryDate || void 0,
|
|
|
|
|
|
|
+ const payload: TransformData = {
|
|
|
|
|
+ certificateName: resolveCertNameCode(cert.name),
|
|
|
|
|
+ certificateNumber: cert.number,
|
|
|
|
|
+ endDate,
|
|
|
isLongTerm: cert.longTerm ? 1 : 0,
|
|
isLongTerm: cert.longTerm ? 1 : 0,
|
|
|
- qualificationStatus: QUALIFICATION_STATUS_TO_BACK[cert.status ?? 'valid'],
|
|
|
|
|
- fileUrl: fileUrl || void 0,
|
|
|
|
|
- attachments: attachments.map((item) => ({
|
|
|
|
|
- fileName: item.name,
|
|
|
|
|
- fileUrl: item.url,
|
|
|
|
|
- type: item.type,
|
|
|
|
|
- })),
|
|
|
|
|
|
|
+ picturePath: fileUrl || void 0,
|
|
|
};
|
|
};
|
|
|
|
|
+
|
|
|
|
|
+ if (cert.type?.trim()) {
|
|
|
|
|
+ payload.qualificationName = cert.type.trim();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (isPersistedQualificationId(cert.id)) {
|
|
|
|
|
+ payload.id = toBackendLong(cert.id);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return payload;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
export function toEmployeeQuery(
|
|
export function toEmployeeQuery(
|
|
@@ -351,9 +430,9 @@ export function toEmployeeQuery(
|
|
|
const keyword = query?.keyword?.trim();
|
|
const keyword = query?.keyword?.trim();
|
|
|
if (keyword) {
|
|
if (keyword) {
|
|
|
if (/^\d+$/.test(keyword)) {
|
|
if (/^\d+$/.test(keyword)) {
|
|
|
- dto.operatorCode = keyword;
|
|
|
|
|
|
|
+ dto.param = keyword;
|
|
|
} else {
|
|
} else {
|
|
|
- dto.name = keyword;
|
|
|
|
|
|
|
+ dto.param = keyword;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -363,22 +442,30 @@ export function toEmployeeQuery(
|
|
|
export function toEmployeePayload(
|
|
export function toEmployeePayload(
|
|
|
data: PersonnelQualificationModel.PersonnelForm,
|
|
data: PersonnelQualificationModel.PersonnelForm,
|
|
|
): TransformData {
|
|
): TransformData {
|
|
|
- const payload: TransformData = {
|
|
|
|
|
- id: data.id || void 0,
|
|
|
|
|
- decoctionCenterCode: data.decoctionCenterId,
|
|
|
|
|
- decoctionCenterName: data.decoctionCenterName,
|
|
|
|
|
|
|
+ const certificates = data.certificates ?? [];
|
|
|
|
|
+ const qualificationStatus = certificates.length
|
|
|
|
|
+ ? QUALIFICATION_STATUS_TO_BACK[resolveWorstStatus(certificates)]
|
|
|
|
|
+ : void 0;
|
|
|
|
|
+
|
|
|
|
|
+ const id = toEmployeeRecordId(data.id);
|
|
|
|
|
+
|
|
|
|
|
+ return {
|
|
|
|
|
+ id: id || void 0,
|
|
|
|
|
+ hospitalCode: data.hospitalCode || void 0,
|
|
|
|
|
+ hospitalName: data.hospitalName || void 0,
|
|
|
|
|
+ yardCode: data.yardCode || void 0,
|
|
|
|
|
+ yardName: data.yardName || void 0,
|
|
|
|
|
+ medCenterId: data.medCenterId || void 0,
|
|
|
|
|
+ medCenterName: data.medCenterName || void 0,
|
|
|
|
|
+ decoctionCenterCode: data.decoctionCenterId || void 0,
|
|
|
|
|
+ decoctionCenterName: data.decoctionCenterName || void 0,
|
|
|
name: data.name,
|
|
name: data.name,
|
|
|
- operatorCode: data.employeeNo,
|
|
|
|
|
- cardNo: data.idNumber,
|
|
|
|
|
|
|
+ operatorCode: toBackendLong(data.employeeNo),
|
|
|
|
|
+ cardNo: toBackendLong(data.idNumber),
|
|
|
post: resolvePostCodes(data.positions),
|
|
post: resolvePostCodes(data.positions),
|
|
|
- qualifications: (data.certificates ?? []).map(toEmployeeQualification),
|
|
|
|
|
|
|
+ qualificationStatus,
|
|
|
|
|
+ qualifications: certificates.map(toEmployeeQualification),
|
|
|
};
|
|
};
|
|
|
-
|
|
|
|
|
- if (data.decoctionCenterId) {
|
|
|
|
|
- payload.decoctionCenterCode = data.decoctionCenterId;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return payload;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** 解析 /employee/list 响应:data.t.rows + expiredNum / isExpired */
|
|
/** 解析 /employee/list 响应:data.t.rows + expiredNum / isExpired */
|