1
This commit is contained in:
2025-10-27 11:46:57 +08:00
parent 37dcd00919
commit c5f1611f3a

View File

@ -74,6 +74,7 @@ export default function App() {
const WEEKEND_DAYS_FIELD_ID = 'fld2BvjbIN'; // 休息日字段ID多选项0-6代表周一到周日
const START_DATE_RULE_FIELD_ID = 'fld0KsQ2j3'; // 起始日期调整规则字段ID
const DATE_ADJUSTMENT_RULE_FIELD_ID = 'fld0KsQ2j3'; // 日期调整规则字段ID
const EXCLUDED_DATES_FIELD_ID = 'fldGxzC5uG'; // 不参与计算日期多选格式yyyy-MM-dd
// 时效数据表相关常量
const TIMELINE_TABLE_ID = 'tblPnQscqwqopJ8V'; // 时效数据表ID
@ -217,7 +218,6 @@ export default function App() {
weekendDaysConfig: [],
matchedLabels: [],
skippedWeekends: 0,
skippedHolidays: 0,
actualDays: undefined,
startDateRule: undefined,
dateAdjustmentRule: undefined,
@ -269,19 +269,7 @@ export default function App() {
// 起始时间字段(货期记录表新增)
const DELIVERY_START_TIME_FIELD_ID = 'fld727qCAv';
// 中国法定节假日配置需要手动维护或使用API
const CHINESE_HOLIDAYS = [
'2024-01-01', // 元旦
'2024-02-10', '2024-02-11', '2024-02-12', // 春节
'2024-04-04', '2024-04-05', '2024-04-06', // 清明节
'2024-05-01', '2024-05-02', '2024-05-03', // 劳动节
'2024-06-10', // 端午节
'2024-09-15', '2024-09-16', '2024-09-17', // 中秋节
'2024-10-01', '2024-10-02', '2024-10-03', // 国庆节
// ... 其他节假日
];
// 已移除未使用的 fetchHolidays 函数
// 已移除中国法定节假日相关常量和配置
// 这个变量声明也不需要了
// const nodeNameToOptionId = new Map();
@ -420,52 +408,39 @@ export default function App() {
}
};
// 计算跳过的法定节假日天数
const calculateSkippedHolidays = (startDateStr: string | Date, endDateStr: string | Date): number => {
// 计算时间范围内实际跳过的自定义日期
const calculateExcludedDatesInRange = (startDate: Date | string, endDate: Date | string, excludedDates: string[] = []): { count: number, dates: string[] } => {
if (!excludedDates || excludedDates.length === 0) {
return { count: 0, dates: [] };
}
try {
const startDate = typeof startDateStr === 'string' ? new Date(startDateStr) : startDateStr;
const endDate = typeof endDateStr === 'string' ? new Date(endDateStr) : endDateStr;
const start = typeof startDate === 'string' ? parseDate(startDate) : startDate;
const end = typeof endDate === 'string' ? parseDate(endDate) : endDate;
if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) {
return 0;
if (!start || !end || isNaN(start.getTime()) || isNaN(end.getTime())) {
return { count: 0, dates: [] };
}
if (typeof startDateStr === 'string' && (startDateStr.includes('未找到') || startDateStr.includes('时效值为0'))) {
return 0;
const actualExcludedDates: string[] = [];
for (const excludedDateStr of excludedDates) {
const excludedDate = parseDate(excludedDateStr);
if (excludedDate && excludedDate >= start && excludedDate <= end) {
actualExcludedDates.push(excludedDateStr);
}
}
if (typeof endDateStr === 'string' && (endDateStr.includes('未找到') || endDateStr.includes('时效值为0'))) {
return 0;
}
let count = 0;
let currentDate = new Date(startDate);
while (currentDate <= endDate) {
if (isChineseHoliday(currentDate)) {
count++;
}
currentDate = addDays(currentDate, 1);
}
return count;
return { count: actualExcludedDates.length, dates: actualExcludedDates };
} catch (error) {
return 0;
console.error('计算跳过日期失败:', error);
return { count: 0, dates: [] };
}
};
// 判断是否为中国节假日
const isChineseHoliday = (date: Date, holidays: string[] = CHINESE_HOLIDAYS): boolean => {
try {
if (isNaN(date.getTime())) {
return false;
}
const dateStr = format(date, 'yyyy-MM-dd');
return holidays.includes(dateStr);
} catch (error) {
return false;
}
};
// 已移除法定节假日跳过统计函数
// 已移除中国节假日判断函数
// 判断是否为自定义周末 - 支持空的休息日配置
const isCustomWeekend = (date: Date, weekendDays: number[] = []): boolean => {
@ -473,9 +448,15 @@ export default function App() {
return weekendDays.includes(date.getDay());
};
// 判断是否为工作日 - 只排除法定节假日和表格配置的休息日
const isBusinessDay = (date: Date, weekendDays: number[] = []): boolean => {
return !isCustomWeekend(date, weekendDays) && !isChineseHoliday(date);
// 判断是否为工作日 - 排除表格休息日、以及节点自定义不参与计算日期
const isBusinessDay = (date: Date, weekendDays: number[] = [], excludedDates: string[] = []): boolean => {
try {
const dateStr = format(date, 'yyyy-MM-dd');
const isExcluded = Array.isArray(excludedDates) && excludedDates.includes(dateStr);
return !isCustomWeekend(date, weekendDays) && !isExcluded;
} catch {
return !isCustomWeekend(date, weekendDays);
}
};
// 日期调整函数
@ -577,7 +558,7 @@ export default function App() {
};
// 调整到下一个工作时间开始点
const adjustToNextWorkingHour = (date: Date, calculationMethod: string): Date => {
const adjustToNextWorkingHour = (date: Date, calculationMethod: string, weekendDays: number[] = [], excludedDates: string[] = []): Date => {
const result = new Date(date);
if (calculationMethod === '内部') {
@ -591,8 +572,8 @@ export default function App() {
result.setDate(result.getDate() + 1);
}
// 找到下一个工作日
while (!isBusinessDay(result, [])) {
// 找到下一个工作日(考虑休息日和自定义跳过日期)
while (!isBusinessDay(result, weekendDays, excludedDates)) {
result.setDate(result.getDate() + 1);
}
@ -605,7 +586,7 @@ export default function App() {
};
// 内部工作时间计算函数
const addInternalBusinessTime = (startDate: Date, businessDays: number, weekendDays: number[] = []): Date => {
const addInternalBusinessTime = (startDate: Date, businessDays: number, weekendDays: number[] = [], excludedDates: string[] = []): Date => {
const result = new Date(startDate);
let remainingDays = businessDays;
@ -615,7 +596,7 @@ export default function App() {
while (addedDays < wholeDays) {
result.setDate(result.getDate() + 1);
if (isBusinessDay(result, weekendDays)) {
if (isBusinessDay(result, weekendDays, excludedDates)) {
addedDays++;
}
}
@ -634,7 +615,7 @@ export default function App() {
} else if (currentHour >= 18) {
// 跳到下一个工作日的9:00
result.setDate(result.getDate() + 1);
while (!isBusinessDay(result, weekendDays)) {
while (!isBusinessDay(result, weekendDays, excludedDates)) {
result.setDate(result.getDate() + 1);
}
currentHour = 9;
@ -653,7 +634,7 @@ export default function App() {
// 跳到下一个工作日
result.setDate(result.getDate() + 1);
while (!isBusinessDay(result, weekendDays)) {
while (!isBusinessDay(result, weekendDays, excludedDates)) {
result.setDate(result.getDate() + 1);
}
@ -666,8 +647,8 @@ export default function App() {
return result;
};
// 添加工作日 - 使用表格配置的休息日
const addBusinessDaysWithHolidays = (startDate: Date, businessDays: number, weekendDays: number[] = []): Date => {
// 添加工作日 - 使用表格配置的休息日与节点自定义跳过日期
const addBusinessDaysWithHolidays = (startDate: Date, businessDays: number, weekendDays: number[] = [], excludedDates: string[] = []): Date => {
const result = new Date(startDate);
let addedDays = 0;
@ -678,7 +659,7 @@ export default function App() {
// 添加整数工作日
while (addedDays < wholeDays) {
result.setDate(result.getDate() + 1);
if (isBusinessDay(result, weekendDays)) {
if (isBusinessDay(result, weekendDays, excludedDates)) {
addedDays++;
}
}
@ -1028,6 +1009,27 @@ export default function App() {
// 如果表格中没有配置休息日或配置为空,则该节点没有固定休息日
// 这样就完全依赖表格数据,不会有任何硬编码的默认值
// 处理不参与计算日期(自定义跳过日期)
let excludedDates: string[] = [];
const excludedDatesField = fields[EXCLUDED_DATES_FIELD_ID];
if (excludedDatesField) {
console.log('原始不参与计算日期字段数据:', excludedDatesField);
if (Array.isArray(excludedDatesField)) {
excludedDates = excludedDatesField.map(item => {
if (item && typeof item === 'object') {
const val = item.text || item.name || item.value || item.id || '';
return String(val).trim();
}
return String(item).trim();
}).filter(d => !!d);
} else if (typeof excludedDatesField === 'string') {
excludedDates = excludedDatesField.split(/[\,\s]+/).map(s => s.trim()).filter(Boolean);
} else if (excludedDatesField && typeof excludedDatesField === 'object' && excludedDatesField.text) {
excludedDates = [String(excludedDatesField.text).trim()].filter(Boolean);
}
console.log('解析后的不参与计算日期:', excludedDates);
}
if (isMatched) {
// 获取起始日期调整规则
const startDateRule = fields[START_DATE_RULE_FIELD_ID];
@ -1041,6 +1043,7 @@ export default function App() {
matchedLabels: matchedLabels,
processOrder: orderValue, // 添加流程顺序
weekendDays: weekendDays, // 添加休息日配置
excludedDates: excludedDates, // 添加自定义跳过日期
startDateRule: startDateRule, // 添加起始日期调整规则
dateAdjustmentRule: dateAdjustmentRule // 添加JSON格式日期调整规则
});
@ -1324,15 +1327,15 @@ export default function App() {
// 计算当前节点的开始和完成时间(使用工作日计算)
const calculateTimeline = (startDate: Date, timelineValue: number, calculationMethod: string = '外部') => {
// 根据计算方式调整开始时间
const adjustedStartDate = adjustToNextWorkingHour(startDate, calculationMethod);
const adjustedStartDate = adjustToNextWorkingHour(startDate, calculationMethod, processNode.weekendDays, processNode.excludedDates || []);
let endDate: Date;
if (calculationMethod === '内部') {
// 使用内部工作时间计算
endDate = addInternalBusinessTime(adjustedStartDate, timelineValue, processNode.weekendDays);
endDate = addInternalBusinessTime(adjustedStartDate, timelineValue, processNode.weekendDays, processNode.excludedDates || []);
} else {
// 使用原有的24小时制计算
endDate = addBusinessDaysWithHolidays(adjustedStartDate, timelineValue, processNode.weekendDays);
endDate = addBusinessDaysWithHolidays(adjustedStartDate, timelineValue, processNode.weekendDays, processNode.excludedDates || []);
}
return {
@ -1410,11 +1413,11 @@ export default function App() {
let nodeEndTime: Date;
if (timelineValue) {
const adjustedStartTime = adjustToNextWorkingHour(nodeStartTime, nodeCalculationMethod);
const adjustedStartTime = adjustToNextWorkingHour(nodeStartTime, nodeCalculationMethod, processNode.weekendDays, processNode.excludedDates || []);
if (nodeCalculationMethod === '内部') {
nodeEndTime = addInternalBusinessTime(adjustedStartTime, timelineValue, processNode.weekendDays);
nodeEndTime = addInternalBusinessTime(adjustedStartTime, timelineValue, processNode.weekendDays, processNode.excludedDates || []);
} else {
nodeEndTime = addBusinessDaysWithHolidays(adjustedStartTime, timelineValue, processNode.weekendDays);
nodeEndTime = addBusinessDaysWithHolidays(adjustedStartTime, timelineValue, processNode.weekendDays, processNode.excludedDates || []);
}
} else {
nodeEndTime = new Date(nodeStartTime);
@ -1422,9 +1425,11 @@ export default function App() {
// 计算跳过的天数
const skippedWeekends = calculateSkippedWeekends(nodeStartTime, nodeEndTime, processNode.weekendDays);
const skippedHolidays = calculateSkippedHolidays(timelineResult.startDate, timelineResult.endDate);
const actualDays = calculateActualDays(timelineResult.startDate, timelineResult.endDate);
// 计算时间范围内实际跳过的自定义日期
const excludedDatesInRange = calculateExcludedDatesInRange(nodeStartTime, nodeEndTime, processNode.excludedDates || []);
results.push({
processOrder: processNode.processOrder,
nodeName: processNode.nodeName,
@ -1445,10 +1450,13 @@ export default function App() {
// 新增:标识是否为累加处理
isAccumulated: processingRule === '累加值' && matchedCandidates.length > 1,
weekendDaysConfig: processNode.weekendDays, // 新增:保存休息日配置用于显示
excludedDates: processNode.excludedDates || [], // 新增:保存不参与计算日期用于显示与快照
// 新增:保存时间范围内实际跳过的日期
actualExcludedDates: excludedDatesInRange.dates,
actualExcludedDatesCount: excludedDatesInRange.count,
calculationMethod: nodeCalculationMethod, // 新增:保存计算方式
ruleDescription: ruleDescription, // 新增:保存规则描述
skippedWeekends: skippedWeekends,
skippedHolidays: skippedHolidays,
actualDays: actualDays,
// 新增:保存调整规则用于重新计算
startDateRule: processNode.startDateRule,
@ -1571,25 +1579,28 @@ export default function App() {
const nodeCalculationMethod = result.calculationMethod || '外部'; // 获取节点的计算方式
let nodeEndTime: Date;
const nodeExcludedDates = Array.isArray(result.excludedDates) ? result.excludedDates : [];
if (adjustedTimelineValue > 0) {
const adjustedStartTime = adjustToNextWorkingHour(nodeStartTime, nodeCalculationMethod);
const adjustedStartTime = adjustToNextWorkingHour(nodeStartTime, nodeCalculationMethod, nodeWeekendDays, nodeExcludedDates);
if (nodeCalculationMethod === '内部') {
nodeEndTime = addInternalBusinessTime(adjustedStartTime, adjustedTimelineValue, nodeWeekendDays);
nodeEndTime = addInternalBusinessTime(adjustedStartTime, adjustedTimelineValue, nodeWeekendDays, nodeExcludedDates);
} else {
nodeEndTime = addBusinessDaysWithHolidays(adjustedStartTime, adjustedTimelineValue, nodeWeekendDays);
nodeEndTime = addBusinessDaysWithHolidays(adjustedStartTime, adjustedTimelineValue, nodeWeekendDays, nodeExcludedDates);
}
} else {
nodeEndTime = new Date(nodeStartTime);
}
// 计算跳过的天数
const adjustedStartTime = adjustedTimelineValue > 0 ? adjustToNextWorkingHour(nodeStartTime, nodeCalculationMethod) : nodeStartTime;
const adjustedStartTime = adjustedTimelineValue > 0 ? adjustToNextWorkingHour(nodeStartTime, nodeCalculationMethod, nodeWeekendDays, nodeExcludedDates) : nodeStartTime;
const skippedWeekends = calculateSkippedWeekends(adjustedStartTime, nodeEndTime, nodeWeekendDays);
const estimatedStartStr = formatDate(adjustedStartTime);
const estimatedEndStr = adjustedTimelineValue > 0 ? formatDate(nodeEndTime) : '时效值为0';
const skippedHolidays = calculateSkippedHolidays(estimatedStartStr, estimatedEndStr);
const actualDays = calculateActualDays(estimatedStartStr, estimatedEndStr);
// 计算时间范围内实际跳过的自定义日期
const excludedDatesInRange = calculateExcludedDatesInRange(adjustedStartTime, nodeEndTime, nodeExcludedDates);
// 更新结果
updatedResults[i] = {
...result,
@ -1599,8 +1610,10 @@ export default function App() {
adjustment: adjustment,
calculationMethod: nodeCalculationMethod, // 保持计算方式
skippedWeekends: skippedWeekends,
skippedHolidays: skippedHolidays,
actualDays: actualDays,
// 更新时间范围内实际跳过的日期
actualExcludedDates: excludedDatesInRange.dates,
actualExcludedDatesCount: excludedDatesInRange.count,
adjustmentDescription: result.adjustmentDescription, // 保持调整规则描述
ruleDescription: ruleDescription // 添加更新后的规则描述
};
@ -2981,11 +2994,14 @@ export default function App() {
backgroundColor: '#f0f0f0',
border: '1px solid #d9d9d9'
}}
title={`计算方式详情:\n${result.calculationMethod === '内部' ? '内部计算 (9小时工作制)' : '外部计算 (24小时制)'}${result.ruleDescription ? `\n应用规则${result.ruleDescription}` : ''}\n已跳过周末${result.skippedWeekends || 0}\n已跳过法定节假日:${result.skippedHolidays || 0}\n${result.weekendDaysConfig && result.weekendDaysConfig.length > 0 ? `休息日配置:${result.weekendDaysConfig.map(day => ['周日', '周一', '周二', '周三', '周四', '周五', '周六'][day]).join(', ')}` : '休息日配置:无固定休息日'}${result.calculationMethod === '内部' ? '\n工作时间9:00-18:00 (9小时制)' : ''}`}
title={`计算方式详情:\n${result.calculationMethod === '内部' ? '内部计算 (9小时工作制)' : '外部计算 (24小时制)'}${result.ruleDescription ? `\n应用规则${result.ruleDescription}` : ''}\n已跳过周末${result.skippedWeekends || 0}\n${result.weekendDaysConfig && result.weekendDaysConfig.length > 0 ? `休息日配置:${result.weekendDaysConfig.map(day => ['周日', '周一', '周二', '周三', '周四', '周五', '周六'][day]).join(', ')}` : '休息日配置:无固定休息日'}${result.calculationMethod === '内部' ? '\n工作时间9:00-18:00 (9小时制)' : ''}${(Array.isArray(result.actualExcludedDates) && result.actualExcludedDates.length > 0) ? `\n\n跳过的具体日期\n${result.actualExcludedDates.join('\n')}` : ''}`}
>
?
</span>
</Text>
<div style={{ fontSize: '12px', color: '#666', marginTop: '2px' }}>
<Text>{(result.actualExcludedDatesCount && result.actualExcludedDatesCount > 0) ? `${result.actualExcludedDatesCount}` : '无'}</Text>
</div>
</div>
</div>
</Card>
@ -3006,7 +3022,7 @@ export default function App() {
<br />
<br />
<br />
"工作日"
<br />