fix: 优化实时监控布局

This commit is contained in:
苑宏博 2024-05-11 09:46:33 +08:00
parent faf0a5682e
commit 93bc21a29a
9 changed files with 103 additions and 71 deletions

View File

@ -35,6 +35,7 @@ interface RealTimeMonitorProps {
size: ISize; size: ISize;
setSize: React.Dispatch<React.SetStateAction<ISize>> setSize: React.Dispatch<React.SetStateAction<ISize>>
maxRecordCount?: number; maxRecordCount?: number;
warningImgStyle?: React.CSSProperties;
} }
export const RealTimeMonitor: React.FC<RealTimeMonitorProps> = (props) => { export const RealTimeMonitor: React.FC<RealTimeMonitorProps> = (props) => {
@ -55,7 +56,8 @@ export const RealTimeMonitor: React.FC<RealTimeMonitorProps> = (props) => {
isRecordListLoading, isRecordListLoading,
size, size,
setSize, setSize,
maxRecordCount maxRecordCount,
warningImgStyle,
} = props } = props
const toggleRef = useRef<HTMLDivElement>() const toggleRef = useRef<HTMLDivElement>()
const componentName = getPrefixCls('biz-real-time-monitor', customizePrefixCls); const componentName = getPrefixCls('biz-real-time-monitor', customizePrefixCls);
@ -81,6 +83,7 @@ export const RealTimeMonitor: React.FC<RealTimeMonitorProps> = (props) => {
recordListTitle="监控预警记录" recordListTitle="监控预警记录"
maxHeight={toggleRef.current?.offsetHeight} maxHeight={toggleRef.current?.offsetHeight}
maxRecordCount={maxRecordCount} maxRecordCount={maxRecordCount}
imgStyle={warningImgStyle}
/> />
</div> </div>
); );

View File

@ -68,8 +68,8 @@ const WarningRecordList: React.FC<WarningRecordListProps> = (props) => {
record={record} record={record}
onRecordClick={(record) => { onRecordClick?.(record) }} onRecordClick={(record) => { onRecordClick?.(record) }}
selectedRecordId={selectedRecordId} selectedRecordId={selectedRecordId}
cardStyle={{ width: 300, height: 264, ...cardStyle }} cardStyle={{ ...cardStyle }}
imgStyle={{ width: 280, height: 169, ...imgStyle }} imgStyle={{ ...imgStyle }}
/>) />)
} }
)} )}

View File

@ -16,7 +16,7 @@
.body { .body {
padding: 10px; padding: 10px;
overflow-y: auto; overflow-y: auto;
// overflow-x: hidden; overflow-x: hidden;
flex: 1; flex: 1;
} }
} }

View File

