feat: im1
This commit is contained in:
270
index.html
Normal file
270
index.html
Normal file
@@ -0,0 +1,270 @@
|
||||
<!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>
|
||||
Reference in New Issue
Block a user