Столбцы страницы мониторинга переработы

This commit is contained in:
goodmice 2021-10-19 12:47:21 +05:00
parent 7f650b0041
commit 2f9efe938c
4 changed files with 285 additions and 198 deletions

View File

@ -2,51 +2,40 @@ import {ValueDisplay} from '../../components/Display'
import {ControlOutlined} from '@ant-design/icons' import {ControlOutlined} from '@ant-design/icons'
import {Popover} from 'antd' import {Popover} from 'antd'
export const ChartTimeOnlineFooter = (props) =>{ export const ChartTimeOnlineFooter = ({ data, lineGroup }) => {
const { data, const getFooterData = (name) => {
lineIdle, const dataIdx = data && lineGroup?.find(line => line?.footer === name)?.xAccessorName
lineSp, return (<ValueDisplay value={data?.[dataIdx]}/>)
linesOther} = props }
let sp = null let spValues = getFooterData('SP')
let idle = null const idleValues = getFooterData('IDLE')
if(data && lineSp) const popContent = lineGroup?.filter(line => line.footer === true).map(line => (
sp = data[lineSp.xAccessorName]
if(data && lineIdle)
idle = data[lineIdle.xAccessorName]
let spField = <ValueDisplay value={sp}/>
let popContent = linesOther?.map(line =>{
let val = null
if(data)
val = data[line.xAccessorName]
return (
<div key={line.label}> <div key={line.label}>
{line.label} {line.label}
<ValueDisplay value={val}/> <ValueDisplay value={data?.[line.xAccessorName]}/>
</div>) </div>
}) ))
if(popContent) return(
spField = <Popover content={popContent}> <div>
<div className="chart-footer"> {popContent?.length > 0 ? (
<ControlOutlined className='display_label'/> <Popover content={popContent}>
{spField} <div className={'chart-footer'}>
<ControlOutlined className={'display_label'}/>
<div style={{display: 'flex', flexDirection: 'column'}}>{spValues}</div>
</div> </div>
</Popover> </Popover>
else ) : (
spField = <div style={{display:"flex"}}> <div style={{display: 'flex', justifyContent: 'flex-end'}}>
{spField} <div style={{display: 'flex', flexDirection: 'column'}}>{spValues}</div>
</div> </div>
)}
return(<div> <div style={{display: 'flex'}}>
{spField}
<div style={{display:"flex"}}>
<span className='display_label'>х.х.</span> <span className='display_label'>х.х.</span>
<ValueDisplay value={idle}/> <div style={{display: 'flex', flexDirection: 'column'}}>{idleValues}</div>
</div> </div>
</div>) </div>
)
} }

View File

@ -1,45 +1,43 @@
import {Display} from "../../components/Display"; import {Grid, GridItem} from '../../components/Grid';
import {ChartTimeOnline} from "./ChartTimeOnline"; import {ChartTimeOnline} from './ChartTimeOnline';
import {ChartTimeOnlineFooter} from "./ChartTimeOnlineFooter"; import {ChartTimeOnlineFooter} from './ChartTimeOnlineFooter';
export const Column = ({lineGroup, data, interval, showBorder, style}) => { const stroke = (sz='1px', c='white') => ({ textShadow: `-${sz} -${sz} 0 ${c}, ${sz} -${sz} 0 ${c}, -${sz} ${sz} 0 ${c}, ${sz} ${sz} 0 ${c}` })
let lines = [lineGroup.linePv]
if (lineGroup.lineSp)
lines.push(lineGroup.lineSp)
if (lineGroup.lineOther)
lines.push(lineGroup.lineOther)
if (lineGroup.lineAvg)
lines.push(lineGroup.lineAvg)
if (lineGroup.lineMax)
lines.push(lineGroup.lineMax)
export const Column = ({lineGroup, data, interval, showBorder, style, headerHeight}) => {
let dataLast = null let dataLast = null
let pv = null let pv = null
if (data?.length > 0) { if (data?.length > 0) {
dataLast = data[data.length - 1]; dataLast = data[data.length - 1];
if (lineGroup.linePv) pv = lineGroup.filter(line => line.showValue).map(line => ({
pv = dataLast[lineGroup.linePv?.xAccessorName] color: line.color,
label: line.label,
unit: line.units,
value: dataLast[line.xAccessorName]
}))
} }
return ( return (
<div style={style}> <div style={style}>
<div style={{boxShadow: showBorder ? "inset 0px 0px 0px 3px black" : ""}}> <Grid style={{height: headerHeight, boxShadow: showBorder ? 'inset 0px 0px 0px 3px black' : ''}}>
<Display {pv?.map((v, idx) => (
label={lineGroup.label} <GridItem className={'display_chart_label'} key={idx} row={idx} col={1} style={{color: v.color}}>{v.label}</GridItem>
value={pv} ))}
suffix={lineGroup.linePv?.units} isArrowVisible={false}/> </Grid>
</div> <div style={{position: 'relative'}}>
<Grid className={'display_chart_values'}>
{pv?.map((v, idx) => (
<GridItem key={idx} col={1} row={idx} style={{...stroke(), color: v.color, padding: '0 4px'}}>{v.value.toFixed(2)} {v.unit}</GridItem>
))}
</Grid>
<ChartTimeOnline <ChartTimeOnline
data={data} data={data}
yDisplay={lineGroup.yDisplay} yDisplay={false}
lines={lines} lines={lineGroup}
interval={interval}/> interval={interval}
<ChartTimeOnlineFooter />
data={dataLast} </div>
{...lineGroup} /> <ChartTimeOnlineFooter data={dataLast} lineGroup={lineGroup} />
</div>) </div>
)
} }

