update ui
This commit is contained in:
@@ -80,18 +80,10 @@ const DynamicNewsCard = forwardRef(({
|
||||
// 通知权限相关
|
||||
const { browserPermission, requestBrowserPermission } = useNotification();
|
||||
|
||||
// 固定模式状态
|
||||
const [isFixedMode, setIsFixedMode] = useState(false);
|
||||
const [headerHeight, setHeaderHeight] = useState(0);
|
||||
// Refs
|
||||
const cardHeaderRef = useRef(null);
|
||||
const cardBodyRef = useRef(null);
|
||||
|
||||
// 导航栏和页脚固定高度
|
||||
const NAVBAR_HEIGHT = 64; // 主导航高度
|
||||
const SECONDARY_NAV_HEIGHT = 44; // 二级导航高度
|
||||
const FOOTER_HEIGHT = 80; // 页脚高度(优化后)
|
||||
const TOTAL_NAV_HEIGHT = NAVBAR_HEIGHT + SECONDARY_NAV_HEIGHT; // 总导航高度 128px
|
||||
|
||||
// 从 Redux 读取关注状态
|
||||
const eventFollowStatus = useSelector(selectEventFollowStatus);
|
||||
|
||||
@@ -387,118 +379,7 @@ const [currentMode, setCurrentMode] = useState('vertical');
|
||||
}, [handlePageChange]);
|
||||
|
||||
// 测量 CardHeader 高度
|
||||
useEffect(() => {
|
||||
const cardHeaderElement = cardHeaderRef.current;
|
||||
if (!cardHeaderElement) return;
|
||||
|
||||
// 测量并更新高度
|
||||
const updateHeaderHeight = () => {
|
||||
const height = cardHeaderElement.offsetHeight;
|
||||
setHeaderHeight(height);
|
||||
};
|
||||
|
||||
// 初始测量
|
||||
updateHeaderHeight();
|
||||
|
||||
// 监听窗口大小变化(响应式调整)
|
||||
window.addEventListener('resize', updateHeaderHeight);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', updateHeaderHeight);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// 监听 CardHeader 是否到达触发点,动态切换固定模式
|
||||
useEffect(() => {
|
||||
const cardHeaderElement = cardHeaderRef.current;
|
||||
const cardBodyElement = cardBodyRef.current;
|
||||
if (!cardHeaderElement || !cardBodyElement) return;
|
||||
|
||||
let ticking = false;
|
||||
const TRIGGER_OFFSET = 150; // 提前 150px 触发(进入固定模式)
|
||||
const EXIT_OFFSET = 200; // 提前 200px 退出(退出比进入更容易)
|
||||
const EXIT_THRESHOLD = 30; // 接近顶部 30px 内即可退出
|
||||
|
||||
// 外部滚动监听:触发固定模式
|
||||
const handleExternalScroll = () => {
|
||||
// 只在非固定模式下监听外部滚动
|
||||
if (!isFixedMode && !ticking) {
|
||||
window.requestAnimationFrame(() => {
|
||||
// 获取 CardHeader 相对视口的位置
|
||||
const rect = cardHeaderElement.getBoundingClientRect();
|
||||
const elementTop = rect.top;
|
||||
|
||||
// 计算触发点:总导航高度 + 150px 偏移量
|
||||
const triggerPoint = TOTAL_NAV_HEIGHT + TRIGGER_OFFSET;
|
||||
|
||||
// 向上滑动:元素顶部到达触发点 → 激活固定模式
|
||||
if (elementTop <= triggerPoint) {
|
||||
setIsFixedMode(true);
|
||||
console.log('🔒 切换为固定全屏模式', {
|
||||
elementTop,
|
||||
triggerPoint,
|
||||
offset: TRIGGER_OFFSET
|
||||
});
|
||||
}
|
||||
|
||||
ticking = false;
|
||||
});
|
||||
|
||||
ticking = true;
|
||||
}
|
||||
};
|
||||
|
||||
// 内部滚动监听:退出固定模式
|
||||
const handleWheel = (e) => {
|
||||
// 只在固定模式下监听内部滚动
|
||||
if (!isFixedMode) return;
|
||||
|
||||
// 检测向上滚动(deltaY < 0)
|
||||
if (e.deltaY < 0) {
|
||||
window.requestAnimationFrame(() => {
|
||||
// 🎯 检查 1:CardHeader 位置(主要条件)
|
||||
const rect = cardHeaderElement.getBoundingClientRect();
|
||||
const elementTop = rect.top;
|
||||
const exitPoint = TOTAL_NAV_HEIGHT + EXIT_OFFSET;
|
||||
|
||||
// 🎯 检查 2:左侧事件列表滚动位置(辅助条件)
|
||||
const eventListContainers = cardBodyElement.querySelectorAll('[data-event-list-container]');
|
||||
const allNearTop = eventListContainers.length === 0 ||
|
||||
Array.from(eventListContainers).every(
|
||||
container => container.scrollTop <= EXIT_THRESHOLD
|
||||
);
|
||||
|
||||
// 🎯 退出条件:CardHeader 超过退出点 OR 左侧列表接近顶部
|
||||
if (elementTop > exitPoint || allNearTop) {
|
||||
setIsFixedMode(false);
|
||||
console.log('🔓 恢复正常文档流模式', {
|
||||
elementTop,
|
||||
exitPoint,
|
||||
listNearTop: allNearTop,
|
||||
exitThreshold: EXIT_THRESHOLD,
|
||||
reason: elementTop > exitPoint ? 'CardHeader位置' : '左侧列表滚动'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 监听外部滚动
|
||||
window.addEventListener('scroll', handleExternalScroll, { passive: true });
|
||||
|
||||
// 监听内部滚轮事件(固定模式下)
|
||||
if (isFixedMode) {
|
||||
cardBodyElement.addEventListener('wheel', handleWheel, { passive: true });
|
||||
}
|
||||
|
||||
// 初次检查位置
|
||||
handleExternalScroll();
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('scroll', handleExternalScroll);
|
||||
cardBodyElement.removeEventListener('wheel', handleWheel);
|
||||
};
|
||||
}, [isFixedMode]);
|
||||
// 固定模式逻辑已移除,改用 sticky 定位
|
||||
|
||||
return (
|
||||
<Card
|
||||
@@ -507,19 +388,14 @@ const [currentMode, setCurrentMode] = useState('vertical');
|
||||
bg={cardBg}
|
||||
borderColor={borderColor}
|
||||
mb={4}
|
||||
position="relative"
|
||||
zIndex={1}
|
||||
>
|
||||
{/* 标题部分 */}
|
||||
{/* 标题和搜索部分 - 可滚动区域 */}
|
||||
<CardHeader
|
||||
ref={cardHeaderRef}
|
||||
position={isFixedMode ? 'fixed' : 'relative'}
|
||||
top={isFixedMode ? `${TOTAL_NAV_HEIGHT}px` : 'auto'}
|
||||
left={isFixedMode ? 0 : 'auto'}
|
||||
right={isFixedMode ? 0 : 'auto'}
|
||||
maxW={isFixedMode ? '1600px' : '100%'}
|
||||
mx={isFixedMode ? 'auto' : 0}
|
||||
px={isFixedMode ? { base: 3, md: 4 } : undefined}
|
||||
zIndex={isFixedMode ? 999 : 1}
|
||||
bg={cardBg}
|
||||
position="relative"
|
||||
zIndex={1}
|
||||
>
|
||||
<Flex justify="space-between" align="center">
|
||||
<VStack align="start" spacing={1}>
|
||||
@@ -613,36 +489,41 @@ const [currentMode, setCurrentMode] = useState('vertical');
|
||||
{/* 主体内容 */}
|
||||
<CardBody
|
||||
ref={cardBodyRef}
|
||||
position={isFixedMode ? 'fixed' : 'relative'}
|
||||
top={isFixedMode ? `${TOTAL_NAV_HEIGHT + headerHeight}px` : 'auto'}
|
||||
left={isFixedMode ? 0 : 'auto'}
|
||||
right={isFixedMode ? 0 : 'auto'}
|
||||
bottom={isFixedMode ? `${FOOTER_HEIGHT}px` : 'auto'}
|
||||
maxW={isFixedMode ? '1600px' : '100%'}
|
||||
mx={isFixedMode ? 'auto' : 0}
|
||||
h={isFixedMode ? `calc(100vh - ${TOTAL_NAV_HEIGHT + headerHeight + FOOTER_HEIGHT}px)` : 'auto'}
|
||||
px={isFixedMode ? { base: 3, md: 4 } : undefined}
|
||||
position="relative"
|
||||
pt={4}
|
||||
display="flex"
|
||||
flexDirection="column"
|
||||
overflow="hidden"
|
||||
zIndex={isFixedMode ? 1000 : 1}
|
||||
bg={cardBg}
|
||||
overflow="visible"
|
||||
zIndex={1}
|
||||
>
|
||||
{/* 顶部控制栏:模式切换按钮 + 筛选按钮 + 分页控制器(固定不滚动) */}
|
||||
<Flex justify="space-between" align="center" mb={2} flexShrink={0}>
|
||||
{/* 左侧:模式切换按钮 + 筛选按钮 */}
|
||||
<ModeToggleButtons mode={mode} onModeChange={handleModeToggle} />
|
||||
{/* 顶部控制栏:模式切换按钮 + 分页控制器(滚动时固定在顶部) */}
|
||||
<Box
|
||||
position="sticky"
|
||||
top="0"
|
||||
zIndex={10}
|
||||
bg={cardBg}
|
||||
py={2}
|
||||
mb={2}
|
||||
borderBottom="1px solid"
|
||||
borderColor={borderColor}
|
||||
mx={-6}
|
||||
px={6}
|
||||
boxShadow="sm"
|
||||
>
|
||||
<Flex justify="space-between" align="center">
|
||||
{/* 左侧:模式切换按钮 */}
|
||||
<ModeToggleButtons mode={mode} onModeChange={handleModeToggle} />
|
||||
|
||||
{/* 右侧:分页控制器(仅在纵向模式显示) */}
|
||||
{mode === 'vertical' && totalPages > 1 && (
|
||||
<PaginationControl
|
||||
currentPage={currentPage}
|
||||
totalPages={totalPages}
|
||||
onPageChange={handlePageChangeWithScroll}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
{/* 右侧:分页控制器(仅在纵向模式显示) */}
|
||||
{mode === 'vertical' && totalPages > 1 && (
|
||||
<PaginationControl
|
||||
currentPage={currentPage}
|
||||
totalPages={totalPages}
|
||||
onPageChange={handlePageChangeWithScroll}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
</Box>
|
||||
|
||||
{/* 内容区域 - 撑满剩余高度 */}
|
||||
<Box flex="1" minH={0} position="relative">
|
||||
|
||||
Reference in New Issue
Block a user