Перейти к содержанию

Комментарии — Администрирование

Обзор

Домен comments охватывает настройку поведения комментариев в задачах: видимость, адресация, быстрые ответы, системные комментарии. Основная часть настроек живёт в категории (смежный домен categories). Администрирование использует:

  • EntityEditor -- 1 схема (quickReply -- шаблоны быстрых ответов)
  • Настройки категории -- поля в dbo.Subcategories, управляющие поведением комментариев

Собственных форм автоадминки и Admin API контроллеров у домена нет.

Механизмы администрирования

EntityEditor

Схема JSON Таблица Назначение
quickReply dbo.QuickReplyTemplates Шаблоны быстрых ответов для комментариев

Настройки через смежный домен (categories)

Ключевые флаги поведения комментариев задаются в настройках категории (автоадминка subcategories / FormsGenerator):

Поле Таблица Что контролирует
EnableComments dbo.Subcategories Глобальное включение/выключение комментариев
HideSystemComments dbo.Subcategories Скрытие системных комментариев из пользовательской ленты
ForwardCommentsToAllHelpers dbo.Subcategories Автодобавление всех исполнителей в адресаты
OneFMainVisibilityMode dbo.Subcategories Ограничение видимости комментариев
IsDeleteUserCommentsForbidden dbo.Subcategories Запрет удаления пользовательских комментариев

Ключевые настройки

Шаблоны быстрых ответов (QuickReplyTemplates)

Где настраивается: EntityEditor -> quickReply Таблица БД: dbo.QuickReplyTemplates

Шаблоны быстрых ответов, доступные пользователям при написании комментария. Администратор создаёт набор стандартных фраз/ответов.

Эффект в runtime: шаблоны загружаются в UI комментирования и доступны через кнопку быстрого ответа.

Поведение комментариев в категории

Где настраивается: автоадминка -> FormsGenerator subcategories → секция комментариев Таблица БД: dbo.Subcategories

Группа полей Что контролирует
Включение комментариев Доступность функции комментирования в задачах
Системные комментарии Отображение автоматических комментариев (смена статуса, исполнителя и т.д.)
Адресация Автоматическое добавление исполнителей в адресаты
Ограничения Запрет удаления, режимы видимости

Эффект в runtime: проверяется CommentsService при создании, отображении и удалении комментариев.

Видимость комментария (runtime)

Таблица БД: dbo.CommentRecipients

Видимость комментария определяется не фактом записи в Comments, а наличием записи в CommentRecipients. Системные комментарии при HideSystemComments = true пишутся в БД, но не попадают в пользовательскую ленту.

Подписки на типы комментариев (runtime)

Таблица БД: dbo.UserLentaCommentTypes

Пользователь фильтрует типы комментариев в своей ленте через настройки подписки.

CustomSettings — глобальные ключи комментариев

Ключ Тип Назначение
FirstCommentIdWithNoRecipients int ID комментария, начиная с которого адресаты больше не хранятся в теле комментария (с v2.240). Создан для совместимости SPA с задачей ClearCommentRecipientsArchiveJob. Рекомендуется компаниям, работающим в SPA
PostMarkAsAnsweredWithUserType bool / false Если true — комментарий «Как отвеченный» отмечается как пользовательский, а не системный. По умолчанию (false) — системный (как раньше)

appsettings.json — кодировка комментариев

Ключ Тип Назначение
UseClassicEncodeInComments bool Использовать классическую кодировку в комментариях. Включается при выявлении проблем с отображением спецсимволов в legacy-окружениях

Типичные ошибки настройки

