No description
  • TypeScript 36.9%
  • Go 35.5%
  • HTML 18.9%
  • SCSS 7.2%
  • Dockerfile 0.9%
  • Other 0.6%
Find a file
2026-06-23 15:20:21 +03:00
backend feat: Установка заголовка приложения при запуске 2026-06-23 15:03:39 +03:00
docs first commit 2026-06-22 20:20:16 +03:00
frontend fix: На мобилках название видно не полностью, но сделан всплывающий тултип при тапе на него 2026-06-23 15:20:21 +03:00
.gitignore feat: Статические файлы для шрифтов и иконок 2026-06-23 10:37:16 +03:00
.woodpecker.yml fix: Статичные файлы 2026-06-23 08:28:39 +03:00
angie.conf.example feat: Кастомный эндпоинт 2026-06-23 08:54:42 +03:00
Dockerfile fix: Статичные файлы 2026-06-23 08:28:39 +03:00
LICENSE CI/CD 2026-06-22 21:08:13 +03:00
README.md fix: Ширина названия конференции 2026-06-23 15:11:36 +03:00

Система управления программой конференции

Мгновенная синхронизация, загрузка презентаций, управление докладчиками и порядком выступлений — всё в одном веб-приложении.


🔥 Особенности

  • Три роли:

    • Администратор добавляет/исключает докладчиков, загружает файлы презентаций, меняет порядок выступлений.
    • Модератор (оператор/секретарь) отмечает выступления как прошедшие, скачивает файлы, сортирует программу.
    • Зритель просматривает программу в реальном времени (обновления с задержкой 30 секунд для снижения нагрузки).
  • Файлы презентаций загрузка через веб-интерфейс, автоматическое сохранение на сервере.

  • Draganddrop интуитивное перетаскивание докладов для изменения порядка.

  • Мгновенные обновления для организаторов, зрители получают обновления с накоплением (30-секундный debounce).

  • Простота одна страница, минималистичный интерфейс на Angular Material.

  • Легкое развертывание одиночный бинарник Go + SQLite, готовый Dockerобраз.

  • Встраивание статики фронтенд вшит в бинарник через go:embed, для запуска не нужна папка static/.

  • Гибкий эндпоинт флаг --prefix позволяет повесить приложение на подпуть (/conference, /meet и т.д.), без отдельного домена. Пример location для Angie/Nginx — в angie.conf.example.

  • Название конференции параметр --name задаёт заголовок страницы и название в интерфейсе. По умолчанию «Конференция».


🚀 Быстрый запуск в Docker

Самый простой способ запустить систему использовать готовый Dockerобраз.

docker run -p 5000:3000 \
  -e ADMIN_PASSWORD=administrator \
  -e MOD_PASSWORD=moderator \
  -e CONFERENCE_NAME="Моя конференция" \
  -v ${PWD}/data/:/data \
  -v ${PWD}/uploads:/uploads \
  git.ymnuktech.ru/ymnuk/reception-conference:latest

После запуска сервер будет доступен по адресу https://localhost:5000 (или ваш IP).
Подставьте свои пароли вместо administrator и moderator.


Параметры Dockerконтейнера

Переменная окружения / аргумент Описание Значение по умолчанию
ADMIN_PASSWORD Пароль для входа как администратор admin
MOD_PASSWORD Пароль для входа как модератор mod
DB_PATH Путь к файлу базы данных SQLite внутри контейнера conference.db
PORT Порт, на котором сервер принимает HTTPзапросы 3000
PREFIX Префикс эндпоинта (например /conference) (пусто)
CONFERENCE_NAME Название конференции (заголовок страницы) Конференция

Важно: пробросьте тома для сохранения данных между перезапусками контейнера:

  • -v /host/path/data:/data для базы данных.
  • -v /host/path/uploads:/uploads для загруженных презентаций.

🛠 Самостоятельная сборка и запуск

Требования

  • Go 1.21+
  • Node.js 18+ и npm
  • Angular CLI (установите глобально: npm install -g @angular/cli)

