diff --git a/db/UDO_PKG_EQUIPDS.pck b/db/UDO_PKG_EQUIPDS.pck
index 0ab68df..073b616 100644
--- a/db/UDO_PKG_EQUIPDS.pck
+++ b/db/UDO_PKG_EQUIPDS.pck
@@ -31,7 +31,7 @@ create or replace package UDO_PKG_EQUIPDS as
procedure CM_LIST
(
NEQUIPDS in number, -- Рег. номер выборки данных
- COUT out clob -- Сериализованная таблица данных
+ COUT out clob -- Сериализованный список
);
/* Клиентское добавление "Выборки данных оборудования (классы оборудования)" */
@@ -102,17 +102,18 @@ create or replace package UDO_PKG_EQUIPDS as
NEQUIPDSCMML in number -- Рег. номер модели класса оборудования выборки данных
);
- /* Код доступного действия с моделью по единице оборудования */
- function CMML_ACT_BY_EQCONFIG
+ /* Состояние моделей по единице оборудования */
+ function CMML_STATUS_BY_EQCONFIG
(
NEQCONFIG in number -- Рег. номер позиции состава оборудования
- ) return number; -- Код действия с моделью (0 - нет доступных, 1 - запросить прогноз, 2 - обучить)
+ ) return number; -- Код действия с моделью (0 - нет моделей, 1 - есть модели в процессе обучения, 2 - есть обученные модели)
/* Список моделей по единице оборудования */
- function CMML_LIST_BY_EQCONFIG
+ procedure CMML_LIST_BY_EQCONFIG
(
- NEQCONFIG in number -- Рег. номер позиции состава оборудования
- ) return varchar2; -- Список моделей с системным разделителем по умолчанию
+ NEQCONFIG in number, -- Рег. номер позиции состава оборудования
+ COUT out clob -- Сериализованная таблица данных
+ );
end UDO_PKG_EQUIPDS;
/
@@ -273,7 +274,7 @@ text="Проверка прав доступа на работу с ""Выбор
procedure CM_LIST
(
NEQUIPDS in number, -- Рег. номер выборки данных
- COUT out clob -- Сериализованная таблица данных
+ COUT out clob -- Сериализованный список
)
is
NCUR integer; -- Курсор документа для результата
@@ -493,7 +494,8 @@ text="Проверка прав доступа на работу с ""Выбор
PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
SNAME => 'STASK',
SCAPTION => 'Задача',
- SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR);
+ SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
+ SHINT => 'Алгоритм прогонозирования модели:
' || UDO_PKG_EQUIPDS_BASE.CMML_TASK_HINT());
PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
SNAME => 'NPRECISION_P',
SCAPTION => 'Точность (план)',
@@ -511,6 +513,10 @@ text="Проверка прав доступа на работу с ""Выбор
SCAPTION => 'Сообщение об ошибке',
SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
BVISIBLE => false);
+ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
+ SNAME => 'SACTIONS',
+ SCAPTION => 'Действия',
+ SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR);
/* Обходим данные */
for C in (select T.RN NRN,
T.TASK STASK,
@@ -529,6 +535,7 @@ text="Проверка прав доступа на работу с ""Выбор
PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NPRECISION_F', NVALUE => C.NPRECISION_F);
PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NSTATUS', NVALUE => C.NSTATUS);
PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SERR', SVALUE => C.SERR);
+ PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SACTIONS');
/* Добавляем строку в таблицу */
PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW);
end loop;
@@ -585,25 +592,128 @@ text="Проверка прав доступа на работу с ""Выбор
end loop;
end CMML_SEND_RQ;
- /* Код доступного действия с моделью по единице оборудования */
- function CMML_ACT_BY_EQCONFIG
+ /* Состояние моделей по единице оборудования */
+ function CMML_STATUS_BY_EQCONFIG
(
- NEQCONFIG in number -- Рег. номер позиции состава оборудования
- ) return number -- Код действия с моделью (0 - нет доступных, 1 - запросить прогноз, 2 - обучить)
+ NEQCONFIG in number -- Рег. номер позиции состава оборудования
+ ) return number -- Код действия с моделью (0 - нет моделей, 1 - есть модели в процессе обучения, 2 - есть обученные модели)
is
+ NRES PKG_STD.TNUMBER; -- Буфер для результата
begin
- return 2;
- end CMML_ACT_BY_EQCONFIG;
+ /* По умолчанию - моделей нет */
+ NRES := 0;
+ /* Обходим модели */
+ for C in (select ML.STATUS
+ from UDO_T_EQUIPDSCM CM,
+ UDO_T_EQUIPDSCMML ML
+ where CM.EQOBJKIND = (select CF.OBJ_KIND from EQCONFIG CF where CF.RN = NEQCONFIG)
+ and CM.RN = ML.PRN)
+ loop
+ /* Модель есть */
+ NRES := 1;
+ /* Если она уже обучена */
+ if (C.STATUS = 2) then
+ NRES := 2;
+ end if;
+ end loop;
+ /* Возвращаем результат */
+ return NRES;
+ end CMML_STATUS_BY_EQCONFIG;
/* Список моделей по единице оборудования */
- function CMML_LIST_BY_EQCONFIG
+ procedure CMML_LIST_BY_EQCONFIG
(
- NEQCONFIG in number -- Рег. номер позиции состава оборудования
- ) return varchar2 -- Список моделей с системным разделителем по умолчанию
+ NEQCONFIG in number, -- Рег. номер позиции состава оборудования
+ COUT out clob -- Сериализованная таблица данных
+ )
is
+ RDG PKG_P8PANELS_VISUAL.TDATA_GRID; -- Описание таблицы
+ RDG_ROW PKG_P8PANELS_VISUAL.TROW; -- Строка таблицы
begin
- return 'TCF;RUL;FP';
- end CMML_LIST_BY_EQCONFIG;
+ /* Инициализируем таблицу данных */
+ RDG := PKG_P8PANELS_VISUAL.TDATA_GRID_MAKE();
+ /* Добавляем в таблицу описание колонок */
+ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
+ SNAME => 'NRN',
+ SCAPTION => 'Рег. номер модели',
+ SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB,
+ BVISIBLE => false);
+ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
+ SNAME => 'NEQUIPDS',
+ SCAPTION => 'Рег. номер выборки',
+ SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB,
+ BVISIBLE => false);
+ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
+ SNAME => 'NEQUIPDSCM',
+ SCAPTION => 'Рег. номер класса оборудования выборки',
+ SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB,
+ BVISIBLE => false);
+ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
+ SNAME => 'SNEQUIPDS',
+ SCAPTION => 'Выборка',
+ SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR);
+ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
+ SNAME => 'STASK',
+ SCAPTION => 'Задача',
+ SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
+ SHINT => 'Алгоритм прогонозирования модели:
' ||
+ UDO_PKG_EQUIPDS_BASE.CMML_TASK_HINT());
+ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
+ SNAME => 'NPRECISION_P',
+ SCAPTION => 'Точность (план)',
+ SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB);
+ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
+ SNAME => 'NPRECISION_F',
+ SCAPTION => 'Точность (факт)',
+ SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB);
+ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
+ SNAME => 'NSTATUS',
+ SCAPTION => 'Состояние',
+ SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB);
+ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
+ SNAME => 'SERR',
+ SCAPTION => 'Сообщение об ошибке',
+ SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
+ BVISIBLE => false);
+ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
+ SNAME => 'SACTIONS',
+ SCAPTION => 'Действия',
+ SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR);
+ /* Обходим данные */
+ for C in (select T.RN NRN,
+ CM.PRN NEQUIPDS,
+ T.PRN NEQUIPDSCM,
+ DS.NAME SNEQUIPDS,
+ T.TASK STASK,
+ T.PRECISION_P NPRECISION_P,
+ T.PRECISION_F NPRECISION_F,
+ T.STATUS NSTATUS,
+ T.ERR SERR
+ from UDO_T_EQUIPDSCMML T,
+ UDO_T_EQUIPDSCM CM,
+ UDO_T_EQUIPDS DS
+ where T.PRN = CM.RN
+ and CM.PRN = DS.RN
+ and CM.EQOBJKIND = (select CF.OBJ_KIND from EQCONFIG CF where CF.RN = NEQCONFIG)
+ order by T.RN)
+ loop
+ /* Добавляем колонки с данными */
+ PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NRN', NVALUE => C.NRN, BCLEAR => true);
+ PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NEQUIPDS', NVALUE => C.NEQUIPDS);
+ PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NEQUIPDSCM', NVALUE => C.NEQUIPDSCM);
+ PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SNEQUIPDS', SVALUE => C.SNEQUIPDS);
+ PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'STASK', SVALUE => C.STASK);
+ PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NPRECISION_P', NVALUE => C.NPRECISION_P);
+ PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NPRECISION_F', NVALUE => C.NPRECISION_F);
+ PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'NSTATUS', NVALUE => C.NSTATUS);
+ PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SERR', SVALUE => C.SERR);
+ PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SACTIONS');
+ /* Добавляем строку в таблицу */
+ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW);
+ end loop;
+ /* Сериализуем описание */
+ COUT := PKG_P8PANELS_VISUAL.TDATA_GRID_TO_XML(RDATA_GRID => RDG, NINCLUDE_DEF => 1);
+ end CMML_LIST_BY_EQCONFIG;
end UDO_PKG_EQUIPDS;
/
diff --git a/db/UDO_PKG_EQUIPDS_BASE.pck b/db/UDO_PKG_EQUIPDS_BASE.pck
index 4b2f34c..e916612 100644
--- a/db/UDO_PKG_EQUIPDS_BASE.pck
+++ b/db/UDO_PKG_EQUIPDS_BASE.pck
@@ -142,6 +142,10 @@ create or replace package UDO_PKG_EQUIPDS_BASE as
SQUEUE_ID in varchar2, -- Идентификатор очереди обработки
SERR in varchar2 -- Сообщение об ошибке
);
+
+ /* Формирование подсказки для задачи "Выборки данных оборудования (классы оборудования, модели)" */
+ function CMML_TASK_HINT
+ return varchar2; -- Подсказка для задачи
end UDO_PKG_EQUIPDS_BASE;
/
@@ -455,6 +459,14 @@ create or replace package body UDO_PKG_EQUIPDS_BASE as
T.ERR = SERR
where T.RN = NRN;
end CMML_SET_STATUS;
+
+ /* Формирование подсказки для задачи "Выборки данных оборудования (классы оборудования, модели)" */
+ function CMML_TASK_HINT
+ return varchar2 -- Подсказка для задачи
+ is
+ begin
+ return 'TCF - Оценка технического состояния (Technical Condition Forecast)
' || 'RUL - Прогнозирование остаточного ресурса (Remaining Useful Life)
' || 'FP - Прогнозирование отказа (Failure Predict)';
+ end CMML_TASK_HINT;
end UDO_PKG_EQUIPDS_BASE;
/
diff --git a/db/UDO_PKG_EQUIPTCF.pck b/db/UDO_PKG_EQUIPTCF.pck
index f572a26..421bedc 100644
--- a/db/UDO_PKG_EQUIPTCF.pck
+++ b/db/UDO_PKG_EQUIPTCF.pck
@@ -166,13 +166,12 @@ text="Проверка прав доступа при формировании
PKG_COND_BROKER.ADD_CONDITION_CODE(SCOLUMN_NAME => 'NAME',
SCONDITION_NAME => 'SOBJ_KINDFrom',
SJOINS => 'OBJ_KIND <- RN;EQOBJKIND');
- /* Модели прогнозирования */
- if (PKG_COND_BROKER.CONDITION_EXISTS(SCONDITION_NAME => 'SEQUIPDSCMMLFrom') = 1) then
- PKG_COND_BROKER.ADD_CLAUSE(SCLAUSE => 'UPPER(' ||
- PKG_SQL_BUILD.PKG_NAME(SNAME => 'UDO_PKG_EQUIPDS.CMML_LIST_BY_EQCONFIG') ||
- '(RN)) like REPLACE(REPLACE(UPPER(:SEQUIPDSCMML), ''?'', ''_''), ''*'', ''%'')');
- PKG_COND_BROKER.BIND_VARIABLE(SVARIABLE_NAME => 'SEQUIPDSCMML',
- SVALUE => PKG_COND_BROKER.GET_CONDITION_STR(SCONDITION_NAME => 'SEQUIPDSCMMLFrom'));
+ /* Действия с моделями прогнозирования */
+ if (PKG_COND_BROKER.CONDITION_EXISTS(SCONDITION_NAME => 'NCMML_STATUSFrom') = 1) then
+ PKG_COND_BROKER.ADD_CLAUSE(SCLAUSE => PKG_SQL_BUILD.PKG_NAME(SNAME => 'UDO_PKG_EQUIPDS.CMML_STATUS_BY_EQCONFIG') ||
+ '(RN) = :NCMML_STATUS');
+ PKG_COND_BROKER.BIND_VARIABLE(SVARIABLE_NAME => 'NCMML_STATUS',
+ SVALUE => PKG_COND_BROKER.GET_CONDITION_NUM(SCONDITION_NAME => 'NCMML_STATUSFrom'));
end if;
end EQCONFIG_THOBJ_LIST_COND;
@@ -194,6 +193,7 @@ text="Проверка прав доступа при формировании
RO PKG_P8PANELS_VISUAL.TORDERS; -- Сортировки
RDG PKG_P8PANELS_VISUAL.TDATA_GRID; -- Описание таблицы
RDG_ROW PKG_P8PANELS_VISUAL.TROW; -- Строка таблицы
+ RCOL_VALS PKG_P8PANELS_VISUAL.TCOL_VALS; -- Предопределённые значения столбцов
NROW_FROM PKG_STD.TREF; -- Номер строки с
NROW_TO PKG_STD.TREF; -- Номер строки по
CSQL clob; -- Буфер для запроса
@@ -251,21 +251,16 @@ text="Проверка прав доступа при формировании
SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
BORDER => true,
BFILTER => true);
+ PKG_P8PANELS_VISUAL.TCOL_VALS_ADD(RCOL_VALS => RCOL_VALS, NVALUE => 0, BCLEAR => true);
+ PKG_P8PANELS_VISUAL.TCOL_VALS_ADD(RCOL_VALS => RCOL_VALS, NVALUE => 1);
+ PKG_P8PANELS_VISUAL.TCOL_VALS_ADD(RCOL_VALS => RCOL_VALS, NVALUE => 2);
PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
- SNAME => 'SEQUIPDSCMML',
- SCAPTION => 'Модели прогнозирования',
- SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR,
- SHINT => 'Модели прогнозирования - доступные для использования модели прогнозирования и задачи, ими решаемые:
' ||
- 'TCF - Оценка технического состояния (Technical Condition Forecast)
' ||
- 'RUL - Прогнозирование остаточного ресурса (Remaining Useful Life)
' ||
- 'FP - Прогнозирование отказа (Failure Predict)',
- BORDER => true,
- BFILTER => true);
- PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
- SNAME => 'NEQUIPDSCMML_ACTION',
- SCAPTION => 'Действия с моделью',
+ SNAME => 'NCMML_STATUS',
+ SCAPTION => 'Модель',
SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_NUMB,
- BVISIBLE => false);
+ BORDER => true,
+ BFILTER => true,
+ RCOL_VALS => RCOL_VALS);
/* Обходим данные */
begin
/* Добавляем подсказку совместимости */
@@ -281,8 +276,7 @@ text="Проверка прав доступа при формировании
PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' ST.CODE SUSE_KIND,');
PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' C.OBJ_KIND NOBJ_KIND,');
PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' OK.NAME SOBJ_KIND,');
- 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 => PKG_SQL_BUILD.PKG_NAME(SNAME => 'UDO_PKG_EQUIPDS.CMML_STATUS_BY_EQCONFIG') || '(C.RN) NCMML_STATUS');
PKG_SQL_BUILD.APPEND(SSQL => CSQL, SELEMENT1 => ' from EQCONFIG C');
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');
@@ -315,9 +309,8 @@ text="Проверка прав доступа при формировании
PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR, IPOSITION => 5);
PKG_SQL_DML.DEFINE_COLUMN_NUM(ICURSOR => ICURSOR, IPOSITION => 6);
PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR, IPOSITION => 7);
- PKG_SQL_DML.DEFINE_COLUMN_STR(ICURSOR => ICURSOR, IPOSITION => 8);
+ PKG_SQL_DML.DEFINE_COLUMN_NUM(ICURSOR => ICURSOR, IPOSITION => 8);
PKG_SQL_DML.DEFINE_COLUMN_NUM(ICURSOR => ICURSOR, IPOSITION => 9);
- PKG_SQL_DML.DEFINE_COLUMN_NUM(ICURSOR => ICURSOR, IPOSITION => 10);
/* Делаем выборку */
if (PKG_SQL_DML.EXECUTE(ICURSOR => ICURSOR) = 0) then
null;
@@ -349,14 +342,10 @@ text="Проверка прав доступа при формировании
SNAME => 'SOBJ_KIND',
ICURSOR => ICURSOR,
NPOSITION => 7);
- PKG_P8PANELS_VISUAL.TROW_ADD_CUR_COLS(RROW => RDG_ROW,
- SNAME => 'SEQUIPDSCMML',
+ PKG_P8PANELS_VISUAL.TROW_ADD_CUR_COLN(RROW => RDG_ROW,
+ SNAME => 'NCMML_STATUS',
ICURSOR => ICURSOR,
NPOSITION => 8);
- PKG_P8PANELS_VISUAL.TROW_ADD_CUR_COLN(RROW => RDG_ROW,
- SNAME => 'NEQUIPDSCMML_ACTION',
- ICURSOR => ICURSOR,
- NPOSITION => 9);
/* Добавляем строку в таблицу */
PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_ROW(RDATA_GRID => RDG, RROW => RDG_ROW);
end loop;
@@ -388,9 +377,12 @@ text="Проверка прав доступа при формировании
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)
+ T.OPER_DATE DOPER_DATE,
+ OK.NAME SEQOBJKIND
+ from EQCONFIG T,
+ EQOBJKIND OK
+ where T.RN = NEQCONFIG
+ and T.OBJ_KIND = OK.RN)
loop
/* Соберем карточку */
XCARD := PKG_XMAKE.ELEMENT(ICURSOR => NCUR,
@@ -407,7 +399,10 @@ text="Проверка прав доступа при формировании
SVALUE => C.SNAME),
RATTRIBUTE03 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
SNAME => 'DOPER_DATE',
- DVALUE => C.DOPER_DATE)));
+ DVALUE => C.DOPER_DATE),
+ RATTRIBUTE04 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
+ SNAME => 'SEQOBJKIND',
+ SVALUE => C.SEQOBJKIND)));
end loop;
/* Формируем XML-представление документа ответа */
XDOC := PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'XDATA', RNODE00 => XCARD);
diff --git a/panels/eqs_tech_cond_forecast/admin_tab.js b/panels/eqs_tech_cond_forecast/admin_tab.js
index 0643458..377d3ea 100644
--- a/panels/eqs_tech_cond_forecast/admin_tab.js
+++ b/panels/eqs_tech_cond_forecast/admin_tab.js
@@ -8,6 +8,7 @@
//---------------------
import React, { useState, useEffect, useContext } from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
import { Box, Grid, Stack, Icon, Button, IconButton } from "@mui/material"; //Интерфейсные компоненты
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с серверомs
@@ -16,7 +17,8 @@ import {
EquipDataSelectionList,
EquipDataSelectionClassMachineIU,
EquipDataSelectionClassMachineList,
- EquipDataSelectionClassMachineCard
+ EquipDataSelectionClassMachineCard,
+ EquipDataSelectionClassMachineModelIU
} from "./admin_tab_layout"; //Вспомогательные компоненты и вёрстка
import {
DS_RN_DEFAULT,
@@ -37,7 +39,8 @@ const REFRESH_INITIAL = {
dataSelection: null,
dataSelectionClassMachine: null,
dataSelectionClassMachineCard: 0,
- dataSelectionClassMachineFilesList: 0
+ dataSelectionClassMachineFilesList: 0,
+ dataSelectionClassMachineModelsList: 0
};
//Стили
@@ -51,7 +54,7 @@ const STYLES = {
//-----------
//Закладка администрирования
-const AdminTab = () => {
+const AdminTab = ({ dataSelection = DS_RN_DEFAULT, dataSelectionClassMachine = null }) => {
//Подключение к контексту взаимодействия с сервером
const { executeStored } = useContext(BackEndСtx);
@@ -59,16 +62,16 @@ const AdminTab = () => {
const { pOnlineUserProcedure } = useContext(ApplicationСtx);
//Собственное состояние - отображаемые диалоги
- const [dialogs, setDialogs] = useState({ dataSelectionIU: false, dataSelectionClassMachineIU: false });
+ const [dialogs, setDialogs] = useState({ dataSelectionIU: false, dataSelectionClassMachineIU: false, dataSelectionClassMachineModelIU: false });
//Собственное состояние - флаги обновления данных
const [refresh, setRefresh] = useState(REFRESH_INITIAL);
//Собственное состояние - выбранная выборка данных
- const [equipDataSelection, setDataSelection] = useState(DS_RN_DEFAULT);
+ const [equipDataSelection, setDataSelection] = useState(dataSelection);
//Собственное состояние - выбранный класс оборудования
- const [equipDataSelectionClassMachine, setDataSelectionClassMachine] = useState(null);
+ const [equipDataSelectionClassMachine, setDataSelectionClassMachine] = useState(dataSelectionClassMachine);
//Загрузка списка выборок данных
const { equipDataSelectionList } = useEquipDataSelectionList(refresh.dataSelection);
@@ -88,8 +91,11 @@ const AdminTab = () => {
refresh.dataSelectionClassMachineFilesList
);
- //Загрузка файлов класса оборудования
- const { equipDataSelectionClassMachineModelsList } = useEquipDataSelectionClassMachineModelsList(equipDataSelectionClassMachine);
+ //Загрузка моделей класса оборудования
+ const { equipDataSelectionClassMachineModelsList } = useEquipDataSelectionClassMachineModelsList(
+ equipDataSelectionClassMachine,
+ refresh.dataSelectionClassMachineModelsList
+ );
//При смене выборки данных
const handleDataSelectionChange = value => {
@@ -166,37 +172,71 @@ const AdminTab = () => {
//При нажатии "Загрузить на сервер" в списке файлов карточки класса оборудования
const handleUploadEquipDataSelectionClassMachineFiles = async equipDSCM => {
- await executeStored({
- stored: "UDO_PKG_EQUIPDS.CMFL_UPLOAD",
- args: {
- NEQUIPDSCM: equipDSCM
- }
- });
+ await executeStored({ stored: "UDO_PKG_EQUIPDS.CMFL_UPLOAD", args: { NEQUIPDSCM: equipDSCM } });
setRefresh(pv => ({ ...pv, dataSelectionClassMachineFilesList: pv.dataSelectionClassMachineFilesList + 1 }));
};
//При нажатии "Передать внешней системе" в списке файлов карточки класса оборудования
const handleSendMdEquipDataSelectionClassMachineFiles = async equipDSCM => {
- await executeStored({
- stored: "UDO_PKG_EQUIPDS.CMFL_SEND_MD",
- args: {
- NEQUIPDSCM: equipDSCM
- }
- });
+ await executeStored({ stored: "UDO_PKG_EQUIPDS.CMFL_SEND_MD", args: { NEQUIPDSCM: equipDSCM } });
setRefresh(pv => ({ ...pv, dataSelectionClassMachineFilesList: pv.dataSelectionClassMachineFilesList + 1 }));
};
+ //При нажатии на "Добавить модель класса оборудования"
+ const handleAddEquipDataSelectionClassMachineModel = () => setDialogs(pv => ({ ...pv, dataSelectionClassMachineModelIU: true }));
+
+ //При нажатии на "Удалить модель класса оборудования"
+ const handleDeleteEquipDataSelectionClassMachineModel = async equipDSCMML => {
+ await executeStored({ stored: "UDO_PKG_EQUIPDS.CMML_DEL", args: { NRN: equipDSCMML } });
+ setRefresh(pv => ({ ...pv, dataSelectionClassMachineModelsList: pv.dataSelectionClassMachineModelsList + 1 }));
+ };
+
+ //При отмене диалога IU модели класса оборудования
+ const handleEquipDataSelectionClassMachineModelIUCancel = () => setDialogs(pv => ({ ...pv, dataSelectionClassMachineModelIU: false }));
+
+ //При сохранении диалога IU модели класса оборудования
+ const handleEquipDataSelectionClassMachineModelIUOk = async values => {
+ await executeStored({
+ stored: "UDO_PKG_EQUIPDS.CMML_INS",
+ args: {
+ NPRN: equipDataSelectionClassMachine,
+ STASK: values.task,
+ NPRECISION_P: parseInt(values.precisionP)
+ }
+ });
+ setDialogs(pv => ({ ...pv, dataSelectionClassMachineModelIU: false }));
+ setRefresh(pv => ({ ...pv, dataSelectionClassMachineModelsList: pv.dataSelectionClassMachineModelsList + 1 }));
+ };
+
+ //При нажатии "Обучить" в списке моделей карточки класса оборудования
+ const handleSendRqEquipDataSelectionClassMachineModel = async equipDSCMML => {
+ await executeStored({ stored: "UDO_PKG_EQUIPDS.CMML_SEND_RQ", args: { NEQUIPDSCMML: equipDSCMML } });
+ setRefresh(pv => ({ ...pv, dataSelectionClassMachineModelsList: pv.dataSelectionClassMachineModelsList + 1 }));
+ };
+
+ //При измении выборки данных через свойства
+ useEffect(() => {
+ setDataSelection(dataSelection);
+ }, [dataSelection]);
+
+ //При изменеии класса оборудования через свойства
+ useEffect(() => {
+ setDataSelectionClassMachine(dataSelectionClassMachine);
+ }, [dataSelectionClassMachine]);
+
//При изменении списка выборок данных
useEffect(() => {
if (refresh.action == "INS" && refresh.dataSelection) {
setDataSelection(refresh.dataSelection);
setDataSelectionClassMachine(null);
}
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [equipDataSelectionList]);
//При изменении списка классов оборудования выборки данных
useEffect(() => {
if (refresh.action == "INS" && refresh.dataSelectionClassMachine) setDataSelectionClassMachine(refresh.dataSelectionClassMachine);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [equipDataSelectionClassMachineList]);
//Генерация содержимого
@@ -211,6 +251,12 @@ const AdminTab = () => {
onCancel={handleEquipDataSelectionClassMachineIUCancel}
/>
) : null}
+ {dialogs.dataSelectionClassMachineModelIU ? (
+
+ ) : null}
@@ -251,6 +297,9 @@ const AdminTab = () => {
onClassMachineFilesMake={handleMakeEquipDataSelectionClassMachineFiles}
onClassMachineFilesUpload={handleUploadEquipDataSelectionClassMachineFiles}
onClassMachineFilesSendMd={handleSendMdEquipDataSelectionClassMachineFiles}
+ onClassMachineModelAdd={handleAddEquipDataSelectionClassMachineModel}
+ onClassMachineModelDelete={handleDeleteEquipDataSelectionClassMachineModel}
+ onClassMachineModelSendRq={handleSendRqEquipDataSelectionClassMachineModel}
/>
@@ -260,6 +309,12 @@ const AdminTab = () => {
);
};
+//Контроль свойств - Закладка администрирования
+AdminTab.propTypes = {
+ dataSelection: PropTypes.number,
+ dataSelectionClassMachine: PropTypes.number
+};
+
//----------------
//Интерфейс модуля
//----------------
diff --git a/panels/eqs_tech_cond_forecast/admin_tab_hooks.js b/panels/eqs_tech_cond_forecast/admin_tab_hooks.js
index ccd144e..0a1a606 100644
--- a/panels/eqs_tech_cond_forecast/admin_tab_hooks.js
+++ b/panels/eqs_tech_cond_forecast/admin_tab_hooks.js
@@ -176,7 +176,7 @@ const useEquipDataSelectionClassMachineFilesList = (classMachine, refresh) => {
};
//Загрузка списка моделей класса оборудования
-const useEquipDataSelectionClassMachineModelsList = classMachine => {
+const useEquipDataSelectionClassMachineModelsList = (classMachine, refresh) => {
//Собственное состояние - флаг загрузки
const [isLoading, setLoading] = useState(false);
@@ -212,7 +212,7 @@ const useEquipDataSelectionClassMachineModelsList = classMachine => {
}
};
if (classMachine) loadData();
- }, [classMachine, executeStored]);
+ }, [classMachine, refresh, executeStored]);
//Вернём данные
return { equipDataSelectionClassMachineModelsList: data, equipDataSelectionClassMachineModelsListIsLoading: isLoading };
diff --git a/panels/eqs_tech_cond_forecast/admin_tab_layout.js b/panels/eqs_tech_cond_forecast/admin_tab_layout.js
index 49dbec4..d4557d5 100644
--- a/panels/eqs_tech_cond_forecast/admin_tab_layout.js
+++ b/panels/eqs_tech_cond_forecast/admin_tab_layout.js
@@ -36,9 +36,10 @@ import {
import { useTheme } from "@mui/material/styles"; //Темы оформления
import { ApplicationСtx } from "../../context/application"; //Контекст приложения
import { BUTTONS } from "../../../app.text"; //Текстовые ресурсы и константы
-import { APP_BAR_HEIGHT, TABS_HEIGHT, SCROLL_STYLES } from "./eqs_tech_cond_forecast_lyaout"; //Общие вспомогательные компоненты и вёрстка
+import { APP_BAR_HEIGHT, TABS_HEIGHT, SCROLL_STYLES, formatModelStateValue } from "./eqs_tech_cond_forecast_lyaout"; //Общие вспомогательные компоненты и вёрстка
import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../components/p8p_data_grid"; //Таблица данных
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
+import { DS_RN_DEFAULT } from "./admin_tab_hooks"; //Вспомогательные хуки
//---------
//Константы
@@ -104,7 +105,7 @@ const STYLES = {
//------------------------------------
//Поле ввода из словаря
-const IUDFormTextField = ({ elementCode, elementValue, labelText, onChange, dictionary, ...other }) => {
+const IUDFormTextField = ({ elementCode, elementValue, labelText, onChange, dictionary, list, ...other }) => {
//Значение элемента
const [value, setValue] = useState(elementValue);
@@ -119,6 +120,7 @@ const IUDFormTextField = ({ elementCode, elementValue, labelText, onChange, dict
//Изменение значения элемента
const handleChange = e => {
+ console.log(e.target.name, e.target.value);
setValue(e.target.value);
if (onChange) onChange(e.target.name, e.target.value);
};
@@ -127,22 +129,45 @@ const IUDFormTextField = ({ elementCode, elementValue, labelText, onChange, dict
return (
- {labelText}
-
-
- list
-
-
- ) : null
- }
- onChange={handleChange}
- />
+ {list ? (
+ <>
+ {labelText}
+
+ >
+ ) : (
+ <>
+ {labelText}
+
+
+ list
+
+
+ ) : null
+ }
+ onChange={handleChange}
+ />
+ >
+ )}
);
@@ -154,7 +179,8 @@ IUDFormTextField.propTypes = {
elementValue: PropTypes.string,
labelText: PropTypes.string.isRequired,
onChange: PropTypes.func,
- dictionary: PropTypes.func
+ dictionary: PropTypes.func,
+ list: PropTypes.array
};
//Кнопка с дополнительной подписью
@@ -165,7 +191,9 @@ const ExtraCaptionButton = ({ caption, title, subtitle, maxWidth, onClick, theme
//Генерация содержимого
return (
-
+
{title} {subtitle}
@@ -218,6 +246,37 @@ const filesListDataCellRender = ({ row, columnDef, theme }) => {
}
};
+//Форматирование колонок таблицы моделей класса оборудования выборки данных
+const modelsListDataCellRender = ({ row, columnDef, theme, card, onDelete, onSendRq }) => {
+ switch (columnDef.name) {
+ case "NSTATUS":
+ return {
+ cellProps: { align: "left" },
+ data: formatModelStateValue(theme, row.NSTATUS, row.SERR)
+ };
+ case "SACTIONS":
+ return {
+ data: (
+
+ (onDelete ? onDelete(row.NRN) : null)}>
+ delete
+
+ {row.NSTATUS == 0 ? (
+ (onSendRq ? onSendRq(row.NRN) : null)}
+ theme={theme}
+ />
+ ) : null}
+
+ )
+ };
+ }
+};
+
//Форматирование ячеек заголовка таблиц файлов и моделей класса оборудования выборки данных
const classMachineCardTableHeadCellRender = ({ columnDef }) => {
switch (columnDef.name) {
@@ -226,6 +285,8 @@ const classMachineCardTableHeadCellRender = ({ columnDef }) => {
stackProps: { justifyContent: "left" },
cellProps: { align: "left" }
};
+ case "SACTIONS":
+ return { data: " " };
}
};
@@ -401,6 +462,50 @@ EquipDataSelectionClassMachineIU.propTypes = {
onCancel: PropTypes.func
};
+//Диалог IU модели класса оборудования выборки данных
+const EquipDataSelectionClassMachineModelIU = ({ onOk, onCancel }) => {
+ //Собственное состояние - значения формы
+ const [values, setValues] = useState({
+ task: "RUL",
+ precisionP: ""
+ });
+
+ //Отработка воода значения в форму
+ const handleValueChanged = (name, value) => setValues(pv => ({ ...pv, [name]: value }));
+
+ //Генерация содержимого
+ return (
+
+ );
+};
+
+//Контроль свойств - Диалог IU модели класса оборудования выборки данных
+EquipDataSelectionClassMachineModelIU.propTypes = {
+ onOk: PropTypes.func,
+ onCancel: PropTypes.func
+};
+
//Список выборок данных оборудования
const EquipDataSelectionList = ({ list, value, onChange }) => {
//При выборе элемента
@@ -410,7 +515,14 @@ const EquipDataSelectionList = ({ list, value, onChange }) => {
return (
Выборка данных оборудования
-
Модели
+
+ add
+
+ modelsListDataCellRender({
+ ...prms,
+ theme,
+ card,
+ onDelete: handleClassMachineModelDeleteClick,
+ onSendRq: handleClassMachineModelSendRqClick
+ })
+ }
/>
@@ -577,7 +707,10 @@ EquipDataSelectionClassMachineCard.propTypes = {
onCardDelete: PropTypes.func,
onClassMachineFilesMake: PropTypes.func,
onClassMachineFilesUpload: PropTypes.func,
- onClassMachineFilesSendMd: PropTypes.func
+ onClassMachineFilesSendMd: PropTypes.func,
+ onClassMachineModelAdd: PropTypes.func,
+ onClassMachineModelDelete: PropTypes.func,
+ onClassMachineModelSendRq: PropTypes.func
};
//----------------
@@ -587,6 +720,7 @@ EquipDataSelectionClassMachineCard.propTypes = {
export {
EquipDataSelectionIU,
EquipDataSelectionClassMachineIU,
+ EquipDataSelectionClassMachineModelIU,
EquipDataSelectionList,
EquipDataSelectionClassMachineList,
EquipDataSelectionClassMachineCard
diff --git a/panels/eqs_tech_cond_forecast/eqs_tech_cond_forecast.js b/panels/eqs_tech_cond_forecast/eqs_tech_cond_forecast.js
index 899446c..a27ce88 100644
--- a/panels/eqs_tech_cond_forecast/eqs_tech_cond_forecast.js
+++ b/panels/eqs_tech_cond_forecast/eqs_tech_cond_forecast.js
@@ -17,6 +17,13 @@ import { ForecastTab } from "./forecast_tab"; //Интерфейс прогно
//Константы
//---------
+//Состояние по умолчанию
+const STATE_INITIAL = {
+ mode: MODES.FORECAST,
+ dataSelection: -1,
+ dataSelectionClassMachine: null
+};
+
//Стили
const STYLES = {
TABS_CONTAINER_BOX: { borderBottom: 1, borderColor: "divider" }
@@ -29,25 +36,34 @@ const STYLES = {
//Корневая панель прогнозирования технического состояния
const EqsTechCondForecast = () => {
//Собственное состояние
- const [mode, setMode] = useState(MODES.ADMIN);
+ const [state, setState] = useState(STATE_INITIAL);
//При переключении закладки
- const handleTabChange = (e, newValue) => setMode(newValue);
+ const handleTabChange = (e, newValue) => setState(pv => ({ ...pv, mode: newValue }));
+
+ //При запросе перехода на закладку администрирования
+ const handleGoToAdmin = (dataSelection, dataSelectionClassMachine) =>
+ setState(pv => ({
+ ...pv,
+ mode: MODES.ADMIN,
+ dataSelection: dataSelection ? dataSelection : STATE_INITIAL.dataSelection,
+ dataSelectionClassMachine: dataSelectionClassMachine ? dataSelectionClassMachine : STATE_INITIAL.dataSelectionClassMachine
+ }));
//Генерация содержимого
return (
<>
-
+
-
-
+
+
-
-
+
+
>
);
diff --git a/panels/eqs_tech_cond_forecast/eqs_tech_cond_forecast_lyaout.js b/panels/eqs_tech_cond_forecast/eqs_tech_cond_forecast_lyaout.js
index ead138e..45b9516 100644
--- a/panels/eqs_tech_cond_forecast/eqs_tech_cond_forecast_lyaout.js
+++ b/panels/eqs_tech_cond_forecast/eqs_tech_cond_forecast_lyaout.js
@@ -9,7 +9,7 @@
import React from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
-import { Box } from "@mui/material"; //Интерфейсные компоненты
+import { Box, Stack, Icon } from "@mui/material"; //Интерфейсные компоненты
//---------
//Константы
@@ -56,6 +56,24 @@ const SCROLL_STYLES = {
//Тело модуля
//-----------
+//Формирование значения для колонки "Состояние" модели класса оборудования выборки данных
+const formatModelStateValue = (theme, value, err) => {
+ const [text, icon, color] =
+ value == 0
+ ? ["Зарегистрирована", "app_registration", null]
+ : value == 1
+ ? ["Обрабатывается внешней системой", "manage_history", theme.palette.warning.main]
+ : value == 2
+ ? ["Успешно обработана внешней системой", "check_circle", theme.palette.primary.main]
+ : [`Ошибка обработки внешней системой: ${err}`, "error", theme.palette.error.main];
+ return (
+
+ {icon}
+ {text}
+
+ );
+};
+
//Закладка
const TabPanel = ({ mode, value, children }) => {children};
@@ -70,4 +88,4 @@ TabPanel.propTypes = {
//Интерфейс модуля
//----------------
-export { MODES, APP_BAR_HEIGHT, TABS_HEIGHT, TABLE_MORE_HEIGHT, TABLE_FILTERS_HEIGHT, SCROLL_STYLES, TabPanel };
+export { MODES, APP_BAR_HEIGHT, TABS_HEIGHT, TABLE_MORE_HEIGHT, TABLE_FILTERS_HEIGHT, SCROLL_STYLES, formatModelStateValue, TabPanel };
diff --git a/panels/eqs_tech_cond_forecast/forecast_tab.js b/panels/eqs_tech_cond_forecast/forecast_tab.js
index b1e5711..e45aa2e 100644
--- a/panels/eqs_tech_cond_forecast/forecast_tab.js
+++ b/panels/eqs_tech_cond_forecast/forecast_tab.js
@@ -8,14 +8,23 @@
//---------------------
import React, { useState, useContext } from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
import { Box, Grid } from "@mui/material"; //Интерфейсные компоненты
import { RichTreeView } from "@mui/x-tree-view/RichTreeView"; //Дерево
+import { useTreeViewApiRef } from "@mui/x-tree-view/hooks/useTreeViewApiRef"; //API дерева
import { MessagingСtx } from "../../context/messaging"; //Контекст сообщений
import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../components/p8p_data_grid"; //Таблица данных
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { APP_BAR_HEIGHT, TABS_HEIGHT, TABLE_FILTERS_HEIGHT, TABLE_MORE_HEIGHT, SCROLL_STYLES } from "./eqs_tech_cond_forecast_lyaout"; //Общие Вспомогательные компоненты и вёрстка
-import { TechObjCard, eqConfigTechObjTableValueFormatter } from "./forecast_tab_layout"; //Вспомогательные компоненты и вёрстка
-import { useEqConfigTree, useEqConfigTechObjTable, useEqConfigTechObjCard, findTreeItem, needLoadLevel } from "./forecast_tab_hooks"; //Вспомогательные хуки
+import { TechObjCard, eqConfigTechObjTableValueFormatter, eqConfigTechObjTableDataCellRender } from "./forecast_tab_layout"; //Вспомогательные компоненты и вёрстка
+import {
+ useEqConfigTree,
+ useEqConfigTechObjTable,
+ useEqConfigTechObjCard,
+ useTechObjModelsList,
+ findTreeItem,
+ needLoadLevel
+} from "./forecast_tab_hooks"; //Вспомогательные хуки
//---------
//Константы
@@ -49,10 +58,13 @@ const TECH_OBJ_SPEC_INIT = { parent: null, filters: [], orders: [], pageNumber:
//-----------
//Закладка прогнозирования
-const ForecastTab = () => {
+const ForecastTab = ({ onGoToAdmin }) => {
//Подключение к контексту сообщений
const { InlineMsgInfo } = useContext(MessagingСtx);
+ //Подключение к API дерева
+ const apiRef = useTreeViewApiRef();
+
//Собственное состояние - текущая загружаемая ветка
const [loadingTreeItem, setLoadingTreeItem] = useState(0);
@@ -73,9 +85,12 @@ const ForecastTab = () => {
techObjSpec.pageNumber
);
- //Загрузчик карточки выбоанного технического объекта
+ //Загрузчик карточки выбранного технического объекта
const { techObjCard, techObjCardIsLoading } = useEqConfigTechObjCard(techObjCardId);
+ //Загрузчик моделей выбранного технического объекта
+ const { techObjModelsList, techObjModelsListIsLoading } = useTechObjModelsList(techObjCardId);
+
//Обработка развёртывания/свёртывания уровня дерева
const handleTreeItemExpansionToggle = (event, itemId, isExpanded) =>
isExpanded && needLoadLevel(eQconfigTree, itemId) ? setLoadingTreeItem(parseInt(itemId)) : null;
@@ -99,6 +114,23 @@ const ForecastTab = () => {
//При изменении количества отображаемых страниц спецификации технических объектов
const handleTechObjSpecPagesCountChanged = () => setTechObjSpec(pv => ({ ...pv, pageNumber: pv.pageNumber + 1 }));
+ //При выполнении действия в колоке "Модели" таблицы технических объектов
+ const handleCMMLStatusClick = (event, row) => {
+ if (row.NCMML_STATUS == 0) {
+ if (onGoToAdmin) onGoToAdmin();
+ } else {
+ const item = findTreeItem(eQconfigTree, row.NRN);
+ if (item && item?.showCard) apiRef.current?.focusItem(event, item.id);
+ else setTechObjCardId(parseInt(row.NRN));
+ }
+ };
+
+ //При переходе к закладке администрирования из карточки технического объекта
+ const handleTechObjeCardGoToModel = model => (onGoToAdmin ? onGoToAdmin(model.NEQUIPDS, model.NEQUIPDSCM) : null);
+
+ //При закрытии карточки технического объекта
+ const handleTechObjeCardClose = () => setTechObjCardId(null);
+
//Текст при отсутствии данных в списке технических объектов
const noDataFoundText =
techObjsDataGridIsLoading || !techObjsDataGrid.init
@@ -113,13 +145,23 @@ const ForecastTab = () => {
-
+
{techObjCardId ? (
- !techObjCardIsLoading ? (
-
+ !techObjCardIsLoading && !techObjModelsListIsLoading ? (
+
) : null
) : techObjsDataGrid.init ? (
{
fixedHeader={true}
reloading={false}
valueFormatter={eqConfigTechObjTableValueFormatter}
+ dataCellRender={prms => eqConfigTechObjTableDataCellRender({ ...prms, onCMMLStatus: handleCMMLStatusClick })}
onFilterChanged={handleTechObjSpecFilterChanged}
onOrderChanged={handleTechObjSpecOrderChanged}
onPagesCountChanged={handleTechObjSpecPagesCountChanged}
@@ -149,6 +192,11 @@ const ForecastTab = () => {
);
};
+//Контроль свойств - Закладка прогнозирования
+ForecastTab.propTypes = {
+ onGoToAdmin: PropTypes.func
+};
+
//----------------
//Интерфейс модуля
//----------------
diff --git a/panels/eqs_tech_cond_forecast/forecast_tab_hooks.js b/panels/eqs_tech_cond_forecast/forecast_tab_hooks.js
index c4d43fa..3cb34c1 100644
--- a/panels/eqs_tech_cond_forecast/forecast_tab_hooks.js
+++ b/panels/eqs_tech_cond_forecast/forecast_tab_hooks.js
@@ -126,7 +126,7 @@ const useEqConfigTechObjTable = (parent, filters, orders, pageNumber) => {
NINCLUDE_DEF: pageNumber == 1 ? 1 : 0
},
respArg: "COUT",
- loader: false
+ loader: true
});
setData(pv => ({
...pv,
@@ -182,8 +182,51 @@ const useEqConfigTechObjCard = id => {
return { techObjCard: card, techObjCardIsLoading: isLoading };
};
+//Загрузка списка моделей единицы оборудования
+const useTechObjModelsList = (id, refresh) => {
+ //Собственное состояние - флаг загрузки
+ const [isLoading, setLoading] = useState(false);
+
+ //Собственное состояние - таблица данных
+ const [data, setData] = useState({
+ init: false,
+ columnsDef: [],
+ rows: []
+ });
+
+ //Подключение к контексту взаимодействия с сервером
+ const { executeStored } = useContext(BackEndСtx);
+
+ //Загрузка данных при изменении зависимостей
+ useEffect(() => {
+ const loadData = async () => {
+ try {
+ setLoading(true);
+ const data = await executeStored({
+ stored: "UDO_PKG_EQUIPDS.CMML_LIST_BY_EQCONFIG",
+ args: { NEQCONFIG: id },
+ respArg: "COUT",
+ loader: false
+ });
+ setData(pv => ({
+ ...pv,
+ columnsDef: [...data.XCOLUMNS_DEF],
+ rows: [...(data.XROWS || [])],
+ init: true
+ }));
+ } finally {
+ setLoading(false);
+ }
+ };
+ if (id) loadData();
+ }, [id, refresh, executeStored]);
+
+ //Вернём данные
+ return { techObjModelsList: data, techObjModelsListIsLoading: isLoading };
+};
+
//----------------
//Интерфейс модуля
//----------------
-export { useEqConfigTree, useEqConfigTechObjTable, useEqConfigTechObjCard, findTreeItem, needLoadLevel };
+export { useEqConfigTree, useEqConfigTechObjTable, useEqConfigTechObjCard, findTreeItem, needLoadLevel, useTechObjModelsList };
diff --git a/panels/eqs_tech_cond_forecast/forecast_tab_layout.js b/panels/eqs_tech_cond_forecast/forecast_tab_layout.js
index ef3fca8..4803d16 100644
--- a/panels/eqs_tech_cond_forecast/forecast_tab_layout.js
+++ b/panels/eqs_tech_cond_forecast/forecast_tab_layout.js
@@ -9,8 +9,13 @@
import React from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
-import { Box, Card, CardContent, Typography, CardActions, Button } from "@mui/material"; //Интерфейсные компоненты
+import { Stack, Icon, Box, Card, CardContent, Typography, CardActions, Button, IconButton, Divider } from "@mui/material"; //Интерфейсные компоненты
+import { useTheme } from "@mui/material/styles"; //Темы оформления
+import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../components/p8p_data_grid"; //Таблица данных
+import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { formatDateRF } from "../../core/utils"; //Вспомогательные функции
+import { SCROLL_STYLES, formatModelStateValue } from "./eqs_tech_cond_forecast_lyaout"; //Общие вспомогательные компоненты и вёрстка
+import { Link } from "react-router-dom";
//---------
//Константы
@@ -19,7 +24,59 @@ import { formatDateRF } from "../../core/utils"; //Вспомогательны
//Стили
const STYLES = {
TECH_OBJ_CARD_TITLE: { fontSize: 14 },
- TECH_OBJ_CARD_SUB_TITLE: { mb: 1.5 }
+ TECH_OBJ_CARD_SUB_TITLE: { mb: 1.5 },
+ EQ_ML_TABLE: {
+ maxHeight: "200px",
+ ...SCROLL_STYLES
+ }
+};
+
+//------------------------------------
+//Вспомогательные функции и компоненты
+//------------------------------------
+
+//Форматирование ячеек заголовка таблицы моделей единицы оборудования
+const techObjCardModelsTableHeadCellRender = ({ columnDef }) => {
+ switch (columnDef.name) {
+ case "NSTATUS":
+ return {
+ stackProps: { justifyContent: "left" },
+ cellProps: { align: "left" }
+ };
+ case "SACTIONS":
+ return { data: " " };
+ }
+};
+
+//Форматирование колонок таблицы моделей класса оборудования выборки данных
+const techObjCardModelsTableDataCellRender = ({ row, columnDef, theme, onGoToModel, onGetPrediction }) => {
+ switch (columnDef.name) {
+ case "SNEQUIPDS":
+ case "STASK":
+ case "NPRECISION_P":
+ case "NPRECISION_F":
+ return {
+ data: (
+ onGoToModel(row)}>
+ {row[columnDef.name]}
+
+ )
+ };
+ case "NSTATUS":
+ return {
+ cellProps: { align: "left" },
+ data: formatModelStateValue(theme, row.NSTATUS, row.SERR)
+ };
+ case "SACTIONS":
+ return {
+ data:
+ row.NSTATUS == 2 ? (
+
+ ) : null
+ };
+ }
};
//-----------
@@ -27,27 +84,71 @@ const STYLES = {
//-----------
//Карточка технического объекта
-const TechObjCard = ({ cardData }) => {
+const TechObjCard = ({ cardData, modelsList, onClose, onGoToModel }) => {
+ //Подключаемся к теме
+ const theme = useTheme();
+
+ //При нажатии на кнопку закрытия карточки
+ const handleClose = () => (onClose ? onClose() : null);
+
+ //При нажатии на переход к модели
+ const handleGoToModelClick = model => (onGoToModel ? onGoToModel(model) : null);
+
+ //При нажатии на запрос предсказания
+ const handleGetPredictionClick = model => {
+ console.log(model);
+ };
+
//Генерация содержимого
return (
-
- Технический объект
-
+
+
+ close
+
+
+ Технический объект
+
+
{cardData.SCODE}
-
- {cardData.DOPER_DATE}
+
+ {`Введён в эксплуатацию: ${formatDateRF(cardData.DOPER_DATE)}`}
+
+ {`Класс: ${cardData.SEQOBJKIND}`}
- {cardData.SNAME}
+ {cardData.SNAME}
+
+
+
+ Модели
+
+
+ techObjCardModelsTableDataCellRender({
+ ...prms,
+ theme,
+ onGoToModel: handleGoToModelClick,
+ onGetPrediction: handleGetPredictionClick
+ })
+ }
+ />
+
-
-
-
+
@@ -56,20 +157,49 @@ const TechObjCard = ({ cardData }) => {
//Контроль свойств - Карточка технического объекта
TechObjCard.propTypes = {
- cardData: PropTypes.object
+ cardData: PropTypes.object.isRequired,
+ modelsList: PropTypes.object.isRequired,
+ onClose: PropTypes.func,
+ onGoToModel: PropTypes.func
};
+//Формирование значения для колонки "Медель" таблицы технических объектов
+const formatTechObjCMMLStatusValue = value => (value == 0 ? "Обучить" : value == 1 ? "Обучается" : "Прогнозировать");
+
+//Формирование цвета для колонки "Медель" таблицы технических объектов
+const formatTechObjCMMLStatusColor = value => (value == 0 ? "primary" : value == 1 ? "warning" : "success");
+
//Форматирование значений колонок таблицы технических объектов
const eqConfigTechObjTableValueFormatter = ({ value, columnDef }) => {
switch (columnDef.name) {
case "DOPER_DATE":
return formatDateRF(value);
+ case "NCMML_STATUS":
+ return formatTechObjCMMLStatusValue(value);
}
return value;
};
+//Форматирование колонок таблицы технических объектов
+const eqConfigTechObjTableDataCellRender = ({ row, columnDef, onCMMLStatus }) => {
+ switch (columnDef.name) {
+ case "NCMML_STATUS":
+ return {
+ data: (
+
+ )
+ };
+ }
+};
+
//----------------
//Интерфейс модуля
//----------------
-export { TechObjCard, eqConfigTechObjTableValueFormatter };
+export { TechObjCard, eqConfigTechObjTableValueFormatter, eqConfigTechObjTableDataCellRender };