Симптом Причина Где проверить SQL-диагностика
Комментарий отправлен, но его никто не видит Нет записей в CommentRecipients dbo.CommentRecipients select * from dbo.CommentRecipients where CommentId = {commentId}
Системные комментарии исчезли из ленты Включён HideSystemComments Настройки категории select HideSystemComments from dbo.Subcategories where Id = {subcatId}
Исполнители не получают комментарии Выключен ForwardCommentsToAllHelpers или неверная адресация Настройки категории select ForwardCommentsToAllHelpers from dbo.Subcategories where Id = {subcatId}
Пользователь не может удалить свой комментарий Включён IsDeleteUserCommentsForbidden Настройки категории select IsDeleteUserCommentsForbidden from dbo.Subcategories where Id = {subcatId}
Тип комментария не виден в ленте Пользователь отписался от типа dbo.UserLentaCommentTypes select * from dbo.UserLentaCommentTypes where UserId = {userId}

Детальная диагностика «Не вижу отправленный комментарий»

Причины (в порядке частоты): 1. Комментарий системный + HideSystemComments включено 2. Пользователь не подписчик задачи → нет записи в CommentRecipients 3. Тип комментария отключён в настройках подписки пользователя 4. Smart Event заблокировал уведомление (BeforeSendNotification) 5. EnableComments выключено / OneFMainVisibilityMode скрывает

SQL-диагностика:

-- 1. Проверить наличие комментария
select c.CommentID, c.TaskID, c.UserID, c.TypeID, c.IsDeleted, c.Content, c.Date
from Comments c
where c.CommentID = @commentId;

-- 2. Проверить адресатов
select r.UserID, u.FullName, r.IsUnread, r.IsRealRecipient, r.IsCopyRecipient, r.HasToAnswer
from CommentRecipients r
        join Users u on u.UserID = r.UserID
where r.CommentID = @commentId
order by r.UserID;

-- 3. Проверить подписку на задачу
select s.UserID, s.IsDeleted
from MailSubscribersUsers s
where s.TaskID = @taskId and s.UserID = @userId;

-- 4. Проверить настройки категории
select sc.SubcatID, sc.HideSystemComments, sc.ForwardCommentsToAllHelpers, sc.EnableComments
from Subcategories sc
where sc.SubcatID = (select t.SubcatID from Tasks t where t.TaskID = @taskId);

Чеклист: 1. Комментарий существует в Comments? Не удалён (IsDeleted = 0)? 2. Есть запись в CommentRecipients для данного пользователя? 3. Если нет — проверить TypeID (системный?) + HideSystemComments 4. Если нет — проверить подписку пользователя на задачу 5. Если нет — проверить Smart Events в категории (BeforeSendNotification) 6. Если есть, но IsUnread = false — проверить AutoRead настройки 7. Если всё корректно в БД — проверить доставку SignalR (NewComment)

«Комментарий виден заказчику, но не исполнителю»

Частая причина: ForwardCommentsToAllHelpers выключено — комментарий адресован конкретному исполнителю, а не всем.

«Системные комментарии не отображаются»

Причина: HideSystemComments = true в настройках категории. Системные комментарии записываются, но адресаты не создаются — никто их не видит в ленте.

REST API комментариев (без MCP)

Создание через MCP (предпочтительно)

mcp_comments_post_comment({
    "taskId": 123,
    "commentText": "Вопрос",
    "needsAnswer": True       # обязательно для триггера Анфисы
})

NeedsAnswer: Анфиса слушает только NeedsAnswer=1. Без этого флага — не ответит.

Создание через REST

# PascalCase обязателен
POST("/api/comments/add", {
    "TaskId": 12345,         # НЕ taskId (lowercase → поле игнорируется)
    "CommentText": "текст"
})  # → {"data": commentId}

Вложение файлов в комментарий

# 1. Preupload
curl -s -X POST -H "1F-Pat: $PAT" \
  -F "file=@path/to/file.md" \
  "https://{host}/api/files/upload/ToPreUploadedFiles"
# → {"data": [{"preUploadFileId": 708072}]}

# 2. Комментарий с файлом через curl (MCP preUploadedFileKeys НЕ работает)
curl -s -X POST -H "1F-Pat: $PAT" \
  -H "Content-Type: application/json" \
  -d '{"TaskId": 123, "CommentText": "Текст", "PreUploadedFileKeys": ["708072"]}' \
  "https://{host}/api/comments/add"