View File

@ -1,17 +1,17 @@
import {useState, useEffect} from 'react' import { useState, useEffect } from 'react'
import {Select} from 'antd' import { Select } from 'antd'
import {Column} from './Column' import { Column } from './Column'
import {CustomColumn} from './CustomColumn' import { CustomColumn } from './CustomColumn'
import ActiveMessagesOnline from './ActiveMessagesOnline' import ActiveMessagesOnline from './ActiveMessagesOnline'
import {ModeDisplay} from "./ModeDisplay" import { ModeDisplay } from "./ModeDisplay"
import {UserOfWell} from './UserOfWells' import { UserOfWell } from './UserOfWells'
import LoaderPortal from '../../components/LoaderPortal' import LoaderPortal from '../../components/LoaderPortal'
import {Grid, GridItem, Flex} from '../../components/Grid' import { Grid, GridItem, Flex } from '../../components/Grid'
import {Subscribe} from '../../services/signalr' import { Subscribe } from '../../services/signalr'
import {TelemetryDataSaubService, TelemetryDataSpinService} from '../../services/api' import { TelemetryDataSaubService, TelemetryDataSpinService } from '../../services/api'
import {invokeWebApiWrapperAsync} from '../../components/factory' import { invokeWebApiWrapperAsync } from '../../components/factory'
import MomentStabPicEnabled from "../../images/DempherOn.png" import MomentStabPicEnabled from "../../images/DempherOn.png"
import MomentStabPicDisabled from "../../images/DempherOff.png" import MomentStabPicDisabled from "../../images/DempherOff.png"
@ -20,123 +20,207 @@ import SpinPicDisabled from "../../images/SpinDisabled.png"
import '../../styles/message.css' import '../../styles/message.css'
const {Option} = Select const { Option } = Select
const dash = [7, 3] const dash = [7, 3]
const blockHeightGroup = { const blockHeightGroup = [
{
label: "Высота блока", label: "Высота блока",
yDisplay: false, units: 'м',
linePv: {label: "blockPosition", units: 'м', xAccessorName: "blockPosition", yAccessorName: "date", color: '#333'}, xAccessorName: "blockPosition",
lineOther: { yAccessorName: "date",
color: '#333',
showValue: true
}, {
label: "wellDepth", label: "wellDepth",
units: 'м', units: 'м',
xAccessorName: "wellDepth", xAccessorName: "wellDepth",
yAccessorName: "date", yAccessorName: "date",
color: '#333', color: '#333',
showLine: false, showLine: false,
xConstValue: 30 xConstValue: 30,
}, dash
} }, {
label: 'Расход',
units: 'м³/ч',
xAccessorName: 'flow',
yAccessorName: 'date',
color: '#077',
showValue: true
}
]
const blockSpeedGroup = { const blockSpeedGroup = [
label: "Скорость блока",
yDisplay: false,
linePv: {label: "blockSpeed", units: 'м/ч', xAccessorName: "blockSpeed", yAccessorName: "date", color: '#0a0'},
lineSp: {label: "blockSpeedSp", units: 'м/ч', xAccessorName: "blockSpeedSp", yAccessorName: "date", color: '#0a0'},
}
const pressureGroup = {
label: "Давление",
yDisplay: false,
linePv: {label: "pressure", units: 'атм', xAccessorName: "pressure", yAccessorName: "date", color: '#c00'},
lineSp: {label: "pressureSp", units: 'атм', xAccessorName: "pressureSp", yAccessorName: "date", color: '#c00'},
lineIdle: {label: "pressureIdle", units: 'атм', xAccessorName: "pressureIdle", yAccessorName: "date", color: '#c00'},
linesOther: [
{ {
label: "мекс. перепад", label: "Скорость блока",
units: 'м/ч',
xAccessorName: "blockSpeed",
yAccessorName: "date",
color: '#0a0',
showValue: true
}, {
label: "blockSpeedSp",
units: 'м/ч',
xAccessorName: "blockSpeedSp",
yAccessorName: "date",
color: '#0a0',
footer: 'SP',
dash
}
]
const pressureGroup = [
{
label: "Давление",
units: 'атм',
xAccessorName: "pressure",
yAccessorName: "date",
color: '#c00',
showValue: true
}, {
label: "pressureSp",
units: 'атм',
xAccessorName: "pressureSp",
yAccessorName: "date",
color: '#c00',
footer: 'SP',
dash
}, {
label: "pressureIdle",
units: 'атм',
xAccessorName: "pressureIdle",
yAccessorName: "date",
color: '#c00',
footer: 'IDLE',
dash
}, {
label: "pressureDeltaLimitMax",
units: 'атм', units: 'атм',
xAccessorName: "pressureDeltaLimitMax", xAccessorName: "pressureDeltaLimitMax",
yAccessorName: "date", yAccessorName: "date",
color: '#c00' color: '#c00',
}, footer: true,
], dash
} }
]
const axialLoadGroup = { const axialLoadGroup = [
{
label: "Осевая нагрузка", label: "Осевая нагрузка",
yDisplay: false, units: 'т',
linePv: {label: "axialLoad", units: 'т', xAccessorName: "axialLoad", yAccessorName: "date", color: '#00a'}, xAccessorName: "axialLoad",
lineSp: {label: "axialLoadSp", units: 'т', xAccessorName: "axialLoadSp", yAccessorName: "date", color: '#00a', dash}, yAccessorName: "date",
linesOther: [ color: '#00a',
{label: "axialLoadLimitMax", units: 'т', xAccessorName: "axialLoadLimitMax", yAccessorName: "date", color: '#00a'}, showValue: true
], }, {
} label: "axialLoadSp",
units: 'т',
xAccessorName: "axialLoadSp",
yAccessorName: "date",
color: '#00a',
footer: 'SP',
dash
}, {
label: "axialLoadLimitMax",
units: 'т',
xAccessorName: "axialLoadLimitMax",
yAccessorName: "date",
color: '#00a',
footer: true,
dash
},
]
const hookWeightGroup = { const hookWeightGroup = [
{
label: "Вес на крюке", label: "Вес на крюке",
yDisplay: false, units: 'т',
linePv: {label: "hookWeight", units: 'т', xAccessorName: "hookWeight", yAccessorName: "date", color: '#0aa'}, xAccessorName: "hookWeight",
lineIdle: { yAccessorName: "date",
color: '#0aa',
showValue: true
}, {
label: "hookWeightIdle", label: "hookWeightIdle",
units: 'т', units: 'т',
xAccessorName: "hookWeightIdle", xAccessorName: "hookWeightIdle",
yAccessorName: "date", yAccessorName: "date",
color: '#0aa', color: '#0aa',
footer: 'IDLE',
dash dash
}, }, {
linesOther: [
{
label: "hookWeightLimitMin", label: "hookWeightLimitMin",
units: 'т', units: 'т',
xAccessorName: "hookWeightLimitMin", xAccessorName: "hookWeightLimitMin",
yAccessorName: "date", yAccessorName: "date",
color: '#0aa' color: '#0aa',
}, footer: true,
{ dash
}, {
label: "hookWeightLimitMax", label: "hookWeightLimitMax",
units: 'т', units: 'т',
xAccessorName: "hookWeightLimitMax", xAccessorName: "hookWeightLimitMax",
yAccessorName: "date", yAccessorName: "date",
color: '#0aa' color: '#0aa',
footer: true,
dash
}, },
], {
} label: 'Обороты ротора',
units: 'об/мин',
xAccessorName: 'rotorSpeed',
yAccessorName: 'date',
color: '#aa0',
showValue: true
}
]
const rotorTorqueGroup = { const rotorTorqueGroup = [
{
label: "Момент на роторе", label: "Момент на роторе",
yDisplay: false, units: 'кН·м',
linePv: {label: "rotorTorque", units: 'кН·м', xAccessorName: "rotorTorque", yAccessorName: "date", color: '#a0a'}, xAccessorName: "rotorTorque",
lineSp: {label: "rotorTorqueSp", units: 'кН·м', xAccessorName: "rotorTorqueSp", yAccessorName: "date", color: '#a0a'}, yAccessorName: "date",
lineIdle: { color: '#a0a',
label: "rotorTorqueIdle", showValue: true
}, {
label: "План. Момент на роторе",
units: 'кН·м',
xAccessorName: "rotorTorqueSp",
yAccessorName: "date",
color: '#a0a',
footer: 'SP',
dash
}, {
label: "Момент на роторе х.х.",
units: 'кН·м', units: 'кН·м',
xAccessorName: "rotorTorqueIdle", xAccessorName: "rotorTorqueIdle",
yAccessorName: "date", yAccessorName: "date",
color: '#a0a' color: '#a0a',
}, footer: 'IDLE',
linesOther: [ dash
{ }, {
label: "rotorTorqueLimitMax", label: "rotorTorqueLimitMax",
units: 'кН·м', units: 'кН·м',
xAccessorName: "rotorTorqueLimitMax", xAccessorName: "rotorTorqueLimitMax",
yAccessorName: "date", yAccessorName: "date",
color: '#a0a' color: '#a0a',
footer: true,
dash
}, },
], ]
}
const paramsGroups = [blockHeightGroup, blockSpeedGroup, pressureGroup, axialLoadGroup, hookWeightGroup, rotorTorqueGroup] const paramsGroups = [blockHeightGroup, blockSpeedGroup, pressureGroup, axialLoadGroup, hookWeightGroup, rotorTorqueGroup]
const timePeriodCollection = [ const timePeriodCollection = [
{value: '60', label: '1 минута'}, { value: '60', label: '1 минута' },
{value: '300', label: '5 минут'}, { value: '300', label: '5 минут' },
{value: '600', label: '10 минут'}, { value: '600', label: '10 минут' },
{value: '1800', label: '30 минут'}, { value: '1800', label: '30 минут' },
{value: '3600', label: '1 час'}, { value: '3600', label: '1 час' },
{value: '21600', label: '6 часов'}, { value: '21600', label: '6 часов' },
{value: '43200', label: '12 часов'}, { value: '43200', label: '12 часов' },
{value: '86400', label: '24 часа'} { value: '86400', label: '24 часа' }
] ]
const defaultChartInterval = '600' const defaultChartInterval = '600'
@ -159,7 +243,7 @@ const isSpinEnabled = (dataSpin) => {
return lastData?.state > 0 && lastData?.state !== 6 return lastData?.state > 0 && lastData?.state !== 6
} }
const getIndexOfDrillingBy = (dataSaub)=>{ const getIndexOfDrillingBy = (dataSaub) => {
const order = { const order = {
0: -1, 0: -1,
1: 1, // скорость 1: 1, // скорость
@ -167,11 +251,11 @@ const getIndexOfDrillingBy = (dataSaub)=>{
3: 3, // нагрузка 3: 3, // нагрузка
4: 5, // момент 4: 5, // момент
} }
const idFeedRegulator = getLast(dataSaub)?.idFeedRegulator??0 const idFeedRegulator = getLast(dataSaub)?.idFeedRegulator ?? 0
return order[idFeedRegulator]??-1 return order[idFeedRegulator] ?? -1
} }
export default function TelemetryView({idWell}) { export default function TelemetryView({ idWell }) {
const [dataSaub, setDataSaub] = useState([]) const [dataSaub, setDataSaub] = useState([])
const [dataSpin, setDataSpin] = useState([]) const [dataSpin, setDataSpin] = useState([])
const [chartInterval, setChartInterval] = useState(defaultChartInterval) const [chartInterval, setChartInterval] = useState(defaultChartInterval)
@ -218,39 +302,40 @@ export default function TelemetryView({idWell}) {
}, [idWell, chartInterval]) }, [idWell, chartInterval])
return (<LoaderPortal show={showLoader}> return (<LoaderPortal show={showLoader}>
<Grid style={{gridTemplateColumns: 'auto repeat(6, 1fr)'}}> <Grid style={{ gridTemplateColumns: 'auto repeat(6, 1fr)' }}>
<GridItem col='1' row='1' colSpan='8' style={{marginBottom: '0.5rem'}}> <GridItem col='1' row='1' colSpan='8' style={{ marginBottom: '0.5rem' }}>
<Flex> <Flex>
<ModeDisplay data={dataSaub}/> <ModeDisplay data={dataSaub} />
<div style={{marginLeft: '1rem'}}> <div style={{ marginLeft: '1rem' }}>
Интервал:&nbsp; Интервал:&nbsp;
<Select defaultValue={defaultChartInterval} onChange={setChartInterval}> <Select defaultValue={defaultChartInterval} onChange={setChartInterval}>
{options} {options}
</Select> </Select>
</div> </div>
<span style={{flexGrow: 20}}>&nbsp;</span> <span style={{ flexGrow: 20 }}>&nbsp;</span>
<img src={isTorqueStabEnabled(dataSpin) ? MomentStabPicEnabled : MomentStabPicDisabled} style={{marginRight: "15px"}} alt="TorqueMaster"/> <img src={isTorqueStabEnabled(dataSpin) ? MomentStabPicEnabled : MomentStabPicDisabled} style={{ marginRight: "15px" }} alt="TorqueMaster" />
<img src={isSpinEnabled(dataSpin) ? SpinPicEnabled : SpinPicDisabled} style={{marginRight: "15px"}} alt="SpinMaster"/> <img src={isSpinEnabled(dataSpin) ? SpinPicEnabled : SpinPicDisabled} style={{ marginRight: "15px" }} alt="SpinMaster" />
<h2 style={{marginBottom: 0, marginRight: "15px",fontWeight: "bold", color: isMseEnabled(dataSaub) ? "green" : "lightgrey"}}>MSE</h2> <h2 style={{ marginBottom: 0, marginRight: "15px", fontWeight: "bold", color: isMseEnabled(dataSaub) ? "green" : "lightgrey" }}>MSE</h2>
<UserOfWell data={dataSaub}/> <UserOfWell data={dataSaub} />
</Flex> </Flex>
</GridItem> </GridItem>
<GridItem col='1' row='2' rowSpan='3' style={{minWidth:'260px', width:'0.142fr'}}> <GridItem col='1' row='2' rowSpan='3' style={{ minWidth: '260px', width: '0.142fr' }}>
<CustomColumn data={dataSaub}/> <CustomColumn data={dataSaub} />
</GridItem> </GridItem>
{paramsGroups.map((group, index) => {paramsGroups.map((group, index) =>
<GridItem col={2 + index} row='2' className='border_small' key={group.label}> <GridItem col={2 + index} row='2' className='border_small' key={`${group.label}${index}`}>
<Column <Column
style={{width:'13vw'}} style={{ width: '13vw' }}
data={dataSaub} data={dataSaub}
lineGroup={group} lineGroup={group}
interval={chartInterval} interval={chartInterval}
showBorder={getIndexOfDrillingBy(dataSaub) === index}/> headerHeight={'60px'}
showBorder={getIndexOfDrillingBy(dataSaub) === index} />
</GridItem> </GridItem>
)} )}
<GridItem col='2' row='3' colSpan='7'> <GridItem col='2' row='3' colSpan='7'>
<ActiveMessagesOnline idWell={idWell}/> <ActiveMessagesOnline idWell={idWell} />
</GridItem> </GridItem>
</Grid> </Grid>
</LoaderPortal>) </LoaderPortal>)

View File

@ -10,6 +10,21 @@
display: flex; display: flex;
} }
.display_chart_label {
font-size: 18px;
font-weight: bold;
height: 20px;
padding: 0 4px;
}
.display_chart_values {
position: absolute;
top: 20px;
left: 50px;
font-size: 18px;
font-weight: bold;
}
.display_label{ .display_label{
font-size: 16px; font-size: 16px;
color: rgb(70, 70, 70); color: rgb(70, 70, 70);