diff --git a/src/components/Table/index.ts b/src/components/Table/index.ts index cbe9dee..485493d 100644 --- a/src/components/Table/index.ts +++ b/src/components/Table/index.ts @@ -119,7 +119,8 @@ export const makeTextColumn = (title: string, dataIndex: string, }) export const makeNumericColumn = (title: string, dataIndex: string, - filters: object[], filterDelegate: (key: string | number) => any, width: string) => ({ + filters: object[], filterDelegate: (key: string | number) => any, + renderDelegate: (_: any, row: object) => any, width: string) => ({ title: title, dataIndex: dataIndex, key: dataIndex, @@ -127,13 +128,15 @@ export const makeNumericColumn = (title: string, dataIndex: string, onFilter: filterDelegate ? filterDelegate(dataIndex) : null, sorter: makeNumericSorter(dataIndex), width: width, + render: renderDelegate, align: 'right' }) -export const makeNumericColumnPlanFact = (title: string, dataIndex: string, filters: object[], filterDelegate: (key: string | number) => any, width: string) => +export const makeNumericColumnPlanFact = (title: string, dataIndex: string, filters: object[], + filterDelegate: (key: string | number) => any, renderDelegate: (_: any, row: object) => any, width: string) => makeGroupColumn( title, [ - makeNumericColumn('п', dataIndex + 'Plan', filters, filterDelegate, width), - makeNumericColumn('ф', dataIndex + 'Fact', filters, filterDelegate, width), + makeNumericColumn('п', dataIndex + 'Plan', filters, filterDelegate, renderDelegate, width), + makeNumericColumn('ф', dataIndex + 'Fact', filters, filterDelegate, renderDelegate, width), ]) type PaginationContainer = { diff --git a/src/pages/Cluster/ClusterSections.jsx b/src/pages/Cluster/ClusterSections.jsx index 69241c7..17e2ac9 100644 --- a/src/pages/Cluster/ClusterSections.jsx +++ b/src/pages/Cluster/ClusterSections.jsx @@ -6,6 +6,10 @@ import { makeTextColumn, makeNumericColumnPlanFact } from "../../components/Table"; +import { invokeWebApiWrapperAsync } from '../../components/factory'; +import { WellOperationStatService } from '../../services/api'; +import ChartDepthToDay from '../../components/charts/ChartDepthToDay'; +import WellOperationsTable from './WellOperationsTable' import { calcAndUpdateStatsBySections, makeFilterMinMaxFunction } from "./functions"; @@ -22,111 +26,19 @@ const filtersMinMax = [ const filtersSectionsType = []; -const ModalWindowButton = ({ - buttonIcon, - buttonText, - modalTitle, - modalContent, -}) => { - const [isModalVisible, setIsModalVisible] = useState(false); - - let content = - typeof modalContent === "string" ? ( - - ) : ( - modalContent - ); - - return ( - <> - - setIsModalVisible(false)} - onCancel={() => setIsModalVisible(false)} - width={1400} - > - {content} - - - ); -}; - -const columns = [ - makeTextColumn("скв №", "caption", null, null, (_, item) => ( - {item.caption} - )), - makeTextColumn("Секция", "sectionType", filtersSectionsType), - makeNumericColumnPlanFact("Глубина", "sectionWellDepth", filtersMinMax, makeFilterMinMaxFunction), - makeNumericColumnPlanFact( - "Продолжительность", - "sectionBuildDays", - filtersMinMax, - makeFilterMinMaxFunction - ), //Цикл строительства - makeNumericColumnPlanFact("МСП", "sectionRateOfPenetration", filtersMinMax, makeFilterMinMaxFunction), - makeNumericColumnPlanFact( - "Рейсовая скорость", - "sectionRouteSpeed", - filtersMinMax, - makeFilterMinMaxFunction - ), - makeNumericColumnPlanFact("Спуск КНБК", "sectionBhaDownSpeed", filtersMinMax, makeFilterMinMaxFunction), //Скорость спуска КНБК - makeNumericColumnPlanFact("Подъем КНБК", "sectionBhaUpSpeed", filtersMinMax, makeFilterMinMaxFunction), //Скорость подъема КНБК - makeNumericColumnPlanFact( - "Скорость спуска ОК", - "sectionCasingDownSpeed", - filtersMinMax, - makeFilterMinMaxFunction - ), - makeNumericColumnPlanFact( - "НПВ, сут", - "nonProductiveTime", - filtersMinMax, - makeFilterMinMaxFunction, - "70px" - ), - { - title: "TVD", - render: (_, record) => ( - } - modalTitle={`График по скв.:${record.caption}`} - /> - ), - //modalContent = {resources['Chart' + record.caption]}/>, - }, - { - title: "Операции", - render: (_, record) => ( - } - modalTitle={`Операции по скв.:${record.caption}`} - /> - ), - //modalContent = {resources['Table' + record.caption]}, - }, - { - title: "Подрядчики", - dataIndex: "companies", - render: (item) => - item?.map((company) => {company.caption}), - }, -]; export default function ClusterSections({ clusterData }) { let { id } = useParams(); const [wellsStat, setWellsStat] = useState([]); const [selectedWells, setSelectedWells] = useState([]); const [selectedWellsKeys, setSelectedWellsKeys] = useState([]); + const [selectedWellId, setSelectedWellId] = useState([]); + const [isTVDModalVisible, setIsTVDModalVisible] = useState(false) + const [isOpsModalVisible, setIsOpsModalVisible] = useState(false) + const [tvdDataPlan, setTvdDataPlan] = useState([]); + const [tvdDataFact, setTvdDataFact] = useState([]); + const [tvdDataForecast, setTvdDataForecast] = useState([]); + const [wellOperations, setWellOperations] = useState([]); calcAndUpdateStatsBySections(wellsStat ?? [], [ "sectionWellDepthPlan", @@ -147,6 +59,38 @@ export default function ClusterSections({ clusterData }) { "nonProductiveTimeFact", ]); + useEffect(() => { + if (selectedWellId > 0) { + invokeWebApiWrapperAsync( + async () => { + const operations = await WellOperationStatService.getTvd(selectedWellId); + + setWellOperations(operations) + + const tvdPlanData = operations.map(el => { + return {key: el.plan?.id, depth: el.plan?.wellDepth, date: el.plan?.startDate} + }).filter(el => el.key) + + setTvdDataPlan(tvdPlanData) + + const tvdFactData = operations.map(el => { + return {key: el.fact?.id, depth: el.fact?.wellDepth, date: el.fact?.startDate} + }).filter(el => el.key) + + setTvdDataFact(tvdFactData) + + const tvdPredictData = operations.map(el => { + return {key: el.predict?.id, depth: el.predict?.wellDepth, date: el.predict?.startDate} + }).filter(el => el.key) + + setTvdDataForecast(tvdPredictData) + }, + null, + `Не удалось загрузить операции по скважине "${selectedWellId}"`, + ); + } + }, [selectedWellId]); + useEffect(() => { let rows = []; @@ -162,23 +106,23 @@ export default function ClusterSections({ clusterData }) { sectionBuildDaysPlan: ( (new Date(section.plan?.end) - new Date(section.plan?.start)) / (1000 * 60 * 60 * 24) - ).toFixed(2), + ), sectionBuildDaysFact: ( (new Date(section.fact?.end) - new Date(section.fact?.start)) / (1000 * 60 * 60 * 24) - ).toFixed(2), - sectionRateOfPenetrationPlan: section.plan?.rop.toFixed(2), - sectionRateOfPenetrationFact: section.fact?.rop.toFixed(2), - sectionRouteSpeedPlan: section.plan?.routeSpeed.toFixed(2), - sectionRouteSpeedFact: section.fact?.routeSpeed.toFixed(2), - sectionBhaDownSpeedPlan: section.plan?.bhaDownSpeed.toFixed(2), - sectionBhaDownSpeedFact: section.fact?.bhaDownSpeed.toFixed(2), - sectionBhaUpSpeedPlan: section.plan?.bhaUpSpeed.toFixed(2), - sectionBhaUpSpeedFact: section.fact?.bhaUpSpeed.toFixed(2), - sectionCasingDownSpeedPlan: section.plan?.casingDownSpeed.toFixed(2), - sectionCasingDownSpeedFact: section.fact?.casingDownSpeed.toFixed(2), - nonProductiveTimePlan: section.plan?.nonProductiveHours.toFixed(2), - nonProductiveTimeFact: section.fact?.nonProductiveHours.toFixed(2), + ), + sectionRateOfPenetrationPlan: section.plan?.rop, + sectionRateOfPenetrationFact: section.fact?.rop, + sectionRouteSpeedPlan: section.plan?.routeSpeed, + sectionRouteSpeedFact: section.fact?.routeSpeed, + sectionBhaDownSpeedPlan: section.plan?.bhaDownSpeed, + sectionBhaDownSpeedFact: section.fact?.bhaDownSpeed, + sectionBhaUpSpeedPlan: section.plan?.bhaUpSpeed, + sectionBhaUpSpeedFact: section.fact?.bhaUpSpeed, + sectionCasingDownSpeedPlan: section.plan?.casingDownSpeed, + sectionCasingDownSpeedFact: section.fact?.casingDownSpeed, + nonProductiveTimePlan: section.plan?.nonProductiveHours, + nonProductiveTimeFact: section.fact?.nonProductiveHours, companies: well.companies, }; @@ -195,6 +139,110 @@ export default function ClusterSections({ clusterData }) { setWellsStat(rows); }, [id, clusterData]); + const columns = [ + makeTextColumn("скв №", "caption", null, null, + (_, item) => {item.caption ?? '-'} + ), + makeTextColumn("Секция", "sectionType", filtersSectionsType, null, + (_, item) => _ ?? '-' + ), + makeNumericColumnPlanFact( + "Глубина", + "sectionWellDepth", + filtersMinMax, + makeFilterMinMaxFunction, + (number) => (!Number.isNaN(number) && number !== undefined) + ? number.toFixed(2) + : '-', + ), + makeNumericColumnPlanFact( + "Продолжительность", + "sectionBuildDays", + filtersMinMax, + makeFilterMinMaxFunction, + (number) => (!Number.isNaN(number) && number !== undefined) + ? number.toFixed(2) + : '-', + ), + makeNumericColumnPlanFact( + "МСП", + "sectionRateOfPenetration", + filtersMinMax, + makeFilterMinMaxFunction, + (number) => (!Number.isNaN(number) && number !== undefined) + ? number.toFixed(2) + : '-', + ), + makeNumericColumnPlanFact( + "Рейсовая скорость", + "sectionRouteSpeed", + filtersMinMax, + makeFilterMinMaxFunction, + (number) => (!Number.isNaN(number) && number !== undefined) + ? number.toFixed(2) + : '-', + ), + makeNumericColumnPlanFact( + "Спуск КНБК", + "sectionBhaDownSpeed", + filtersMinMax, + makeFilterMinMaxFunction, + (number) => (!Number.isNaN(number) && number !== undefined) + ? number.toFixed(2) + : '-', + ), + makeNumericColumnPlanFact( + "Подъем КНБК", + "sectionBhaUpSpeed", + filtersMinMax, + makeFilterMinMaxFunction, + (number) => (!Number.isNaN(number) && number !== undefined) + ? number.toFixed(2) + : '-', + ), + makeNumericColumnPlanFact( + "Скорость спуска ОК", + "sectionCasingDownSpeed", + filtersMinMax, + makeFilterMinMaxFunction, + (number) => (!Number.isNaN(number) && number !== undefined) + ? number.toFixed(2) + : '-', + ), + makeNumericColumnPlanFact( + "НПВ, сут", + "nonProductiveTime", + filtersMinMax, + makeFilterMinMaxFunction, + (number) => (!Number.isNaN(number) && number !== undefined) + ? number.toFixed(2) + : '-', + "70px" + ), + { + title: "TVD", + render: (value) => , + align: 'center' + }, + { + title: "Операции", + render: (value) => , + align: 'center' + }, + { + title: "Подрядчики", + dataIndex: "companies", + render: (item) => + item?.map((company) => {company.caption}), + }, + ]; + const rowSelection = { selectedRowKeys: selectedWellsKeys, onChange: (keys, items) => { @@ -229,6 +277,33 @@ export default function ClusterSections({ clusterData }) { scroll={{ x: true }} pagination={false} /> + + setIsTVDModalVisible(false)} + width={1500} + footer={null} + > + + + + setIsOpsModalVisible(false)} + width={1500} + footer={null} + > + + ); } diff --git a/src/pages/Cluster/ClusterWells.jsx b/src/pages/Cluster/ClusterWells.jsx index 1cae3f2..a8f8043 100644 --- a/src/pages/Cluster/ClusterWells.jsx +++ b/src/pages/Cluster/ClusterWells.jsx @@ -2,6 +2,7 @@ import { useParams } from "react-router-dom"; import { Link } from "react-router-dom"; import { useState, useEffect } from "react"; import { Table, Tag, Button, Modal } from "antd"; +import { LineChartOutlined, ProfileOutlined } from "@ant-design/icons"; import { makeTextColumn, makeGroupColumn, @@ -25,16 +26,7 @@ const filtersMinMax = [ }, ]; -const filtersWellsType = [ - { - text: "Наклонно-направленная", - value: "Наклонно-направленная", - }, - { - text: "Горизонтальная", - value: "Горизонтальная", - }, -]; +const filtersWellsType = []; export default function ClusterWells({ clusterData }) { let { id } = useParams(); @@ -47,6 +39,18 @@ export default function ClusterWells({ clusterData }) { const [tvdDataForecast, setTvdDataForecast] = useState([]); const [wellOperations, setWellOperations] = useState([]); + calcAndUpdateStatsBySections(wellsStat ?? [], [ + "factStart", + "factEnd", + "periodPlan", + "periodFact", + "rateOfPenetrationPlan", + "rateOfPenetrationFact", + "routeSpeedPlan", + "routeSpeedFact", + "notProductiveTime", + ]); + useEffect(() => { if (selectedWellId > 0) { invokeWebApiWrapperAsync( @@ -79,41 +83,36 @@ export default function ClusterWells({ clusterData }) { } }, [selectedWellId]); - calcAndUpdateStatsBySections(wellsStat ?? [], [ - "factStart", - "factEnd", - "periodPlan", - "periodFact", - "rateOfPenetrationPlan", - "rateOfPenetrationFact", - "routeSpeedPlan", - "routeSpeedFact", - "notProductiveTime", - ]); - useEffect(() => { let tableData = clusterData.statsWells?.map((well) => { + + if (!filtersWellsType.some((el) => el.text === well.wellType)) + filtersWellsType.push({ + text: well.wellType, + value: well.wellType, + }); + return { key: well.id, id: well.id, caption: well.caption, wellType: well.wellType, - factStart: new Date(well.total.fact.start).toLocaleString(), - factEnd: new Date(well.total.fact.end).toLocaleString(), + factStart: well.total?.fact?.start, + factEnd: well.total?.fact?.end, periodPlan: ( - (new Date(well.total.plan.end) - new Date(well.total.plan.start)) / + (new Date(well.total?.plan?.end) - new Date(well.total?.plan?.start)) / (1000 * 60 * 60 * 24) - ).toFixed(2), + ), periodFact: ( - (new Date(well.total.fact.end) - new Date(well.total.fact.start)) / + (new Date(well.total?.fact?.end) - new Date(well.total?.fact?.start)) / (1000 * 60 * 60 * 24) - ).toFixed(2), - rateOfPenetrationPlan: well.total.plan.rop.toFixed(2), - rateOfPenetrationFact: well.total.fact.rop.toFixed(2), - routeSpeedPlan: well.total.plan.routeSpeed.toFixed(2), - routeSpeedFact: well.total.fact.routeSpeed.toFixed(2), - notProductiveTimePlan: well.total.plan.nonProductiveHours.toFixed(2), - notProductiveTimeFact: well.total.fact.nonProductiveHours.toFixed(2), + ), + rateOfPenetrationPlan: well.total?.plan?.rop, + rateOfPenetrationFact: well.total?.fact?.rop, + routeSpeedPlan: well.total?.plan?.routeSpeed, + routeSpeedFact: well.total?.fact?.routeSpeed, + notProductiveTimePlan: well.total?.plan?.nonProductiveHours, + notProductiveTimeFact: well.total?.fact?.nonProductiveHours, companies: well.companies, }; }); @@ -122,31 +121,63 @@ export default function ClusterWells({ clusterData }) { }, [id, clusterData]); const columns = [ - makeTextColumn("скв №", "caption", null, null, (_, item) => ( - {item.caption} + makeTextColumn("скв №", "caption", null, null, + (_, item) => ({item.caption ?? '-'} )), - makeTextColumn("Тип скв.", "wellType", filtersWellsType), + makeTextColumn("Тип скв.", "wellType", filtersWellsType, null, + (text) => text ?? '-' + ), makeGroupColumn("Фактические сроки", [ - makeNumericColumn("начало", "factStart"), - makeNumericColumn("окончание", "factEnd"), + makeNumericColumn("начало", "factStart", null, null, (dateString) => !Number.isNaN(new Date(dateString).getTime()) ? new Date(dateString).toLocaleString() : '-'), + makeNumericColumn("окончание", "factEnd", null, null, (dateString) => !Number.isNaN(new Date(dateString).getTime()) ? new Date(dateString).toLocaleString() : '-'), ]), - makeNumericColumnPlanFact("Продолжительность", "period", filtersMinMax, makeFilterMinMaxFunction), - makeNumericColumnPlanFact("МСП", "rateOfPenetration", filtersMinMax, makeFilterMinMaxFunction), - makeNumericColumnPlanFact("Рейсовая скорость", "routeSpeed", filtersMinMax, makeFilterMinMaxFunction), - makeNumericColumnPlanFact("НПВ, сут", "notProductiveTime", filtersMinMax, makeFilterMinMaxFunction), + makeNumericColumnPlanFact( + "Продолжительность", + "period", + filtersMinMax, + makeFilterMinMaxFunction, + (number) => (!Number.isNaN(number) && number !== undefined) + ? number.toFixed(2) + : '-'), + makeNumericColumnPlanFact( + "МСП", + "rateOfPenetration", + filtersMinMax, + makeFilterMinMaxFunction, + (number) => (!Number.isNaN(number) && number !== undefined) + ? number.toFixed(2) + : '-'), + makeNumericColumnPlanFact( + "Рейсовая скорость", + "routeSpeed", + filtersMinMax, + makeFilterMinMaxFunction, + (number) => (!Number.isNaN(number) && number !== undefined) + ? number.toFixed(2) + : '-'), + makeNumericColumnPlanFact( + "НПВ, сут", + "notProductiveTime", + filtersMinMax, + makeFilterMinMaxFunction, + (number) => (!Number.isNaN(number) && number !== undefined) + ? number.toFixed(2) + : '-'), { - title: "График глубина-день", + title: "TVD", render: (value) => , + }}>, + align: 'center' }, { - title: "Таблица по операциям", + title: "Операции", render: (value) => , + }}>, + align: 'center' }, { title: "Подрядчики", diff --git a/src/pages/Cluster/WellOperationsTable.jsx b/src/pages/Cluster/WellOperationsTable.jsx index 8c36d3b..d42e1ae 100644 --- a/src/pages/Cluster/WellOperationsTable.jsx +++ b/src/pages/Cluster/WellOperationsTable.jsx @@ -10,21 +10,43 @@ export default function WellOperationsTable({wellOperations}) { const columns = [ makeTextColumn("Конструкция секции","sectionType"), makeTextColumn("Операция","operationName"), - makeNumericColumnPlanFact("Глубина забоя", "depth"), - makeNumericColumnPlanFact("Часы", "durationHours"), - makeNumericColumnPlanFact("Комментарий", "comment") + makeNumericColumnPlanFact( + "Глубина забоя", + "depth", + null, + null, + (number) => (!Number.isNaN(number) && number !== undefined) + ? number.toFixed(2) + : '-' + ), + makeNumericColumnPlanFact( + "Часы", + "durationHours", + null, + null, + (number) => (!Number.isNaN(number) && number !== undefined) + ? number.toFixed(2) + : '-' + ), + makeNumericColumnPlanFact( + "Комментарий", + "comment", + null, + null, + (text) => text ?? '-' + ) ]; const operations = wellOperations.map(el => { return { key: el.plan?.id ?? el.fact.id, sectionType: el.plan?.wellSectionTypeName ?? el.fact?.wellSectionTypeName, - operationName: `${el.plan?.categoryName ?? el.fact?.categoryName} ${' '} + operationName: `${el.plan?.categoryName ?? el.fact?.categoryName ?? ''} ${' '} ${el.plan?.categoryInfo ?? el.fact?.categoryInfo ?? ''}`, - depthPlan: el.plan?.wellDepth?.toFixed(0) ?? '-', - depthFact: el.fact?.wellDepth?.toFixed(0) ?? '-', - durationHoursPlan: el.plan?.durationHours?.toFixed(2) ?? '-', - durationHoursFact: el.fact?.durationHours?.toFixed(2) ?? '-', + depthPlan: el.plan?.wellDepth, + depthFact: el.fact?.wellDepth, + durationHoursPlan: el.plan?.durationHours, + durationHoursFact: el.fact?.durationHours, commentPlan: el.plan?.comment ?? '-', commentFact: el.fact?.comment ?? '-' }