wenlele
1 year ago
11 changed files with 1544 additions and 236 deletions
@ -0,0 +1,774 @@ |
|||
import React, { useEffect, useState, useRef } from 'react'; |
|||
import { connect } from 'react-redux'; |
|||
import { Timeline, Card, Button, Modal, Form, Tooltip, Select, Radio, RadioGroup } from '@douyinfe/semi-ui'; |
|||
import { push } from 'react-router-redux'; |
|||
import { Setup, OutHidden } from "$components"; |
|||
import ReactECharts from 'echarts-for-react'; |
|||
import moment from "moment"; |
|||
import SimpleBar from 'simplebar-react'; |
|||
|
|||
|
|||
|
|||
const AlarmChart = ({ dispatch, actions, user, history, projectPoms, loading, socket, pepProjectId, statisticOnline, strucSeries }) => { |
|||
|
|||
const { control, install, problem } = actions |
|||
const [setup, setSetup] = useState(false); //设置是否显现
|
|||
const [tableType, setTableType] = useState(''); //localStorage存储名
|
|||
const [tableSetup, setTableSetup] = useState([]); //单一表格设置信息
|
|||
const [long, setLong] = useState(''); //最新动态设置
|
|||
const [pomsList, setPomsList] = useState([]); //项目
|
|||
const [faultId, setFaultId] = useState(''); //项目id 故障数统计
|
|||
const [onlineId, setOnlineId] = useState(''); //项目id 数据在线率
|
|||
const [successionId, setSuccessionId] = useState(''); //项目id 数据连续率
|
|||
const [setData, setSetData] = useState(); //设置总数
|
|||
const [radioStatistics, setRadioStatistics] = useState('day'); //故障数统计(日,周,月)
|
|||
const [radioRank, setRadioRank] = useState('day'); //故障数排名(日,周,月)
|
|||
const [dataAlarm, setDataAlarm] = useState({}); //故障数统计--数据类
|
|||
const [videoAlarm, setVideoAlarm] = useState({}); //故障故障数统计--视频
|
|||
const [useAlarm, setUseAlarm] = useState({}); //故障故障数统计--应用
|
|||
const [behind, setBehind] = useState(true); //故障数统计下钻
|
|||
const [behindShow, setBehindShow] = useState([]); //故障数统计展示
|
|||
const [videoData, setVideoData] = useState([]); //视频故障统计
|
|||
const [datumData, setDatumData] = useState([]); //数据故障统计
|
|||
const [useData, setUseData] = useState([]); //应用故障统计
|
|||
const [rankData, setRankData] = useState([]); //故障排名
|
|||
|
|||
const [onlineStruc, setOnlineStruc] = useState([]) |
|||
const [online, setOnline] = useState([]) |
|||
const [value, setValue] = useState([]) |
|||
|
|||
const [seriesStruc, setSeriesStruc] = useState([]) |
|||
const [series, setSeries] = useState([]) |
|||
const [seriesValue, setSeriesValue] = useState([]) |
|||
|
|||
|
|||
|
|||
useEffect(() => { |
|||
if (projectPoms?.length > 0) { |
|||
let data = projectPoms?.filter(v => v.pepProjectIsDelete != 1)?.map(v => ({ value: v.id, label: v.pepProjectName || v.name })) |
|||
setPomsList(data) |
|||
} |
|||
}, [projectPoms]) |
|||
|
|||
useEffect(async () => { |
|||
if (projectPoms?.length > 0) { |
|||
let data = await getData('day', pepProjectId, true, true) |
|||
await getRank(data) |
|||
setRadioStatistics('day') |
|||
setRadioRank('day') |
|||
setFaultId('') |
|||
if (pepProjectId) { |
|||
setPomsList(projectPoms?.filter(v => v.pepProjectIsDelete != 1 && ((pepProjectId?.length > 0 ? pepProjectId.split(",")?.map(p => Number(p)) : [pepProjectId]).includes(v.id)))?.map(v => ({ value: v.id, label: v.pepProjectName || v.name }))) |
|||
} else { |
|||
setPomsList(projectPoms?.filter(v => v.pepProjectIsDelete != 1)?.map(v => ({ value: v.id, label: v.pepProjectName || v.name }))) |
|||
} |
|||
} |
|||
}, [pepProjectId, projectPoms]) |
|||
|
|||
|
|||
useEffect(() => { |
|||
setOnlineId('') |
|||
dispatch(control.getStatisticOnline({ pepProjectId: onlineId || pepProjectId })).then(res => { |
|||
if (res.success) { |
|||
let data = res.payload.data?.filter(s => !onlineId || s.pomsProject?.map(p => p.id)?.includes(onlineId)) |
|||
setOnlineStruc(data?.map(v => ({ value: v.strucId, label: v.strucName })) || []) |
|||
setOnline(data?.slice(0, 10) || []) |
|||
setValue(data?.map(v => v.strucId)?.slice(0, 10) || []) |
|||
} |
|||
}) |
|||
}, [onlineId, pepProjectId]) |
|||
|
|||
useEffect(() => { |
|||
setSuccessionId('') |
|||
dispatch(control.getStrucSeries({ pepProjectId: successionId || pepProjectId })).then(res => { |
|||
if (res.success) { |
|||
let data = res.payload.data?.filter(s => !successionId || s.pomsProject?.map(p => p.id)?.includes(successionId)) |
|||
setSeriesStruc(data?.map(v => ({ value: v.strucId, label: v.strucName })) || []) |
|||
setSeries(data?.slice(0, 10) || []) |
|||
setSeriesValue(data?.map(v => v.strucId)?.slice(0, 10) || []) |
|||
} |
|||
}) |
|||
}, [successionId, pepProjectId]) |
|||
|
|||
const getRank = async (data) => { |
|||
let dataList = [] |
|||
if (pepProjectId && (!pepProjectId?.length || pepProjectId.split(",")?.length == 1) || projectPoms?.legend == 1) { |
|||
|
|||
data?.AlarmData?.filter(p => p.State < 3)?.forEach(s => { |
|||
let find = dataList?.find(a => a.StructureId == s.StructureId) |
|||
if (find) { |
|||
find.sum += 1 |
|||
} else { |
|||
dataList.push({ |
|||
StructureId: s.StructureId, |
|||
name: s.StructureName, |
|||
sum: 1 |
|||
}) |
|||
} |
|||
}) |
|||
|
|||
data?.AlarmVideo?.filter(p => !p.confirmTime)?.forEach(s => { |
|||
s?.struc?.forEach(f => { |
|||
let find = dataList?.find(a => a.id == s.StructureId) |
|||
if (find) { |
|||
find.sum += 1 |
|||
} else { |
|||
dataList.push({ |
|||
StructureId: f.id, |
|||
name: f.name, |
|||
sum: 1 |
|||
}) |
|||
} |
|||
}) |
|||
}) |
|||
|
|||
} else { |
|||
projectPoms?.filter(v => v.pepProjectIsDelete != 1)?.forEach(d => { |
|||
let data1 = data?.AlarmData?.filter(v => v.pomsProject?.map(p => p.id)?.includes(d.id) && v.State < 3)?.length || 0 |
|||
let data2 = data?.AlarmVideo?.filter(v => v.pomsProject?.map(p => p.id)?.includes(d.id) && !v.confirmTime)?.length || 0 |
|||
dataList.push({ |
|||
name: d.name || d.pepProjectName, |
|||
sum: data1 + data2 |
|||
}) |
|||
}) |
|||
|
|||
} |
|||
setRankData(dataList.sort((a, b) => b.sum - a.sum)?.slice(0, 5) || []) |
|||
} |
|||
|
|||
const getData = async (radio, pepProjectId, diff1, diff2) => { |
|||
let data = {} |
|||
await dispatch(control.getAlarmData({ |
|||
pepProjectId: pepProjectId, |
|||
startTime: moment().startOf(radio).format('YYYY-MM-DD HH:mm:ss') |
|||
})).then((res) => { |
|||
if (res.success) { |
|||
if (diff1) { |
|||
data.AlarmData = res.payload.data || [] |
|||
} |
|||
if (diff2) { |
|||
setDatumData(res.payload.data || []) |
|||
let group = { |
|||
group1: { sum: 0, untreated: 0 }, group2: { sum: 0, untreated: 0 }, group3: { sum: 0, untreated: 0 }, |
|||
group4: { sum: 0, untreated: 0 }, group5: { sum: 0, untreated: 0 } |
|||
} |
|||
res.payload.data?.forEach(v => { |
|||
group['group' + v.AlarmGroup].sum += 1 |
|||
if (v.State < 3) { |
|||
group['group' + v.AlarmGroup].untreated += 1 |
|||
} |
|||
}) |
|||
setDataAlarm(group) |
|||
} |
|||
} |
|||
}) |
|||
|
|||
|
|||
|
|||
await dispatch(problem.getAlarmVideoList({ |
|||
pepProjectId: pepProjectId, |
|||
startTime: moment().startOf(radio).format('YYYY-MM-DD HH:mm:ss') |
|||
})).then((res) => { |
|||
if (res.success) { |
|||
if (diff1) { |
|||
data.AlarmVideo = res.payload.data || [] |
|||
} |
|||
if (diff2) { |
|||
setVideoData(res.payload.data || []) |
|||
let alarmData = { sum: 0, untreated: 0 } |
|||
res.payload.data?.forEach(v => { |
|||
alarmData.sum += 1 |
|||
if (!v.confirmTime) { |
|||
alarmData.untreated += 1 |
|||
} |
|||
}) |
|||
setVideoAlarm(alarmData) |
|||
} |
|||
|
|||
} |
|||
}) |
|||
|
|||
if (diff2) { |
|||
await dispatch(control.getAlarmUse({ |
|||
pepProjectId: pepProjectId, |
|||
startTime: moment().startOf(radio).format('YYYY-MM-DD HH:mm:ss') |
|||
})).then((res) => { |
|||
if (res.success) { |
|||
setUseData(res.payload.data || []) |
|||
let alarmData = { sum: 0, untreated: 0 } |
|||
res.payload.data?.forEach(v => { |
|||
alarmData.sum += 1 |
|||
if (!v.confirmTime) { |
|||
alarmData.untreated += 1 |
|||
} |
|||
}) |
|||
setUseAlarm(alarmData) |
|||
} |
|||
}) |
|||
} |
|||
|
|||
return data |
|||
} |
|||
|
|||
|
|||
const behindHandle = (key) => { |
|||
let show = [] |
|||
switch (key) { |
|||
case '数据中段': |
|||
dispatch(problem.getAlarmDataGroup()).then((res) => { |
|||
if (res.success) { |
|||
let data = res.payload.data?.find(v => v.desc == '数据中断')?.unit || [] |
|||
let sumData = datumData?.filter(s => s.AlarmGroup == 1) || [] |
|||
data?.forEach(v => { |
|||
let dataList = sumData?.filter(s => s.AlarmGroupUnit == v.id) || [] |
|||
let untreated = dataList?.filter(s => s.State < 3)?.length || 0 |
|||
show.push({ |
|||
name: v.name, |
|||
untreated: untreated, |
|||
processed: dataList?.length - untreated, |
|||
num: dataList?.length |
|||
}) |
|||
}) |
|||
setBehindShow(show.sort((a, b) => b.num - a.num)?.slice(0, 5) || []) |
|||
} |
|||
}) |
|||
break; |
|||
case '数据异常': |
|||
dispatch(problem.getAlarmDataGroup()).then((res) => { |
|||
if (res.success) { |
|||
let data = res.payload.data?.find(v => v.desc == '数据异常')?.unit || [] |
|||
let sumData = datumData?.filter(s => s.AlarmGroup == 2) || [] |
|||
data?.forEach(v => { |
|||
let dataList = sumData?.filter(s => s.AlarmGroupUnit == v.id) || [] |
|||
let untreated = dataList?.filter(s => s.State < 3)?.length || 0 |
|||
show.push({ |
|||
name: v.name, |
|||
untreated: untreated, |
|||
processed: dataList?.length - untreated, |
|||
num: dataList?.length |
|||
}) |
|||
}) |
|||
setBehindShow(show.sort((a, b) => b.num - a.num)?.slice(0, 5) || []) |
|||
} |
|||
}) |
|||
break; |
|||
case '策略命中': |
|||
dispatch(problem.getAlarmDataGroup()).then((res) => { |
|||
if (res.success) { |
|||
let data = res.payload.data?.find(v => v.desc == '策略命中')?.unit || [] |
|||
let sumData = datumData?.filter(s => s.AlarmGroup == 3) || [] |
|||
data?.forEach(v => { |
|||
let dataList = sumData?.filter(s => s.AlarmGroupUnit == v.id) || [] |
|||
let untreated = dataList?.filter(s => s.State < 3)?.length || 0 |
|||
show.push({ |
|||
name: v.name, |
|||
untreated: untreated, |
|||
processed: dataList?.length - untreated, |
|||
num: dataList?.length |
|||
}) |
|||
}) |
|||
setBehindShow(show.sort((a, b) => b.num - a.num)?.slice(0, 5) || []) |
|||
} |
|||
}) |
|||
break; |
|||
case '视频异常': |
|||
dispatch(problem.getAlarmVideoExceptionType()).then((res) => { |
|||
if (res.success) { |
|||
res.payload.data?.forEach(v => { |
|||
let dataList = videoData?.filter(s => s.statusId == v.statusId) || [] |
|||
let untreated = dataList?.filter(s => !s.confirmTime)?.length || 0 |
|||
show.push({ |
|||
name: v.describe, |
|||
untreated: untreated, |
|||
processed: dataList?.length - untreated, |
|||
num: dataList?.length |
|||
}) |
|||
}) |
|||
setBehindShow(show.sort((a, b) => b.num - a.num)?.slice(0, 5) || []) |
|||
} |
|||
}) |
|||
|
|||
setBehind(false) |
|||
|
|||
break; |
|||
case '应用异常': |
|||
[{ name: '接口报错', value: 'apiError ' }, |
|||
{ name: '加载超时', value: 'timeout' }, |
|||
{ name: '元素异常', value: 'element' }].forEach(v => { |
|||
let dataList = useData?.filter(s => s.type == v.value) || [] |
|||
let untreated = dataList?.filter(s => !s.confirmTime)?.length || 0 |
|||
show.push({ |
|||
name: v.name, |
|||
untreated: untreated, |
|||
processed: dataList?.length - untreated, |
|||
num: dataList?.length |
|||
}) |
|||
}) |
|||
setBehindShow(show.sort((a, b) => b.num - a.num)?.slice(0, 5) || []) |
|||
break; |
|||
case '设备异常': |
|||
dispatch(problem.getAlarmDataGroup()).then((res) => { |
|||
if (res.success) { |
|||
let data = res.payload.data?.find(v => v.desc == '掉线' || v.desc == '不活跃')?.unit || [] |
|||
let sumData = datumData?.filter(s => s.AlarmGroup == 4 || s.AlarmGroup == 5) || [] |
|||
data?.forEach(v => { |
|||
let dataList = sumData?.filter(s => s.AlarmGroupUnit == v.id) || [] |
|||
let untreated = dataList?.filter(s => s.State < 3)?.length || 0 |
|||
show.push({ |
|||
name: v.name, |
|||
untreated: untreated, |
|||
processed: dataList?.length - untreated, |
|||
num: dataList?.length |
|||
}) |
|||
}) |
|||
setBehindShow(show.sort((a, b) => b.num - a.num)?.slice(0, 5) || []) |
|||
} |
|||
}) |
|||
break; |
|||
} |
|||
setBehind(false) |
|||
} |
|||
|
|||
|
|||
return (<> |
|||
{/* 数据分析 */} |
|||
{ |
|||
<div style={{ background: '#FFFFFF', boxShadow: '0px 0px 12px 2px rgba(220,222,224,0.2)', borderRadius: 2, paddingTop: 20, paddingLeft: 24, marginTop: 22 }}> |
|||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}> |
|||
<div style={{ display: 'flex', alignItems: 'center' }}> |
|||
<div style={{ width: 0, height: 20, borderLeft: '3px solid #005ABD', borderTop: '3px solid transparent', borderBottom: '3px solid transparent' }}></div> |
|||
<div style={{ fontFamily: "YouSheBiaoTiHei", fontSize: 24, color: '#101531', marginLeft: 8 }}>数据分析</div> |
|||
<div style={{ marginLeft: 6, fontSize: 12, color: '#969799', fontFamily: "DINExp", }}>DATA ANALYSIS</div> |
|||
</div> |
|||
{/* <div style={{ marginRight: 25 }}> |
|||
<img title='设置' src="/assets/images/problem/setup.png" style={{ width: 18, height: 18, cursor: "pointer" }} onClick={() => { |
|||
setSetup(true) |
|||
setTableType('analyse') |
|||
attribute('analyse') |
|||
setSetData(10) |
|||
}} /> |
|||
</div> */} |
|||
</div> |
|||
<div style={{ width: '100%', height: '100%', marginTop: 20 }}> |
|||
|
|||
<div style={{ display: "flex" }}> |
|||
{/* 故障数统计 */} |
|||
<div style={{ padding: 16, width: '50%', height: 300 }}> |
|||
{behind ? |
|||
<> |
|||
<div style={{ display: "flex", justifyContent: "space-between" }}> |
|||
<div style={{ fontSize: 18, fontWeight: 'bold', color: "#0b0b0bbd" }}>故障数统计</div> |
|||
<div> |
|||
<Select showClear filter placeholder='项目' value={faultId} style={{ width: 160, marginRight: 10 }} |
|||
onChange={(v) => { |
|||
setFaultId(v) |
|||
getData(radioStatistics, v, false, true) |
|||
}} |
|||
optionList={pomsList} |
|||
/> |
|||
<RadioGroup type='button' buttonSize='middle' value={radioStatistics} style={{ marginRight: 10 }} |
|||
onChange={e => { |
|||
setRadioStatistics(e.target.value) |
|||
getData(e.target.value, pepProjectId, false, true) |
|||
}} |
|||
> |
|||
<Radio value="day">今日</Radio> |
|||
<Radio value="week">本周</Radio> |
|||
<Radio value="month">本月</Radio> |
|||
</RadioGroup> |
|||
</div> |
|||
</div> |
|||
<div style={{ display: 'flex', padding: 16, height: "100%" }}> |
|||
<div style={{ display: "flex", flexDirection: "column", justifyContent: "space-evenly", width: 180 }}> |
|||
<div style={{ display: 'flex', justifyContent: "space-between", cursor: 'pointer' }} onClick={() => behindHandle('数据中段')}> |
|||
<div>数据中段:</div> |
|||
<div style={{ fontWeight: 500 }}> |
|||
<sapn style={{ color: "red" }}>{dataAlarm?.group1?.untreated || 0}</sapn> / |
|||
<span style={{ color: "rgb(48 47 138)" }}>{dataAlarm?.group1?.sum || 0}</span> |
|||
</div> |
|||
</div> |
|||
<div style={{ display: 'flex', justifyContent: "space-between", cursor: 'pointer' }} onClick={() => behindHandle('数据异常')}> |
|||
<div>数据异常:</div> |
|||
<div style={{ fontWeight: 500 }}> |
|||
<sapn style={{ color: "red" }}>{dataAlarm?.group2?.untreated || 0}</sapn> / |
|||
<span style={{ color: "rgb(48 47 138)" }}>{dataAlarm?.group2?.sum || 0}</span> |
|||
</div> |
|||
</div> |
|||
<div style={{ display: 'flex', justifyContent: "space-between", cursor: 'pointer' }} onClick={() => behindHandle('策略命中')}> |
|||
<div>策略命中:</div> |
|||
<div style={{ fontWeight: 500 }}> |
|||
<sapn style={{ color: "red" }}>{dataAlarm?.group3?.untreated || 0}</sapn> / |
|||
<span style={{ color: "rgb(48 47 138)" }}>{dataAlarm?.group3?.sum || 0}</span> |
|||
</div> |
|||
</div> |
|||
|
|||
<div style={{ display: 'flex', justifyContent: "space-between", cursor: 'pointer' }} onClick={() => behindHandle('视频异常')}> |
|||
<div>视频异常:</div> |
|||
<div style={{ fontWeight: 500 }}> |
|||
<sapn style={{ color: "red" }}>{videoAlarm?.untreated || 0}</sapn> / |
|||
<span style={{ color: "rgb(48 47 138)" }}>{videoAlarm?.sum || 0}</span> |
|||
</div> |
|||
</div> |
|||
<div style={{ display: 'flex', justifyContent: "space-between", cursor: 'pointer' }} onClick={() => behindHandle('应用异常')}> |
|||
<div>应用异常:</div> |
|||
<div style={{ fontWeight: 500 }}> |
|||
<sapn style={{ color: "red" }}>{useAlarm?.untreated || 0}</sapn> / |
|||
<span style={{ color: "rgb(48 47 138)" }}>{useAlarm?.sum || 0}</span> |
|||
</div> |
|||
</div> |
|||
|
|||
<div style={{ display: 'flex', justifyContent: "space-between", cursor: 'pointer' }} onClick={() => behindHandle('设备异常')}> |
|||
<div>设备异常:</div> |
|||
<div style={{ fontWeight: 500 }}> |
|||
<sapn style={{ color: "red" }}>{(dataAlarm?.group4?.untreated || 0) + (dataAlarm?.group5?.untreated || 0)}</sapn> / |
|||
<span style={{ color: "rgb(48 47 138)" }}>{(dataAlarm?.group4?.sum || 0) + (dataAlarm?.group5?.sum || 0)}</span> |
|||
</div> |
|||
</div> |
|||
|
|||
</div> |
|||
<div style={{ width: 'calc(100% - 180px)', display: 'flex', justifyContent: 'center', alignItems: 'center', fontSize: 46, fontWeight: 600 }}> |
|||
<div style={{ fontWeight: 500 }}> |
|||
|
|||
{(dataAlarm?.group1?.untreated || 0) |
|||
+ (dataAlarm?.group2?.untreated || 0) |
|||
+ (dataAlarm?.group3?.untreated || 0) |
|||
+ (dataAlarm?.group4?.untreated || 0) |
|||
+ (dataAlarm?.group5?.untreated || 0) |
|||
+ (videoAlarm?.untreated || 0) |
|||
+ (useAlarm?.untreated || 0) |
|||
} |
|||
/ |
|||
{(dataAlarm?.group1?.sum || 0) |
|||
+ (dataAlarm?.group2?.sum || 0) |
|||
+ (dataAlarm?.group3?.sum || 0) |
|||
+ (dataAlarm?.group4?.sum || 0) |
|||
+ (dataAlarm?.group5?.sum || 0) |
|||
+ (videoAlarm?.sum || 0) |
|||
+ (useAlarm?.sum || 0) |
|||
} |
|||
|
|||
</div> |
|||
</div> |
|||
</div> |
|||
</> |
|||
: <div onClick={() => { |
|||
setBehindShow([]) |
|||
setBehind(true) |
|||
}}> |
|||
<ReactECharts |
|||
option={{ |
|||
title: { |
|||
text: '故障数统计', |
|||
}, |
|||
grid: { |
|||
left: '10%', |
|||
// right: '4%',
|
|||
// bottom: '3%',
|
|||
// containLabel: true
|
|||
}, |
|||
// dataZoom: [
|
|||
// {
|
|||
// type: 'slider',
|
|||
// // startValue: behindShow?.map(v => v.name) || []
|
|||
// },
|
|||
// {
|
|||
// type: 'inside',
|
|||
// },
|
|||
// ],
|
|||
tooltip: { |
|||
trigger: 'axis' |
|||
}, |
|||
legend: { |
|||
data: ['未处理', '已处理'], |
|||
right: '10%', |
|||
}, |
|||
xAxis: { |
|||
type: 'category', |
|||
// boundaryGap: false,
|
|||
data: behindShow?.map(v => v.name) || [] |
|||
}, |
|||
yAxis: { |
|||
type: 'value', |
|||
name: "单位:条", |
|||
}, |
|||
series: [ |
|||
{ |
|||
type: 'bar', |
|||
name: '未处理', |
|||
smooth: true, |
|||
itemStyle: { color: '#df4141', }, |
|||
barWidth: 20, |
|||
data: behindShow?.map(v => v.untreated) || [] |
|||
}, |
|||
{ |
|||
type: 'bar', |
|||
name: '已处理', |
|||
smooth: true, |
|||
itemStyle: { color: '#0ddf42', }, |
|||
barWidth: 20, |
|||
data: behindShow?.map(v => v.processed) || [] |
|||
}, |
|||
|
|||
] |
|||
}} |
|||
notMerge={true} |
|||
lazyUpdate={true} |
|||
// onChartReady={this.onChartReadyCallback}
|
|||
// onEvents={EventsDict}
|
|||
// opts={}
|
|||
/> |
|||
</div> |
|||
} |
|||
</div> |
|||
{/* 故障数排名*/} |
|||
<div style={{ padding: 10, width: '50%', height: 300, position: "relative" }}> |
|||
<RadioGroup type='button' buttonSize='middle' value={radioRank} style={{ marginRight: 10, zIndex: 10, position: "absolute", top: 8, left: 112 }} |
|||
onChange={async e => { |
|||
setRadioRank(e.target.value) |
|||
let data = await getData(e.target.value, pepProjectId, true, false) |
|||
await getRank(data) |
|||
}} |
|||
> |
|||
<Radio value="day">今日</Radio> |
|||
<Radio value="week">本周</Radio> |
|||
<Radio value="month">本月</Radio> |
|||
</RadioGroup> |
|||
<ReactECharts |
|||
option={{ |
|||
title: { |
|||
text: '故障数排名', |
|||
}, |
|||
grid: { |
|||
left: '10%', |
|||
// right: '4%',
|
|||
// bottom: '3%',
|
|||
// containLabel: true
|
|||
}, |
|||
tooltip: { |
|||
trigger: 'axis' |
|||
}, |
|||
legend: { |
|||
data: ['故障数'], |
|||
right: '10%', |
|||
}, |
|||
yAxis: { |
|||
type: 'category', |
|||
data: rankData?.map(v => v.name) || [] |
|||
}, |
|||
xAxis: { |
|||
type: 'value', |
|||
}, |
|||
series: [ |
|||
{ |
|||
type: 'bar', |
|||
name: '故障数', |
|||
smooth: true, |
|||
itemStyle: { color: '#0ddf42', }, |
|||
barWidth: 20, |
|||
data: rankData?.map(v => v.sum) || [] |
|||
}, |
|||
|
|||
] |
|||
}} |
|||
notMerge={true} |
|||
lazyUpdate={true} |
|||
// onChartReady={this.onChartReadyCallback}
|
|||
// onEvents={EventsDict}
|
|||
// opts={}
|
|||
/> |
|||
</div> |
|||
</div> |
|||
<div style={{ display: "flex" }}> |
|||
{/* 数据在线率 */} |
|||
<div style={{ marginTop: 30, padding: 10, width: '50%', height: 350, position: "relative" }}> |
|||
<div style={{ zIndex: 10, position: "absolute", top: 8, left: 112, display: 'flex' }}> |
|||
<Select filter showClear placeholder='项目' value={onlineId} style={{ width: 160, marginRight: 10 }} |
|||
onChange={(v) => { |
|||
setOnlineId(v) |
|||
}} |
|||
optionList={pomsList} |
|||
/> |
|||
<Select showClear |
|||
filter |
|||
value={value} |
|||
multiple={true} |
|||
maxTagCount={1} |
|||
style={{ width: 160, marginRight: 10 }} |
|||
optionList={onlineStruc} |
|||
onChange={v => { |
|||
setValue(v) |
|||
let data = statisticOnline?.filter(s => !onlineId || s.pomsProject?.map(p => p.id)?.includes(onlineId)) |
|||
setOnline(data?.filter(s => v.includes(s.strucId))) |
|||
}} |
|||
/> |
|||
|
|||
</div> |
|||
<ReactECharts |
|||
option={{ |
|||
title: { |
|||
text: '数据在线率', |
|||
}, |
|||
grid: { |
|||
left: 27, |
|||
right: 10, |
|||
bottom: 20, |
|||
}, |
|||
tooltip: { |
|||
trigger: 'axis', |
|||
formatter: function (params) { |
|||
// 自定义提示框内容
|
|||
// console.log(params);
|
|||
let title = params[0].data[0] + '<br/>' + '<br/>' |
|||
params.forEach(v => { |
|||
let find = online?.find(s => s.strucName == v.seriesName)?.online?.find(d => moment(d.collect_time).format('YYYY-MM-DD HH') == v.data[0]) || {} |
|||
title = title + v.seriesName + ":" + " " + " " + v.data[1] + "%" + "(" + find?.online + "/" + find?.total + ")" + '<br/>' |
|||
}) |
|||
return title |
|||
} |
|||
}, |
|||
xAxis: { |
|||
type: 'time', |
|||
// name: "时间",
|
|||
boundaryGap: false, |
|||
minInterval: 1000 * 60 * 60, |
|||
}, |
|||
yAxis: { |
|||
type: 'value', |
|||
name: "单位%", |
|||
areaStyle: { |
|||
color: '#FFF', |
|||
}, |
|||
}, |
|||
series: online?.map(v => ({ |
|||
type: 'line', |
|||
name: v.strucName, |
|||
smooth: true, |
|||
areaStyle: { |
|||
color: '#0e9cff26', |
|||
}, |
|||
data: v.online?.map(f => [moment(f.collect_time).format('YYYY-MM-DD HH'), f.rate.toFixed(1)]) || [] |
|||
})) || [] |
|||
}} |
|||
notMerge={true} |
|||
lazyUpdate={true} |
|||
style={{ width: "100%", height: "100%" }} |
|||
/> |
|||
|
|||
</div> |
|||
{/* 数据连续率 */} |
|||
<div style={{ marginTop: 30, padding: 10, width: '50%', height: 350, position: "relative" }}> |
|||
<div style={{ zIndex: 10, position: "absolute", top: 8, left: 112, display: 'flex' }}> |
|||
<Select filter showClear placeholder='项目' value={successionId} style={{ width: 160, marginRight: 10 }} |
|||
onChange={(v) => { |
|||
setSuccessionId(v) |
|||
}} |
|||
optionList={pomsList} |
|||
/> |
|||
<Select showClear |
|||
filter |
|||
placeholder='结构物' |
|||
value={seriesValue} |
|||
multiple={true} |
|||
maxTagCount={1} |
|||
style={{ width: 160, marginRight: 10 }} |
|||
optionList={seriesStruc} |
|||
onChange={v => { |
|||
setSeriesValue(v) |
|||
let data = strucSeries?.filter(s => !onlineId || s.pomsProject?.map(p => p.id)?.includes(onlineId)) |
|||
setSeries(data?.filter(s => v.includes(s.strucId))) |
|||
}} |
|||
/> |
|||
|
|||
</div> |
|||
<ReactECharts |
|||
option={{ |
|||
title: { |
|||
text: '数据在线率', |
|||
}, |
|||
grid: { |
|||
left: 27, |
|||
right: 10, |
|||
bottom: 20, |
|||
}, |
|||
tooltip: { |
|||
trigger: 'axis', |
|||
formatter: function (params) { |
|||
// 自定义提示框内容
|
|||
// console.log(params);
|
|||
let title = params[0].data[0] + '<br/>' + '<br/>' |
|||
params.forEach(v => { |
|||
let find = series?.find(s => s.strucName == v.seriesName)?.series?.find(d => moment(d.collect_time).format('YYYY-MM-DD HH') == v.data[0]) || {} |
|||
title = title + v.seriesName + ":" + " " + " " + v.data[1] + "%" + "(" + find?.num + "/" + find?.tTotal + ")" + '<br/>' |
|||
}) |
|||
return title |
|||
} |
|||
}, |
|||
xAxis: { |
|||
type: 'time', |
|||
// name: "时间",
|
|||
boundaryGap: false, |
|||
minInterval: 1000 * 60 * 60, |
|||
}, |
|||
yAxis: { |
|||
type: 'value', |
|||
name: "单位%", |
|||
areaStyle: { |
|||
color: '#FFF', |
|||
}, |
|||
}, |
|||
series: series?.map(v => ({ |
|||
type: 'line', |
|||
name: v.strucName, |
|||
smooth: true, |
|||
areaStyle: { |
|||
color: '#0e9cff26', |
|||
}, |
|||
data: v.series?.map(f => [moment(f.collect_time).format('YYYY-MM-DD HH'), Number(f.cont)]) || [] |
|||
})) || [] |
|||
}} |
|||
notMerge={true} |
|||
lazyUpdate={true} |
|||
style={{ width: "100%", height: "100%" }} |
|||
/> |
|||
|
|||
</div> |
|||
</div> |
|||
|
|||
|
|||
</div> |
|||
</div >} |
|||
|
|||
{/* 设置弹窗 */} |
|||
{ |
|||
setup && <Setup |
|||
tableType={tableType} |
|||
tableList={tableSetup} |
|||
layout={long} |
|||
data={setData} |
|||
close={() => { |
|||
setSetup(false); |
|||
attribute(tableType); |
|||
setTableType('') |
|||
setLong('') |
|||
}} |
|||
/> |
|||
} |
|||
</> |
|||
) |
|||
} |
|||
|
|||
function mapStateToProps (state) { |
|||
const { auth, global, members, webSocket, ProjectPoms, statisticOnline, strucSeries } = state; |
|||
|
|||
return { |
|||
user: auth.user, |
|||
actions: global.actions, |
|||
pepProjectId: global.pepProjectId, |
|||
socket: webSocket.socket, |
|||
projectPoms: ProjectPoms?.data?.rows, |
|||
statisticOnline: statisticOnline?.data || [], |
|||
strucSeries: strucSeries?.data || [] |
|||
}; |
|||
} |
|||
|
|||
export default connect(mapStateToProps)(AlarmChart); |
Loading…
Reference in new issue