diff --git a/src/App.tsx b/src/App.tsx index 5385e80..06cd9a4 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2903,7 +2903,10 @@ export default function App() { }; // 获取重新计算后的时间线结果(不更新状态,逻辑对齐页面的重算口径) - const getRecalculatedTimeline = (adjustments: { [key: number]: number }) => { + const getRecalculatedTimeline = ( + adjustments: { [key: number]: number }, + opts?: { ignoreActualCompletionDates?: boolean; actualCompletionDatesOverride?: { [key: number]: Date | null } } + ) => { const updatedResults = [...timelineResults]; let cumulativeStartTime = startTime ? new Date(startTime) : new Date(); // 从起始时间开始 @@ -2974,11 +2977,18 @@ export default function App() { nodeEndTime = new Date(nodeStartTime); } + const actualEnd = opts?.ignoreActualCompletionDates + ? null + : (opts?.actualCompletionDatesOverride ?? actualCompletionDates)?.[i] ?? null; + // 计算跳过的天数及日期范围内的自定义跳过日期 const adjustedStartTime = adjustToNextWorkingHour(nodeStartTime, nodeCalculationMethod, nodeWeekendDays, nodeExcludedDates); const skippedWeekends = calculateSkippedWeekends(adjustedStartTime, nodeEndTime, nodeWeekendDays); const estimatedStartStr = formatDate(adjustedStartTime); - const estimatedEndStr = adjustedTimelineValue !== 0 ? formatDate(nodeEndTime) : '时效值为0'; + let estimatedEndStr = adjustedTimelineValue !== 0 ? formatDate(nodeEndTime) : '时效值为0'; + if (actualEnd && actualEnd instanceof Date && !isNaN(actualEnd.getTime())) { + estimatedEndStr = formatDate(actualEnd); + } const actualDays = calculateActualDays(estimatedStartStr, estimatedEndStr); const excludedDatesInRange = calculateExcludedDatesInRange(adjustedStartTime, nodeEndTime, nodeExcludedDates); @@ -3000,7 +3010,11 @@ export default function App() { // 更新累积开始时间:使用当前节点的预计完成时间 if (adjustedTimelineValue !== 0) { - cumulativeStartTime = new Date(nodeEndTime); + if (actualEnd && actualEnd instanceof Date && !isNaN(actualEnd.getTime())) { + cumulativeStartTime = new Date(actualEnd); + } else { + cumulativeStartTime = new Date(nodeEndTime); + } } } @@ -3168,7 +3182,7 @@ export default function App() { const computeLastNodeEndDeltaDays = (adjustments: { [key: number]: number }): number => { try { if (timelineDirection === 'backward') return 0; - const baseline = getRecalculatedTimeline({}); + const baseline = getRecalculatedTimeline({}, { ignoreActualCompletionDates: true }); const current = getRecalculatedTimeline(adjustments); const pickLastNodeEnd = (results: any[]): Date | null => { @@ -3216,10 +3230,19 @@ export default function App() { const handleExpectedDeliveryDateLockChange = (checked: boolean) => { const nextLocked = !!checked; setIsExpectedDeliveryDateLocked(nextLocked); - if (!nextLocked) return; - if (lockedExpectedDeliveryDateTs !== null && lockedExpectedDeliveryDateTs !== undefined) return; - const computed = computeExpectedDeliveryDateTsFromResults(timelineResults, timelineAdjustments); - if (computed !== null) setLockedExpectedDeliveryDateTs(computed); + if (!nextLocked) { + setLockedExpectedDeliveryDateTs(null); + return; + } + if (!expectedDate || isNaN(expectedDate.getTime())) { + setIsExpectedDeliveryDateLocked(false); + setLockedExpectedDeliveryDateTs(null); + if (bitable.ui.showToast) { + bitable.ui.showToast({ toastType: ToastType.warning, message: '请先选择客户期望日期,再开启锁交付' }); + } + return; + } + setLockedExpectedDeliveryDateTs(expectedDate.getTime()); }; const computeDynamicBufferDaysUsingEndDelta = (adjustments: { [key: number]: number }, baseBufferDaysOverride?: number): number => { @@ -5675,11 +5698,9 @@ export default function App() { } }} footer={ -
- - - {mode === 'adjust' && isExpectedDeliveryDateLocked ? '缓冲期(天)(不影响已锁交付):' : '缓冲期(天):'} - +
+ + {mode === 'adjust' && isExpectedDeliveryDateLocked ? '基础缓冲期(天)(不影响已锁交付):' : '基础缓冲期(天):'} + 剩余缓冲期(天): + @@ -6249,6 +6276,7 @@ export default function App() { style={{ width: '200px' }} placeholder="请选择客户期望日期" value={expectedDate ?? undefined} + disabled={mode === 'adjust' && isExpectedDeliveryDateLocked} onChange={(date) => { if (date instanceof Date) { setExpectedDate(date);