diff --git a/db/UDO_PKG_EQUIPDS.pck b/db/UDO_PKG_EQUIPDS.pck
index 6b0568a..216a832 100644
--- a/db/UDO_PKG_EQUIPDS.pck
+++ b/db/UDO_PKG_EQUIPDS.pck
@@ -1,5 +1,32 @@
create or replace package UDO_PKG_EQUIPDS as
+ /* Список выборок данных */
+ procedure LIST
+ (
+ COUT out clob -- Сериализованная таблица данных
+ );
+
+ /* Список классов оборудования выборки данных */
+ procedure CM_LIST
+ (
+ NEQUIPDS in number, -- Рег. номер выборки данных
+ COUT out clob -- Сериализованная таблица данных
+ );
+
+ /* Список файлов данных класса оборудования */
+ procedure CMFL_LIST
+ (
+ NEQUIPDSCM in number, -- Рег. номер класса оборудования выборки данных
+ COUT out clob -- Сериализованная таблица данных
+ );
+
+ /* Список моделей класса оборудования */
+ procedure CMML_LIST
+ (
+ NEQUIPDSCM in number, -- Рег. номер класса оборудования выборки данных
+ COUT out clob -- Сериализованная таблица данных
+ );
+
/* Код доступного действия с моделью по единице оборудования */
function CMML_ACT_BY_EQCONFIG
(
@@ -16,6 +43,222 @@ end UDO_PKG_EQUIPDS;
/
create or replace package body UDO_PKG_EQUIPDS as
+ /* Список выборок данных */
+ procedure LIST
+ (
+ COUT out clob -- Сериализованная таблица данных
+ )
+ is
+ NCOMPANY PKG_STD.TREF := GET_SESSION_COMPANY(); -- Организация сеанса
+ NCUR integer; -- Курсор документа для результата
+ XDOC PKG_XMAKE.TNODE; -- Документ для результата
+ XDS PKG_XMAKE.TNODE; -- Элемент для выборки данных
+ begin
+ /* Открываем документ */
+ NCUR := PKG_XMAKE.OPEN_CURSOR();
+ /* Обходим выборки данных */
+ for C in (select T.RN NRN,
+ T.NAME SNAME
+ from UDO_T_EQUIPDS T
+ where T.COMPANY = NCOMPANY
+ order by T.NAME)
+ loop
+ XDS := PKG_XMAKE.CONCAT(ICURSOR => NCUR,
+ RNODE00 => XDS,
+ RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR => NCUR,
+ SNAME => 'XDS',
+ RATTRIBUTES => PKG_XMAKE.ATTRIBUTES(ICURSOR => NCUR,
+ RATTRIBUTE00 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
+ SNAME => 'NRN',
+ SVALUE => C.NRN),
+ RATTRIBUTE01 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
+ SNAME => 'SNAME',
+ SVALUE => C.SNAME))));
+ end loop;
+ /* Формируем XML-представление ответа */
+ XDOC := PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'XDATA', RNODE00 => XDS);
+ /* Конвертируем в CLOB */
+ 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 LIST;
+
+ /* Список классов оборудования выборки данных */
+ procedure CM_LIST
+ (
+ NEQUIPDS in number, -- Рег. номер выборки данных
+ COUT out clob -- Сериализованная таблица данных
+ )
+ is
+ NCUR integer; -- Курсор документа для результата
+ XDOC PKG_XMAKE.TNODE; -- Документ для результата
+ XDSCM PKG_XMAKE.TNODE; -- Элемент для выборки данных
+ begin
+ /* Открываем документ */
+ NCUR := PKG_XMAKE.OPEN_CURSOR();
+ /* Обходим классы оборудования заданной выборки данных */
+ for C in (select T.RN NRN,
+ OK.CODE SCODE,
+ OK.NAME SNAME
+ from UDO_T_EQUIPDSCM T,
+ EQOBJKIND OK
+ where T.PRN = NEQUIPDS
+ and T.EQOBJKIND = OK.RN
+ order by OK.CODE)
+ loop
+ XDSCM := PKG_XMAKE.CONCAT(ICURSOR => NCUR,
+ RNODE00 => XDSCM,
+ RNODE01 => PKG_XMAKE.ELEMENT(ICURSOR => NCUR,
+ SNAME => 'XDSCM',
+ RATTRIBUTES => PKG_XMAKE.ATTRIBUTES(ICURSOR => NCUR,
+ RATTRIBUTE00 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
+ SNAME => 'NRN',
+ SVALUE => C.NRN),
+ RATTRIBUTE01 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
+ SNAME => 'SCODE',
+ SVALUE => C.SCODE),
+ RATTRIBUTE02 => PKG_XMAKE.ATTRIBUTE(ICURSOR => NCUR,
+ SNAME => 'SNAME',
+ SVALUE => C.SNAME))));
+ end loop;
+ /* Формируем XML-представление ответа */
+ XDOC := PKG_XMAKE.ELEMENT(ICURSOR => NCUR, SNAME => 'XDATA', RNODE00 => XDSCM);
+ /* Конвертируем в CLOB */
+ 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 CM_LIST;
+
+ /* Список файлов данных класса оборудования */
+ procedure CMFL_LIST
+ (
+ NEQUIPDSCM in number, -- Рег. номер класса оборудования выборки данных
+ COUT out clob -- Сериализованная таблица данных
+ )
+ is
+ RDG PKG_P8PANELS_VISUAL.TDATA_GRID; -- Описание таблицы
+ RDG_ROW PKG_P8PANELS_VISUAL.TROW; -- Строка таблицы
+ begin
+ /* Инициализируем таблицу данных */
+ 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 => 'SFILE_NAME',
+ SCAPTION => 'Имя',
+ SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR);
+ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG,
+ SNAME => 'SDESCR',
+ SCAPTION => 'Описание',
+ SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR);
+ 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);
+ /* Обходим данные */
+ for C in (select T.RN NRN,
+ T.FILE_NAME SFILE_NAME,
+ T.DESCR SDESCR,
+ T.STATUS NSTATUS,
+ T.ERR SERR
+ from UDO_T_EQUIPDSCMFL T
+ where T.PRN = NEQUIPDSCM
+ 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 => 'SFILE_NAME', SVALUE => C.SFILE_NAME);
+ PKG_P8PANELS_VISUAL.TROW_ADD_COL(RROW => RDG_ROW, SNAME => 'SDESCR', SVALUE => C.SDESCR);
+ 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.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 CMFL_LIST;
+
+ /* Список моделей класса оборудования */
+ procedure CMML_LIST
+ (
+ NEQUIPDSCM in number, -- Рег. номер класса оборудования выборки данных
+ COUT out clob -- Сериализованная таблица данных
+ )
+ is
+ RDG PKG_P8PANELS_VISUAL.TDATA_GRID; -- Описание таблицы
+ RDG_ROW PKG_P8PANELS_VISUAL.TROW; -- Строка таблицы
+ begin
+ /* Инициализируем таблицу данных */
+ 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 => 'STASK',
+ SCAPTION => 'Задача',
+ SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR);
+ 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);
+ /* Обходим данные */
+ for C in (select T.RN NRN,
+ T.TASK STASK,
+ T.PRECISION_P NPRECISION_P,
+ T.PRECISION_F NPRECISION_F,
+ T.STATUS NSTATUS,
+ T.ERR SERR
+ from UDO_T_EQUIPDSCMML T
+ where T.PRN = NEQUIPDSCM
+ 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 => '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.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;
+
/* Код доступного действия с моделью по единице оборудования */
function CMML_ACT_BY_EQCONFIG
(
@@ -34,7 +277,7 @@ create or replace package body UDO_PKG_EQUIPDS as
is
begin
return 'TCF;RUL;FP';
- end CMML_LIST_BY_EQCONFIG;
+ end CMML_LIST_BY_EQCONFIG;
end UDO_PKG_EQUIPDS;
/
diff --git a/panels/eqs_tech_cond_forecast/admin_tab.js b/panels/eqs_tech_cond_forecast/admin_tab.js
index 454bb7e..e85929d 100644
--- a/panels/eqs_tech_cond_forecast/admin_tab.js
+++ b/panels/eqs_tech_cond_forecast/admin_tab.js
@@ -7,8 +7,26 @@
//Подключение библиотек
//---------------------
-import React from "react"; //Классы React
-import { Grid } from "@mui/material"; //Интерфейсные компоненты
+import React, { useState, useEffect } from "react"; //Классы React
+import { Box, Grid, Stack, Icon, Button } from "@mui/material"; //Интерфейсные компоненты
+import { EquipDataSelectionList, EquipDataSelectionClassMachineList, EquipDataSelectionClassMachineCard } from "./admin_tab_layout"; //Вспомогательные компоненты и вёрстка
+import {
+ DS_RN_DEFAULT,
+ useEquipDataSelectionList,
+ useEquipDataSelectionClassMachineList,
+ useEquipDataSelectionClassMachineFilesList,
+ useEquipDataSelectionClassMachineModelsList
+} from "./admin_tab_hooks"; //Вспомогательные хуки
+
+//---------
+//Константы
+//---------
+
+//Стили
+const STYLES = {
+ DATA_SELECTION_STACK: { alignItems: "center" },
+ CLASS_MACHINE_ADD_BUTTON: { margin: "5px" }
+};
//-----------
//Тело модуля
@@ -16,15 +34,70 @@ import { Grid } from "@mui/material"; //Интерфейсные компоне
//Закладка администрирования
const AdminTab = () => {
+ //Собственное состояние - выбранная выборка данных
+ const [equipDataSelection, setDataSelection] = useState(DS_RN_DEFAULT);
+
+ //Собственное состояние - выбранный класс оборудования
+ const [equipDataSelectionClassMachine, setDataSelectionClassMachine] = useState(null);
+
+ //Загрузка списка выборок данных
+ const { equipDataSelectionList } = useEquipDataSelectionList();
+
+ //Загрузка классов оборудования выбранной выборки данных
+ const { equipDataSelectionClassMachineList } = useEquipDataSelectionClassMachineList(equipDataSelection);
+
+ //Загрузка файлов класса оборудования
+ const { equipDataSelectionClassMachineFilesList } = useEquipDataSelectionClassMachineFilesList(equipDataSelectionClassMachine);
+
+ //Загрузка файлов класса оборудования
+ const { equipDataSelectionClassMachineModelsList } = useEquipDataSelectionClassMachineModelsList(equipDataSelectionClassMachine);
+
+ //При подключении компонента к странице
+ useEffect(() => {}, []);
+
+ //При смене выборки данных
+ const handleDataSelectionChange = value => {
+ setDataSelectionClassMachine(null);
+ setDataSelection(value);
+ };
+
+ //При нажатии на класс оборудования
+ const handleDataSelectionClassMachineClick = value => setDataSelectionClassMachine(value);
+
//Генерация содержимого
return (
-
+
-
- Здесь только администраторы могут работать
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
);
};
diff --git a/panels/eqs_tech_cond_forecast/admin_tab_hooks.js b/panels/eqs_tech_cond_forecast/admin_tab_hooks.js
new file mode 100644
index 0000000..2ec3e41
--- /dev/null
+++ b/panels/eqs_tech_cond_forecast/admin_tab_hooks.js
@@ -0,0 +1,196 @@
+/*
+ Парус 8 - Панели мониторинга - ТОиР - Прогнозирование технического состояния
+ Закладка администрирования: кастомные хуки
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import { useState, useEffect, useContext } from "react"; //Классы React
+import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером
+
+//---------
+//Константы
+//---------
+
+//Рег. номер выборки данных по умолчанию
+const DS_RN_DEFAULT = -1;
+
+//Наименование выборки данных по умолчанию
+const DS_NAME_DEFAULT = "Не указана";
+
+//Выборка данных по умолчанию
+const DS_DEFAULT = { NRN: DS_RN_DEFAULT, SNAME: DS_NAME_DEFAULT };
+
+//-----------
+//Тело модуля
+//-----------
+
+//Загрузка списка выборок данных
+const useEquipDataSelectionList = () => {
+ //Собственное состояние - флаг загрузки
+ const [isLoading, setLoading] = useState(false);
+
+ //Собственное состояние - данные
+ const [data, setData] = useState([DS_DEFAULT]);
+
+ //Подключение к контексту взаимодействия с сервером
+ const { executeStored } = useContext(BackEndСtx);
+
+ //Загрузка данных при изменении зависимостей
+ useEffect(() => {
+ const loadData = async () => {
+ try {
+ setLoading(true);
+ const data = await executeStored({
+ stored: "UDO_PKG_EQUIPDS.LIST",
+ respArg: "COUT",
+ isArray: name => ["XDS"].includes(name),
+ loader: false
+ });
+ setData([DS_DEFAULT, ...(data?.XDS ? data.XDS : [])]);
+ } finally {
+ setLoading(false);
+ }
+ };
+ loadData();
+ }, [executeStored]);
+
+ //Вернём данные
+ return { equipDataSelectionList: data, equipDataSelectionListIsLoading: isLoading };
+};
+
+//Загрузка классов оборудования выбороки данных
+const useEquipDataSelectionClassMachineList = dataSelection => {
+ //Собственное состояние - флаг загрузки
+ const [isLoading, setLoading] = useState(false);
+
+ //Собственное состояние - данные
+ const [data, setData] = useState([]);
+
+ //Подключение к контексту взаимодействия с сервером
+ const { executeStored } = useContext(BackEndСtx);
+
+ //Загрузка данных при изменении зависимостейuse
+ useEffect(() => {
+ const loadData = async () => {
+ try {
+ setLoading(true);
+ const data = await executeStored({
+ stored: "UDO_PKG_EQUIPDS.CM_LIST",
+ args: { NEQUIPDS: dataSelection },
+ respArg: "COUT",
+ isArray: name => ["XDSCM"].includes(name),
+ attributeValueProcessor: (name, val) => (["SCODE"].includes(name) ? undefined : val),
+ loader: false
+ });
+ setData(data?.XDSCM || []);
+ } finally {
+ setLoading(false);
+ }
+ };
+ if (dataSelection && dataSelection != DS_RN_DEFAULT) loadData();
+ }, [dataSelection, executeStored]);
+
+ //Вернём данные
+ return { equipDataSelectionClassMachineList: data, equipDataSelectionClassMachineListIsLoading: isLoading };
+};
+
+//Загрузка списка файлов класса оборудования
+const useEquipDataSelectionClassMachineFilesList = classMachine => {
+ //Собственное состояние - флаг загрузки
+ 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.CMFL_LIST",
+ args: { NEQUIPDSCM: classMachine },
+ respArg: "COUT",
+ loader: false
+ });
+ setData(pv => ({
+ ...pv,
+ columnsDef: [...data.XCOLUMNS_DEF],
+ rows: [...(data.XROWS || [])],
+ init: true
+ }));
+ } finally {
+ setLoading(false);
+ }
+ };
+ if (classMachine) loadData();
+ }, [classMachine, executeStored]);
+
+ //Вернём данные
+ return { equipDataSelectionClassMachineFilesList: data, equipDataSelectionClassMachineFilesListIsLoading: isLoading };
+};
+
+//Загрузка списка моделей класса оборудования
+const useEquipDataSelectionClassMachineModelsList = classMachine => {
+ //Собственное состояние - флаг загрузки
+ 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",
+ args: { NEQUIPDSCM: classMachine },
+ respArg: "COUT",
+ loader: false
+ });
+ setData(pv => ({
+ ...pv,
+ columnsDef: [...data.XCOLUMNS_DEF],
+ rows: [...(data.XROWS || [])],
+ init: true
+ }));
+ } finally {
+ setLoading(false);
+ }
+ };
+ if (classMachine) loadData();
+ }, [classMachine, executeStored]);
+
+ //Вернём данные
+ return { equipDataSelectionClassMachineModelsList: data, equipDataSelectionClassMachineModelsListIsLoading: isLoading };
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export {
+ DS_RN_DEFAULT,
+ useEquipDataSelectionList,
+ useEquipDataSelectionClassMachineList,
+ useEquipDataSelectionClassMachineFilesList,
+ useEquipDataSelectionClassMachineModelsList
+};
diff --git a/panels/eqs_tech_cond_forecast/admin_tab_layout.js b/panels/eqs_tech_cond_forecast/admin_tab_layout.js
new file mode 100644
index 0000000..7224caf
--- /dev/null
+++ b/panels/eqs_tech_cond_forecast/admin_tab_layout.js
@@ -0,0 +1,206 @@
+/*
+ Парус 8 - Панели мониторинга - ТОиР - Прогнозирование технического состояния
+ Закладка администрирования: дополнительная разметка и вёрстка клиентских элементов
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import {
+ Box,
+ Stack,
+ FormControl,
+ InputLabel,
+ Select,
+ MenuItem,
+ List,
+ ListItem,
+ ListItemButton,
+ ListItemText,
+ Card,
+ CardContent,
+ CardActions,
+ Typography,
+ Button
+} from "@mui/material"; //Интерфейсные компоненты
+import { APP_BAR_HEIGHT, TABS_HEIGHT, SCROLL_STYLES } 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"; //Подключение компонентов к настройкам приложения
+
+//---------
+//Константы
+//---------
+
+//Высота списка выборок данных
+const DS_SELECTOR_HEIGHT = "80px";
+
+//Высота кнопки добавления технического объекта
+const CM_ADD_BTN_HEIGHT = "46.5px";
+
+//Структура элемента списка выборок данных оборудования
+const EQUIP_DATA_SELECTION_LIST = PropTypes.shape({
+ NRN: PropTypes.number.isRequired,
+ SNAME: PropTypes.string.isRequired
+});
+
+//Структура элемента списка классов оборудования выборки данных
+const EQUIP_DATA_SELECTION_CLASS_MACHINE_LIST = PropTypes.shape({
+ NRN: PropTypes.number.isRequired,
+ SCODE: PropTypes.string.isRequired,
+ SNAME: PropTypes.string.isRequired
+});
+
+//Стили
+const STYLES = {
+ EQUIP_DS_LIST_FORM_CONTROL: { minWidth: "300px" },
+ EQUIP_DSCM_LIST: {
+ minHeight: `calc(100vh - ${APP_BAR_HEIGHT} - ${TABS_HEIGHT} - ${DS_SELECTOR_HEIGHT} - ${CM_ADD_BTN_HEIGHT})`,
+ maxHeight: `calc(100vh - ${APP_BAR_HEIGHT} - ${TABS_HEIGHT} - ${DS_SELECTOR_HEIGHT} - ${CM_ADD_BTN_HEIGHT})`,
+ overflowX: "hidden",
+ overflowY: "auto",
+ ...SCROLL_STYLES
+ },
+ EQUIP_DSCM_CARD: {
+ minHeight: `calc(100vh - ${APP_BAR_HEIGHT} - ${TABS_HEIGHT} - ${DS_SELECTOR_HEIGHT})`,
+ maxHeight: `calc(100vh - ${APP_BAR_HEIGHT} - ${TABS_HEIGHT} - ${DS_SELECTOR_HEIGHT})`,
+ overflowY: "auto",
+ ...SCROLL_STYLES
+ },
+ FL_ML_TABLE: {
+ height: `200px`,
+ ...SCROLL_STYLES
+ }
+};
+
+//-----------
+//Тело модуля
+//-----------
+
+//Список выборок данных оборудования
+const EquipDataSelectionList = ({ list, value, onChange }) => {
+ //При выборе элемента
+ const handleChange = e => (onChange ? onChange(e.target.value) : null);
+
+ //Генерация содержимого
+ return (
+
+ Выборка данных оборудования
+
+
+ );
+};
+
+//Контроль свойств - Список выборок данных оборудования
+EquipDataSelectionList.propTypes = {
+ list: PropTypes.arrayOf(EQUIP_DATA_SELECTION_LIST).isRequired,
+ value: PropTypes.number.isRequired,
+ onChange: PropTypes.func
+};
+
+//Список классов оборудования выборки данных
+const EquipDataSelectionClassMachineList = ({ list, value, onClick }) => {
+ //При щелчке на элементе
+ const handleClick = id => (onClick ? onClick(id) : null);
+
+ //Генерация содержимого
+ return (
+
+ {list.map((item, i) => (
+
+ handleClick(item.NRN)}>
+
+
+
+ ))}
+
+ );
+};
+
+//Контроль свойств - Список классов оборудования выборки данных
+EquipDataSelectionClassMachineList.propTypes = {
+ list: PropTypes.arrayOf(EQUIP_DATA_SELECTION_CLASS_MACHINE_LIST).isRequired,
+ value: PropTypes.number,
+ onClick: PropTypes.func
+};
+
+//Карточка класса оборудования выборки данных
+const EquipDataSelectionClassMachineCard = ({ filesList, modelsList }) => {
+ //Генерация содержимого
+ return (
+
+
+
+
+
+ Наименование технического объекта
+
+
+ Состояние: готов к ...
+
+ фывафывафва
+
+
+
+
+
+
+
+
+
+
+ Файлы данных
+
+
+
+
+
+
+
+ Модели
+
+
+
+
+
+
+ );
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { 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 e086ac0..899446c 100644
--- a/panels/eqs_tech_cond_forecast/eqs_tech_cond_forecast.js
+++ b/panels/eqs_tech_cond_forecast/eqs_tech_cond_forecast.js
@@ -7,8 +7,9 @@
//Подключение библиотек
//---------------------
-import React, { useState, useEffect } from "react"; //Классы React
+import React, { useState } from "react"; //Классы React
import { Box, Tabs, Tab } from "@mui/material"; //Интерфейсные компоненты
+import { MODES, TabPanel } from "./eqs_tech_cond_forecast_lyaout"; //Вспомогательные компоненты и вёрстка
import { AdminTab } from "./admin_tab"; //Интерфейс администрирования
import { ForecastTab } from "./forecast_tab"; //Интерфейс прогнозирования
@@ -16,23 +17,19 @@ import { ForecastTab } from "./forecast_tab"; //Интерфейс прогно
//Константы
//---------
-//Режимы работы панели
-const MODES = {
- FORECAST: 1,
- ADMIN: 2
+//Стили
+const STYLES = {
+ TABS_CONTAINER_BOX: { borderBottom: 1, borderColor: "divider" }
};
//-----------
//Тело модуля
//-----------
-//Закладка
-const TapPanel = ({ children }) => {children};
-
//Корневая панель прогнозирования технического состояния
const EqsTechCondForecast = () => {
//Собственное состояние
- const [mode, setMode] = useState(MODES.FORECAST);
+ const [mode, setMode] = useState(MODES.ADMIN);
//При переключении закладки
const handleTabChange = (e, newValue) => setMode(newValue);
@@ -40,22 +37,18 @@ const EqsTechCondForecast = () => {
//Генерация содержимого
return (
<>
-
+
- {mode == MODES.ADMIN ? (
-
- {" "}
-
- ) : null}
- {mode == MODES.FORECAST ? (
-
-
-
- ) : null}
+
+
+
+
+
+
>
);
};
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
new file mode 100644
index 0000000..ead138e
--- /dev/null
+++ b/panels/eqs_tech_cond_forecast/eqs_tech_cond_forecast_lyaout.js
@@ -0,0 +1,73 @@
+/*
+ Парус 8 - Панели мониторинга - ТОиР - Прогнозирование технического состояния
+ Корневая панель прогнозирования технического состояния: дополнительная разметка и вёрстка клиентских элементов
+*/
+
+//---------------------
+//Подключение библиотек
+//---------------------
+
+import React from "react"; //Классы React
+import PropTypes from "prop-types"; //Контроль свойств компонента
+import { Box } from "@mui/material"; //Интерфейсные компоненты
+
+//---------
+//Константы
+//---------
+
+//Режимы работы панели
+const MODES = {
+ FORECAST: 1,
+ ADMIN: 2
+};
+
+//Высота главного меню
+const APP_BAR_HEIGHT = "64px";
+
+//Высота закладок
+const TABS_HEIGHT = "49px";
+
+//Высота кнопки "Ещё"
+const TABLE_MORE_HEIGHT = "49px";
+
+//Высота фильтров таблицы
+const TABLE_FILTERS_HEIGHT = "48px";
+
+//Стиль скролов
+const SCROLL_STYLES = {
+ "&::-webkit-scrollbar": {
+ height: "8px",
+ width: "8px"
+ },
+ "&::-webkit-scrollbar-track": {
+ borderRadius: "8px",
+ backgroundColor: "#EBEBEB"
+ },
+ "&::-webkit-scrollbar-thumb": {
+ borderRadius: "8px",
+ backgroundColor: "#b4b4b4"
+ },
+ "&::-webkit-scrollbar-thumb:hover": {
+ backgroundColor: "#808080"
+ }
+};
+
+//-----------
+//Тело модуля
+//-----------
+
+//Закладка
+const TabPanel = ({ mode, value, children }) => {children};
+
+//Контроль свойств - Закладка
+TabPanel.propTypes = {
+ mode: PropTypes.number.isRequired,
+ value: PropTypes.number.isRequired,
+ children: PropTypes.element
+};
+
+//----------------
+//Интерфейс модуля
+//----------------
+
+export { MODES, APP_BAR_HEIGHT, TABS_HEIGHT, TABLE_MORE_HEIGHT, TABLE_FILTERS_HEIGHT, SCROLL_STYLES, TabPanel };
diff --git a/panels/eqs_tech_cond_forecast/forecast_tab.js b/panels/eqs_tech_cond_forecast/forecast_tab.js
index 672d6f2..b1e5711 100644
--- a/panels/eqs_tech_cond_forecast/forecast_tab.js
+++ b/panels/eqs_tech_cond_forecast/forecast_tab.js
@@ -13,25 +13,14 @@ import { RichTreeView } from "@mui/x-tree-view/RichTreeView"; //Дерево
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 { useEqConfigTree, useEqConfigTechObjTable, useEqConfigTechObjCard, findTreeItem, needLoadLevel } from "./forecast_tab_hooks"; //Вспомогательные хуки
+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"; //Вспомогательные хуки
//---------
//Константы
//---------
-//Высота главного меню
-const APP_BAR_HEIGHT = "64px";
-
-//Высота закладок
-const TABS_HEIGHT = "49px";
-
-//Высота кнопки "Ещё"
-const TABLE_MORE_HEIGHT = "49px";
-
-//Высота фильтров таблицы
-const TABLE_FILTERS_HEIGHT = "48px";
-
//Стили
const STYLES = {
LEFT_SIDE_GRID: {},
@@ -40,15 +29,15 @@ const STYLES = {
minHeight: `calc(100vh - ${APP_BAR_HEIGHT} - ${TABS_HEIGHT})`,
maxHeight: `calc(100vh - ${APP_BAR_HEIGHT} - ${TABS_HEIGHT})`,
overflowX: "hidden",
- overflowY: "scroll",
- scrollbarWidth: "thin",
- padding: "3px"
+ overflowY: "auto",
+ padding: "3px",
+ ...SCROLL_STYLES
},
TECH_OBJ_TABLE: (morePages, filters) => ({
height: `calc(100vh - ${APP_BAR_HEIGHT} - ${TABS_HEIGHT} - ${morePages ? TABLE_MORE_HEIGHT : "0px"} - ${
filters ? TABLE_FILTERS_HEIGHT : "0px"
})`,
- scrollbarWidth: "thin"
+ ...SCROLL_STYLES
})
};
@@ -74,7 +63,7 @@ const ForecastTab = () => {
const [techObjCardId, setTechObjCardId] = useState(null);
//Загрузчик веток дерева
- const { tree } = useEqConfigTree(loadingTreeItem);
+ const { eQconfigTree } = useEqConfigTree(loadingTreeItem);
//Загрузчик технических объектов для выбранной ветки
const { techObjsDataGrid, techObjsDataGridIsLoading } = useEqConfigTechObjTable(
@@ -89,11 +78,11 @@ const ForecastTab = () => {
//Обработка развёртывания/свёртывания уровня дерева
const handleTreeItemExpansionToggle = (event, itemId, isExpanded) =>
- isExpanded && needLoadLevel(tree, itemId) ? setLoadingTreeItem(parseInt(itemId)) : null;
+ isExpanded && needLoadLevel(eQconfigTree, itemId) ? setLoadingTreeItem(parseInt(itemId)) : null;
//Обработка фокусировки на элементе дерева
const handleTreeItemFocus = (event, itemId) => {
- const item = findTreeItem(tree, itemId);
+ const item = findTreeItem(eQconfigTree, itemId);
if (item && item?.showCard) setTechObjCardId(parseInt(itemId));
else {
setTechObjCardId(null);
@@ -124,7 +113,7 @@ const ForecastTab = () => {
-
+
diff --git a/panels/eqs_tech_cond_forecast/forecast_tab_hooks.js b/panels/eqs_tech_cond_forecast/forecast_tab_hooks.js
index fe5ba33..c4d43fa 100644
--- a/panels/eqs_tech_cond_forecast/forecast_tab_hooks.js
+++ b/panels/eqs_tech_cond_forecast/forecast_tab_hooks.js
@@ -1,6 +1,6 @@
/*
Парус 8 - Панели мониторинга - ТОиР - Прогнозирование технического состояния
- Кастомные хуки закладки Прогнозирования
+ Закладка прогнозирования: кастомные хуки
*/
//---------------------
@@ -91,7 +91,7 @@ const useEqConfigTree = parent => {
}, [parent, executeStored]);
//Вернём данные
- return { tree, isLoading };
+ return { eQconfigTree: tree, eQconfigTreeIsLoading: isLoading };
};
//Загрузка списка технических объектов
@@ -151,7 +151,7 @@ const useEqConfigTechObjCard = id => {
//Собственное состояние - флаг загрузки
const [isLoading, setLoading] = useState(false);
- //Собственное состояние - данные дерева
+ //Собственное состояние - данные карточки
const [card, setCard] = useState({});
//Подключение к контексту взаимодействия с сервером
diff --git a/panels/eqs_tech_cond_forecast/forecast_tab_layout.js b/panels/eqs_tech_cond_forecast/forecast_tab_layout.js
index f80149d..ef3fca8 100644
--- a/panels/eqs_tech_cond_forecast/forecast_tab_layout.js
+++ b/panels/eqs_tech_cond_forecast/forecast_tab_layout.js
@@ -1,6 +1,6 @@
/*
Парус 8 - Панели мониторинга - ТОиР - Прогнозирование технического состояния
- Дополнительная разметка и вёрстка клиентских элементов
+ Закладка прогнозирования: дополнительная разметка и вёрстка клиентских элементов
*/
//---------------------
@@ -12,6 +12,16 @@ import PropTypes from "prop-types"; //Контроль свойств компо
import { Box, Card, CardContent, Typography, CardActions, Button } from "@mui/material"; //Интерфейсные компоненты
import { formatDateRF } from "../../core/utils"; //Вспомогательные функции
+//---------
+//Константы
+//---------
+
+//Стили
+const STYLES = {
+ TECH_OBJ_CARD_TITLE: { fontSize: 14 },
+ TECH_OBJ_CARD_SUB_TITLE: { mb: 1.5 }
+};
+
//-----------
//Тело модуля
//-----------
@@ -20,16 +30,16 @@ import { formatDateRF } from "../../core/utils"; //Вспомогательны
const TechObjCard = ({ cardData }) => {
//Генерация содержимого
return (
-
+
-
+
Технический объект
{cardData.SCODE}
-
+
{cardData.DOPER_DATE}
{cardData.SNAME}