事件中心不提示通知修复,增加开启/关闭通知按钮。修复edge或者opera浏览器登录扫码无跳转的问题
This commit is contained in:
@@ -508,19 +508,19 @@ export default function WechatRegister() {
|
|||||||
title="微信扫码登录"
|
title="微信扫码登录"
|
||||||
width="300"
|
width="300"
|
||||||
height="350"
|
height="350"
|
||||||
scrolling="no" // ✅ 新增:禁止滚动
|
scrolling="no"
|
||||||
// sandbox="allow-scripts allow-same-origin allow-forms" // ✅ 阻止iframe跳转父页面
|
sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-top-navigation"
|
||||||
|
allow="clipboard-write"
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
transform: 'scale(0.77) translateY(-35px)', // ✅ 裁剪顶部logo
|
transform: 'scale(0.77) translateY(-35px)',
|
||||||
transformOrigin: 'top left',
|
transformOrigin: 'top left',
|
||||||
marginLeft: '-5px',
|
marginLeft: '-5px',
|
||||||
pointerEvents: 'auto', // 允许点击 │ │
|
pointerEvents: 'auto',
|
||||||
overflow: 'hidden', // 尝试隐藏滚动条(可能不起作用)
|
overflow: 'hidden',
|
||||||
}}
|
}}
|
||||||
// 使用 onWheel 事件阻止滚动 │ │
|
onWheel={(e) => e.preventDefault()}
|
||||||
onWheel={(e) => e.preventDefault()} // ✅ 在父容器上阻止滚动
|
onTouchMove={(e) => e.preventDefault()}
|
||||||
onTouchMove={(e) => e.preventDefault()} // ✅ 移动端也阻止
|
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
/* 未获取:显示占位符 */
|
/* 未获取:显示占位符 */
|
||||||
|
|||||||
@@ -25,8 +25,12 @@ import {
|
|||||||
useColorModeValue,
|
useColorModeValue,
|
||||||
useToast,
|
useToast,
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
|
Switch,
|
||||||
|
Tooltip,
|
||||||
|
Icon,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { TimeIcon } from '@chakra-ui/icons';
|
import { TimeIcon, BellIcon } from '@chakra-ui/icons';
|
||||||
|
import { useNotification } from '../../../contexts/NotificationContext';
|
||||||
import EventScrollList from './DynamicNewsCard/EventScrollList';
|
import EventScrollList from './DynamicNewsCard/EventScrollList';
|
||||||
import ModeToggleButtons from './DynamicNewsCard/ModeToggleButtons';
|
import ModeToggleButtons from './DynamicNewsCard/ModeToggleButtons';
|
||||||
import PaginationControl from './DynamicNewsCard/PaginationControl';
|
import PaginationControl from './DynamicNewsCard/PaginationControl';
|
||||||
@@ -73,6 +77,9 @@ const DynamicNewsCard = forwardRef(({
|
|||||||
const cardBg = useColorModeValue('white', 'gray.800');
|
const cardBg = useColorModeValue('white', 'gray.800');
|
||||||
const borderColor = useColorModeValue('gray.200', 'gray.700');
|
const borderColor = useColorModeValue('gray.200', 'gray.700');
|
||||||
|
|
||||||
|
// 通知权限相关
|
||||||
|
const { browserPermission, requestBrowserPermission } = useNotification();
|
||||||
|
|
||||||
// 固定模式状态
|
// 固定模式状态
|
||||||
const [isFixedMode, setIsFixedMode] = useState(false);
|
const [isFixedMode, setIsFixedMode] = useState(false);
|
||||||
const [headerHeight, setHeaderHeight] = useState(0);
|
const [headerHeight, setHeaderHeight] = useState(0);
|
||||||
@@ -146,6 +153,23 @@ const [currentMode, setCurrentMode] = useState('vertical');
|
|||||||
dispatch(toggleEventFollow(eventId));
|
dispatch(toggleEventFollow(eventId));
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
|
||||||
|
// 通知开关处理
|
||||||
|
const handleNotificationToggle = useCallback(async () => {
|
||||||
|
if (browserPermission === 'granted') {
|
||||||
|
// 已授权,提示用户去浏览器设置中关闭
|
||||||
|
toast({
|
||||||
|
title: '已开启通知',
|
||||||
|
description: '要关闭通知,请在浏览器地址栏左侧点击锁图标,找到"通知"选项进行设置',
|
||||||
|
status: 'info',
|
||||||
|
duration: 5000,
|
||||||
|
isClosable: true,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 未授权,请求权限
|
||||||
|
await requestBrowserPermission();
|
||||||
|
}
|
||||||
|
}, [browserPermission, requestBrowserPermission, toast]);
|
||||||
|
|
||||||
// 本地状态
|
// 本地状态
|
||||||
const [selectedEvent, setSelectedEvent] = useState(null);
|
const [selectedEvent, setSelectedEvent] = useState(null);
|
||||||
|
|
||||||
@@ -511,9 +535,66 @@ const [currentMode, setCurrentMode] = useState('vertical');
|
|||||||
<Badge colorScheme="blue">快讯</Badge>
|
<Badge colorScheme="blue">快讯</Badge>
|
||||||
</HStack>
|
</HStack>
|
||||||
</VStack>
|
</VStack>
|
||||||
|
|
||||||
|
<VStack align="end" spacing={2}>
|
||||||
|
{/* 通知开关 */}
|
||||||
|
<Tooltip
|
||||||
|
label={browserPermission === 'granted'
|
||||||
|
? '浏览器通知已开启,新事件将实时推送'
|
||||||
|
: '开启后可接收实时事件推送通知'}
|
||||||
|
placement="left"
|
||||||
|
hasArrow
|
||||||
|
>
|
||||||
|
<HStack
|
||||||
|
spacing={2}
|
||||||
|
px={3}
|
||||||
|
py={2}
|
||||||
|
borderRadius="md"
|
||||||
|
bg={browserPermission === 'granted'
|
||||||
|
? useColorModeValue('green.50', 'green.900')
|
||||||
|
: useColorModeValue('gray.50', 'gray.700')}
|
||||||
|
borderWidth="1px"
|
||||||
|
borderColor={browserPermission === 'granted'
|
||||||
|
? useColorModeValue('green.200', 'green.700')
|
||||||
|
: useColorModeValue('gray.200', 'gray.600')}
|
||||||
|
cursor="pointer"
|
||||||
|
_hover={{
|
||||||
|
borderColor: browserPermission === 'granted'
|
||||||
|
? useColorModeValue('green.300', 'green.600')
|
||||||
|
: useColorModeValue('blue.300', 'blue.600'),
|
||||||
|
}}
|
||||||
|
transition="all 0.2s"
|
||||||
|
onClick={handleNotificationToggle}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
as={BellIcon}
|
||||||
|
boxSize={4}
|
||||||
|
color={browserPermission === 'granted'
|
||||||
|
? useColorModeValue('green.600', 'green.300')
|
||||||
|
: useColorModeValue('gray.500', 'gray.400')}
|
||||||
|
/>
|
||||||
|
<Text
|
||||||
|
fontSize="sm"
|
||||||
|
fontWeight="medium"
|
||||||
|
color={browserPermission === 'granted'
|
||||||
|
? useColorModeValue('green.700', 'green.200')
|
||||||
|
: useColorModeValue('gray.600', 'gray.300')}
|
||||||
|
>
|
||||||
|
{browserPermission === 'granted' ? '通知已开启' : '开启通知'}
|
||||||
|
</Text>
|
||||||
|
<Switch
|
||||||
|
size="sm"
|
||||||
|
isChecked={browserPermission === 'granted'}
|
||||||
|
pointerEvents="none"
|
||||||
|
colorScheme="green"
|
||||||
|
/>
|
||||||
|
</HStack>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
<Text fontSize="xs" color="gray.500">
|
<Text fontSize="xs" color="gray.500">
|
||||||
最后更新: {lastUpdateTime?.toLocaleTimeString() || '未知'}
|
最后更新: {lastUpdateTime?.toLocaleTimeString() || '未知'}
|
||||||
</Text>
|
</Text>
|
||||||
|
</VStack>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
{/* 搜索和筛选组件 */}
|
{/* 搜索和筛选组件 */}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// src/views/Community/index.js
|
// src/views/Community/index.js
|
||||||
import React, { useEffect, useRef } from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
@@ -10,6 +10,15 @@ import {
|
|||||||
Box,
|
Box,
|
||||||
Container,
|
Container,
|
||||||
useColorModeValue,
|
useColorModeValue,
|
||||||
|
Alert,
|
||||||
|
AlertIcon,
|
||||||
|
AlertTitle,
|
||||||
|
AlertDescription,
|
||||||
|
Button,
|
||||||
|
CloseButton,
|
||||||
|
HStack,
|
||||||
|
VStack,
|
||||||
|
Text,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
|
|
||||||
// 导入组件
|
// 导入组件
|
||||||
@@ -40,7 +49,10 @@ const Community = () => {
|
|||||||
const containerRef = useRef(null);
|
const containerRef = useRef(null);
|
||||||
|
|
||||||
// ⚡ 通知权限引导
|
// ⚡ 通知权限引导
|
||||||
const { showCommunityGuide } = useNotification();
|
const { browserPermission, requestBrowserPermission } = useNotification();
|
||||||
|
|
||||||
|
// 通知横幅显示状态
|
||||||
|
const [showNotificationBanner, setShowNotificationBanner] = useState(false);
|
||||||
|
|
||||||
// 🎯 初始化Community埋点Hook
|
// 🎯 初始化Community埋点Hook
|
||||||
const communityEvents = useCommunityEvents({ navigate });
|
const communityEvents = useCommunityEvents({ navigate });
|
||||||
@@ -71,17 +83,38 @@ const Community = () => {
|
|||||||
}
|
}
|
||||||
}, [events, loading, pagination, filters]);
|
}, [events, loading, pagination, filters]);
|
||||||
|
|
||||||
// ⚡ 首次访问社区时,延迟显示权限引导
|
// ⚡ 检查通知权限状态,显示横幅提示
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (showCommunityGuide) {
|
// 延迟3秒显示,让用户先浏览页面
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
logger.info('Community', '显示社区权限引导');
|
// 如果未授权或未请求过权限,显示横幅
|
||||||
showCommunityGuide();
|
if (browserPermission !== 'granted') {
|
||||||
}, 5000); // 延迟 5 秒,让用户先浏览页面
|
const hasClosedBanner = localStorage.getItem('notification_banner_closed');
|
||||||
|
if (!hasClosedBanner) {
|
||||||
|
setShowNotificationBanner(true);
|
||||||
|
logger.info('Community', '显示通知权限横幅');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
|
}, [browserPermission]);
|
||||||
|
|
||||||
|
// 处理开启通知
|
||||||
|
const handleEnableNotifications = async () => {
|
||||||
|
const permission = await requestBrowserPermission();
|
||||||
|
if (permission === 'granted') {
|
||||||
|
setShowNotificationBanner(false);
|
||||||
|
logger.info('Community', '通知权限已授予');
|
||||||
}
|
}
|
||||||
}, [showCommunityGuide]); // 只在组件挂载时执行一次
|
};
|
||||||
|
|
||||||
|
// 处理关闭横幅
|
||||||
|
const handleCloseBanner = () => {
|
||||||
|
setShowNotificationBanner(false);
|
||||||
|
localStorage.setItem('notification_banner_closed', 'true');
|
||||||
|
logger.info('Community', '通知横幅已关闭');
|
||||||
|
};
|
||||||
|
|
||||||
// ⚡ 首次进入页面时滚动到内容区域(考虑导航栏高度)
|
// ⚡ 首次进入页面时滚动到内容区域(考虑导航栏高度)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -104,6 +137,42 @@ const Community = () => {
|
|||||||
<Box minH="100vh" bg={bgColor}>
|
<Box minH="100vh" bg={bgColor}>
|
||||||
{/* 主内容区域 */}
|
{/* 主内容区域 */}
|
||||||
<Container ref={containerRef} maxW="1600px" pt={6} pb={8}>
|
<Container ref={containerRef} maxW="1600px" pt={6} pb={8}>
|
||||||
|
{/* 通知权限提示横幅 */}
|
||||||
|
{showNotificationBanner && (
|
||||||
|
<Alert
|
||||||
|
status="info"
|
||||||
|
variant="subtle"
|
||||||
|
borderRadius="lg"
|
||||||
|
mb={4}
|
||||||
|
boxShadow="md"
|
||||||
|
bg={useColorModeValue('blue.50', 'blue.900')}
|
||||||
|
borderWidth="1px"
|
||||||
|
borderColor={useColorModeValue('blue.200', 'blue.700')}
|
||||||
|
>
|
||||||
|
<AlertIcon />
|
||||||
|
<Box flex="1">
|
||||||
|
<AlertTitle fontSize="md" mb={1}>
|
||||||
|
开启桌面通知,不错过重要事件
|
||||||
|
</AlertTitle>
|
||||||
|
<AlertDescription fontSize="sm">
|
||||||
|
即使浏览器最小化,也能第一时间接收新事件推送通知
|
||||||
|
</AlertDescription>
|
||||||
|
</Box>
|
||||||
|
<HStack spacing={2} ml={4}>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
colorScheme="blue"
|
||||||
|
onClick={handleEnableNotifications}
|
||||||
|
>
|
||||||
|
立即开启
|
||||||
|
</Button>
|
||||||
|
<CloseButton
|
||||||
|
onClick={handleCloseBanner}
|
||||||
|
position="relative"
|
||||||
|
/>
|
||||||
|
</HStack>
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
{/* 热点事件区域 */}
|
{/* 热点事件区域 */}
|
||||||
<HotEventsSection
|
<HotEventsSection
|
||||||
events={hotEvents}
|
events={hotEvents}
|
||||||
|
|||||||
Reference in New Issue
Block a user