Форматирование

Подробности: text-formatting.md.

  1. Пиши обычный markdown (CommonMark/GFM). Не нужно «кастомного синтаксиса 1Формы» — поддерживается стандарт.
  2. 1Форма-специфика:
  3. __текст__ это курсив, не жирный — для жирного используй **текст**
  4. ((текст)) — подчёркнутый (опционально)
  5. #TaskId — автоссылка на задачу, @user{UserId} — упоминание пользователя
  6. Переносы строк — настоящий перевод строки (LF). Не \n как двусимвольный escape.
  7. Списки -/1. в SPA (лента, чат) рендерят маркированный/нумерованный список; на iOS/Android — plain text.
  8. Заголовки/fenced/таблицы в SPA работают (с мая 2026), на iOS/Android — plain text. Если комментарий важен для мобильных — используй inline-разметку (**bold**, `code`) вместо блочной.

HTML-теги запрещены. XSS-санитайзер вырезает угловые скобки <TKey, TValue> — экранировать: &lt;TKey, TValue&gt; или обратные кавычки.

Ссылки на сущности — URL-паттерны

В комментариях URL автоматически кликабельны (SPA, iOS, Android).

Shorthand (парсится системой)

Синтаксис Результат Пример
#TaskId Ссылка на задачу #12345
@user{UserId} Упоминание пользователя @user42

Полные URL

Задачи и гриды:

Сущность URL
Задача https://<host>/spa/tasks/{taskId}
Грид категории https://<host>/spa/tasks/subcat/{subcatId}/grid
Канбан категории https://<host>/spa/tasks/subcat/{subcatId}/kanban
Портал категории https://<host>/spa/tasks/subcat/{subcatId}/portal

Администрирование:

Сущность URL
Настройки категории https://<host>/spa/administration/subcategory/{subcatId}
ДП категории (список) https://<host>/spa/administration/ext-params-settings/subcat/{subcatId}
Конкретный ДП https://<host>/spa/administration/ext-params-settings/{subcatId}/{extParamId}
SmartScripts https://<host>/spa/administration/smart-scripts/{scriptId}
Пользователь (профиль) https://<host>/spa/users/{userId}/info

Правила:

  • Задачи — ВСЕГДА shorthand #TaskId, не полный URL. Система автоматически рендерит кликабельную ссылку.
  • Для остальных сущностей — полный URL. Подставляй реальные ID из контекста.
  • <host> — адрес вашего стенда 1Формы (на клиентских площадках домен свой, пути те же).

Типичные ошибки REST API

Проблема Причина Решение
POST /api/comments (без /add) Это GET-эндпоинт — возвращает 200 + 229KB task DTO /api/comments/add
POST /api/comments/post → 404 Нет такого эндпоинта /api/comments/add
taskId (camelCase) PascalCase обязателен TaskId — иначе поле игнорируется
Комментарий в закрытую задачу OldLogicException Проверять IsClosed перед постингом

Реакции (emoji)

⚠️ Нет admin API для управления настройкой ReactionsEnabled. Включение/выключение реакций — только через SQL (таблица настроек). REST-эндпоинты (/api/comments/{id}/reactions/add, remove, GET) — только пользовательские операции.

Real-time подписка через SignalR

Канонический способ ловить новые комментарии — SignalR-хаб /notificationHub. Backend при добавлении комментария отправляет invocation notify(NewComment, payload) — все подключённые клиенты с правом видеть задачу получают событие.

Контракт payload:

{
  "id": 12345,                     // CommentID
  "taskId": 67890,
  "sender": {"userId": 28, "displayName": "..."},
  "text": "...",                   // HTML
  "inReplyToComment": {"id": 12340},  // если ответ на коммент
  "threadCommentId": null,
  "createdAt": "2026-04-26T15:30:00+03:00"
}

Аутентификация: JWT через header 1FormaAuth в negotiate. PAT не работает (см. полный контракт хаба).

