From ddc2bd94919db51aa4f71e7fea26e56c1473d9fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8C=D1=8F=D1=81=20=D0=A1=D1=83=D0=BB=D1=82?= =?UTF-8?q?=D0=B0=D0=BD=D0=BE=D0=B2?= Date: Sun, 6 Sep 2026 15:08:23 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D0=BB=D1=8F=20=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D1=84=D0=B8=D0=BB=D1=8F=20=D1=81=20options.readOnly:=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=BF=D1=80=D0=B5=D1=82=20=D1=80=D0=B5=D0=B4=D0=B0=D0=BA?= =?UTF-8?q?=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=C2=AB?= =?UTF-8?q?=D0=9E=D1=86=D0=B5=D0=BD=D0=BA=D0=B8=C2=BB=20=D0=B8=20=C2=AB?= =?UTF-8?q?=D0=A1=D1=80=D0=B5=D0=B4=D0=BD=D0=B5=D0=B9=20=D0=BE=D1=86=D0=B5?= =?UTF-8?q?=D0=BD=D0=BA=D0=B8=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - UI: read-only поля отображаются текстом (у history-number остаётся кнопка графика), исключены из сохранения; кнопка «Сохранить» скрыта, если все поля вкладки read-only - Сервер: POST/PATCH field-values профиля отклоняют запись в поле с options.readOnly (400); автоматизации пишут через storage напрямую и не затрагиваются - Данные: options.readOnly=true у полей «Оценка» и «Средняя оценка» --- client/src/pages/UserProfilePage.tsx | 51 ++++++++++++++++++---------- server/routes/user-profile.routes.ts | 18 ++++++++++ 2 files changed, 52 insertions(+), 17 deletions(-) diff --git a/client/src/pages/UserProfilePage.tsx b/client/src/pages/UserProfilePage.tsx index 4cc1ac5..1262e4b 100644 --- a/client/src/pages/UserProfilePage.tsx +++ b/client/src/pages/UserProfilePage.tsx @@ -334,26 +334,33 @@ function HistoryTab({ auditLog }: { auditLog: AuditLogEntry[] }) { // Поле history-number: обычный ввод значения + кнопка с графиком истории оценок. // График доступен всегда (просмотр), редактирование значения — как у остальных полей. +// readOnly (options.readOnly): ввод недоступен — только значение текстом и график. function HistoryNumberFieldInput({ field, value, onChange, userId, + readOnly, }: { field: UserProfileField; value: any; onChange: (val: any) => void; userId: number; + readOnly?: boolean; }) { const [historyOpen, setHistoryOpen] = useState(false); return (
- onChange(e.target.value)} - placeholder={field.placeholder} - required={field.isRequired} - /> + {readOnly ? ( + {value ?? '—'} + ) : ( + onChange(e.target.value)} + placeholder={field.placeholder} + required={field.isRequired} + /> + )}
))} - {canEdit && ( + {canEdit && tabFields.some((f) => !f.options?.readOnly) && (