|
@@ -37,6 +37,8 @@ var PROFILE_FIELD_IDS = {
|
|
|
employmentStatus: 'radioField_mp1sngq1',
|
|
employmentStatus: 'radioField_mp1sngq1',
|
|
|
// prd 人员档案入职时间(DateField,毫秒时间戳);入职当日可填,之前日期禁止填报
|
|
// prd 人员档案入职时间(DateField,毫秒时间戳);入职当日可填,之前日期禁止填报
|
|
|
employmentStartDate: 'dateField_mh8xhqc6',
|
|
employmentStartDate: 'dateField_mh8xhqc6',
|
|
|
|
|
+ employmentEndDate: 'dateField_mh8xhqc7',
|
|
|
|
|
+ overseasStaff: 'radioField_mvxqpaxw',
|
|
|
// ppExt 主管 Manager(EmployeeField)— 用于 PM 离职兜底反查替补审批人(v2.42)
|
|
// ppExt 主管 Manager(EmployeeField)— 用于 PM 离职兜底反查替补审批人(v2.42)
|
|
|
manager: 'employeeField_mh8xhqc3'
|
|
manager: 'employeeField_mh8xhqc3'
|
|
|
};
|
|
};
|
|
@@ -342,8 +344,11 @@ var TC_I18N = {
|
|
|
statusEditable: '可编辑',
|
|
statusEditable: '可编辑',
|
|
|
statusSubmitted: '已提交(不可修改)',
|
|
statusSubmitted: '已提交(不可修改)',
|
|
|
statusApproved: '已审批(不可修改)',
|
|
statusApproved: '已审批(不可修改)',
|
|
|
- statusReadonly: '不可填写(外部 / 已下线 / 入职前)',
|
|
|
|
|
- preEmploymentLocked: '入职日期之前不可填写',
|
|
|
|
|
|
|
+ statusReadonly: '不可填写(外部 / 已下线 / 任职期外)',
|
|
|
|
|
+ preEmploymentLocked: '任职期间以外不可填写(入职前/离职后)',
|
|
|
|
|
+ employmentInvalid: '人员档案入离职日期异常,请核实后重试',
|
|
|
|
|
+ employmentDraftOutside: '以下日期不在任职期间,草稿不能保存或提交:',
|
|
|
|
|
+ personnelCalendarChanged: '人员档案日期或海外标签已更新,请刷新页面重新加载后再保存或提交',
|
|
|
sectionBillable: '▸ Billable 工时',
|
|
sectionBillable: '▸ Billable 工时',
|
|
|
sectionNonBillable: '▸ Non Billable 工时',
|
|
sectionNonBillable: '▸ Non Billable 工时',
|
|
|
sectionOther: '▸ 其他工时 Other Activities',
|
|
sectionOther: '▸ 其他工时 Other Activities',
|
|
@@ -403,8 +408,11 @@ var TC_I18N = {
|
|
|
statusEditable: 'Editable',
|
|
statusEditable: 'Editable',
|
|
|
statusSubmitted: 'Submitted (Locked)',
|
|
statusSubmitted: 'Submitted (Locked)',
|
|
|
statusApproved: 'Approved (Locked)',
|
|
statusApproved: 'Approved (Locked)',
|
|
|
- statusReadonly: 'N/A (External / Offline / Before employment)',
|
|
|
|
|
- preEmploymentLocked: 'Dates before the employment start date cannot be entered.',
|
|
|
|
|
|
|
+ statusReadonly: 'N/A (External / Offline / Outside employment)',
|
|
|
|
|
+ preEmploymentLocked: 'Dates outside the employment period cannot be entered.',
|
|
|
|
|
+ employmentInvalid: 'Invalid employment dates. Please check the employee profile.',
|
|
|
|
|
+ employmentDraftOutside: 'Draft hours outside the employment period cannot be saved or submitted: ',
|
|
|
|
|
+ personnelCalendarChanged: 'Employment dates or overseas status changed. Reload the page before saving or submitting.',
|
|
|
sectionBillable: '▸ Billable Hours',
|
|
sectionBillable: '▸ Billable Hours',
|
|
|
sectionNonBillable: '▸ Non-Billable Hours',
|
|
sectionNonBillable: '▸ Non-Billable Hours',
|
|
|
sectionOther: '▸ Other Activities',
|
|
sectionOther: '▸ Other Activities',
|
|
@@ -628,6 +636,8 @@ export function initPageData(userId, year, month) {
|
|
|
// ppExt 当前登录用户:基础信息用页面全局变量,staffType/workNo/cfStaff 从人员档案获取
|
|
// ppExt 当前登录用户:基础信息用页面全局变量,staffType/workNo/cfStaff 从人员档案获取
|
|
|
var loginInfo = this.buildLoginUserInfo();
|
|
var loginInfo = this.buildLoginUserInfo();
|
|
|
loginInfo.staffType = profileInfo.staffType || '';
|
|
loginInfo.staffType = profileInfo.staffType || '';
|
|
|
|
|
+ loginInfo.isOverseasStaff = profileInfo.isOverseasStaff === true;
|
|
|
|
|
+ loginInfo.employmentEndDate = profileInfo.employmentEndDate || '';
|
|
|
if (profileInfo.workNo) loginInfo.workNo = profileInfo.workNo;
|
|
if (profileInfo.workNo) loginInfo.workNo = profileInfo.workNo;
|
|
|
if (profileInfo.cfStaff) loginInfo.cfStaff = profileInfo.cfStaff;
|
|
if (profileInfo.cfStaff) loginInfo.cfStaff = profileInfo.cfStaff;
|
|
|
if (profileInfo.managerId) loginInfo.managerId = profileInfo.managerId;
|
|
if (profileInfo.managerId) loginInfo.managerId = profileInfo.managerId;
|
|
@@ -839,7 +849,9 @@ export function loadUserProfile(userId) {
|
|
|
cfStaff: fd[PROFILE_FIELD_IDS.cfStaff] || '',
|
|
cfStaff: fd[PROFILE_FIELD_IDS.cfStaff] || '',
|
|
|
managerId: (fd[PROFILE_FIELD_IDS.manager + '_id'] || [])[0] || '',
|
|
managerId: (fd[PROFILE_FIELD_IDS.manager + '_id'] || [])[0] || '',
|
|
|
managerName: (fd[PROFILE_FIELD_IDS.manager] || [])[0] || '',
|
|
managerName: (fd[PROFILE_FIELD_IDS.manager] || [])[0] || '',
|
|
|
- employmentStartDate: fd[PROFILE_FIELD_IDS.employmentStartDate] || ''
|
|
|
|
|
|
|
+ employmentStartDate: fd[PROFILE_FIELD_IDS.employmentStartDate] || '',
|
|
|
|
|
+ employmentEndDate: fd[PROFILE_FIELD_IDS.employmentEndDate] || '',
|
|
|
|
|
+ isOverseasStaff: fd[PROFILE_FIELD_IDS.overseasStaff] === '是'
|
|
|
};
|
|
};
|
|
|
}.bind(this));
|
|
}.bind(this));
|
|
|
}
|
|
}
|
|
@@ -1026,6 +1038,11 @@ export async function queryFullDetails(formUuid, formInstId, tableFieldId) {
|
|
|
* @returns {Promise<Object>} holidayMap { day(1-31): '调休'|'加班' }
|
|
* @returns {Promise<Object>} holidayMap { day(1-31): '调休'|'加班' }
|
|
|
*/
|
|
*/
|
|
|
export function loadHolidays(year, month) {
|
|
export function loadHolidays(year, month) {
|
|
|
|
|
+ // prd 海外员工只按自然周;清除国内全年缓存,供跨月请假及日期类型统一复用。
|
|
|
|
|
+ if ((this.state.userInfo || {}).isOverseasStaff === true) {
|
|
|
|
|
+ this._tcHolidayCalendarByYear = {};
|
|
|
|
|
+ return Promise.resolve({});
|
|
|
|
|
+ }
|
|
|
// prd 按年份字段查询节假日,每年不超过100条,再在 JS 中过滤当月
|
|
// prd 按年份字段查询节假日,每年不超过100条,再在 JS 中过滤当月
|
|
|
var holidaySearchFields = {};
|
|
var holidaySearchFields = {};
|
|
|
holidaySearchFields[HOLIDAY_FIELD_IDS.year] = String(year);
|
|
holidaySearchFields[HOLIDAY_FIELD_IDS.year] = String(year);
|
|
@@ -1138,6 +1155,7 @@ export function parseBeisenLeaveDate(value) {
|
|
|
* @returns {boolean} 是否工作日
|
|
* @returns {boolean} 是否工作日
|
|
|
*/
|
|
*/
|
|
|
export function isBeisenLeaveWorkday(year, month, day) {
|
|
export function isBeisenLeaveWorkday(year, month, day) {
|
|
|
|
|
+ if ((this.state.userInfo || {}).isOverseasStaff === true) return !this.isWeekend(year, month, day);
|
|
|
var dateKey = String(year) + toTwoDigitText(month) + toTwoDigitText(day);
|
|
var dateKey = String(year) + toTwoDigitText(month) + toTwoDigitText(day);
|
|
|
var yearCalendar = (this._tcHolidayCalendarByYear || {})[year] || {};
|
|
var yearCalendar = (this._tcHolidayCalendarByYear || {})[year] || {};
|
|
|
var holidayType = yearCalendar[dateKey];
|
|
var holidayType = yearCalendar[dateKey];
|
|
@@ -1784,7 +1802,7 @@ export function applyDefaultWorkdayHours(year, month, holidayMap, projectRows, b
|
|
|
var billable = billableData || {};
|
|
var billable = billableData || {};
|
|
|
var nonBillable = nonBillableData || {};
|
|
var nonBillable = nonBillableData || {};
|
|
|
var other = otherData || {};
|
|
var other = otherData || {};
|
|
|
- var holidays = holidayMap || {};
|
|
|
|
|
|
|
+ var holidays = (this.state.userInfo || {}).isOverseasStaff === true ? {} : holidayMap || {};
|
|
|
var blocked = blockedDays || {};
|
|
var blocked = blockedDays || {};
|
|
|
var daysInMonth = new Date(year, month, 0).getDate();
|
|
var daysInMonth = new Date(year, month, 0).getDate();
|
|
|
var today = new Date();
|
|
var today = new Date();
|
|
@@ -1977,9 +1995,14 @@ export function getRepairSubmitterStaffType() {
|
|
|
var staffType = data[PROFILE_FIELD_IDS.staffType];
|
|
var staffType = data[PROFILE_FIELD_IDS.staffType];
|
|
|
// fixme 唯一记录与真实被填报人 ID 必须同时成立,属性缺失或重复时不得豁免暂存校验。
|
|
// fixme 唯一记录与真实被填报人 ID 必须同时成立,属性缺失或重复时不得豁免暂存校验。
|
|
|
if (ids.length !== 1 || ids[0] !== userId || ['内部', '外部'].indexOf(staffType) < 0) throw new Error(failureText);
|
|
if (ids.length !== 1 || ids[0] !== userId || ['内部', '外部'].indexOf(staffType) < 0) throw new Error(failureText);
|
|
|
|
|
+ this.assertPersonnelSnapshot({
|
|
|
|
|
+ employmentStartDate: data[PROFILE_FIELD_IDS.employmentStartDate] || '',
|
|
|
|
|
+ employmentEndDate: data[PROFILE_FIELD_IDS.employmentEndDate] || '',
|
|
|
|
|
+ isOverseasStaff: data[PROFILE_FIELD_IDS.overseasStaff] === '是'
|
|
|
|
|
+ });
|
|
|
return staffType;
|
|
return staffType;
|
|
|
- }).catch(() => {
|
|
|
|
|
- throw new Error(failureText);
|
|
|
|
|
|
|
+ }).catch(error => {
|
|
|
|
|
+ throw new Error(error && error.message || failureText);
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1993,6 +2016,9 @@ export function getMissingOriginalSummaryDay() {
|
|
|
if (String(this.state.userId || '').trim() !== submitterUserId) throw new Error(this.getTexts().staffTypeCheckFailed);
|
|
if (String(this.state.userId || '').trim() !== submitterUserId) throw new Error(this.getTexts().staffTypeCheckFailed);
|
|
|
// prd 外部人员通过补填填报,只豁免当天正常 TimeCard 暂存工时校验。
|
|
// prd 外部人员通过补填填报,只豁免当天正常 TimeCard 暂存工时校验。
|
|
|
if (staffType === '外部') return '';
|
|
if (staffType === '外部') return '';
|
|
|
|
|
+ var businessToday = new Date(Date.now() + 8 * 60 * 60 * 1000);
|
|
|
|
|
+ // prd 任职期外提交日无需正常TimeCard暂存,仍严格校验补填来源日期。
|
|
|
|
|
+ if (this.isOutsideEmploymentDates(businessToday.getUTCFullYear(), businessToday.getUTCMonth() + 1, businessToday.getUTCDate())) return '';
|
|
|
var today = new Date();
|
|
var today = new Date();
|
|
|
var monthText = this.getRepairMonthText(today.getFullYear(), today.getMonth() + 1);
|
|
var monthText = this.getRepairMonthText(today.getFullYear(), today.getMonth() + 1);
|
|
|
var dayText = monthText + toTwoDigitText(today.getDate());
|
|
var dayText = monthText + toTwoDigitText(today.getDate());
|
|
@@ -2072,28 +2098,16 @@ export function nextMonth() {
|
|
|
// ============================================================
|
|
// ============================================================
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 判断指定日期是否早于当前员工入职日期。
|
|
|
|
|
- * prd 入职当日可填写;人员档案未维护或日期无效时保持原行为。
|
|
|
|
|
|
|
+ * 兼容入口:判断指定日期是否位于当前员工任职期间外。
|
|
|
|
|
+ * prd 入职和离职当日可填写;空日期不设边界,非法日期显式报错。
|
|
|
* @param {number} year - 年份
|
|
* @param {number} year - 年份
|
|
|
* @param {number} month - 月份 1-12
|
|
* @param {number} month - 月份 1-12
|
|
|
* @param {number} day - 日 1-31
|
|
* @param {number} day - 日 1-31
|
|
|
- * @returns {boolean} 是否为入职前日期
|
|
|
|
|
|
|
+ * @returns {boolean} 是否为任职期间外日期
|
|
|
*/
|
|
*/
|
|
|
export function isBeforeEmploymentDate(year, month, day) {
|
|
export function isBeforeEmploymentDate(year, month, day) {
|
|
|
- var raw = this.state && this.state.userInfo ? this.state.userInfo.employmentStartDate : '';
|
|
|
|
|
- if (raw === undefined || raw === null || raw === '') return false;
|
|
|
|
|
- var employmentDate;
|
|
|
|
|
- if (typeof raw === 'string' && /^\d{4}[-/]\d{1,2}[-/]\d{1,2}/.test(raw)) {
|
|
|
|
|
- var parts = raw.substring(0, 10).split(/[-/]/);
|
|
|
|
|
- employmentDate = new Date(parseInt(parts[0], 10), parseInt(parts[1], 10) - 1, parseInt(parts[2], 10));
|
|
|
|
|
- } else {
|
|
|
|
|
- var timestamp = typeof raw === 'string' ? parseInt(raw, 10) : raw;
|
|
|
|
|
- employmentDate = new Date(timestamp);
|
|
|
|
|
- }
|
|
|
|
|
- if (isNaN(employmentDate.getTime())) return false;
|
|
|
|
|
- var employmentKey = employmentDate.getFullYear() * 10000 + (employmentDate.getMonth() + 1) * 100 + employmentDate.getDate();
|
|
|
|
|
- var targetKey = year * 10000 + month * 100 + day;
|
|
|
|
|
- return targetKey < employmentKey;
|
|
|
|
|
|
|
+ // ppExt 兼容已有输入、默认值、保存及审批入口;现在统一限制任职闭区间。
|
|
|
|
|
+ return this.isOutsideEmploymentDates(year, month, day);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -2457,7 +2471,7 @@ export function saveDraft() {
|
|
|
});
|
|
});
|
|
|
this.showLoading();
|
|
this.showLoading();
|
|
|
// prd 补填保存与提交一致:先实时确认月份已封账,再校验员工和 yyyyMM 月份。
|
|
// prd 补填保存与提交一致:先实时确认月份已封账,再校验员工和 yyyyMM 月份。
|
|
|
- this.assertRepairMonthAvailable().then(function () {
|
|
|
|
|
|
|
+ this.getRepairSubmitterStaffType().then(() => this.assertRepairMonthAvailable()).then(function () {
|
|
|
var contextError = this.getRepairSubmissionContextError();
|
|
var contextError = this.getRepairSubmissionContextError();
|
|
|
if (contextError) throw new Error(contextError);
|
|
if (contextError) throw new Error(contextError);
|
|
|
return this.saveTimecardData('draft');
|
|
return this.saveTimecardData('draft');
|
|
@@ -3304,7 +3318,7 @@ export function saveTimecardData(saveType) {
|
|
|
|
|
|
|
|
// prd 写入日期类型:先取常规值(工作日/周末),再按节假日覆盖
|
|
// prd 写入日期类型:先取常规值(工作日/周末),再按节假日覆盖
|
|
|
var dayTypeVal = this.isWeekend(year, month, d) ? '周末' : '工作日';
|
|
var dayTypeVal = this.isWeekend(year, month, d) ? '周末' : '工作日';
|
|
|
- var hType = (this.state.holidayMap || {})[d];
|
|
|
|
|
|
|
+ var hType = this.getHolidayType(d);
|
|
|
if (hType === '加班') dayTypeVal = '节假日-加班';
|
|
if (hType === '加班') dayTypeVal = '节假日-加班';
|
|
|
if (hType === '调休') dayTypeVal = '节假日-调休';
|
|
if (hType === '调休') dayTypeVal = '节假日-调休';
|
|
|
formData[TIME_FIELD_IDS.dayType] = dayTypeVal;
|
|
formData[TIME_FIELD_IDS.dayType] = dayTypeVal;
|
|
@@ -3698,6 +3712,7 @@ export function isWeekend(year, month, day) {
|
|
|
* @returns {boolean} 是否休息日
|
|
* @returns {boolean} 是否休息日
|
|
|
*/
|
|
*/
|
|
|
export function isDayOff(year, month, day) {
|
|
export function isDayOff(year, month, day) {
|
|
|
|
|
+ if ((this.state.userInfo || {}).isOverseasStaff === true) return this.isWeekend(year, month, day);
|
|
|
var holidayMap = this.state.holidayMap || {};
|
|
var holidayMap = this.state.holidayMap || {};
|
|
|
var hType = holidayMap[day];
|
|
var hType = holidayMap[day];
|
|
|
if (hType === '加班') return false;
|
|
if (hType === '加班') return false;
|
|
@@ -3711,6 +3726,7 @@ export function isDayOff(year, month, day) {
|
|
|
* @returns {string|null} '调休' | '加班' | null
|
|
* @returns {string|null} '调休' | '加班' | null
|
|
|
*/
|
|
*/
|
|
|
export function getHolidayType(day) {
|
|
export function getHolidayType(day) {
|
|
|
|
|
+ if ((this.state.userInfo || {}).isOverseasStaff === true) return null;
|
|
|
var holidayMap = this.state.holidayMap || {};
|
|
var holidayMap = this.state.holidayMap || {};
|
|
|
return holidayMap[day] || null;
|
|
return holidayMap[day] || null;
|
|
|
}
|
|
}
|
|
@@ -4997,7 +5013,7 @@ export function renderJsx() {
|
|
|
var dt = new Date(selectedYear, selectedMonth - 1, d);
|
|
var dt = new Date(selectedYear, selectedMonth - 1, d);
|
|
|
var dow = dt.getDay();
|
|
var dow = dt.getDay();
|
|
|
// prd 综合节假日判断:调休→休息日,加班→工作日,未维护→原逻辑
|
|
// prd 综合节假日判断:调休→休息日,加班→工作日,未维护→原逻辑
|
|
|
- var hType = holidayMap[d];
|
|
|
|
|
|
|
+ var hType = userInfo.isOverseasStaff === true ? null : holidayMap[d];
|
|
|
var isNaturalWe = dow === 0 || dow === 6;
|
|
var isNaturalWe = dow === 0 || dow === 6;
|
|
|
var isDayOff = hType === '调休' ? true : hType === '加班' ? false : isNaturalWe;
|
|
var isDayOff = hType === '调休' ? true : hType === '加班' ? false : isNaturalWe;
|
|
|
allDays.push({
|
|
allDays.push({
|
|
@@ -5827,3 +5843,68 @@ export function didUnmount() {
|
|
|
}
|
|
}
|
|
|
this._tcResizeHandler = null;
|
|
this._tcResizeHandler = null;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+/** @param {number|string} raw 日期字段值 @returns {number} 上海业务日期yyyyMMdd,空值为0 */
|
|
|
|
|
+export function getEmploymentDateKey(raw) {
|
|
|
|
|
+ if (raw === undefined || raw === null || raw === '') return 0;
|
|
|
|
|
+ const text = String(raw).trim();
|
|
|
|
|
+ let date;
|
|
|
|
|
+ if (/^\d{4}[-/]\d{1,2}[-/]\d{1,2}$/.test(text)) {
|
|
|
|
|
+ const parts = text.split(/[-/]/).map(value => Number(value));
|
|
|
|
|
+ date = new Date(Date.UTC(parts[0], parts[1] - 1, parts[2]));
|
|
|
|
|
+ if (date.getUTCFullYear() !== parts[0] || date.getUTCMonth() + 1 !== parts[1] || date.getUTCDate() !== parts[2]) date = new Date(NaN);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ const epoch = /^\d+$/.test(text) ? Number(text) : Date.parse(text);
|
|
|
|
|
+ date = new Date(epoch + 8 * 60 * 60 * 1000);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!Number.isFinite(date.getTime())) throw new Error(this.getTexts().employmentInvalid);
|
|
|
|
|
+ return date.getUTCFullYear() * 10000 + (date.getUTCMonth() + 1) * 100 + date.getUTCDate();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** @param {Object} profile 人员档案 @returns {Array<number>} 任职闭区间,0表示未维护 */
|
|
|
|
|
+export function getEmploymentBounds(profile) {
|
|
|
|
|
+ const info = profile || {};
|
|
|
|
|
+ const start = this.getEmploymentDateKey(info.employmentStartDate);
|
|
|
|
|
+ const end = this.getEmploymentDateKey(info.employmentEndDate);
|
|
|
|
|
+ if (start && end && start > end) throw new Error(this.getTexts().employmentInvalid);
|
|
|
|
|
+ return [start, end];
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** @param {number} year 年 @param {number} month 月 @param {number} day 日 @returns {boolean} 任职期间外 */
|
|
|
|
|
+export function isOutsideEmploymentDates(year, month, day) {
|
|
|
|
|
+ const bounds = this.getEmploymentBounds((this.state || {}).userInfo);
|
|
|
|
|
+ const target = year * 10000 + month * 100 + day;
|
|
|
|
|
+ return !!((bounds[0] && target < bounds[0]) || (bounds[1] && target > bounds[1]));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** @returns {void} 明确阻止范围外草稿被静默过滤后部分提交,已锁定历史记录只读保留 */
|
|
|
|
|
+export function assertEmploymentInputs() {
|
|
|
|
|
+ const year = this.state.selectedYear;
|
|
|
|
|
+ const month = this.state.selectedMonth;
|
|
|
|
|
+ const invalid = [];
|
|
|
|
|
+ for (let day = 1; day <= new Date(year, month, 0).getDate(); day++) {
|
|
|
|
|
+ if (!this.isOutsideEmploymentDates(year, month, day)) continue;
|
|
|
|
|
+ if ((this.state.lockedDays || {})[day] || (this.state.originalBlockedDays || {})[day] || (this.state.repairBlockedDays || {})[day]) continue;
|
|
|
|
|
+ const hasDraft = ['billable', 'nonBillable', 'other'].some(section => {
|
|
|
|
|
+ const data = this.state[section + 'Data'] || {};
|
|
|
|
|
+ return Object.keys(data).some(row => {
|
|
|
|
|
+ const status = (this.state.cellStatusMap || {})[section + '_' + row + '_' + day];
|
|
|
|
|
+ return status !== 'approved' && status !== 'submitted' && Math.abs(Number((data[row] || {})[day]) || 0) > 0;
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+ if (hasDraft) invalid.push(String(year * 10000 + month * 100 + day));
|
|
|
|
|
+ }
|
|
|
|
|
+ if (invalid.length) throw new Error(this.getTexts().employmentDraftOutside + invalid.join(', '));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/** @param {Object} profile 实时人员档案 @returns {void} 档案变化必须重新加载,避免旧默认值和日历继续提交 */
|
|
|
|
|
+export function assertPersonnelSnapshot(profile) {
|
|
|
|
|
+ const current = (this.state || {}).userInfo || {};
|
|
|
|
|
+ const before = this.getEmploymentBounds(current);
|
|
|
|
|
+ const after = this.getEmploymentBounds(profile);
|
|
|
|
|
+ if (before.join(',') !== after.join(',') || !!current.isOverseasStaff !== !!profile.isOverseasStaff) {
|
|
|
|
|
+ throw new Error(this.getTexts().personnelCalendarChanged);
|
|
|
|
|
+ }
|
|
|
|
|
+ this.assertEmploymentInputs();
|
|
|
|
|
+}
|