fix: 实时监控 预警记录添加滚动条

This commit is contained in:
苑宏博 2024-05-10 11:07:58 +08:00
parent a47aa0c431
commit 15a46122e8
6 changed files with 54 additions and 39 deletions

View File

@ -1,4 +1,4 @@
import React, { useContext } from 'react'; import React, { useContext, useRef } from 'react';
import WindowToggle, { ISize } from './components/WindowToggle'; import WindowToggle, { ISize } from './components/WindowToggle';
import WarningRecordList from './components/WarningRecordList'; import WarningRecordList from './components/WarningRecordList';
import { ConfigProvider } from '@zhst/meta'; import { ConfigProvider } from '@zhst/meta';
@ -34,6 +34,7 @@ interface RealTimeMonitorProps {
largeImageTitle?: string; largeImageTitle?: string;
size: ISize; size: ISize;
setSize: React.Dispatch<React.SetStateAction<ISize>> setSize: React.Dispatch<React.SetStateAction<ISize>>
maxRecordCount?: number;
} }
export const RealTimeMonitor: React.FC<RealTimeMonitorProps> = (props) => { export const RealTimeMonitor: React.FC<RealTimeMonitorProps> = (props) => {
@ -53,19 +54,22 @@ export const RealTimeMonitor: React.FC<RealTimeMonitorProps> = (props) => {
selectedRecordId, selectedRecordId,
isRecordListLoading, isRecordListLoading,
size, size,
setSize setSize,
maxRecordCount
} = props } = props
const toggleRef = useRef<HTMLDivElement>()
const componentName = getPrefixCls('biz-real-time-monitor', customizePrefixCls); const componentName = getPrefixCls('biz-real-time-monitor', customizePrefixCls);
return ( return (
<div className={componentName} style={{ display: 'flex' }} > <div className={componentName} style={{ display: 'flex' }} >
<WindowToggle <WindowToggle
toggleRef={toggleRef}
selectedWindowKey={selectedWindowKey} selectedWindowKey={selectedWindowKey}
dataSource={videoDataSource} dataSource={videoDataSource}
handleWindowClick={handleWindowClick} handleWindowClick={handleWindowClick}
handleCloseButtonClick={handleCloseButtonClick} handleCloseButtonClick={handleCloseButtonClick}
size = {size} size={size}
setSize = {setSize} setSize={setSize}
/> />
<WarningRecordList <WarningRecordList
dataSource={warningDataSource} dataSource={warningDataSource}
@ -75,6 +79,8 @@ export const RealTimeMonitor: React.FC<RealTimeMonitorProps> = (props) => {
viewLargerImageModalRef={viewLargerImageModalRef} viewLargerImageModalRef={viewLargerImageModalRef}
isRecordListLoading={isRecordListLoading} isRecordListLoading={isRecordListLoading}
recordListTitle="监控预警记录" recordListTitle="监控预警记录"
maxHeight={toggleRef.current?.offsetHeight}
maxRecordCount={maxRecordCount}
/> />
</div> </div>
); );

View File

@ -4,6 +4,7 @@ import { ViewLargerImageModalRef } from '../../../ViewLargerImageModal';
import WarningRecordCard from '../../../WarningRecordCard'; import WarningRecordCard from '../../../WarningRecordCard';
import ViewLargerImageModal from '../../../ViewLargerImageModal'; import ViewLargerImageModal from '../../../ViewLargerImageModal';
import { Empty, Space, Spin } from 'antd'; import { Empty, Space, Spin } from 'antd';
import { pxToRem } from '@zhst/func'
import { LoadingOutlined } from '@ant-design/icons'; import { LoadingOutlined } from '@ant-design/icons';
import "./index.less" import "./index.less"
@ -28,6 +29,8 @@ interface WarningRecordListProps {
cardStyle?: React.CSSProperties; cardStyle?: React.CSSProperties;
imgStyle?: React.CSSProperties; imgStyle?: React.CSSProperties;
largeImageTitle?: string; largeImageTitle?: string;
maxHeight?: number;
maxRecordCount?: number;
} }
const WarningRecordList: React.FC<WarningRecordListProps> = (props) => { const WarningRecordList: React.FC<WarningRecordListProps> = (props) => {
@ -43,11 +46,12 @@ const WarningRecordList: React.FC<WarningRecordListProps> = (props) => {
style, style,
cardStyle, cardStyle,
imgStyle, imgStyle,
largeImageTitle largeImageTitle,
maxHeight,
maxRecordCount = 10
} = props } = props
return ( return (
<div className='zhst-biz-warning-record-list' style={style}> <div className='zhst-biz-warning-record-list' style={{ maxHeight : `${pxToRem(`${maxHeight}`)}` , ...style }} >
<div className='header'>{recordListTitle}</div> <div className='header'>{recordListTitle}</div>
<div className='body'> <div className='body'>
{ {
@ -58,7 +62,7 @@ const WarningRecordList: React.FC<WarningRecordListProps> = (props) => {
: (dataSource?.length) > 0 ? : (dataSource?.length) > 0 ?
<Space direction='vertical' size={10} > <Space direction='vertical' size={10} >
{dataSource?.map((record, index) => { {dataSource?.map((record, index) => {
if (index > 2) return if (index > maxRecordCount -1) return
return (<WarningRecordCard return (<WarningRecordCard
key={record?.id} key={record?.id}
record={record} record={record}

View File

@ -2,19 +2,21 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
border-left: solid 1px #00000026; border-left: solid 1px #00000026;
width: 320px; min-width: 320px;
.header { .header {
width: 100%; width: 100%;
height: 48px; height: 48px;
background-color: #EFF2F4; background-color: #EFF2F4;
padding: 10px 20px; padding: 0 20px;
box-sizing: border-box; box-sizing: border-box;
line-height: 48px;
} }
.body { .body {
padding: 10px; padding: 10px;
overflow: hidden; overflow-y: auto;
// overflow-x: hidden;
flex: 1; flex: 1;
} }
} }

View File

@ -1,53 +1,56 @@
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 } from 'antd'; import { ConfigProvider, Segmented, theme } from 'antd';
import { AppstoreOutlined, BarsOutlined } from '@ant-design/icons'; import { AppstoreOutlined, BarsOutlined } from '@ant-design/icons';
import { theme } from 'antd/lib'; 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;
selectedWindowKey?: string; selectedWindowKey?: string;
size: ISize; size: ISize;
setSize: React.Dispatch<React.SetStateAction<ISize>> setSize: React.Dispatch<React.SetStateAction<ISize>>
toggleRef: React.MutableRefObject<any>
} }
export const WindowToggle: React.FC<WindowToggleProps> = (props) => { export const WindowToggle: React.FC<WindowToggleProps> = (props) => {
const { dataSource = [], handleWindowClick, handleCloseButtonClick, selectedWindowKey , size = "large",setSize} = 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 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'> <div className='zhst-biz-window-toggle' ref={toggleRef}>
{/* 切换按钮 */} {/* 切换按钮 */}
<div className='header'> <div className='header'>
<Segmented <Segmented
defaultValue='large' defaultValue='large'
options={[ options={[
{ value: 'large', label: <div style={getLabelStyle(size === 'large')}><BarsOutlined /></div> }, { value: 'large', label: <div style={getLabelStyle(size === 'large')}><BarsOutlined /></div> },
{ value: 'small', label: <div style={getLabelStyle(size === 'small')}><AppstoreOutlined /></div> }, { value: 'small', label: <div style={getLabelStyle(size === 'small')}><AppstoreOutlined /></div> },
]} ]}
onChange={(value) => { onChange={(value) => {
// 当一个窗口时 默认 selectedkey 第一条数据的 windowkey // 当一个窗口时 默认 selectedkey 第一条数据的 windowkey
if (value === 'large' && dataSource.length > 0) { if (value === 'large' && dataSource.length > 0) {
const { windowKey } = dataSource[0] const { windowKey } = dataSource[0]
handleWindowClick?.(windowKey) handleWindowClick?.(windowKey)
} }
setSize(value as ISize) setSize(value as ISize)
}} }}
/> />
</div> </div>
<div className='body'> <div className='body'>
@ -57,7 +60,7 @@ export const WindowToggle: React.FC<WindowToggleProps> = (props) => {
if (size === "large" && index > 0) return if (size === "large" && index > 0) return
return ( return (
<VideoPlayerCard <VideoPlayerCard
key={item.windowKey} key={size === "large" ? "" : item.windowKey}
selectedWindowKey={selectedWindowKey} selectedWindowKey={selectedWindowKey}
size={size} size={size}
handleWindowClick={handleWindowClick} handleWindowClick={handleWindowClick}

View File

@ -87,7 +87,7 @@ export default () => {
setTimeout(() => { setTimeout(() => {
// 对后端返回数据进行处理 组装一套符合属性的 数据 // 对后端返回数据进行处理 组装一套符合属性的 数据
// videoSrc : videoData.videoSrc // videoSrc : videoData.videoSrc
const newVideoData: VideoPlayerCardProps = { imageKey: videoData.imageKey, title: videoData.title, odRect: videoData.odRect, videoSrc: videoData.videoSrc } const newVideoData: VideoPlayerCardProps = { imageKey: videoData.imageKey, title: videoData.title, odRect: videoData.odRect}
setVideoDataSource((pre) => { setVideoDataSource((pre) => {
const newVideoDataSource: VideoPlayerCardProps[] = pre.map((item) => { const newVideoDataSource: VideoPlayerCardProps[] = pre.map((item) => {
// 传给 选中的视频窗口 // 传给 选中的视频窗口

View File

@ -3,6 +3,7 @@ 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;
@ -48,11 +49,10 @@ 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: 931 } : { height: 456, cursor: 'pointer' }), ...(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% - 20px)" } : { flex: 1 } 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;
@ -65,7 +65,7 @@ export const VideoPlayerCard: React.FC<VideoPlayerCardProps> = (props) => {
} else if (imageKey) { } else if (imageKey) {
contentElement = ( contentElement = (
<div style={{ width: "100%", height: "100%", display: 'block' }}> <div style={{ width: "100%", height: "100%" }}>
<CropperImage <CropperImage
// editAble={true} // editAble={true}
odList={odRectDefault} odList={odRectDefault}
@ -102,7 +102,7 @@ export const VideoPlayerCard: React.FC<VideoPlayerCardProps> = (props) => {
{cardContent} {cardContent}
</> </>
) : ( ) : (
<div style={{ backgroundColor: '#000', height: '100%', display: 'flex', padding: '20px', boxSizing: 'border-box' }}> <div style={{ backgroundColor: '#000', height: '100%', display: 'flex', padding: `${pxToRem("20px")}`, boxSizing: 'border-box' }}>
{ {
isWindowLoading ? isWindowLoading ?
<div style={{ flex: 1, display: 'flex', justifyContent: 'center', alignItems: 'center' }}> <div style={{ flex: 1, display: 'flex', justifyContent: 'center', alignItems: 'center' }}>