133 lines
16 KiB
Markdown
133 lines
16 KiB
Markdown
# Техническое задание: управление системными сообщениями
|
||
|
||
## 1. Цель и контекст
|
||
- Обеспечить управляемое отображение системных сообщений на главной странице (`/`, компонент `HomeView.vue`) и добавить административный интерфейс для их создания и модерации в разделе контента (`/content`, компонент `ContentListView.vue`).
|
||
- Системные сообщения должны поддерживать статусы «черновик» и «опубликовано», храниться в базе данных и быть доступны через REST API.
|
||
|
||
## 2. Актуальное состояние
|
||
- Главная страница строится компонентом `HomeView.vue` и отображает чат ассистента (`ChatInterface.vue`), в котором выделены системные сообщения (`Message.vue`) по признаку `message.role === 'system'`.
|
||
- Раздел контента (`ContentListView.vue`) содержит карточки переходов: «Создать страницу», «Шаблоны», «Публичные», «Настройка», «Внутренние». Карточки ведут на существующие маршруты `content-create`, `content-templates`, `content-published`, `content-settings`, `content-internal`.
|
||
- В проекте отсутствуют сущности и API для системных сообщений; текущий `pagesService.js` работает только со страницами (`/pages`).
|
||
|
||
## 3. Новые пользовательские сценарии
|
||
- **Просмотр системных сообщений (главная, `/`):**
|
||
- Опубликованные системные сообщения подгружаются в чат ассистента и отображаются в виде свернутых карточек с кликабельным заголовком.
|
||
- При клике на заголовок сообщение раскрывается: в ленте чата отображается полный текст сообщения **или** отправляется предзаготовленный ответ от ИИ ассистента (контент «ответа» хранится вместе с сообщением и выбирается по флагу `reply_type`).
|
||
- Сообщения должны явно маркироваться как системные (цвет, иконка). При повторном открытии пользователь видит последнее состояние раскрытия; возможно локальное запоминание «прочитано».
|
||
- **Раздел «Системные сообщения» (`/content`):**
|
||
- На странице `/content` появляется новая карточка «Системные сообщения» с кнопкой «Подробнее». Переход ведёт на страницу с пользовательской таблицей (`/content/system-messages/table`), построенной на уже существующих компонентах таблиц (см. `UserTablesList.vue`), без отдельного дэшборда карточек.
|
||
- Таблица отображает системные сообщения построчно, с возможностью множественного выбора через чекбоксы; доступные массовые действия: публикация, снятие с публикации, перевод в черновики, удаление.
|
||
- Для каждого сообщения по клику «Подробнее» (внутри строки) открывается просмотр/редактирование с формой (см. ниже).
|
||
- **Создание/редактирование (`/content/system-messages/create`, `/content/system-messages/:id/edit`):**
|
||
- Форма с полями: заголовок, краткое описание, основной текст (Markdown/HTML), тип ответа (`inline` — показывать контент, `assistant_reply` — отправлять подготовленный ответ от ассистента), поле «Ответ ассистента» (активно при `assistant_reply`), тег важности (info/warning/danger), дата начала публикации (опционально), дата окончания (опционально), флаг отображения гостям.
|
||
- Кнопки: «Сохранить как черновик», «Опубликовать». При редактировании — «Обновить», «Снять с публикации», «Удалить».
|
||
- Проверки: обязательность заголовка и основного текста (или ответа ассистента в соответствующем режиме); валидация дат (окончание ≥ начало).
|
||
- **Работа с таблицей системных сообщений:**
|
||
- Колонки: чекбокс выбора, заголовок (кликабелен), статус, тип ответа, период действия, целевая аудитория (гости/авторизованные/все), дата создания, автор.
|
||
- Массовые действия выполняются для выбранных строк; одиночные действия доступны через контекстное меню/кнопки в строке (редактировать, опубликовать, снять с публикации, удалить).
|
||
|
||
## 4. Требования к интерфейсу
|
||
- В `ContentListView.vue` в сетку `management-blocks` добавить карточку «Системные сообщения» с кнопкой `Подробнее`. По дизайну карточка должна соответствовать существующим блокам (заголовок, описание, кнопка).
|
||
- Страница с таблицей системных сообщений:
|
||
- Использовать `BaseLayout` и локальные стили (`scoped`).
|
||
- Таблица поддерживает сортировку, фильтрацию по статусам и поиск по заголовку.
|
||
- Чекбоксы в шапке и строках для массового выбора; панель действий появляется при наличии выбора.
|
||
- Кнопка «Создать сообщение» открывает форму создания.
|
||
- Форма создания/редактирования:
|
||
- Rich-text (минимум Markdown) с предпросмотром и счётчиками символов/слов.
|
||
- Переключатель режима показа (`inline`/`assistant_reply`) с условным отображением поля «Ответ ассистента» (можно использовать `<transition>`).
|
||
- Поле для выбора иконки/цвета по `severity` (статические пресеты).
|
||
- Главная страница:
|
||
- Системные сообщения отображаются в блоке чата как свернутые карточки (`system-message-collapsed`). При клике заголовок разворачивает карточку (`system-message-expanded`) или инициирует отправку ассистента (UI показывает «сообщение от ассистента»).
|
||
- Для развёрнутых сообщений предусмотреть кнопку «Свернуть» и (опционально) «Отметить как прочитанное». Состояние хранить в `localStorage`.
|
||
|
||
## 5. Маршрутизация и компоненты
|
||
- Добавить маршруты в `router/index.js`:
|
||
- - `/content/system-messages/table` → `SystemMessagesTableView.vue`
|
||
- - `/content/system-messages/create` → `SystemMessageCreateView.vue`
|
||
- - `/content/system-messages/:id` → `SystemMessageDetailsView.vue` (просмотр)
|
||
- - `/content/system-messages/:id/edit` → `SystemMessageEditView.vue`
|
||
- При необходимости для модальных/вложенных маршрутов можно использовать дочерние маршруты или именованные вью.
|
||
- Создать соответствующие Vue-компоненты в `src/views/content/system-messages/` и общий набор переиспользуемых элементов (таблица, форма, фильтры, массовые действия) в `src/components/system-messages/`.
|
||
- Создать сервис `src/services/systemMessagesService.js` с методами для нового API.
|
||
|
||
## 6. Требования к API и данным
|
||
- **Новая таблица** `system_messages` (PostgreSQL):
|
||
- `id` (uuid, pk)
|
||
- `title` (text, not null)
|
||
- `summary` (text, nullable)
|
||
- `content` (text, not null)
|
||
- `reply_type` (enum: inline, assistant_reply; default inline)
|
||
- `assistant_reply_content` (text, nullable; требуется при `reply_type = assistant_reply`)
|
||
- `severity` (enum: info, warning, danger; default info)
|
||
- `status` (enum: draft, published; not null)
|
||
- `visible_for` (enum: all, authenticated, guests; default all)
|
||
- `publish_at` (timestamp, nullable)
|
||
- `expire_at` (timestamp, nullable)
|
||
- `created_at`, `updated_at`
|
||
- `created_by`, `updated_by` (references users/identities, nullable)
|
||
- `slug` (text, уникальный, для адресации по ссылке при необходимости)
|
||
- **REST API (Express):**
|
||
- `GET /system-messages` (пагинация, фильтры по статусу, поиску)
|
||
- `GET /system-messages/published` (фильтрация по дате/аудитории; публичная)
|
||
- `GET /system-messages/:id` (доступ только авторизованным редакторам)
|
||
- `POST /system-messages` (создание; права `MANAGE_LEGAL_DOCS`)
|
||
- `PATCH /system-messages/:id` (редактирование; проверка статусов)
|
||
- `DELETE /system-messages/:id` (мягкое удаление или физическое)
|
||
- `POST /system-messages/:id/publish` и `POST /system-messages/:id/unpublish` (опционально, если не использовать PATCH)
|
||
- Все защищённые эндпоинты должны требовать авторизацию и права (см. `permissions.js`, `usePermissions`).
|
||
- Добавить новую миграцию (`backend/scripts/run-migrations.js`) и ORM/SQL-файлы в существующем формате проекта.
|
||
- Обновить логирование и обработку ошибок `winston`, добавить валидацию входных данных (например, `Joi` или кастомную).
|
||
|
||
## 7. Логика отображения на фронтенде
|
||
- `HomeView.vue`:
|
||
- При инициализации запрашивать опубликованные системные сообщения (учитывая текущую аудиторию) через `systemMessagesService.getPublished({ includeExpired: false })`.
|
||
- Кэшировать ответ в сторе или локальном состоянии; при подписке на WebSocket можно предусмотреть `system_message_updated` событие.
|
||
- Добавить обработчик раскрытия: по клику на заголовок либо подставлять полный текст сообщения (`inline`), либо инициировать цепочку отправки `assistant_reply_content` в чат (без участия пользователя).
|
||
- Добавить обработчик скрытия сообщения, сохраняющий идентификатор в `localStorage` и фильтрующий локально.
|
||
- `ContentListView.vue`:
|
||
- Добавить новую карточку «Системные сообщения» в сетку `management-blocks`, не нарушая адаптивную сетку (обновить `grid-template-columns` при необходимости).
|
||
- Страницы списков:
|
||
- Реализовать пагинацию (lazy loading или обычная), сортировку по дате.
|
||
- Для статусов использовать цветовые бейджи (info/warning/danger).
|
||
- Форма создания:
|
||
- Поддерживать сабмит через `yarn lint`-friendly код; валидация на клиенте (например, с использованием `computed`/`watch`).
|
||
- При успешной публикации перенаправлять на список опубликованных; при сохранении черновика — оставаться на странице с уведомлением.
|
||
|
||
## 8. Требования к безопасности и доступу
|
||
- Сценарии создания/изменения доступны только ролям с `PERMISSIONS.MANAGE_LEGAL_DOCS`.
|
||
- Публичный список (`GET /system-messages/published`) фильтрует по:
|
||
- `status === 'published'`.
|
||
- `publish_at <= now()` (или null).
|
||
- `expire_at > now()` (или null).
|
||
- `visible_for` проверяется на основе контекста (гость/авторизованный).
|
||
- При выдаче через чат скрывать поля `created_by`, `updated_by`, внутренние метки.
|
||
- Учитывать CSRF, CORS, rate-limit (перенять конфиг из существующих роутов).
|
||
|
||
## 9. Тестирование
|
||
- **Backend:**
|
||
- Юнит-тесты для CRUD в `tests/system-messages/*.test.js` (Mocha).
|
||
- Проверка фильтров publish/expire и доступа по ролям.
|
||
- Тест миграции (откат/применение).
|
||
- **Frontend:**
|
||
- Юнит-тесты Vue (если настроены) для основных компонентов (форма, список).
|
||
- E2E (при наличии) — сценарий: создание черновика → публикация → отображение на главной.
|
||
- **Регрессионные проверки:**
|
||
- Убедиться, что существующий список контента и чат ассистента продолжают работать без ошибок (`yarn lint`, `yarn test`).
|
||
|
||
## 10. Интеграция и DevOps
|
||
- Обновить `docker-compose.yml` при необходимости (например, добавить миграции в стартовый процесс).
|
||
- Убедиться, что новые переменные окружения (если будут, например, лимиты количества сообщений) документированы в `README.md` и `setup-instruction.md`.
|
||
- Добавить скрипт seeding (опционально) для тестовых системных сообщений.
|
||
|
||
## 11. Открытые вопросы
|
||
- Нужно ли хранить историю публикаций (auditing)? Если да — предусмотреть таблицу `system_messages_history`.
|
||
- Требуется ли поддержка многоязычности? (При отсутствии — ограничение на один язык, RU).
|
||
- Нужно ли уведомление по WebSocket при появлении новых сообщений? (Если да — добавить событие в `wsHub.js`).
|
||
|
||
## 12. Итоговые артефакты
|
||
- Backend: новые маршруты, контроллеры, сервис, миграция.
|
||
- Frontend: новые страницы и сервис, обновлённые маршруты и компоненты `HomeView`, `ContentListView`.
|
||
- Документация: обновление `README.md` (раздел запуск), `application-description.md` или `tables-system.md` при изменении схем, настоящая спецификация.
|
||
|