Compare commits

...

4 Commits

Author SHA1 Message Date
zdl
93f43054fd fix:事件详情弹窗UI 2025-11-27 15:35:48 +08:00
zdl
101d042b0e fix:调整客服UI 2025-11-27 15:31:07 +08:00
zdl
a1aa6718e6 fix: 事件详情弹窗UI调整 2025-11-27 15:08:14 +08:00
zdl
753727c1c0 fix: 事件详情弹窗UI调整
重要性h5不展示
事件列表卡片间距调整
2025-11-27 14:40:38 +08:00
8 changed files with 191 additions and 50 deletions

View File

@@ -63,6 +63,59 @@ const BytedeskWidget = ({
bytedesk.init();
widgetRef.current = bytedesk;
// ⚡ H5 端样式适配:使用 MutationObserver 立即应用样式(避免闪烁)
const isMobile = window.innerWidth <= 768;
const applyBytedeskStyles = () => {
const allElements = document.querySelectorAll('body > div');
allElements.forEach(el => {
const style = window.getComputedStyle(el);
// 检查是否是右下角固定定位的元素Bytedesk 按钮)
if (style.position === 'fixed' && style.right && style.bottom) {
const rightVal = parseInt(style.right);
const bottomVal = parseInt(style.bottom);
if (rightVal >= 0 && rightVal < 100 && bottomVal >= 0 && bottomVal < 100) {
// H5 端设置按钮尺寸为 48x48只执行一次
if (isMobile && !el.dataset.bytedeskStyled) {
el.dataset.bytedeskStyled = 'true';
const button = el.querySelector('button');
if (button) {
button.style.width = '48px';
button.style.height = '48px';
button.style.minWidth = '48px';
button.style.minHeight = '48px';
}
}
// 提示框 3 秒后隐藏(查找白色气泡框)
const children = el.querySelectorAll('div');
children.forEach(child => {
if (child.dataset.bytedeskTooltip) return; // 已处理过
const childStyle = window.getComputedStyle(child);
// 白色背景的提示框
if (childStyle.backgroundColor === 'rgb(255, 255, 255)') {
child.dataset.bytedeskTooltip = 'true';
setTimeout(() => {
child.style.transition = 'opacity 0.3s';
child.style.opacity = '0';
setTimeout(() => child.remove(), 300);
}, 3000);
}
});
}
}
});
};
// 立即执行一次
applyBytedeskStyles();
// 监听 DOM 变化,新元素出现时立即应用样式
const observer = new MutationObserver(applyBytedeskStyles);
observer.observe(document.body, { childList: true, subtree: true });
// 5 秒后停止监听(避免性能问题)
setTimeout(() => observer.disconnect(), 5000);
// ⚡ 屏蔽 STOMP WebSocket 错误日志(不影响功能)
const originalConsoleError = console.error;
console.error = function(...args) {

View File

@@ -36,3 +36,37 @@ iframe[src*="/visitor/"] {
[class*="bytedesk-badge"] {
z-index: 1000000 !important;
}
/* ========== H5 端客服组件整体缩小 ========== */
@media (max-width: 768px) {
/* 整个客服容器缩小(包括按钮和提示框) */
[class*="bytedesk"],
[id*="bytedesk"],
[class*="BytedeskWeb"] {
transform: scale(0.7) !important;
transform-origin: bottom right !important;
}
}
/* ========== 提示框 3 秒后自动消失 ========== */
/* 提示框("在线客服 点击咨询"气泡)- 扩展选择器 */
[class*="bytedesk-bubble"],
[class*="bytedesk-tooltip"],
[class*="BytedeskWeb"] [class*="bubble"],
[class*="BytedeskWeb"] [class*="tooltip"],
[class*="bytedesk"] > div:not(button):not(iframe),
[class*="BytedeskWeb"] > div:not(button):not(iframe),
[id*="bytedesk"] > div:not(button):not(iframe) {
animation: bytedeskFadeOut 0.3s ease-out 3s forwards !important;
}
@keyframes bytedeskFadeOut {
from {
opacity: 1;
visibility: visible;
}
to {
opacity: 0;
visibility: hidden;
}
}

View File

@@ -543,7 +543,7 @@ const [currentMode, setCurrentMode] = useState('vertical');
<Flex justify="space-between" align="center">
{/* 左侧:标题 + 模式切换按钮 */}
<HStack spacing={4}>
<Heading size="md" color={PROFESSIONAL_COLORS.text.primary}>
<Heading size={isMobile ? "sm" : "md"} color={PROFESSIONAL_COLORS.text.primary}>
<HStack spacing={2}>
<TimeIcon color={PROFESSIONAL_COLORS.gold[500]} />
<Text bgGradient={PROFESSIONAL_COLORS.gradients.gold} bgClip="text">实时要闻·动态追踪</Text>
@@ -610,7 +610,9 @@ const [currentMode, setCurrentMode] = useState('vertical');
<CardBody
ref={cardBodyRef}
position="relative"
pt={4}
pt={0}
px={0}
mx={0}
display="flex"
flexDirection="column"
overflow="visible"

View File

@@ -9,18 +9,12 @@ import {
Center,
Text,
useBreakpointValue,
Modal,
ModalOverlay,
ModalContent,
ModalHeader,
ModalBody,
ModalCloseButton,
useDisclosure
} from '@chakra-ui/react';
import { InfoIcon } from '@chakra-ui/icons';
import HorizontalDynamicNewsEventCard from '../EventCard/HorizontalDynamicNewsEventCard';
import EventDetailScrollPanel from './EventDetailScrollPanel';
import DynamicNewsDetailPanel from '../DynamicNewsDetail/DynamicNewsDetailPanel';
import EventDetailModal from '../EventDetailModal';
/**
* 纵向分栏模式布局
@@ -165,20 +159,11 @@ const VerticalModeLayout = React.memo(({
{/* 移动端详情弹窗 */}
{isMobile && (
<Modal isOpen={isMobileModalOpen} onClose={onMobileModalClose} size="full" scrollBehavior="inside">
<ModalOverlay bg="blackAlpha.800" backdropFilter="blur(10px)" />
<ModalContent maxW="100vw" m={0} borderRadius={0}>
<ModalHeader bg="gray.900" color="white" borderBottom="1px solid" borderColor="gray.700">
{mobileSelectedEvent?.title || '事件详情'}
</ModalHeader>
<ModalCloseButton color="white" />
<ModalBody p={0} bg="gray.900">
{mobileSelectedEvent && (
<DynamicNewsDetailPanel event={mobileSelectedEvent} showHeader={false} />
)}
</ModalBody>
</ModalContent>
</Modal>
<EventDetailModal
open={isMobileModalOpen}
onClose={onMobileModalClose}
event={mobileSelectedEvent}
/>
)}
</Flex>
);

View File

@@ -47,7 +47,7 @@ const CompactMetaBar = ({ event, importance, isFollowing, followerCount, onToggl
spacing={3}
zIndex={1}
>
{/* 重要性徽章 - 与 EventHeaderInfo 样式一致,尺寸略小 */}
{/* 重要性徽章 - 与 EventHeaderInfo 样式一致,尺寸略小 - H5 隐藏 */}
<Badge
px={3}
py={1.5}
@@ -62,7 +62,7 @@ const CompactMetaBar = ({ event, importance, isFollowing, followerCount, onToggl
}
color="white"
boxShadow="lg"
display="flex"
display={{ base: 'none', lg: 'flex' }}
alignItems="center"
gap={1}
>

View File

@@ -0,0 +1,36 @@
.event-detail-modal {
top: 20% !important;
margin: 0 auto !important;
padding-bottom: 0 !important;
.ant-modal-content {
border-radius: 24px !important;
background: transparent;
}
// 标题样式 - 深色文字(白色背景)
.ant-modal-title {
color: #1A202C;
}
// 关闭按钮样式 - 深色(白色背景)
.ant-modal-close {
color: #4A5568;
&:hover {
color: #1A202C;
}
}
}
// 自底向上滑入动画
@keyframes slideUp {
from {
transform: translateY(100%);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}

View File

@@ -0,0 +1,48 @@
import React from 'react';
import { useSelector } from 'react-redux';
import { Modal } from 'antd';
import { selectIsMobile } from '@store/slices/deviceSlice';
import DynamicNewsDetailPanel from './DynamicNewsDetail/DynamicNewsDetailPanel';
import './EventDetailModal.less';
interface EventDetailModalProps {
/** 是否打开弹窗 */
open: boolean;
/** 关闭弹窗回调 */
onClose: () => void;
/** 事件对象 */
event: any; // TODO: 后续可替换为具体的 Event 类型
}
/**
* 事件详情弹窗组件
*/
const EventDetailModal: React.FC<EventDetailModalProps> = ({
open,
onClose,
event,
}) => {
const isMobile = useSelector(selectIsMobile);
return (
<Modal
open={open}
onCancel={onClose}
footer={null}
title={event?.title || '事件详情'}
width='100vw'
destroyOnClose
className="event-detail-modal"
styles={{
mask: { background: 'transparent' },
content: { borderRadius: 24, padding: 0, maxWidth: 1400, background: 'transparent', margin: '0 auto' },
header: { background: '#FFFFFF', borderBottom: '1px solid #E2E8F0', padding: '16px 24px', borderRadius: '24px 24px 0 0', margin: 0 },
body: { padding: 0 },
}}
>
{event && <DynamicNewsDetailPanel event={event} showHeader={false} />}
</Modal>
);
};
export default EventDetailModal;

View File

@@ -2,19 +2,11 @@
import React, { useState } from 'react';
import { Card, Badge, Tag, Empty, Carousel, Tooltip } from 'antd';
import { ArrowUpOutlined, ArrowDownOutlined, LeftOutlined, RightOutlined } from '@ant-design/icons';
import {
Modal,
ModalOverlay,
ModalContent,
ModalHeader,
ModalBody,
ModalCloseButton,
useDisclosure
} from '@chakra-ui/react';
import { useDisclosure } from '@chakra-ui/react';
import EventDetailModal from './EventDetailModal';
import dayjs from 'dayjs';
import './HotEvents.css';
import defaultEventImage from '../../../assets/img/default-event.jpg';
import DynamicNewsDetailPanel from './DynamicNewsDetail';
// 自定义箭头组件
const CustomArrow = ({ className, style, onClick, direction }) => {
@@ -196,21 +188,12 @@ const HotEvents = ({ events, onPageChange, onEventClick }) => {
</Card>
)}
{/* 事件详情弹窗 - 使用 Chakra UI Modal与平铺模式一致 */}
{isModalOpen ? (
<Modal isOpen={isModalOpen} onClose={onModalClose} size="6xl" scrollBehavior="inside">
<ModalOverlay />
<ModalContent>
<ModalHeader>
{modalEvent?.title || '事件详情'}
</ModalHeader>
<ModalCloseButton />
<ModalBody pb={6}>
{modalEvent && <DynamicNewsDetailPanel event={modalEvent} />}
</ModalBody>
</ModalContent>
</Modal>
): null}
{/* 事件详情弹窗 */}
<EventDetailModal
open={isModalOpen}
onClose={onModalClose}
event={modalEvent}
/>
</div>
);
};