forked from ddrilling/asb_cloud_front
219 lines
9.0 KiB
React
219 lines
9.0 KiB
React
|
import { Table as RawTable, Typography } from 'antd'
|
|||
|
import { Fragment, memo, useCallback, useEffect, useState } from 'react'
|
|||
|
|
|||
|
import LoaderPortal from '@components/LoaderPortal'
|
|||
|
import { getTreeData, getTreeLabels, WellSelector } from '@components/WellSelector'
|
|||
|
import { invokeWebApiWrapperAsync } from '@components/factory'
|
|||
|
import { makeGroupColumn, makeNumericColumn, makeNumericRender, makeTextColumn, Table } from '@components/Table'
|
|||
|
import { OperationStatService, WellOperationService } from '@api'
|
|||
|
import { arrayOrDefault } from '@utils'
|
|||
|
|
|||
|
import '@styles/index.css'
|
|||
|
import '@styles/statistics.less'
|
|||
|
|
|||
|
const { Text } = Typography
|
|||
|
const { Summary } = RawTable
|
|||
|
const { Cell, Row } = Summary
|
|||
|
|
|||
|
const numericRender = makeNumericRender()
|
|||
|
const speedNumericRender = (section) => numericRender(section?.speed)
|
|||
|
|
|||
|
export const makeSectionColumn = (title, key, { speedRender } = {}) => makeGroupColumn(title, [
|
|||
|
makeNumericColumn('Проходка', key, null, null, (section => numericRender(section?.depth)), 100),
|
|||
|
makeNumericColumn('Время', key, null, null, (section => numericRender(section?.time)), 100),
|
|||
|
makeNumericColumn((<>V<sub>рейсовая</sub></>), key, null, null, speedRender ?? speedNumericRender, 100),
|
|||
|
])
|
|||
|
|
|||
|
export const defaultColumns = [
|
|||
|
//makeTextColumn('Куст', 'cluster', null, null, null, { fixed: 'left', width: 100 }),
|
|||
|
makeTextColumn('Скважина', 'caption', null, null, null, { fixed: 'left', width: 100 }),
|
|||
|
]
|
|||
|
|
|||
|
const scrollSettings = { scrollToFirstRowOnChange: true, x: 100, y: 200 }
|
|||
|
const summaryColSpan = 1 /// TODO: Когда добавится куст изменить на 2
|
|||
|
|
|||
|
const getWellData = async (wellsList) => {
|
|||
|
const stats = arrayOrDefault(await OperationStatService.getWellsStat(wellsList))
|
|||
|
const wellData = stats.map((well) => {
|
|||
|
const stat = {
|
|||
|
// cluster: null,
|
|||
|
caption: well.caption,
|
|||
|
}
|
|||
|
|
|||
|
well.sections?.forEach(({ id, fact }) => {
|
|||
|
if (!fact) return
|
|||
|
stat[`section_${id}`] = {
|
|||
|
time: (+new Date(fact.end) - +new Date(fact.start)) / 3600_000,
|
|||
|
depth: fact.wellDepthEnd - fact.wellDepthStart,
|
|||
|
speed: fact.routeSpeed,
|
|||
|
}
|
|||
|
})
|
|||
|
|
|||
|
return stat
|
|||
|
})
|
|||
|
|
|||
|
return wellData
|
|||
|
}
|
|||
|
|
|||
|
export const Statistics = memo(({ idWell }) => {
|
|||
|
const [sectionTypes, setSectionTypes] = useState([])
|
|||
|
const [avgColumns, setAvgColumns] = useState(defaultColumns)
|
|||
|
const [cmpColumns, setCmpColumns] = useState(defaultColumns)
|
|||
|
const [isAvgTableLoading, setIsAvgTableLoading] = useState(false)
|
|||
|
const [isCmpTableLoading, setIsCmpTableLoading] = useState(false)
|
|||
|
const [isPageLoading, setIsPageLoading] = useState(false)
|
|||
|
const [avgWells, setAvgWells] = useState([])
|
|||
|
const [cmpWells, setCmpWells] = useState([])
|
|||
|
const [filteredCmpWells, setFilteredCmpWells] = useState([])
|
|||
|
const [avgData, setAvgData] = useState([])
|
|||
|
const [cmpData, setCmpData] = useState([])
|
|||
|
const [avgRow, setAvgRow] = useState({})
|
|||
|
|
|||
|
const cmpSpeedRender = useCallback((key) => (section) => {
|
|||
|
let spanClass = ''
|
|||
|
// Дополнительная проверка на "null" необходима, чтобы значение "0" не стало исключением
|
|||
|
if ((avgRow[key]?.speed ?? null) !== null && (section?.speed ?? null) !== null) {
|
|||
|
const avgSpeed = avgRow[key].speed - section.speed
|
|||
|
if (avgSpeed < 0)
|
|||
|
spanClass = 'high-efficienty'
|
|||
|
else if (avgSpeed > 0)
|
|||
|
spanClass = 'low-efficienty'
|
|||
|
}
|
|||
|
|
|||
|
return (
|
|||
|
<span className={spanClass}>
|
|||
|
{numericRender(section?.speed)}
|
|||
|
</span>
|
|||
|
)
|
|||
|
}, [avgRow])
|
|||
|
|
|||
|
useEffect(() => invokeWebApiWrapperAsync(
|
|||
|
async () => {
|
|||
|
const types = await WellOperationService.getSectionTypes(idWell)
|
|||
|
setSectionTypes(Object.entries(types))
|
|||
|
setAvgColumns([
|
|||
|
...defaultColumns,
|
|||
|
...Object.entries(types).map(([id, name]) => makeSectionColumn(name, `section_${id}`)),
|
|||
|
])
|
|||
|
setCmpColumns([
|
|||
|
...defaultColumns,
|
|||
|
...Object.entries(types).map(([id, name]) => makeSectionColumn(name, `section_${id}`, {
|
|||
|
speedRender: cmpSpeedRender(`section_${id}`)
|
|||
|
}))
|
|||
|
])
|
|||
|
},
|
|||
|
setIsPageLoading,
|
|||
|
`Не удалось получить типы секции`,
|
|||
|
`Получение списка возможных секций`,
|
|||
|
), [idWell, cmpSpeedRender])
|
|||
|
|
|||
|
useEffect(() => invokeWebApiWrapperAsync(
|
|||
|
async () => {
|
|||
|
const avgData = await getWellData(avgWells)
|
|||
|
setAvgData(avgData)
|
|||
|
|
|||
|
const avgRow = {}
|
|||
|
|
|||
|
avgData.forEach((row) => row && Object.keys(row).forEach((key) => {
|
|||
|
if (!key.startsWith('section_')) return
|
|||
|
if (!avgRow[key]) avgRow[key] = { depth: 0, time: 0, speed: 0, count: 0 }
|
|||
|
avgRow[key].depth += row[key].depth ?? 0
|
|||
|
avgRow[key].time += row[key].time ?? 0
|
|||
|
avgRow[key].speed += row[key].speed ?? 0
|
|||
|
avgRow[key].count++
|
|||
|
}))
|
|||
|
|
|||
|
Object.values(avgRow).forEach((section) => section.speed /= section.count)
|
|||
|
|
|||
|
setAvgRow(avgRow)
|
|||
|
},
|
|||
|
setIsAvgTableLoading,
|
|||
|
'Не удалось загрузить данные для расчёта средних значений',
|
|||
|
), [avgWells])
|
|||
|
|
|||
|
useEffect(() => invokeWebApiWrapperAsync(
|
|||
|
async () => {
|
|||
|
const cmpData = await getWellData(cmpWells)
|
|||
|
setCmpData(cmpData)
|
|||
|
},
|
|||
|
setIsCmpTableLoading,
|
|||
|
'Не удалось получить скважины для сравнения',
|
|||
|
), [cmpWells])
|
|||
|
|
|||
|
const getStatisticsAvgSummary = useCallback((data) => (
|
|||
|
<Summary fixed={'bottom'}>
|
|||
|
<Row>
|
|||
|
<Cell index={0} colSpan={summaryColSpan}>
|
|||
|
<Text>Итого:</Text>
|
|||
|
</Cell>
|
|||
|
{sectionTypes.map(([id, _], i) => (
|
|||
|
<Fragment key={id ?? i}>
|
|||
|
<Cell index={3 * i + summaryColSpan}>
|
|||
|
<Text>{numericRender(avgRow[`section_${id}`]?.depth)}</Text>
|
|||
|
</Cell>
|
|||
|
<Cell index={3 * i + summaryColSpan + 1}>
|
|||
|
<Text>{numericRender(avgRow[`section_${id}`]?.time)}</Text>
|
|||
|
</Cell>
|
|||
|
<Cell index={3 * i + summaryColSpan + 2}>
|
|||
|
<Text>{numericRender(avgRow[`section_${id}`]?.speed)}</Text>
|
|||
|
</Cell>
|
|||
|
</Fragment>
|
|||
|
))}
|
|||
|
</Row>
|
|||
|
</Summary>
|
|||
|
), [avgRow, sectionTypes])
|
|||
|
|
|||
|
return (
|
|||
|
<div className={'statistics-page'}>
|
|||
|
<LoaderPortal show={isPageLoading}>
|
|||
|
<h2 style={{ padding: '10px' }}>Расчёт средних значений без Цифровой буровой</h2>
|
|||
|
<div className={'average-table'}>
|
|||
|
<div className={'well-selector'}>
|
|||
|
<span className={'well-selector-label'}>Выберите скважины для расчёта средних значений:</span>
|
|||
|
<WellSelector
|
|||
|
idWell={idWell}
|
|||
|
value={avgWells}
|
|||
|
style={{ flex: 100 }}
|
|||
|
onChange={setAvgWells}
|
|||
|
placeholder={'Ничего не выбрано'}
|
|||
|
/>
|
|||
|
</div>
|
|||
|
<Table
|
|||
|
bordered
|
|||
|
size={'small'}
|
|||
|
pagination={false}
|
|||
|
columns={avgColumns}
|
|||
|
dataSource={avgData}
|
|||
|
scroll={scrollSettings}
|
|||
|
loading={isAvgTableLoading}
|
|||
|
summary={getStatisticsAvgSummary}
|
|||
|
/>
|
|||
|
</div>
|
|||
|
<div className={'compare-table'}>
|
|||
|
<div className={'well-selector'}>
|
|||
|
<span className={'well-selector-label'}>Выберите скважины сравнения:</span>
|
|||
|
<WellSelector
|
|||
|
idWell={idWell}
|
|||
|
value={cmpWells}
|
|||
|
style={{ flex: 100 }}
|
|||
|
onChange={setCmpWells}
|
|||
|
placeholder={'Ничего не выбрано'}
|
|||
|
/>
|
|||
|
</div>
|
|||
|
<Table
|
|||
|
bordered
|
|||
|
size={'small'}
|
|||
|
pagination={false}
|
|||
|
columns={cmpColumns}
|
|||
|
dataSource={cmpData}
|
|||
|
scroll={scrollSettings}
|
|||
|
loading={isCmpTableLoading}
|
|||
|
/>
|
|||
|
</div>
|
|||
|
</LoaderPortal>
|
|||
|
</div>
|
|||
|
)
|
|||
|
})
|
|||
|
|
|||
|
export default Statistics
|