- TypeScript 36.9%
- Go 35.5%
- HTML 18.9%
- SCSS 7.2%
- Dockerfile 0.9%
- Other 0.6%
|
|
||
|---|---|---|
| backend | ||
| docs | ||
| frontend | ||
| .gitignore | ||
| .woodpecker.yml | ||
| angie.conf.example | ||
| Dockerfile | ||
| LICENSE | ||
| README.md | ||
Система управления программой конференции
Мгновенная синхронизация, загрузка презентаций, управление докладчиками и порядком выступлений — всё в одном веб-приложении.
🔥 Особенности
-
Три роли:
- Администратор – добавляет/исключает докладчиков, загружает файлы презентаций, меняет порядок выступлений.
- Модератор (оператор/секретарь) – отмечает выступления как прошедшие, скачивает файлы, сортирует программу.
- Зритель – просматривает программу в реальном времени (обновления с задержкой 30 секунд для снижения нагрузки).
-
Файлы презентаций – загрузка через веб-интерфейс, автоматическое сохранение на сервере.
-
Drag‑and‑drop – интуитивное перетаскивание докладов для изменения порядка.
-
Мгновенные обновления для организаторов, зрители получают обновления с накоплением (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)
Шаги
-
Клонировать репозиторий
git clone <repository-url> cd reception-conference -
Собрать фронтенд
cd frontend npm install ng build --prod --output-path=../backend/cmd/server/static cd .. -
Собрать бэкенд
cd backend go mod download go build -o conference-server ./cmd/server -
Запустить сервер
./conference-server -admin=myadmin -mod=mymod -db=./data.db -port=8080(Все параметры можно также задавать через переменные окружения, см. ниже.)
-
Открыть в браузере – перейдите на
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 |
Прочитан | Выступление отмечено как состоявшееся. |
Правила перехода:
pending→ready— администратор загружает файлready→done— модератор/администратор отмечает выступлениеdone→ready— модератор/администратор возвращает в работу
Ограничения по статусам:
- Редактировать (имя, тему) можно в статусах
pendingиready - Удалить участника можно в статусах
pendingиready(нельзя удалитьdone); исключённый (excluded) участник не редактируется и не удаляется
Массовый импорт через JSON
Администратор может загрузить несколько докладчиков одновременно через кнопку «Импорт» в тулбаре. Формат JSON:
[
{"name": "Иван Петров", "topic": "Квантовые вычисления"},
{"name": "Мария Сидорова", "topic": "Нейросети в медицине"}
]
Каждая запись проходит валидацию: name (1–100 символов) и topic (1–2000 байт). При ошибках импорт не прерывается — все ошибки собираются и показываются разом, а успешно прошедшие валидацию записи отправляются на сервер по одной через 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)
Если приложение встраивается в существующий сайт на подпуть:
-
Запустите сервер с флагом
--prefix:./server --prefix /conference -
Добавьте 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.
При создании тега автоматически:
- Собирается фронтенд (
ng build). - Копируется в
backend/cmd/server/static/— туда, где//go:embed staticподхватит файлы. - Собирается Go‑бинарник (статика вшивается внутрь).
- Собирается Docker‑образ без слоя
/static/— только бинарник.
Эти шаги гарантируют, что релиз всегда содержит актуальные статические файлы.
🐛 Известные ограничения
- База данных SQLite не рассчитана на высокую конкурентную запись (более 10 одновременных редакторов). Для реального использования с большим количеством организаторов рекомендуется перейти на PostgreSQL.
- Нет поддержки нескольких конференций одновременно – одна программа за раз (для новой конференции просто удалите БД и перезапустите сервер).
- Загрузка файлов ограничена 10 МБ (можно изменить в коде).
🤝 Вклад в проект
Если у вас есть идеи по улучшению или вы нашли ошибку, создайте Issue или Pull Request.
Для локального тестирования используйте описанный выше процесс разработки.
📄 Лицензия
Проект распространяется под лицензией MIT. Подробнее в файле LICENSE.
✉️ Контакты
По вопросам поддержки и коммерческого использования обращайтесь к разработчику: [ваш email или ссылка].