vdkch/index.html
2025-02-10 15:53:52 +03:00

271 lines
8.4 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="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FutaClone</title>
<!-- Добавляем библиотеку для визуализации графа -->
<script src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script>
<style>
/* Добавляем новые стили */
#network {
width: 100%;
height: 600px;
border: 1px solid #800;
background: white;
}
.hidden { display: none; }
#greeting { text-align: center; padding: 20px; }
#graphContainer { margin-top: 20px; }
/* Стили в духе традиционных имиджборд */
body {
background-color: #F0E0D6;
font-family: Arial, sans-serif;
margin: 20px;
max-width: 800px;
margin-left: auto;
margin-right: auto;
}
.post-form {
background: #FFF;
border: 1px solid #800;
padding: 15px;
margin-bottom: 20px;
}
.post {
background: #FFF;
border: 1px solid #800;
padding: 15px;
margin-bottom: 10px;
}
.post img {
max-width: 200px;
max-height: 200px;
margin-top: 10px;
}
input, textarea, button {
margin: 5px;
padding: 5px;
}
.hidden {
display: none;
}
.preview-image {
max-width: 150px;
margin: 10px 0;
}
</style>
</head>
<body>
<!-- Добавляем новые блоки -->
<div id="greeting" class="hidden">
<h2>Отправьте первое сообщение, чтобы начать</h2>
</div>
<div id="graphContainer" class="hidden">
<h2>Древо мыслей</h2>
<div id="network"></div>
</div>
<!-- Форма создания поста -->
<div class="post-form">
<h2>Новый пост</h2>
<form id="postForm">
<textarea id="postText" rows="4" cols="50" placeholder="Текст поста"></textarea><br>
<input type="file" id="imageInput" accept="image/*"><br>
<div id="imagePreview" class="hidden"></div>
<button type="submit">Отправить</button>
</form>
</div>
<!-- Форма поиска (только текст) -->
<div class="post-form">
<h2>Поиск</h2>
<input type="text" id="searchText" placeholder="Текст для поиска">
<button onclick="searchPosts()">Искать</button>
</div>
<!-- Список постов -->
<div id="postsContainer"></div>
<script>
// Базовый URL бэкенда
const API_URL = 'http://localhost:8000';
// Обработка отправки поста (оставляем без изменений)
document.getElementById('postForm').addEventListener('submit', async (e) => {
e.preventDefault();
const text = document.getElementById('postText').value;
const fileInput = document.getElementById('imageInput');
const formData = new FormData();
if (text) formData.append('text', text);
if (fileInput.files[0]) formData.append('image', fileInput.files[0]);
try {
const response = await fetch(`${API_URL}/posts/`, {
method: 'POST',
body: formData
});
if (response.ok) {
const postData = await response.json();
// Сохраняем вектор в localStorage
localStorage.setItem('userVector', JSON.stringify(postData.vector));
checkUserVector();
loadPosts();
document.getElementById('postForm').reset();
document.getElementById('imagePreview').classList.add('hidden');
} else {
console.error('Error:', error);
}
} catch (error) {
console.error('Error:', error);
}
});
// Превью изображения перед загрузкой
document.getElementById('imageInput').addEventListener('change', function(e) {
const preview = document.getElementById('imagePreview');
if (this.files && this.files[0]) {
const reader = new FileReader();
reader.onload = function(e) {
preview.innerHTML = `<img src="${e.target.result}" class="preview-image">`;
preview.classList.remove('hidden');
}
reader.readAsDataURL(this.files[0]);
}
});
// Загрузка и отображение постов (оставляем без изменений)
async function loadPosts() {
try {
const response = await fetch(`${API_URL}/posts/`);
const posts = await response.json();
const container = document.getElementById('postsContainer');
container.innerHTML = posts.map(post => `
<div class="post">
<div class="post-meta">#${post.id} - ${new Date(post.created_at).toLocaleString()}</div>
${post.text ? `<div class="post-text">${post.text}</div>` : ''}
${post.image ? `<img src="${API_URL}/${post.image}" />` : ''}
</div>
`).join('');
} catch (error) {
console.error('Error:', error);
}
}
// Обновлённая функция поиска, использующая GET-запрос
async function searchPosts() {
const text = document.getElementById('searchText').value;
// Формируем строку запроса, если введён текст
const query = text ? `?text=${encodeURIComponent(text)}` : '';
try {
const response = await fetch(`${API_URL}/search/${query}`, {
method: 'GET'
});
if (!response.ok) {
throw new Error('Запрос поиска завершился с ошибкой');
}
const results = await response.json();
alert('Найдено постов: ' + results.length);
// Здесь можно добавить отображение результатов поиска в интерфейсе
} catch (error) {
console.error('Error during search:', error);
}
}
// Первоначальная загрузка постов
loadPosts();
// Новая функция проверки вектора
function checkUserVector() {
const hasVector = localStorage.getItem('userVector') !== null;
document.getElementById('greeting').classList.toggle('hidden', hasVector);
document.getElementById('graphContainer').classList.toggle('hidden', !hasVector);
if (hasVector) {
loadUserTree();
} else {
loadPosts();
}
}
// Функция загрузки дерева
async function loadUserTree() {
const userVector = JSON.parse(localStorage.getItem('userVector'));
if (!userVector) return;
try {
const response = await fetch(`${API_URL}/posts/tree`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ vector: userVector }),
});
const posts = await response.json();
renderGraph(posts);
} catch (error) {
console.error('Error loading tree:', error);
}
}
// Визуализация графа
function renderGraph(posts) {
const container = document.getElementById('network');
const nodes = [];
const edges = [];
posts.forEach((post, index) => {
nodes.push({
id: post.id,
label: post.text || '[Изображение]',
image: post.image ? `${API_URL}/${post.image}` : 'https://via.placeholder.com/100',
shape: 'circularImage',
size: 25
});
if (index > 0) {
edges.push({
from: posts[index-1].id,
to: post.id,
arrows: 'to',
smooth: { type: 'curvedCW' }
});
}
});
const data = { nodes, edges };
const options = {
nodes: {
borderWidth: 2,
color: {
border: '#800',
background: '#F0E0D6'
},
font: { size: 14 }
},
edges: {
color: '#800',
width: 2
},
physics: {
stabilization: true,
barnesHut: {
gravitationalConstant: -2000,
springLength: 200
}
}
};
new vis.Network(container, data, options);
}
// Инициализация при загрузке страницы
checkUserVector();
</script>
</body>
</html>