This commit is contained in:
KharchenkoVV 2021-08-27 17:11:48 +05:00
commit e586e7ae59
10 changed files with 481 additions and 544 deletions

View File

@ -2,7 +2,7 @@ import { useState, useEffect } from 'react'
import { DepositService } from '../services/api'
import LoaderPortal from './LoaderPortal'
import { TreeSelect } from 'antd'
import { useHistory } from 'react-router-dom'
import { useHistory, useRouteMatch } from 'react-router-dom'
import { notify } from "./factory"
import '../styles/wellTreeSelect.css'
@ -10,6 +10,7 @@ export default function WellTreeSelector() {
const [wellsTree, setWellsTree] = useState([])
const [showLoader, setShowLoader] = useState(false)
const history = useHistory()
const routeMatch = useRouteMatch('/:route/:id')
const updateWellsList = async () => {
setShowLoader(true)
@ -21,8 +22,8 @@ export default function WellTreeSelector() {
value: `/deposit/${deposit.id}`,
children: deposit.clusters.map(cluster => ({
title: cluster.caption,
key: `/cluster/${cluster.id}/all`,
value: `/cluster/${cluster.id}/all`,
key: `/cluster/${cluster.id}`,
value: `/cluster/${cluster.id}`,
children: cluster.wells.map(well => ({
title: well.caption,
key: `/well/${well.id}`,
@ -56,6 +57,7 @@ export default function WellTreeSelector() {
treeData={wellsTree}
treeDefaultExpandAll
onSelect={onSelect}
value = {routeMatch?.url}
/>
</LoaderPortal>
)

View File

@ -0,0 +1,231 @@
import { Table, Tag, Button, Badge, Divider, Modal } from "antd";
import { useParams } from "react-router-dom";
import { LineChartOutlined, ProfileOutlined } from "@ant-design/icons";
import { useState, useEffect } from "react";
import {
makeTextColumn,
makeNumericColumnPlanFact,
calcAndUpdateStatsBySections,
} from "../../components/Table";
const filtersMinMax = [
{
text: "min",
value: "min",
},
{
text: "max",
value: "max",
},
];
const filtersSectionsType = [];
const ModalWindowButton = ({
buttonIcon,
buttonText,
modalTitle,
modalContent,
}) => {
const [isModalVisible, setIsModalVisible] = useState(false);
let content =
typeof modalContent === "string" ? (
<img src={modalContent} alt="" style={{ width: "100%" }} />
) : (
modalContent
);
return (
<>
<Button
type="secondary"
onClick={() => setIsModalVisible(true)}
icon={buttonIcon}
>
{buttonText}
</Button>
<Modal
title={modalTitle}
centered
visible={isModalVisible}
onOk={() => setIsModalVisible(false)}
onCancel={() => setIsModalVisible(false)}
width={1400}
>
{content}
</Modal>
</>
);
};
const columns = [
makeTextColumn("скв №", "caption"),
makeTextColumn("Секция", "sectionType", filtersSectionsType),
makeNumericColumnPlanFact("Глубина", "sectionWellDepth", filtersMinMax),
makeNumericColumnPlanFact(
"Продолжительность",
"sectionBuildDays",
filtersMinMax
), //Цикл строительства
makeNumericColumnPlanFact("МСП", "sectionRateOfPenetration", filtersMinMax),
makeNumericColumnPlanFact(
"Рейсовая скорость",
"sectionRouteSpeed",
filtersMinMax
),
makeNumericColumnPlanFact("Спуск КНБК", "sectionBhaDownSpeed", filtersMinMax), //Скорость спуска КНБК
makeNumericColumnPlanFact("Подъем КНБК", "sectionBhaUpSpeed", filtersMinMax), //Скорость подъема КНБК
makeNumericColumnPlanFact(
"Скорость спуска ОК",
"sectionCasingDownSpeed",
filtersMinMax
),
makeNumericColumnPlanFact(
"НПВ, сут",
"nonProductiveTime",
filtersMinMax,
"70px"
),
{
title: "TVD",
render: (_, record) => (
<ModalWindowButton
buttonIcon={<LineChartOutlined />}
modalTitle={`График по скв.:${record.caption}`}
/>
),
//modalContent = {resources['Chart' + record.caption]}/>,
},
{
title: "Операции",
render: (_, record) => (
<ModalWindowButton
buttonIcon={<ProfileOutlined />}
modalTitle={`Операции по скв.:${record.caption}`}
/>
),
//modalContent = {resources['Table' + record.caption]},
},
{
title: "Подрядчики",
dataIndex: "companies",
render: (item) =>
item?.map((company) => <Tag color="blue">{company.caption}</Tag>),
},
];
export default function ClusterSections({ clusterData }) {
let { id } = useParams();
const [wellsStat, setWellsStat] = useState([]);
const [selectedWells, setSelectedWells] = useState([]);
const [selectedWellsKeys, setSelectedWellsKeys] = useState([]);
calcAndUpdateStatsBySections(wellsStat ?? [], [
"sectionWellDepthPlan",
"sectionWellDepthFact",
"sectionBuildDaysPlan",
"sectionBuildDaysFact",
"sectionRateOfPenetrationPlan",
"sectionRateOfPenetrationFact",
"sectionRouteSpeedPlan",
"sectionRouteSpeedFact",
"sectionBhaDownSpeedPlan",
"sectionBhaDownSpeedFact",
"sectionBhaUpSpeedPlan",
"sectionBhaUpSpeedFact",
"sectionCasingDownSpeedPlan",
"sectionCasingDownSpeedFact",
"nonProductiveTimePlan",
"nonProductiveTimeFact",
]);
useEffect(() => {
let rows = [];
clusterData.statsWells?.forEach((el) => {
el.sections.forEach((section) => {
let row = {
key: el.caption + section.id,
id: el.caption + section.id,
caption: el.caption,
sectionType: section.caption,
sectionWellDepthPlan: section.plan.wellDepthEnd,
sectionWellDepthFact: section.fact.wellDepthEnd,
sectionBuildDaysPlan: (
Math.abs(
new Date(section.plan.start) - new Date(section.plan.end)
) /
(1000 * 60 * 60 * 24)
).toFixed(2),
sectionBuildDaysFact: (
Math.abs(
new Date(section.fact.start) - new Date(section.fact.end)
) /
(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),
companies: el.companies,
};
rows.push(row);
if (!filtersSectionsType.some((el) => el.text === section.caption))
filtersSectionsType.push({
text: section.caption,
value: section.caption,
});
});
});
setWellsStat(rows);
}, [id, clusterData]);
const rowSelection = {
selectedRowKeys: selectedWellsKeys,
onChange: (keys, items) => {
setSelectedWells(items);
setSelectedWellsKeys(keys);
},
};
return (
<>
<Table
columns={columns}
dataSource={wellsStat}
size={"small"}
bordered
scroll={{ x: true, y: 620 }}
rowSelection={rowSelection}
pagination={false}
/>
<Divider />
<Badge.Ribbon text="комбинированная скважина" color="gray">
<h3>
Выбранные секции<></>
</h3>
</Badge.Ribbon>
<Table
columns={columns}
dataSource={selectedWells}
rowSelection={rowSelection}
size={"small"}
bordered
scroll={{ x: true }}
pagination={false}
/>
</>
);
}

View File

@ -0,0 +1,125 @@
import { useParams } from "react-router-dom";
import { Link } from "react-router-dom";
import { useState, useEffect } from "react";
import { Table, Tag, Button } from "antd";
import {
makeTextColumn,
makeGroupColumn,
makeNumericColumn,
makeNumericColumnPlanFact,
calcAndUpdateStatsBySections,
} from "../../components/Table";
const filtersMinMax = [
{
text: "min",
value: "min",
},
{
text: "max",
value: "max",
},
];
const filtersWellsType = [
{
text: "Наклонно-направленная",
value: "Наклонно-направленная",
},
{
text: "Горизонтальная",
value: "Горизонтальная",
},
];
export default function ClusterWells({ clusterData }) {
let { id } = useParams();
const [wellsStat, setWellsStat] = useState([]);
calcAndUpdateStatsBySections(wellsStat ?? [], [
"factStart",
"factEnd",
"periodPlan",
"periodFact",
"rateOfPenetrationPlan",
"rateOfPenetrationFact",
"routeSpeedPlan",
"routeSpeedFact",
"notProductiveTime",
]);
useEffect(() => {
let tableData = clusterData.statsWells?.map((el) => {
return {
key: el.id,
id: el.id,
caption: el.caption,
wellType: el.wellType,
factStart: new Date(el.total.fact.start).toLocaleString(),
factEnd: new Date(el.total.fact.end).toLocaleString(),
periodPlan: (
Math.abs(
new Date(el.total.plan.start) - new Date(el.total.plan.end)
) /
(1000 * 60 * 60 * 24)
).toFixed(2),
periodFact: (
Math.abs(
new Date(el.total.fact.start) - new Date(el.total.fact.end)
) /
(1000 * 60 * 60 * 24)
).toFixed(2),
rateOfPenetrationPlan: el.total.plan.rop.toFixed(2),
rateOfPenetrationFact: el.total.fact.rop.toFixed(2),
routeSpeedPlan: el.total.plan.routeSpeed.toFixed(2),
routeSpeedFact: el.total.fact.routeSpeed.toFixed(2),
notProductiveTimePlan: el.total.plan.nonProductiveHours.toFixed(2),
notProductiveTimeFact: el.total.fact.nonProductiveHours.toFixed(2),
companies: el.companies,
};
});
setWellsStat(tableData);
}, [id, clusterData]);
const columns = [
makeTextColumn("скв №", "caption", null, null, (_, item) => (
<Link to={`/well/${item.id}`}>{item.caption}</Link>
)),
makeTextColumn("Тип скв.", "wellType", filtersWellsType),
makeGroupColumn("Фактические сроки", [
makeNumericColumn("начало", "factStart"),
makeNumericColumn("окончание", "factEnd"),
]),
makeNumericColumnPlanFact("Продолжительность", "period", filtersMinMax),
makeNumericColumnPlanFact("МСП", "rateOfPenetration", filtersMinMax),
makeNumericColumnPlanFact("Рейсовая скорость", "routeSpeed", filtersMinMax),
makeNumericColumnPlanFact("НПВ, сут", "notProductiveTime", filtersMinMax),
{
title: "График глубина-день",
render: (_, item) => <Button>Открыть</Button>,
},
{
title: "Таблица по операциям",
render: (_) => <Button>Открыть</Button>,
},
{
title: "Подрядчики",
key: "companies",
dataIndex: "companies",
render: (item) =>
item.map((company) => <Tag color="blue">{company.caption}</Tag>),
},
];
return (
<Table
columns={columns}
dataSource={wellsStat}
size={"small"}
bordered
pagination={false}
rowKey={(record) => record.id}
/>
);
}

View File

@ -0,0 +1,67 @@
import { Layout, Menu } from "antd";
import { Link, Switch, Route, Redirect, useParams } from "react-router-dom";
import { useState, useEffect } from "react";
import ClusterWells from "./ClusterWells";
import ClusterSections from "./ClusterSections";
import LoaderPortal from "../../components/LoaderPortal";
import { invokeWebApiWrapperAsync } from "../../components/factory";
import { WellOperationStatService } from "../../services/api";
const { Content } = Layout;
export default function Cluster() {
let { idClaster, tab } = useParams();
const [data, setData] = useState([]);
const [showLoader, setShowLoader] = useState(false);
useEffect(() => {
invokeWebApiWrapperAsync(
async () => {
const clusterData = await WellOperationStatService.getStatCluster(
idClaster
);
setData(clusterData);
},
setShowLoader,
`Не удалось загрузить данные по кусту "${idClaster}"`
);
}, [idClaster]);
return (
<>
<Layout>
<Menu
mode="horizontal"
selectable={true}
selectedKeys={[tab]}
className="well_menu"
>
<Menu.Item key="wells">
<Link to={`/cluster/${idClaster}/wells`}>Скважины</Link>
</Menu.Item>
<Menu.Item key="sections">
<Link to={`/cluster/${idClaster}/sections`}>Секции</Link>
</Menu.Item>
</Menu>
</Layout>
<Layout>
<LoaderPortal show={showLoader}>
<Content className="site-layout-background">
<Switch>
<Route path="/cluster/:id/wells">
<ClusterWells clusterData={data} />
</Route>
<Route path="/cluster/:id/sections">
<ClusterSections clusterData={data} />
</Route>
<Route path="/">
<Redirect to={`/cluster/${idClaster}/wells`} />
</Route>
</Switch>
</Content>
</LoaderPortal>
</Layout>
</>
);
}

View File

@ -1,58 +0,0 @@
import { Layout, Menu } from "antd";
import { Link, Switch, Route, useParams } from "react-router-dom";
import { useState, useEffect } from "react"
import ClusterWells from './ClusterWells'
import ClusterSections from './ClusterSections'
import LoaderPortal from '../components/LoaderPortal'
import {invokeWebApiWrapperAsync} from '../components/factory'
import {WellOperationStatService} from "../services/api";
const { Content } = Layout;
export default function ClusterInfo() {
let { id } = useParams();
let { tab } = useParams()
const [data, setData] = useState([]);
const [showLoader, setShowLoader] = useState(false)
useEffect(() => {
invokeWebApiWrapperAsync(
async () => {
const clusterData = await WellOperationStatService.getStatCluster(id)
setData(clusterData)
},
setShowLoader,
`Не удалось загрузить данные по кусту "${id}"`)
} ,[id])
return(<>
<Layout>
<Menu mode="horizontal"
selectable={true}
selectedKeys={[tab]}
className="well_menu">
<Menu.Item key="all">
<Link to={`/cluster/${id}/all`}>Скважины</Link>
</Menu.Item>
<Menu.Item key="sections">
<Link to={`/cluster/${id}/sections`}>Секции</Link>
</Menu.Item>
</Menu>
</Layout>
<Layout>
<LoaderPortal show={showLoader}>
<Content className="site-layout-background">
<Switch>
<Route path="/cluster/:id/all">
<ClusterWells clusterData = {data}/>
</Route>
<Route path="/cluster/:id/sections">
<ClusterSections clusterData = {data}/>
</Route>
</Switch>
</Content>
</LoaderPortal>
</Layout>
</>)
}

View File

@ -1,183 +0,0 @@
import { Table, Tag, Button, Badge, Divider, Modal} from "antd"
import { useParams } from "react-router-dom";
import { LineChartOutlined, ProfileOutlined } from '@ant-design/icons'
import { useState, useEffect } from "react"
import { makeTextColumn, makeNumericColumnPlanFact, calcAndUpdateStatsBySections } from '../components/Table/index'
const filtersMinMax = [
{
text: "min",
value: "min",
},
{
text: "max",
value: "max",
},
]
const filtersSectionsType = [ ]
const ModalWindowButton = ({buttonIcon, buttonText, modalTitle, modalContent}) =>{
const [isModalVisible, setIsModalVisible] = useState(false)
let content = (typeof(modalContent)==="string")
? <img src={modalContent} alt="" style={{width: "100%"}}/>
: modalContent
return (
<>
<Button
type="secondary"
onClick={() => setIsModalVisible(true)}
icon={buttonIcon}
>{buttonText}</Button>
<Modal
title={modalTitle}
centered
visible={isModalVisible}
onOk={() => setIsModalVisible(false)}
onCancel={() => setIsModalVisible(false)}
width={1400}>
{content}
</Modal>
</>
)
}
const columns = [
makeTextColumn('скв №', 'caption'),
makeTextColumn('Секция', 'sectionType', filtersSectionsType),
makeNumericColumnPlanFact('Глубина', 'sectionWellDepth', filtersMinMax),
makeNumericColumnPlanFact('Продолжительность', 'sectionBuildDays', filtersMinMax), //Цикл строительства
makeNumericColumnPlanFact('МСП', 'sectionRateOfPenetration', filtersMinMax),
makeNumericColumnPlanFact('Рейсовая скорость', 'sectionRouteSpeed', filtersMinMax),
makeNumericColumnPlanFact('Спуск КНБК', 'sectionBhaDownSpeed', filtersMinMax),//Скорость спуска КНБК
makeNumericColumnPlanFact('Подъем КНБК', 'sectionBhaUpSpeed', filtersMinMax),//Скорость подъема КНБК
makeNumericColumnPlanFact('Скорость спуска ОК', 'sectionCasingDownSpeed', filtersMinMax),
makeNumericColumnPlanFact('НПВ, сут', 'nonProductiveTime', filtersMinMax, '70px'),
{
title: "TVD",
render: (_, record) => <ModalWindowButton
buttonIcon={<LineChartOutlined/>}
modalTitle={`График по скв.:${record.caption}`}/>
//modalContent = {resources['Chart' + record.caption]}/>,
},
{
title: "Операции",
render: (_, record) => <ModalWindowButton
buttonIcon={<ProfileOutlined/>}
modalTitle={`Операции по скв.:${record.caption}`}/>
//modalContent = {resources['Table' + record.caption]},
},
{
title: "Подрядчики",
dataIndex: "companies",
render: (item) =>
item?.map((company) => <Tag color="blue">{company.caption}</Tag>),
},
]
export default function ClusterSections({clusterData}) {
let { id } = useParams()
const [wellsStat, setWellsStat] = useState([])
const [selectedWells, setSelectedWells] = useState([])
const [selectedWellsKeys, setSelectedWellsKeys] = useState([])
calcAndUpdateStatsBySections(wellsStat ?? [], [
"sectionWellDepthPlan",
"sectionWellDepthFact",
"sectionBuildDaysPlan",
"sectionBuildDaysFact",
"sectionRateOfPenetrationPlan",
"sectionRateOfPenetrationFact",
"sectionRouteSpeedPlan",
"sectionRouteSpeedFact",
"sectionBhaDownSpeedPlan",
"sectionBhaDownSpeedFact",
"sectionBhaUpSpeedPlan",
"sectionBhaUpSpeedFact",
"sectionCasingDownSpeedPlan",
"sectionCasingDownSpeedFact",
"nonProductiveTimePlan",
"nonProductiveTimeFact"
])
useEffect(() => {
let rows = []
clusterData.statsWells?.forEach(el => {
el.sections.forEach(section => {
let row = {
key: el.caption + section.id,
id: el.caption + section.id,
caption: el.caption,
sectionType: section.caption,
sectionWellDepthPlan: section.plan.wellDepthEnd,
sectionWellDepthFact: section.fact.wellDepthEnd,
sectionBuildDaysPlan: (Math.abs(new Date(section.plan.start) -
new Date(section.plan.end)) / (1000 * 60 * 60 * 24)).toFixed(2),
sectionBuildDaysFact: (Math.abs(new Date(section.fact.start) -
new Date(section.fact.end)) / (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),
companies: el.companies
}
rows.push(row)
if(!filtersSectionsType.some(el => el.text === section.caption))
filtersSectionsType.push({text: section.caption, value: section.caption})
})
})
setWellsStat(rows)
}, [id, clusterData])
const rowSelection = {
selectedRowKeys: selectedWellsKeys,
onChange: (keys, items) => {
setSelectedWells(items)
setSelectedWellsKeys(keys)
},
}
return (
<>
<Table
columns={columns}
dataSource={wellsStat}
size={"small"}
bordered
scroll={{ x: true, y: 620}}
rowSelection={rowSelection}
pagination={false}
/>
<Divider/>
<Badge.Ribbon text="комбинированная скважина" color="gray">
<h3>Выбранные секции<></></h3>
</Badge.Ribbon>
<Table
columns={columns}
dataSource={selectedWells}
rowSelection={rowSelection}
size={"small"}
bordered
scroll={{ x: true}}
pagination={false}
/>
</>
)
}

View File

@ -1,143 +0,0 @@
import {useParams} from "react-router-dom";
import {Link} from "react-router-dom";
import LoaderPortal from '../components/LoaderPortal'
import { useState, useEffect } from "react";
import {ClusterService} from '../services/api'
import { notify } from "../components/factory"
import {Table, Tag, Button} from 'antd';
const columns = [
{
title: 'скв №',
key: 'caption',
dataIndex: 'caption',
render: (_, item) => <Link to={`/well/${item.id}`}>{item.caption}</Link>
},
{
title: 'Тип скв.',
key: 'wellType',
dataIndex: 'wellType',
},
{
title: 'Фактические сроки бурения',
children: [
{
title: 'начало',
key: 'factStart',
dataIndex: 'factStart',
},
{
title: 'окончание',
key: 'factEnd',
dataIndex: 'factEnd',
},
]
},
{
title: 'Продолжительность бурения',
children: [
{
title: 'план',
key: 'periodPlan',
dataIndex: 'periodPlan',
},
{
title: 'факт',
key: 'periodFact',
dataIndex: 'periodFact',
},
]
},
{
title: 'МСП за скв',
children: [
{
title: 'план',
key: 'rateOfPenetrationPlan',
dataIndex: 'rateOfPenetrationPlan',
},
{
title: 'факт',
key: 'rateOfPenetrationFact',
dataIndex: 'rateOfPenetrationFact',
},
],
},
{
title: 'Рейсовая скорость за скв',
children: [
{
title: 'план',
key: 'routeSpeedPlan',
dataIndex: 'routeSpeedPlan',
},
{
title: 'факт',
key: 'routeSpeedFact',
dataIndex: 'routeSpeedFact',
},
],
},
{
title: 'Секции',
key: 'sections',
dataIndex: 'sections',
render: (item) => (<span>таблица по секциям</span>)
},
{
title: 'График глубина-день',
render: _ => (<Button>Открыть</Button>)
},
{
title: 'Таблица по операциям',
render: _ => (<Button>Открыть</Button>)
},
{
title: 'Подрядчики',
key: 'companies',
dataIndex: 'companies',
render: (item) => item.map(company => <Tag color="blue">{company.caption}</Tag>)
},
];
export default function ClusterStat() {
let { id } = useParams()
const [clusterTitle, setClusterTitle] = useState("")
const [wellsStat, setWellsStat] = useState(null)
const [showLoader, setShowLoader] = useState(false)
useEffect(()=>{
const updateWellsStat = async() => {
setShowLoader(true)
try{
const msInDay = 1000*60*60*24
const data = await ClusterService.getStat(id)
const wellsStat = data.wellsStat.map(w=>({...w,
periodPlan: (new Date(w.planEnd) - new Date(w.planStart))/msInDay,
periodFact: (new Date(w.factEnd) - new Date(w.factStart))/msInDay,
}))
setWellsStat(wellsStat)
setClusterTitle(data.caption)
}
catch(ex) {
notify(`Не удалось загрузить статистику по скважинам куста "${id}"`, 'error')
console.log(ex)
}
setShowLoader(false)
}
updateWellsStat()
},[id])
return(
<LoaderPortal show={showLoader}>
<h3>{clusterTitle}</h3>
<Table
columns={columns}
dataSource={wellsStat}
size={'small'}
bordered
pagination={false}
rowKey={(record) => record.id}
/>
</LoaderPortal>)
}

View File

@ -1,113 +0,0 @@
import { useParams } from "react-router-dom";
import { Link } from "react-router-dom";
import { useState, useEffect } from "react";
import { Table, Tag, Button } from 'antd';
import { makeTextColumn, makeGroupColumn, makeNumericColumn,
makeNumericColumnPlanFact, calcAndUpdateStatsBySections } from '../components/Table/index'
const filtersMinMax = [
{
text: "min",
value: "min",
},
{
text: "max",
value: "max",
},
]
const filtersWellsType = [
{
text: "Наклонно-направленная",
value: "Наклонно-направленная",
},
{
text: "Горизонтальная",
value: "Горизонтальная",
}
]
export default function ClusterWells({clusterData}) {
let { id } = useParams()
const [wellsStat, setWellsStat] = useState([])
calcAndUpdateStatsBySections(wellsStat ?? [], [
"factStart",
"factEnd",
"periodPlan",
"periodFact",
"rateOfPenetrationPlan",
"rateOfPenetrationFact",
"routeSpeedPlan",
"routeSpeedFact",
"notProductiveTime"
])
useEffect(() => {
let tableData = clusterData.statsWells?.map(el => {
return {
key: el.id,
id: el.id,
caption: el.caption,
wellType: el.wellType,
factStart: new Date(el.total.fact.start).toLocaleString(),
factEnd: new Date(el.total.fact.end).toLocaleString(),
periodPlan: (Math.abs(new Date(el.total.plan.start) -
new Date(el.total.plan.end)) / (1000 * 60 * 60 * 24)).toFixed(2),
periodFact: (Math.abs(new Date(el.total.fact.start) -
new Date(el.total.fact.end)) / (1000 * 60 * 60 * 24)).toFixed(2),
rateOfPenetrationPlan: el.total.plan.rop.toFixed(2),
rateOfPenetrationFact: el.total.fact.rop.toFixed(2),
routeSpeedPlan: el.total.plan.routeSpeed.toFixed(2),
routeSpeedFact: el.total.fact.routeSpeed.toFixed(2),
notProductiveTimePlan: el.total.plan.nonProductiveHours.toFixed(2),
notProductiveTimeFact: el.total.fact.nonProductiveHours.toFixed(2),
companies: el.companies
}
})
setWellsStat(tableData)
}, [id, clusterData])
const columns = [
makeTextColumn('скв №', 'caption', null, null,
(_, item) => <Link to={`/well/${item.id}`}>{item.caption}</Link>),
makeTextColumn('Тип скв.', 'wellType', filtersWellsType),
makeGroupColumn( 'Фактические сроки', [
makeNumericColumn('начало', 'factStart'),
makeNumericColumn('окончание', 'factEnd'),
]),
makeNumericColumnPlanFact('Продолжительность', 'period', filtersMinMax),
makeNumericColumnPlanFact('МСП', 'rateOfPenetration', filtersMinMax),
makeNumericColumnPlanFact('Рейсовая скорость', 'routeSpeed', filtersMinMax),
makeNumericColumnPlanFact('НПВ, сут', 'notProductiveTime', filtersMinMax),
{
title: 'График глубина-день',
render: (_, item) => (<Button>Открыть</Button>)
},
{
title: 'Таблица по операциям',
render: _ => (<Button>Открыть</Button>)
},
{
title: 'Подрядчики',
key: 'companies',
dataIndex: 'companies',
render: (item) => item.map(company => <Tag color="blue">{company.caption}</Tag>)
},
];
return (
<Table
columns={columns}
dataSource={wellsStat}
size={'small'}
bordered
pagination={false}
rowKey={(record) => record.id}
/>
)
}

View File

@ -1,31 +1,30 @@
import Deposit from './Deposit'
import ClusterInfo from './ClusterInfo'
import { Redirect, Route, Switch } from "react-router-dom";
import Deposit from "./Deposit";
import Cluster from "./Cluster";
import Well from "./Well";
import LayoutPortal from '../components/LayoutPortal'
import {Redirect, Route, Switch} from "react-router-dom";
import LayoutPortal from "../components/LayoutPortal";
export default function Main() {
return (
<Switch>
<Route path="/well/:idWell/">
<LayoutPortal>
<Well/>
</LayoutPortal>
</Route>
<Route path="/deposit">
<LayoutPortal noSheet>
<Deposit/>
</LayoutPortal>
</Route>
<Route path="/cluster/:id/:tab">
<LayoutPortal>
<ClusterInfo />
</LayoutPortal>
</Route>
<Route path="/">
<Redirect to={{pathname: `/deposit`}}/>
</Route>
</Switch>
)
<Switch>
<Route path="/deposit">
<LayoutPortal noSheet>
<Deposit />
</LayoutPortal>
</Route>
<Route path="/cluster/:idClaster/:tab?">
<LayoutPortal>
<Cluster />
</LayoutPortal>
</Route>
<Route path="/well/:idWell/:tab?">
<LayoutPortal>
<Well />
</LayoutPortal>
</Route>
<Route path="/">
<Redirect to={{ pathname: `/deposit` }} />
</Route>
</Switch>
);
}

View File

@ -1,19 +1,25 @@
import { Layout, Menu } from "antd";
import { FolderOutlined, FundViewOutlined, AlertOutlined, FilePdfOutlined, DatabaseOutlined } from "@ant-design/icons";
import {
FolderOutlined,
FundViewOutlined,
AlertOutlined,
FilePdfOutlined,
DatabaseOutlined,
} from "@ant-design/icons";
import { Link, Redirect, Route, Switch, useParams } from "react-router-dom";
import TelemetryView from "./TelemetryView";
import Messages from "./Messages";
import Report from "./Report";
import Archive from "./Archive";
import Documents from "./Documents";
import LastData from './LastData'
import LastData from "./LastData";
import { makeMenuItems } from "./Documents/menuItems";
import WellOperations from "./WellOperations";
const { Content } = Layout;
export default function Well() {
let { idWell } = useParams();
let { idWell, tab } = useParams();
const rootPath = `/well/${idWell}`;
const { SubMenu } = Menu;
@ -21,30 +27,34 @@ export default function Well() {
return (
<>
<Layout>
<Menu mode="horizontal" selectable={true} className="well_menu">
<Menu.Item key="1" icon={<FundViewOutlined />}>
<Menu
mode="horizontal"
selectable={true}
selectedKeys={[tab]}
className="well_menu"
>
<Menu.Item key="telemetry" icon={<FundViewOutlined />}>
<Link to={`${rootPath}/telemetry`}>Мониторинг</Link>
</Menu.Item>
<Menu.Item key="2" icon={<AlertOutlined />}>
<Menu.Item key="message" icon={<AlertOutlined />}>
<Link to={`${rootPath}/message`}>Сообщения</Link>
</Menu.Item>
<Menu.Item key="3" icon={<FilePdfOutlined />}>
<Menu.Item key="report" icon={<FilePdfOutlined />}>
<Link to={`${rootPath}/report`}>Рапорт</Link>
</Menu.Item>
<Menu.Item key="5" icon={<FolderOutlined />}>
<Link to={`${rootPath}/operations/plan`}>
Операции по скважине
</Link>
<Menu.Item key="operations" icon={<FolderOutlined />}>
<Link to={`${rootPath}/operations/plan`}>Операции по скважине</Link>
</Menu.Item>
<Menu.Item key="7" icon={<DatabaseOutlined/>}>
<Menu.Item key="archive" icon={<DatabaseOutlined />}>
<Link to={`${rootPath}/archive`}>Архив</Link>
</Menu.Item>
<SubMenu
key="documentsSub"
key="document"
title={
<Link
to={`${rootPath}/document/fluidService` }
className="linkDocuments">
to={`${rootPath}/document/fluidService`}
className="linkDocuments"
>
Документы
</Link>
}
@ -53,7 +63,7 @@ export default function Well() {
>
{makeMenuItems(rootPath)}
</SubMenu>
<Menu.Item key="9" icon={<FolderOutlined />}>
<Menu.Item key="lastData" icon={<FolderOutlined />}>
<Link to={`${rootPath}/lastData`}>Последние данные</Link>
</Menu.Item>
</Menu>
@ -80,7 +90,7 @@ export default function Well() {
<Documents idWell={idWell} />
</Route>
<Route path="/well/:id/lastData">
<LastData/>
<LastData />
</Route>
<Route path="/">
<Redirect to={`${rootPath}/telemetry`} />