13.08.2026 налажена работа с ИИ. Подготовка к разбивке файлов agent и db_tools

This commit is contained in:
2026-08-13 14:21:43 +03:00
parent a622fd98d2
commit fc1a608a5f
13 changed files with 3628 additions and 210 deletions
+124 -3
View File
@@ -1,3 +1,11 @@
// Вспомогательная функция для автоматического изменения высоты текстового поля (1-3 строки)
function updateInputHeight(el) {
if (!el) return;
el.style.height = "24px";
const newHeight = Math.min(el.scrollHeight, 120);
el.style.height = newHeight + "px";
}
let selectedFile = null;
function handleFileSelect(e) {
@@ -57,7 +65,7 @@ async function sendMessage(e) {
chatWindow.insertAdjacentHTML("beforeend", userMsgHtml);
input.value = "";
input.style.height = "auto";
updateInputHeight(input);
chatWindow.scrollTop = chatWindow.scrollHeight;
if (sendBtn) {
@@ -70,7 +78,6 @@ async function sendMessage(e) {
const endpoint = isGuest ? "/api/v1/chat/guest" : "/api/v1/chat";
// Формируем единый FormData без дублирования
const formData = new FormData();
formData.append("session_id", "web_session_main");
formData.append("message", text || "Проанализируй прикрепленный файл");
@@ -142,4 +149,118 @@ function escapeHtml(text) {
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
}
document.addEventListener("DOMContentLoaded", () => {
const input = document.getElementById("user-input");
const dropZone = document.getElementById("chat-window")?.parentElement;
const dropOverlay = document.getElementById("drop-overlay");
// --- 1. УМНАЯ НАВИГАЦИЯ СТРЕЛКАМИ В МНОГОСТРОЧНОМ ТЕКСТЕ ---
if (input) {
let historyIndex = -1;
let localHistory = JSON.parse(localStorage.getItem("scud_chat_input_history") || "[]");
input.addEventListener("keydown", (e) => {
// Отправка по Enter без Shift
if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault();
const text = input.value.trim();
if (text) {
if (localHistory.length === 0 || localHistory[0] !== text) {
localHistory.unshift(text);
if (localHistory.length > 50) localHistory.pop();
localStorage.setItem("scud_chat_input_history", JSON.stringify(localHistory));
}
historyIndex = -1;
}
sendMessage(e);
updateInputHeight(input);
return;
}
// Стрелка ВВЕРХ
if (e.key === "ArrowUp") {
const textBeforeCursor = input.value.substring(0, input.selectionStart);
const isFirstLine = !textBeforeCursor.includes("\n");
// Переключаем историю ТОЛЬКО когда курсор на 1-й строке И уперся в самое начало (позиция 0)
if (isFirstLine && input.selectionStart === 0 && localHistory.length > 0) {
if (historyIndex < localHistory.length - 1) {
e.preventDefault();
if (historyIndex === -1) {
input.dataset.draft = input.value;
}
historyIndex++;
input.value = localHistory[historyIndex];
updateInputHeight(input);
input.setSelectionRange(input.value.length, input.value.length);
}
}
}
// Стрелка ВНИЗ
if (e.key === "ArrowDown") {
const textAfterCursor = input.value.substring(input.selectionEnd);
const isLastLine = !textAfterCursor.includes("\n");
// Переключаем историю ТОЛЬКО когда курсор на последней строке И уперся в самый конец
if (isLastLine && input.selectionEnd === input.value.length && historyIndex >= 0) {
e.preventDefault();
if (historyIndex > 0) {
historyIndex--;
input.value = localHistory[historyIndex];
} else {
historyIndex = -1;
input.value = input.dataset.draft || "";
}
updateInputHeight(input);
input.setSelectionRange(input.value.length, input.value.length);
}
}
});
}
// --- 2. ОБРАБОТКА DRAG-AND-DROP ФАЙЛОВ ---
if (dropZone && dropOverlay) {
["dragenter", "dragover", "dragleave", "drop"].forEach(eventName => {
dropZone.addEventListener(eventName, (e) => {
e.preventDefault();
e.stopPropagation();
}, false);
});
["dragenter", "dragover"].forEach(eventName => {
dropZone.addEventListener(eventName, () => {
dropOverlay.classList.remove("hidden");
dropOverlay.classList.add("flex");
}, false);
});
["dragleave", "drop"].forEach(eventName => {
dropZone.addEventListener(eventName, (e) => {
if (eventName === "drop" || e.target === dropZone || !dropZone.contains(e.relatedTarget)) {
dropOverlay.classList.add("hidden");
dropOverlay.classList.remove("flex");
}
}, false);
});
dropZone.addEventListener("drop", (e) => {
const dt = e.dataTransfer;
const files = dt.files;
if (files && files.length > 0) {
const file = files[0];
handleFileSelect({ target: { files: [file] } });
const fileInput = document.getElementById("file-input");
if (fileInput) {
const dataTransfer = new DataTransfer();
dataTransfer.items.add(file);
fileInput.files = dataTransfer.files;
}
}
}, false);
}
});