Когда использовать: - Real-time UI комментариев (SPA — уже подписан). - AI ждёт ответ Анфисы в задаче — фильтр по sender.userId == ANFISA_USER_ID && inReplyToComment.id == myPostedCommentId. - E2E-тесты Анфисы (используется automation/e2e-unified.py).

Когда НЕ использовать: - Cron-джобы / серверы без stateful-соединения. - Короткие CLI-сессии (handshake съест время) — sleep + get_comments приемлем.

Reference-реализация Python (готовый класс SignalRListener с wait_for_reply(), ~140 строк): docs/projects/1f-agent/automation/e2e-unified.py:102-238. Используется в проде E2E suite Анфисы.

Полный контракт хаба (negotiate, handshake, ловушки, отладка): docs/reference/api/signalr-hub.md.

Ловушки: - Имя события приходит в двух регистрах (NewComment / newComment) — фильтруй обоими. - inReplyToComment форма: int или {id: ...} — нормализуй. - Технические комменты Анфисы с префиксом v32 | (служебная версионная пометка) — игнорировать через regex ^v\d+\s*\|. - Thread-сообщения: при ответе в треде приходит и inReplyToComment и threadCommentId. Чтобы отделить «ответ на коммент» от «активность в треде» — игнорируй где threadCommentId && !inReplyToComment.

Типы комментариев (TypeID)

Внутренние идентификаторы типов — используются в диагностике, смарт-событиях и фильтрах ленты.

Пользовательские типы

TypeID Описание Создаётся
3 Пользовательский комментарий Вручную пользователем
6 Комментарий из подзадачи Автоматически при публикации в подзадаче
10 Вложение файла (без текста) Пользователем через drag&drop файла
20 Внесение трудозатрат Пользователем через форму трудозатрат

Системные типы

TypeID Описание Событие
1 Переход по маршруту Смена шага/статуса задачи
2 Подпись (резолюция) Согласование/подписание
5 Служебный Различные системные действия
7 Изменение ДП или файлов Изменение допараметра или файла
8 Создание задачи Создание новой задачи
9 Изменение текста задачи Редактирование описания
11 Смена категории Перемещение задачи
12 Смена срока Изменение дедлайна
13 Добавлен исполнитель Назначение исполнителя
15 Добавлен подписчик Добавление подписчика
16 Задача просрочена Автоматически при просрочке
18 Смена заказчика Изменение заказчика задачи
19 Удалён файл Удаление файла

Типы адресатов (CommentRecipients)

Поле Значение
IsRealRecipient = true Явный адресат — выбран пользователем при отправке
IsRealRecipient = false Неявный адресат / подписчик задачи без прямой адресации
IsCopyRecipient = true В копии — получает сообщение, но без «непрочитанного»
HasToAnswer = true per-recipient Получатель должен ответить (вопрос)

Автопрочтение: технические условия

Комментарий автоматически помечается как прочитанный если выполнено одно из условий:

  1. В профиле пользователя включена настройка автопрочтения (User.AutoReadComments)
  2. Пользователь исключён из адресатов смарт-событием (BeforeSendNotification)
  3. Для событий календаря — при выключенном уведомлении по событию (CalendarEnableNotify)
  4. По персональным настройкам уведомлений пользователя (NotificationSettings)

Связанные документы

  • docs/domains/comments/text-formatting.md -- полные правила форматирования
  • docs/domains/comments/backend.md -- backend-архитектура (контроллеры, сервисы, типы комментариев)
  • docs/domains/comments/business.md -- бизнес-логика (адресация, read/unread, треды)
  • docs/domains/comments/data-flow.md -- E2E диагностика (post → recipients → UI)
  • docs/domains/comments/database.md -- схема БД (Comments, CommentRecipients, и т.д.)
  • docs/domains/categories/admin.md -- настройка категорий (поля комментариев в Subcategories)
  • docs/platform/backend/admin-architecture.md -- общая архитектура администрирования