我需要解决一个问题,主要内容区域,不管设备大小是多大,都要默认展示三行,这是我的页面文件代码:/**
* @Date: 2023-12-20 09:59:06
* @LastEditTime: 2024-01-09 18:22:35
* @FilePath: \工作\xinsheng-chasiwu-legacy-front\src\h5\components\Detail\modules\VideoSummaryH5\index.js
* @Description: 智能视频摘要
*/
import { useState, useRef, useEffect } from 'react';
import PropTypes from 'prop-types';
import SvgIcon from '@src/components/SvgIcon';
import css from './style.m.css';
import eventBus from '@src/utils/eventBus';
import { useLocalStorage } from '@src/components/Detail/modules/VideoPlayer/modules/VideoSummary/summaryHooks';
import { getNls, locale } from '@src/utils/i18n';
import { useTypeWriterHooks } from '@src/components/Detail/modules/VideoPlayer/modules/VideoSummary/summaryHooks.js';
import { DownOutlined, UpOutlined } from '@ant-design/icons';
import Panel, { PanelItem } from '@hui/react-mobile/Panel';
const isEn = locale === 'en';
const dict = getNls('components_LiveDetail_modules_Content_modules_Summary');
// 添加/移除评论区 class
const addCommentsClass = ({ seth5VideoHeight, h5VideoHeight, type = 0 }) => {
const commentDom = document.querySelector('#content-main .ev_tab_container');
if (!commentDom) return;
if (type === 1) {
commentDom.classList.remove('live-comments-top');
} else if (!commentDom.classList.contains('live-comments-top')) {
commentDom.classList.add('live-comments-top');
if (seth5VideoHeight) seth5VideoHeight(h5VideoHeight + 56);
}
};
const renderExpandTitle = (item) => {
return (
<div className={css.summaryTitleBox}>
<span className={`${css.summaryTimeItem} h5ap-font-12`}>{item.time.split('~')[0]}</span>
<span className={`${css.summaryTitleItem} h5ap-font-14`}>{item.title}</span>
</div>
);
};
function renderContent(props) {
const {
showAll,
aiSummaryTitle,
aiSummaryContent,
aiSummaryContentEn,
keyWordsTitle,
keyWordsContent,
keyList,
keyListEn,
selectedIndex,
setSelectedIndex,
summaryRef,
contentSumRef,
} = props;
const keyListContent = isEn ? keyListEn : keyList;
return (
<div ref={summaryRef} className={`${css.summaryContent} ${css.summaryContentWidth} h5ap-font-14`}>
<div ref={contentSumRef}>
<div className={`${css.label} h5ap-font-14`}>{aiSummaryTitle}</div>
<div className={css.description}>{isEn ? aiSummaryContentEn : aiSummaryContent}</div>
{keyWordsContent && (
<>
<div className={`${css.label} ${css.keywordsLabel}`}>{keyWordsTitle}</div>
<p className={css.keywords}>{keyWordsContent}</p>
</>
)}
{showAll && (
<Panel
enableMultiExpand={true}
selectedIndex={selectedIndex}
onExpand={(index, event, isExpand) => {
if (!isExpand) {
setSelectedIndex([...selectedIndex, index]);
}
}}
onClose={(index, event, isExpand) => {
const indexArr = selectedIndex.filter((f) => f !== index);
if (isExpand) {
setSelectedIndex(indexArr);
}
}}
>
{keyListContent.map((item, index) => (
<PanelItem
titlePosition="left"
key={index}
closable={false}
expandTitle={renderExpandTitle(item)}
shrinkTitle={renderExpandTitle(item)}
>
{item.content}
</PanelItem>
))}
</Panel>
)}
</div>
</div>
);
}
function VideoSummaryH5(props) {
const { videoId, videoUuids, columnType, seth5VideoHeight, h5VideoHeight } = props;
const [isNotFirstClosed, setIsNotFirstClosed] = useLocalStorage(videoUuids, 'isNotFirstClosed');
const [isFirstClosed, setIsFirstClosed] = useState(isNotFirstClosed);
const [visible, setVisible] = useState(false);
const [showAll, setShowAll] = useState(false);
const [selectedIndex, setSelectedIndex] = useState([0]);
const [isOneScreen, setIsOneScreen] = useState(0); // 是否一屏可显示全部 1:可一屏
const [reloadCompoent, setReloadCompoent] = useState(0); // 更新副作用函数
const [expandClickState, setExpandClickState] = useState(false);
const summaryRef = useRef(null);
const contentSumRef = useRef(null);
const contentRef = useRef(null);
const containerRef = useRef(null);
const {
aiSummaryTitle,
aiSummaryContent,
aiSummaryContentEn,
keyWordsTitle,
keyWordsContent,
isShowGenerateBtn,
keyList,
keyListEn,
} = useTypeWriterHooks(props);
const params = {
aiSummaryTitle,
aiSummaryContent,
aiSummaryContentEn,
keyWordsTitle,
keyWordsContent,
keyList,
keyListEn,
showAll,
setShowAll,
selectedIndex,
setSelectedIndex,
summaryRef,
contentSumRef,
};
// 检测是否可以在一屏内显示全部内容
useEffect(() => {
let element = summaryRef?.current;
if (!element && !contentSumRef?.current) return;
if (!contentSumRef?.current || !containerRef?.current) return;
// 获取视口高度
const viewportHeight = window.innerHeight;
const contentHeight = contentSumRef.current.offsetHeight;
// 获取元素的位置信息
const rect = containerRef?.current.getBoundingClientRect();
const elementBottomPos = rect.top;
let flag = contentHeight <= viewportHeight - elementBottomPos - 130;
setIsOneScreen(flag ? 1 : 2);
if (flag) return;
// 获取元素距离文档顶部的位置
const elementRect = element.getBoundingClientRect();
// 获取元素距离视口顶部的位置
const elementTopFromViewport = elementRect.top;
// 计算剩余可用高度
const availableHeight = viewportHeight - elementTopFromViewport;
element.style.height = `${availableHeight - 30}px`; // 设置摘要高度
document.body.style.overflow = 'hidden'; // 关闭body滚动
}, [summaryRef?.current, containerRef?.current, reloadCompoent]);
const handleClickClose = () => {
eventBus.emit(`showFloatWindow${videoId}`, true, 'click');
document.body.style.overflow = 'auto'; // 开启body滚动
eventBus.emit('options_show', true);
setVisible(false);
setShowAll(false);
setIsFirstClosed(true);
setIsNotFirstClosed(true);
if (columnType !== 'live') return;
addCommentsClass({ seth5VideoHeight, h5VideoHeight, type: 1 });
};
useEffect(() => {
if (isOneScreen === 2 && expandClickState) {
eventBus.emit('options_show', false); // 一屏展示不完隐藏操作栏
}
}, [isOneScreen, expandClickState]);
useEffect(() => {
eventBus.removeAllListeners('evt_showSummaryH5');
eventBus.on('evt_showSummaryH5', (value) => {
setVisible(value);
if (columnType !== 'live') return;
if (!isFirstClosed && value) {
addCommentsClass({ seth5VideoHeight, h5VideoHeight });
} else {
addCommentsClass({ seth5VideoHeight, h5VideoHeight, type: 1 });
}
});
return () => {
eventBus.removeAllListeners('evt_showSummaryH5');
};
}, [columnType, isFirstClosed, seth5VideoHeight, h5VideoHeight, videoId]);
if (!visible) return null;
return (
<div
ref={containerRef}
className={`${css.videoSummaryH5} video-summary-h5 ${locale === 'en' ? css.summaryH5En : ''}`}
>
{/* 标题与关闭按钮 */}
<div className={css.summaryH5Notice}>
<div className={css.summaryH5Left}>
<SvgIcon iconClass="summaryIcon" svgClass={css.svg} svg />
<div className={css.title}>{dict.aiSummary}</div>
</div>
<div className={css.summaryH5Right}>
<SvgIcon iconClass="close" click={handleClickClose} />
</div>
</div>
{/* 内容区域 */}
<div className={css.summaryH5Container}>
{/* 主要内容 */}
<div ref={contentRef} className={showAll ? css.summaryH5Expanded : css.summaryH5Clamp}>
{renderContent(params)}
</div>
{/* 按钮容器:根据是否一屏显示决定位置 */}
<div className={css.actionButton}>
{!showAll ? (
<span
className={css.expandIcon}
onClick={(e) => {
e.stopPropagation();
setShowAll(true);
setReloadCompoent((pre) => pre + 1); // 执行副作用函数
setExpandClickState(true);
}}
>
<DownOutlined />
</span>
) : (
<span
className={css.foldButtonInline}
onClick={(e) => {
e.stopPropagation();
eventBus.emit('options_show', true);
document.body.style.overflow = 'auto'; // 开启body滚动
setShowAll(false);
setExpandClickState(false);
setSelectedIndex([0]);
}}
>
<UpOutlined />
</span>
)}
</div>
</div>
</div>
);
}
VideoSummaryH5.propTypes = {
videoId: PropTypes.string,
videoUuids: PropTypes.string,
columnType: PropTypes.string,
seth5VideoHeight: PropTypes.func,
h5VideoHeight: PropTypes.number,
};
export default VideoSummaryH5;
这是我的样式文件代码:.videoSummaryH5 {
background: rgba(0, 65, 211, 0.05);
padding: 8px 24px;
line-height: 1.5;
font-size: 14px;
}
.svg {
font-size: 22px;
margin-right: 4px;
}
.summaryH5Notice {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 2px;
}
.summaryH5Right,
.summaryH5Left {
display: flex;
align-items: center;
}
.summaryH5Left {
color: #000;
}
/* 三行截断,单词不断开 */
.summaryH5Clamp {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
/* 精确控制 */
font-size: 14px;
height: 90px;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-word;
box-sizing: border-box;
/* 防止外部样式干扰 */
white-space: normal;
margin: 0;
padding: 0;
}
/* 展开后:全文显示 */
.summaryH5Expanded {
white-space: pre-wrap;
overflow: visible;
text-overflow: unset;
display: block;
}
/* 容器定位图标 */
.summaryH5Container {
position: relative;
padding-right: 20px;
}
.actionButton {
position: absolute;
right: 0;
bottom: 0;
color: #0041d3;
}
/* 展开/收起图标 */
.expandIcon {
position: absolute;
right: 0;
bottom: 0;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
z-index: 1;
cursor: pointer;
color: #0041d3;
font-size: 12px;
}
/* 收起按钮:内联 vs 固定到底部 */
.foldButtonInline {
position: relative;
text-align: center;
margin: 8px 0;
display: flex;
justify-content: flex-end;
align-items: center;
width: 327px;
}
.foldButtonFixed {
position: fixed;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 65, 211, 0.1);
padding: 4px 12px;
border-radius: 20px;
z-index: 1000;
}
/* 内容样式 */
.summaryContent {
overflow-y: auto;
border-radius: 0.8rem;
padding-bottom: 1.6rem;
width: 32rem;
font-size: 1.4rem;
line-height: 2.4rem;
/* 阻止滚动链 */
overscroll-behavior: contain;
}
.summaryContent::-webkit-scrollbar {
display: none;
}
.summaryContentWidth {
width: 28.8rem;
}
.label {
color: #666666;
margin-bottom: 4px;
}
.description,
.keywords {
color: #000000;
text-align: justify;
word-break: break-word;
}
.keywordsLabel {
margin-top: 16px;
}
/* Panel 样式覆盖 */
.summaryContent :global .ev_Panel {
margin-top: 24px;
}
.summaryContent :global .ev_Panel .ev_PanelItem:not(:first-child) {
margin-top: 16px;
}
.summaryContent :global .ev_Panel .ev_PanelItem_title {
flex-direction: row-reverse;
justify-content: space-between;
height: auto;
}
.summaryContent :global .ev_Panel .ev_PanelItem_title .ev_PanelItem_title_titleInfo {
flex: 1;
font-size: 14px;
color: #666666;
line-height: 24px;
word-break: break-all;
}
.summaryContent :global .ev_Panel .ev_PanelItem .ev_PanelItem_title .ev_PanelItem_title_showChange {
margin-right: 0;
align-self: flex-start;
margin-left: 4px;
width: 24px !important;
height: 24px !important;
line-height: 24px !important;
display: flex;
align-items: center;
justify-content: center;
}
.summaryContent :global .ev_Panel .ev_PanelItem .ev_PanelItem_title .panelHide {
justify-content: flex-start;
}
.summaryContent :global .ev_Panel .ev_PanelItem .ev_PanelItem_title .panelShow {
justify-content: flex-end;
}
.summaryContent :global .ev_Panel .ev_PanelItem .ev_PanelItem_title .ev_PanelItem_title_showChange > .ev_icon {
display: flex;
align-items: center;
justify-content: center;
}
.summaryContent :global .ev_Panel .ev_PanelItem .ev_PanelItem_title .ev_PanelItem_title_showChange svg {
width: 12px;
height: 12px;
}
.summaryContent :global .ev_Panel .ev_PanelItem_container {
padding: 0;
margin-top: 6px;
font-size: 14px;
color: #000000;
text-align: justify;
line-height: 24px;
}
/* 时间标题样式 */
.summaryTitleBox {
display: flex;
}
.summaryTimeItem {
text-wrap: nowrap;
margin-right: 8px;
max-width: 60px;
white-space: nowrap;
}
.summaryTitleItem {
flex: 1;
word-break: break-all;
}
/* 图标类 */
.operationIcon {
margin-left: 12px;
font-size: 18px;
color: #666;
}
/* 英文适配 */
.summaryH5En .title {
line-height: 22px;
font-size: 14px;
color: #000;
}
.summaryH5En .operationIcon {
margin-left: 8px;
}
/* 全局兼容 */
:global(.video-summary-h5 .summaryTest) {
width: max-content !important;
white-space: nowrap !important;
max-width: max-content !important;
}
请你将修改好的完整代码发我