@ -1,16 +1,14 @@
import React from 'react'; import React from 'react';
import VideoPlayerCard from '../../../VideoPlayerCard'; import VideoPlayerCard from '../../../VideoPlayerCard';
import { VideoPlayerCardProps } from '../../../VideoPlayerCard'; import { VideoPlayerCardProps } from '../../../VideoPlayerCard';
import { Segmented, theme } from 'antd'; import { Row, Col, Segmented, theme } from 'antd';
import { AppstoreOutlined, BarsOutlined } from '@ant-design/icons'; import { AppstoreOutlined, BarsOutlined } from '@ant-design/icons';
import { pxToRem } from '@zhst/func' import { pxToRem } from '@zhst/func'
import './index.less' import './index.less'
export type ISize = 'large' | 'small' export type ISize = 'large' | 'small'
interface WindowToggleProps { interface WindowToggleProps {
dataSource?: VideoPlayerCardProps[]; dataSource?: VideoPlayerCardProps[];
handleWindowClick?: (key?: string) => void; handleWindowClick?: (key?: string) => void;
handleCloseButtonClick?: (key?: string) => void; handleCloseButtonClick?: (key?: string) => void;
@ -25,13 +23,11 @@ export const WindowToggle: React.FC<WindowToggleProps> = (props) => {
const { dataSource = [], handleWindowClick, handleCloseButtonClick, selectedWindowKey, size = "large", setSize, toggleRef } = props const { dataSource = [], handleWindowClick, handleCloseButtonClick, selectedWindowKey, size = "large", setSize, toggleRef } = props
const { useToken } = theme const { useToken } = theme
const { token } = useToken() const { token } = useToken()
const getLabelStyle = (isSelected: boolean) => ({ const getLabelStyle = (isSelected: boolean) => ({
padding: `0 ${pxToRem("11px")}`, background: "#fff", padding: `0 ${pxToRem("11px")}`, background: "#fff",
...(isSelected ? { background: token.colorPrimary, color: '#fff' } : {}), ...(isSelected ? { background: token.colorPrimary, color: '#fff' } : {}),
}); });
return ( return (
<div className='zhst-biz-window-toggle' ref={toggleRef}> <div className='zhst-biz-window-toggle' ref={toggleRef}>
{/* 切换按钮 */} {/* 切换按钮 */}
@ -54,21 +50,46 @@ export const WindowToggle: React.FC<WindowToggleProps> = (props) => {
</div> </div>
<div className='body'> <div className='body'>
{
dataSource?.map((item, index) => {
if (size === "large" && index > 0) return <Row gutter={[0, 20]} style={{ width: "100%" }}> {/* 设置栅格间距 */}
{
size === "large" ?
<>
{
dataSource?.map((item, index) => { // 仅显示前四个元素,即两行两列
if (index > 0) return null
return ( return (
<Col xs={24} sm={24} md={24} lg={24} xl={24} >
<VideoPlayerCard <VideoPlayerCard
key={size === "large" ? "" : item.windowKey} key={""}
selectedWindowKey={selectedWindowKey} selectedWindowKey={selectedWindowKey}
size={size} size={size}
handleWindowClick={handleWindowClick} handleWindowClick={handleWindowClick}
handleCloseButtonClick={handleCloseButtonClick} handleCloseButtonClick={handleCloseButtonClick}
{...item} {...item}
/>) />
</Col>)
}) })
} }
</>
: <>
{dataSource?.map((item) => {
return (
<Col xs={24} sm={12} md={12} lg={12} xl={12} className='sm-card'>
<VideoPlayerCard
key={item.windowKey}
selectedWindowKey={selectedWindowKey}
size={size}
handleWindowClick={handleWindowClick}
handleCloseButtonClick={handleCloseButtonClick}
{...item}
/>
</Col>
);
})}</>
}
</Row>
</div> </div>
</div> </div>
); );

View File

@ -29,17 +29,16 @@
} }
.body { .body {
flex: 1;
width: 100%;
background-color: #E5EAEC; background-color: #E5EAEC;
padding: 10px; padding: 20px;
box-sizing: border-box; box-sizing: border-box;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
>div { .sm-card:nth-child(odd) {
margin: 10px; padding-right: 10px;
}
.sm-card:nth-child(even) {
padding-left: 10px;
} }
} }
} }

View File

