From 6d92d7f9c1a9a889e0cfa51007cd686593aec42e Mon Sep 17 00:00:00 2001 From: "gorbenko.pavel" Date: Tue, 1 Sep 2026 17:06:06 +0500 Subject: [PATCH] =?UTF-8?q?fix(approval):=20=D0=BA=D0=BE=D0=BB=D0=BE=D0=BD?= =?UTF-8?q?=D0=BA=D0=B8=20SLA=20=D0=B2=20=D0=BC=D0=B0=D0=BD=D0=B8=D1=84?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D0=B0=D1=85=20=D1=81=D0=BE=D0=B3=D0=BB=D0=B0?= =?UTF-8?q?=D1=81=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20+=20=D1=87=D0=B8?= =?UTF-8?q?=D1=82=D0=B0=D0=B5=D0=BC=D1=8B=D0=B9=20=D1=82=D0=B5=D0=BA=D1=81?= =?UTF-8?q?=D1=82=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Маршрут «Заявки на услуги» падал с 400 «Поле или свойство SLAhours не существует»: общий ApprovalListService читает и пишет SLAhours/ AskOverdueReason у ЛЮБОЙ формы, а в манифесте согласования их не было. Манифест копировался с TmcTransfer, где их тоже нет — там на тенанте колонки почему-то есть, поэтому не проявлялось, но следующая партиция списка создалась бы уже сломанной. Добавил обеим формам. Текст ошибки при этом выводился как «Поле…»: useMatrixEditor и useRequestTypeId клали в state сырой err.message, а PnPjs кладёт туда тело ответа SharePoint целиком, где кириллица — \u-escape-последовательности. Пропустил оба через friendlyErrorMessage, который для этого и написан (он уже используется формами). Co-Authored-By: Claude Opus 5 --- .../forms/ServiceRequest/approval/provisioning.json | 2 ++ .../forms/TmcTransfer/approval/provisioning.json | 2 ++ .../requestPortal/shared/approval/useMatrixEditor.ts | 7 ++++++- .../requestPortal/shared/approval/useRequestTypeId.ts | 5 ++++- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/webparts/requestPortal/forms/ServiceRequest/approval/provisioning.json b/src/webparts/requestPortal/forms/ServiceRequest/approval/provisioning.json index 18bb7b5..eafb929 100644 --- a/src/webparts/requestPortal/forms/ServiceRequest/approval/provisioning.json +++ b/src/webparts/requestPortal/forms/ServiceRequest/approval/provisioning.json @@ -9,6 +9,8 @@ { "internalName": "StepOrder", "title": "Порядок", "type": "Number" }, { "internalName": "AllowReassignToOtherApprovers", "title": "Можно перепоручать", "type": "Boolean" }, { "internalName": "Phase", "title": "Фаза", "type": "Choice", "choices": ["Согласование", "Исполнение"] }, + { "internalName": "SLAhours", "title": "SLA, часов", "type": "Number" }, + { "internalName": "AskOverdueReason", "title": "Опрос причины просрочки", "type": "Boolean" }, { "internalName": "DelegatedBy", "title": "Кем переназначено", "type": "User", "userSelectionMode": "PeopleOnly" } ] } diff --git a/src/webparts/requestPortal/forms/TmcTransfer/approval/provisioning.json b/src/webparts/requestPortal/forms/TmcTransfer/approval/provisioning.json index 2ad169b..3ebe166 100644 --- a/src/webparts/requestPortal/forms/TmcTransfer/approval/provisioning.json +++ b/src/webparts/requestPortal/forms/TmcTransfer/approval/provisioning.json @@ -9,6 +9,8 @@ { "internalName": "StepOrder", "title": "Порядок", "type": "Number" }, { "internalName": "AllowReassignToOtherApprovers", "title": "Можно перепоручать", "type": "Boolean" }, { "internalName": "Phase", "title": "Фаза", "type": "Choice", "choices": ["Согласование", "Исполнение"] }, + { "internalName": "SLAhours", "title": "SLA, часов", "type": "Number" }, + { "internalName": "AskOverdueReason", "title": "Опрос причины просрочки", "type": "Boolean" }, { "internalName": "DelegatedBy", "title": "Кем переназначено", "type": "User", "userSelectionMode": "PeopleOnly" } ] } diff --git a/src/webparts/requestPortal/shared/approval/useMatrixEditor.ts b/src/webparts/requestPortal/shared/approval/useMatrixEditor.ts index 46c5b87..9d516a2 100644 --- a/src/webparts/requestPortal/shared/approval/useMatrixEditor.ts +++ b/src/webparts/requestPortal/shared/approval/useMatrixEditor.ts @@ -1,4 +1,5 @@ import { useState, useEffect } from 'react'; +import { friendlyErrorMessage } from '../diagnostics'; import { IMatrixRow } from './models/IMatrixRow'; import { ISiteUser } from './models/ISiteUser'; @@ -175,7 +176,11 @@ export function useMatrixEditor( }) .catch((err: Error) => { if (!active) return; - setError(err.message); + // Через friendlyErrorMessage, а не err.message: PnPjs кладёт в message + // тело ответа SharePoint целиком, и кириллица в нём остаётся + // \u-escape-последовательностями — пользователь видел «Поле или + // свойство…» набором «Поле». + setError(friendlyErrorMessage(err)); setLoading(false); }); return () => { diff --git a/src/webparts/requestPortal/shared/approval/useRequestTypeId.ts b/src/webparts/requestPortal/shared/approval/useRequestTypeId.ts index 6880679..940b20e 100644 --- a/src/webparts/requestPortal/shared/approval/useRequestTypeId.ts +++ b/src/webparts/requestPortal/shared/approval/useRequestTypeId.ts @@ -1,5 +1,6 @@ import { useEffect, useState } from 'react'; import type { WebPartContext } from '@microsoft/sp-webpart-base'; +import { friendlyErrorMessage } from '../diagnostics'; import { getRequestTypeIdByPageUrl } from './approvalRoute.service'; export interface IRequestTypeIdState { @@ -33,7 +34,9 @@ export function useRequestTypeId(context: WebPartContext, pageUrl: string): IReq }) .catch((e: Error) => { if (alive) { - setError(e.message); + // См. useMatrixEditor: сырой message от PnPjs/SharePoint показывает + // кириллицу \u-escape-последовательностями. + setError(friendlyErrorMessage(e)); setLoading(false); } });