import React, { useState, useEffect, useContext, useMemo } from 'react'; import PropTypes from 'prop-types'; import Empty from '@wisdom-components/empty'; import classNames from 'classnames'; import { Modal, Button, Tabs, Input, Radio, ConfigProvider, message } from 'antd'; import BasicTable from '@wisdom-components/basictable'; import { getMonitorConfig, getSensorType, getDeviceRealInfo, getPointAddressEntry, getPointAddress, } from './apis'; import './index.less'; const { TabPane } = Tabs; const defaultColumns = [ { title: '序号', dataIndex: 'index', width: 60, }, { title: '指标名称', dataIndex: 'name', width: 150, }, { title: '最新指标', dataIndex: 'value', render: (text) => <a>{text}</a>, }, { title: '单位', dataIndex: 'unit', }, { title: '指标类型', dataIndex: 'type', }, { title: '数据描述', dataIndex: 'desc', }, { title: '更新时间', dataIndex: 'time', }, ]; const RealTimeInfo = (props) => { const { getPrefixCls } = useContext(ConfigProvider.ConfigContext); const prefixCls = getPrefixCls('realtime-info'); const { deviceParams, infoData, user, placeholder, defaultTargetValue, modalTitle, buttonText } = props; const [isModalVisible, setIsModalVisible] = useState(false); const [targetValue, setTargetValue] = useState(defaultTargetValue); // 重点/全部 const [searchValue, setSearchValue] = useState(''); // 搜索框内容 const [tabKey, setTabKey] = useState(''); const [guid, setGuid] = useState(''); const [deviceConf, setDeviceConf] = useState([]); // 设备配置 const [deviceInfo, setDeviceInfo] = useState({}); // 设备实时数据 const [sensorType, setSensorType] = useState([]); // sensorType const [pointAddress, setPointAddress] = useState([]); // pointAddress const tabData = useMemo(() => { const data = deviceInfo; let tData = []; if (!data) return tData; tData.push({ key: data.code, title: data.name, guid: data.guid, versionID: data.versionID, deviceType: data.aName, }); if (data.child && data.child.length) { data.child.forEach((child) => { tData.push({ key: child.code, title: data.name + child.name, guid: child.guid, versionID: child.versionID, deviceType: child.aName, }); }); } return tData; }, [deviceInfo]); // 过滤重点指标(带搜索) const filterEmphasis = (dataSource, searchValue) => { const cur = tabData.filter((item) => item.key === tabKey); const conf = cur.length > 0 ? deviceConf.filter((item) => item.deviceType === cur[0].deviceType) : []; const dPoints = conf.length > 0 && conf[0].dPoints ? conf[0].dPoints.split(',') : []; const data = dataSource.filter((item) => searchValue ? dPoints.indexOf(searchValue) > -1 && dPoints.includes(item.name) : dPoints.includes(item.name), ); return data; }; // 过滤普通指标(带搜索) const filterSearch = (dataSource, searchValue) => { return !searchValue ? dataSource : dataSource.filter((item) => item.name.includes(searchValue)); }; const getData = () => { let deviceType = ''; if (infoData) { let devices = [infoData.aName]; infoData.child?.forEach(function (val) { let k = devices.find(function (a) { return a == val.aName; }); if (!k) { devices.push(val.aName); } }); deviceType = devices.join(','); } else { deviceType = deviceParams.length > 0 ? Array.from(new Set(deviceParams.map((item) => item.deviceType))).join(',') : '二供泵房,二供机组'; } const configReq = getMonitorConfig({ params: { user, showAll: true, deviceType: deviceType, }, }); const sensorReq = getSensorType(); const realDataReq = getDeviceRealInfo({ data: { pageIndex: 1, pageSize: 200, param: deviceParams, useID: user, }, }); Promise.all([configReq, sensorReq, realDataReq]) .then((results) => { if (results.some((item) => item.code !== 0)) message.error('获取数据失败'); const [configRes, sensorRes, realDataRes] = results; setSensorType(sensorRes.data); setDeviceConf(configRes.data); setDeviceInfo(realDataRes.data.list[0]); setTabKey(realDataRes?.data?.list?.[0]?.code); }) .catch((err) => { message.error('获取数据失败'); }); }; useEffect(() => { if (!isModalVisible || !deviceParams || !deviceParams.length) return; getData(); }, [deviceParams, user, isModalVisible]); const GetPointAddressEntry = () => { const cur = tabData.filter((item) => item.key === tabKey); !!cur.length && getPointAddressEntry({ params: { versionId: cur[0].versionID, }, }).then((res) => { if (res.code === 0 && res.data.length) { setPointAddress(res.data); } }); }; useEffect(() => { if (!tabKey || !tabData || !tabData.length) return; GetPointAddressEntry(); const g = tabData.filter((item) => item.key === tabKey); setGuid(g?.[0]?.guid); }, [tabKey]); const formatData = (data = [], sensorType = [], deviceInfo = {}) => { if (!deviceInfo) return []; let time = deviceInfo.pt; if (time) time = time.slice(5, 19).replace('-', '/'); let newData = data.map((item, index) => { return { id: item.id, key: item.id, index: index + 1, name: item.name, value: 0, unit: '--', type: '--', time: time, desc: item.valDesc || '--', ...item, }; }); newData.forEach((item) => { let curData1 = sensorType.filter((child) => child.id == item.sensorTypeID); let curData2 = deviceInfo.dataList.filter((child) => child.paid == item.id); if (curData1.length) { item.unit = curData1[0].unit || '--'; item.type = curData1[0].name || '--'; } if (curData2.length) { item.value = curData2[0].pv || '--'; } }); return newData; }; const tableData = useMemo(() => { // 过滤数据 let points = []; if (targetValue === 'emphasis') { points = filterEmphasis(pointAddress, searchValue); } else { points = filterSearch(pointAddress, searchValue); } const deviceData = deviceInfo.code === tabKey ? deviceInfo : deviceInfo?.child?.find((item) => item.code === tabKey); const newData = formatData(points, sensorType, deviceData); return newData; }, [targetValue, searchValue, pointAddress, deviceInfo]); const columns = useMemo(() => { return defaultColumns; }, []); const showModal = () => { setIsModalVisible(true); }; const handleOk = () => { setIsModalVisible(false); }; const handleCancel = () => { setIsModalVisible(false); }; const changeSearch = (e) => { e.target && e.target.value === '' && setSearchValue(''); }; const onSearch = (value) => { // 前端搜索 setSearchValue(value); }; const onTabChange = (key) => { setTabKey(key); }; const onRadioChange = (e) => { setTargetValue(e.target.value); }; const renderTitle = () => { return ( <div className={classNames(`${prefixCls}-modal-title`)}> <Tabs tabBarExtraContent={{ left: <h3 style={{ fontWeight: 'bold' }}>{modalTitle}</h3> }} activeKey={tabKey} onChange={onTabChange} centered > {tabData.map((item) => ( <TabPane tab={item.title} key={item.key} /> ))} </Tabs> </div> ); }; return ( <div className={classNames(prefixCls)}> <Button type="link" onClick={showModal}> {buttonText} </Button> <Modal className={classNames(`${prefixCls}-modal`)} width={915} title={renderTitle()} footer={null} visible={isModalVisible} onOk={handleOk} onCancel={handleCancel} > <div className={classNames(`${prefixCls}-modal-content`)}> <div className={classNames(`${prefixCls}-search-wrap`)}> <div className={classNames(`${prefixCls}-search`)}> <div className={classNames(`${prefixCls}-label`)}>搜索:</div> <Input.Search placeholder={placeholder} onSearch={onSearch} onChange={changeSearch} /> </div> <div className={classNames(`${prefixCls}-target`)}> <div className={classNames(`${prefixCls}-label`)}>指标:</div> <Radio.Group onChange={onRadioChange} defaultValue={targetValue}> <Radio.Button value="emphasis">重点指标</Radio.Button> <Radio.Button value="all">全部</Radio.Button> </Radio.Group> </div> </div> <div className={classNames(`${prefixCls}-code-wrap`)}> <div>采集编码:{guid || '--'}</div> <div>更新时间:{(tableData.length && tableData[0].time) || '--'}</div> </div> <div className={classNames(`${prefixCls}-modal-table`)}> <BasicTable bordered columns={columns} locale={{ emptyText: <Empty /> }} pagination={false} dataSource={tableData} {...props} /> </div> </div> </Modal> </div> ); }; RealTimeInfo.defaultProps = { buttonText: '查看更多', modalTitle: '实时指标监控', placeholder: '输入指标名称等', defaultTargetValue: 'emphasis', user: null, deviceParams: [], deviceRealInfoParams: {}, deviceConfService: () => {}, pointAddressEntryService: () => {}, sensorTypeService: () => {}, deviceRealInfoService: () => {}, }; RealTimeInfo.propTypes = { buttonText: PropTypes.string, modalTitle: PropTypes.string, placeholder: PropTypes.string, defaultTargetValue: PropTypes.string, user: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), deviceParams: PropTypes.array, deviceRealInfoParams: PropTypes.object, deviceConfService: PropTypes.func, pointAddressEntryService: PropTypes.func, sensorTypeService: PropTypes.func, deviceRealInfoService: PropTypes.func, }; export default RealTimeInfo;