From 01e128c22d5f39afe46544819c3ea278b4052a4f Mon Sep 17 00:00:00 2001 From: GGlamer <52128225+Gamer201760@users.noreply.github.com> Date: Sun, 27 Sep 2026 22:29:33 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D1=85=20=D1=81=D0=BB=D1=83=D0=B6=D0=B1=20=D0=BD=D0=B0=20=D0=90?= =?UTF-8?q?=D0=A0=D0=9C=20=D0=94=D0=94=D0=A1=20=D0=B1=D0=B5=D0=B7=20=D0=BF?= =?UTF-8?q?=D1=83=D1=81=D1=82=D0=BE=D0=B3=D0=BE=20=D0=B7=D0=BD=D0=B0=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F,=20=D0=BF=D0=B8=D0=BA=D0=B5=D1=80=20?= =?UTF-8?q?=D1=81=20=D0=BB=D0=B8=D0=BC=D0=B8=D1=82=D0=BE=D0=BC=2020=20?= =?UTF-8?q?=D0=B8=20=D0=B1=D0=B5=D0=B7=20=D1=81=D0=BB=D1=83=D0=B6=D0=B1=20?= =?UTF-8?q?=D0=B8=D0=B7=20notify?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/features/kio-card/KioCard.tsx | 30 ++++++++++++++++------ frontend/src/pages/dds/Dds.tsx | 7 ++++- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/frontend/src/features/kio-card/KioCard.tsx b/frontend/src/features/kio-card/KioCard.tsx index 2e37fa4..6ca9c4b 100644 --- a/frontend/src/features/kio-card/KioCard.tsx +++ b/frontend/src/features/kio-card/KioCard.tsx @@ -19,6 +19,7 @@ interface Props { export function KioCard({ state, required = [], readOnly = false, referenceArm = false, onChange }: Props) { const dds = display(state, "dds") as string | null; const incidentGroup = display(state, "incident_group") as number | null; + const notify = (display(state, "notify") as string[] | null) ?? []; const groups = visibleGroups(dds); const section = (group: FieldGroup) => (
@@ -38,6 +39,7 @@ export function KioCard({ state, required = [], readOnly = false, referenceArm = readOnly={readOnly || field.readOnly} referenceArm={referenceArm} incidentGroup={incidentGroup} + notify={notify} onChange={onChange} /> ))} @@ -60,7 +62,7 @@ export function KioCard({ state, required = [], readOnly = false, referenceArm = } function Row({ - field, value, pending, required, readOnly, referenceArm, incidentGroup, onChange, + field, value, pending, required, readOnly, referenceArm, incidentGroup, notify, onChange, }: { field: Field; value: unknown; @@ -69,6 +71,7 @@ function Row({ readOnly?: boolean; referenceArm: boolean; incidentGroup: number | null; + notify: string[]; onChange?: (path: string, value: unknown) => void; }) { const empty = value === null || value === undefined || value === "" || (Array.isArray(value) && value.length === 0); @@ -87,7 +90,7 @@ function Row({ {readOnly ? ( {formatValue(value, field)} ) : ( - + )} @@ -95,12 +98,13 @@ function Row({ } function Input({ - field, value, referenceArm, incidentGroup, onChange, + field, value, referenceArm, incidentGroup, notify, onChange, }: { field: Field; value: unknown; referenceArm: boolean; incidentGroup: number | null; + notify: string[]; onChange?: (path: string, value: unknown) => void; }) { const emit = (next: unknown) => onChange?.(field.path, next); @@ -144,7 +148,7 @@ function Input({ ); } if (field.kind === "services") { - return emit(next)} />; + return emit(next)} />; } if (field.kind === "signs") { return emit(next)} />; @@ -175,15 +179,24 @@ function Input({ ); } +/** Как `max_length` у `KIO.notify_extra`. */ +const SERVICES_LIMIT = 20; + /** Ручное добавление служб из каталога — окно «Добавьте службы» боевого АРМ. * Список оповещения по признакам остаётся как есть: здесь только добавки. */ -function ServicesPicker({ value, onChange }: { value: string[]; onChange: (next: string[]) => void }) { +function ServicesPicker({ value, notify, onChange }: { + value: string[]; notify: string[]; onChange: (next: string[]) => void; +}) { const catalog = useServiceCatalog(); const [query, setQuery] = useState(""); const needle = query.trim().toLowerCase(); - const found = needle + // Лимит и службы из списка оповещения — те же правила, что на сервере: + // лишняя служба отклонила бы весь пакет правок. + const full = value.length >= SERVICES_LIMIT; + const found = needle && !full ? (catalog.data?.services ?? []) - .filter((item) => !value.includes(item.name) && item.name.toLowerCase().includes(needle)) + .filter((item) => !value.includes(item.name) && !notify.includes(item.name) + && item.name.toLowerCase().includes(needle)) .slice(0, 8) : []; return ( @@ -194,7 +207,8 @@ function ServicesPicker({ value, onChange }: { value: string[]; onChange: (next: onClick={() => onChange(value.filter((item) => item !== name))}>× )} } - setQuery(event.target.value)} /> {found.length > 0 &&
    {found.map((item) =>
  • diff --git a/frontend/src/pages/dds/Dds.tsx b/frontend/src/pages/dds/Dds.tsx index 106ccce..59267b6 100644 --- a/frontend/src/pages/dds/Dds.tsx +++ b/frontend/src/pages/dds/Dds.tsx @@ -47,6 +47,11 @@ function field(card: CardState, path: string): string { const value = readPath(card.server, path); return value === null || value === undefined || value === "" ? "—" : String(value); } +/** Список из карточки: `field()` не годится — `String([])` пустая строка, а не «—». */ +function names(card: CardState, path: string): string[] { + const value = readPath(card.server, path); + return Array.isArray(value) ? value.map(String) : []; +} function time(value: string): string { const parsed = new Date(value); return Number.isNaN(parsed.getTime()) ? value : parsed.toLocaleTimeString("ru-RU"); @@ -548,7 +553,7 @@ export function Dds() {
    {field(card, "description")}
    Класс: {field(card, "incident_type")}
    Получатели карточки: {station?.recipient_services?.join(", ") || field(card, "notify")}
    - {field(card, "notify_extra") !== "—" &&
    Добавлены оператором: {field(card, "notify_extra")}
    } + {names(card, "notify_extra").length > 0 &&
    Добавлены оператором: {names(card, "notify_extra").join(", ")}
    }
    Ваша ДДС: {station?.managed_service || "служба не назначена"}