18
18
This commit is contained in:
116
src/App.tsx
116
src/App.tsx
@ -206,8 +206,6 @@ export default function App() {
|
|||||||
const [actualCompletionDates, setActualCompletionDates] = useState<{[key: number]: Date | null}>({});
|
const [actualCompletionDates, setActualCompletionDates] = useState<{[key: number]: Date | null}>({});
|
||||||
// 基础缓冲期天数(可配置),用于计算动态缓冲期,默认0天
|
// 基础缓冲期天数(可配置),用于计算动态缓冲期,默认0天
|
||||||
const [baseBufferDays, setBaseBufferDays] = useState<number>(0);
|
const [baseBufferDays, setBaseBufferDays] = useState<number>(0);
|
||||||
const [lockedExpectedDeliveryDateTs, setLockedExpectedDeliveryDateTs] = useState<number | null>(null);
|
|
||||||
const [isExpectedDeliveryDateLocked, setIsExpectedDeliveryDateLocked] = useState<boolean>(false);
|
|
||||||
// 快照回填来源(foreign_id、款式、颜色、文本2)
|
// 快照回填来源(foreign_id、款式、颜色、文本2)
|
||||||
const [currentForeignId, setCurrentForeignId] = useState<string | null>(null);
|
const [currentForeignId, setCurrentForeignId] = useState<string | null>(null);
|
||||||
const [currentStyleText, setCurrentStyleText] = useState<string>('');
|
const [currentStyleText, setCurrentStyleText] = useState<string>('');
|
||||||
@ -283,8 +281,6 @@ export default function App() {
|
|||||||
setIsRestoringSnapshot(false);
|
setIsRestoringSnapshot(false);
|
||||||
setRestoredRecordIds([]);
|
setRestoredRecordIds([]);
|
||||||
setRestoredRecordIdsText('');
|
setRestoredRecordIdsText('');
|
||||||
setLockedExpectedDeliveryDateTs(null);
|
|
||||||
setIsExpectedDeliveryDateLocked(false);
|
|
||||||
|
|
||||||
// 重置初始快照捕获状态
|
// 重置初始快照捕获状态
|
||||||
try {
|
try {
|
||||||
@ -475,8 +471,6 @@ export default function App() {
|
|||||||
// 切换功能时重置全局变量,但保留新的mode
|
// 切换功能时重置全局变量,但保留新的mode
|
||||||
resetGlobalState({ resetMode: false });
|
resetGlobalState({ resetMode: false });
|
||||||
setMode(m);
|
setMode(m);
|
||||||
setIsExpectedDeliveryDateLocked(false);
|
|
||||||
setLockedExpectedDeliveryDateTs(null);
|
|
||||||
setModeSelectionVisible(false);
|
setModeSelectionVisible(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1068,26 +1062,6 @@ export default function App() {
|
|||||||
: deriveTimelineAdjustmentsFromResults(snapshot?.timelineResults);
|
: deriveTimelineAdjustmentsFromResults(snapshot?.timelineResults);
|
||||||
setTimelineAdjustments(normalized);
|
setTimelineAdjustments(normalized);
|
||||||
}
|
}
|
||||||
{
|
|
||||||
const snapLockedFlag = snapshot?.isExpectedDeliveryDateLocked;
|
|
||||||
const snapLockedTs = snapshot?.lockedExpectedDeliveryDateTs;
|
|
||||||
const shouldLock = snapLockedFlag === true || (snapLockedFlag === undefined && snapLockedTs !== undefined && snapLockedTs !== null);
|
|
||||||
if (shouldLock) {
|
|
||||||
const ts = (typeof snapLockedTs === 'number' && Number.isFinite(snapLockedTs))
|
|
||||||
? snapLockedTs
|
|
||||||
: expectedDeliveryTsFromField;
|
|
||||||
if (ts !== null && ts !== undefined) {
|
|
||||||
setLockedExpectedDeliveryDateTs(ts);
|
|
||||||
setIsExpectedDeliveryDateLocked(true);
|
|
||||||
} else {
|
|
||||||
setLockedExpectedDeliveryDateTs(null);
|
|
||||||
setIsExpectedDeliveryDateLocked(false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setLockedExpectedDeliveryDateTs(null);
|
|
||||||
setIsExpectedDeliveryDateLocked(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
restoreExcludedDatesOverrideFromSnapshot(snapshot, snapshot.timelineResults);
|
restoreExcludedDatesOverrideFromSnapshot(snapshot, snapshot.timelineResults);
|
||||||
restoreExcludedDatesByNodeOverrideFromSnapshot(snapshot, snapshot.timelineResults);
|
restoreExcludedDatesByNodeOverrideFromSnapshot(snapshot, snapshot.timelineResults);
|
||||||
if (snapshot.expectedDateTimestamp) {
|
if (snapshot.expectedDateTimestamp) {
|
||||||
@ -1238,18 +1212,6 @@ export default function App() {
|
|||||||
: deriveTimelineAdjustmentsFromResults(snapshot?.timelineResults);
|
: deriveTimelineAdjustmentsFromResults(snapshot?.timelineResults);
|
||||||
setTimelineAdjustments(normalized);
|
setTimelineAdjustments(normalized);
|
||||||
}
|
}
|
||||||
{
|
|
||||||
const snapLockedFlag = snapshot?.isExpectedDeliveryDateLocked;
|
|
||||||
const snapLockedTs = snapshot?.lockedExpectedDeliveryDateTs;
|
|
||||||
const shouldLock = snapLockedFlag === true || (snapLockedFlag === undefined && snapLockedTs !== undefined && snapLockedTs !== null);
|
|
||||||
if (shouldLock && typeof snapLockedTs === 'number' && Number.isFinite(snapLockedTs)) {
|
|
||||||
setLockedExpectedDeliveryDateTs(snapLockedTs);
|
|
||||||
setIsExpectedDeliveryDateLocked(true);
|
|
||||||
} else {
|
|
||||||
setLockedExpectedDeliveryDateTs(null);
|
|
||||||
setIsExpectedDeliveryDateLocked(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (snapshot.expectedDateTimestamp) {
|
if (snapshot.expectedDateTimestamp) {
|
||||||
setExpectedDate(new Date(snapshot.expectedDateTimestamp));
|
setExpectedDate(new Date(snapshot.expectedDateTimestamp));
|
||||||
} else if (snapshot.expectedDateString) {
|
} else if (snapshot.expectedDateString) {
|
||||||
@ -1591,8 +1553,6 @@ export default function App() {
|
|||||||
text2: nodeSnapshot.text2,
|
text2: nodeSnapshot.text2,
|
||||||
mode: nodeSnapshot.mode,
|
mode: nodeSnapshot.mode,
|
||||||
timelineDirection: nodeSnapshot.timelineDirection,
|
timelineDirection: nodeSnapshot.timelineDirection,
|
||||||
lockedExpectedDeliveryDateTs: nodeSnapshot.lockedExpectedDeliveryDateTs,
|
|
||||||
isExpectedDeliveryDateLocked: nodeSnapshot.isExpectedDeliveryDateLocked,
|
|
||||||
selectedLabels: nodeSnapshot.selectedLabels,
|
selectedLabels: nodeSnapshot.selectedLabels,
|
||||||
expectedDateTimestamp: nodeSnapshot.expectedDateTimestamp,
|
expectedDateTimestamp: nodeSnapshot.expectedDateTimestamp,
|
||||||
expectedDateString: nodeSnapshot.expectedDateString,
|
expectedDateString: nodeSnapshot.expectedDateString,
|
||||||
@ -1707,18 +1667,6 @@ export default function App() {
|
|||||||
setTimelineResults(nodeSnapshots);
|
setTimelineResults(nodeSnapshots);
|
||||||
setTimelineVisible(true);
|
setTimelineVisible(true);
|
||||||
|
|
||||||
{
|
|
||||||
const snapLockedFlag = (globalSnapshotData as any)?.isExpectedDeliveryDateLocked;
|
|
||||||
const snapLockedTs = (globalSnapshotData as any)?.lockedExpectedDeliveryDateTs;
|
|
||||||
const shouldLock = snapLockedFlag === true || (snapLockedFlag === undefined && snapLockedTs !== undefined && snapLockedTs !== null);
|
|
||||||
if (shouldLock && typeof snapLockedTs === 'number' && Number.isFinite(snapLockedTs)) {
|
|
||||||
setLockedExpectedDeliveryDateTs(snapLockedTs);
|
|
||||||
setIsExpectedDeliveryDateLocked(true);
|
|
||||||
} else {
|
|
||||||
setLockedExpectedDeliveryDateTs(null);
|
|
||||||
setIsExpectedDeliveryDateLocked(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 恢复智能缓冲期状态(如果存在)
|
// 恢复智能缓冲期状态(如果存在)
|
||||||
if (globalSnapshotData.bufferManagement) {
|
if (globalSnapshotData.bufferManagement) {
|
||||||
@ -4153,24 +4101,6 @@ export default function App() {
|
|||||||
return Number.isFinite(ts) ? ts : null;
|
return Number.isFinite(ts) ? ts : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleExpectedDeliveryDateLockChange = (checked: boolean) => {
|
|
||||||
const nextLocked = !!checked;
|
|
||||||
setIsExpectedDeliveryDateLocked(nextLocked);
|
|
||||||
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 = (
|
const computeDynamicBufferDaysUsingEndDelta = (
|
||||||
adjustments: Record<string, number>,
|
adjustments: Record<string, number>,
|
||||||
expectedDateOverride?: Date | null,
|
expectedDateOverride?: Date | null,
|
||||||
@ -4450,8 +4380,6 @@ export default function App() {
|
|||||||
timelineResults,
|
timelineResults,
|
||||||
timelineAdjustments,
|
timelineAdjustments,
|
||||||
baseBufferDays,
|
baseBufferDays,
|
||||||
lockedExpectedDeliveryDateTs,
|
|
||||||
isExpectedDeliveryDateLocked,
|
|
||||||
actualCompletionDates,
|
actualCompletionDates,
|
||||||
completionDateAdjustment,
|
completionDateAdjustment,
|
||||||
hasAppliedSuggestedBuffer,
|
hasAppliedSuggestedBuffer,
|
||||||
@ -4470,7 +4398,6 @@ export default function App() {
|
|||||||
setCompletionDateAdjustment(0); // 重置最后流程完成日期调整
|
setCompletionDateAdjustment(0); // 重置最后流程完成日期调整
|
||||||
setActualCompletionDates({}); // 重置实际完成日期
|
setActualCompletionDates({}); // 重置实际完成日期
|
||||||
setBaseBufferDays(0); // 重置固定缓冲期为默认值
|
setBaseBufferDays(0); // 重置固定缓冲期为默认值
|
||||||
setIsExpectedDeliveryDateLocked(false);
|
|
||||||
try { lastBufferDeficitRef.current = 0; } catch {}
|
try { lastBufferDeficitRef.current = 0; } catch {}
|
||||||
setHasAppliedSuggestedBuffer(false); // 重置建议缓冲期应用标志
|
setHasAppliedSuggestedBuffer(false); // 重置建议缓冲期应用标志
|
||||||
setLastSuggestedApplied(null); // 清空上次建议值
|
setLastSuggestedApplied(null); // 清空上次建议值
|
||||||
@ -4499,14 +4426,6 @@ export default function App() {
|
|||||||
const normalizedAdjustments = normalizeTimelineAdjustmentsFromSnapshot(s.timelineAdjustments || {}, s.timelineResults || []);
|
const normalizedAdjustments = normalizeTimelineAdjustmentsFromSnapshot(s.timelineAdjustments || {}, s.timelineResults || []);
|
||||||
setTimelineAdjustments(normalizedAdjustments);
|
setTimelineAdjustments(normalizedAdjustments);
|
||||||
setBaseBufferDays(s.baseBufferDays ?? 0);
|
setBaseBufferDays(s.baseBufferDays ?? 0);
|
||||||
const shouldLock = s.isExpectedDeliveryDateLocked === true || (s.isExpectedDeliveryDateLocked === undefined && s.lockedExpectedDeliveryDateTs !== null && s.lockedExpectedDeliveryDateTs !== undefined);
|
|
||||||
if (shouldLock && typeof s.lockedExpectedDeliveryDateTs === 'number' && Number.isFinite(s.lockedExpectedDeliveryDateTs)) {
|
|
||||||
setLockedExpectedDeliveryDateTs(s.lockedExpectedDeliveryDateTs);
|
|
||||||
setIsExpectedDeliveryDateLocked(true);
|
|
||||||
} else {
|
|
||||||
setLockedExpectedDeliveryDateTs(null);
|
|
||||||
setIsExpectedDeliveryDateLocked(false);
|
|
||||||
}
|
|
||||||
setActualCompletionDates(s.actualCompletionDates || {});
|
setActualCompletionDates(s.actualCompletionDates || {});
|
||||||
setCompletionDateAdjustment(s.completionDateAdjustment || 0);
|
setCompletionDateAdjustment(s.completionDateAdjustment || 0);
|
||||||
setHasAppliedSuggestedBuffer(!!s.hasAppliedSuggestedBuffer && s.hasAppliedSuggestedBuffer);
|
setHasAppliedSuggestedBuffer(!!s.hasAppliedSuggestedBuffer && s.hasAppliedSuggestedBuffer);
|
||||||
@ -4699,9 +4618,6 @@ export default function App() {
|
|||||||
|
|
||||||
// 获取预计交付日期(交期余量的日期版本:根据客户期望日期自动计算缓冲期)
|
// 获取预计交付日期(交期余量的日期版本:根据客户期望日期自动计算缓冲期)
|
||||||
let expectedDeliveryDate = computeExpectedDeliveryDateTsFromResults(timelineResults, timelineAdjustments, overrides?.expectedDate ?? expectedDate, completionDateAdjustment);
|
let expectedDeliveryDate = computeExpectedDeliveryDateTsFromResults(timelineResults, timelineAdjustments, overrides?.expectedDate ?? expectedDate, completionDateAdjustment);
|
||||||
if (isExpectedDeliveryDateLocked && lockedExpectedDeliveryDateTs !== null) {
|
|
||||||
expectedDeliveryDate = lockedExpectedDeliveryDateTs;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取客户期望日期:批量模式优先使用传入的expectedDate
|
// 获取客户期望日期:批量模式优先使用传入的expectedDate
|
||||||
let customerExpectedDate = null;
|
let customerExpectedDate = null;
|
||||||
@ -4787,8 +4703,6 @@ export default function App() {
|
|||||||
timelineDirection,
|
timelineDirection,
|
||||||
excludedDatesOverride,
|
excludedDatesOverride,
|
||||||
excludedDatesByNodeOverride: excludedDatesByNodeOverrideRef.current || excludedDatesByNodeOverride,
|
excludedDatesByNodeOverride: excludedDatesByNodeOverrideRef.current || excludedDatesByNodeOverride,
|
||||||
lockedExpectedDeliveryDateTs,
|
|
||||||
isExpectedDeliveryDateLocked,
|
|
||||||
selectedLabels: currentSelectedLabels,
|
selectedLabels: currentSelectedLabels,
|
||||||
expectedDateTimestamp,
|
expectedDateTimestamp,
|
||||||
expectedDateString,
|
expectedDateString,
|
||||||
@ -6396,8 +6310,6 @@ export default function App() {
|
|||||||
<Select value={mode} onChange={(v) => {
|
<Select value={mode} onChange={(v) => {
|
||||||
const next = v as any;
|
const next = v as any;
|
||||||
setMode(next);
|
setMode(next);
|
||||||
setIsExpectedDeliveryDateLocked(false);
|
|
||||||
setLockedExpectedDeliveryDateTs(null);
|
|
||||||
setExcludedDatesOverride([]);
|
setExcludedDatesOverride([]);
|
||||||
setExcludedDatesOverrideText('');
|
setExcludedDatesOverrideText('');
|
||||||
}}
|
}}
|
||||||
@ -7016,10 +6928,10 @@ export default function App() {
|
|||||||
footer={
|
footer={
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
<Space align="center">
|
<Space align="center">
|
||||||
<Text>{isExpectedDeliveryDateLocked ? '缓冲期(天)(不影响已锁交付):' : '缓冲期(天):'}</Text>
|
<Text>缓冲期(天):</Text>
|
||||||
{(() => {
|
{(() => {
|
||||||
const dynamicBufferDays = computeDynamicBufferDaysUsingEndDelta(timelineAdjustments, expectedDate, timelineResults, completionDateAdjustment);
|
const dynamicBufferDays = computeDynamicBufferDaysUsingEndDelta(timelineAdjustments, expectedDate, timelineResults, completionDateAdjustment);
|
||||||
const canEdit = !isExpectedDeliveryDateLocked && !!getAdjustedLastCompletionDate(timelineResults, completionDateAdjustment);
|
const canEdit = !!getAdjustedLastCompletionDate(timelineResults, completionDateAdjustment);
|
||||||
return (
|
return (
|
||||||
<InputNumber
|
<InputNumber
|
||||||
value={dynamicBufferDays}
|
value={dynamicBufferDays}
|
||||||
@ -7568,9 +7480,6 @@ export default function App() {
|
|||||||
adjustedCompletionDate.setDate(adjustedCompletionDate.getDate() + completionDateAdjustment);
|
adjustedCompletionDate.setDate(adjustedCompletionDate.getDate() + completionDateAdjustment);
|
||||||
const deliveryDate = new Date(adjustedCompletionDate);
|
const deliveryDate = new Date(adjustedCompletionDate);
|
||||||
deliveryDate.setDate(deliveryDate.getDate() + dynamicBufferDays);
|
deliveryDate.setDate(deliveryDate.getDate() + dynamicBufferDays);
|
||||||
const lockedDeliveryDate = (isExpectedDeliveryDateLocked && lockedExpectedDeliveryDateTs !== null)
|
|
||||||
? new Date(lockedExpectedDeliveryDateTs)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -7611,7 +7520,7 @@ export default function App() {
|
|||||||
</span>
|
</span>
|
||||||
<span style={{ fontSize: 16, color: '#1890ff', fontWeight: 700 }}>=</span>
|
<span style={{ fontSize: 16, color: '#1890ff', fontWeight: 700 }}>=</span>
|
||||||
<span style={{ fontSize: 13, color: '#666', fontWeight: 600 }}>
|
<span style={{ fontSize: 13, color: '#666', fontWeight: 600 }}>
|
||||||
{lockedDeliveryDate ? '结束日期(未锁)' : '结束日期'}
|
结束日期
|
||||||
</span>
|
</span>
|
||||||
<span style={{
|
<span style={{
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
@ -7626,24 +7535,6 @@ export default function App() {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{lockedDeliveryDate && (
|
|
||||||
<div style={{ marginTop: 8, display: 'flex', alignItems: 'center', justifyContent: 'flex-start', gap: 8, flexWrap: 'nowrap', whiteSpace: 'nowrap', overflowX: 'auto' }}>
|
|
||||||
<Text style={{ fontSize: 13, color: '#333', fontWeight: 600, whiteSpace: 'nowrap' }}>结束日期(已锁定)</Text>
|
|
||||||
<span style={{
|
|
||||||
fontSize: 13,
|
|
||||||
color: '#722ed1',
|
|
||||||
backgroundColor: 'rgba(114, 46, 209, 0.08)',
|
|
||||||
border: '1px solid rgba(114, 46, 209, 0.24)',
|
|
||||||
borderRadius: 6,
|
|
||||||
padding: '3px 8px',
|
|
||||||
fontWeight: 700,
|
|
||||||
whiteSpace: 'nowrap'
|
|
||||||
}}>
|
|
||||||
{formatDate(lockedDeliveryDate)}({getDayOfWeek(lockedDeliveryDate)})
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* 第二行:客户期望日期(可更改,优化展示为标签样式) */}
|
{/* 第二行:客户期望日期(可更改,优化展示为标签样式) */}
|
||||||
<div style={{ marginTop: 8, display: 'flex', alignItems: 'center', justifyContent: 'flex-start', gap: 8, flexWrap: 'nowrap', whiteSpace: 'nowrap', overflowX: 'auto' }}>
|
<div style={{ marginTop: 8, display: 'flex', alignItems: 'center', justifyContent: 'flex-start', gap: 8, flexWrap: 'nowrap', whiteSpace: 'nowrap', overflowX: 'auto' }}>
|
||||||
<Text style={{ fontSize: 13, color: '#333', fontWeight: 600, whiteSpace: 'nowrap' }}>客户期望日期(可更改)</Text>
|
<Text style={{ fontSize: 13, color: '#333', fontWeight: 600, whiteSpace: 'nowrap' }}>客户期望日期(可更改)</Text>
|
||||||
@ -7651,7 +7542,6 @@ export default function App() {
|
|||||||
style={{ width: '200px' }}
|
style={{ width: '200px' }}
|
||||||
placeholder="请选择客户期望日期"
|
placeholder="请选择客户期望日期"
|
||||||
value={expectedDate ?? undefined}
|
value={expectedDate ?? undefined}
|
||||||
disabled={isExpectedDeliveryDateLocked}
|
|
||||||
onChange={(date) => {
|
onChange={(date) => {
|
||||||
if (date instanceof Date) {
|
if (date instanceof Date) {
|
||||||
setExpectedDate(date);
|
setExpectedDate(date);
|
||||||
|
|||||||
Reference in New Issue
Block a user