Шаги

  1. Клонировать репозиторий

    git clone <repository-url>
    cd reception-conference
    
  2. Собрать фронтенд

    cd frontend
    npm install
    ng build --prod --output-path=../backend/cmd/server/static
    cd ..
    
  3. Собрать бэкенд

    cd backend
    go mod download
    go build -o conference-server ./cmd/server
    
  4. Запустить сервер

    ./conference-server -admin=myadmin -mod=mymod -db=./data.db -port=8080
    

    (Все параметры можно также задавать через переменные окружения, см. ниже.)

  5. Открыть в браузере перейдите на https://localhost:8080 (или другой порт).

Примечание: Фронтенд встраивается в Go-бинарник через //go:embed, поэтому папка static/ не нужна во время выполнения. Для локальной разработки можно запустить фронт отдельно (ng serve) и проксировать запросы к бэкенду — режим --prefix также поддерживается в dev-режиме через proxy.conf.json.


Параметры командной строки

Аргумент Переменная окружения По умолчанию Описание
--admin ADMIN_PASSWORD admin Пароль администратора
--mod MOD_PASSWORD mod Пароль модератора
--db DB_PATH conference.db Путь к файлу SQLite
--port PORT 3000 Порт для HTTP/HTTPS
--prefix PREFIX (пусто) Префикс эндпоинта (например /conference)
--name CONFERENCE_NAME Конференция Название конференции

Если не указать TLS-сертификаты, сервер запустится без HTTPS (не рекомендуется для продакшена). Для защищённого соединения положите cert.pem и key.pem в директорию с бинарником, либо укажите пути в коде (см. раздел «Настройка HTTPS»).


📁 Структура проекта

.
├── .woodpecker.yml              # CI/CD конфигурация (автоматическая сборка)
├── angie.conf.example           # Пример location для Angie/Nginx
├── backend/                     # Серверная часть (Go)
│   ├── cmd/server/
│   │   ├── main.go              # Точка входа (go:embed static/)
│   │   └── static/              # Собранный фронтенд (создаётся при сборке)
│   ├── internal/
│   │   ├── models/              # GORM-модели
│   │   ├── ws/                  # WebSocket обработчики
│   │   ├── handlers/            # HTTP хендлеры (upload, download)
│   │   ├── db/                  # Инициализация БД
│   │   └── config/              # Парсинг аргументов
│   ├── uploads/                 # Хранилище загруженных файлов
│   ├── go.mod
│   └── go.sum
├── frontend/                    # Клиентская часть (Angular)
│   ├── src/
│   │   ├── app/                 # Основной модуль
│   │   │   ├── app.component.*  # Главный компонент (таблица + действия)
│   │   │   ├── services/        # WebSocket, HTTP
│   │   │   ├── dialogs/         # Диалоги входа, загрузки, добавления
│   │   │   └── models/          # Интерфейсы
│   │   ├── environments/        # Конфигурация окружения
│   │   └── index.html
│   ├── angular.json
│   ├── package.json
│   └── tsconfig.json
└── README.md

🧩 Как это работает

Аутентификация

  • При открытии страницы автоматически устанавливается WebSocketсоединение.
  • Если вы хотите войти как администратор или модератор нажмите кнопку «Войти» и введите пароль.
  • После успешной аутентификации сервер привязывает роль к текущему сокету, и интерфейс адаптируется (появляются кнопки управления).

Управление программой

  • Администратор:
    • Добавляет докладчика (имя, тема).
    • Массовый импорт докладчиков через JSON (кнопка «Импорт»).
    • Исключает/восстанавливает участника (исключённые скрыты от зрителей).
    • Загружает файл презентации для конкретного докладчика (статус становится ready).
    • Меняет порядок выступлений перетаскиванием строк.
    • Может также отмечать доклады как прошедшие (но это обычно делает модератор).
  • Модератор:
    • Отмечает выступление как done (и обратно в ready).
    • Скачивает презентацию.
    • Перетаскивает строки для изменения порядка.
  • Зритель:
    • Видит только неисключённых участников.
    • Данные обновляются с задержкой до 30 секунд (сервер накапливает изменения и рассылает пачкой).

Статусы участников

У каждого участника есть один из трёх статусов:

Статус Отображается как Описание
pending Ожидание Начальный статус при добавлении. Файл ещё не загружен.
ready Готов Файл презентации загружен. Участник готов к выступлению.
done Прочитан Выступление отмечено как состоявшееся.

Правила перехода:

  • pendingready — администратор загружает файл
  • readydone — модератор/администратор отмечает выступление
  • doneready — модератор/администратор возвращает в работу

