/** @format */ 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-order-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, amount, apiEnv = 'dev', projectId, sourceType, 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; useEffect(() => { if (!(projectId && sourceType)) { return; } const fetchData = async () => { try { const requestParams: Record = { projectId, amount: amount || 30, sourceType, }; const res: Record = await fetchEventList( requestParams, apiEnv, ); if (res && res.errorCode === 0) { setEventList(res.data || []); } } catch (error) { console.error(error); } }; fetchData(); }, [projectId, amount, sourceType, apiEnv]); 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.eventId, townId: projectId, content: eventList[index], }); // 抛出IOC点击事件,供IOC处理后续业务逻辑 DispatchIOCEvent(EVENT_CLICK_EVENT_NAME, { id: item.eventId, townId: projectId, content: eventList[index], }); // 点击时获取当前事件的详情,若状态不一需更新 fetchEventDetail( { eventId: item.eventId, }, apiEnv, ).then((res: Record) => { if (res && res.errorCode === 0) { if ( res.data.deviceRepairOrderCardVO.deviceErrorType !== item.deviceErrorType ) { setEventList( eventList.map(event => event.id === item.id ? { ...event, deviceRepairOrderCardVO: res.data.deviceRepairOrderCardVO, } : 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(''); } document.addEventListener(IOC_BACK_EVENT_NAME, handleIOCBackClick); return () => { document.removeEventListener(IOC_BACK_EVENT_NAME, handleIOCBackClick); }; }, [setActiveId]); // 接收消息 function handleReceiveMessage(msg: Record) { const cloneData = cloneDeep(eventList); cloneData.length >= 30 && cloneData.pop(); cloneData.forEach(item => { item.__isNewEvent = false; }); cloneData.unshift({ ...msg, __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;