import cloneDeep from 'lodash/cloneDeep'; import React, { useEffect, useRef, useState } from 'react'; import { animated, useTransition } from 'react-spring'; import { useDeepCompareEffect } from 'react-use'; import { DispatchEvent, DispatchIOCEvent } from '../../../utils'; import { fetchEventDetail, fetchEventList } from '../services'; import EventItem from './EventItem'; import EventWebSocket from './EventWebSocket'; import { getEventFilter } from './helper'; import { EventListProps, IEventListFilter } from './index.d'; import { Container } from './styled'; // 列表元素宽度 const FIXED_EVENT_WIDTH = 400; // 列表元素间距 const FIXED_MARGIN = 12; const FIXED_WIDTH = FIXED_EVENT_WIDTH + FIXED_MARGIN; // 事件点击暴露的事件名 const EVENT_CLICK_EVENT_NAME = 'event-biz-event-click'; // IOC返回暴露的事件名 const IOC_BACK_EVENT_NAME = 'edata-event.ioc_back_click'; // 接收事件筛选的事件名 const EVENT_FILTER_EVENT_NAME = 'edata-eventList.filter'; // 还原事件筛选的事件名 const EVENT_REVERT_EVENT_NAME = 'edata-eventList.revert'; /** * 事件列表 * @param props */ const EventList = (props: EventListProps) => { const { id, limit, apiEnv = 'dev', projectId, eventCategories, scale = 1, size: { width, height }, } = props; const eventListRef = useRef(null); const [activeId, setActiveId] = useState(''); const [scrollLeft, setScrollLeft] = useState(0); const [wrapperWidth, setWrapperWidth] = useState(0); const [eventPanelVisible, setEventPanelVisible] = useState(true); const [animation, setAnimation] = useState(false); const [eventList, setEventList] = useState[]>([]); const [filter, setFilter] = useState(undefined); const transitions = useTransition(eventList, item => item.id, { from: { transform: 'translate3d(-400px,0,0)' }, enter: { transform: 'translate3d(0,0,0)' }, leave: { transform: 'translate3d(400px,0,0)', display: 'none' }, config: { duration: 500 }, }); const eventListDomWidth = eventList.length * FIXED_EVENT_WIDTH * scale + (eventList.length - 1) * FIXED_MARGIN * scale; useDeepCompareEffect(() => { if (!(projectId && eventCategories && eventCategories.length && apiEnv)) { return; } let isCanceled = false; const fetchData = async () => { try { const filterOptions = getEventFilter(eventCategories, filter); const requestParams: Record = { env: apiEnv, projectId, pageParam: { pageNum: 1, numPerPage: limit || 30 }, }; if (filterOptions.eventCategories) { requestParams.eventCategories = filterOptions.eventCategories.join(); } if (filterOptions.eventTypes) { requestParams.eventTypes = filterOptions.eventTypes.join(); } if (filterOptions.effectiveTime) { requestParams.effectiveTime = filterOptions.effectiveTime; } const res: Record = await fetchEventList(requestParams); if (res && res.errorCode === 0 && !isCanceled) { setEventList(res.data?.recordList || []); } } catch (error) { console.error(error); } }; fetchData(); return () => { isCanceled = true; }; }, [projectId, apiEnv, filter, limit, eventCategories]); useEffect(() => { if (eventListRef && eventListRef.current) { eventListRef.current.scrollLeft = scrollLeft / scale; } }, [scrollLeft, eventListRef]); useEffect(() => { if (eventListRef && eventListRef.current) { setWrapperWidth(eventListRef.current.getBoundingClientRect().width); } }, [eventListRef, eventList]); // 监听滚动条 function onScrollHandle() { if (eventListRef && eventListRef.current) { setScrollLeft(eventListRef.current.scrollLeft * scale); } } // prev function handlePrevClick() { if (scrollLeft + wrapperWidth >= eventListDomWidth) { setScrollLeft(0); } if (scrollLeft <= 0) { // setScrollLeft(eventListDomWidth - wrapperWidth); } else if (scrollLeft <= FIXED_WIDTH * scale) { setScrollLeft(0); } else if (scrollLeft % (FIXED_WIDTH * scale) <= 1) { setScrollLeft(scrollLeft - FIXED_WIDTH * scale); } else { setScrollLeft(scrollLeft - (scrollLeft % (FIXED_WIDTH * scale))); } } // next function handleNextClick() { if (scrollLeft + wrapperWidth >= eventListDomWidth) { // setScrollLeft(0); } else if (scrollLeft % (FIXED_WIDTH * scale) <= 1) { setScrollLeft(scrollLeft + FIXED_WIDTH * scale); } else { setScrollLeft( scrollLeft + (FIXED_WIDTH * scale - (scrollLeft % (FIXED_WIDTH * scale))), ); } } // 事件点击 function handleEventClick(item: Record, index: number) { if (!(eventListRef && eventListRef.current)) { return; } const eventTargetRect = eventListRef.current.children[ index ].getBoundingClientRect(); const eventWrapperRect = eventListRef.current.getBoundingClientRect(); // 更新选中 setActiveId(item.id); // 抛出Edata点击事件,供后续隐藏显示图层 DispatchEvent(id, EVENT_CLICK_EVENT_NAME, { id: item.id, townId: projectId, content: eventList[index], }); // 抛出IOC点击事件,供IOC处理后续业务逻辑 DispatchIOCEvent(EVENT_CLICK_EVENT_NAME, { id: item.id, townId: projectId, content: eventList[index], }); // 点击时获取当前事件的详情,若状态不一需更新 fetchEventDetail({ env: apiEnv, eventRecordId: item.id, }).then((res: Record) => { if (res && res.errorCode === 0) { if (res.data.eventStatus !== item.eventStatus) { setEventList( eventList.map(event => event.id === item.id ? { ...event, eventStatus: res.data.eventStatus } : event, ), ); } } }); // 右侧事件显示不完全时平移 if ( eventTargetRect.left + FIXED_WIDTH * scale > eventWrapperRect.left + wrapperWidth ) { setScrollLeft( scrollLeft + eventTargetRect.left + FIXED_WIDTH * scale - eventWrapperRect.left - wrapperWidth, ); } else if (eventTargetRect.left < eventWrapperRect.left) { // 左侧事件显示不完全时平移 setScrollLeft(index * FIXED_WIDTH * scale); } } useEffect(() => { // IOC返回点击时清空当前的选中项 function handleIOCBackClick() { setActiveId(''); } // 事件筛选 function handleEventFilter(e: any) { try { const result = e.detail; if (result) { setFilter(result); } } catch (error) { console.error(error); } } // 事件筛选还原 function handleEventRevert() { setFilter(undefined); } document.addEventListener(IOC_BACK_EVENT_NAME, handleIOCBackClick); document.addEventListener(EVENT_FILTER_EVENT_NAME, handleEventFilter); document.addEventListener(EVENT_REVERT_EVENT_NAME, handleEventRevert); return () => { document.removeEventListener(IOC_BACK_EVENT_NAME, handleIOCBackClick); document.removeEventListener(EVENT_FILTER_EVENT_NAME, handleEventFilter); document.removeEventListener(EVENT_REVERT_EVENT_NAME, handleEventRevert); }; }, [setActiveId]); // 接收消息 function handleReceiveMessage(msg: Record) { const cloneData = cloneDeep(eventList); cloneData.pop(); cloneData.forEach(item => { item.__isNewEvent = false; }); cloneData.unshift({ ...msg, id: msg.recordId, __isNewEvent: true, }); setScrollLeft(0); setEventList(cloneData); if (!animation) { setAnimation(true); } } // 事件数据为空时不显示事件区 if (!filter && !eventList.length) { return null; } return (
setEventPanelVisible(!eventPanelVisible)} />
事件列表
onScrollHandle()} > {transitions.length ? transitions.map(({ item, props, key }, index) => ( handleEventClick(item, index)} style={props} > )) : null} {!eventList.length ? (
近{filter?.effectiveTime || 3}小时无该类告警
) : null}
); }; export default EventList;