gongxiangp2/lib/dingtalk-approval-no.ts

70 lines
1.7 KiB
TypeScript

export const DINGTALK_APPROVAL_NO_MAX_LENGTH = 64
function isLeapYear(year: number): boolean {
return year % 400 === 0 || (year % 4 === 0 && year % 100 !== 0)
}
function getDaysInMonth(year: number, month: number): number {
if (month === 2) {
return isLeapYear(year) ? 29 : 28
}
return [4, 6, 9, 11].includes(month) ? 30 : 31
}
function hasValidDatePrefix(value: string): boolean {
const year = Number.parseInt(value.slice(0, 4), 10)
const month = Number.parseInt(value.slice(4, 6), 10)
const day = Number.parseInt(value.slice(6, 8), 10)
if (year < 1000 || year > 9999 || month < 1 || month > 12 || day < 1) {
return false
}
return day <= getDaysInMonth(year, month)
}
export function normalizeDingtalkApprovalNo(
value: string | null | undefined,
): string | null {
if (typeof value !== 'string') {
return null
}
const normalized = value.trim()
return normalized || null
}
export function getDingtalkApprovalNoError(
value: string | null | undefined,
): string | null {
const normalized = normalizeDingtalkApprovalNo(value)
if (!normalized) {
return null
}
if (!/^\d+$/.test(normalized)) {
return '钉钉审批编号只能输入数字'
}
if (normalized.length < 9) {
return '钉钉审批编号需包含8位日期和后续编号'
}
if (normalized.length > DINGTALK_APPROVAL_NO_MAX_LENGTH) {
return `钉钉审批编号不能超过${DINGTALK_APPROVAL_NO_MAX_LENGTH}位`
}
if (!hasValidDatePrefix(normalized)) {
return '钉钉审批编号前8位不是有效日期'
}
return null
}
export function validateDingtalkApprovalNo(
value: string | null | undefined,
): boolean {
return getDingtalkApprovalNoError(value) === null
}