feat: 动画调整
This commit is contained in:
@@ -54,6 +54,7 @@ let dynamicNewsCardRenderCount = 0;
|
||||
* @param {Function} onSearchFocus - 搜索框获得焦点回调
|
||||
* @param {Function} onEventClick - 事件点击回调
|
||||
* @param {Function} onViewDetail - 查看详情回调
|
||||
* @param {Object} trackingFunctions - PostHog 追踪函数集合
|
||||
* @param {Object} ref - 用于滚动的ref
|
||||
*/
|
||||
const DynamicNewsCard = forwardRef(({
|
||||
@@ -64,6 +65,7 @@ const DynamicNewsCard = forwardRef(({
|
||||
onSearchFocus,
|
||||
onEventClick,
|
||||
onViewDetail,
|
||||
trackingFunctions = {},
|
||||
...rest
|
||||
}, ref) => {
|
||||
const dispatch = useDispatch();
|
||||
@@ -205,9 +207,22 @@ const [currentMode, setCurrentMode] = useState('vertical');
|
||||
// 四排模式的事件点击处理(打开弹窗)
|
||||
const handleFourRowEventClick = useCallback((event) => {
|
||||
console.log('%c🔲 [四排模式] 点击事件,打开详情弹窗', 'color: #8B5CF6; font-weight: bold;', { eventId: event.id, title: event.title });
|
||||
|
||||
// 🎯 追踪事件详情打开
|
||||
if (trackingFunctions.trackNewsDetailOpened) {
|
||||
trackingFunctions.trackNewsDetailOpened({
|
||||
eventId: event.id,
|
||||
eventTitle: event.title,
|
||||
importance: event.importance,
|
||||
source: 'four_row_mode',
|
||||
displayMode: 'modal',
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
|
||||
setModalEvent(event);
|
||||
onModalOpen();
|
||||
}, [onModalOpen]);
|
||||
}, [onModalOpen, trackingFunctions]);
|
||||
|
||||
// 初始加载 - 只在组件首次挂载且对应模式数据为空时执行
|
||||
useEffect(() => {
|
||||
@@ -302,6 +317,18 @@ const [currentMode, setCurrentMode] = useState('vertical');
|
||||
console.log('%c🎯 [首次加载] 自动选中第一个事件', 'color: #10B981; font-weight: bold;');
|
||||
hasAutoSelectedFirstEvent.current = true;
|
||||
setSelectedEvent(currentPageEvents[0]);
|
||||
|
||||
// 🎯 追踪事件点击(首次自动选中)
|
||||
if (trackingFunctions.trackNewsArticleClicked) {
|
||||
trackingFunctions.trackNewsArticleClicked({
|
||||
eventId: currentPageEvents[0].id,
|
||||
eventTitle: currentPageEvents[0].title,
|
||||
importance: currentPageEvents[0].importance,
|
||||
source: 'auto_select_first',
|
||||
displayMode: mode,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -310,7 +337,7 @@ const [currentMode, setCurrentMode] = useState('vertical');
|
||||
e => e.id === selectedEvent?.id
|
||||
);
|
||||
}
|
||||
}, [currentPageEvents, selectedEvent?.id, mode]);
|
||||
}, [currentPageEvents, selectedEvent?.id, mode, trackingFunctions]);
|
||||
|
||||
// 组件卸载时清理选中状态
|
||||
useEffect(() => {
|
||||
@@ -364,7 +391,9 @@ const [currentMode, setCurrentMode] = useState('vertical');
|
||||
if (!cardHeaderElement || !cardBodyElement) return;
|
||||
|
||||
let ticking = false;
|
||||
const TRIGGER_OFFSET = 100; // 提前 100px 触发
|
||||
const TRIGGER_OFFSET = 150; // 提前 150px 触发(进入固定模式)
|
||||
const EXIT_OFFSET = 200; // 提前 200px 退出(退出比进入更容易)
|
||||
const EXIT_THRESHOLD = 30; // 接近顶部 30px 内即可退出
|
||||
|
||||
// 外部滚动监听:触发固定模式
|
||||
const handleExternalScroll = () => {
|
||||
@@ -375,7 +404,7 @@ const [currentMode, setCurrentMode] = useState('vertical');
|
||||
const rect = cardHeaderElement.getBoundingClientRect();
|
||||
const elementTop = rect.top;
|
||||
|
||||
// 计算触发点:总导航高度 + 100px 偏移量
|
||||
// 计算触发点:总导航高度 + 150px 偏移量
|
||||
const triggerPoint = TOTAL_NAV_HEIGHT + TRIGGER_OFFSET;
|
||||
|
||||
// 向上滑动:元素顶部到达触发点 → 激活固定模式
|
||||
@@ -402,25 +431,31 @@ const [currentMode, setCurrentMode] = useState('vertical');
|
||||
|
||||
// 检测向上滚动(deltaY < 0)
|
||||
if (e.deltaY < 0) {
|
||||
// 查找所有滚动容器
|
||||
const scrollContainers = cardBodyElement.querySelectorAll('[data-scroll-container]');
|
||||
window.requestAnimationFrame(() => {
|
||||
// 🎯 检查 1:CardHeader 位置(主要条件)
|
||||
const rect = cardHeaderElement.getBoundingClientRect();
|
||||
const elementTop = rect.top;
|
||||
const exitPoint = TOTAL_NAV_HEIGHT + EXIT_OFFSET;
|
||||
|
||||
if (scrollContainers.length === 0) {
|
||||
// 如果没有找到标记的容器,查找所有可滚动元素
|
||||
const allScrollable = cardBodyElement.querySelectorAll('[style*="overflow"]');
|
||||
scrollContainers = allScrollable;
|
||||
}
|
||||
|
||||
// 检查是否所有滚动容器都在顶部
|
||||
const allAtTop = scrollContainers.length === 0 ||
|
||||
Array.from(scrollContainers).every(
|
||||
container => container.scrollTop === 0
|
||||
// 🎯 检查 2:左侧事件列表滚动位置(辅助条件)
|
||||
const eventListContainers = cardBodyElement.querySelectorAll('[data-event-list-container]');
|
||||
const allNearTop = eventListContainers.length === 0 ||
|
||||
Array.from(eventListContainers).every(
|
||||
container => container.scrollTop <= EXIT_THRESHOLD
|
||||
);
|
||||
|
||||
if (allAtTop) {
|
||||
// 🎯 退出条件:CardHeader 超过退出点 OR 左侧列表接近顶部
|
||||
if (elementTop > exitPoint || allNearTop) {
|
||||
setIsFixedMode(false);
|
||||
console.log('🔓 恢复正常文档流模式(内部滚动到顶部)');
|
||||
console.log('🔓 恢复正常文档流模式', {
|
||||
elementTop,
|
||||
exitPoint,
|
||||
listNearTop: allNearTop,
|
||||
exitThreshold: EXIT_THRESHOLD,
|
||||
reason: elementTop > exitPoint ? 'CardHeader位置' : '左侧列表滚动'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -490,6 +525,7 @@ const [currentMode, setCurrentMode] = useState('vertical');
|
||||
filters={filters}
|
||||
mode={mode}
|
||||
pageSize={pageSize}
|
||||
trackingFunctions={trackingFunctions}
|
||||
/>
|
||||
</Box>
|
||||
</CardHeader>
|
||||
|
||||
Reference in New Issue
Block a user