Добавлена возможность изменения ширины AI Drawer
- Добавлен resize handle (полоска для перетаскивания) слева от drawer - Реализовано изменение ширины перетаскиванием (от 300px до 50% экрана) - Сохранение ширины в localStorage - Автоматическое обновление margin для main-container - Обработка изменения размера окна браузера - Скрытие resize handle на мобильных устройствах
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
right: -400px; /* Начально скрыт */
|
||||
top: 0;
|
||||
width: 400px;
|
||||
min-width: 300px; /* Минимальная ширина */
|
||||
max-width: 50vw; /* Максимальная ширина - половина экрана */
|
||||
height: 100vh;
|
||||
background: #ffffff; /* Чистый белый фон */
|
||||
box-shadow: -2px 0 15px rgba(0,0,0,0.1);
|
||||
@@ -15,6 +17,38 @@
|
||||
border-left: 1px solid #e9ecef;
|
||||
}
|
||||
|
||||
/* Полоска для изменения ширины */
|
||||
.ai-drawer-resize-handle {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 4px;
|
||||
height: 100%;
|
||||
cursor: ew-resize;
|
||||
background: transparent;
|
||||
z-index: 1000000;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.ai-drawer-resize-handle:hover {
|
||||
background: #007bff;
|
||||
}
|
||||
|
||||
.ai-drawer-resize-handle:active {
|
||||
background: #0056b3;
|
||||
}
|
||||
|
||||
/* Визуальная индикация при перетаскивании */
|
||||
.ai-drawer.resizing {
|
||||
transition: none !important;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.ai-drawer.resizing .ai-drawer-resize-handle {
|
||||
background: #007bff;
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
.ai-drawer.open {
|
||||
right: 0;
|
||||
}
|
||||
@@ -192,6 +226,11 @@ body.ai-drawer-open .ai-drawer-toggle {
|
||||
margin-right: 400px;
|
||||
}
|
||||
|
||||
/* Динамический margin для main-container при изменении ширины drawer */
|
||||
.main-container.drawer-open[data-drawer-width] {
|
||||
margin-right: var(--drawer-width, 400px);
|
||||
}
|
||||
|
||||
/* Плавающий индикатор загрузки */
|
||||
.ai-loading-overlay {
|
||||
position: fixed;
|
||||
@@ -476,6 +515,13 @@ body.ai-drawer-open .ai-drawer-toggle {
|
||||
height: 100dvh; /* Динамическая высота viewport для мобильных */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* Скрываем resize handle на мобильных */
|
||||
.ai-drawer-resize-handle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.main-container.drawer-open {
|
||||
@@ -683,6 +729,8 @@ body.ai-drawer-open .ai-drawer-toggle {
|
||||
/* Десктопная версия drawer */
|
||||
.ai-drawer {
|
||||
width: 400px;
|
||||
min-width: 300px;
|
||||
max-width: 50vw;
|
||||
right: -400px;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
|
||||
@@ -5,6 +5,8 @@ class AIDrawer {
|
||||
this.avatarType = 'default';
|
||||
this.sessionId = null;
|
||||
this.currentEventSource = null; // Для SSE соединения
|
||||
this.drawerWidth = 400; // Текущая ширина drawer
|
||||
this.isResizing = false; // Флаг перетаскивания
|
||||
this.init();
|
||||
|
||||
// Загружаем историю сразу при инициализации (при загрузке страницы)
|
||||
@@ -21,6 +23,7 @@ class AIDrawer {
|
||||
const drawerHTML =
|
||||
'<button class="ai-drawer-toggle">AI</button>' +
|
||||
'<div class="ai-drawer font-normal">' +
|
||||
'<div class="ai-drawer-resize-handle"></div>' +
|
||||
'<div class="ai-drawer-header">' +
|
||||
'<span>AI Ассистент</span>' +
|
||||
'<button class="ai-drawer-close">×</button>' +
|
||||
@@ -73,6 +76,7 @@ class AIDrawer {
|
||||
this.avatarButtons = document.querySelectorAll('.avatar-btn');
|
||||
this.chatInput = document.querySelector('#ai-chat-input');
|
||||
this.sendButton = document.querySelector('#ai-send-button');
|
||||
this.resizeHandle = document.querySelector('.ai-drawer-resize-handle');
|
||||
|
||||
// Обработчики событий
|
||||
if (this.toggleBtn) {
|
||||
@@ -119,8 +123,91 @@ class AIDrawer {
|
||||
// Восстанавливаем настройки
|
||||
this.restoreSettings();
|
||||
|
||||
// Инициализируем изменение размера
|
||||
this.initResize();
|
||||
|
||||
// Обработчик изменения размера окна - ограничиваем ширину если нужно
|
||||
window.addEventListener('resize', () => {
|
||||
if (this.drawerWidth > window.innerWidth / 2) {
|
||||
const maxWidth = window.innerWidth / 2;
|
||||
this.setDrawerWidth(maxWidth);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('AI Drawer: Простая инициализация завершена');
|
||||
}
|
||||
|
||||
initResize() {
|
||||
if (!this.resizeHandle || !this.drawer) return;
|
||||
|
||||
// Загружаем сохраненную ширину
|
||||
const savedWidth = localStorage.getItem('ai-drawer-width');
|
||||
if (savedWidth) {
|
||||
const width = parseInt(savedWidth, 10);
|
||||
if (width >= 300 && width <= window.innerWidth / 2) {
|
||||
this.setDrawerWidth(width);
|
||||
}
|
||||
}
|
||||
|
||||
// Обработчики для перетаскивания
|
||||
this.resizeHandle.addEventListener('mousedown', (e) => {
|
||||
e.preventDefault();
|
||||
this.startResize(e);
|
||||
});
|
||||
}
|
||||
|
||||
startResize(e) {
|
||||
this.isResizing = true;
|
||||
this.drawer.classList.add('resizing');
|
||||
document.body.style.cursor = 'ew-resize';
|
||||
document.body.style.userSelect = 'none';
|
||||
|
||||
const startX = e.clientX;
|
||||
const startWidth = this.drawerWidth;
|
||||
|
||||
const doResize = (e) => {
|
||||
if (!this.isResizing) return;
|
||||
|
||||
const diff = startX - e.clientX; // Инвертируем, т.к. drawer справа
|
||||
const newWidth = Math.max(300, Math.min(window.innerWidth / 2, startWidth + diff));
|
||||
|
||||
this.setDrawerWidth(newWidth);
|
||||
};
|
||||
|
||||
const stopResize = () => {
|
||||
this.isResizing = false;
|
||||
this.drawer.classList.remove('resizing');
|
||||
document.body.style.cursor = '';
|
||||
document.body.style.userSelect = '';
|
||||
document.removeEventListener('mousemove', doResize);
|
||||
document.removeEventListener('mouseup', stopResize);
|
||||
|
||||
// Сохраняем ширину
|
||||
localStorage.setItem('ai-drawer-width', this.drawerWidth.toString());
|
||||
};
|
||||
|
||||
document.addEventListener('mousemove', doResize);
|
||||
document.addEventListener('mouseup', stopResize);
|
||||
}
|
||||
|
||||
setDrawerWidth(width) {
|
||||
if (this.drawer) {
|
||||
// Ограничиваем ширину максимум до половины экрана и минимум 300px
|
||||
const maxWidth = window.innerWidth / 2;
|
||||
const finalWidth = Math.max(300, Math.min(maxWidth, width));
|
||||
this.drawerWidth = finalWidth;
|
||||
|
||||
this.drawer.style.width = finalWidth + 'px';
|
||||
|
||||
// Обновляем margin для main-container
|
||||
const mainContainer = document.querySelector('.main-container');
|
||||
if (mainContainer && this.isOpen) {
|
||||
mainContainer.style.setProperty('--drawer-width', finalWidth + 'px');
|
||||
mainContainer.style.marginRight = finalWidth + 'px';
|
||||
mainContainer.setAttribute('data-drawer-width', finalWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
toggle() {
|
||||
if (this.isOpen) {
|
||||
@@ -139,6 +226,14 @@ class AIDrawer {
|
||||
document.body.classList.add('ai-drawer-open');
|
||||
this.isOpen = true;
|
||||
|
||||
// Обновляем margin для main-container с текущей шириной
|
||||
const mainContainer = document.querySelector('.main-container');
|
||||
if (mainContainer) {
|
||||
mainContainer.style.setProperty('--drawer-width', this.drawerWidth + 'px');
|
||||
mainContainer.style.marginRight = this.drawerWidth + 'px';
|
||||
mainContainer.setAttribute('data-drawer-width', this.drawerWidth);
|
||||
}
|
||||
|
||||
// История уже загружена при инициализации страницы
|
||||
// Не нужно дополнительных запросов при открытии
|
||||
}
|
||||
@@ -151,6 +246,13 @@ class AIDrawer {
|
||||
|
||||
document.body.classList.remove('ai-drawer-open');
|
||||
this.isOpen = false;
|
||||
|
||||
// Убираем margin у main-container
|
||||
const mainContainer = document.querySelector('.main-container');
|
||||
if (mainContainer) {
|
||||
mainContainer.style.marginRight = '';
|
||||
mainContainer.removeAttribute('data-drawer-width');
|
||||
}
|
||||
}
|
||||
|
||||
setFontSize(size) {
|
||||
|
||||
Reference in New Issue
Block a user