feat: 视频分析模块开发
parent
43c86f77a0
commit
f3357251d0
@ -0,0 +1,104 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Image, Popover, Button, message } from 'antd';
|
||||||
|
import { CloseCircleOutlined, EllipsisOutlined } from '@ant-design/icons';
|
||||||
|
import { useIntl } from '@umijs/max';
|
||||||
|
import { postRecognition } from '@/services/alarm/Involved';
|
||||||
|
|
||||||
|
interface ImageWithPopoverProps {
|
||||||
|
src: string;
|
||||||
|
reload: any;
|
||||||
|
person_id: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ImageWithPopover: React.FC<ImageWithPopoverProps> = ({ src, person_id,reload }) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
|
const content = (
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'center',alignItems: 'center', height: '100%'}}>
|
||||||
|
{/* <div>选项1</div>
|
||||||
|
<div>选项2</div> */}
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
style={{ height:22, padding: 0,fontSize: 12,color: '#FFF' }}
|
||||||
|
icon={<CloseCircleOutlined style={{ color: '#E80D0D',fontSize: 12}} />}
|
||||||
|
onClick={(event)=>{
|
||||||
|
event.stopPropagation();
|
||||||
|
postRecognition({
|
||||||
|
person_id: person_id,
|
||||||
|
classify: '0'
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
message.success('此人已被移除重点关注');
|
||||||
|
reload();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
|
||||||
|
});
|
||||||
|
setOpen(false)
|
||||||
|
}}
|
||||||
|
>移除重点关注</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
const handleVisibleChange = (value: boolean) => {
|
||||||
|
setVisible(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOpenChange = (value: boolean) => {
|
||||||
|
setOpen(value);
|
||||||
|
};
|
||||||
|
const handleButtonClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
|
event.stopPropagation(); // 阻止事件冒泡到父组件并阻止默认事件触发
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ position: 'relative', boxSizing: 'border-box', width: 96, height: 96 }}>
|
||||||
|
<Image
|
||||||
|
style={{ borderRadius: 4 }}
|
||||||
|
width={96}
|
||||||
|
height={96}
|
||||||
|
preview={false}
|
||||||
|
src={src}
|
||||||
|
/>
|
||||||
|
<Popover
|
||||||
|
placement="right"
|
||||||
|
content={content}
|
||||||
|
trigger="click"
|
||||||
|
style={{ width: 104, height: 32 }}
|
||||||
|
color="rgba(0, 0, 0, 0.6)"
|
||||||
|
overlayInnerStyle={{ width: 104, height: 32, padding: 4, borderRadius: 2 }}
|
||||||
|
open={open}
|
||||||
|
onOpenChange={handleOpenChange}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
style={{ position: 'absolute', bottom: 0, right: -4 }}
|
||||||
|
type="text"
|
||||||
|
icon={<EllipsisOutlined style={{ color: '#fff', fontSize: 24, transform: 'rotate(90deg)' }} />}
|
||||||
|
onClick={handleButtonClick}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
{/* {involved.state && (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
right: 0,
|
||||||
|
width: 64,
|
||||||
|
height: 24,
|
||||||
|
background: '#FAAD14',
|
||||||
|
borderRadius: '0px 4px 0px 4px',
|
||||||
|
color: '#FFF',
|
||||||
|
fontSize: 12,
|
||||||
|
textAlign: 'center',
|
||||||
|
lineHeight: '24px'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
重点关注
|
||||||
|
</div>
|
||||||
|
)} */}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ImageWithPopover;
|
@ -0,0 +1,26 @@
|
|||||||
|
.InvolvedImgBox {
|
||||||
|
box-sizing: border-box;
|
||||||
|
// display: flex;
|
||||||
|
// justify-content: flex-start;
|
||||||
|
padding: 16px 32px;
|
||||||
|
border-top: 1px solid #E0E0E0;
|
||||||
|
.involvedImgList {
|
||||||
|
position: relative;
|
||||||
|
span {
|
||||||
|
position: absolute;
|
||||||
|
width: 2px;
|
||||||
|
height: 30px;
|
||||||
|
bottom: -30px;
|
||||||
|
left: 15px;
|
||||||
|
border-left: 2px dashed #081FA8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.myButtonDisabled{
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
.involvedModalForm {
|
||||||
|
.ant-modal .ant-modal-content {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,304 @@
|
|||||||
|
import { putDeviceCategoryUpdateDeviceCategory } from '@/services/device/DeviceCategory';
|
||||||
|
import { postDeviceGroupGetDeviceGroupFkSelect } from '@/services/device/DeviceGroup';
|
||||||
|
import { ModalForm, ProForm, ProFormFieldSet, ProFormSelect, ProFormSwitch, ProFormText } from '@ant-design/pro-components';
|
||||||
|
import { FormattedMessage, useIntl } from '@umijs/max';
|
||||||
|
import { Form, message,Image, Button, Popover, List, Avatar } from 'antd';
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { getUploadInvolvedTravelList, postUploadRecognition } from '@/services/alarm/Involved';
|
||||||
|
import styles from './InvolvedDetails.less'
|
||||||
|
import './InvolvedDetails.less'
|
||||||
|
import moment from 'moment';
|
||||||
|
import { CloseCircleOutlined, EllipsisOutlined } from '@ant-design/icons';
|
||||||
|
import VirtualList from 'rc-virtual-list';
|
||||||
|
import trajectoryBottom from '../../../../../public/images/involved/trajectoryBottom.png'
|
||||||
|
export type FormValueType = {
|
||||||
|
target?: string;
|
||||||
|
template?: string;
|
||||||
|
type?: string;
|
||||||
|
time?: string;
|
||||||
|
frequency?: string;
|
||||||
|
} & Partial<API.InvolvedDetailsParams>;
|
||||||
|
|
||||||
|
export type UpdateFormProps = {
|
||||||
|
updateModalOpen: boolean;
|
||||||
|
handleModal: () => void;
|
||||||
|
values: Partial<API.InvolvedDetailsParams>;
|
||||||
|
reload: any;
|
||||||
|
};
|
||||||
|
const InvolvedDetails: React.FC<UpdateFormProps> = (props) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const [form] = Form.useForm<API.InvolvedDetailsParams>();
|
||||||
|
const [dataFlag, setDataFlag] = useState(false);;
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const [trajectoryData, setTrajectoryData] = useState([]);
|
||||||
|
// 动态设置每页数量
|
||||||
|
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
|
||||||
|
const [currentPage, setCurrentPage] = useState<number>(1);
|
||||||
|
const [total, setTotal] = useState<number>(0);
|
||||||
|
const ContainerHeight = 630;
|
||||||
|
const content = (
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'center',alignItems: 'center', height: '100%'}}>
|
||||||
|
{/* <div>选项1</div>
|
||||||
|
<div>选项2</div> */}
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
style={{ height:22, padding: 0,fontSize: 12,color: '#FFF' }}
|
||||||
|
icon={<CloseCircleOutlined style={{ color: '#E80D0D',fontSize: 12}} />}
|
||||||
|
onClick={(event)=>{
|
||||||
|
event.stopPropagation();
|
||||||
|
postUploadRecognition({
|
||||||
|
person_id: props.values.person_id,
|
||||||
|
classify: '0'
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
message.success('此人已被移除重点关注');
|
||||||
|
props.reload();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
|
||||||
|
});
|
||||||
|
setOpen(false)
|
||||||
|
props.handleModal()
|
||||||
|
}}
|
||||||
|
>移除重点关注</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
const handleOpenChange = (value: boolean) => {
|
||||||
|
setOpen(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const appendData = (page: any, pageSize: any) => {
|
||||||
|
const reqParams = {
|
||||||
|
page: page,
|
||||||
|
pageSize: pageSize,
|
||||||
|
// desc: false,
|
||||||
|
person_id: props.values.person_id,
|
||||||
|
// ...rest,
|
||||||
|
};
|
||||||
|
getUploadInvolvedTravelList(reqParams).then((res) => {
|
||||||
|
console.log(res);
|
||||||
|
if(res.data.results) {
|
||||||
|
setTrajectoryData(trajectoryData.concat(res.data.results));
|
||||||
|
setTotal(res.data.count)
|
||||||
|
if(res.data.next) {
|
||||||
|
setDataFlag(true)
|
||||||
|
}else {
|
||||||
|
setDataFlag(false)
|
||||||
|
// setTrajectoryData([]); // 重置trajectoryData数据为空数组
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
// setLoading(false);
|
||||||
|
setDataFlag(false)
|
||||||
|
// setTrajectoryData([]); // 重置trajectoryData数据为空数组
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const onScroll = (e: React.UIEvent<HTMLElement, UIEvent>) => {
|
||||||
|
// Refer to: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#problems_and_solutions
|
||||||
|
console.log(e.currentTarget.scrollHeight - e.currentTarget.scrollTop - ContainerHeight);
|
||||||
|
|
||||||
|
if (Math.abs(e.currentTarget.scrollHeight - e.currentTarget.scrollTop - ContainerHeight) <= 1) {
|
||||||
|
if(dataFlag) {
|
||||||
|
const nextPage = currentPage + 1
|
||||||
|
setCurrentPage(nextPage);
|
||||||
|
appendData(nextPage, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
if (props.updateModalOpen) {
|
||||||
|
// 调用接口获取数据
|
||||||
|
setTrajectoryData([]); // 重置trajectoryData数据为空数组
|
||||||
|
setCurrentPage(1);
|
||||||
|
setCurrentPageSize(10);
|
||||||
|
appendData(currentPage, currentPageSize);
|
||||||
|
}
|
||||||
|
}, [props.updateModalOpen]);
|
||||||
|
return (
|
||||||
|
<ModalForm<any>
|
||||||
|
width={615}
|
||||||
|
title={
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
padding: '24px 32px 0px',
|
||||||
|
justifyContent: 'flex-start',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ position: 'relative', boxSizing: 'border-box', width: 120, height: 120 }}>
|
||||||
|
<Image
|
||||||
|
style={{ borderRadius: 4 }}
|
||||||
|
width={120}
|
||||||
|
height={120}
|
||||||
|
preview={false}
|
||||||
|
src={props?.values?.picture_path}
|
||||||
|
/>
|
||||||
|
<Popover
|
||||||
|
placement="right"
|
||||||
|
content={content}
|
||||||
|
trigger="click"
|
||||||
|
style={{ width: 104, height: 32 }}
|
||||||
|
color="rgba(0, 0, 0, 0.6)"
|
||||||
|
overlayInnerStyle={{ width: 104, height: 32, padding: 4, borderRadius: 2 }}
|
||||||
|
open={open}
|
||||||
|
onOpenChange={handleOpenChange}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
style={{ position: 'absolute', bottom: 0, right: -4 }}
|
||||||
|
type="text"
|
||||||
|
icon={<EllipsisOutlined style={{ color: '#fff', fontSize: 24, transform: 'rotate(90deg)' }} />}
|
||||||
|
// onClick={handleButtonClick}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
right: 0,
|
||||||
|
width: 64,
|
||||||
|
height: 24,
|
||||||
|
background: '#FAAD14',
|
||||||
|
borderRadius: '0px 4px 0px 4px',
|
||||||
|
color: '#FFF',
|
||||||
|
fontSize: 12,
|
||||||
|
textAlign: 'center',
|
||||||
|
lineHeight: '24px',
|
||||||
|
fontWeight: 400
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
重点关注
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
marginLeft: 12,
|
||||||
|
height: 98,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
justifyContent: 'flex-start',
|
||||||
|
color: '#666',
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: 400
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
关注时间:{' '}
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
color: '#333',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{moment(props?.values?.classify_time).format('YYYY-MM-DD hh:mm:ss')}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
最近发现:{' '}
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
color: '#333',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{moment(props?.values?.appear_time).format('YYYY-MM-DD hh:mm:ss')}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{/* <div>
|
||||||
|
来源设备:{' '}
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
color: '#333',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{props?.values?.device_name}
|
||||||
|
</span>
|
||||||
|
</div> */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
open={props.updateModalOpen}
|
||||||
|
form={form}
|
||||||
|
autoFocusFirstInput
|
||||||
|
modalProps={{
|
||||||
|
destroyOnClose: true,
|
||||||
|
onCancel: () => {
|
||||||
|
setTrajectoryData([]);
|
||||||
|
setCurrentPage(1);
|
||||||
|
setCurrentPageSize(10);
|
||||||
|
props.handleModal()
|
||||||
|
},
|
||||||
|
wrapClassName:"involvedModalForm"
|
||||||
|
}}
|
||||||
|
submitter={false}
|
||||||
|
submitTimeout={2000}
|
||||||
|
onFinish={async (values) => {
|
||||||
|
values.is_ignore = true
|
||||||
|
values.person_id = props.values.person_id
|
||||||
|
// console.log(values);
|
||||||
|
// postIgnoringvents(values)
|
||||||
|
// .then(() => {
|
||||||
|
// message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
|
||||||
|
// props.reload();
|
||||||
|
// })
|
||||||
|
// .catch(() => {
|
||||||
|
// message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
|
||||||
|
// });
|
||||||
|
setTrajectoryData([]);
|
||||||
|
setCurrentPage(1);
|
||||||
|
setCurrentPageSize(10);
|
||||||
|
props.handleModal();
|
||||||
|
return true;
|
||||||
|
}}
|
||||||
|
|
||||||
|
>
|
||||||
|
{/* <ProForm.Group> */}
|
||||||
|
{/* <div className={styles.alarmDetails}>
|
||||||
|
告警名称: <span className={styles.alarmSpan}>单人徘徊告警</span>来源设备: <span className={styles.alarmSpan}>北广场检票口1#摄像头</span>触发时间: <span className={styles.alarmSpan}>2023-01-15 22:00:03</span>
|
||||||
|
</div> */}
|
||||||
|
<div className={styles.InvolvedImgBox}>
|
||||||
|
<List>
|
||||||
|
<VirtualList
|
||||||
|
data={trajectoryData}
|
||||||
|
height={ContainerHeight}
|
||||||
|
itemHeight={64}
|
||||||
|
itemKey="id"
|
||||||
|
onScroll={onScroll}
|
||||||
|
>
|
||||||
|
{(item: any, index:any) => (
|
||||||
|
<div key={item.person_id + index}>
|
||||||
|
<List.Item style={{ borderBottom: 0, height: 64, padding: 0 }}>
|
||||||
|
<List.Item.Meta
|
||||||
|
avatar={
|
||||||
|
<div className={styles.involvedImgList}>
|
||||||
|
<img style={{ width: 32, height: 32 }} src={trajectoryBottom} />
|
||||||
|
{index + 1 !== total && <span />}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
title={<div style={{ lineHeight: '30px', color: '#666' }}>时间定位: <span style={{ color: '#333', marginRight: 16}}>{moment(item.appear_time).format('YYYY-MM-DD hh:mm:ss')}</span> 来源视频: <span style={{ color: '#333'}}>{item.video_name}</span></div>}
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<Image
|
||||||
|
style={{ borderRadius: 4 }}
|
||||||
|
width={48}
|
||||||
|
height={48}
|
||||||
|
preview={{
|
||||||
|
mask: '',
|
||||||
|
}}
|
||||||
|
src={item.picture_path}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</List.Item>
|
||||||
|
{index === total - 1 && (
|
||||||
|
<div style={{ textAlign: 'center', color: '#999' }}>已无更多数据~</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</VirtualList>
|
||||||
|
</List>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* </ProForm.Group> */}
|
||||||
|
</ModalForm>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default InvolvedDetails;
|
@ -0,0 +1,58 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Button, Tag, message } from 'antd';
|
||||||
|
import { RedoOutlined } from '@ant-design/icons';
|
||||||
|
import { postTestDevice } from '@/services/alarm/Interfaces'
|
||||||
|
import moment from 'moment';
|
||||||
|
import { useIntl } from '@umijs/max';
|
||||||
|
|
||||||
|
|
||||||
|
interface ImageSinglePopoverProps {
|
||||||
|
values: any;
|
||||||
|
reload: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CaptureButton: React.FC<ImageSinglePopoverProps> = (props) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
const connection = () => {
|
||||||
|
setLoading(true);
|
||||||
|
postTestDevice({
|
||||||
|
device_ip: props.values.device_ip,
|
||||||
|
id: props.values.id,
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if(res.success) {
|
||||||
|
message.success(res.msg);
|
||||||
|
}
|
||||||
|
props.reload();
|
||||||
|
setLoading(false);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
|
||||||
|
setLoading(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Tag bordered={false} color={props.values.test_result === 1? "success": ""} style={{
|
||||||
|
// fontSize:14,
|
||||||
|
color: props.values.test_result === 1? '#52C41A': "#999"
|
||||||
|
}}>
|
||||||
|
{props.values.test_result === 1 ? '在线' : '离线'}
|
||||||
|
</Tag>
|
||||||
|
<span>{moment(props.values.test_time).format('YYYY-MM-DD hh:mm:ss')}</span>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
icon={<RedoOutlined />}
|
||||||
|
loading={loading}
|
||||||
|
onClick={() => {
|
||||||
|
connection()
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CaptureButton;
|
@ -0,0 +1,24 @@
|
|||||||
|
.captureImgBox {
|
||||||
|
.captureImgDescribe {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
font-family: PingFang SC;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #666;
|
||||||
|
span {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.captureImgContent {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
padding: 16px;
|
||||||
|
width: 100%;
|
||||||
|
// height: 172px;
|
||||||
|
background: #F7F7F7;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px dashed #DCDCDC;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
import { postInterfaces, postTestDevice } from '@/services/alarm/Interfaces';
|
||||||
|
import { ModalForm, ProForm, ProFormFieldSet, ProFormSelect, ProFormSwitch, ProFormText, ProFormTextArea } from '@ant-design/pro-components';
|
||||||
|
import { FormattedMessage, useIntl } from '@umijs/max';
|
||||||
|
import { Image, Form, message } from 'antd';
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import {
|
||||||
|
proFormSmallItemStyleProps,
|
||||||
|
proFormSmallModelWidth,
|
||||||
|
} from '../../../../../config/defaultForm';
|
||||||
|
import moment from 'moment';
|
||||||
|
import styles from './CaptureForm.less'
|
||||||
|
export type FormValueType = {
|
||||||
|
target?: string;
|
||||||
|
template?: string;
|
||||||
|
type?: string;
|
||||||
|
time?: string;
|
||||||
|
frequency?: string;
|
||||||
|
} & Partial<API.UpdateInterfacesParams>;
|
||||||
|
|
||||||
|
export type UpdateFormProps = {
|
||||||
|
captureModalOpen: boolean;
|
||||||
|
handleModal: () => void;
|
||||||
|
values: Partial<API.UpdateInterfacesParams>;
|
||||||
|
reload: any;
|
||||||
|
};
|
||||||
|
const CaptureForm: React.FC<UpdateFormProps> = (props) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const [form] = Form.useForm<API.UpdateInterfacesParams>();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalForm<any>
|
||||||
|
width={proFormSmallModelWidth}
|
||||||
|
title={intl.formatMessage({
|
||||||
|
id: 'device.interface_manage.table.list.capture',
|
||||||
|
defaultMessage: `最近拍摄`,
|
||||||
|
})}
|
||||||
|
open={props.captureModalOpen}
|
||||||
|
form={form}
|
||||||
|
autoFocusFirstInput
|
||||||
|
modalProps={{
|
||||||
|
destroyOnClose: true,
|
||||||
|
onCancel: () => {
|
||||||
|
props.handleModal()
|
||||||
|
},
|
||||||
|
// okText: intl.formatMessage({ id: 'common.okText', defaultMessage: '确认' }),
|
||||||
|
// cancelText: intl.formatMessage({ id: 'common.cancelText', defaultMessage: '取消' }),
|
||||||
|
}}
|
||||||
|
submitTimeout={2000}
|
||||||
|
submitter={false}
|
||||||
|
onFinish={async (values) => {
|
||||||
|
console.log(values);
|
||||||
|
values.id = props.values.id
|
||||||
|
postInterfaces(values)
|
||||||
|
.then(() => {
|
||||||
|
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
|
||||||
|
props.reload();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
|
||||||
|
});
|
||||||
|
|
||||||
|
props.handleModal();
|
||||||
|
return true;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className={styles.captureImgBox}>
|
||||||
|
<div className={styles.captureImgDescribe}>来源: <span>{props.values.device_name}</span></div>
|
||||||
|
<div className={styles.captureImgDescribe}>触发时间: <span>{moment(props.values.appear_time).format('YYYY-MM-DD hh:mm:ss')}</span></div>
|
||||||
|
<div className={styles.captureImgContent}>
|
||||||
|
<Image
|
||||||
|
width={100}
|
||||||
|
preview={false}
|
||||||
|
src={props.values.picture_path}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ModalForm>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default CaptureForm;
|
@ -0,0 +1,84 @@
|
|||||||
|
.alarmImgBox {
|
||||||
|
// display: flex;
|
||||||
|
// justify-content: flex-start;
|
||||||
|
.alarmImgLeft {
|
||||||
|
position: relative;
|
||||||
|
margin-right: 32px;
|
||||||
|
width: 120px;
|
||||||
|
// height: 600px;
|
||||||
|
.alarmImgLeftBox{
|
||||||
|
width: 112px;
|
||||||
|
height: 112px;
|
||||||
|
border-radius: 4px;
|
||||||
|
// background: skyblue;
|
||||||
|
}
|
||||||
|
.alarmImgLeftBoxActive {
|
||||||
|
width: 112px;
|
||||||
|
height: 112px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1.5px solid #081FA8;
|
||||||
|
}
|
||||||
|
.shadowBox {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0px;
|
||||||
|
width: 112px;
|
||||||
|
height: 20px;
|
||||||
|
background: #FFF;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.alarmImgRight{
|
||||||
|
flex: 1;
|
||||||
|
position: relative;
|
||||||
|
.alarmImgRightTopBox {
|
||||||
|
width: 640px;
|
||||||
|
height: 640px;
|
||||||
|
background: skyblue;
|
||||||
|
}
|
||||||
|
.alarmDetails {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 38px;
|
||||||
|
padding-left: 24px;
|
||||||
|
line-height: 38px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
font-family: PingFang SC;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #FFFFFF;
|
||||||
|
background: rgba(0, 0, 0, 0.6);
|
||||||
|
.alarmSpan {
|
||||||
|
// color: #333;
|
||||||
|
margin-right: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.alarmImgDescribe {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
font-family: PingFang SC;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #666;
|
||||||
|
span {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.alarmImgContent {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
padding: 16px;
|
||||||
|
width: 784px;
|
||||||
|
// height: 172px;
|
||||||
|
background: #F7F7F7;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px dashed #DCDCDC;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.myButtonDisabled{
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
@ -0,0 +1,305 @@
|
|||||||
|
|
||||||
|
import { ModalForm, ProForm, ProFormFieldSet, ProFormSelect, ProFormSwitch, ProFormText } from '@ant-design/pro-components';
|
||||||
|
import { FormattedMessage, useIntl } from '@umijs/max';
|
||||||
|
import { Form, message,Image, Button, Popover } from 'antd';
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { postIgnoringvents } from '@/services/alarm/Alarmlist';
|
||||||
|
import { postUploadRecognition } from '@/services/alarm/Involved';
|
||||||
|
// Import Swiper React components
|
||||||
|
// import { Swiper, SwiperSlide } from 'swiper/react';
|
||||||
|
// import { Navigation, Pagination, Mousewheel } from 'swiper/modules';
|
||||||
|
// Import Swiper styles
|
||||||
|
import 'swiper/css';
|
||||||
|
import 'swiper/css/navigation';
|
||||||
|
import 'swiper/css/pagination';
|
||||||
|
import styles from './AlarmDetails.less'
|
||||||
|
import moment from 'moment';
|
||||||
|
import ImageWithPopover from './ImageWithPopover';
|
||||||
|
import ImageSinglePopover from './ImageSinglePopover';
|
||||||
|
export type FormValueType = {
|
||||||
|
target?: string;
|
||||||
|
template?: string;
|
||||||
|
type?: string;
|
||||||
|
time?: string;
|
||||||
|
frequency?: string;
|
||||||
|
} & Partial<API.AlarmDetailsParams>;
|
||||||
|
|
||||||
|
export type UpdateFormProps = {
|
||||||
|
updateModalOpen: boolean;
|
||||||
|
handleModal: () => void;
|
||||||
|
values: Partial<API.AlarmDetailsParams>;
|
||||||
|
reload: any;
|
||||||
|
warning_type: any;
|
||||||
|
};
|
||||||
|
const UpdateForm: React.FC<UpdateFormProps> = (props) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const [form] = Form.useForm<API.AlarmDetailsParams>();
|
||||||
|
// const [isActive, setIsActive] = useState(0);
|
||||||
|
const [imageSrc, setImageSrc] = useState('');
|
||||||
|
// const [visible, setVisible] = useState(false);
|
||||||
|
const [involved, setInvolved] = useState(0);
|
||||||
|
// const [involvedInfo, setInvolvedInfo] = useState([...(props?.values?.person_list || [])]);
|
||||||
|
const [involvedInfo, setInvolvedInfo] = useState<any[]>([]);
|
||||||
|
// useEffect(() => {
|
||||||
|
// if (props.values?.person_list) {
|
||||||
|
// setInvolvedInfo([...props.values.person_list]);
|
||||||
|
// }
|
||||||
|
// }, [props.values?.person_list]);
|
||||||
|
// console.log(object);
|
||||||
|
// if(props.warning_type === '1') {
|
||||||
|
// console.log('props.values?.warning_type1');
|
||||||
|
// setInvolved(props.values.person_list[0][2]);
|
||||||
|
// }else {
|
||||||
|
// console.log('props.values?.warning_type2');
|
||||||
|
// // setInvolvedInfo([...props.values.person_list]);
|
||||||
|
// }
|
||||||
|
const handlePostRecognition = (person_id: any, classify: any) => {
|
||||||
|
postUploadRecognition({
|
||||||
|
person_id: person_id,
|
||||||
|
classify: classify
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
console.log(res.data.classify,'res.data.classify');
|
||||||
|
if(res.data.classify === 1) {
|
||||||
|
message.success('此人已被设为重点关注');
|
||||||
|
}else {
|
||||||
|
message.success('此人已被移除重点关注');
|
||||||
|
}
|
||||||
|
props.reload();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
/** 多人告警组件 */
|
||||||
|
const handleInvolved = (value: any, index: any) => {
|
||||||
|
const updatedInvolvedInfo = [...involvedInfo];
|
||||||
|
console.log(updatedInvolvedInfo);
|
||||||
|
updatedInvolvedInfo[index][2] = value;
|
||||||
|
setInvolvedInfo(updatedInvolvedInfo);
|
||||||
|
handlePostRecognition(updatedInvolvedInfo[index][0], value)
|
||||||
|
};
|
||||||
|
/** 单人告警组件 */
|
||||||
|
// const handleSingleInvolved = () => {
|
||||||
|
// if (involved === 1) {
|
||||||
|
// setInvolved(0);
|
||||||
|
// handlePostRecognition(props.values?.person_id, 0)
|
||||||
|
// } else {
|
||||||
|
// setInvolved(1);
|
||||||
|
// handlePostRecognition(props.values?.person_id, 1)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const [open, setOpen] = useState(false);
|
||||||
|
useEffect(() => {
|
||||||
|
// console.log(Array.isArray(props.values?.person_id),'Array.isArray(props.values?.person_id)');
|
||||||
|
// setImageSrc(props?.values?.picture_path?.[0])
|
||||||
|
if(props.updateModalOpen) {
|
||||||
|
if(props.warning_type === '1') {
|
||||||
|
console.log('props.values?.warning_type1');
|
||||||
|
setInvolved(props.values.person_list[0][2]);
|
||||||
|
}else {
|
||||||
|
console.log('props.values?.warning_type2');
|
||||||
|
setInvolvedInfo([...props.values.person_list]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [props.updateModalOpen])
|
||||||
|
return (
|
||||||
|
<ModalForm<any>
|
||||||
|
width={832}
|
||||||
|
title={`${props.values.warning_name}告警`}
|
||||||
|
open={props.updateModalOpen}
|
||||||
|
form={form}
|
||||||
|
autoFocusFirstInput
|
||||||
|
modalProps={{
|
||||||
|
destroyOnClose: true,
|
||||||
|
onCancel: () => {
|
||||||
|
setInvolved(0);
|
||||||
|
props.handleModal()
|
||||||
|
},
|
||||||
|
okText: intl.formatMessage({ id: 'common.yes', defaultMessage: '确认' }),
|
||||||
|
cancelText: intl.formatMessage({ id: 'common.no', defaultMessage: '取消' }),
|
||||||
|
}}
|
||||||
|
|
||||||
|
submitter={{
|
||||||
|
// resetButtonProps: {
|
||||||
|
// style: {
|
||||||
|
// display: 'none',
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// searchConfig: {
|
||||||
|
// submitText: '忽略此事件',
|
||||||
|
// },
|
||||||
|
render: (prop) => {
|
||||||
|
return [
|
||||||
|
<Button
|
||||||
|
key="ok"
|
||||||
|
style={{ backgroundColor: '#E80D0D',color: '#FFF',borderBlockColor: '#E80D0D' }}
|
||||||
|
onClick={() => {
|
||||||
|
prop.submit();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
忽略此事件
|
||||||
|
</Button>,
|
||||||
|
props.warning_type === '2' ? null : (
|
||||||
|
<Button
|
||||||
|
key="involved"
|
||||||
|
style={{ backgroundColor: '#FAAD14',color: '#FFF',borderBlockColor: '#FAAD14' }}
|
||||||
|
onClick={() => {
|
||||||
|
// console.log(props.updateModalOpen);
|
||||||
|
setInvolved(1);
|
||||||
|
handlePostRecognition(props.values?.person_list[0][0], 1)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
加入重点关注
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
props.warning_type === '2' ? null : (
|
||||||
|
<Button
|
||||||
|
key="noInvolved"
|
||||||
|
style={{ background: '#FFF',color: '#E80D0D',borderColor: '#E80D0D' }}
|
||||||
|
onClick={() => {
|
||||||
|
// console.log(props.updateModalOpen);
|
||||||
|
setInvolved(0);
|
||||||
|
handlePostRecognition(props.values?.person_list[0][0], 0)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
移除重点关注
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
];
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
submitTimeout={2000}
|
||||||
|
onFinish={async (values) => {
|
||||||
|
values.is_ignore = true
|
||||||
|
values.person_id = props.values.person_id
|
||||||
|
// console.log(values);
|
||||||
|
postIgnoringvents(values)
|
||||||
|
.then(() => {
|
||||||
|
message.success(intl.formatMessage({ id: 'common.success', defaultMessage: '成功' }));
|
||||||
|
props.reload();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
message.error(intl.formatMessage({ id: 'common.failure', defaultMessage: '失败' }));
|
||||||
|
});
|
||||||
|
|
||||||
|
props.handleModal();
|
||||||
|
return true;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* <ProForm.Group> */}
|
||||||
|
<div className={styles.alarmImgBox}>
|
||||||
|
<div className={styles.alarmImgDescribe}>来源: <span>{props.values.origin}</span></div>
|
||||||
|
<div className={styles.alarmImgDescribe}>触发时间: <span className={styles.alarmSpan}>{moment(props.values.trigger_time).format('YYYY-MM-DD hh:mm:ss')}</span></div>
|
||||||
|
<div className={styles.alarmImgContent}>
|
||||||
|
{Array.isArray(props.values?.person_id_list)}
|
||||||
|
{props.warning_type === '2' ? (
|
||||||
|
Array.isArray(involvedInfo) && involvedInfo.length ? (
|
||||||
|
involvedInfo.map((item: any, index: any) => {
|
||||||
|
return (
|
||||||
|
<ImageWithPopover
|
||||||
|
src={item?.[1]}
|
||||||
|
involved={involvedInfo[index][2]}
|
||||||
|
key={index}
|
||||||
|
indexId={index}
|
||||||
|
handleInvolved={handleInvolved}
|
||||||
|
time={props.values.trigger_time}
|
||||||
|
></ImageWithPopover>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
) : (
|
||||||
|
Array.isArray(props?.values?.picture_path) && props?.values?.picture_path.length ? (
|
||||||
|
props.values.picture_path.map((item: any, index: any) => {
|
||||||
|
return (
|
||||||
|
<ImageSinglePopover
|
||||||
|
src={item}
|
||||||
|
involved={involved}
|
||||||
|
key={index}
|
||||||
|
// handleInvolved={handleSingleInvolved}
|
||||||
|
reload={props.reload} // 将reload方法作为prop传递给ImageSinglePopover组件
|
||||||
|
time={props.values.trigger_time}
|
||||||
|
></ImageSinglePopover>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
) : null
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
Array.isArray(props?.values?.picture_path) && props?.values?.picture_path.length ? (
|
||||||
|
props.values.picture_path.map((item: any, index: any) => {
|
||||||
|
return (
|
||||||
|
<ImageSinglePopover
|
||||||
|
src={item}
|
||||||
|
involved={involved}
|
||||||
|
key={index}
|
||||||
|
// handleInvolved={handleSingleInvolved}
|
||||||
|
reload={props.reload} // 将reload方法作为prop传递给ImageSinglePopover组件
|
||||||
|
time={props.values.trigger_time}
|
||||||
|
></ImageSinglePopover>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
) : null
|
||||||
|
)}
|
||||||
|
{/* { Array.isArray(involvedInfo) && involvedInfo.length && involvedInfo.map((item: any, index: any) => {
|
||||||
|
console.log(involvedInfo,'item');
|
||||||
|
return(<ImageWithPopover src={item?.[1]} involved={involvedInfo[index][2]} key={index} indexId={index} handleInvolved={handleInvolved}></ImageWithPopover>)
|
||||||
|
})} */}
|
||||||
|
</div>
|
||||||
|
{/* <div className={styles.alarmImgLeft}>
|
||||||
|
<Swiper
|
||||||
|
style={{height:660}}
|
||||||
|
slidesPerView={5}
|
||||||
|
spaceBetween={20}
|
||||||
|
direction='vertical'
|
||||||
|
mousewheel={true}
|
||||||
|
modules={[Mousewheel]}
|
||||||
|
onSlideChange={() => {
|
||||||
|
console.log(111);
|
||||||
|
}}
|
||||||
|
// pagination={{
|
||||||
|
// clickable: true,
|
||||||
|
// }}
|
||||||
|
// modules={[Pagination]}
|
||||||
|
>
|
||||||
|
{ Array.isArray(props?.values?.picture_path) && props?.values?.picture_path.length && props?.values?.picture_path.map((item: any, index: any) => {
|
||||||
|
return (<SwiperSlide key={index} virtualIndex={index} onClick={() => {
|
||||||
|
console.log(index);
|
||||||
|
setIsActive(index)
|
||||||
|
setImageSrc(item)
|
||||||
|
}}>
|
||||||
|
<div className={ styles.alarmImgLeftBox }>
|
||||||
|
<Image
|
||||||
|
style={{
|
||||||
|
width: 112,
|
||||||
|
height: 112,
|
||||||
|
borderRadius: 4
|
||||||
|
}}
|
||||||
|
className={ index === isActive ? styles.alarmImgLeftBoxActive : '' }
|
||||||
|
preview={false}
|
||||||
|
src={item}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</SwiperSlide>)
|
||||||
|
})}
|
||||||
|
</Swiper>
|
||||||
|
<div className={styles.shadowBox}></div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.alarmImgRight}>
|
||||||
|
<div className={styles.alarmImgRightTopBox}>
|
||||||
|
<Image
|
||||||
|
width={640}
|
||||||
|
height={640}
|
||||||
|
preview={false}
|
||||||
|
src={imageSrc}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={styles.alarmDetails}>
|
||||||
|
来源: <span className={styles.alarmSpan}>{props.values.device_name}</span>触发时间: <span className={styles.alarmSpan}>{moment(props.values.trigger_time).format('YYYY-MM-DD hh:mm:ss')}</span>
|
||||||
|
</div>
|
||||||
|
</div> */}
|
||||||
|
</div>
|
||||||
|
{/* </ProForm.Group> */}
|
||||||
|
</ModalForm>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default UpdateForm;
|
@ -0,0 +1,117 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Image } from 'antd';
|
||||||
|
import { EyeOutlined } from '@ant-design/icons';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
|
||||||
|
interface ImageSinglePopoverProps {
|
||||||
|
src: string;
|
||||||
|
involved: any;
|
||||||
|
// handleInvolved: () => void;
|
||||||
|
reload: any;
|
||||||
|
time: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ImageSinglePopover: React.FC<ImageSinglePopoverProps> = ({ src, involved, reload, time}) => {
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
// const [open, setOpen] = useState(false);
|
||||||
|
// 定义一个方法,用于生成自定义的遮罩层
|
||||||
|
const generateMask = (text:any) => (
|
||||||
|
<div style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff' }}>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', fontSize: 12 }}>
|
||||||
|
<EyeOutlined style={{ marginRight: 8, fontSize: 12 }} />
|
||||||
|
<div>{text}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
// const content = (
|
||||||
|
// <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center',alignItems: 'center', height: 56}}>
|
||||||
|
// {/* <div>选项1</div>
|
||||||
|
// <div>选项2</div> */}
|
||||||
|
// <Button
|
||||||
|
// type="text"
|
||||||
|
// style={{ height:22, padding: 0,fontSize: 12,color: '#FFF' }}
|
||||||
|
// icon={<InfoCircleOutlined style={{ color: '#FAAD14',fontSize: 12}} />}
|
||||||
|
// onClick={()=>{
|
||||||
|
// // setInvolved(true)
|
||||||
|
// // handleInvolved();
|
||||||
|
// // reload()
|
||||||
|
// setOpen(false)
|
||||||
|
// }}
|
||||||
|
// >加入重点关注</Button>
|
||||||
|
// <Button
|
||||||
|
// type="text"
|
||||||
|
// style={{ height:22, padding: 0,fontSize: 12,color: '#FFF' }}
|
||||||
|
// icon={<CloseCircleOutlined style={{ color: '#E80D0D',fontSize: 12}} />}
|
||||||
|
// onClick={()=>{
|
||||||
|
// // setInvolved(false)
|
||||||
|
// // handleInvolved();
|
||||||
|
// // reload()
|
||||||
|
// setOpen(false)
|
||||||
|
// }}
|
||||||
|
// >移除重点关注</Button>
|
||||||
|
// </div>
|
||||||
|
// );
|
||||||
|
const handleVisibleChange = (value: boolean) => {
|
||||||
|
setVisible(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
// const handleOpenChange = (value: boolean) => {
|
||||||
|
// setOpen(value);
|
||||||
|
// };
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ position: 'relative', boxSizing: 'border-box', width: 140, height: 160, marginRight: 12 }}>
|
||||||
|
<Image
|
||||||
|
style={{ borderRadius: 4 }}
|
||||||
|
width={140}
|
||||||
|
height={140}
|
||||||
|
preview={{
|
||||||
|
visible,
|
||||||
|
src,
|
||||||
|
onVisibleChange: handleVisibleChange,
|
||||||
|
mask: generateMask("点击可预览大图"),
|
||||||
|
}}
|
||||||
|
src={src}
|
||||||
|
/>
|
||||||
|
<div style={{height: 30,textAlign: 'center',lineHeight: '30px',fontWeight: 500,color: '#333'}}>{moment(time).format('YYYY-MM-DD hh:mm:ss')}</div>
|
||||||
|
{/* <Popover
|
||||||
|
placement="right"
|
||||||
|
content={content}
|
||||||
|
trigger="click"
|
||||||
|
style={{ width: 104, height: 64 }}
|
||||||
|
color="rgba(0, 0, 0, 0.6)"
|
||||||
|
overlayInnerStyle={{ width: 104, height: 64, padding: 4, borderRadius: 2 }}
|
||||||
|
open={open}
|
||||||
|
onOpenChange={handleOpenChange}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
style={{ position: 'absolute', bottom: 8, right: 0 }}
|
||||||
|
type="text"
|
||||||
|
icon={<EllipsisOutlined style={{ color: '#fff', fontSize: 24, transform: 'rotate(90deg)' }} />}
|
||||||
|
/>
|
||||||
|
</Popover> */}
|
||||||
|
{involved === 1 && (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
right: 0,
|
||||||
|
width: 64,
|
||||||
|
height: 24,
|
||||||
|
background: '#FAAD14',
|
||||||
|
borderRadius: '0px 4px 0px 4px',
|
||||||
|
color: '#FFF',
|
||||||
|
fontSize: 12,
|
||||||
|
textAlign: 'center',
|
||||||
|
lineHeight: '24px'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
重点关注
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ImageSinglePopover;
|
@ -0,0 +1,115 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Image, Popover, Button } from 'antd';
|
||||||
|
import { CloseCircleOutlined, EllipsisOutlined, EyeOutlined, InfoCircleOutlined } from '@ant-design/icons';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
interface ImageWithPopoverProps {
|
||||||
|
src: string;
|
||||||
|
involved: any;
|
||||||
|
indexId: any;
|
||||||
|
handleInvolved: (value: any,index: any) => void;
|
||||||
|
time: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ImageWithPopover: React.FC<ImageWithPopoverProps> = ({ src, involved, indexId, handleInvolved,time }) => {
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
|
// 定义一个方法,用于生成自定义的遮罩层
|
||||||
|
const generateMask = (text:any) => (
|
||||||
|
<div style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff' }}>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', fontSize: 12 }}>
|
||||||
|
<EyeOutlined style={{ marginRight: 8, fontSize: 12 }} />
|
||||||
|
<div>{text}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
const content = (
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center',alignItems: 'center', height: 56}}>
|
||||||
|
{/* <div>选项1</div>
|
||||||
|
<div>选项2</div> */}
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
style={{ height:22, padding: 0,fontSize: 12,color: '#FFF',marginBottom: 4 }}
|
||||||
|
icon={<InfoCircleOutlined style={{ color: '#FAAD14',fontSize: 12}} />}
|
||||||
|
onClick={()=>{
|
||||||
|
// setInvolved(true)
|
||||||
|
handleInvolved(1, indexId);
|
||||||
|
setOpen(false)
|
||||||
|
}}
|
||||||
|
>加入重点关注</Button>
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
style={{ height:22, padding: 0,fontSize: 12,color: '#FFF' }}
|
||||||
|
icon={<CloseCircleOutlined style={{ color: '#E80D0D',fontSize: 12}} />}
|
||||||
|
onClick={()=>{
|
||||||
|
// setInvolved(false)
|
||||||
|
handleInvolved(0, indexId);
|
||||||
|
setOpen(false)
|
||||||
|
}}
|
||||||
|
>移除重点关注</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
const handleVisibleChange = (value: boolean) => {
|
||||||
|
setVisible(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOpenChange = (value: boolean) => {
|
||||||
|
setOpen(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ position: 'relative', boxSizing: 'border-box', width: 140, height: 160, marginRight: 12 }}>
|
||||||
|
<Image
|
||||||
|
style={{ borderRadius: 4 }}
|
||||||
|
width={140}
|
||||||
|
height={140}
|
||||||
|
preview={{
|
||||||
|
visible,
|
||||||
|
src,
|
||||||
|
onVisibleChange: handleVisibleChange,
|
||||||
|
mask: generateMask("点击可预览大图"),
|
||||||
|
}}
|
||||||
|
src={src}
|
||||||
|
/>
|
||||||
|
<Popover
|
||||||
|
placement="right"
|
||||||
|
content={content}
|
||||||
|
trigger="click"
|
||||||
|
style={{ width: 104, height: 64 }}
|
||||||
|
color="rgba(0, 0, 0, 0.6)"
|
||||||
|
overlayInnerStyle={{ width: 104, height: 68, padding: 4, borderRadius: 2 }}
|
||||||
|
open={open}
|
||||||
|
onOpenChange={handleOpenChange}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
style={{ position: 'absolute', bottom: 20, right: 0 }}
|
||||||
|
type="text"
|
||||||
|
icon={<EllipsisOutlined style={{ color: '#fff', fontSize: 24, transform: 'rotate(90deg)' }} />}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
<div style={{height: 30,textAlign: 'center',lineHeight: '30px',fontWeight: 500,color: '#333'}}>{moment(time).format('YYYY-MM-DD hh:mm:ss')}</div>
|
||||||
|
{involved === 1 && (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
right: 0,
|
||||||
|
width: 64,
|
||||||
|
height: 24,
|
||||||
|
background: '#FAAD14',
|
||||||
|
borderRadius: '0px 4px 0px 4px',
|
||||||
|
color: '#FFF',
|
||||||
|
fontSize: 12,
|
||||||
|
textAlign: 'center',
|
||||||
|
lineHeight: '24px'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
重点关注
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ImageWithPopover;
|
Loading…
Reference in New Issue