This commit is contained in:
Фролов 2021-08-30 12:19:11 +05:00
commit 8462eb7158
7 changed files with 134 additions and 135 deletions

View File

@ -74,17 +74,6 @@ export const makeColumnsPlanFact = (title:string|any, key:string|string[], colum
} }
} }
const maxPrefix = "isMax"
const minPrefix = "isMin"
export const makeFilterMinMaxFunction = (key: string | number) => (filterValue: string | number,
dataItem: any) =>
filterValue === "max"
? dataItem[maxPrefix + key]
: filterValue === "min"
? dataItem[minPrefix + key]
: false
export const makeFilterTextMatch = (key: string | number) => (filterValue: string | number, dataItem: any) => export const makeFilterTextMatch = (key: string | number) => (filterValue: string | number, dataItem: any) =>
dataItem[key] === filterValue dataItem[key] === filterValue
@ -118,56 +107,22 @@ export const makeTextColumn = (title: any, dataIndex: any, filters: any, sorter:
...other ...other
}) })
export const makeNumericColumn = (title: any, dataIndex: any, filters: any, width: string) => ({ export const makeNumericColumn = (title: any, dataIndex: any, filters: any, filterDelegate: (key: string | number) => any, width: string) => ({
title: title, title: title,
dataIndex: dataIndex, dataIndex: dataIndex,
key: dataIndex, key: dataIndex,
filters: filters, filters: filters,
onFilter: makeFilterMinMaxFunction(dataIndex), onFilter: filterDelegate ? filterDelegate(dataIndex) : null,
sorter: makeNumericSorter(dataIndex), sorter: makeNumericSorter(dataIndex),
width: width width: width
}) })
export const makeNumericColumnPlanFact = (title: any, dataIndex: any, filters: any, width: string) => export const makeNumericColumnPlanFact = (title: any, dataIndex: any, filters: any, filterDelegate: (key: string | number) => any, width: string) =>
makeGroupColumn( title, [ makeGroupColumn( title, [
makeNumericColumn('п', dataIndex + 'Plan', filters, width), makeNumericColumn('п', dataIndex + 'Plan', filters, filterDelegate, width),
makeNumericColumn('ф', dataIndex + 'Fact', filters, width), makeNumericColumn('ф', dataIndex + 'Fact', filters, filterDelegate, width),
]) ])
export const calcAndUpdateStats = (data: any, keys: any) => {
let mins: any = {}
let maxs: any = {}
keys.forEach((key: any) => {
maxs[key] = Number.MIN_VALUE
mins[key] = Number.MAX_VALUE
})
data.forEach((item: any) => {
keys.forEach((key: any) => {
if (mins[key] > item[key]) mins[key] = item[key]
if (maxs[key] < item[key]) maxs[key] = item[key]
})
})
for (let i = 0; i < data.length; i++) {
keys.forEach((key: any) => {
data[i][maxPrefix + key] = data[i][key] === maxs[key]
data[i][minPrefix + key] = data[i][key] === mins[key]
})
}
}
export const calcAndUpdateStatsBySections = (data: any, keys: any) => {
const sectionTypes = new Set()
data.forEach((item: any) => sectionTypes.add(item.sectionType))
sectionTypes.forEach(sectionType => {
const filteredBySectionData = data.filter((item: any) => item.sectionType === sectionType)
calcAndUpdateStats(filteredBySectionData, keys)
})
}
type PaginationContainer = { type PaginationContainer = {
skip?: number; skip?: number;
take?: number; take?: number;

View File

@ -68,8 +68,8 @@ const defaultOptions = {
reverse:true, reverse:true,
display: true, display: true,
title: { title: {
display: true, display: false,
text: 'Value' text: ''
}, },
} }
}, },
@ -111,7 +111,7 @@ const makeDataset = (data, label, color, width=1.5, dash) => ({
borderDash: dash, borderDash: dash,
}) })
export default function DepthToDay({dataPlan, dataFact, dataForecast}) { export default function ChartDepthToDay({dataPlan, dataFact, dataForecast}) {
const chartRef = useRef(null) const chartRef = useRef(null)
const [chart, setChart] = useState() const [chart, setChart] = useState()

View File

@ -4,9 +4,10 @@ import { LineChartOutlined, ProfileOutlined } from "@ant-design/icons";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { import {
makeTextColumn, makeTextColumn,
makeNumericColumnPlanFact, makeNumericColumnPlanFact
calcAndUpdateStatsBySections,
} from "../../components/Table"; } from "../../components/Table";
import { calcAndUpdateStatsBySections, makeFilterMinMaxFunction } from "./functions";
const filtersMinMax = [ const filtersMinMax = [
{ {
@ -62,29 +63,33 @@ const ModalWindowButton = ({
const columns = [ const columns = [
makeTextColumn("скв №", "caption"), makeTextColumn("скв №", "caption"),
makeTextColumn("Секция", "sectionType", filtersSectionsType), makeTextColumn("Секция", "sectionType", filtersSectionsType),
makeNumericColumnPlanFact("Глубина", "sectionWellDepth", filtersMinMax), makeNumericColumnPlanFact("Глубина", "sectionWellDepth", filtersMinMax, makeFilterMinMaxFunction),
makeNumericColumnPlanFact( makeNumericColumnPlanFact(
"Продолжительность", "Продолжительность",
"sectionBuildDays", "sectionBuildDays",
filtersMinMax filtersMinMax,
makeFilterMinMaxFunction
), //Цикл строительства ), //Цикл строительства
makeNumericColumnPlanFact("МСП", "sectionRateOfPenetration", filtersMinMax), makeNumericColumnPlanFact("МСП", "sectionRateOfPenetration", filtersMinMax, makeFilterMinMaxFunction),
makeNumericColumnPlanFact( makeNumericColumnPlanFact(
"Рейсовая скорость", "Рейсовая скорость",
"sectionRouteSpeed", "sectionRouteSpeed",
filtersMinMax filtersMinMax,
makeFilterMinMaxFunction
), ),
makeNumericColumnPlanFact("Спуск КНБК", "sectionBhaDownSpeed", filtersMinMax), //Скорость спуска КНБК makeNumericColumnPlanFact("Спуск КНБК", "sectionBhaDownSpeed", filtersMinMax, makeFilterMinMaxFunction), //Скорость спуска КНБК
makeNumericColumnPlanFact("Подъем КНБК", "sectionBhaUpSpeed", filtersMinMax), //Скорость подъема КНБК makeNumericColumnPlanFact("Подъем КНБК", "sectionBhaUpSpeed", filtersMinMax, makeFilterMinMaxFunction), //Скорость подъема КНБК
makeNumericColumnPlanFact( makeNumericColumnPlanFact(
"Скорость спуска ОК", "Скорость спуска ОК",
"sectionCasingDownSpeed", "sectionCasingDownSpeed",
filtersMinMax filtersMinMax,
makeFilterMinMaxFunction
), ),
makeNumericColumnPlanFact( makeNumericColumnPlanFact(
"НПВ, сут", "НПВ, сут",
"nonProductiveTime", "nonProductiveTime",
filtersMinMax, filtersMinMax,
makeFilterMinMaxFunction,
"70px" "70px"
), ),
{ {
@ -143,26 +148,22 @@ export default function ClusterSections({ clusterData }) {
useEffect(() => { useEffect(() => {
let rows = []; let rows = [];
clusterData.statsWells?.forEach((el) => { clusterData.statsWells?.forEach((well) => {
el.sections.forEach((section) => { well.sections.forEach((section) => {
let row = { let row = {
key: el.caption + section.id, key: well.caption + section.id,
id: el.caption + section.id, id: well.caption + section.id,
caption: el.caption, caption: well.caption,
sectionType: section.caption, sectionType: section.caption,
sectionWellDepthPlan: section.plan.wellDepthEnd, sectionWellDepthPlan: section.plan.wellDepthEnd,
sectionWellDepthFact: section.fact.wellDepthEnd, sectionWellDepthFact: section.fact.wellDepthEnd,
sectionBuildDaysPlan: ( sectionBuildDaysPlan: (
Math.abs( (new Date(section.plan.end) - new Date(section.plan.start)) /
new Date(section.plan.start) - new Date(section.plan.end) (1000 * 60 * 60 * 24)
) /
(1000 * 60 * 60 * 24)
).toFixed(2), ).toFixed(2),
sectionBuildDaysFact: ( sectionBuildDaysFact: (
Math.abs( (new Date(section.fact.end) - new Date(section.fact.start)) /
new Date(section.fact.start) - new Date(section.fact.end) (1000 * 60 * 60 * 24)
) /
(1000 * 60 * 60 * 24)
).toFixed(2), ).toFixed(2),
sectionRateOfPenetrationPlan: section.plan.rop.toFixed(2), sectionRateOfPenetrationPlan: section.plan.rop.toFixed(2),
sectionRateOfPenetrationFact: section.fact.rop.toFixed(2), sectionRateOfPenetrationFact: section.fact.rop.toFixed(2),
@ -176,7 +177,7 @@ export default function ClusterSections({ clusterData }) {
sectionCasingDownSpeedFact: section.fact.casingDownSpeed.toFixed(2), sectionCasingDownSpeedFact: section.fact.casingDownSpeed.toFixed(2),
nonProductiveTimePlan: section.plan.nonProductiveHours.toFixed(2), nonProductiveTimePlan: section.plan.nonProductiveHours.toFixed(2),
nonProductiveTimeFact: section.fact.nonProductiveHours.toFixed(2), nonProductiveTimeFact: section.fact.nonProductiveHours.toFixed(2),
companies: el.companies, companies: well.companies,
}; };
rows.push(row); rows.push(row);

View File

@ -6,12 +6,12 @@ import {
makeTextColumn, makeTextColumn,
makeGroupColumn, makeGroupColumn,
makeNumericColumn, makeNumericColumn,
makeNumericColumnPlanFact, makeNumericColumnPlanFact
calcAndUpdateStatsBySections,
} from "../../components/Table"; } from "../../components/Table";
import { calcAndUpdateStatsBySections, makeFilterMinMaxFunction } from "./functions";
import { invokeWebApiWrapperAsync } from '../../components/factory'; import { invokeWebApiWrapperAsync } from '../../components/factory';
import { WellOperationStatService } from '../../services/api'; import { WellOperationStatService } from '../../services/api';
import DepthToDay from '../../components/charts/DepthToDay'; import ChartDepthToDay from '../../components/charts/ChartDepthToDay';
const filtersMinMax = [ const filtersMinMax = [
{ {
@ -45,31 +45,33 @@ export default function ClusterWells({ clusterData }) {
const [dataForecast, setDataForecast] = useState([]); const [dataForecast, setDataForecast] = useState([]);
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( if (selectedWellId > 0) {
async () => { invokeWebApiWrapperAsync(
const operations = await WellOperationStatService.getTvd(selectedWellId); async () => {
const operations = await WellOperationStatService.getTvd(selectedWellId);
const planData = operations.map(el => {
return {key: el.plan?.id, depth: el.plan?.wellDepth, date: el.plan?.startDate} const planData = operations.map(el => {
}).filter(el => el.key) return {key: el.plan?.id, depth: el.plan?.wellDepth, date: el.plan?.startDate}
}).filter(el => el.key)
setDataPlan(planData)
setDataPlan(planData)
const factData = operations.map(el => {
return {key: el.fact?.id, depth: el.fact?.wellDepth, date: el.fact?.startDate} const factData = operations.map(el => {
}).filter(el => el.key) return {key: el.fact?.id, depth: el.fact?.wellDepth, date: el.fact?.startDate}
}).filter(el => el.key)
setDataFact(factData)
setDataFact(factData)
const predictData = operations.map(el => {
return {key: el.predict?.id, depth: el.predict?.wellDepth, date: el.predict?.startDate} const predictData = operations.map(el => {
}).filter(el => el.key) return {key: el.predict?.id, depth: el.predict?.wellDepth, date: el.predict?.startDate}
}).filter(el => el.key)
setDataForecast(predictData)
}, setDataForecast(predictData)
null, },
`Не удалось загрузить операции по скважине "${selectedWellId}"`, null,
); `Не удалось загрузить операции по скважине "${selectedWellId}"`,
);
}
}, [selectedWellId]); }, [selectedWellId]);
const closeModal = () => { const closeModal = () => {
@ -89,33 +91,29 @@ export default function ClusterWells({ clusterData }) {
]); ]);
useEffect(() => { useEffect(() => {
let tableData = clusterData.statsWells?.map((el) => { let tableData = clusterData.statsWells?.map((well) => {
return { return {
key: el.id, key: well.id,
id: el.id, id: well.id,
caption: el.caption, caption: well.caption,
wellType: el.wellType, wellType: well.wellType,
factStart: new Date(el.total.fact.start).toLocaleString(), factStart: new Date(well.total.fact.start).toLocaleString(),
factEnd: new Date(el.total.fact.end).toLocaleString(), factEnd: new Date(well.total.fact.end).toLocaleString(),
periodPlan: ( periodPlan: (
Math.abs( (new Date(well.total.plan.end) - new Date(well.total.plan.start)) /
new Date(el.total.plan.start) - new Date(el.total.plan.end) (1000 * 60 * 60 * 24)
) /
(1000 * 60 * 60 * 24)
).toFixed(2), ).toFixed(2),
periodFact: ( periodFact: (
Math.abs( (new Date(well.total.fact.end) - new Date(well.total.fact.start)) /
new Date(el.total.fact.start) - new Date(el.total.fact.end) (1000 * 60 * 60 * 24)
) /
(1000 * 60 * 60 * 24)
).toFixed(2), ).toFixed(2),
rateOfPenetrationPlan: el.total.plan.rop.toFixed(2), rateOfPenetrationPlan: well.total.plan.rop.toFixed(2),
rateOfPenetrationFact: el.total.fact.rop.toFixed(2), rateOfPenetrationFact: well.total.fact.rop.toFixed(2),
routeSpeedPlan: el.total.plan.routeSpeed.toFixed(2), routeSpeedPlan: well.total.plan.routeSpeed.toFixed(2),
routeSpeedFact: el.total.fact.routeSpeed.toFixed(2), routeSpeedFact: well.total.fact.routeSpeed.toFixed(2),
notProductiveTimePlan: el.total.plan.nonProductiveHours.toFixed(2), notProductiveTimePlan: well.total.plan.nonProductiveHours.toFixed(2),
notProductiveTimeFact: el.total.fact.nonProductiveHours.toFixed(2), notProductiveTimeFact: well.total.fact.nonProductiveHours.toFixed(2),
companies: el.companies, companies: well.companies,
}; };
}); });
@ -131,10 +129,10 @@ export default function ClusterWells({ clusterData }) {
makeNumericColumn("начало", "factStart"), makeNumericColumn("начало", "factStart"),
makeNumericColumn("окончание", "factEnd"), makeNumericColumn("окончание", "factEnd"),
]), ]),
makeNumericColumnPlanFact("Продолжительность", "period", filtersMinMax), makeNumericColumnPlanFact("Продолжительность", "period", filtersMinMax, makeFilterMinMaxFunction),
makeNumericColumnPlanFact("МСП", "rateOfPenetration", filtersMinMax), makeNumericColumnPlanFact("МСП", "rateOfPenetration", filtersMinMax, makeFilterMinMaxFunction),
makeNumericColumnPlanFact("Рейсовая скорость", "routeSpeed", filtersMinMax), makeNumericColumnPlanFact("Рейсовая скорость", "routeSpeed", filtersMinMax, makeFilterMinMaxFunction),
makeNumericColumnPlanFact("НПВ, сут", "notProductiveTime", filtersMinMax), makeNumericColumnPlanFact("НПВ, сут", "notProductiveTime", filtersMinMax, makeFilterMinMaxFunction),
{ {
title: "График глубина-день", title: "График глубина-день",
render: (_, item) => <Button onClick={()=> { render: (_, item) => <Button onClick={()=> {
@ -167,14 +165,14 @@ export default function ClusterWells({ clusterData }) {
/> />
<Modal <Modal
title='Modal' title='TVD'
centered centered
visible={isModalVisible} visible={isModalVisible}
onOk={closeModal} onOk={closeModal}
onCancel={closeModal} onCancel={closeModal}
width={800} width={1500}
> >
<DepthToDay <ChartDepthToDay
dataPlan={dataPlan} dataPlan={dataPlan}
dataFact={dataFact} dataFact={dataFact}
dataForecast={dataForecast} /> dataForecast={dataForecast} />

View File

@ -0,0 +1,44 @@
const maxPrefix = "isMax"
const minPrefix = "isMin"
export const makeFilterMinMaxFunction = (key) => (filterValue,
dataItem) =>
filterValue === "max"
? dataItem[maxPrefix + key]
: filterValue === "min"
? dataItem[minPrefix + key]
: false
export const calcAndUpdateStats = (data, keys) => {
let mins = {}
let maxs = {}
keys.forEach((key) => {
maxs[key] = Number.MIN_VALUE
mins[key] = Number.MAX_VALUE
})
data.forEach((item) => {
keys.forEach((key) => {
if (mins[key] > item[key]) mins[key] = item[key]
if (maxs[key] < item[key]) maxs[key] = item[key]
})
})
for (let i = 0; i < data.length; i++) {
keys.forEach((key) => {
data[i][maxPrefix + key] = data[i][key] === maxs[key]
data[i][minPrefix + key] = data[i][key] === mins[key]
})
}
}
export const calcAndUpdateStatsBySections = (data, keys) => {
const sectionTypes = new Set()
data.forEach((item) => sectionTypes.add(item.sectionType))
sectionTypes.forEach(sectionType => {
const filteredBySectionData = data.filter((item) => item.sectionType === sectionType)
calcAndUpdateStats(filteredBySectionData, keys)
})
}

View File

@ -9,6 +9,7 @@ import { WellOperationStatService } from "../../services/api";
const { Content } = Layout; const { Content } = Layout;
export default function Cluster() { export default function Cluster() {
let { idClaster, tab } = useParams(); let { idClaster, tab } = useParams();
const [data, setData] = useState([]); const [data, setData] = useState([]);

View File

@ -1,4 +1,4 @@
import DepthToDay from '../../components/charts/DepthToDay'; import ChartDepthToDay from '../../components/charts/ChartDepthToDay';
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { invokeWebApiWrapperAsync } from '../../components/factory'; import { invokeWebApiWrapperAsync } from '../../components/factory';
import { WellOperationStatService } from '../../services/api'; import { WellOperationStatService } from '../../services/api';
@ -39,7 +39,7 @@ export const Tvd = ({ idWell }) => {
<div className="container"> <div className="container">
<div> <div>
<h2 className={'mt-20px'}>График Глубина-день</h2> <h2 className={'mt-20px'}>График Глубина-день</h2>
<DepthToDay <ChartDepthToDay
dataPlan={dataPlan} dataPlan={dataPlan}
dataFact={dataFact} dataFact={dataFact}
dataForecast={dataForecast} /> dataForecast={dataForecast} />