Закладка "Прогнозирование" - карточка технического объекта
This commit is contained in:
parent
57d7dd2e68
commit
a9ffc6cc09
@ -21,11 +21,23 @@ create or replace package UDO_PKG_EQUIPTCF as
|
||||
NINCLUDE_DEF in number, -- Признак включения описания колонок таблицы в ответ
|
||||
COUT out clob -- Сериализованная таблица данных
|
||||
);
|
||||
|
||||
/* Формирование карточки технического объекта */
|
||||
procedure EQCONFIG_THOBJ_CARD
|
||||
(
|
||||
NEQCONFIG in number, -- Рег. номер технического объекта
|
||||
COUT out clob -- Сериализованная карточка
|
||||
);
|
||||
|
||||
end UDO_PKG_EQUIPTCF;
|
||||
/
|
||||
create or replace package body UDO_PKG_EQUIPTCF as
|
||||
|
||||
/*
|
||||
TODO: owner="root" created="02.08.2024"
|
||||
text="Проверка прав доступа при формировании таблицы и карточки ТО"
|
||||
*/
|
||||
|
||||
/* Формирование ветки дерева состава оборудования */
|
||||
function EQCONFIG_HIER_NODE
|
||||
(
|
||||
@ -51,7 +63,9 @@ create or replace package body UDO_PKG_EQUIPTCF as
|
||||
1
|
||||
else
|
||||
0
|
||||
end NHASCHILDREN
|
||||
end NHASCHILDREN,
|
||||
M.OBJ_KIND NOBJ_KIND,
|
||||
0 NSHOW_CARD
|
||||
from EQCONFIG M,
|
||||
EQOBJLEVEL OL
|
||||
where M.PR_OBJ_LEVEL = OL.RN(+)
|
||||
@ -77,6 +91,10 @@ create or replace package body UDO_PKG_EQUIPTCF as
|
||||
else
|
||||
XCHILD := null;
|
||||
end if;
|
||||
/* Для технического объекта, не имеющего дочерних - соберём признак отображения карточки */
|
||||
if ((C.NHASCHILDREN = 0) and (C.NOBJ_KIND is not null)) then
|
||||
C.NSHOW_CARD := 1;
|
||||
end if;
|
||||
/* Соберём лист */
|
||||
XLEAF := PKG_XMAKE.ELEMENT(ICURSOR => NCUR,
|
||||
SNAME => 'children',
|
||||
@ -86,7 +104,10 @@ create or replace package body UDO_PKG_EQUIPTCF as
|
||||
SVALUE => C.NRN),
|
||||
RATTRIBUTE01 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
|
||||
SNAME => 'label',
|
||||
SVALUE => C.SNAME)),
|
||||
SVALUE => C.SNAME),
|
||||
RATTRIBUTE02 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
|
||||
SNAME => 'showCard',
|
||||
NVALUE => C.NSHOW_CARD)),
|
||||
RNODE00 => XCHILD);
|
||||
/* Соберём листы в ветку */
|
||||
XRES := PKG_XMAKE.CONCAT(ICURSOR => NCUR, RNODE00 => XRES, RNODE01 => XLEAF);
|
||||
@ -231,9 +252,10 @@ create or replace package body UDO_PKG_EQUIPTCF as
|
||||
PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => PKG_SQL_BUILD.PKG_NAME(SNAME => 'UDO_PKG_EQUIPDS.CMML_LIST_BY_EQCONFIG') || '(C.RN) SEQUIPDSCMML,');
|
||||
PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => PKG_SQL_BUILD.PKG_NAME(SNAME => 'UDO_PKG_EQUIPDS.CMML_ACT_BY_EQCONFIG') || '(C.RN) NEQUIPDSCMML_ACTION');
|
||||
PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' from EQCONFIG C');
|
||||
PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' left outer join EQOBJKIND OK on C.OBJ_KIND = OK.RN');
|
||||
PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' left outer join HLSTATETYPES ST on C.HLSTATETYPES = ST.RN');
|
||||
PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' left outer join HLSTATETYPES ST on C.HLSTATETYPES = ST.RN,');
|
||||
PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' EQOBJKIND OK');
|
||||
PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' where C.EQPARENT = :NEQPARENT');
|
||||
PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and C.OBJ_KIND = OK.RN');
|
||||
PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' and C.RN in (select ID from COND_BROKER_IDSMART where IDENT = :NIDENT) %ORDER_BY%) D) F');
|
||||
PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' where F.NROW between :NROW_FROM and :NROW_TO');
|
||||
/* Учтём сортировки */
|
||||
@ -316,6 +338,57 @@ create or replace package body UDO_PKG_EQUIPTCF as
|
||||
/* Сериализуем описание */
|
||||
COUT := PKG_P8PANELS_VISUAL.TDATA_GRID_TO_XML(RDATA_GRID => RDG, NINCLUDE_DEF => NINCLUDE_DEF);
|
||||
end EQCONFIG_THOBJ_LIST;
|
||||
|
||||
/* Формирование карточки технического объекта */
|
||||
procedure EQCONFIG_THOBJ_CARD
|
||||
(
|
||||
NEQCONFIG in number, -- Рег. номер технического объекта
|
||||
COUT out clob -- Сериализованная карточка
|
||||
)
|
||||
is
|
||||
NCUR integer; -- Курсор документа для результата
|
||||
XDOC PKG_XMAKE.TNODE; -- Документ для результата
|
||||
XCARD PKG_XMAKE.TNODE; -- XML-карточка
|
||||
begin
|
||||
/* Открываем документ */
|
||||
NCUR := PKG_XMAKE.OPEN_CURSOR();
|
||||
/* Обратимся к данным технического объекта */
|
||||
for C in (select T.RN NRN,
|
||||
T.CODE SCODE,
|
||||
T.NAME SNAME,
|
||||
T.OPER_DATE DOPER_DATE
|
||||
from EQCONFIG T
|
||||
where T.RN = NEQCONFIG)
|
||||
loop
|
||||
/* Соберем карточку */
|
||||
XCARD := PKG_XMAKE.ELEMENT(ICURSOR => NCUR,
|
||||
SNAME => 'techObj',
|
||||
RATTRIBUTES => PKG_XMAKE.ATTRIBUTES(ICURSOR => NCUR,
|
||||
RATTRIBUTE00 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
|
||||
SNAME => 'NRN',
|
||||
NVALUE => C.NRN),
|
||||
RATTRIBUTE01 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
|
||||
SNAME => 'SCODE',
|
||||
SVALUE => C.SCODE),
|
||||
RATTRIBUTE02 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
|
||||
SNAME => 'SNAME',
|
||||
SVALUE => C.SNAME),
|
||||
RATTRIBUTE03 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
|
||||
SNAME => 'DOPER_DATE',
|
||||
DVALUE => C.DOPER_DATE)));
|
||||
end loop;
|
||||
/* Формируем XML-представление документа ответа */
|
||||
XDOC := PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'XDATA', RNODE00 => XCARD);
|
||||
/* Сериализуем документ */
|
||||
COUT := PKG_XMAKE.SERIALIZE_TO_CLOB(ICURSOR => NCUR,
|
||||
ITYPE => PKG_XMAKE.CONTENT_,
|
||||
RNODE => XDOC,
|
||||
RHEADER => PKG_XHEADER.WRAP_ALL(SVERSION => PKG_XHEADER.VERSION_1_0_,
|
||||
SENCODING => PKG_XHEADER.ENCODING_UTF_,
|
||||
SSTANDALONE => PKG_XHEADER.STANDALONE_YES_));
|
||||
/* Закрываем документ */
|
||||
PKG_XMAKE.CLOSE_CURSOR(ICURSOR => NCUR);
|
||||
end EQCONFIG_THOBJ_CARD;
|
||||
|
||||
end UDO_PKG_EQUIPTCF;
|
||||
/
|
||||
|
@ -12,7 +12,8 @@ import { Box, Grid } from "@mui/material"; //Интерфейсные компо
|
||||
import { RichTreeView } from "@mui/x-tree-view/RichTreeView"; //Дерево
|
||||
import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../components/p8p_data_grid"; //Таблица данных
|
||||
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
|
||||
import { useEqConfigTree, useEqConfigTechObjTable, needLoadLevel } from "./forecast_tab_hooks"; //Вспомогательные хуки
|
||||
import { useEqConfigTree, useEqConfigTechObjTable, useEqConfigTechObjCard, findTreeItem, needLoadLevel } from "./forecast_tab_hooks"; //Вспомогательные хуки
|
||||
import { TechObjCard } from "./forecast_tab_layout"; //Вспомогательные компоненты и вёрстка
|
||||
|
||||
//---------
|
||||
//Константы
|
||||
@ -25,22 +26,20 @@ const APP_BAR_HEIGHT = "64px";
|
||||
const TABS_HEIGHT = "49px";
|
||||
|
||||
//Высота кнопки "Ещё"
|
||||
const TABLE_MORE_HEIGHT = "47px";
|
||||
const TABLE_MORE_HEIGHT = "49px";
|
||||
|
||||
//Стили
|
||||
const STYLES = {
|
||||
LEFT_SIDE_GRID: { backgroundColor: "red" },
|
||||
RIGHT_SIDE_GRID: { backgroundColor: "green" },
|
||||
LEFT_SIDE_GRID: {},
|
||||
RIGHT_SIDE_GRID: {},
|
||||
TREE_BOX: {
|
||||
minHeight: `calc(100vh - ${APP_BAR_HEIGHT} - ${TABS_HEIGHT})`,
|
||||
maxHeight: `calc(100vh - ${APP_BAR_HEIGHT} - ${TABS_HEIGHT})`,
|
||||
backgroundColor: "yellow",
|
||||
overflowX: "hidden",
|
||||
overflowY: "auto",
|
||||
scrollbarWidth: "thin",
|
||||
scrollbarColor: "red blue"
|
||||
overflowY: "scroll",
|
||||
scrollbarWidth: "thin"
|
||||
},
|
||||
TECH_OBJ_TABLE: { height: `calc(100vh - ${APP_BAR_HEIGHT} - ${TABS_HEIGHT} - ${TABLE_MORE_HEIGHT})` }
|
||||
TECH_OBJ_TABLE: morePages => ({ height: `calc(100vh - ${APP_BAR_HEIGHT} - ${TABS_HEIGHT} - ${morePages ? TABLE_MORE_HEIGHT : "0px"})` })
|
||||
};
|
||||
|
||||
//Начальное состояние спецификации техничких объектов
|
||||
@ -58,6 +57,9 @@ const ForecastTab = () => {
|
||||
//Собственное состояние - спецификация технических объектов
|
||||
const [techObjSpec, setTechObjSpec] = useState({ ...TECH_OBJ_SPEC_INIT });
|
||||
|
||||
//Собственное состояния - карточка технического объекта
|
||||
const [techObjCardId, setTechObjCardId] = useState(null);
|
||||
|
||||
//Загрузчик веток дерева
|
||||
const { tree } = useEqConfigTree(loadingTreeItem);
|
||||
|
||||
@ -69,12 +71,22 @@ const ForecastTab = () => {
|
||||
techObjSpec.pageNumber
|
||||
);
|
||||
|
||||
//Загрузчик карточки выбоанного технического объекта
|
||||
const { techObjCard, techObjCardIsLoading } = useEqConfigTechObjCard(techObjCardId);
|
||||
|
||||
//Обработка развёртывания/свёртывания уровня дерева
|
||||
const handleTreeItemExpansionToggle = (event, itemId, isExpanded) =>
|
||||
isExpanded && needLoadLevel(tree, itemId) ? setLoadingTreeItem(parseInt(itemId)) : null;
|
||||
|
||||
//Обработка фокусировки на элементе дерева
|
||||
const handleTreeItemFocus = (event, itemId) => setTechObjSpec({ ...TECH_OBJ_SPEC_INIT, parent: parseInt(itemId) });
|
||||
const handleTreeItemFocus = (event, itemId) => {
|
||||
const item = findTreeItem(tree, itemId);
|
||||
if (item && item?.showCard) setTechObjCardId(parseInt(itemId));
|
||||
else {
|
||||
setTechObjCardId(null);
|
||||
setTechObjSpec({ ...TECH_OBJ_SPEC_INIT, parent: parseInt(itemId) });
|
||||
}
|
||||
};
|
||||
|
||||
//При изменении состояния фильтров спецификации технических объектов
|
||||
const handleTechObjSpecFilterChanged = ({ filters }) => setTechObjSpec(pv => ({ ...pv, filters: [...filters], pageNumber: 1 }));
|
||||
@ -95,7 +107,11 @@ const ForecastTab = () => {
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item xs={8} sx={STYLES.RIGHT_SIDE_GRID}>
|
||||
{techObjsDataGrid.init ? (
|
||||
{techObjCardId ? (
|
||||
!techObjCardIsLoading ? (
|
||||
<TechObjCard cardData={techObjCard} />
|
||||
) : null
|
||||
) : techObjsDataGrid.init ? (
|
||||
<P8PDataGrid
|
||||
{...{
|
||||
...P8P_DATA_GRID_CONFIG_PROPS,
|
||||
@ -104,7 +120,7 @@ const ForecastTab = () => {
|
||||
? "Минуточку..."
|
||||
: "Выбранный уровень структуры не содержит данных о технических объектах"
|
||||
}}
|
||||
containerComponentProps={{ sx: STYLES.TECH_OBJ_TABLE, elevation: 0 }}
|
||||
containerComponentProps={{ sx: STYLES.TECH_OBJ_TABLE(techObjsDataGrid.morePages), elevation: 0 }}
|
||||
columnsDef={techObjsDataGrid.columnsDef}
|
||||
rows={techObjsDataGrid.rows}
|
||||
size={P8P_DATA_GRID_SIZE.SMALL}
|
||||
|
@ -146,8 +146,44 @@ const useEqConfigTechObjTable = (parent, filters, orders, pageNumber) => {
|
||||
return { techObjsDataGrid: data, techObjsDataGridIsLoading: isLoading };
|
||||
};
|
||||
|
||||
//Загрузка карточки технического объекта
|
||||
const useEqConfigTechObjCard = id => {
|
||||
//Собственное состояние - флаг загрузки
|
||||
const [isLoading, setLoading] = useState(false);
|
||||
|
||||
//Собственное состояние - данные дерева
|
||||
const [card, setCard] = useState({});
|
||||
|
||||
//Подключение к контексту взаимодействия с сервером
|
||||
const { executeStored } = useContext(BackEndСtx);
|
||||
|
||||
//Загрузка данных при изменении зависимостей
|
||||
useEffect(() => {
|
||||
const loadData = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await executeStored({
|
||||
stored: "UDO_PKG_EQUIPTCF.EQCONFIG_THOBJ_CARD",
|
||||
args: {
|
||||
NEQCONFIG: id
|
||||
},
|
||||
respArg: "COUT",
|
||||
loader: false
|
||||
});
|
||||
setCard(data.techObj ? data.techObj : {});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
if (id) loadData();
|
||||
}, [id, executeStored]);
|
||||
|
||||
//Вернём данные
|
||||
return { techObjCard: card, techObjCardIsLoading: isLoading };
|
||||
};
|
||||
|
||||
//----------------
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export { useEqConfigTree, useEqConfigTechObjTable, needLoadLevel };
|
||||
export { useEqConfigTree, useEqConfigTechObjTable, useEqConfigTechObjCard, findTreeItem, needLoadLevel };
|
||||
|
48
panels/eqs_tech_cond_forecast/forecast_tab_layout.js
Normal file
48
panels/eqs_tech_cond_forecast/forecast_tab_layout.js
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
Парус 8 - Панели мониторинга - ТОиР - Прогнозирование технического состояния
|
||||
Дополнительная разметка и вёрстка клиентских элементов
|
||||
*/
|
||||
|
||||
//---------------------
|
||||
//Подключение библиотек
|
||||
//---------------------
|
||||
|
||||
import React from "react"; //Классы React
|
||||
import { Box, Card, CardContent, Typography, CardActions, Button } from "@mui/material"; //Интерфейсные компоненты
|
||||
|
||||
//-----------
|
||||
//Тело модуля
|
||||
//-----------
|
||||
|
||||
const TechObjCard = ({ cardData }) => {
|
||||
//Генерация содержимого
|
||||
return (
|
||||
<Box p={3}>
|
||||
<Card>
|
||||
<CardContent>
|
||||
<Typography sx={{ fontSize: 14 }} color="text.secondary" gutterBottom>
|
||||
Технологический объект
|
||||
</Typography>
|
||||
<Typography variant="h5" component="div">
|
||||
{cardData.SCODE}
|
||||
</Typography>
|
||||
<Typography sx={{ mb: 1.5 }} color="text.secondary">
|
||||
{cardData.DOPER_DATE}
|
||||
</Typography>
|
||||
<Typography variant="body2">{cardData.SNAME}</Typography>
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
<Button size="large">Прогнозировать</Button>
|
||||
<Button size="large">Ремонтировать</Button>
|
||||
<Button size="large">Обучать</Button>
|
||||
</CardActions>
|
||||
</Card>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
//----------------
|
||||
//Интерфейс модуля
|
||||
//----------------
|
||||
|
||||
export { TechObjCard };
|
Loading…
x
Reference in New Issue
Block a user