This commit is contained in:
zlwu committed 2026-07-12 17:55:11 +08:00
1 parent c2cba3e668
commit 2142b33cfa
24 files changed
+4834 -3684

No files matched your search

+109
View File
@@ -72,6 +72,16 @@ export function getRequiredPersonnelCertNamesByType(
return PL_PERSONNEL_DRIVER_REQUIRED_CERT_NAMES
}
/** 车辆关联人员:从人员主数据类型映射为关联角色(司机/押运员) */
export function mapPersonnelTypeToVehicleRole(
personnelType?: string | null
): 'driver' | 'escort' | undefined {
if (personnelType === 'driver') return 'driver'
if (personnelType === 'escort') return 'escort'
if (personnelType === 'both') return 'driver'
return undefined
}
export function validatePersonnelTypeRoleCompat(
personnelType: string | undefined,
role: string | undefined,
@@ -176,3 +186,102 @@ export function getPersonnelCertMissingSuffix(
}
return hasPersonnelMasterCertMissing(certList) ? PL_PERSONNEL_CERT_MISSING_SUFFIX : ''
}
export const PL_PERSONNEL_CERT_SHORT_LABELS: Record<string, string> = {
身份证: '身',
驾驶证: '驾',
从业资格证: '业'
}
export type PersonnelCertBadgeStatus = 'missing' | 'valid' | 'expiring' | 'expired'
export interface PersonnelCertBadgeItem {
requiredName: string
shortLabel: string
status: PersonnelCertBadgeStatus
title: string
}
function getPersonnelCertMissingFieldLabels(
cert: Pick<CertRow, 'certName' | 'certNo' | 'expireDate' | 'attachmentUrls'> | undefined,
requiredName: string
): string[] {
if (!cert || !matchRequiredCertName(cert.certName, requiredName)) {
return ['证号', '有效期', '附件']
}
const missing: string[] = []
if (!cert.certNo?.trim()) missing.push('证号')
if (!cert.expireDate) missing.push('有效期')
if (!cert.attachmentUrls?.trim()) missing.push('附件')
return missing
}
function formatPersonnelCertBadgeTooltip(
requiredName: string,
status: PersonnelCertBadgeStatus,
cert?: Pick<CertRow, 'certName' | 'certNo' | 'expireDate' | 'attachmentUrls' | 'remindDays'>
): string {
if (status === 'missing') {
if (!cert || !matchRequiredCertName(cert.certName, requiredName)) {
return `${requiredName}:缺失(未登记该证书)`
}
const missing = getPersonnelCertMissingFieldLabels(cert, requiredName)
return `${requiredName}:缺失(缺少${missing.join('、')})`
}
const expireDate = cert?.expireDate || '—'
const expDate = new Date(expireDate)
const today = new Date()
today.setHours(0, 0, 0, 0)
expDate.setHours(0, 0, 0, 0)
const diffDays = Math.ceil((expDate.getTime() - today.getTime()) / (1000 * 60 * 60 * 24))
const certNo = cert?.certNo?.trim()
const certNoText = certNo ? `,证号 ${certNo}` : ''
if (status === 'expired') {
return `${requiredName}:已过期,有效期 ${expireDate},已过期 ${Math.abs(diffDays)} 天${certNoText}`
}
if (status === 'expiring') {
return `${requiredName}:临期,有效期 ${expireDate},剩余 ${diffDays} 天${certNoText}`
}
return `${requiredName}:正常,有效期 ${expireDate}${certNoText}`
}
export function getPersonnelCertBadgeStatus(
cert: Pick<CertRow, 'certName' | 'certNo' | 'expireDate' | 'attachmentUrls' | 'remindDays'> | undefined,
requiredName: string
): PersonnelCertBadgeStatus {
if (!isPersonnelCertStrictComplete(cert, requiredName)) {
return 'missing'
}
const expireDate = cert?.expireDate
if (!expireDate) return 'missing'
const remindDays = cert?.remindDays ?? 30
const expDate = new Date(expireDate)
const today = new Date()
today.setHours(0, 0, 0, 0)
expDate.setHours(0, 0, 0, 0)
const diffDays = Math.ceil((expDate.getTime() - today.getTime()) / (1000 * 60 * 60 * 24))
if (diffDays <= 0) return 'expired'
if (diffDays <= remindDays) return 'expiring'
return 'valid'
}
export function getPersonnelRequiredCertBadges(
personnelType: string | null | undefined,
certList: CertRow[] = []
): PersonnelCertBadgeItem[] {
return getRequiredPersonnelCertNamesByType(personnelType).map(requiredName => {
const matched = certList.find(cert => matchRequiredCertName(cert.certName, requiredName))
const status = getPersonnelCertBadgeStatus(matched, requiredName)
const shortLabel = PL_PERSONNEL_CERT_SHORT_LABELS[requiredName] || requiredName.slice(0, 1)
return {
requiredName,
shortLabel,
status,
title: formatPersonnelCertBadgeTooltip(requiredName, status, matched)
}
})
}
+121
View File
@@ -235,3 +235,124 @@ export function validateVehicleCertNamesNotEmpty(
}
return true
}
export const PL_VEHICLE_CERT_SHORT_LABELS: Record<string, string> = {
行驶证: '行',
营运证: '营',
保险单: '保',
罐检报告: '罐'
}
export type VehicleCertBadgeStatus = 'missing' | 'valid' | 'expiring' | 'expired'
export interface VehicleCertBadgeItem {
requiredName: string
shortLabel: string
status: VehicleCertBadgeStatus
title: string
}
function matchVehicleRequiredCertName(
actualName: string | undefined,
requiredName: string
): boolean {
return (actualName?.trim() || '') === requiredName
}
function getVehicleCertMissingFieldLabels(
cert: Pick<CertRow, 'certName' | 'certNo' | 'expireDate' | 'attachmentUrls'> | undefined,
requiredName: string
): string[] {
if (!cert || !matchVehicleRequiredCertName(cert.certName, requiredName)) {
return ['证号', '有效期', '附件']
}
const missing: string[] = []
if (!cert.certNo?.trim()) missing.push('证号')
if (!cert.expireDate) missing.push('有效期')
if (!cert.attachmentUrls?.trim()) missing.push('附件')
return missing
}
function formatVehicleCertBadgeTooltip(
partLabel: string,
requiredName: string,
status: VehicleCertBadgeStatus,
cert?: Pick<CertRow, 'certName' | 'certNo' | 'expireDate' | 'attachmentUrls' | 'remindDays'>
): string {
const prefix = partLabel ? `${partLabel} · ` : ''
if (status === 'missing') {
if (!cert || !matchVehicleRequiredCertName(cert.certName, requiredName)) {
return `${prefix}${requiredName}:缺失(未登记该证书)`
}
const missing = getVehicleCertMissingFieldLabels(cert, requiredName)
return `${prefix}${requiredName}:缺失(缺少${missing.join('、')})`
}
const expireDate = cert?.expireDate || '—'
const expDate = new Date(expireDate)
const today = new Date()
today.setHours(0, 0, 0, 0)
expDate.setHours(0, 0, 0, 0)
const diffDays = Math.ceil((expDate.getTime() - today.getTime()) / (1000 * 60 * 60 * 24))
const certNo = cert?.certNo?.trim()
const certNoText = certNo ? `,证号 ${certNo}` : ''
if (status === 'expired') {
return `${prefix}${requiredName}:已过期,有效期 ${expireDate},已过期 ${Math.abs(diffDays)} 天${certNoText}`
}
if (status === 'expiring') {
return `${prefix}${requiredName}:临期,有效期 ${expireDate},剩余 ${diffDays} 天${certNoText}`
}
return `${prefix}${requiredName}:正常,有效期 ${expireDate}${certNoText}`
}
export function getVehicleCertBadgeStatus(
cert: Pick<CertRow, 'certName' | 'certNo' | 'expireDate' | 'attachmentUrls' | 'remindDays'> | undefined,
requiredName: string
): VehicleCertBadgeStatus {
if (!isVehicleCertUploaded(cert) || !matchVehicleRequiredCertName(cert?.certName, requiredName)) {
return 'missing'
}
const expireDate = cert?.expireDate
if (!expireDate) return 'missing'
const remindDays = cert?.remindDays ?? 30
const expDate = new Date(expireDate)
const today = new Date()
today.setHours(0, 0, 0, 0)
expDate.setHours(0, 0, 0, 0)
const diffDays = Math.ceil((expDate.getTime() - today.getTime()) / (1000 * 60 * 60 * 24))
if (diffDays <= 0) return 'expired'
if (diffDays <= remindDays) return 'expiring'
return 'valid'
}
export function getVehiclePartRequiredCertBadges(options: {
vehicleType: PlVehicleCertCheckType
certList?: CertRow[]
part: VehicleCertPart
partLabel?: string
}): VehicleCertBadgeItem[] {
const { vehicleType, certList = [], part, partLabel = '' } = options
const partCerts =
part === PL_VEHICLE_CERT_PART_TRAILER
? splitVehicleCertsByPart(certList).trailerCerts
: splitVehicleCertsByPart(certList).headCerts
const requiredNames =
part === PL_VEHICLE_CERT_PART_TRAILER
? getVehicleTrailerRequiredCertNames(vehicleType)
: getVehicleHeadRequiredCertNames(vehicleType)
return requiredNames.map(requiredName => {
const matched = partCerts.find(cert => matchVehicleRequiredCertName(cert.certName, requiredName))
const status = getVehicleCertBadgeStatus(matched, requiredName)
const shortLabel = PL_VEHICLE_CERT_SHORT_LABELS[requiredName] || requiredName.slice(0, 1)
return {
requiredName,
shortLabel,
status,
title: formatVehicleCertBadgeTooltip(partLabel, requiredName, status, matched)
}
})
}