WEBAPP: "Редактор настроек РО" - перевод диалогов на типовые компоненты P8PDialog и P8PInput

This commit is contained in:
Mikhail Chechnev 2025-07-21 10:13:32 +03:00
parent 3f539065ba
commit a3fd089452
8 changed files with 38 additions and 258 deletions

View File

@ -10,7 +10,7 @@
import React from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Typography, List, ListItem } from "@mui/material"; //Интерфейсные элементы
import { Form } from "./form"; //Типовая форма
import { P8PDialog } from "../../../components/p8p_dialog"; //Типовой диалог
//---------
//Константы
@ -53,7 +53,7 @@ const DialogHelp = ({ onClose }) => {
//Генерация содержимого
return (
<Form title={"Информация"} onClose={handleClose}>
<P8PDialog title={"Информация"} onClose={handleClose}>
<Typography>Карточки показателей содержат сокращенную информацию о типе состава показателя. Список сокращений:</Typography>
<List disablePadding={true}>
<HelpListItem name={"fx"} desc={"формула"} />
@ -71,7 +71,7 @@ const DialogHelp = ({ onClose }) => {
<HelpListItem name={"ДПНП"} desc={"декларация по налогу на прибыль"} />
<HelpListItem name={"РО"} desc={"регламентированный отчет"} />
</List>
</Form>
</P8PDialog>
);
};

View File

@ -10,7 +10,7 @@
import React from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { useDictionary } from "../hooks"; //Кастомные хуки
import { Form } from "./form"; //Типовая форма
import { P8PDialog } from "../../../components/p8p_dialog"; //Типовой диалог
//-----------
//Тело модуля
@ -67,15 +67,15 @@ const DialogMarkIU = ({
//Генерация содержимого
return (
<Form
<P8PDialog
title={`${insert === true ? "Добавление" : "Исправление"} показателя`}
fields={[
{ elementCode: "code", elementValue: code, labelText: "Мнемокод" },
{ elementCode: "name", elementValue: name, labelText: "Наименование" },
{ elementCode: "rowCode", elementValue: rowCode, labelText: "Строка", dictionary: selectRow },
{ elementCode: "rowVersion", elementValue: rowVersion, labelText: "Редакция строки", disabled: true },
{ elementCode: "columnCode", elementValue: columnCode, labelText: "Графа", dictionary: selectColumn },
{ elementCode: "columnVersion", elementValue: columnVersion, labelText: "Редакция графы", disabled: true }
inputs={[
{ name: "code", value: code, label: "Мнемокод" },
{ name: "name", value: name, label: "Наименование" },
{ name: "rowCode", value: rowCode, label: "Строка", dictionary: selectRow },
{ name: "rowVersion", value: rowVersion, label: "Редакция строки", disabled: true },
{ name: "columnCode", value: columnCode, label: "Графа", dictionary: selectColumn },
{ name: "columnVersion", value: columnVersion, label: "Редакция графы", disabled: true }
]}
onOk={handleOk}
onCancel={handleCancel}

View File

@ -9,7 +9,7 @@
import React from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Form } from "./form"; //Типовая форма
import { P8PDialog } from "../../../components/p8p_dialog"; //Типовой диалог
import { COL_ROW_ORDER } from "../common"; //Обще стили и константы
//-----------
@ -26,11 +26,11 @@ const DialogOrder = ({ rowOrder = 0, columnOrder = 0, onOk, onCancel }) => {
//Генерация содержимого
return (
<Form
<P8PDialog
title={"Сортировка"}
fields={[
{ elementCode: "rowOrder", elementValue: rowOrder, labelText: "Строки", list: COL_ROW_ORDER },
{ elementCode: "columnOrder", elementValue: columnOrder, labelText: "Графы", list: COL_ROW_ORDER }
inputs={[
{ name: "rowOrder", value: rowOrder, label: "Строки", list: COL_ROW_ORDER },
{ name: "columnOrder", value: columnOrder, label: "Графы", list: COL_ROW_ORDER }
]}
onOk={handleOk}
onCancel={handleCancel}

View File

@ -9,7 +9,7 @@
import React from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Form } from "./form"; //Типовая форма
import { P8PDialog } from "../../../components/p8p_dialog"; //Типовой диалог
//-----------
//Тело модуля
@ -25,11 +25,11 @@ const DialogSectionIU = ({ code = "", name = "", insert = true, onOk, onCancel }
//Генерация содержимого
return (
<Form
<P8PDialog
title={`${insert === true ? "Добавление" : "Исправление"} раздела`}
fields={[
{ elementCode: "code", elementValue: code, labelText: "Мнемокод" },
{ elementCode: "name", elementValue: name, labelText: "Наименование" }
inputs={[
{ name: "code", value: code, label: "Мнемокод" },
{ name: "name", value: name, label: "Наименование" }
]}
onOk={handleOk}
onCancel={handleCancel}

View File

@ -1,76 +0,0 @@
/*
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
Компонент панели: Форма
*/
//---------------------
//Подключение библиотек
//---------------------
import React, { useEffect, useState } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Dialog, DialogTitle, DialogContent, DialogActions, Button } from "@mui/material"; //Интерфейсные компоненты
import { BUTTONS } from "../../../../app.text"; //Общие текстовые ресурсы
import { FORM_FILED, FormField } from "./form_field"; //Элемент формы
//-----------
//Тело модуля
//-----------
//Форма
const Form = ({ title, fields = [], children, onOk, onCancel, onClose }) => {
//Состояние формы
const [state, setState] = useState({});
//При изменении элемента формы
const handleFieldChange = (name, value) => setState(pv => ({ ...pv, [name]: value }));
//При нажатии на "ОК" формы
const handleOk = () => onOk && onOk(state);
//При нажатии на "Отмена" формы
const handleCancel = () => onCancel && onCancel();
//При нажатии на "Закрыть" формы
const handleClose = () => (onClose ? onClose() : onCancel ? onCancel() : null);
//При подключении к старнице
useEffect(() => {
setState(fields.reduce((res, f) => ({ ...res, [f.elementCode]: f.elementValue == undefined ? null : f.elementValue }), {}));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
//Формирование представления
return (
<Dialog onClose={handleClose} open>
<DialogTitle>{title}</DialogTitle>
<DialogContent>
{fields.map((f, i) => (
<FormField key={i} {...f} elementValue={state[f.elementCode]} formValues={state} onChange={handleFieldChange} />
))}
{children}
</DialogContent>
<DialogActions>
{onOk && <Button onClick={handleOk}>{BUTTONS.OK}</Button>}
{onCancel && <Button onClick={handleCancel}>{BUTTONS.CANCEL}</Button>}
{onClose && <Button onClick={handleClose}>{BUTTONS.CLOSE}</Button>}
</DialogActions>
</Dialog>
);
};
//Контроль свойств - Форма
Form.propTypes = {
title: PropTypes.string.isRequired,
fields: PropTypes.arrayOf(PropTypes.shape(FORM_FILED)),
children: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)]),
onOk: PropTypes.func,
onCancel: PropTypes.func,
onClose: PropTypes.func
};
//----------------
//Интерфейс модуля
//----------------
export { Form };

View File

@ -1,149 +0,0 @@
/*
Парус 8 - Панели мониторинга - РО - Редактор настройки регламентированного отчёта
Компонент панели: Поле ввода формы
*/
//---------------------
//Подключение библиотек
//---------------------
import React, { useState, useEffect } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Box, Icon, Input, InputAdornment, FormControl, Select, InputLabel, MenuItem, IconButton, Autocomplete, TextField } from "@mui/material"; //Интерфейсные компоненты
//---------
//Константы
//---------
//Формат свойств поля формы
const FORM_FILED = {
elementCode: PropTypes.string.isRequired,
elementValue: PropTypes.oneOfType([PropTypes.number, PropTypes.string, PropTypes.instanceOf(Date)]),
labelText: PropTypes.string.isRequired,
onChange: PropTypes.func,
dictionary: PropTypes.func,
list: PropTypes.array,
type: PropTypes.string,
freeSolo: PropTypes.bool,
disabled: PropTypes.bool,
formValues: PropTypes.object
};
//-----------
//Тело модуля
//-----------
//Поле ввода формы
const FormField = ({
elementCode,
elementValue,
labelText,
onChange,
dictionary,
list,
type,
freeSolo = false,
disabled = false,
formValues,
...other
}) => {
//Значение элемента
const [value, setValue] = useState(elementValue);
//При получении нового значения из вне
useEffect(() => {
setValue(elementValue);
}, [elementValue]);
//Выбор значения из словаря
const handleDictionaryClick = () => dictionary && dictionary(formValues, res => (res ? res.map(i => handleChangeByName(i.name, i.value)) : null));
//Изменение значения элемента (по событию)
const handleChange = e => {
setValue(e.target.value);
if (onChange) onChange(e.target.name, e.target.value);
};
//Изменение значения элемента (по имени и значению)
const handleChangeByName = (name, value) => {
if (name === elementCode) setValue(value);
if (onChange) onChange(name, value);
};
//Генерация содержимого
return (
<Box p={1}>
<FormControl variant="standard" fullWidth {...other}>
{list ? (
freeSolo ? (
<Autocomplete
id={elementCode}
name={elementCode}
freeSolo
disabled={disabled}
inputValue={value ? value : ""}
onChange={(event, newValue) => handleChangeByName(elementCode, newValue)}
onInputChange={(event, newInputValue) => handleChangeByName(elementCode, newInputValue)}
options={list}
renderInput={params => <TextField {...params} label={labelText} name={elementCode} variant={"standard"} />}
/>
) : (
<>
<InputLabel id={`${elementCode}Lable`} shrink>
{labelText}
</InputLabel>
<Select
labelId={`${elementCode}Lable`}
id={elementCode}
name={elementCode}
label={labelText}
value={[undefined, null].includes(value) ? "" : value}
onChange={handleChange}
disabled={disabled}
displayEmpty
>
{list.map((item, i) => (
<MenuItem key={i} value={[undefined, null].includes(item.value) ? "" : item.value}>
{item.name}
</MenuItem>
))}
</Select>
</>
)
) : (
<>
<InputLabel {...(type == "date" ? { shrink: true } : {})} htmlFor={elementCode}>
{labelText}
</InputLabel>
<Input
id={elementCode}
name={elementCode}
value={value ? value : ""}
endAdornment={
dictionary ? (
<InputAdornment position="end">
<IconButton aria-label={`${elementCode} select`} onClick={handleDictionaryClick} edge="end">
<Icon>list</Icon>
</IconButton>
</InputAdornment>
) : null
}
{...(type ? { type } : {})}
onChange={handleChange}
disabled={disabled}
/>
</>
)}
</FormControl>
</Box>
);
};
//Контроль свойств - Поле ввода формы
FormField.propTypes = FORM_FILED;
//----------------
//Интерфейс модуля
//----------------
export { FORM_FILED, FormField };

View File

@ -103,14 +103,14 @@ const Marks = ({ marks, order, marksLoading, marksInit, onRefresh, onMarkInsert,
//При переходе к составу показателя
const handleMarkCnOpen = (mark, constitution) => showMarkCn(mark, constitution, res => res.success && handleRefresh());
//При закрытии формы добавления/исправления по "ОК"
const handleIUFormOk = values => {
//При закрытии диалога добавления/исправления по "ОК"
const handleIUDialogOk = values => {
if (modMark === true) onMarkInsert && onMarkInsert(values, res => res && setModMark(null));
else onMarkUpdate && onMarkUpdate({ ...modMark, ...values }, res => res && setModMark(null));
};
//При закрытии формы добавления/исправления по "Отмена"
const handleIUFormCancel = () => setModMark(null);
//При закрытии диалога добавления/исправления по "Отмена"
const handleIUDialogCancel = () => setModMark(null);
//Формирование представления
return (
@ -118,7 +118,12 @@ const Marks = ({ marks, order, marksLoading, marksInit, onRefresh, onMarkInsert,
{dialogOrder && <DialogOrder {...order} onOk={handleOrderChange} onCancel={toggleOrderDialog} />}
{dialogHelp && <DialogHelp onClose={toggleHelpDialog} />}
{modMark && (
<DialogMarkIU {...(modMark === true ? {} : modMark)} insert={modMark === true} onOk={handleIUFormOk} onCancel={handleIUFormCancel} />
<DialogMarkIU
{...(modMark === true ? {} : modMark)}
insert={modMark === true}
onOk={handleIUDialogOk}
onCancel={handleIUDialogCancel}
/>
)}
{marksInit &&
(marks ? (

View File

@ -118,15 +118,15 @@ const Sections = ({ conf, onSectionChange, onSectionCountChange }) => {
//При удалении раздела настройки
const handleSectionDelete = section => showMsgWarn("Удалить раздел?", () => deleteSection(section));
//При закрытии формы добавления/исправления по "ОК"
const handleIUFormOk = async values => {
//При закрытии диалога добавления/исправления по "ОК"
const handleIUDialogOk = async values => {
if (modSection === true) await insertSection({ conf, ...values });
else await updateSection({ rn: modSection.NRN, ...values });
setModSection(null);
};
//При закрытии формы добавления/исправления по "Отмена"
const handleIUFormCancel = () => setModSection(null);
//При закрытии диалога добавления/исправления по "Отмена"
const handleIUDialogCancel = () => setModSection(null);
//При изменении состава разделов
useEffect(() => {
@ -155,8 +155,8 @@ const Sections = ({ conf, onSectionChange, onSectionCountChange }) => {
code={modSection?.SCODE}
name={modSection?.SNAME}
insert={modSection === true}
onOk={handleIUFormOk}
onCancel={handleIUFormCancel}
onOk={handleIUDialogOk}
onCancel={handleIUDialogCancel}
/>
)}
{sections.length > 0 ? (