You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
482 lines
16 KiB
482 lines
16 KiB
import React, { useEffect, useState } from 'react'
|
|
import { Spin, Popconfirm, message, Button, Input } from 'antd'
|
|
import { connect } from 'react-redux'
|
|
import ProTable from '@ant-design/pro-table'
|
|
import moment from 'moment'
|
|
import ReactEcharts from 'echarts-for-react'
|
|
import PerfectScrollbar from 'perfect-scrollbar'
|
|
import '../style.less'
|
|
import AutoRollComponent from '../AutoRollComponent'
|
|
|
|
let scrollbarLeft
|
|
let problems
|
|
const Left = props => {
|
|
const { dispatch, clientHeight, clientWidth, actions } = props
|
|
const [startTime, setStartTime] = useState(moment().startOf('week').format('YYYY-MM-DD HH:mm:ss'))
|
|
const [endTime, setEndTime] = useState(moment().endOf('week').format('YYYY-MM-DD HH:mm:ss'))
|
|
const [plan, setPlan] = useState(0)
|
|
const [done, setDone] = useState(0)
|
|
const [cRate, setCRate] = useState([]) //完成率
|
|
const [rRate, setRRate] = useState([]) //修复率
|
|
const [months, setMonths] = useState([])
|
|
const [period, setPeriod] = useState('week')
|
|
const [rank,setRank]=useState([])
|
|
const [state, setState] = useState(0)
|
|
const [rankCopy,setRankCopy]=useState([])//用于排序(巡检次数)
|
|
const { bigScreen } = actions
|
|
// const questFontColor = { color: '#8f7a49' } //有问题的颜色
|
|
const normalFontColor = { color: 'yellow' } //正常的颜色
|
|
useEffect(() => {
|
|
scrollbarLeft = new PerfectScrollbar('#left1', { suppressScrollX: true })
|
|
const dom = document.getElementById('left1')
|
|
if (dom) {
|
|
scrollbarLeft.update()
|
|
// dom.scrollTop = 0
|
|
}
|
|
// getData()
|
|
queryData()
|
|
const months = generateMonthNames()
|
|
setMonths(months)
|
|
}, [])
|
|
useEffect(() => {
|
|
getData()
|
|
}, [startTime])
|
|
|
|
const queryData = async () => {
|
|
let repair = []
|
|
const structArr = JSON.parse(sessionStorage.getItem('user')).monitorObject
|
|
const sTime = moment().subtract(6, 'months').format('YYYY-MM-DD HH:mm:ss')
|
|
const eTime = moment().format('YYYY-MM-DD HH:mm:ss')
|
|
// let count={}
|
|
let cRate = []
|
|
for (let i = 5; i >= 0; i--) {
|
|
const currentTime = moment()
|
|
const startOfMonth = currentTime.subtract(i, 'months').startOf('month')
|
|
const startTime = startOfMonth.format('YYYY-MM-DD HH:mm:ss')
|
|
const endTime = startOfMonth.endOf('month').format('YYYY-MM-DD HH:mm:ss')
|
|
await dispatch(bigScreen.findPatrolRecords({ projectId: structArr.toString(), startTime, endTime })).then(res => {
|
|
if (res.success) {
|
|
const data = res.payload.data
|
|
// count[i] = { plan: data.planCount, done: data.done, rate:((data.done/data.planCount+data.done)*100).toFixed(2) }
|
|
cRate.push(
|
|
Number(data.planCount + data.done > 0 ? ((data.done / (data.planCount + data.done)) * 100).toFixed(2) : 0)
|
|
)
|
|
}
|
|
})
|
|
}
|
|
setCRate(cRate)
|
|
dispatch(bigScreen.findPatrolRate({ projectId: structArr.toString(), startTime: sTime, endTime: eTime })).then(
|
|
res => {
|
|
if (res.success) {
|
|
const data = res.payload.data
|
|
if (data && data.length) {
|
|
const repairObject = {}
|
|
for (let i = 0; i < 6; i++) {
|
|
const currentDate = moment().subtract(i, 'months')
|
|
const month = currentDate.month() + 1
|
|
const year = currentDate.year()
|
|
repairObject[`${year}-${month}`] = { done: 0, quests: 0, ratio: 0 }
|
|
}
|
|
data.forEach(item => {
|
|
const createTime = moment(item.patrolRecordIssueHandles[0].createTime)
|
|
const month = createTime.month()+1
|
|
const year = createTime.year()
|
|
const state = item.patrolRecordIssueHandles[0].state
|
|
if (state === 6) {
|
|
repairObject[`${year}-${month}`].done++
|
|
}
|
|
|
|
repairObject[`${year}-${month}`].quests++
|
|
})
|
|
//计算比例
|
|
Object.values(repairObject).forEach(item => {
|
|
repair.push(item.quests === 0 ? 0 : Number((item.done / item.quests * 100).toFixed(2)));
|
|
});
|
|
setRRate(repair)
|
|
}
|
|
}
|
|
}
|
|
)
|
|
dispatch(bigScreen.countByProject({ projectId: structArr.toString()})).then(res=>{
|
|
if(res.success){
|
|
//[{},{},{},{},{},{},{},{}]||
|
|
// [{id:1,issueHandleCount:1,patrolRecordCount:2},
|
|
// {id:1,issueHandleCount:2,patrolRecordCount:3},
|
|
// {id:1,issueHandleCount:3,patrolRecordCount:2},
|
|
// {id:1,issueHandleCount:6,patrolRecordCount:4},
|
|
// {id:1,issueHandleCount:7,patrolRecordCount:5},
|
|
// {id:1,issueHandleCount:10,patrolRecordCount:6},
|
|
// {id:1,issueHandleCount:11,patrolRecordCount:7},
|
|
// {id:1,issueHandleCount:19,patrolRecordCount:9}]
|
|
const data=res.payload.data
|
|
if(data.length>4){
|
|
let problemstop = 0
|
|
let problemsId = document.getElementById('left1');
|
|
if (problems) clearInterval(problems)
|
|
if (problemsId) {
|
|
let problems;
|
|
let problemstop = 0;
|
|
|
|
function problemstart() {
|
|
problems = setInterval(() => {
|
|
problemstop += 5;
|
|
problemsId.scrollTop = problemstop;
|
|
if (problemsId.scrollTop >= (problemsId.scrollHeight - 90) / 2) {
|
|
problemstop = 0;
|
|
problemsId.scrollTop = problemstop;
|
|
}
|
|
}, 500);
|
|
|
|
problemsId.onmouseover = () => clearInterval(problems);
|
|
}
|
|
|
|
problemsId.onmouseout = () => problemstart();
|
|
|
|
setTimeout(problemstart, 1000);
|
|
}
|
|
}
|
|
if(data.length>10){
|
|
setRank(data.slice(0,10))
|
|
}else{
|
|
setRank(data)
|
|
|
|
}
|
|
setRankCopy(data)
|
|
}
|
|
})
|
|
}
|
|
|
|
function generateMonthNames() {
|
|
const currentTime = moment()
|
|
const monthNames = []
|
|
for (let i = 0; i < 6; i++) {
|
|
const currentMonth = currentTime.clone().subtract(i, 'months').format('MMMM')
|
|
monthNames.unshift(currentMonth)
|
|
}
|
|
return monthNames
|
|
}
|
|
|
|
const getData = () => {
|
|
const structArr = JSON.parse(sessionStorage.getItem('user')).monitorObject
|
|
dispatch(bigScreen.findPatrolRecords({ projectId: structArr.toString(), startTime, endTime })).then(res => {
|
|
if (res.success) {
|
|
const data = res.payload.data
|
|
setPlan(data.planCount)
|
|
setDone(data.done)
|
|
}
|
|
})
|
|
}
|
|
const selectTime = time => {
|
|
if (time === 'week') {
|
|
setPeriod('week')
|
|
setStartTime(moment().startOf('week').format('YYYY-MM-DD HH:mm:ss'))
|
|
setEndTime(moment().endOf('week').format('YYYY-MM-DD HH:mm:ss'))
|
|
} else {
|
|
setPeriod('month')
|
|
setStartTime(moment().startOf('month').format('YYYY-MM-DD HH:mm:ss'))
|
|
setEndTime(moment().endOf('month').format('YYYY-MM-DD HH:mm:ss'))
|
|
}
|
|
}
|
|
|
|
const topClick=(e)=>{
|
|
switch (e) {
|
|
case 'perBottom':
|
|
const rs=rankCopy.sort((a,b)=>b.patrolRecordCount-a.patrolRecordCount)
|
|
if(rs.length>10){
|
|
setRank(rs.slice(0,10))
|
|
}else{
|
|
setRank(rs)
|
|
}
|
|
setState(1)
|
|
break;
|
|
case 'perTop':
|
|
const rs1=rankCopy.sort((a,b)=>a.patrolRecordCount-b.patrolRecordCount)
|
|
if(rs1.length>10){
|
|
setRank(rs1.slice(0,10))
|
|
}else{
|
|
setRank(rs1)
|
|
}
|
|
setState(0)
|
|
break;
|
|
case 'timeBottom':
|
|
const rs2=rankCopy.sort((a,b)=>b.issueHandleCount-a.issueHandleCount)
|
|
if(rs2.length>10){
|
|
setRank(rs2.slice(0,10))
|
|
}else{
|
|
setRank(rs2)
|
|
}
|
|
setState(3)
|
|
break;
|
|
case 'timeTop':
|
|
const rs3=rankCopy.sort((a,b)=>a.issueHandleCount-b.issueHandleCount)
|
|
if(rs3.length>10){
|
|
setRank(rs3.slice(0,10))
|
|
}else{
|
|
setRank(rs3)
|
|
}
|
|
setState(2)
|
|
break;
|
|
default:
|
|
return
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
<>
|
|
{/* 左一 */}
|
|
{/**backgroundImage: 'linear-gradient(269deg, #000080ff 0%, #1a0080ff 58%, #3d0080ff 100%)' */}
|
|
<div>
|
|
<div style={{ position: 'relative' }} className='contanier1'>
|
|
<div
|
|
style={{
|
|
display: 'flex',
|
|
justifyContent: 'space-between',
|
|
height: '2.6875rem',
|
|
background: 'url(/assets/bigScreen/cardHeader.png)',
|
|
backgroundSize: '100% 100%',
|
|
backgroundRepeat: 'no-repeat',
|
|
}}>
|
|
<div className='title'>巡检数据统计</div>
|
|
<div className='monthOrWeek'>
|
|
<span
|
|
style={{ color: period === 'week' ? '#6EECE9' : '#8FCFFF' }}
|
|
onClick={() => {
|
|
selectTime('week')
|
|
}}>
|
|
周
|
|
</span>
|
|
|
|
|
<span
|
|
style={{ color: period === 'month' ? '#6EECE9' : '#8FCFFF' }}
|
|
onClick={() => {
|
|
selectTime('month')
|
|
}}>
|
|
月
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div
|
|
style={{
|
|
width: '26.3125rem',
|
|
height: '9.5625rem',
|
|
display: 'flex',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
}}>
|
|
<img src='/assets/bigScreen/doneRate.png'></img>
|
|
</div>
|
|
<div className='rate' style={{ bottom: '6.5125rem', left: '11.875rem' }}>
|
|
{`${plan > 0 ? ((done / done + plan) * 100).toFixed(2) : 0}%`}
|
|
</div>
|
|
<div style={{ display: 'flex', justifyContent: 'center', marginTop: '.5rem' }}>当前巡检完成率</div>
|
|
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
<div
|
|
style={{
|
|
background: 'url(/assets/bigScreen/plan.png)',
|
|
width: '10.375rem',
|
|
height: '3.625rem',
|
|
position: 'relative',
|
|
marginLeft: '.7rem',
|
|
backgroundSize: '100% 100%',
|
|
}}>
|
|
<div
|
|
style={{
|
|
position: 'absolute',
|
|
bottom: '1.7rem',
|
|
right: '2.35rem',
|
|
width: '3.75rem',
|
|
height: '.75rem',
|
|
textAlign: 'center',
|
|
}}
|
|
className='plan'>
|
|
计划巡检数
|
|
</div>
|
|
<div
|
|
style={{
|
|
position: 'absolute',
|
|
bottom: '.1044rem',
|
|
right: '2.35rem',
|
|
width: '3.75rem',
|
|
height: '1.375rem',
|
|
textAlign: 'center',
|
|
}}
|
|
className='number'>
|
|
{plan}
|
|
</div>
|
|
</div>
|
|
<div
|
|
style={{
|
|
background: 'url(/assets/bigScreen/plan.png)',
|
|
width: '10.375rem',
|
|
height: '3.625rem',
|
|
position: 'relative',
|
|
marginLeft: '.7rem',
|
|
backgroundSize: '100% 100%',
|
|
marginRight: '.625rem',
|
|
}}>
|
|
<div
|
|
style={{
|
|
position: 'absolute',
|
|
bottom: '1.7rem',
|
|
right: '1.75rem',
|
|
width: '4.75rem',
|
|
height: '.75rem',
|
|
textAlign: 'center',
|
|
}}
|
|
className='plan'>
|
|
已完成巡检数
|
|
</div>
|
|
<div
|
|
style={{
|
|
position: 'absolute',
|
|
bottom: '.1044rem',
|
|
right: '1.75rem',
|
|
width: '4.75rem',
|
|
height: '1.375rem',
|
|
textAlign: 'center',
|
|
}}
|
|
className='number'>
|
|
{done}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{/* 左二 */}
|
|
<div className='contanier' style={{ height: '17.8125rem' }}>
|
|
<div
|
|
style={{
|
|
display: 'flex',
|
|
justifyContent: 'space-between',
|
|
height: '2.5rem',
|
|
background: 'url(/assets/bigScreen/cardHeader.png)',
|
|
backgroundSize: '100% 100%',
|
|
backgroundRepeat: 'no-repeat',
|
|
}}>
|
|
<div className='title'>巡检成效评估</div>
|
|
{/* <div className='monthOrWeek'>{'更多' + '>>'}</div> */}
|
|
</div>
|
|
<ReactEcharts
|
|
style={{ height: '13.4375rem', width: '25.2662rem' }}
|
|
option={{
|
|
tooltip: {
|
|
trigger: 'axis',
|
|
axisPointer: {
|
|
type: 'shadow',
|
|
},
|
|
},
|
|
legend: {
|
|
right: 0,
|
|
textStyle: { color: '#CCE6FF' },
|
|
},
|
|
grid: {
|
|
left: '3%',
|
|
right: '4%',
|
|
bottom: '3%',
|
|
containLabel: true,
|
|
},
|
|
xAxis: [
|
|
{
|
|
type: 'category',
|
|
data: months,
|
|
},
|
|
],
|
|
yAxis: [
|
|
{
|
|
type: 'value',
|
|
name: '单位%',
|
|
},
|
|
],
|
|
series: [
|
|
{
|
|
name: '巡检完成率',
|
|
nameTextStyle: {
|
|
color: ' #CCE6FF',
|
|
fontSize: 14,
|
|
fontFamily: 'SourceHanSansCN-Medium',
|
|
},
|
|
type: 'bar',
|
|
stack: 'Search Engine',
|
|
// emphasis: {
|
|
// focus: 'series'
|
|
// },
|
|
data: cRate,
|
|
},
|
|
{
|
|
name: '故障修复率',
|
|
type: 'bar',
|
|
stack: 'Search Engine',
|
|
// emphasis: {
|
|
// focus: 'series'
|
|
// },
|
|
data: rRate,
|
|
},
|
|
],
|
|
}}></ReactEcharts>
|
|
</div>
|
|
{/* 左三 */}
|
|
<div className='contanier'>
|
|
<div
|
|
style={{
|
|
display: 'flex',
|
|
justifyContent: 'space-between',
|
|
height: '2.5rem',
|
|
background: 'url(/assets/bigScreen/cardHeader.png)',
|
|
backgroundSize: '100% 100%',
|
|
backgroundRepeat: 'no-repeat',
|
|
}}>
|
|
<div className='title'>巡检次数排名</div>
|
|
</div>
|
|
<div className='header' style={{ width: '24.3125rem' }}>
|
|
<div className='threeHeaderFontStyle'>序号</div>
|
|
<div className='threeHeaderFontStyle'>结构物</div>
|
|
<div className='threeHeaderFontStyle' style={{position:'relative'}}>巡检次数
|
|
<i class="angle_top" id={state==0?'angleSelected':null} onClick={()=>topClick('perTop')}></i>
|
|
<i id={state==1?'angleSelected':null} class="angle_bottom" onClick={()=>topClick('perBottom')}></i>
|
|
</div>
|
|
<div className='threeHeaderFontStyle'style={{position:'relative'}}>问题个数
|
|
<i class="angle_top" id={state==2?'angleSelected':null} onClick={()=>topClick('timeTop')}></i>
|
|
<i id={state==3?'angleSelected':null} class="angle_bottom" onClick={()=>topClick('timeBottom')}></i>
|
|
</div>
|
|
</div>
|
|
<div id='left1' style={{ width: '25.8125rem', height: '12rem', position: 'relative' }}>
|
|
|
|
{rank.map((item,index)=>(
|
|
<div className='thridCardItem' style={{ width: '24.3125rem' }}>
|
|
<div className='index1'>
|
|
<div>{index+1}</div>
|
|
</div>
|
|
<div className='name1' title={item.name}>{item.name}</div>
|
|
<div className='num1'>{item.patrolRecordCount}</div>
|
|
<div className='quests1' style={{ ...normalFontColor }}>
|
|
{item.issueHandleCount}
|
|
</div>
|
|
</div>
|
|
))}
|
|
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</>
|
|
)
|
|
}
|
|
|
|
function mapStateToProps(state) {
|
|
const { auth, global } = state
|
|
return {
|
|
clientHeight: global.clientHeight,
|
|
clientWidth: global.clientWidth,
|
|
actions: global.actions,
|
|
}
|
|
}
|
|
|
|
export default connect(mapStateToProps)(Left)
|
|
|