From d97f5183b7c51406da21a0ab13425265e2c04c6d Mon Sep 17 00:00:00 2001 From: davay-popozhe Date: Fri, 26 Jul 2024 15:03:26 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A6=D0=98=D0=A2=D0=9A-831=20+=20=D0=A6=D0=98?= =?UTF-8?q?=D0=A2=D0=9A-833?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/panels/eqs_prfrm/eqs_prfrm.js | 112 +++++++++++++++++++++++------- app/panels/eqs_prfrm/hooks.js | 36 ++++++++++ app/panels/eqs_prfrm/layouts.js | 27 +++++-- db/PKG_P8PANELS_EQUIPSRV.pck | 11 +-- 4 files changed, 148 insertions(+), 38 deletions(-) create mode 100644 app/panels/eqs_prfrm/hooks.js diff --git a/app/panels/eqs_prfrm/eqs_prfrm.js b/app/panels/eqs_prfrm/eqs_prfrm.js index f49142b..01e4014 100644 --- a/app/panels/eqs_prfrm/eqs_prfrm.js +++ b/app/panels/eqs_prfrm/eqs_prfrm.js @@ -8,7 +8,7 @@ //--------------------- import React, { useState, useContext, useCallback, useEffect } from "react"; //Классы React -import { Grid, Paper, Box } from "@mui/material"; //Интерфейсные компоненты +import { Box } from "@mui/material"; //Интерфейсные компоненты import { P8PDataGrid, P8P_DATA_GRID_SIZE } from "../../components/p8p_data_grid"; //Таблица данных import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения import { BackEndСtx } from "../../context/backend"; //Контекст взаимодействия с сервером @@ -18,6 +18,33 @@ import { headCellRender, dataCellRender, groupCellRender, DIGITS_REG_EXP, MONTH_ import { TEXTS } from "../../../app.text"; //Тектовые ресурсы и константы import { Filter } from "./filter"; //Компонент фильтра import { FilterDialog } from "./filter_dialog"; //Компонент диалогового окна фильтра отбора +import { useWindowResize } from "./hooks"; //Пользовательские хуки + +//--------- +//Константы +//--------- + +//Высота меню Парус (пиксели) +const pxOuterMenuH = 53; +//Высота заголовка панели (пиксели) +const pxPanelHeaderH = 64; +//Минимальная ширина таблицы (пиксели) +const minGridW = 800; +//Минимальная высота таблицы (пиксели) +const minGridH = 200; + +//Стили +const STYLES = { + BOX_ROW: { display: "flex", justifyContent: "center", alignItems: "center" }, + GRID_PADDING: { paddingTop: 1, paddingBottom: 1 }, + GRID_SIZES: (width, height) => ({ + padding: "0px", + minWidth: minGridW, + maxWidth: width * 0.975 > minGridW ? width * 0.975 : minGridW, + minHeight: minGridH, + maxHeight: (height - pxOuterMenuH - pxPanelHeaderH) * 0.975 > minGridH ? (height - pxOuterMenuH - pxPanelHeaderH) * 0.975 : minGridH + }) +}; //----------- //Тело модуля @@ -31,6 +58,8 @@ const EqsPrfrm = () => { columnsDef: [], groups: [], rows: [], + fixedHeader: false, + fixedColumns: 0, reload: false }); @@ -39,6 +68,7 @@ const EqsPrfrm = () => { isOpen: false, isDefault: false, isSetByUser: false, + needSave: false, values: { belong: "", prodObj: "", @@ -128,6 +158,8 @@ const EqsPrfrm = () => { ...pv, columnsDef: data.XCOLUMNS_DEF ? [...data.XCOLUMNS_DEF] : pv.columnsDef, rows: [...(data.XROWS || [])], + fixedHeader: data.XDATA_GRID.fixedHeader, + fixedColumns: data.XDATA_GRID.fixedColumns, groups: [...(data.XGROUPS || [])], dataLoaded: true, reload: false @@ -135,7 +167,7 @@ const EqsPrfrm = () => { } }, [dataGrid.reload, filter, executeStored]); - //Загрузка значений фильра по умолчанию + //Загрузка значений фильтра по умолчанию const loadDefaultFilter = useCallback(async () => { const data = await executeStored({ stored: "PKG_P8PANELS_EQUIPSRV.GET_DEFAULT_FP", @@ -148,6 +180,17 @@ const EqsPrfrm = () => { })); }, [executeStored]); + //Загрузка значений фильтра из локального хранилища браузера + const loadLocalFilter = useCallback(async () => { + let vs = filter.values; + Object.keys(vs).map(function (k) { + vs[k] = + k == "fromMonth" || k == "fromYear" || k == "toMonth" || k == "toYear" ? Number(localStorage.getItem(k)) : localStorage.getItem(k); + }); + setFilter(pv => ({ ...pv, isDefault: true, values: { ...vs } })); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + //Отбор документа (ТОиР или Ремонтных ведомостей) по ячейке даты const showEquipSrv = async ({ date, workType, info }) => { const [techName, servKind] = info.split("_"); @@ -180,7 +223,7 @@ const EqsPrfrm = () => { const setFilterOpen = isOpen => setFilter(pv => ({ ...pv, isOpen })); //Установить значение фильтра - const setFilterValues = values => setFilter(pv => ({ ...pv, isSetByUser: true, values: { ...values } })); + const setFilterValues = values => setFilter(pv => ({ ...pv, isSetByUser: true, needSave: true, values: { ...values } })); //Отработка события скрытия/раскрытия ячейки даты const handleClick = (e, ref) => { @@ -223,16 +266,26 @@ const EqsPrfrm = () => { //eslint-disable-next-line react-hooks/exhaustive-deps }, [refIsDeprecated]); + //При закрытии панели + useEffect(() => { + filter.needSave + ? window.addEventListener("beforeunload", function () { + Object.keys(filter.values).map(function (k) { + localStorage.setItem(k, filter.values[k]); + }); + }) + : null; + }, [filter.needSave, filter.values]); + //При загрузке фильтра по умолчанию useEffect(() => { if (filter.isDefault) setFilterOpen(true); }, [filter.isDefault]); - //При подключении к страницк + //При подключении к странице useEffect(() => { - loadDefaultFilter(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + localStorage.getItem("belong") ? loadLocalFilter() : loadDefaultFilter(); + }, [loadDefaultFilter, loadLocalFilter]); //При открытии диалога фильтра const handleFilterClick = () => setFilterOpen(true); @@ -246,32 +299,37 @@ const EqsPrfrm = () => { //При закрытии диалога фильтра const handleFilterCancel = () => setFilterOpen(false); + //Состояние ширины и высоты рабочей области окна + const [width, height] = useWindowResize(); + //Генерация содержимого return (
{filter.isOpen ? : null} {dataGrid.dataLoaded ? ( - - - - - headCellRender({ ...prms }, handleClick)} - dataCellRender={prms => dataCellRender({ ...prms }, showEquipSrv)} - groupCellRender={prms => groupCellRender({ ...prms })} - showCellRightBorder={true} - /> - - - - + + headCellRender({ ...prms }, handleClick)} + dataCellRender={prms => dataCellRender({ ...prms }, width * 0.2, showEquipSrv)} + groupCellRender={prms => groupCellRender({ ...prms })} + showCellRightBorder={true} + /> + ) : null}
); diff --git a/app/panels/eqs_prfrm/hooks.js b/app/panels/eqs_prfrm/hooks.js new file mode 100644 index 0000000..4637885 --- /dev/null +++ b/app/panels/eqs_prfrm/hooks.js @@ -0,0 +1,36 @@ +/* + Парус 8 - Панели мониторинга - ТОиР - Выполнение работ + Пользовательские хуки +*/ + +//--------------------- +//Подключение библиотек +//--------------------- + +import { useState, useLayoutEffect } from "react"; //Классы React + +//----------- +//Тело модуля +//----------- + +//Хук для отработки изменений ширины и высоты рабочей области окна +const useWindowResize = () => { + //Состояние размера рабочей области + const [size, setSize] = useState([0, 0]); + //При изменении размера + useLayoutEffect(() => { + function updateSize() { + setSize([document.documentElement.clientWidth, document.documentElement.clientHeight]); + } + window.addEventListener("resize", updateSize); + updateSize(); + return () => window.removeEventListener("resize", updateSize); + }, []); + return size; +}; + +//-------------- +//Интерфейс хука +//-------------- + +export { useWindowResize }; diff --git a/app/panels/eqs_prfrm/layouts.js b/app/panels/eqs_prfrm/layouts.js index 82b08cb..c854873 100644 --- a/app/panels/eqs_prfrm/layouts.js +++ b/app/panels/eqs_prfrm/layouts.js @@ -20,7 +20,7 @@ export const MONTH_NAME_REG_EXP = /_\d{4}_\d{1,2}/; export const DAY_NAME_REG_EXP = /_\d{4}_\d{1,2}_\d{1,2}/; //Стили -export const STYLES = { +const STYLES = { HIDE_CELL_STYLE: { display: "none" }, HCR_MAIN_STYLE: { border: "1px solid rgba(0, 0, 0)", textAlign: "center" }, HCR_DATE_STYLE: { padding: "5px", minWidth: "25px", maxWidth: "25px" }, @@ -31,7 +31,12 @@ export const STYLES = { DCR_FACT_NOT_RELATED_CELL_STYLE: { cursor: "pointer", backgroundColor: "crimson", border: "1px solid rgba(0, 0, 0) !important" }, DCR_DOUBLE_CELL: { padding: "unset" }, DCR_DOUBLE_CELL_GRID_ITEM: backgroundColor => ({ cursor: "pointer", backgroundColor }), - HIDDEN_PARAGRAPH: { display: "none" } + HIDDEN_PARAGRAPH: { display: "none" }, + STICKY_WIDTH_UNSET: { minWidth: "unset", maxWidth: "unset" }, + FIRST_STICKY_CELL: { left: "0px" }, + OBJINFO_WIDTH: width => ({ minWidth: width, maxWidth: width }), + OBJINFO_WRKNAME_WIDTH: width => ({ minWidth: width * 0.6, maxWidth: width * 0.6 }), + WRKTYPE_WIDTH: width => ({ left: width * 0.6, minWidth: width - width * 0.4, maxWidth: width - width * 0.4 }) }; //----------- @@ -71,7 +76,11 @@ export const headCellRender = ({ columnDef }, hClick) => { //Объединение нужных колонок и строк if (columnDef.name == "SINFO" || columnDef.name == "SWRKTYPE") { cellProps = { colSpan: 2 }; - if (columnDef.name == "SINFO") cellProps = { ...cellProps, rowSpan: 2 }; + cellStyle = { ...cellStyle, ...STYLES.STICKY_WIDTH_UNSET }; + if (columnDef.name == "SINFO") { + cellProps = { ...cellProps, rowSpan: 2 }; + cellStyle = { ...cellStyle, ...STYLES.FIRST_STICKY_CELL }; + } } //Изменения в заголовках с датами if (columnDef.visible && DAY_NAME_REG_EXP.test(columnDef.name)) { @@ -82,7 +91,7 @@ export const headCellRender = ({ columnDef }, hClick) => { }; //Генерация представления ячейки -export const dataCellRender = ({ row, columnDef }, showEquipSrv) => { +export const dataCellRender = ({ row, columnDef }, width, showEquipSrv) => { let curParent = ""; let cellDate; let cellStyle = STYLES.DCR_MAIN_STYLE; @@ -93,10 +102,10 @@ export const dataCellRender = ({ row, columnDef }, showEquipSrv) => { //Ячейка "Информация по объекту ремонта" if (columnDef.name == "SOBJINFO") { cellProps = { colSpan: 2 }; - cellStyle = { ...cellStyle, ...STYLES.DCR_OBJECT_INFO_STYLE }; + cellStyle = { ...cellStyle, ...STYLES.DCR_OBJECT_INFO_STYLE, ...STYLES.OBJINFO_WIDTH(width) }; } //Ячейка "Тип работ" - if (columnDef.name == "SWRKTYPE") cellStyle = STYLES.HIDE_CELL_STYLE; + if (columnDef.name == "SWRKTYPE") cellStyle = { ...STYLES.HIDE_CELL_STYLE }; //Ячейки колонок месяцев if (columnDef.parent == "" && columnDef.expandable == true && columnDef.expanded == false) { curParent = columnDef.name; @@ -118,13 +127,17 @@ export const dataCellRender = ({ row, columnDef }, showEquipSrv) => { } //Строка плана по объекту ремонта if (columnDef.name == "SOBJINFO" && row["SWRKTYPE"] == "План") { - cellStyle = { ...cellStyle }; + cellStyle = { ...cellStyle, ...STYLES.FIRST_STICKY_CELL, ...STYLES.OBJINFO_WRKNAME_WIDTH(width) }; cellProps = { rowSpan: 2 }; } //Строка факта по объекту ремонта if (columnDef.name == "SOBJINFO" && row["SWRKTYPE"] == "Факт") { cellStyle = { display: "none" }; } + //Ячейка план/факт + if (columnDef.name == "SWRKTYPE") { + cellStyle = { ...cellStyle, ...STYLES.WRKTYPE_WIDTH(width) }; + } //Закрашивание ячеек switch (row[columnDef.name]) { case "blue": diff --git a/db/PKG_P8PANELS_EQUIPSRV.pck b/db/PKG_P8PANELS_EQUIPSRV.pck index e748fc5..e11f20d 100644 --- a/db/PKG_P8PANELS_EQUIPSRV.pck +++ b/db/PKG_P8PANELS_EQUIPSRV.pck @@ -399,21 +399,24 @@ create or replace package body PKG_P8PANELS_EQUIPSRV as /* Определим дату конца периода */ NTODATE := LAST_DAY(TO_DATE('01.' || LPAD(TO_CHAR(NTOMONTH), 2, '0') || '.' || TO_CHAR(NTOYEAR), 'dd.mm.yyyy')); /* Инициализируем таблицу данных */ - RDG := PKG_P8PANELS_VISUAL.TDATA_GRID_MAKE(); + RDG := PKG_P8PANELS_VISUAL.TDATA_GRID_MAKE(BFIXED_HEADER => true, NFIXED_COLUMNS => 2); /* Формируем структуру заголовка */ PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG, SNAME => 'SOBJINFO', SCAPTION => 'Информация по объекту ремонта', - SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR); + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR, + NWIDTH => 80); PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG, SNAME => 'SINFO', SCAPTION => 'Объект ремонта', - SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR); + SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR, + NWIDTH => 80); PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG, SNAME => 'SWRKTYPE', SCAPTION => 'Тип работ', SDATA_TYPE => PKG_P8PANELS_VISUAL.SDATA_TYPE_STR, - SPARENT => 'SINFO'); + SPARENT => 'SINFO', + NWIDTH => 80); PKG_P8PANELS_VISUAL.TDATA_GRID_ADD_COL_DEF(RDATA_GRID => RDG, SNAME => 'NRN', SCAPTION => 'Рег. номер',