@ -3,6 +3,7 @@ import React, { useState } from 'react';
import { IRecord, RealTimeMonitor, VideoPlayerCardProps, useViewLargerImageModal } from '@zhst/biz'; import { IRecord, RealTimeMonitor, VideoPlayerCardProps, useViewLargerImageModal } from '@zhst/biz';
import { videoData, warningData } from './mock'; import { videoData, warningData } from './mock';
import { Space } from 'antd'; import { Space } from 'antd';
import { pxToRem } from '@zhst/func';
import dayjs from 'dayjs' import dayjs from 'dayjs'
import './index.less' import './index.less'
@ -153,6 +154,7 @@ export default () => {
recordListTitle="监控预警记录" recordListTitle="监控预警记录"
size={size} size={size}
setSize={setSize} setSize={setSize}
warningImgStyle={{ width: `${pxToRem("280px")}`, height: `${pxToRem("169px")}` }}
/> />
<button onClick={() => { mockData() }}></button> <button onClick={() => { mockData() }}></button>

View File

@ -3,7 +3,6 @@ import { theme } from 'antd/lib';
import { ConfigProvider, VideoPlayer, CropperImage, type VideoViewRef, } from '@zhst/meta'; import { ConfigProvider, VideoPlayer, CropperImage, type VideoViewRef, } from '@zhst/meta';
import React, { useState, useEffect, ReactNode, useRef, useContext } from 'react'; import React, { useState, useEffect, ReactNode, useRef, useContext } from 'react';
import { CloseOutlined, LoadingOutlined } from '@ant-design/icons'; import { CloseOutlined, LoadingOutlined } from '@ant-design/icons';
import { pxToRem } from '@zhst/func'
import './index.less' import './index.less'
export interface VideoPlayerCardProps { export interface VideoPlayerCardProps {
prefixCls?: string; prefixCls?: string;
@ -32,7 +31,6 @@ export interface VideoPlayerCardProps {
export const VideoPlayerCard: React.FC<VideoPlayerCardProps> = (props) => { export const VideoPlayerCard: React.FC<VideoPlayerCardProps> = (props) => {
const { ConfigContext } = ConfigProvider; const { ConfigContext } = ConfigProvider;
const { getPrefixCls } = useContext(ConfigContext); const { getPrefixCls } = useContext(ConfigContext);
const { prefixCls: customizePrefixCls, showType, imageKey, videoSrc, cardProps, isWindowLoading, errorReasonText, size, title, handleCloseButtonClick, handleWindowClick, windowKey, selectedWindowKey = '', odRect = [] } = props; const { prefixCls: customizePrefixCls, showType, imageKey, videoSrc, cardProps, isWindowLoading, errorReasonText, size, title, handleCloseButtonClick, handleWindowClick, windowKey, selectedWindowKey = '', odRect = [] } = props;
@ -49,10 +47,8 @@ export const VideoPlayerCard: React.FC<VideoPlayerCardProps> = (props) => {
border: `2px solid ${token.colorPrimary}`, boxShadow: " 0px 2px 9px 0px rgba(0,0,0,0.16)" border: `2px solid ${token.colorPrimary}`, boxShadow: " 0px 2px 9px 0px rgba(0,0,0,0.16)"
} }
const cardStyle: React.CSSProperties = { const cardStyle: React.CSSProperties = {
...(size === 'large' ? { height: `${pxToRem("931px")}` } : { height: `${pxToRem("456px")}` , cursor: 'pointer' }),
...(size === 'small' && selectedWindowKey === windowKey ? selectedBorderStyle : {}) ...(size === 'small' && selectedWindowKey === windowKey ? selectedBorderStyle : {})
}; };
const videoPlayerCardStyle = size === 'small' ? { width: `calc(50% - ${pxToRem("20px")})` } : { flex: 1 }
useEffect(() => { useEffect(() => {
if (!isWindowLoading && (videoSrc || imageKey)) { if (!isWindowLoading && (videoSrc || imageKey)) {
let contentElement: JSX.Element | null = null; let contentElement: JSX.Element | null = null;
@ -64,7 +60,6 @@ export const VideoPlayerCard: React.FC<VideoPlayerCardProps> = (props) => {
} else if (imageKey) { } else if (imageKey) {
contentElement = ( contentElement = (
<div style={{ width: "100%", height: "100%" }}> <div style={{ width: "100%", height: "100%" }}>
<CropperImage <CropperImage
// editAble={true} // editAble={true}
@ -72,7 +67,6 @@ export const VideoPlayerCard: React.FC<VideoPlayerCardProps> = (props) => {
url={imageKey} url={imageKey}
/> />
</div> </div>
); );
} }
setCardContent(contentElement); setCardContent(contentElement);
@ -80,10 +74,10 @@ export const VideoPlayerCard: React.FC<VideoPlayerCardProps> = (props) => {
setCardContent(null) setCardContent(null)
} }
}, [showType, imageKey, videoSrc, isWindowLoading]); }, [showType, imageKey, videoSrc, isWindowLoading]);
return ( return (
<div className={componentName} onClick={() => { handleWindowClick?.(windowKey) }} style={videoPlayerCardStyle}> <div className={componentName} onClick={() => { handleWindowClick?.(windowKey) }} >
<Card <Card
className={`${size === 'large' ? `${componentName}-large` : `${componentName}-small`}`}
title={ title={
<Space style={{ width: "100%", justifyContent: "space-between" }}> <Space style={{ width: "100%", justifyContent: "space-between" }}>
<div>{title}</div> <div>{title}</div>
@ -102,7 +96,7 @@ export const VideoPlayerCard: React.FC<VideoPlayerCardProps> = (props) => {
{cardContent} {cardContent}
</> </>
) : ( ) : (
<div style={{ backgroundColor: '#000', height: '100%', display: 'flex', padding: `${pxToRem("20px")}`, boxSizing: 'border-box' }}> <div className={`${componentName}-error`} >
{ {
isWindowLoading ? isWindowLoading ?
<div style={{ flex: 1, display: 'flex', justifyContent: 'center', alignItems: 'center' }}> <div style={{ flex: 1, display: 'flex', justifyContent: 'center', alignItems: 'center' }}>

View File

@ -1,4 +1,21 @@
.zhst-biz-video-player-card { .zhst-biz-video-player-card {
&-large {
height: 931px;
}
&-small {
height: 456px;
cursor: pointer
}
&-error {
background-color: #000;
height: 100%;
display: flex;
padding: 20px;
box-sizing: border-box;
}
.ant-card-head { .ant-card-head {
padding: 0 20px; padding: 0 20px;
} }

View File

@ -1,6 +1,5 @@
import React, { useImperativeHandle, useRef, useState, forwardRef, useContext } from 'react'; import React, { useImperativeHandle, useRef, useState, forwardRef, useContext } from 'react';
import { Modal, ModalProps, Space, SpaceProps } from 'antd'; import { Modal, ModalProps, Space, SpaceProps, theme } from 'antd';
import theme from 'antd/lib/theme';
import { DownloadOutlined } from '@ant-design/icons'; import { DownloadOutlined } from '@ant-design/icons';
import { ConfigProvider, CropperImage } from '@zhst/meta'; import { ConfigProvider, CropperImage } from '@zhst/meta';
@ -44,8 +43,6 @@ export const ViewLargerImageModal = forwardRef<ViewLargerImageModalRef, ViewLarg
const { getPrefixCls } = useContext(ConfigContext); const { getPrefixCls } = useContext(ConfigContext);
const { prefixCls: customizePrefixCls, modalProps, downloadImg, imgStyle, title = '预警大图', downloadText = '下载大图', spaceProps } = props const { prefixCls: customizePrefixCls, modalProps, downloadImg, imgStyle, title = '预警大图', downloadText = '下载大图', spaceProps } = props
const componentName = getPrefixCls('biz-warning-larger-image', customizePrefixCls); const componentName = getPrefixCls('biz-warning-larger-image', customizePrefixCls);
const { useToken } = theme const { useToken } = theme
const { token } = useToken() const { token } = useToken()
const [open, setOpen] = useState<boolean>(false); const [open, setOpen] = useState<boolean>(false);
@ -86,7 +83,6 @@ export const ViewLargerImageModal = forwardRef<ViewLargerImageModalRef, ViewLarg
> >
<Space size={0} {...spaceProps}> <Space size={0} {...spaceProps}>
<div className={`${componentName}-left-img`} style={{ ...imgStyle }}> <div className={`${componentName}-left-img`} style={{ ...imgStyle }}>
<CropperImage <CropperImage
// editAble={false} // editAble={false}
// selectAble={false} // selectAble={false}