@@ -1593,17 +1593,40 @@ export default {
|
||||
const fullNation = `${nation}族`;
|
||||
return this.nationOptions.includes(fullNation) ? fullNation : nation;
|
||||
},
|
||||
/**
|
||||
* OCR / 手工录入日期归一化:对齐车辆侧与后端 FlexibleLocalDateDeserializer。
|
||||
* 支持 yyyyMMdd、yyyy-MM-dd、2018.3.9、2030年05月20日及任意非数字分隔;无法识别返回空串。
|
||||
*/
|
||||
normalizeBirthday(value = '') {
|
||||
const birthday = String(value || '').trim();
|
||||
const compactMatch = birthday.match(/^(\d{4})(\d{2})(\d{2})$/);
|
||||
if (compactMatch) {
|
||||
const [, year, month, day] = compactMatch;
|
||||
return `${year}-${month}-${day}`;
|
||||
if (!birthday) return '';
|
||||
if (/长期|永久/.test(birthday)) return '';
|
||||
const looseMatch = birthday.match(/(\d{4})\D+(\d{1,2})\D+(\d{1,2})/);
|
||||
if (looseMatch) {
|
||||
return this.toValidDateText(looseMatch[1], looseMatch[2], looseMatch[3]);
|
||||
}
|
||||
const match = birthday.match(/^(\d{4})[-/.年](\d{1,2})[-/.月](\d{1,2})日?$/);
|
||||
if (!match) return birthday;
|
||||
const [, year, month, day] = match;
|
||||
return `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`;
|
||||
const compact = birthday.replace(/\D/g, '');
|
||||
if (compact.length === 8) {
|
||||
return this.toValidDateText(compact.slice(0, 4), compact.slice(4, 6), compact.slice(6, 8));
|
||||
}
|
||||
return '';
|
||||
},
|
||||
toValidDateText(yearText, monthText, dayText) {
|
||||
const year = Number(yearText);
|
||||
const month = Number(monthText);
|
||||
const day = Number(dayText);
|
||||
if (!Number.isInteger(year) || !Number.isInteger(month) || !Number.isInteger(day)) {
|
||||
return '';
|
||||
}
|
||||
const date = new Date(year, month - 1, day);
|
||||
if (
|
||||
date.getFullYear() !== year ||
|
||||
date.getMonth() !== month - 1 ||
|
||||
date.getDate() !== day
|
||||
) {
|
||||
return '';
|
||||
}
|
||||
return `${String(year).padStart(4, '0')}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
|
||||
},
|
||||
parseIdCardInfo(idCardNo = '') {
|
||||
if (!/^\d{17}[\dX]$/.test(idCardNo)) {
|
||||
|
||||
@@ -1174,37 +1174,59 @@ export default {
|
||||
});
|
||||
},
|
||||
/**
|
||||
* OCR 日期常为区间(如 2022-08-17至2024-01-05)或含无效日(如 01-65)。
|
||||
* 提取可解析的合法日期;prefer=first 取登记类起始日,prefer=last 取有效期截止日。
|
||||
* OCR 日期常为区间(如 2022-08-17至2024-01-05)、无分隔符(如 20260317)、
|
||||
* 年月日/点分(2030年05月20日、2018.3.9)或任意非数字分隔。
|
||||
* 对齐司机侧 normalizeBirthday / 后端 OcrFieldSupport:年与月、月与日之间允许任意非数字。
|
||||
* prefer=first 取登记类起始日,prefer=last 取有效期截止日。
|
||||
* 返回值统一为 YYYY-MM-DD,供 el-date-picker 展示与后端 LocalDate 反序列化。
|
||||
*/
|
||||
normalizeDate(value = '', prefer = 'first') {
|
||||
const dateValue = String(value || '').trim();
|
||||
if (!dateValue) return '';
|
||||
const segments = dateValue.match(/\d{4}[-/.年]\d{1,2}[-/.月]\d{1,2}日?/g) || [];
|
||||
const sourceList = segments.length ? segments : [dateValue];
|
||||
const candidates = sourceList
|
||||
.map(item => {
|
||||
const match = String(item)
|
||||
.trim()
|
||||
.match(/^(\d{4})[-/.年](\d{1,2})[-/.月](\d{1,2})日?$/);
|
||||
if (!match) return '';
|
||||
const year = Number(match[1]);
|
||||
const month = Number(match[2]);
|
||||
const day = Number(match[3]);
|
||||
const date = new Date(year, month - 1, day);
|
||||
if (
|
||||
date.getFullYear() !== year ||
|
||||
date.getMonth() !== month - 1 ||
|
||||
date.getDate() !== day
|
||||
) {
|
||||
return '';
|
||||
if (/长期|永久/.test(dateValue)) return '';
|
||||
const candidates = [];
|
||||
const loosePattern = /(\d{4})\D+(\d{1,2})\D+(\d{1,2})/g;
|
||||
let match = loosePattern.exec(dateValue);
|
||||
while (match) {
|
||||
const normalized = this.toValidDateText(match[1], match[2], match[3]);
|
||||
if (normalized) {
|
||||
candidates.push(normalized);
|
||||
}
|
||||
match = loosePattern.exec(dateValue);
|
||||
}
|
||||
if (!candidates.length) {
|
||||
const compact = dateValue.replace(/\D/g, '');
|
||||
if (compact.length === 8) {
|
||||
const normalized = this.toValidDateText(
|
||||
compact.slice(0, 4),
|
||||
compact.slice(4, 6),
|
||||
compact.slice(6, 8)
|
||||
);
|
||||
if (normalized) {
|
||||
candidates.push(normalized);
|
||||
}
|
||||
return `${String(year).padStart(4, '0')}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
|
||||
})
|
||||
.filter(Boolean);
|
||||
}
|
||||
}
|
||||
if (!candidates.length) return '';
|
||||
return prefer === 'last' ? candidates[candidates.length - 1] : candidates[0];
|
||||
},
|
||||
toValidDateText(yearText, monthText, dayText) {
|
||||
const year = Number(yearText);
|
||||
const month = Number(monthText);
|
||||
const day = Number(dayText);
|
||||
if (!Number.isInteger(year) || !Number.isInteger(month) || !Number.isInteger(day)) {
|
||||
return '';
|
||||
}
|
||||
const date = new Date(year, month - 1, day);
|
||||
if (
|
||||
date.getFullYear() !== year ||
|
||||
date.getMonth() !== month - 1 ||
|
||||
date.getDate() !== day
|
||||
) {
|
||||
return '';
|
||||
}
|
||||
return `${String(year).padStart(4, '0')}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
|
||||
},
|
||||
normalizeVehicleDateFields(form = {}) {
|
||||
const dateFields = [
|
||||
['compulsoryScrapDate', 'first'],
|
||||
@@ -1216,8 +1238,13 @@ export default {
|
||||
['registrationDate', 'first'],
|
||||
];
|
||||
dateFields.forEach(([prop, prefer]) => {
|
||||
if (form[prop] === undefined || form[prop] === null || form[prop] === '') return;
|
||||
form[prop] = this.normalizeDate(form[prop], prefer);
|
||||
if (form[prop] === undefined || form[prop] === null || form[prop] === '') {
|
||||
form[prop] = null;
|
||||
return;
|
||||
}
|
||||
const normalized = this.normalizeDate(form[prop], prefer);
|
||||
// 无法识别或空串统一置 null,避免把 "" / "20260317" 原样提交给 LocalDate
|
||||
form[prop] = normalized || null;
|
||||
});
|
||||
return form;
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user