- Создана структура docs/ с категориями: completed, guides, architecture, diagnostic, in-progress, reports - Перемещено 47+ MD файлов из корня проекта в docs/ - Удалено 6 устаревших/дублирующихся файлов - Создана структура backend/scripts/ для тестов и утилит - Перемещено 35 Python скриптов в backend/scripts/ - Создана структура backend/docs/ для технической документации - Перемещено 12 MD файлов backend в backend/docs/ - Перемещены LDAP тестовые данные в backend/tests/fixtures/ - Добавлены README файлы для навигации - Добавлены правила в .github/copilot-instructions.md для размещения документации Результат: - Корень проекта: только README.md - Корень backend/: только manage.py и Django приложения - Вся документация организована в структурированные папки
12 KiB
12 KiB
Avatar Cropper Implementation for FaceID
📋 Описание
Реализован компонент обрезки аватара с требованиями для системы распознавания лиц (FaceID).
🎯 Цели
- ✅ Обеспечить единообразие фотографий для FaceID
- ✅ Гарантировать, что лицо занимает 70-80% кадра
- ✅ Минимальный размер: 600x600px
- ✅ Формат: JPEG с оптимизацией качества (92%)
- ✅ Интеграция в 2 места: регистрация + редактор профиля
🔧 Технические детали
Используемые технологии
- Cropper.js v1.6.1 - библиотека для обрезки изображений
- Bootstrap 5 Modal - модальное окно
- Canvas API - конвертация в нужный формат
- File API - работа с файлами
Компоненты
1. avatarCropperHandler.js
Основной модуль с классом AvatarCropper:
import { initAvatarCropper } from '/static/js/components/avatarCropperHandler.js';
// Инициализация
initAvatarCropper({
fileInputSelector: 'input[type="file"][name="avatar"]',
previewImageId: 'avatarPreview',
placeholderId: 'avatarPlaceholder',
modalId: 'avatarCropperModal'
});
Возможности:
- ✅ Автоматическое открытие cropper при выборе файла
- ✅ Валидация размера и формата
- ✅ Квадратная область обрезки (1:1)
- ✅ Минимальный размер обрезки: 200x200px
- ✅ Выходной размер: 800x800px
- ✅ Качество JPEG: 92%
- ✅ Индикатор размера в реальном времени
- ✅ Превью обрезанного изображения
- ✅ Автоматическое обновление file input
Интеграция
Место 1: Регистрация (templates/auth/register.html)
<!-- Cropper.js CDN -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.6.1/cropper.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.6.1/cropper.min.js"></script>
<script type="module">
import { initAvatarCropper } from "{% static 'js/components/avatarCropperHandler.js' %}";
initAvatarCropper({
fileInputSelector: 'input[type="file"][name="avatar"]',
previewImageId: 'avatarPreview',
placeholderId: 'avatarPlaceholder'
});
</script>
Место 2: Редактор профиля (templates/employees/components/employee_form_scripts.html)
<!-- Cropper.js CDN -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.6.1/cropper.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.6.1/cropper.min.js"></script>
<script type="module">
import { initAvatarCropper } from '{% static "js/components/avatarCropperHandler.js" %}';
initAvatarCropper({
fileInputSelector: '#avatarInput',
previewImageId: 'avatarPreview',
modalId: 'avatarCropperModal'
});
</script>
📝 Требования FaceID
Обязательные требования:
- ✅ Размер лица: 70-80% кадра
- ✅ Центрирование: Лицо в центре рамки
- ✅ Минимальный размер: 600x600px
- ✅ Соотношение сторон: 1:1 (квадрат)
- ✅ Формат: JPEG
- ✅ Качество: 92%
Рекомендации для пользователей:
- Избегайте теней и бликов
- Смотрите прямо в камеру
- Нейтральное выражение лица
- Хорошее освещение
🎨 UI/UX
Модальное окно cropper
┌─────────────────────────────────────────┐
│ Обрезка фото для FaceID [X] │
├─────────────────────────────────────────┤
│ │
│ ℹ️ Требования для системы распознавания:│
│ • Лицо должно занимать 70-80% кадра │
│ • Расположите лицо в центре рамки │
│ • Избегайте теней и бликов │
│ • Смотрите прямо в камеру │
│ • Нейтральное выражение лица │
│ │
│ ┌───────────────────────────────────┐ │
│ │ │ │
│ │ [Cropper Canvas Area] │ │
│ │ │ │
│ └───────────────────────────────────┘ │
│ │
│ Размер обрезанного фото: 800x800px │
│ │
├─────────────────────────────────────────┤
│ [Отмена] [✓ Применить] │
└─────────────────────────────────────────┘
Превью в форме
- До выбора: Иконка placeholder (bi-person или bi-person-circle)
- После обрезки: Обрезанное изображение 120x120px
- Подсказка: Текст с требованиями FaceID
🚀 Workflow
Шаг 1: Пользователь выбирает файл
Input[type=file] → change event
Шаг 2: Валидация
✓ Формат: JPG, PNG, GIF
✓ Размер: < 10 MB
✓ Минимальный размер: 600x600px
Шаг 3: Открытие Cropper
FileReader → DataURL → Modal → Cropper.js init
Шаг 4: Обрезка
User adjusts crop area → Real-time size indicator
Шаг 5: Применение
getCroppedCanvas(800x800) → Blob → File → Update input
Шаг 6: Превью
Canvas → DataURL → Update preview image
Шаг 7: Отправка формы
FormData with cropped file → Backend API
📊 Конфигурация
Настройки по умолчанию:
{
// Cropper.js options
aspectRatio: 1,
viewMode: 2,
dragMode: 'move',
autoCropArea: 0.8,
minCropBoxWidth: 200,
minCropBoxHeight: 200,
// Output settings
minOutputSize: 600,
outputSize: 800,
outputQuality: 0.92,
outputFormat: 'image/jpeg',
// Validation
maxFileSize: 10 * 1024 * 1024, // 10 MB
allowedFormats: ['image/jpeg', 'image/png', 'image/gif']
}
Кастомизация:
initAvatarCropper({
// Селекторы
fileInputSelector: '#myAvatarInput',
previewImageId: 'myPreview',
modalId: 'myCropperModal',
// Cropper опции
cropperOptions: {
aspectRatio: 1,
autoCropArea: 0.9
},
// Выходные параметры
outputSize: 1024,
outputQuality: 0.95,
// Тексты
texts: {
modalTitle: 'Обрезать фото',
cropButton: 'Готово',
cancelButton: 'Отмена'
}
});
🧪 Тестирование
Тестовые сценарии:
-
Регистрация нового пользователя
- Открыть
/auth/register/ - Выбрать фото
- Проверить открытие cropper
- Обрезать фото
- Отправить форму
- Проверить, что аватар сохранился
- Открыть
-
Редактирование профиля
- Открыть
/employees/profile/ - Выбрать новое фото
- Обрезать фото
- Сохранить изменения
- Проверить обновление аватара
- Открыть
-
Валидация
- Попытаться загрузить файл < 600x600px → Ошибка
- Попытаться загрузить файл > 10MB → Ошибка
- Попытаться загрузить .txt файл → Ошибка
-
Отмена
- Выбрать фото
- Открыть cropper
- Нажать "Отмена"
- Проверить, что input очищен
📦 Зависимости
CDN (используется):
<!-- Cropper.js CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.6.1/cropper.min.css"
integrity="sha512-hvNR0F/e2J7zPPfLC9auFe3/SE0yG4aJCOd/qxew74NN7eyiSKjr7xJJMu1Jy2wf7FXITpWS1E/RY8yzuXN7VA=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<!-- Cropper.js JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.6.1/cropper.min.js"
integrity="sha512-9KkIqdfN7ipEW6B6k+Aq20PV31bjODg4AA52W+tYtAE0jE0kMx49bjJ3FgvS56wzmyfMUHbQ4Km2b7l9+Y/+Eg=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
Существующие зависимости:
- ✅ Bootstrap 5 (для модального окна)
- ✅ Bootstrap Icons (для иконок)
🔍 Troubleshooting
Проблема: Cropper не открывается
Решение: Проверьте, что Cropper.js загружен из CDN и Bootstrap модальные окна работают.
Проблема: File input не обновляется
Решение: Проверьте console на ошибки. Убедитесь, что DataTransfer API поддерживается.
Проблема: Превью не обновляется
Решение: Проверьте селекторы previewImageId и placeholderId.
Проблема: Ошибка "Image too small"
Решение: Убедитесь, что исходное изображение >= 600x600px.
✅ Checklist
Файлы созданы:
- ✅
backend/static/js/components/avatarCropperHandler.js(542 строки) - ✅
AVATAR_CROPPER_IMPLEMENTATION.md(этот файл)
Файлы изменены:
- ✅
backend/templates/auth/register.html- добавлен cropper - ✅
backend/templates/employees/components/employee_form_scripts.html- добавлен cropper - ✅
backend/templates/employees/components/employee_form_personal.html- обновлен текст подсказки
Функционал:
- ✅ Валидация размера файла (10 MB)
- ✅ Валидация формата (JPG, PNG, GIF)
- ✅ Валидация минимального размера (600x600px)
- ✅ Cropper с квадратной областью (1:1)
- ✅ Индикатор размера в реальном времени
- ✅ Превью обрезанного изображения
- ✅ Обновление file input
- ✅ Инструкции для FaceID
- ✅ Модальное окно Bootstrap
- ✅ Обработка ошибок
- ✅ Cleanup при закрытии
🎉 Готово к тестированию!
Все изменения в ветке feature/avatar-validation.
Следующие шаги:
- Тестирование на локальном сервере
- Проверка валидации
- Проверка сохранения аватара
- Коммит и push изменений
- Создание PR в master (после тестирования)