Комментарии — Администрирование¶
Обзор¶
Домен 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.
- Пиши обычный markdown (CommonMark/GFM). Не нужно «кастомного синтаксиса 1Формы» — поддерживается стандарт.
- 1Форма-специфика:
__текст__это курсив, не жирный — для жирного используй**текст**((текст))— подчёркнутый (опционально)#TaskId— автоссылка на задачу,@user{UserId}— упоминание пользователя- Переносы строк — настоящий перевод строки (LF). Не
\nкак двусимвольный escape. - Списки
-/1.в SPA (лента, чат) рендерят маркированный/нумерованный список; на iOS/Android — plain text. - Заголовки/fenced/таблицы в SPA работают (с мая 2026), на iOS/Android — plain text. Если комментарий важен для мобильных — используй inline-разметку (
**bold**,`code`) вместо блочной.
HTML-теги запрещены. XSS-санитайзер вырезает угловые скобки <TKey, TValue> — экранировать: <TKey, TValue> или обратные кавычки.
Ссылки на сущности — 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 |
Получатель должен ответить (вопрос) |
Автопрочтение: технические условия¶
Комментарий автоматически помечается как прочитанный если выполнено одно из условий:
- В профиле пользователя включена настройка автопрочтения (
User.AutoReadComments) - Пользователь исключён из адресатов смарт-событием (
BeforeSendNotification) - Для событий календаря — при выключенном уведомлении по событию (
CalendarEnableNotify) - По персональным настройкам уведомлений пользователя (
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-- общая архитектура администрирования