forked from ddrilling/asb_cloud_front
Обработка данных графика перенесена в Column.jsx, зоны закончены
This commit is contained in:
parent
35136f6269
commit
1ee38ca733
@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useRef, useState} from 'react';
|
import { useEffect, useRef, useState} from 'react'
|
||||||
import {
|
import {
|
||||||
Chart,
|
Chart,
|
||||||
TimeScale,
|
TimeScale,
|
||||||
@ -10,11 +10,20 @@ import {
|
|||||||
ChartData,
|
ChartData,
|
||||||
ChartTypeRegistry,
|
ChartTypeRegistry,
|
||||||
ChartOptions} from 'chart.js'
|
ChartOptions} from 'chart.js'
|
||||||
import 'chartjs-adapter-moment';
|
import 'chartjs-adapter-moment'
|
||||||
import ChartDataLabels from 'chartjs-plugin-datalabels';
|
import ChartDataLabels from 'chartjs-plugin-datalabels'
|
||||||
import zoomPlugin from 'chartjs-plugin-zoom';
|
import zoomPlugin from 'chartjs-plugin-zoom'
|
||||||
|
|
||||||
Chart.register( TimeScale, LinearScale, LineController, LineElement, PointElement, Legend, ChartDataLabels, zoomPlugin );
|
Chart.register(
|
||||||
|
TimeScale,
|
||||||
|
LinearScale,
|
||||||
|
LineController,
|
||||||
|
LineElement,
|
||||||
|
PointElement,
|
||||||
|
Legend,
|
||||||
|
ChartDataLabels,
|
||||||
|
zoomPlugin
|
||||||
|
)
|
||||||
|
|
||||||
const defaultOptions = {
|
const defaultOptions = {
|
||||||
responsive: true,
|
responsive: true,
|
||||||
@ -23,9 +32,7 @@ const defaultOptions = {
|
|||||||
tooltips: {
|
tooltips: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
callbacks: {
|
callbacks: {
|
||||||
label(tooltipItem:any) {
|
label: (tooltipItem:any) => tooltipItem.yLabel
|
||||||
return tooltipItem.yLabel;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
events: ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove'],
|
events: ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove'],
|
||||||
@ -53,9 +60,9 @@ const defaultOptions = {
|
|||||||
ticks: {
|
ticks: {
|
||||||
z: 1,
|
z: 1,
|
||||||
display : false,
|
display : false,
|
||||||
textStrokeColor : "#ffff",
|
textStrokeColor : '#ffff',
|
||||||
textStrokeWidth : 2,
|
textStrokeWidth : 2,
|
||||||
color:"#000",
|
color:'#000',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -118,7 +125,7 @@ export type TimeParams = {
|
|||||||
|
|
||||||
const linesPerInterval = 32
|
const linesPerInterval = 32
|
||||||
|
|
||||||
export const timeUnitByInterval = (intervalSec:number):String => {
|
export const timeUnitByInterval = (intervalSec: number): String => {
|
||||||
if(intervalSec <= 60)
|
if(intervalSec <= 60)
|
||||||
return 'millisecond'
|
return 'millisecond'
|
||||||
|
|
||||||
@ -146,42 +153,42 @@ export const timeUnitByInterval = (intervalSec:number):String => {
|
|||||||
return 'year'
|
return 'year'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const timeParamsByInterval = (intervalSec:number) :TimeParams => {
|
export const timeParamsByInterval = (intervalSec: number): TimeParams => {
|
||||||
let stepSize = intervalSec
|
let stepSize = intervalSec
|
||||||
let unit = timeUnitByInterval(intervalSec)
|
let unit = timeUnitByInterval(intervalSec)
|
||||||
|
|
||||||
switch(unit){
|
switch(unit){
|
||||||
case "millisecond":
|
case 'millisecond':
|
||||||
stepSize *= 1000
|
stepSize *= 1000
|
||||||
break;
|
break;
|
||||||
case "second":
|
case 'second':
|
||||||
//stepSize *= 1
|
//stepSize *= 1
|
||||||
break;
|
break;
|
||||||
case "minute":
|
case 'minute':
|
||||||
stepSize /= 60
|
stepSize /= 60
|
||||||
break;
|
break;
|
||||||
case "hour":
|
case 'hour':
|
||||||
stepSize /= 60*60
|
stepSize /= 60*60
|
||||||
break;
|
break;
|
||||||
case "day":
|
case 'day':
|
||||||
stepSize /= 24*60*60
|
stepSize /= 24*60*60
|
||||||
break;
|
break;
|
||||||
case "week":
|
case 'week':
|
||||||
stepSize /= 7*24*60*60
|
stepSize /= 7*24*60*60
|
||||||
break;
|
break;
|
||||||
case "month":
|
case 'month':
|
||||||
stepSize /= 30*24*60*60
|
stepSize /= 30*24*60*60
|
||||||
break;
|
break;
|
||||||
case "quarter":
|
case 'quarter':
|
||||||
stepSize /= 91*24*60*60
|
stepSize /= 91*24*60*60
|
||||||
break;
|
break;
|
||||||
case "year":
|
case 'year':
|
||||||
stepSize /= 365.25*24*60*60
|
stepSize /= 365.25*24*60*60
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
stepSize = Math.round(stepSize/linesPerInterval)
|
stepSize = Math.round(stepSize/linesPerInterval)
|
||||||
stepSize = stepSize > 0 ? stepSize : 1;
|
stepSize = stepSize > 0 ? stepSize : 1
|
||||||
return {unit, stepSize}
|
return {unit, stepSize}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,20 +211,17 @@ export const ChartTimeBase: React.FC<ChartTimeBaseProps> = ({options, dataParams
|
|||||||
|
|
||||||
return () => chart?.destroy()
|
return () => chart?.destroy()
|
||||||
}
|
}
|
||||||
}, [chart, options, dataParams])
|
|
||||||
|
|
||||||
useEffect(()=>{
|
if(!chart) return
|
||||||
if(!chart)
|
|
||||||
return
|
|
||||||
|
|
||||||
chart.data = dataParams.data
|
chart.data = dataParams.data
|
||||||
chart.options.aspectRatio = options?.aspectRatio
|
chart.options.aspectRatio = options?.aspectRatio
|
||||||
if(dataParams.yStart){
|
if(dataParams.yStart){
|
||||||
let interval = Number(dataParams.yInterval ?? 600)
|
const interval = Number(dataParams.yInterval ?? 600)
|
||||||
let start = new Date(dataParams.yStart)
|
const start = new Date(dataParams.yStart)
|
||||||
let end = new Date(dataParams.yStart)
|
const end = new Date(dataParams.yStart)
|
||||||
end.setSeconds(end.getSeconds() + interval)
|
end.setSeconds(end.getSeconds() + interval)
|
||||||
let {unit, stepSize} = timeParamsByInterval(interval)
|
const { unit, stepSize } = timeParamsByInterval(interval)
|
||||||
|
|
||||||
if(chart.options.scales?.y){
|
if(chart.options.scales?.y){
|
||||||
chart.options.scales.y.max = end.getTime()
|
chart.options.scales.y.max = end.getTime()
|
||||||
|
@ -1,26 +1,24 @@
|
|||||||
import { useParams } from "react-router-dom";
|
import { useParams } from 'react-router-dom'
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from 'react'
|
||||||
import ClusterWells from "./ClusterWells";
|
import ClusterWells from './ClusterWells'
|
||||||
import LoaderPortal from "../../components/LoaderPortal";
|
import LoaderPortal from '../../components/LoaderPortal'
|
||||||
import { invokeWebApiWrapperAsync } from "../../components/factory";
|
import { invokeWebApiWrapperAsync } from '../../components/factory'
|
||||||
import { WellOperationStatService } from "../../services/api";
|
import { WellOperationStatService } from '../../services/api'
|
||||||
|
|
||||||
|
|
||||||
export default function Cluster() {
|
export const Cluster = () => {
|
||||||
let { idClaster } = useParams();
|
const { idClaster } = useParams()
|
||||||
const [data, setData] = useState([]);
|
const [data, setData] = useState([])
|
||||||
const [showLoader, setShowLoader] = useState(false);
|
const [showLoader, setShowLoader] = useState(false)
|
||||||
|
|
||||||
useEffect(() => invokeWebApiWrapperAsync(
|
useEffect(() => invokeWebApiWrapperAsync(
|
||||||
async () => {
|
async () => {
|
||||||
const clusterData = await WellOperationStatService.getStatCluster(idClaster);
|
const clusterData = await WellOperationStatService.getStatCluster(idClaster)
|
||||||
setData(clusterData?.statsWells ?? []);
|
setData(clusterData?.statsWells ?? [])
|
||||||
},
|
},
|
||||||
setShowLoader,
|
setShowLoader,
|
||||||
`Не удалось загрузить данные по кусту "${idClaster}"`
|
`Не удалось загрузить данные по кусту "${idClaster}"`
|
||||||
), [idClaster]);
|
), [idClaster])
|
||||||
|
|
||||||
useEffect(() => console.log(data), [data])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LoaderPortal show={showLoader}>
|
<LoaderPortal show={showLoader}>
|
||||||
@ -28,3 +26,5 @@ export default function Cluster() {
|
|||||||
</LoaderPortal>
|
</LoaderPortal>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default Cluster
|
||||||
|
@ -1,121 +0,0 @@
|
|||||||
import { useEffect, useState} from 'react';
|
|
||||||
import {ChartTimeBase, ChartTimeData, ChartTimeDataParams} from '../../components/charts/ChartTimeBase'
|
|
||||||
|
|
||||||
const GetRandomColor = () => "#" + Math.floor(Math.random()*16777215).toString(16)
|
|
||||||
function GetOrCreateDatasetByLineConfig (data: ChartTimeData, lineConfig: LineConfig) {
|
|
||||||
let dataset = data?.datasets.find(d=>d.label === lineConfig.label)
|
|
||||||
if(!dataset)
|
|
||||||
{
|
|
||||||
let color = lineConfig.borderColor
|
|
||||||
?? lineConfig.backgroundColor
|
|
||||||
?? lineConfig.color
|
|
||||||
?? GetRandomColor()
|
|
||||||
|
|
||||||
dataset = {
|
|
||||||
label:lineConfig.label,
|
|
||||||
data:[],
|
|
||||||
backgroundColor: lineConfig.backgroundColor ?? color,
|
|
||||||
borderColor: lineConfig.borderColor ?? color,
|
|
||||||
borderWidth: lineConfig.borderWidth ?? 1,
|
|
||||||
borderDash: lineConfig.dash ?? [],
|
|
||||||
showLine: lineConfig.showLine,
|
|
||||||
}
|
|
||||||
data.datasets.push(dataset);
|
|
||||||
}
|
|
||||||
return dataset
|
|
||||||
}
|
|
||||||
|
|
||||||
export type LineConfig = {
|
|
||||||
type?: string
|
|
||||||
label: string
|
|
||||||
units?: string
|
|
||||||
xAccessorName: string
|
|
||||||
yAccessorName: string
|
|
||||||
color?:string
|
|
||||||
borderColor?: string
|
|
||||||
backgroundColor?: string
|
|
||||||
borderWidth?: number
|
|
||||||
dash?:number[]
|
|
||||||
labels?: any[]
|
|
||||||
showLine: boolean
|
|
||||||
xConstValue?: number|null
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ChartTimeProps = {
|
|
||||||
label?: string,
|
|
||||||
yDisplay: Boolean,
|
|
||||||
// linePv?: LineConfig,
|
|
||||||
// lineSp?: LineConfig,
|
|
||||||
// lineIdle?: LineConfig,
|
|
||||||
lines: LineConfig[],
|
|
||||||
data: any[],
|
|
||||||
interval: number,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ChartTimeOnline: React.FC<ChartTimeProps> = (props) => {
|
|
||||||
const [dataParams, setDataParams] = useState<ChartTimeDataParams>({data: {datasets:[]}, yStart: new Date(), })
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if( (!props?.lines)
|
|
||||||
|| (!props?.data)
|
|
||||||
|| (props.lines.length === 0)
|
|
||||||
|| (props.data.length === 0))
|
|
||||||
return
|
|
||||||
|
|
||||||
setDataParams((preDataParams) => {
|
|
||||||
props.lines.forEach(lineCfg => {
|
|
||||||
let dataset = GetOrCreateDatasetByLineConfig(preDataParams.data, lineCfg)
|
|
||||||
let points = props.data.map(dataItem => {return{
|
|
||||||
x: lineCfg.xConstValue ?? dataItem[lineCfg.xAccessorName],
|
|
||||||
label: dataItem[lineCfg.xAccessorName],
|
|
||||||
y: new Date(dataItem[lineCfg.yAccessorName])}
|
|
||||||
})
|
|
||||||
//dataset.data = [ ...dataset.data, ...points,].slice(-1024)
|
|
||||||
let data = [ ...dataset.data, ...points,]
|
|
||||||
if(points?.length > 2)
|
|
||||||
data.sort((a,b) => a.y > b.y ? 1 : -1)
|
|
||||||
if(data.length > 1024)
|
|
||||||
data.splice(0, (1024 - data.length))
|
|
||||||
dataset.data = data;
|
|
||||||
});
|
|
||||||
|
|
||||||
preDataParams.yStart = new Date()
|
|
||||||
preDataParams.yStart.setSeconds(preDataParams.yStart.getSeconds() - props.interval)
|
|
||||||
preDataParams.yInterval = props.interval
|
|
||||||
preDataParams.displayLabels = props.yDisplay
|
|
||||||
return preDataParams
|
|
||||||
})
|
|
||||||
|
|
||||||
}, [ props.data, props.lines, props.interval, props.yDisplay])
|
|
||||||
|
|
||||||
const chartPluginsOptions = {
|
|
||||||
plugins:{
|
|
||||||
legend:{
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
datalabels: {
|
|
||||||
backgroundColor: 'transparent',
|
|
||||||
borderRadius: 4,
|
|
||||||
color: '#000B',
|
|
||||||
display: function(context:any) {
|
|
||||||
return context.dataset.label === 'wellDepth'
|
|
||||||
? 'auto'
|
|
||||||
: false
|
|
||||||
},
|
|
||||||
formatter: function(value: any, context: any) {
|
|
||||||
return `${value.y.toLocaleTimeString()} ${value.label.toPrecision(4)}`
|
|
||||||
},
|
|
||||||
padding: 6,
|
|
||||||
align: 'left',
|
|
||||||
anchor: 'center',
|
|
||||||
clip: true
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
enable: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return(<ChartTimeBase dataParams = {dataParams} options = { chartPluginsOptions } />)
|
|
||||||
}
|
|
||||||
|
|
@ -1,37 +1,129 @@
|
|||||||
import {Grid, GridItem} from '../../components/Grid';
|
import { useState, useEffect } from 'react'
|
||||||
import {ChartTimeOnline} from './ChartTimeOnline';
|
import { Grid, GridItem } from '../../components/Grid'
|
||||||
import {ChartTimeOnlineFooter} from './ChartTimeOnlineFooter';
|
import { ChartTimeBase } from '../../components/charts/ChartTimeBase'
|
||||||
|
import { ChartTimeOnlineFooter } from './ChartTimeOnlineFooter'
|
||||||
|
|
||||||
const stroke = (sz='1px', c='white') => ({ textShadow: `-${sz} -${sz} 0 ${c}, ${sz} -${sz} 0 ${c}, -${sz} ${sz} 0 ${c}, ${sz} ${sz} 0 ${c}` })
|
const stroke = (sz = '1px', c = 'white') => ({ textShadow: `-${sz} -${sz} 0 ${c}, ${sz} -${sz} 0 ${c}, -${sz} ${sz} 0 ${c}, ${sz} ${sz} 0 ${c}` })
|
||||||
|
|
||||||
export const Column = ({lineGroup, data, interval, showBorder, style, headerHeight}) => {
|
const chartPluginsOptions = {
|
||||||
let dataLast = data?.length > 0 ? data[data.length - 1] : null
|
plugins: {
|
||||||
let pv = lineGroup.filter(line => line.showGraph).map(line => ({
|
datalabels: {
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
borderRadius: 4,
|
||||||
|
color: '#000B',
|
||||||
|
display: context => (context.dataset.label === 'wellDepth') && 'auto',
|
||||||
|
formatter: value => `${value.y.toLocaleTimeString()} ${value.label.toPrecision(4)}`,
|
||||||
|
padding: 6,
|
||||||
|
align: 'left',
|
||||||
|
anchor: 'center',
|
||||||
|
clip: true
|
||||||
|
},
|
||||||
|
legend:{ display: false },
|
||||||
|
tooltip: { enable: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const GetLimitShape = (flowChartData, points, accessor) => {
|
||||||
|
const min = [], max = []
|
||||||
|
|
||||||
|
for (let point of points) {
|
||||||
|
const program = flowChartData.find(v => v.depthStart < point.depth && point.depth < v.depthEnd)
|
||||||
|
if (!program) continue
|
||||||
|
|
||||||
|
min.push({ x: program[`${accessor}Min`], y: new Date(point.y), label: point.label })
|
||||||
|
max.push({ x: program[`${accessor}Max`], y: new Date(point.y), label: point.label })
|
||||||
|
}
|
||||||
|
|
||||||
|
return min.concat(max.reverse()) ?? []
|
||||||
|
}
|
||||||
|
|
||||||
|
const GetRandomColor = () => '#' + Math.floor(Math.random()*16777215).toString(16)
|
||||||
|
const GetOrCreateDatasetByLineConfig = (data, lineConfig) => {
|
||||||
|
let dataset = data?.datasets.find(d => d.label === lineConfig.label)
|
||||||
|
if(!dataset) {
|
||||||
|
let color = lineConfig.borderColor
|
||||||
|
?? lineConfig.backgroundColor
|
||||||
|
?? lineConfig.color
|
||||||
|
?? GetRandomColor()
|
||||||
|
|
||||||
|
dataset = {
|
||||||
|
label: lineConfig.label,
|
||||||
|
data: [],
|
||||||
|
backgroundColor: lineConfig.backgroundColor ?? color,
|
||||||
|
borderColor: lineConfig.borderColor ?? color,
|
||||||
|
borderWidth: lineConfig.borderWidth ?? 1,
|
||||||
|
borderDash: lineConfig.dash ?? [],
|
||||||
|
showLine: lineConfig.showLine ?? !lineConfig.isShape,
|
||||||
|
fill: lineConfig.fill ?? (lineConfig.isShape ? 'shape' : 'none')
|
||||||
|
}
|
||||||
|
data.datasets.push(dataset);
|
||||||
|
}
|
||||||
|
return dataset
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Column = ({ lineGroup, data, flowChartData, interval, showBorder, style, headerHeight, yDisplay }) => {
|
||||||
|
const [dataParams, setDataParams] = useState({data: {datasets:[]}, yStart: new Date(), })
|
||||||
|
|
||||||
|
let dataLast = data?.[data.length - 1]
|
||||||
|
let pv = lineGroup.filter(line => line.showLabels).map(line => ({
|
||||||
color: line.color,
|
color: line.color,
|
||||||
label: line.label,
|
label: line.label,
|
||||||
unit: line.units,
|
unit: line.units,
|
||||||
value: dataLast?.[line.xAccessorName]
|
value: dataLast?.[line.xAccessorName]
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if((lineGroup.length === 0) || (data.length === 0)) return
|
||||||
|
|
||||||
|
setDataParams((preDataParams) => {
|
||||||
|
lineGroup.forEach(lineCfg => {
|
||||||
|
if (lineCfg.isShape) return
|
||||||
|
const dataset = GetOrCreateDatasetByLineConfig(preDataParams.data, lineCfg)
|
||||||
|
const points = data.map(dataItem => ({
|
||||||
|
x: lineCfg.xConstValue ?? dataItem[lineCfg.xAccessorName],
|
||||||
|
label: dataItem[lineCfg.xAccessorName],
|
||||||
|
y: new Date(dataItem[lineCfg.yAccessorName]),
|
||||||
|
depth: dataItem.wellDepth
|
||||||
|
})).filter(point => (point.x ?? null) !== null && (point.y ?? null) !== null)
|
||||||
|
|
||||||
|
const lineData = [ ...dataset.data, ...points,]
|
||||||
|
if(points?.length > 2)
|
||||||
|
lineData.sort((a,b) => a.y > b.y ? 1 : -1)
|
||||||
|
if(lineData.length > 1024)
|
||||||
|
lineData.splice(0, (1024 - lineData.length))
|
||||||
|
|
||||||
|
dataset.data = lineData
|
||||||
|
|
||||||
|
//Area
|
||||||
|
lineGroup.filter(cfg => cfg.isShape && cfg.xAccessorName === lineCfg.xAccessorName).forEach(areaCfg => {
|
||||||
|
const dataset = GetOrCreateDatasetByLineConfig(preDataParams.data, areaCfg)
|
||||||
|
dataset.data = GetLimitShape(flowChartData, lineData, areaCfg.xAccessorName)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
preDataParams.yStart = new Date()
|
||||||
|
preDataParams.yStart.setSeconds(preDataParams.yStart.getSeconds() - interval)
|
||||||
|
preDataParams.yInterval = interval
|
||||||
|
preDataParams.displayLabels = yDisplay ?? false
|
||||||
|
return {...preDataParams}
|
||||||
|
})
|
||||||
|
|
||||||
|
}, [data, lineGroup, interval, yDisplay, flowChartData])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={style}>
|
<div style={style}>
|
||||||
<Grid style={{height: headerHeight, boxShadow: showBorder ? 'inset 0px 0px 0px 3px black' : ''}}>
|
<Grid style={{ height: headerHeight, boxShadow: showBorder ? 'inset 0px 0px 0px 3px black' : '' }}>
|
||||||
{pv?.map((v, idx) => (
|
{pv?.map((v, idx) => (
|
||||||
<GridItem className={'display_chart_label'} key={idx} row={idx} col={1} style={{color: v.color}}>{v.label}</GridItem>
|
<GridItem className={'display_chart_label'} key={idx} row={idx} col={1} style={{ color: v.color }}>{v.label}</GridItem>
|
||||||
))}
|
))}
|
||||||
</Grid>
|
</Grid>
|
||||||
<div style={{position: 'relative'}}>
|
<div style={{ position: 'relative' }}>
|
||||||
<Grid className={'display_chart_values'}>
|
<Grid className={'display_chart_values'}>
|
||||||
{pv?.map((v, idx) => (
|
{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>
|
<GridItem key={idx} col={1} row={idx} style={{ ...stroke(), color: v.color, padding: '0 4px' }}>{v.value?.toFixed(2) ?? '--'} {v.unit}</GridItem>
|
||||||
))}
|
))}
|
||||||
</Grid>
|
</Grid>
|
||||||
<ChartTimeOnline
|
<ChartTimeBase dataParams = {dataParams} options = { chartPluginsOptions } />
|
||||||
data={data}
|
|
||||||
yDisplay={false}
|
|
||||||
lines={lineGroup}
|
|
||||||
interval={interval}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<ChartTimeOnlineFooter data={dataLast} lineGroup={lineGroup} />
|
<ChartTimeOnlineFooter data={dataLast} lineGroup={lineGroup} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,7 +10,12 @@ 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, WellService } from '../../services/api'
|
import {
|
||||||
|
DrillFlowChartService,
|
||||||
|
TelemetryDataSaubService,
|
||||||
|
TelemetryDataSpinService,
|
||||||
|
WellService
|
||||||
|
} 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'
|
||||||
@ -31,7 +36,7 @@ const blockHeightGroup = [
|
|||||||
xAccessorName: 'blockPosition',
|
xAccessorName: 'blockPosition',
|
||||||
yAccessorName: 'date',
|
yAccessorName: 'date',
|
||||||
color: '#333',
|
color: '#333',
|
||||||
showGraph: true
|
showLabels: true
|
||||||
}, {
|
}, {
|
||||||
label: 'wellDepth',
|
label: 'wellDepth',
|
||||||
units: 'м',
|
units: 'м',
|
||||||
@ -47,7 +52,15 @@ const blockHeightGroup = [
|
|||||||
xAccessorName: 'flow',
|
xAccessorName: 'flow',
|
||||||
yAccessorName: 'date',
|
yAccessorName: 'date',
|
||||||
color: '#077',
|
color: '#077',
|
||||||
showGraph: true
|
showLabels: true,
|
||||||
|
showLine: true
|
||||||
|
}, {
|
||||||
|
label: 'flowLimits',
|
||||||
|
units: 'л/с',
|
||||||
|
xAccessorName: 'flow',
|
||||||
|
yAccessorName: 'date',
|
||||||
|
color: 'rgba(0,119,119,.1)',
|
||||||
|
isShape: true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -58,7 +71,7 @@ const blockSpeedGroup = [
|
|||||||
xAccessorName: 'blockSpeed',
|
xAccessorName: 'blockSpeed',
|
||||||
yAccessorName: 'date',
|
yAccessorName: 'date',
|
||||||
color: '#0a0',
|
color: '#0a0',
|
||||||
showGraph: true
|
showLabels: true,
|
||||||
}, {
|
}, {
|
||||||
label: 'blockSpeedSp',
|
label: 'blockSpeedSp',
|
||||||
units: 'м/ч',
|
units: 'м/ч',
|
||||||
@ -77,7 +90,7 @@ const pressureGroup = [
|
|||||||
xAccessorName: 'pressure',
|
xAccessorName: 'pressure',
|
||||||
yAccessorName: 'date',
|
yAccessorName: 'date',
|
||||||
color: '#c00',
|
color: '#c00',
|
||||||
showGraph: true
|
showLabels: true
|
||||||
}, {
|
}, {
|
||||||
label: 'pressureSp',
|
label: 'pressureSp',
|
||||||
units: 'атм',
|
units: 'атм',
|
||||||
@ -102,6 +115,13 @@ const pressureGroup = [
|
|||||||
color: '#c00',
|
color: '#c00',
|
||||||
footer: true,
|
footer: true,
|
||||||
dash
|
dash
|
||||||
|
}, {
|
||||||
|
label: 'pressureLimits',
|
||||||
|
units: 'атм',
|
||||||
|
xAccessorName: 'pressure',
|
||||||
|
yAccessorName: 'date',
|
||||||
|
color: 'rgba(204,0,0,.1)',
|
||||||
|
isShape: true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -112,7 +132,7 @@ const axialLoadGroup = [
|
|||||||
xAccessorName: 'axialLoad',
|
xAccessorName: 'axialLoad',
|
||||||
yAccessorName: 'date',
|
yAccessorName: 'date',
|
||||||
color: '#00a',
|
color: '#00a',
|
||||||
showGraph: true
|
showLabels: true
|
||||||
}, {
|
}, {
|
||||||
label: 'axialLoadSp',
|
label: 'axialLoadSp',
|
||||||
units: 'т',
|
units: 'т',
|
||||||
@ -129,7 +149,14 @@ const axialLoadGroup = [
|
|||||||
color: '#00a',
|
color: '#00a',
|
||||||
footer: true,
|
footer: true,
|
||||||
dash
|
dash
|
||||||
},
|
}, {
|
||||||
|
label: 'axialLoadLimits',
|
||||||
|
units: 'т',
|
||||||
|
xAccessorName: 'axialLoad',
|
||||||
|
yAccessorName: 'date',
|
||||||
|
color: 'rgba(0,0,170,.1)',
|
||||||
|
isShape: true
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
const hookWeightGroup = [
|
const hookWeightGroup = [
|
||||||
@ -139,7 +166,7 @@ const hookWeightGroup = [
|
|||||||
xAccessorName: 'hookWeight',
|
xAccessorName: 'hookWeight',
|
||||||
yAccessorName: 'date',
|
yAccessorName: 'date',
|
||||||
color: '#0aa',
|
color: '#0aa',
|
||||||
showGraph: true
|
showLabels: true
|
||||||
}, {
|
}, {
|
||||||
label: 'hookWeightIdle',
|
label: 'hookWeightIdle',
|
||||||
units: 'т',
|
units: 'т',
|
||||||
@ -164,14 +191,20 @@ const hookWeightGroup = [
|
|||||||
color: '#0aa',
|
color: '#0aa',
|
||||||
footer: true,
|
footer: true,
|
||||||
dash
|
dash
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
label: 'Обороты ротора',
|
label: 'Обороты ротора',
|
||||||
units: 'об/мин',
|
units: 'об/мин',
|
||||||
xAccessorName: 'rotorSpeed',
|
xAccessorName: 'rotorSpeed',
|
||||||
yAccessorName: 'date',
|
yAccessorName: 'date',
|
||||||
color: '#aa0',
|
color: '#aa0',
|
||||||
showGraph: true
|
showLabels: true
|
||||||
|
}, {
|
||||||
|
label: 'rotorSpeedLimits',
|
||||||
|
units: 'об/мин',
|
||||||
|
xAccessorName: 'rotorSpeed',
|
||||||
|
yAccessorName: 'date',
|
||||||
|
color: 'rgba(170,170,0,.1)',
|
||||||
|
isShape: true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -182,7 +215,7 @@ const rotorTorqueGroup = [
|
|||||||
xAccessorName: 'rotorTorque',
|
xAccessorName: 'rotorTorque',
|
||||||
yAccessorName: 'date',
|
yAccessorName: 'date',
|
||||||
color: '#a0a',
|
color: '#a0a',
|
||||||
showGraph: true
|
showLabels: true
|
||||||
}, {
|
}, {
|
||||||
label: 'План. Момент на роторе',
|
label: 'План. Момент на роторе',
|
||||||
units: 'кН·м',
|
units: 'кН·м',
|
||||||
@ -207,7 +240,14 @@ const rotorTorqueGroup = [
|
|||||||
color: '#a0a',
|
color: '#a0a',
|
||||||
footer: true,
|
footer: true,
|
||||||
dash
|
dash
|
||||||
},
|
}, {
|
||||||
|
label: 'rotorTorqueLimits',
|
||||||
|
units: 'кН·м',
|
||||||
|
xAccessorName: 'rotorTorque',
|
||||||
|
yAccessorName: 'date',
|
||||||
|
color: 'rgba(170,0,170,.1)',
|
||||||
|
isShape: true
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
const paramsGroups = [blockHeightGroup, blockSpeedGroup, pressureGroup, axialLoadGroup, hookWeightGroup, rotorTorqueGroup]
|
const paramsGroups = [blockHeightGroup, blockSpeedGroup, pressureGroup, axialLoadGroup, hookWeightGroup, rotorTorqueGroup]
|
||||||
@ -259,8 +299,9 @@ 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)
|
||||||
const [wellData, setWellData] = useState({idState: 0})
|
const [wellData, setWellData] = useState({ idState: 0 })
|
||||||
const [showLoader, setShowLoader] = useState(false)
|
const [showLoader, setShowLoader] = useState(false)
|
||||||
|
const [flowChartData, setFlowChartData] = useState([])
|
||||||
|
|
||||||
const options = timePeriodCollection.map((line) => <Option key={line.value}>{line.label}</Option>)
|
const options = timePeriodCollection.map((line) => <Option key={line.value}>{line.label}</Option>)
|
||||||
|
|
||||||
@ -284,18 +325,20 @@ export default function TelemetryView({ idWell }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const unsubscribeSaub = Subscribe('hubs/telemetry', 'ReceiveDataSaub', `well_${idWell}`, handleDataSaub)
|
||||||
|
const unsubscribeSpin = Subscribe('hubs/telemetry', 'ReceiveDataSpin', `well_${idWell}`, handleDataSpin)
|
||||||
invokeWebApiWrapperAsync(
|
invokeWebApiWrapperAsync(
|
||||||
async () => {
|
async () => {
|
||||||
|
const flowChart = await DrillFlowChartService.get(idWell)
|
||||||
const dataSaub = await TelemetryDataSaubService.getData(idWell, null, chartInterval)
|
const dataSaub = await TelemetryDataSaubService.getData(idWell, null, chartInterval)
|
||||||
const dataSpin = await TelemetryDataSpinService.getData(idWell, null, chartInterval)
|
const dataSpin = await TelemetryDataSpinService.getData(idWell, null, chartInterval)
|
||||||
|
setFlowChartData(flowChart ?? [])
|
||||||
handleDataSaub(dataSaub)
|
handleDataSaub(dataSaub)
|
||||||
handleDataSpin(dataSpin)
|
handleDataSpin(dataSpin)
|
||||||
},
|
},
|
||||||
setShowLoader,
|
null,
|
||||||
`Не удалось получить данные по скважине "${idWell}"`,
|
`Не удалось получить данные по скважине "${idWell}"`,
|
||||||
)
|
)
|
||||||
const unsubscribeSaub = Subscribe('hubs/telemetry', 'ReceiveDataSaub', `well_${idWell}`, handleDataSaub)
|
|
||||||
const unsubscribeSpin = Subscribe('hubs/telemetry', 'ReceiveDataSpin', `well_${idWell}`, handleDataSpin)
|
|
||||||
return () => {
|
return () => {
|
||||||
unsubscribeSaub()
|
unsubscribeSaub()
|
||||||
unsubscribeSpin()
|
unsubscribeSpin()
|
||||||
@ -314,7 +357,7 @@ export default function TelemetryView({ idWell }) {
|
|||||||
const onStatusChanged = (value) => {
|
const onStatusChanged = (value) => {
|
||||||
invokeWebApiWrapperAsync(
|
invokeWebApiWrapperAsync(
|
||||||
async () => {
|
async () => {
|
||||||
const well = {...wellData, idState: value}
|
const well = { ...wellData, idState: value }
|
||||||
await WellService.updateWell(idWell, well)
|
await WellService.updateWell(idWell, well)
|
||||||
setWellData(well)
|
setWellData(well)
|
||||||
},
|
},
|
||||||
@ -335,9 +378,9 @@ export default function TelemetryView({ idWell }) {
|
|||||||
{options}
|
{options}
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ marginLeft: '1rem'}}>
|
<div style={{ marginLeft: '1rem' }}>
|
||||||
Статус:
|
Статус:
|
||||||
<Select value={wellData.idState} onChange={onStatusChanged}>
|
<Select value={wellData.idState ?? 0} onChange={onStatusChanged}>
|
||||||
<Option value={0} disabled>Неизвестно</Option>
|
<Option value={0} disabled>Неизвестно</Option>
|
||||||
<Option value={1}>В работе</Option>
|
<Option value={1}>В работе</Option>
|
||||||
<Option value={2}>Завершено</Option>
|
<Option value={2}>Завершено</Option>
|
||||||
@ -358,6 +401,7 @@ export default function TelemetryView({ idWell }) {
|
|||||||
<Column
|
<Column
|
||||||
style={{ width: '13vw' }}
|
style={{ width: '13vw' }}
|
||||||
data={dataSaub}
|
data={dataSaub}
|
||||||
|
flowChartData={flowChartData}
|
||||||
lineGroup={group}
|
lineGroup={group}
|
||||||
interval={chartInterval}
|
interval={chartInterval}
|
||||||
headerHeight={'60px'}
|
headerHeight={'60px'}
|
||||||
|
Loading…
Reference in New Issue
Block a user