feat: 添加 视频窗口切换组件

This commit is contained in:
YuanHongbo 2024-03-10 16:20:59 +08:00
parent d064da49a4
commit c3041a7d9e
7 changed files with 52 additions and 46 deletions

View File

@ -12,15 +12,15 @@ type ViewLargerImageModalParams = {
}[]; }[];
}; };
interface ViewLargerImageModalRef { export interface ViewLargerImageModalRef {
show: (params?: ViewLargerImageModalParams) => void; show: (params?: ViewLargerImageModalParams) => void;
handleCancel: () => void; handleCancel: () => void;
} }
interface ViewLargerImageModalProps { export interface ViewLargerImageModalProps {
imgStyle?: React.CSSProperties; imgStyle?: React.CSSProperties;
downloadImg?: (imgSrc: string) => void; downloadImg?: (imgSrc?: string) => void;
title: string; title?: string;
downloadText?: string; downloadText?: string;
modalProps?: ModalProps modalProps?: ModalProps
spaceProps?: SpaceProps; spaceProps?: SpaceProps;
@ -29,7 +29,7 @@ interface ViewLargerImageModalProps {
export const ViewLargerImageModal = forwardRef<ViewLargerImageModalRef, ViewLargerImageModalProps>( export const ViewLargerImageModal = forwardRef<ViewLargerImageModalRef, ViewLargerImageModalProps>(
(props, ref) => { (props, ref) => {
const { modalProps, downloadImg, imgStyle, title, downloadText = '下载大图' ,spaceProps} = props const { modalProps, downloadImg, imgStyle, title = '预警大图', downloadText = '下载大图', spaceProps } = props
const { useToken } = theme const { useToken } = theme
const { token } = useToken() const { token } = useToken()
const [open, setOpen] = useState<boolean>(false); const [open, setOpen] = useState<boolean>(false);
@ -38,7 +38,7 @@ export const ViewLargerImageModal = forwardRef<ViewLargerImageModalRef, ViewLarg
const handleCancel = () => { const handleCancel = () => {
setOpen(false); setOpen(false);
} }
useImperativeHandle(ref, () => { useImperativeHandle(ref, () => {
return { return {
@ -64,7 +64,6 @@ export const ViewLargerImageModal = forwardRef<ViewLargerImageModalRef, ViewLarg
> >
<Space size={0} styles={{ item: { backgroundColor: '#F6F9FAFF' } }} {...spaceProps}> <Space size={0} styles={{ item: { backgroundColor: '#F6F9FAFF' } }} {...spaceProps}>
<img alt={title} src={imgSrc} style={{ width: 789, height: 444, display: 'block', ...imgStyle }} /> <img alt={title} src={imgSrc} style={{ width: 789, height: 444, display: 'block', ...imgStyle }} />
<div className='right-context'> <div className='right-context'>
{warningData?.map(({ label, value }) => ( {warningData?.map(({ label, value }) => (
<div key={label} > <div key={label} >
@ -72,11 +71,8 @@ export const ViewLargerImageModal = forwardRef<ViewLargerImageModalRef, ViewLarg
{value} {value}
</div> </div>
))} ))}
{imgSrc && downloadImg && <div className='img-download' style={{ color: token.colorPrimary }} onClick={() => downloadImg?.(imgSrc)} ><DownloadOutlined /><span style={{ paddingLeft: 3 }}>{downloadText}</span></div>} {imgSrc && downloadImg && <div className='img-download' style={{ color: token.colorPrimary }} onClick={() => downloadImg?.(imgSrc)} ><DownloadOutlined /><span style={{ paddingLeft: 3 }}>{downloadText}</span></div>}
</div> </div>
</Space> </Space>
</Modal> </Modal>
); );

View File

@ -4,8 +4,6 @@ import { ViewLargerImageModal, WarningRecordCard, IRecord, useViewLargerImageMod
import { Space } from 'antd'; import { Space } from 'antd';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
// 结合预警图列表 演示查看预警大图的使用 例如 后端返回这样的数据结构 // 结合预警图列表 演示查看预警大图的使用 例如 后端返回这样的数据结构
const backEndData = [ const backEndData = [
{ {
@ -41,7 +39,7 @@ const dataSource = backEndData.map(o => {
boxId: o.boxId, boxId: o.boxId,
position: o.position, position: o.position,
cabietId: o.cabietId, cabietId: o.cabietId,
//,`柜子ID: ${o.cabietId}` //,`柜子ID ${o.cabietId}`
warningInfo: [`盒子${o.boxId}`, `位置${o.position}`], warningInfo: [`盒子${o.boxId}`, `位置${o.position}`],
cabietText: `柜子ID: ${o.cabietId}`, cabietText: `柜子ID: ${o.cabietId}`,
warningTimestamp: o.warningTimestamp, warningTimestamp: o.warningTimestamp,
@ -52,6 +50,8 @@ const dataSource = backEndData.map(o => {
export default () => { export default () => {
const [selectedRecordId, setSelectedRecordId] = React.useState<string | undefined>()
// 把弹窗的ref 拿出来 // 把弹窗的ref 拿出来
const viewLargerImageModalRef = useViewLargerImageModal() const viewLargerImageModalRef = useViewLargerImageModal()
@ -76,18 +76,19 @@ export default () => {
] ]
// 调用这个方法打开弹框 // 调用这个方法打开弹框
viewLargerImageModalRef?.current?.show({ imgSrc: imgSrc, warningData: warningData }) viewLargerImageModalRef?.current?.show({ imgSrc: imgSrc, warningData: warningData })
setSelectedRecordId(record?.id)
} }
return ( return (
<> <>
<Space size={[8, 16]} > <Space size={[8, 16]} >
{ {
dataSource?.map((record) => <WarningRecordCard key={record?.id} record={record} onRecordClick={(record) => { handleClick(record) }} />) dataSource?.map((record) => <WarningRecordCard key={record?.id} record={record} onRecordClick={(record) => { handleClick(record) }} selectedRecordId={selectedRecordId} />)
} }
</Space> </Space>
{/* 弹窗 绑定ref 后可以调用 handleCancel方法关闭弹窗 show方法打开弹窗 */} {/* 弹窗 绑定ref 后可以调用 handleCancel方法关闭弹窗 show方法打开弹窗 */}
<ViewLargerImageModal ref={viewLargerImageModalRef} downloadImg={handleDownloadImg} title="预警大图" /> <ViewLargerImageModal ref={viewLargerImageModalRef} downloadImg={handleDownloadImg} title="预警大图" />
</> </>
) )
} }

View File

@ -1,3 +1,4 @@
import ViewLargerImageModal,{useViewLargerImageModal } from './ViewLargerImageModal' import ViewLargerImageModal, { useViewLargerImageModal } from './ViewLargerImageModal'
export type { ViewLargerImageModalRef, ViewLargerImageModalProps } from './ViewLargerImageModal'
export default ViewLargerImageModal; export default ViewLargerImageModal;
export { useViewLargerImageModal }; export { useViewLargerImageModal };

View File

@ -1,10 +1,8 @@
import { Card, Space, Divider, CardProps } from 'antd'; import { Card, Space, Divider, CardProps } from 'antd';
import { theme } from 'antd/lib';
import React from 'react'; import React from 'react';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import './index.less' import './index.less'
const componentName = `zhst-biz-warning-record-card`;
export interface IRecord { export interface IRecord {
imgSrc?: string; imgSrc?: string;
@ -59,14 +57,26 @@ export interface WarningRecordCardProps {
onRecordClick?: (record?: IRecord) => void; onRecordClick?: (record?: IRecord) => void;
style?: React.CSSProperties; style?: React.CSSProperties;
cardProps?: CardProps; cardProps?: CardProps;
selectedRecordId?: string;
cardStyle?: React.CSSProperties;
imgStyle?: React.CSSProperties;
}; };
export const WarningRecordCard: React.FC<WarningRecordCardProps> = (props) => { export const WarningRecordCard: React.FC<WarningRecordCardProps> = (props) => {
const { record, onRecordClick, style, cardProps } = props; const componentName = `zhst-biz-warning-record-card`;
const { record, onRecordClick, style, cardProps, selectedRecordId, cardStyle, imgStyle } = props;
const { imgSrc, id, warningType, warningInfo = [], cabietText, warningTime, warningTimestamp, warningTimeFormat = 'YYYY-MM-DD HH:mm:ss' } = record || {} const { imgSrc, id, warningType, warningInfo = [], cabietText, warningTime, warningTimestamp, warningTimeFormat = 'YYYY-MM-DD HH:mm:ss' } = record || {}
const formattedDate = warningTimestamp ? dayjs(warningTimestamp).format(warningTimeFormat) : ''; const formattedDate = warningTimestamp ? dayjs(warningTimestamp).format(warningTimeFormat) : '';
const warningTimeShow = warningTime ? warningTime : formattedDate const warningTimeShow = warningTime ? warningTime : formattedDate
const { useToken } = theme
const { token } = useToken()
const selectedBorderStyle = {
border: `2px solid ${token.colorPrimary}`, boxShadow: " 0px 2px 9px 0px rgba(0,0,0,0.16)"
}
const selectedCardStyle: React.CSSProperties = {
...(selectedRecordId === record?.id ? selectedBorderStyle : {})
};
const handleClick = () => { const handleClick = () => {
onRecordClick?.(record); onRecordClick?.(record);
@ -74,15 +84,13 @@ export const WarningRecordCard: React.FC<WarningRecordCardProps> = (props) => {
return ( return (
<div className={componentName} key={id} onClick={handleClick} style={style}> <div className={componentName} key={id} onClick={handleClick} style={style}>
<Card <Card
cover={<img alt="预警图" src={imgSrc} style={{ width: 336, height: 203, borderRadius: 0 }} />} cover={<img alt="预警图" src={imgSrc} style={{ width: 336, height: 203, borderRadius: 0, ...imgStyle }} />}
style={{ width: 356, height: 302, padding: 10, borderRadius: 4 }} style={{ width: 356, height: 302, padding: 10, borderRadius: 4, ...selectedCardStyle, ...cardStyle }}
{...cardProps} {...cardProps}
> >
<div className='left-context'> <div className='left-context'>
<div className="description">{warningType}</div> <div className="warning-type">{warningType}</div>
<Space size={0} split={<Divider type="vertical" />}> <Space size={0} split={<Divider type="vertical" />}>
{warningInfo?.map((item, index) => ( {warningInfo?.map((item, index) => (
<div key={index} className="info-item"> <div key={index} className="info-item">
@ -92,9 +100,7 @@ export const WarningRecordCard: React.FC<WarningRecordCardProps> = (props) => {
</Space> </Space>
<div className='warning-time'>{warningTimeShow}</div> <div className='warning-time'>{warningTimeShow}</div>
</div> </div>
<div className='cabietInfo' >{cabietText}</div> <div className='cabietInfo' >{cabietText}</div>
</Card> </Card>
</div> </div>
); );

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import { WarningRecordCard, type IRecord } from '@zhst/biz'; import { WarningRecordCard } from '@zhst/biz';
import { Space } from 'antd'; import { Space } from 'antd';
// 例如 后端返回这样的数据结构 // 例如 后端返回这样的数据结构
@ -38,13 +38,14 @@ const dataSource = backEndData.map(o => {
boxId: o.boxId, boxId: o.boxId,
position: o.position, position: o.position,
cabietId: o.cabietId, cabietId: o.cabietId,
warningInfo: [`盒子${o.boxId}`, `位置${o.position}`, `柜子ID: ${o.cabietId}`], warningInfo: [`盒子${o.boxId}`, `位置${o.position}`, `柜子ID${o.cabietId}`],
// cabietText: `柜子ID: ${o.cabietId}`, // cabietText: `柜子ID: ${o.cabietId}`,
warningTimestamp: o.warningTimestamp, warningTimestamp: o.warningTimestamp,
} }
}) })
export default () => { export default () => {
return ( return (
<Space size={[8, 16]} direction="vertical"> <Space size={[8, 16]} direction="vertical">
{ {

View File

@ -1,27 +1,27 @@
.zhst-biz-warning-record-card { .zhst-biz-warning-record-card {
cursor: pointer; cursor: pointer;
.ant-card-body { .ant-card-body {
padding: 0; padding: 0;
font-family: MicrosoftYaHei; font-family: MicrosoftYaHei;
line-height: 19px; line-height: 19px;
display: flex; display: flex;
margin-top: 10px; margin-top: 10px;
.left-context { .left-context {
flex: 1; flex: 1;
>div { >div {
margin-top: 6px; margin-top: 6px;
}
>div:nth-child(1) {
margin-top: 0;
}
} }
>div:nth-child(1) { .warning-type {
margin-top: 0; font-weight: bold;
} }
} }
.description {
font-weight: bold;
}
}
} }

View File

@ -6,6 +6,7 @@ export { default as TreeTransfer } from './treeTransfer'
export { default as TreeTransferModal } from './treeTransferModal' export { default as TreeTransferModal } from './treeTransferModal'
export { default as WarningRecordCard } from './WarningRecordCard' export { default as WarningRecordCard } from './WarningRecordCard'
export type { IRecord, WarningRecordCardProps } from './WarningRecordCard' export type { IRecord, WarningRecordCardProps } from './WarningRecordCard'
export type { ViewLargerImageModalRef, ViewLargerImageModalProps } from './ViewLargerImageModal'
export { default as ViewLargerImageModal, useViewLargerImageModal } from './ViewLargerImageModal' export { default as ViewLargerImageModal, useViewLargerImageModal } from './ViewLargerImageModal'
export type { VideoPlayerCardProps } from './VideoPlayerCard' export type { VideoPlayerCardProps } from './VideoPlayerCard'
export { default as VideoPlayerCard } from './VideoPlayerCard' export { default as VideoPlayerCard } from './VideoPlayerCard'