|
|
<!DOCTYPE html> |
|
|
<html lang="ru"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>ChatGPT с генерацией изображений</title> |
|
|
<script src="https://cdn.tailwindcss.com"></script> |
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
|
|
<style> |
|
|
@keyframes pulse { |
|
|
0%, 100% { opacity: 1; } |
|
|
50% { opacity: 0.5; } |
|
|
} |
|
|
.typing-indicator span { |
|
|
animation: pulse 1.5s infinite; |
|
|
} |
|
|
.typing-indicator span:nth-child(2) { |
|
|
animation-delay: 0.2s; |
|
|
} |
|
|
.typing-indicator span:nth-child(3) { |
|
|
animation-delay: 0.4s; |
|
|
} |
|
|
.message-enter { |
|
|
animation: messageEnter 0.3s ease-out; |
|
|
} |
|
|
@keyframes messageEnter { |
|
|
from { |
|
|
opacity: 0; |
|
|
transform: translateY(10px); |
|
|
} |
|
|
to { |
|
|
opacity: 1; |
|
|
transform: translateY(0); |
|
|
} |
|
|
} |
|
|
.scrollbar-hide::-webkit-scrollbar { |
|
|
display: none; |
|
|
} |
|
|
.scrollbar-hide { |
|
|
-ms-overflow-style: none; |
|
|
scrollbar-width: none; |
|
|
} |
|
|
.tab-button { |
|
|
transition: all 0.2s ease; |
|
|
} |
|
|
.tab-button.active { |
|
|
border-bottom: 2px solid #10B981; |
|
|
color: #10B981; |
|
|
font-weight: 500; |
|
|
} |
|
|
.generated-image { |
|
|
transition: transform 0.3s ease; |
|
|
} |
|
|
.generated-image:hover { |
|
|
transform: scale(1.03); |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body class="bg-gray-50 h-screen flex flex-col"> |
|
|
|
|
|
<header class="bg-white border-b border-gray-200 py-3 px-4 flex items-center justify-between"> |
|
|
<div class="flex items-center space-x-2"> |
|
|
<div class="w-8 h-8 rounded-full bg-green-500 flex items-center justify-center text-white font-bold">C</div> |
|
|
<h1 class="text-lg font-semibold">ChatGPT</h1> |
|
|
</div> |
|
|
<div class="flex items-center space-x-4"> |
|
|
<button class="text-gray-500 hover:text-gray-700"> |
|
|
<i class="fas fa-sun"></i> |
|
|
</button> |
|
|
<button class="text-gray-500 hover:text-gray-700"> |
|
|
<i class="fas fa-cog"></i> |
|
|
</button> |
|
|
</div> |
|
|
</header> |
|
|
|
|
|
|
|
|
<div class="bg-white border-b border-gray-200 px-4"> |
|
|
<div class="max-w-3xl mx-auto flex space-x-6"> |
|
|
<button id="chat-tab" class="tab-button active py-3">Чат</button> |
|
|
<button id="image-tab" class="tab-button py-3">Генератор изображений</button> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div id="chat-section" class="flex-1 overflow-y-auto scrollbar-hide py-4 px-4 space-y-6"> |
|
|
|
|
|
<div class="max-w-3xl mx-auto message-enter"> |
|
|
<div class="flex space-x-4"> |
|
|
<div class="flex-shrink-0 w-8 h-8 rounded-full bg-green-500 flex items-center justify-center text-white font-bold">C</div> |
|
|
<div class="flex-1"> |
|
|
<div class="bg-white p-4 rounded-lg shadow-sm"> |
|
|
<p class="text-gray-800">Привет! Я ChatGPT, ваш ИИ-помощник. Чем могу помочь сегодня?</p> |
|
|
</div> |
|
|
<div class="mt-2 flex space-x-4 text-sm text-gray-500"> |
|
|
<button class="hover:bg-gray-100 px-2 py-1 rounded">Идеи для проекта</button> |
|
|
<button class="hover:bg-gray-100 px-2 py-1 rounded">Объяснить тему</button> |
|
|
<button class="hover:bg-gray-100 px-2 py-1 rounded">Помощь с кодом</button> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div id="image-section" class="flex-1 overflow-y-auto scrollbar-hide py-4 px-4 space-y-6 hidden"> |
|
|
<div class="max-w-3xl mx-auto message-enter"> |
|
|
<div class="flex space-x-4"> |
|
|
<div class="flex-shrink-0 w-8 h-8 rounded-full bg-green-500 flex items-center justify-center text-white font-bold">C</div> |
|
|
<div class="flex-1"> |
|
|
<div class="bg-white p-4 rounded-lg shadow-sm"> |
|
|
<p class="text-gray-800">Я могу генерировать изображения по вашему описанию. Просто напишите, что вы хотите увидеть, например: "Кот в космосе в стиле Ван Гога"</p> |
|
|
</div> |
|
|
<div class="mt-4 grid grid-cols-1 md:grid-cols-2 gap-4" id="image-examples"> |
|
|
<div class="bg-gray-100 rounded-lg overflow-hidden"> |
|
|
<img src="https://source.unsplash.com/random/300x300/?cat,space,art" alt="Пример изображения" class="w-full h-48 object-cover generated-image"> |
|
|
<div class="p-3"> |
|
|
<p class="text-sm text-gray-600">"Кот в космосе"</p> |
|
|
</div> |
|
|
</div> |
|
|
<div class="bg-gray-100 rounded-lg overflow-hidden"> |
|
|
<img src="https://source.unsplash.com/random/300x300/?fantasy,castle" alt="Пример изображения" class="w-full h-48 object-cover generated-image"> |
|
|
<div class="p-3"> |
|
|
<p class="text-sm text-gray-600">"Фэнтезийный замок"</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
<div id="image-results" class="max-w-3xl mx-auto space-y-4"></div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="bg-white border-t border-gray-200 py-4 px-4"> |
|
|
<div class="max-w-3xl mx-auto relative"> |
|
|
<form id="chat-form" class="relative"> |
|
|
<textarea |
|
|
id="message-input" |
|
|
rows="1" |
|
|
placeholder="Напишите сообщение..." |
|
|
class="w-full border border-gray-300 rounded-lg py-3 px-4 pr-12 focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent resize-none" |
|
|
style="min-height: 60px; max-height: 200px;"></textarea> |
|
|
<button |
|
|
type="submit" |
|
|
id="send-button" |
|
|
class="absolute right-2 bottom-2 w-8 h-8 rounded-md bg-green-500 text-white flex items-center justify-center hover:bg-green-600 disabled:opacity-50 disabled:cursor-not-allowed" |
|
|
disabled> |
|
|
<i class="fas fa-paper-plane"></i> |
|
|
</button> |
|
|
</form> |
|
|
<div class="mt-2 text-xs text-gray-500 text-center"> |
|
|
ChatGPT может допускать ошибки. Проверяйте важную информацию. |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<script> |
|
|
document.addEventListener('DOMContentLoaded', function() { |
|
|
const chatForm = document.getElementById('chat-form'); |
|
|
const messageInput = document.getElementById('message-input'); |
|
|
const sendButton = document.getElementById('send-button'); |
|
|
const chatContainer = document.getElementById('chat-section'); |
|
|
const imageResults = document.getElementById('image-results'); |
|
|
const chatTab = document.getElementById('chat-tab'); |
|
|
const imageTab = document.getElementById('image-tab'); |
|
|
const chatSection = document.getElementById('chat-section'); |
|
|
const imageSection = document.getElementById('image-section'); |
|
|
|
|
|
let currentMode = 'chat'; |
|
|
|
|
|
|
|
|
chatTab.addEventListener('click', function() { |
|
|
currentMode = 'chat'; |
|
|
chatTab.classList.add('active'); |
|
|
imageTab.classList.remove('active'); |
|
|
chatSection.classList.remove('hidden'); |
|
|
imageSection.classList.add('hidden'); |
|
|
messageInput.placeholder = "Напишите сообщение..."; |
|
|
}); |
|
|
|
|
|
imageTab.addEventListener('click', function() { |
|
|
currentMode = 'image'; |
|
|
imageTab.classList.add('active'); |
|
|
chatTab.classList.remove('active'); |
|
|
imageSection.classList.remove('hidden'); |
|
|
chatSection.classList.add('hidden'); |
|
|
messageInput.placeholder = "Опишите изображение для генерации..."; |
|
|
}); |
|
|
|
|
|
|
|
|
messageInput.addEventListener('input', function() { |
|
|
this.style.height = 'auto'; |
|
|
this.style.height = (this.scrollHeight) + 'px'; |
|
|
sendButton.disabled = this.value.trim() === ''; |
|
|
}); |
|
|
|
|
|
|
|
|
chatForm.addEventListener('submit', function(e) { |
|
|
e.preventDefault(); |
|
|
const message = messageInput.value.trim(); |
|
|
if (message) { |
|
|
if (currentMode === 'chat') { |
|
|
addUserMessage(message); |
|
|
showTypingIndicator(); |
|
|
setTimeout(() => { |
|
|
removeTypingIndicator(); |
|
|
addAiResponse(message); |
|
|
}, 1000 + Math.random() * 2000); |
|
|
} else { |
|
|
addUserImageRequest(message); |
|
|
showImageLoading(); |
|
|
setTimeout(() => { |
|
|
removeImageLoading(); |
|
|
generateImages(message); |
|
|
}, 1500 + Math.random() * 2000); |
|
|
} |
|
|
|
|
|
messageInput.value = ''; |
|
|
messageInput.style.height = 'auto'; |
|
|
sendButton.disabled = true; |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
function addUserMessage(message) { |
|
|
const messageDiv = document.createElement('div'); |
|
|
messageDiv.className = 'max-w-3xl mx-auto message-enter'; |
|
|
messageDiv.innerHTML = ` |
|
|
<div class="flex space-x-4 justify-end"> |
|
|
<div class="flex-1 max-w-[80%]"> |
|
|
<div class="bg-green-500 text-white p-4 rounded-lg shadow-sm"> |
|
|
<p>${message}</p> |
|
|
</div> |
|
|
</div> |
|
|
<div class="flex-shrink-0 w-8 h-8 rounded-full bg-gray-300 flex items-center justify-center text-gray-600"> |
|
|
<i class="fas fa-user"></i> |
|
|
</div> |
|
|
</div> |
|
|
`; |
|
|
chatContainer.appendChild(messageDiv); |
|
|
scrollToBottom(); |
|
|
} |
|
|
|
|
|
|
|
|
function addUserImageRequest(message) { |
|
|
const messageDiv = document.createElement('div'); |
|
|
messageDiv.className = 'max-w-3xl mx-auto message-enter'; |
|
|
messageDiv.innerHTML = ` |
|
|
<div class="flex space-x-4 justify-end"> |
|
|
<div class="flex-1 max-w-[80%]"> |
|
|
<div class="bg-green-500 text-white p-4 rounded-lg shadow-sm"> |
|
|
<p>Сгенерируй изображение: ${message}</p> |
|
|
</div> |
|
|
</div> |
|
|
<div class="flex-shrink-0 w-8 h-8 rounded-full bg-gray-300 flex items-center justify-center text-gray-600"> |
|
|
<i class="fas fa-user"></i> |
|
|
</div> |
|
|
</div> |
|
|
`; |
|
|
imageResults.appendChild(messageDiv); |
|
|
scrollToBottom(); |
|
|
} |
|
|
|
|
|
|
|
|
function showTypingIndicator() { |
|
|
const typingDiv = document.createElement('div'); |
|
|
typingDiv.className = 'max-w-3xl mx-auto message-enter'; |
|
|
typingDiv.id = 'typing-indicator'; |
|
|
typingDiv.innerHTML = ` |
|
|
<div class="flex space-x-4"> |
|
|
<div class="flex-shrink-0 w-8 h-8 rounded-full bg-green-500 flex items-center justify-center text-white font-bold">C</div> |
|
|
<div class="flex-1"> |
|
|
<div class="bg-white p-4 rounded-lg shadow-sm w-20"> |
|
|
<div class="typing-indicator flex space-x-1"> |
|
|
<span class="w-2 h-2 rounded-full bg-gray-400"></span> |
|
|
<span class="w-2 h-2 rounded-full bg-gray-400"></span> |
|
|
<span class="w-2 h-2 rounded-full bg-gray-400"></span> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
`; |
|
|
chatContainer.appendChild(typingDiv); |
|
|
scrollToBottom(); |
|
|
} |
|
|
|
|
|
|
|
|
function showImageLoading() { |
|
|
const loadingDiv = document.createElement('div'); |
|
|
loadingDiv.className = 'max-w-3xl mx-auto message-enter'; |
|
|
loadingDiv.id = 'image-loading'; |
|
|
loadingDiv.innerHTML = ` |
|
|
<div class="flex space-x-4"> |
|
|
<div class="flex-shrink-0 w-8 h-8 rounded-full bg-green-500 flex items-center justify-center text-white font-bold">C</div> |
|
|
<div class="flex-1"> |
|
|
<div class="bg-white p-4 rounded-lg shadow-sm"> |
|
|
<div class="flex items-center space-x-2"> |
|
|
<div class="animate-spin"> |
|
|
<i class="fas fa-spinner text-green-500"></i> |
|
|
</div> |
|
|
<p class="text-gray-800">Генерирую изображения по вашему запросу...</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
`; |
|
|
imageResults.appendChild(loadingDiv); |
|
|
scrollToBottom(); |
|
|
} |
|
|
|
|
|
|
|
|
function removeTypingIndicator() { |
|
|
const typingIndicator = document.getElementById('typing-indicator'); |
|
|
if (typingIndicator) { |
|
|
typingIndicator.remove(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function removeImageLoading() { |
|
|
const loadingIndicator = document.getElementById('image-loading'); |
|
|
if (loadingIndicator) { |
|
|
loadingIndicator.remove(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function addAiResponse(userMessage) { |
|
|
const responses = [ |
|
|
`Я понял ваш запрос о "${userMessage}". Вот что я могу рассказать по этой теме...`, |
|
|
`Интересный вопрос! "${userMessage}" - это то, с чем я могу помочь. Давайте разберёмся...`, |
|
|
`Относительно "${userMessage}", я могу дать следующую информацию...`, |
|
|
`Я проанализировал ваш запрос о "${userMessage}" и вот мой ответ...`, |
|
|
`Отличный вопрос! "${userMessage}" - это тема, в которой я разбираюсь. Вот что вам нужно знать...` |
|
|
]; |
|
|
|
|
|
const randomResponse = responses[Math.floor(Math.random() * responses.length)]; |
|
|
|
|
|
const messageDiv = document.createElement('div'); |
|
|
messageDiv.className = 'max-w-3xl mx-auto message-enter'; |
|
|
messageDiv.innerHTML = ` |
|
|
<div class="flex space-x-4"> |
|
|
<div class="flex-shrink-0 w-8 h-8 rounded-full bg-green-500 flex items-center justify-center text-white font-bold">C</div> |
|
|
<div class="flex-1"> |
|
|
<div class="bg-white p-4 rounded-lg shadow-sm"> |
|
|
<p class="text-gray-800">${randomResponse}</p> |
|
|
</div> |
|
|
<div class="mt-2 flex space-x-4 text-sm text-gray-500"> |
|
|
<button class="hover:bg-gray-100 px-2 py-1 rounded" onclick="copyResponse(this)"><i class="fas fa-copy mr-1"></i> Копировать</button> |
|
|
<button class="hover:bg-gray-100 px-2 py-1 rounded" onclick="likeResponse(this)"><i class="far fa-thumbs-up mr-1"></i> Нравится</button> |
|
|
<button class="hover:bg-gray-100 px-2 py-1 rounded" onclick="dislikeResponse(this)"><i class="far fa-thumbs-down mr-1"></i> Не нравится</button> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
`; |
|
|
chatContainer.appendChild(messageDiv); |
|
|
scrollToBottom(); |
|
|
} |
|
|
|
|
|
|
|
|
function generateImages(prompt) { |
|
|
|
|
|
const imageUrls = [ |
|
|
`https://source.unsplash.com/random/600x600/?${encodeURIComponent(prompt.split(' ').join(','))}&sig=${Math.floor(Math.random() * 1000)}`, |
|
|
`https://source.unsplash.com/random/600x600/?${encodeURIComponent(prompt.split(' ').join(','))}&sig=${Math.floor(Math.random() * 1000) + 1000}` |
|
|
]; |
|
|
|
|
|
const responseDiv = document.createElement('div'); |
|
|
responseDiv.className = 'max-w-3xl mx-auto message-enter'; |
|
|
responseDiv.innerHTML = ` |
|
|
<div class="flex space-x-4"> |
|
|
<div class="flex-shrink-0 w-8 h-8 rounded-full bg-green-500 flex items-center justify-center text-white font-bold">C</div> |
|
|
<div class="flex-1"> |
|
|
<div class="bg-white p-4 rounded-lg shadow-sm"> |
|
|
<p class="text-gray-800">Вот изображения по вашему запросу: "${prompt}"</p> |
|
|
</div> |
|
|
<div class="mt-4 grid grid-cols-1 md:grid-cols-2 gap-4"> |
|
|
<div class="bg-gray-100 rounded-lg overflow-hidden"> |
|
|
<img src="${imageUrls[0]}" alt="${prompt}" class="w-full h-64 object-cover generated-image"> |
|
|
<div class="p-3 flex justify-between items-center"> |
|
|
<p class="text-sm text-gray-600">"${prompt}"</p> |
|
|
<button class="text-green-500 hover:text-green-600" onclick="downloadImage('${imageUrls[0]}', '${prompt.replace(/[^a-zа-яё0-9]/gi, '_')}')"> |
|
|
<i class="fas fa-download"></i> |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
<div class="bg-gray-100 rounded-lg overflow-hidden"> |
|
|
<img src="${imageUrls[1]}" alt="${prompt}" class="w-full h-64 object-cover generated-image"> |
|
|
<div class="p-3 flex justify-between items-center"> |
|
|
<p class="text-sm text-gray-600">"${prompt}"</p> |
|
|
<button class="text-green-500 hover:text-green-600" onclick="downloadImage('${imageUrls[1]}', '${prompt.replace(/[^a-zа-яё0-9]/gi, '_')}')"> |
|
|
<i class="fas fa-download"></i> |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
<div class="mt-3 text-sm text-gray-500"> |
|
|
<p>Хотите уточнить или сгенерировать другие варианты?</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
`; |
|
|
imageResults.appendChild(responseDiv); |
|
|
scrollToBottom(); |
|
|
} |
|
|
|
|
|
|
|
|
function scrollToBottom() { |
|
|
if (currentMode === 'chat') { |
|
|
chatSection.scrollTop = chatSection.scrollHeight; |
|
|
} else { |
|
|
imageSection.scrollTop = imageSection.scrollHeight; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
document.querySelectorAll('#chat-section button').forEach(button => { |
|
|
button.addEventListener('click', function() { |
|
|
const text = this.textContent.trim(); |
|
|
messageInput.value = text; |
|
|
messageInput.dispatchEvent(new Event('input')); |
|
|
messageInput.focus(); |
|
|
}); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
function copyResponse(button) { |
|
|
const response = button.closest('.flex-1').querySelector('p').textContent; |
|
|
navigator.clipboard.writeText(response); |
|
|
|
|
|
|
|
|
const originalHtml = button.innerHTML; |
|
|
button.innerHTML = '<i class="fas fa-check mr-1"></i> Скопировано!'; |
|
|
setTimeout(() => { |
|
|
button.innerHTML = originalHtml; |
|
|
}, 2000); |
|
|
} |
|
|
|
|
|
function likeResponse(button) { |
|
|
button.innerHTML = '<i class="fas fa-thumbs-up mr-1"></i> Понравилось'; |
|
|
button.nextElementSibling.disabled = true; |
|
|
button.disabled = true; |
|
|
} |
|
|
|
|
|
function dislikeResponse(button) { |
|
|
button.innerHTML = '<i class="fas fa-thumbs-down mr-1"></i> Не понравилось'; |
|
|
button.previousElementSibling.disabled = true; |
|
|
button.disabled = true; |
|
|
} |
|
|
|
|
|
function downloadImage(url, filename) { |
|
|
|
|
|
|
|
|
const link = document.createElement('a'); |
|
|
link.href = url; |
|
|
link.download = filename || 'generated_image'; |
|
|
document.body.appendChild(link); |
|
|
link.click(); |
|
|
document.body.removeChild(link); |
|
|
|
|
|
|
|
|
alert(`Изображение сохранено как ${filename || 'generated_image'}.jpg`); |
|
|
} |
|
|
</script> |
|
|
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Greats/redfs" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
|
|
</html> |