Browse Source

控制台bug优化

dev
wenlele 1 year ago
parent
commit
bbf5a3546a
  1. 2
      api/app/lib/controllers/alarm/video.js
  2. 63
      api/app/lib/controllers/control/analysis.js
  3. 559
      web/client/src/sections/control/components/alarm-chart.js
  4. 2
      web/client/src/sections/control/containers/control.jsx

2
api/app/lib/controllers/alarm/video.js

@ -138,6 +138,7 @@ async function alarmList (ctx) {
cameraAlarm.cameraId AS cameraId, cameraAlarm.cameraId AS cameraId,
cameraAlarm.cameraName AS cameraName, cameraAlarm.cameraName AS cameraName,
cameraAlarm.cameraKindId AS cameraKindId, cameraAlarm.cameraKindId AS cameraKindId,
cameraAlarm.statusId AS statusId,
cameraAlarm.venderId AS venderId, cameraAlarm.venderId AS venderId,
cameraAlarm.venderName AS venderName, cameraAlarm.venderName AS venderName,
cameraAlarm.cameraSerialNo AS cameraSerialNo, cameraAlarm.cameraSerialNo AS cameraSerialNo,
@ -257,6 +258,7 @@ async function alarmList (ctx) {
let d = { let d = {
cameraId: a.cameraId, cameraId: a.cameraId,
cameraName: a.cameraName, cameraName: a.cameraName,
statusId: a.statusId,
camerOnline: a.cameraOnline, camerOnline: a.cameraOnline,
cameraSerialNo: a.cameraSerialNo, cameraSerialNo: a.cameraSerialNo,
cameraChannelNo: a.cameraChannelNo, cameraChannelNo: a.cameraChannelNo,

63
api/app/lib/controllers/control/analysis.js

@ -757,26 +757,26 @@ async function getStrucSeries (ctx) {
index: strucSeriesClient.config.index, index: strucSeriesClient.config.index,
type: strucSeriesClient.config.type, type: strucSeriesClient.config.type,
body: { body: {
// "query": { "query": {
// "bool": { "bool": {
// "filter": [ "filter": [
// { {
// "range": { "range": {
// "collect_time": { "collect_time": {
// "gte": `${moment().subtract(32, 'hours').format('YYYY-MM-DDTHH:mm:ss.SSS')}Z`, "gte": `${moment().subtract(32, 'hours').format('YYYY-MM-DDTHH:mm:ss.SSS')}Z`,
// // "gte": "2023-08-24T08:00:00.000Z", // "gte": "2023-08-24T08:00:00.000Z",
// } }
// } }
// }, },
// { {
// "terms": { "terms": {
// "structure": anxinStrucIds, "structure": anxinStrucIds,
// // "structure": [1, 2, 3] // "structure": [1, 2, 3]
// } }
// } }
// ] ]
// } }
// }, },
"sort": [ "sort": [
{ {
"collect_time": { "collect_time": {
@ -793,23 +793,32 @@ async function getStrucSeries (ctx) {
} }
} }
for (let struc of anxinStruc) { const sensor = anxinStrucIds.length ? await clickHouse.anxinyun.query(
`SELECT
id,structure,name
FROM t_sensor
INNER JOIN t_structure
ON t_structure.id = t_sensor.structure
WHERE
t_sensor.structure IN (${anxinStrucIds.join(',')})`
).toPromise() : []
for (let data of sensor) {
let curSeries = let curSeries =
seriesRes.hits.hits seriesRes.hits.hits
.filter((h) => h._source.structure == struc.strucId) .filter((h) => h._source.sensor == data.id)
// .sort((a, b) => {
// return a._source.collect_time - b._source.collect_time
// })
.map(s => { .map(s => {
return { return {
...s._source, ...s._source,
} }
}) })
struc.series = curSeries let struc = anxinStruc.find((h) => h.strucId == data.structure)
data.series = curSeries
data.struc = struc
} }
ctx.status = 200; ctx.status = 200;
ctx.body = anxinStruc; ctx.body = sensor;
} else { } else {
ctx.status = 200; ctx.status = 200;
ctx.body = []; ctx.body = [];

559
web/client/src/sections/control/components/alarm-chart.js

@ -1,6 +1,6 @@
import React, { useEffect, useState, useRef } from 'react'; import React, { useEffect, useState, useRef } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Timeline, Card, Button, Modal, Form, Tooltip, Select, Radio, RadioGroup } from '@douyinfe/semi-ui'; import { Timeline, Card, Button, Modal, Form, Tooltip, Select, Radio, RadioGroup, Spin } from '@douyinfe/semi-ui';
import { push } from 'react-router-redux'; import { push } from 'react-router-redux';
import { Setup, OutHidden } from "$components"; import { Setup, OutHidden } from "$components";
import ReactECharts from 'echarts-for-react'; import ReactECharts from 'echarts-for-react';
@ -19,7 +19,6 @@ const AlarmChart = ({ dispatch, actions, user, history, projectPoms, loading, so
const [pomsList, setPomsList] = useState([]); //项目 const [pomsList, setPomsList] = useState([]); //项目
const [faultId, setFaultId] = useState(''); //项目id 故障数统计 const [faultId, setFaultId] = useState(''); //项目id 故障数统计
const [onlineId, setOnlineId] = useState(''); //项目id 数据在线率 const [onlineId, setOnlineId] = useState(''); //项目id 数据在线率
const [successionId, setSuccessionId] = useState(''); //项目id 数据连续率
const [setData, setSetData] = useState(); //设置总数 const [setData, setSetData] = useState(); //设置总数
const [radioStatistics, setRadioStatistics] = useState('day'); //故障数统计(日,周,月) const [radioStatistics, setRadioStatistics] = useState('day'); //故障数统计(日,周,月)
const [radioRank, setRadioRank] = useState('day'); //故障数排名(日,周,月) const [radioRank, setRadioRank] = useState('day'); //故障数排名(日,周,月)
@ -37,9 +36,16 @@ const AlarmChart = ({ dispatch, actions, user, history, projectPoms, loading, so
const [online, setOnline] = useState([]) const [online, setOnline] = useState([])
const [value, setValue] = useState([]) const [value, setValue] = useState([])
const [seriesStruc, setSeriesStruc] = useState([]) const [successionId, setSuccessionId] = useState(''); //项目id 数据连续率
const [series, setSeries] = useState([]) const [seriesStruc, setSeriesStruc] = useState([]) //连续率 结构物数据
const [seriesValue, setSeriesValue] = useState([]) const [series, setSeries] = useState([]) //连续率 数据
const [seriesValue, setSeriesValue] = useState([]) //连续率 结构物Id
const [sensorValue, setSensorValue] = useState([]) //连续率 测点Id
const [sensorList, setSensorList] = useState([]) //连续率 测点数数据
const [statisticsSpin, setStatisticsSpin] = useState(false) //故障数统计 加载中
const [rankSpin, setRankSpin] = useState(false) //故障数排名 加载中
@ -52,43 +58,49 @@ const AlarmChart = ({ dispatch, actions, user, history, projectPoms, loading, so
useEffect(async () => { useEffect(async () => {
if (projectPoms?.length > 0) { if (projectPoms?.length > 0) {
let data = await getData('day', pepProjectId, true, true) let data = await getData('day', pepProjectId, true, true)
await getRank(data) await getRank(data)
setRadioStatistics('day') setRadioStatistics('day')
setRadioRank('day') setRadioRank('day')
setFaultId('') 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 }))) await dispatch(control.getStatisticOnline({ pepProjectId: pepProjectId })).then(res => {
} else { if (res.success) {
setPomsList(projectPoms?.filter(v => v.pepProjectIsDelete != 1)?.map(v => ({ value: v.id, label: v.pepProjectName || v.name }))) setOnlineId('')
let data = res.payload.data
setOnlineStruc(data?.map(v => ({ value: v.strucId, label: v.strucName })) || [])
setOnline(data?.slice(0, 10) || [])
setValue(data?.map(v => v.strucId)?.slice(0, 10) || [])
} }
} })
}, [pepProjectId, projectPoms])
await dispatch(control.getStrucSeries({ pepProjectId: pepProjectId })).then(res => {
if (res.success) {
setSuccessionId('')
setSeriesValue('')
let data = res.payload.data?.filter(s => !successionId || s?.struc?.pomsProject?.map(p => p.id)?.includes(successionId))
setSeriesStruc(data?.map(v => ({ value: v.id, label: v.name })) || [])
setSeries(data?.slice(0, 10) || [])
setSensorList(data?.map(v => ({ value: v.id, label: v.name })) || [])
setSensorValue(data?.map(v => v.id)?.slice(0, 10) || [])
}
})
useEffect(() => { if (pepProjectId) {
setOnlineId('') 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 })))
dispatch(control.getStatisticOnline({ pepProjectId: onlineId || pepProjectId })).then(res => { if (!pepProjectId?.length > 0 || pepProjectId.split(",")?.length == 1) {
if (res.success) { setFaultId(Number(pepProjectId))
let data = res.payload.data?.filter(s => !onlineId || s.pomsProject?.map(p => p.id)?.includes(onlineId)) setOnlineId(Number(pepProjectId))
setOnlineStruc(data?.map(v => ({ value: v.strucId, label: v.strucName })) || []) setSuccessionId(Number(pepProjectId))
setOnline(data?.slice(0, 10) || []) }
setValue(data?.map(v => v.strucId)?.slice(0, 10) || []) } else {
setPomsList(projectPoms?.filter(v => v.pepProjectIsDelete != 1)?.map(v => ({ value: v.id, label: v.pepProjectName || v.name })))
} }
})
}, [onlineId, pepProjectId])
useEffect(() => { }
setSuccessionId('') }, [pepProjectId, projectPoms])
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) => { const getRank = async (data) => {
let dataList = [] let dataList = []
@ -137,6 +149,8 @@ const AlarmChart = ({ dispatch, actions, user, history, projectPoms, loading, so
} }
const getData = async (radio, pepProjectId, diff1, diff2) => { const getData = async (radio, pepProjectId, diff1, diff2) => {
if (diff2) setStatisticsSpin(true)
if (diff1) setRankSpin(true)
let data = {} let data = {}
await dispatch(control.getAlarmData({ await dispatch(control.getAlarmData({
pepProjectId: pepProjectId, pepProjectId: pepProjectId,
@ -206,7 +220,8 @@ const AlarmChart = ({ dispatch, actions, user, history, projectPoms, loading, so
} }
}) })
} }
setStatisticsSpin(false)
setRankSpin(false)
return data return data
} }
@ -214,7 +229,7 @@ const AlarmChart = ({ dispatch, actions, user, history, projectPoms, loading, so
const behindHandle = (key) => { const behindHandle = (key) => {
let show = [] let show = []
switch (key) { switch (key) {
case '数据中': case '数据中':
dispatch(problem.getAlarmDataGroup()).then((res) => { dispatch(problem.getAlarmDataGroup()).then((res) => {
if (res.success) { if (res.success) {
let data = res.payload.data?.find(v => v.desc == '数据中断')?.unit || [] let data = res.payload.data?.find(v => v.desc == '数据中断')?.unit || []
@ -354,228 +369,246 @@ const AlarmChart = ({ dispatch, actions, user, history, projectPoms, loading, so
<div style={{ display: "flex" }}> <div style={{ display: "flex" }}>
{/* 故障数统计 */} {/* 故障数统计 */}
<div style={{ padding: 16, width: '50%', height: 300 }}> <div style={{ padding: 16, width: '50%', height: 300 }}>
{behind ? <Spin spinning={statisticsSpin} tip="数据加载中...">
<> {behind ?
<div style={{ display: "flex", justifyContent: "space-between" }}> <>
<div style={{ fontSize: 18, fontWeight: 'bold', color: "#0b0b0bbd" }}>故障数统计</div> <div style={{ display: "flex", justifyContent: "space-between" }}>
<div> <div style={{ fontSize: 18, fontWeight: 'bold', color: "#0b0b0bbd" }}>故障数统计</div>
<Select showClear filter placeholder='项目' value={faultId} style={{ width: 160, marginRight: 10 }} <div>
onChange={(v) => { <Select showClear filter placeholder='项目' value={faultId} style={{ width: 160, marginRight: 10 }}
setFaultId(v) onChange={(v) => {
getData(radioStatistics, v, false, true) setFaultId(v)
}} getData(radioStatistics, v, false, true)
optionList={pomsList} }}
/> optionList={pomsList}
<RadioGroup type='button' buttonSize='middle' value={radioStatistics} style={{ marginRight: 10 }} />
onChange={e => { <RadioGroup type='button' buttonSize='middle' value={radioStatistics} style={{ marginRight: 10 }}
setRadioStatistics(e.target.value) onChange={e => {
getData(e.target.value, pepProjectId, false, true) setRadioStatistics(e.target.value)
}} getData(e.target.value, pepProjectId, false, true)
> }}
<Radio value="day">今日</Radio> >
<Radio value="week">本周</Radio> <Radio value="day">今日</Radio>
<Radio value="month">本月</Radio> <Radio value="week">本周</Radio>
</RadioGroup> <Radio value="month">本月</Radio>
</RadioGroup>
</div>
</div> </div>
</div> <div style={{ display: 'flex', padding: 16, height: "100%" }}>
<div style={{ display: 'flex', padding: 16, height: "100%" }}> <div style={{ display: "flex", flexDirection: "column", justifyContent: "space-evenly", width: 180 }}>
<div style={{ display: "flex", flexDirection: "column", justifyContent: "space-evenly", width: 180 }}> <div style={{ display: 'flex', justifyContent: "space-between", cursor: 'pointer' }} onClick={() => behindHandle('数据中段')}>
<div style={{ display: 'flex', justifyContent: "space-between", cursor: 'pointer' }} onClick={() => behindHandle('数据中段')}> <div>数据中断</div>
<div>数据中段</div> <div style={{ fontWeight: 500 }}>
<div style={{ fontWeight: 500 }}> <sapn style={{ color: "red" }}>{dataAlarm?.group1?.untreated || 0}</sapn> /
<sapn style={{ color: "red" }}>{dataAlarm?.group1?.untreated || 0}</sapn> / <span style={{ color: "rgb(48 47 138)" }}>{dataAlarm?.group1?.sum || 0}</span>
<span style={{ color: "rgb(48 47 138)" }}>{dataAlarm?.group1?.sum || 0}</span> </div>
</div> </div>
</div> <div style={{ display: 'flex', justifyContent: "space-between", cursor: 'pointer' }} onClick={() => behindHandle('数据异常')}>
<div style={{ display: 'flex', justifyContent: "space-between", cursor: 'pointer' }} onClick={() => behindHandle('数据异常')}> <div>数据异常</div>
<div>数据异常</div> <div style={{ fontWeight: 500 }}>
<div style={{ fontWeight: 500 }}> <sapn style={{ color: "red" }}>{dataAlarm?.group2?.untreated || 0}</sapn> /
<sapn style={{ color: "red" }}>{dataAlarm?.group2?.untreated || 0}</sapn> / <span style={{ color: "rgb(48 47 138)" }}>{dataAlarm?.group2?.sum || 0}</span>
<span style={{ color: "rgb(48 47 138)" }}>{dataAlarm?.group2?.sum || 0}</span> </div>
</div> </div>
</div> <div style={{ display: 'flex', justifyContent: "space-between", cursor: 'pointer' }} onClick={() => behindHandle('策略命中')}>
<div style={{ display: 'flex', justifyContent: "space-between", cursor: 'pointer' }} onClick={() => behindHandle('策略命中')}> <div>策略命中</div>
<div>策略命中</div> <div style={{ fontWeight: 500 }}>
<div style={{ fontWeight: 500 }}> <sapn style={{ color: "red" }}>{dataAlarm?.group3?.untreated || 0}</sapn> /
<sapn style={{ color: "red" }}>{dataAlarm?.group3?.untreated || 0}</sapn> / <span style={{ color: "rgb(48 47 138)" }}>{dataAlarm?.group3?.sum || 0}</span>
<span style={{ color: "rgb(48 47 138)" }}>{dataAlarm?.group3?.sum || 0}</span> </div>
</div> </div>
</div>
<div style={{ display: 'flex', justifyContent: "space-between", cursor: 'pointer' }} onClick={() => behindHandle('视频异常')}> <div style={{ display: 'flex', justifyContent: "space-between", cursor: 'pointer' }} onClick={() => behindHandle('视频异常')}>
<div>视频异常</div> <div>视频异常</div>
<div style={{ fontWeight: 500 }}> <div style={{ fontWeight: 500 }}>
<sapn style={{ color: "red" }}>{videoAlarm?.untreated || 0}</sapn> / <sapn style={{ color: "red" }}>{videoAlarm?.untreated || 0}</sapn> /
<span style={{ color: "rgb(48 47 138)" }}>{videoAlarm?.sum || 0}</span> <span style={{ color: "rgb(48 47 138)" }}>{videoAlarm?.sum || 0}</span>
</div>
</div> </div>
</div> <div style={{ display: 'flex', justifyContent: "space-between", cursor: 'pointer' }} onClick={() => behindHandle('应用异常')}>
<div style={{ display: 'flex', justifyContent: "space-between", cursor: 'pointer' }} onClick={() => behindHandle('应用异常')}> <div>应用异常</div>
<div>应用异常</div> <div style={{ fontWeight: 500 }}>
<div style={{ fontWeight: 500 }}> <sapn style={{ color: "red" }}>{useAlarm?.untreated || 0}</sapn> /
<sapn style={{ color: "red" }}>{useAlarm?.untreated || 0}</sapn> / <span style={{ color: "rgb(48 47 138)" }}>{useAlarm?.sum || 0}</span>
<span style={{ color: "rgb(48 47 138)" }}>{useAlarm?.sum || 0}</span> </div>
</div> </div>
</div>
<div style={{ display: 'flex', justifyContent: "space-between", cursor: 'pointer' }} onClick={() => behindHandle('设备异常')}> <div style={{ display: 'flex', justifyContent: "space-between", cursor: 'pointer' }} onClick={() => behindHandle('设备异常')}>
<div>设备异常</div> <div>设备异常</div>
<div style={{ fontWeight: 500 }}> <div style={{ fontWeight: 500 }}>
<sapn style={{ color: "red" }}>{(dataAlarm?.group4?.untreated || 0) + (dataAlarm?.group5?.untreated || 0)}</sapn> / <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> <span style={{ color: "rgb(48 47 138)" }}>{(dataAlarm?.group4?.sum || 0) + (dataAlarm?.group5?.sum || 0)}</span>
</div>
</div> </div>
</div> </div>
<div style={{ width: 'calc(100% - 180px)', display: 'flex', justifyContent: 'center', alignItems: 'center', fontSize: 46, fontWeight: 600 }}>
<div style={{ fontWeight: 500 }}>
</div> {(dataAlarm?.group1?.untreated || 0)
<div style={{ width: 'calc(100% - 180px)', display: 'flex', justifyContent: 'center', alignItems: 'center', fontSize: 46, fontWeight: 600 }}> + (dataAlarm?.group2?.untreated || 0)
<div style={{ fontWeight: 500 }}> + (dataAlarm?.group3?.untreated || 0)
+ (dataAlarm?.group4?.untreated || 0)
{(dataAlarm?.group1?.untreated || 0) + (dataAlarm?.group5?.untreated || 0)
+ (dataAlarm?.group2?.untreated || 0) + (videoAlarm?.untreated || 0)
+ (dataAlarm?.group3?.untreated || 0) + (useAlarm?.untreated || 0)
+ (dataAlarm?.group4?.untreated || 0) }
+ (dataAlarm?.group5?.untreated || 0) /
+ (videoAlarm?.untreated || 0) {(dataAlarm?.group1?.sum || 0)
+ (useAlarm?.untreated || 0) + (dataAlarm?.group2?.sum || 0)
} + (dataAlarm?.group3?.sum || 0)
/ + (dataAlarm?.group4?.sum || 0)
{(dataAlarm?.group1?.sum || 0) + (dataAlarm?.group5?.sum || 0)
+ (dataAlarm?.group2?.sum || 0) + (videoAlarm?.sum || 0)
+ (dataAlarm?.group3?.sum || 0) + (useAlarm?.sum || 0)
+ (dataAlarm?.group4?.sum || 0) }
+ (dataAlarm?.group5?.sum || 0)
+ (videoAlarm?.sum || 0)
+ (useAlarm?.sum || 0)
}
</div>
</div> </div>
</div> </div>
</div> </>
</> : <div onClick={() => {
: <div onClick={() => { setBehindShow([])
setBehindShow([]) setBehind(true)
setBehind(true) }}>
}}> <ReactECharts
<ReactECharts option={{
option={{ title: {
title: { text: '故障数统计',
text: '故障数统计', },
}, grid: {
grid: { left: '10%',
left: '10%', // right: '4%',
// right: '4%', // bottom: '3%',
// bottom: '3%', // containLabel: true
// containLabel: true },
}, // dataZoom: [
// dataZoom: [ // {
// { // type: 'slider',
// type: 'slider', // // startValue: behindShow?.map(v => v.name) || []
// // startValue: behindShow?.map(v => v.name) || [] // },
// }, // {
// { // type: 'inside',
// type: 'inside', // },
// }, // ],
// ], tooltip: {
tooltip: { trigger: 'axis'
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) || []
}, },
{ legend: {
type: 'bar', data: ['未处理', '已处理'],
name: '已处理', right: '10%',
smooth: true,
itemStyle: { color: '#0ddf42', },
barWidth: 20,
data: behindShow?.map(v => v.processed) || []
}, },
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>
}
</Spin>
]
}}
notMerge={true}
lazyUpdate={true}
// onChartReady={this.onChartReadyCallback}
// onEvents={EventsDict}
// opts={}
/>
</div>
}
</div> </div>
{/* 故障数排名*/} {/* 故障数排名*/}
<div style={{ padding: 10, width: '50%', height: 300, position: "relative" }}> <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 }} <Spin spinning={rankSpin} tip="数据加载中...">
onChange={async e => { <RadioGroup type='button' buttonSize='middle' value={radioRank} style={{ marginRight: 10, zIndex: 10, position: "absolute", top: 8, left: 112 }}
setRadioRank(e.target.value) onChange={async e => {
let data = await getData(e.target.value, pepProjectId, true, false) setRadioRank(e.target.value)
await getRank(data) let data = await getData(e.target.value, pepProjectId, true, false)
}} await getRank(data)
> }}
<Radio value="day">今日</Radio> >
<Radio value="week">本周</Radio> <Radio value="day">今日</Radio>
<Radio value="month">本月</Radio> <Radio value="week">本周</Radio>
</RadioGroup> <Radio value="month">本月</Radio>
<ReactECharts </RadioGroup>
option={{ <ReactECharts
title: { option={{
text: '故障数排名', title: {
}, text: '故障数排名',
grid: { },
left: '10%', grid: {
// right: '4%', left: 70,
// bottom: '3%', // right: '4%',
// containLabel: true // bottom: '3%',
}, // containLabel: true
tooltip: { },
trigger: 'axis' tooltip: {
}, trigger: 'axis',
legend: { formatter: function (params) {
data: ['故障数'], // 自定义提示框内容
right: '10%', // console.log(params);
}, let title = rankData[params[0].dataIndex]?.name + '<br/>' + '<br/>' + params[0]?.seriesName + ":" + "&nbsp" + "&nbsp" + params[0]?.value
yAxis: { return title
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) || []
}, },
legend: {
data: ['未处理故障数'],
right: '10%',
},
yAxis: {
type: 'category',
data: rankData?.map(v => {
if (v.name?.length > 4) {
return v.name?.slice(0, 4) + '...'
} else {
return 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={}
/>
</Spin>
]
}}
notMerge={true}
lazyUpdate={true}
// onChartReady={this.onChartReadyCallback}
// onEvents={EventsDict}
// opts={}
/>
</div> </div>
</div> </div>
<div style={{ display: "flex" }}> <div style={{ display: "flex" }}>
@ -585,6 +618,10 @@ const AlarmChart = ({ dispatch, actions, user, history, projectPoms, loading, so
<Select filter showClear placeholder='项目' value={onlineId} style={{ width: 160, marginRight: 10 }} <Select filter showClear placeholder='项目' value={onlineId} style={{ width: 160, marginRight: 10 }}
onChange={(v) => { onChange={(v) => {
setOnlineId(v) setOnlineId(v)
let data = statisticOnline?.filter(s => !v || s.pomsProject?.map(p => p.id)?.includes(v))
setOnlineStruc(data?.map(v => ({ value: v.strucId, label: v.strucName })) || [])
setOnline(data?.slice(0, 10) || [])
setValue(data?.map(v => v.strucId)?.slice(0, 10) || [])
}} }}
optionList={pomsList} optionList={pomsList}
/> />
@ -661,6 +698,18 @@ const AlarmChart = ({ dispatch, actions, user, history, projectPoms, loading, so
<Select filter showClear placeholder='项目' value={successionId} style={{ width: 160, marginRight: 10 }} <Select filter showClear placeholder='项目' value={successionId} style={{ width: 160, marginRight: 10 }}
onChange={(v) => { onChange={(v) => {
setSuccessionId(v) setSuccessionId(v)
setSeriesValue('')
let data = strucSeries?.filter(s => !v || s?.struc?.pomsProject?.map(p => p.id)?.includes(v))
let struc = []
data?.forEach(f => {
if (!struc?.find(h => h.value == f.structure)) {
struc.push({ value: f.structure, label: f?.struc?.strucName })
}
})
setSeriesStruc(struc)
setSeries(data?.slice(0, 10) || [])
setSensorList(data?.slice(0, 10)?.map(v => ({ value: v.id, label: v.name })) || [])
setSensorValue(data?.slice(0, 10)?.map(d => d.id) || [])
}} }}
optionList={pomsList} optionList={pomsList}
/> />
@ -674,8 +723,24 @@ const AlarmChart = ({ dispatch, actions, user, history, projectPoms, loading, so
optionList={seriesStruc} optionList={seriesStruc}
onChange={v => { onChange={v => {
setSeriesValue(v) setSeriesValue(v)
let data = strucSeries?.filter(s => !onlineId || s.pomsProject?.map(p => p.id)?.includes(onlineId)) let data = strucSeries?.filter(s => (!v.length > 0 || v.includes(s.structure)) && (!successionId || s.pomsProject?.map(p => p.id)?.includes(successionId)))
setSeries(data?.filter(s => v.includes(s.strucId))) setSeries(data?.slice(0, 10) || [])
setSensorList(data?.slice(0, 10)?.map(v => ({ value: v.id, label: v.name })) || [])
setSensorValue(data?.slice(0, 10)?.map(d => d.id) || [])
}}
/>
<Select showClear
filter
placeholder='测点'
value={sensorValue}
multiple={true}
maxTagCount={1}
style={{ width: 160, marginRight: 10 }}
optionList={sensorList}
onChange={v => {
setSensorValue(v)
let data = strucSeries?.filter(s => (!v.length > 0 || v.includes(s.id)) && (!seriesValue?.length > 0 || seriesValue?.includes(s.structure)) && (!successionId || s.pomsProject?.map(p => p.id)?.includes(successionId)))
setSeries(data || [])
}} }}
/> />
@ -683,7 +748,7 @@ const AlarmChart = ({ dispatch, actions, user, history, projectPoms, loading, so
<ReactECharts <ReactECharts
option={{ option={{
title: { title: {
text: '数据在线率', text: '数据连续率',
}, },
grid: { grid: {
left: 27, left: 27,
@ -694,11 +759,11 @@ const AlarmChart = ({ dispatch, actions, user, history, projectPoms, loading, so
trigger: 'axis', trigger: 'axis',
formatter: function (params) { formatter: function (params) {
// 自定义提示框内容 // 自定义提示框内容
// console.log(params); let title = params[0]?.data[0] + '<br/>' + '<br/>'
let title = params[0].data[0] + '<br/>' + '<br/>'
params.forEach(v => { 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]) || {} let find = series?.find(s => s.name == v.seriesName) || {}
title = title + v.seriesName + ":" + "&nbsp" + "&nbsp" + v.data[1] + "%" + "(" + find?.num + "/" + find?.tTotal + ")" + '<br/>' let findOne = find?.series?.find(d => moment(d.collect_time).format('YYYY-MM-DD HH') == v.data[0]) || {}
title = title + find?.name + ":" + "&nbsp" + "&nbsp" + v.data[1] * 100 + "%" + "(" + findOne?.tTotal + "/" + (findOne?.num || findOne?.tTotal) + ")" + '<br/>'
}) })
return title return title
} }
@ -718,7 +783,7 @@ const AlarmChart = ({ dispatch, actions, user, history, projectPoms, loading, so
}, },
series: series?.map(v => ({ series: series?.map(v => ({
type: 'line', type: 'line',
name: v.strucName, name: v.name,
smooth: true, smooth: true,
areaStyle: { areaStyle: {
color: '#0e9cff26', color: '#0e9cff26',

2
web/client/src/sections/control/containers/control.jsx

@ -620,7 +620,7 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
dynamic: ['discovery', 'notice', 'handle', 'confirm'], dynamic: ['discovery', 'notice', 'handle', 'confirm'],
} }
let show = { let show = {
overall: ['workbench', 'statistical', 'dataAnalyse'], overall: ['workbench', 'dataAnalyse'],
workbench: ['project', 'data', 'app', 'device'], workbench: ['project', 'data', 'app', 'device'],
statistical: ['milestone', 'personnel', 'web', 'problem'], statistical: ['milestone', 'personnel', 'web', 'problem'],
analyse: ['dataInterrupt', 'dataAbnormal', 'policyHit', 'videoException', 'appAbnormal', 'deviceAbnormal', 'problemAnalysis'], analyse: ['dataInterrupt', 'dataAbnormal', 'policyHit', 'videoException', 'appAbnormal', 'deviceAbnormal', 'problemAnalysis'],

Loading…
Cancel
Save