Ограничения по статусам:

  • Редактировать (имя, тему) можно в статусах pending и ready
  • Удалить участника можно в статусах pending и ready (нельзя удалить done); исключённый (excluded) участник не редактируется и не удаляется

Массовый импорт через JSON

Администратор может загрузить несколько докладчиков одновременно через кнопку «Импорт» в тулбаре. Формат JSON:

[
  {"name": "Иван Петров", "topic": "Квантовые вычисления"},
  {"name": "Мария Сидорова", "topic": "Нейросети в медицине"}
]

Каждая запись проходит валидацию: name (1100 символов) и topic (12000 байт). При ошибках импорт не прерывается — все ошибки собираются и показываются разом, а успешно прошедшие валидацию записи отправляются на сервер по одной через WebSocket.

Синхронизация

  • Все изменения немедленно отправляются организаторам (admin/moderator) через WebSocket.
  • Для зрителей используется debounce сервер ждёт 30 секунд после последнего изменения и затем рассылает актуальную программу всем зрителям. Это снижает нагрузку при большом количестве зрителей (до 200+).

Файлы

  • Загрузка файла происходит через HTTP POST на /upload?id=...&pass=....
  • Скачивание через GET /download/{id}?pass=....
  • Пароль передаётся в query для простоты (защищено TLS).

🔒 Настройка HTTPS (обязательно для продакшена)

По умолчанию сервер запускается без HTTPS. Для публичного доступа используйте обратный прокси (Angie/Nginx/Caddy) с терминированием TLS — см. раздел «Развёртывание за обратным прокси».

Если нужно, сервер может сам работать по HTTPS — положите cert.pem и key.pem в рабочую директорию или укажите пути в коде.
Сертификаты можно получить через Let's Encrypt (Certbot) или использовать самоподписанные для тестирования:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes

🌐 Развёртывание за обратным прокси (Angie/Nginx)

Если приложение встраивается в существующий сайт на подпуть:

  1. Запустите сервер с флагом --prefix:

    ./server --prefix /conference
    
  2. Добавьте location в конфиг Angie/Nginx (готовый пример — angie.conf.example):

    location /conference/ {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 86400s;
        proxy_send_timeout 86400s;
    }
    

Прокси не обрезает префикс — сервер сам обрабатывает путь.
WebSocket автоматически использует wss:// если сайт работает по HTTPS.


🧪 Разработка

Для разработки рекомендуется запускать frontend и backend отдельно:

  • Frontend: cd frontend && ng serve доступен по http://localhost:4200.
  • Backend: cd backend && go run ./cmd/server -port=8080 доступен по http://localhost:8080.

Чтобы фронт обращался к бэкенду, настройте прокси (создайте frontend/proxy.conf.json):

{
  "/ws": {
    "target": "http://localhost:8080",
    "ws": true
  },
  "/upload": "http://localhost:8080",
  "/download": "http://localhost:8080"
}

Затем запускайте ng serve --proxy-config proxy.conf.json.


📦 Непрерывная интеграция

В корне репозитория находится файл .woodpecker.yml для Woodpecker CI.
При создании тега автоматически:

  1. Собирается фронтенд (ng build).
  2. Копируется в backend/cmd/server/static/ — туда, где //go:embed static подхватит файлы.
  3. Собирается Goбинарник (статика вшивается внутрь).
  4. Собирается Dockerобраз без слоя /static/ — только бинарник.

Эти шаги гарантируют, что релиз всегда содержит актуальные статические файлы.


🐛 Известные ограничения

  • База данных SQLite не рассчитана на высокую конкурентную запись (более 10 одновременных редакторов). Для реального использования с большим количеством организаторов рекомендуется перейти на PostgreSQL.
  • Нет поддержки нескольких конференций одновременно одна программа за раз (для новой конференции просто удалите БД и перезапустите сервер).
  • Загрузка файлов ограничена 10 МБ (можно изменить в коде).

🤝 Вклад в проект

Если у вас есть идеи по улучшению или вы нашли ошибку, создайте Issue или Pull Request.
Для локального тестирования используйте описанный выше процесс разработки.


📄 Лицензия

Проект распространяется под лицензией MIT. Подробнее в файле LICENSE.


✉️ Контакты

По вопросам поддержки и коммерческого использования обращайтесь к разработчику: [ваш email или ссылка].