NoteJS/public/index.html
Fovway d89a617264 Добавлены функции для работы с AI настройками и улучшения текста
- Реализованы API для сохранения и получения AI настроек пользователя, включая OpenAI API ключ, базовый URL и модель.
- Добавлена возможность окончательного удаления всех архивных заметок с подтверждением пароля.
- Внедрена функция улучшения текста через AI, с обработкой запросов к OpenAI API.
- Обновлены интерфейсы для работы с AI настройками и добавлены уведомления для улучшения пользовательского опыта.
2025-10-26 14:45:02 +07:00

308 lines
10 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<title>Вход в систему заметок</title>
<script>
try {
if (localStorage.getItem("isAuthenticated") === "true") {
// Используем replace, чтобы не оставлять страницу логина в истории
window.location.replace("/notes");
}
} catch (e) {}
</script>
<!-- Предотвращение мерцания темы -->
<script>
(function () {
try {
const savedTheme = localStorage.getItem("theme");
const systemPrefersDark = window.matchMedia(
"(prefers-color-scheme: dark)"
).matches;
const theme = savedTheme || (systemPrefersDark ? "dark" : "light");
if (theme === "dark") {
document.documentElement.setAttribute("data-theme", "dark");
}
} catch (e) {}
})();
</script>
<!-- PWA Meta Tags -->
<meta
name="description"
content="NoteJS - современная система заметок с поддержкой Markdown, изображений, тегов и календаря"
/>
<meta name="theme-color" content="#007bff" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta
name="apple-mobile-web-app-status-bar-style"
content="black-translucent"
/>
<meta name="apple-mobile-web-app-title" content="NoteJS" />
<meta name="apple-touch-fullscreen" content="yes" />
<meta name="msapplication-TileColor" content="#007bff" />
<meta name="msapplication-config" content="/browserconfig.xml" />
<meta name="msapplication-TileImage" content="/icons/icon-144x144.png" />
<meta name="application-name" content="NoteJS" />
<meta name="format-detection" content="telephone=no" />
<!-- Icons -->
<link rel="icon" type="image/svg+xml" href="/icon.svg" />
<link
rel="icon"
type="image/png"
sizes="32x32"
href="/icons/icon-32x32.png"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="/icons/icon-16x16.png"
/>
<link rel="apple-touch-icon" sizes="57x57" href="/icons/icon-48x48.png" />
<link rel="apple-touch-icon" sizes="60x60" href="/icons/icon-48x48.png" />
<link rel="apple-touch-icon" sizes="72x72" href="/icons/icon-72x72.png" />
<link rel="apple-touch-icon" sizes="76x76" href="/icons/icon-72x72.png" />
<link
rel="apple-touch-icon"
sizes="114x114"
href="/icons/icon-128x128.png"
/>
<link
rel="apple-touch-icon"
sizes="120x120"
href="/icons/icon-128x128.png"
/>
<link
rel="apple-touch-icon"
sizes="144x144"
href="/icons/icon-144x144.png"
/>
<link
rel="apple-touch-icon"
sizes="152x152"
href="/icons/icon-152x152.png"
/>
<link
rel="apple-touch-icon"
sizes="180x180"
href="/icons/icon-192x192.png"
/>
<link rel="mask-icon" href="/icon.svg" color="#007bff" />
<!-- Manifest -->
<link rel="manifest" href="/manifest.json" />
<!-- Styles -->
<link rel="stylesheet" href="/style.css" />
<!-- Scripts -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/iconify/2.0.0/iconify.min.js"></script>
</head>
<body>
<div class="container">
<header>
<div
style="
display: flex;
align-items: center;
justify-content: space-between;
"
>
<span
><span class="iconify" data-icon="mdi:login"></span> Вход в
систему</span
>
<button
id="theme-toggle-btn"
class="theme-toggle-btn"
title="Переключить тему"
>
<span class="iconify" data-icon="mdi:theme-light-dark"></span>
</button>
</div>
</header>
<div class="login-form">
<form id="loginForm">
<div class="form-group">
<label for="username">Логин:</label>
<input
type="text"
id="username"
name="username"
required
placeholder="Введите ваш логин"
/>
</div>
<div class="form-group">
<label for="password">Пароль:</label>
<input
type="password"
id="password"
name="password"
required
placeholder="Введите пароль"
/>
</div>
<button type="submit" class="btnSave">Войти</button>
</form>
<div
id="errorMessage"
class="error-message"
style="display: none"
></div>
<p class="auth-link">
Нет аккаунта? <a href="/register">Зарегистрируйтесь</a>
</p>
</div>
</div>
<div class="footer">
<p>Создатель: <span>Fovway</span></p>
</div>
<script src="/login.js"></script>
<!-- PWA Service Worker Registration -->
<script>
// Универсальная функция для модальных окон подтверждения
function showConfirmModal(title, message, options = {}) {
return new Promise((resolve) => {
// Создаем модальное окно
const modal = document.createElement("div");
modal.className = "modal";
modal.style.display = "block";
// Создаем содержимое модального окна
const modalContent = document.createElement("div");
modalContent.className = "modal-content";
// Создаем заголовок
const modalHeader = document.createElement("div");
modalHeader.className = "modal-header";
modalHeader.innerHTML = `
<h3>${title}</h3>
<span class="modal-close">&times;</span>
`;
// Создаем тело модального окна
const modalBody = document.createElement("div");
modalBody.className = "modal-body";
modalBody.innerHTML = `<p>${message}</p>`;
// Создаем футер с кнопками
const modalFooter = document.createElement("div");
modalFooter.className = "modal-footer";
modalFooter.innerHTML = `
<button id="confirmBtn" class="${
options.confirmType === "danger" ? "btn-danger" : "btn-primary"
}" style="margin-right: 10px">
${options.confirmText || "OK"}
</button>
<button id="cancelBtn" class="btn-secondary">
${options.cancelText || "Отмена"}
</button>
`;
// Собираем модальное окно
modalContent.appendChild(modalHeader);
modalContent.appendChild(modalBody);
modalContent.appendChild(modalFooter);
modal.appendChild(modalContent);
// Добавляем на страницу
document.body.appendChild(modal);
// Функция закрытия
function closeModal() {
modal.style.display = "none";
if (modal.parentNode) {
modal.parentNode.removeChild(modal);
}
}
// Обработчики событий
const closeBtn = modalHeader.querySelector(".modal-close");
const cancelBtn = modalFooter.querySelector("#cancelBtn");
const confirmBtn = modalFooter.querySelector("#confirmBtn");
closeBtn.addEventListener("click", () => {
closeModal();
resolve(false);
});
cancelBtn.addEventListener("click", () => {
closeModal();
resolve(false);
});
confirmBtn.addEventListener("click", () => {
closeModal();
resolve(true);
});
// Закрытие при клике вне модального окна
modal.addEventListener("click", (e) => {
if (e.target === modal) {
closeModal();
resolve(false);
}
});
// Закрытие по Escape
const handleEscape = (e) => {
if (e.key === "Escape") {
closeModal();
resolve(false);
document.removeEventListener("keydown", handleEscape);
}
};
document.addEventListener("keydown", handleEscape);
});
}
if ("serviceWorker" in navigator) {
window.addEventListener("load", () => {
navigator.serviceWorker
.register("/sw.js")
.then((registration) => {
console.log("SW зарегистрирован успешно:", registration.scope);
// Проверяем обновления
registration.addEventListener("updatefound", () => {
const newWorker = registration.installing;
newWorker.addEventListener("statechange", async () => {
if (
newWorker.state === "installed" &&
navigator.serviceWorker.controller
) {
// Новый контент доступен, можно показать уведомление
const confirmed = await showConfirmModal(
"Обновление приложения",
"Доступна новая версия приложения. Обновить?",
{ confirmText: "Обновить" }
);
if (confirmed) {
newWorker.postMessage({ type: "SKIP_WAITING" });
window.location.reload();
}
}
});
});
})
.catch((error) => {
console.log("Ошибка регистрации SW:", error);
});
});
}
</script>
</body>
</html>