Комментарии — Администрирование¶
Обзор¶
Домен 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} |
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.
| Что использовать | Синтаксис |
|---|---|
| Жирный | **текст** |
| Курсив | __текст__ |
| Ссылка на задачу | #12345 |
| Код (inline) | `текст` |
Запрещено: HTML-теги, стандартный markdown (##, -, 1., таблицы), литеральные \n.
XSS-санитайзер: угловые скобки <TKey, TValue> вырезаются. Экранировать: <TKey, TValue> или обратные кавычки.
Типичные ошибки 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.
Связанные документы¶
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-- общая архитектура администрирования