Skip to content

Чат в реальном времени

Planner включает встроенную систему обмена сообщениями в реальном времени на базе Socket.IO WebSockets.

Архитектура

  • Пространство имён Socket.IO: /chat
  • Аутентификация: На основе токена через handshake.auth.token
  • События: join, leave, typing (клиент→сервер); chat:typing, chat:message, chat:created (сервер→клиент)

API Endpoints

МетодПутьОписание
GET/api/chatsСписок бесед пользователя
POST/api/chatsСоздать беседу
POST/api/chats/direct/:userIdСоздать или получить личную беседу
POST/api/chats/task/:taskIdСоздать или получить беседу задачи
GET/api/chats/:id/messagesСписок сообщений (курсорная пагинация: ?before=&limit=)
POST/api/chats/:id/messagesОтправить сообщение
POST/api/chats/:id/messages/attachmentsЗагрузить вложения (до 10 файлов)
POST/api/chats/:id/readОтметить беседу как прочитанную

Socket.IO события

Клиент → Сервер

СобытиеPayloadОписание
joinconversationId: stringПрисоединиться к комнате беседы
leaveconversationId: stringПокинуть комнату беседы
typingconversationId: stringИндикатор печатания

Сервер → Клиент

СобытиеPayloadОписание
chat:typing{ conversationId, userId }Другой участник печатает

Сообщения отправляются через REST (POST /api/chats/:id/messages), доставка в реальном времени — через sendToConversation() на сервере.

Фронтенд

Store чата

typescript
const store = useChatStore()
const { conversations, messages } = storeToRefs(store)

await store.fetchConversations()
await store.createConversation(userId)  // личная
await store.createTaskConversation(taskId)  // чат задачи
await store.fetchMessages(conversationId)
await store.sendMessage(conversationId, body)

Структура UI

Интерфейс чата имеет двухпанельный макет:

  • Левая панель: Список бесед (фильтруется по типу — чаты задач отображаются отдельно на страницах задач)
  • Правая панель: Поток сообщений с обновлениями в реальном времени

Ключевые детали реализации

  • Беседы задач создаются через POST /api/chats/task/:taskId — это отдельный эндпоинт от личных бесед
  • Сегмент пути task статический, что позволяет избежать конфликтов маршрутов с /direct/:userId
  • Создание беседы задачи автоматически добавляет запрашивающего пользователя как участника
  • Доставка сообщений происходит в реальном времени через socket-события — без polling
  • Индикаторы печатания показывают, когда другой участник набирает текст
  • Основная страница чата фильтрует беседы типа task (они отображаются встроенно на странице деталей задачи)

Голосовые сообщения

Чат поддерживает запись и воспроизведение голосовых сообщений:

  • VoiceRecorder.vue — запись аудио через MediaRecorder API, загрузка как файловое вложение
  • AudioPlayer.vue — пользовательский аудиоплеер для воспроизведения голосовых сообщений с отображением волновой формы
  • Голосовые сообщения загружаются через POST /api/chats/:id/messages/attachments с флагом voice
  • Метаданные продолжительности хранятся вместе с аудиофайлом