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