Mypersonalassistant / index.html
Really-amin's picture
Update index.html
73643f2 verified
raw
history blame
22.5 kB
<!DOCTYPE html>
<html dir="rtl" lang="fa">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="description" content="دستیار هوش مصنوعی با قابلیت چت و پاسخگویی">
<meta name="keywords" content="هوش مصنوعی, چت بات, دستیار هوش مصنوعی">
<title>دستیار هوش مصنوعی</title>
<!-- فونت وزیر -->
<link href="https://cdn.jsdelivr.net/gh/rastikerdar/vazir-font@v30.1.0/dist/font-face.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
:root {
--bg-color: #f0f2f5;
--chat-bg: white;
--text-color: #333;
--border-color: #ddd;
--primary-color: #0088cc;
--hover-color: #006699;
--user-message-bg: #e3f2fd;
--bot-message-bg: #f5f5f5;
--header-height: 120px;
--border-radius: 20px;
--brain-size: 90px;
--animation-timing: cubic-bezier(0.4, 0, 0.2, 1);
--shadow-color: rgba(0, 0, 0, 0.2);
--glass-effect: rgba(255, 255, 255, 0.1);
}
.dark-theme {
--bg-color: #1a1a1a;
--chat-bg: #2d2d2d;
--text-color: #fff;
--border-color: #444;
--primary-color: #0099ff;
--hover-color: #0077cc;
--user-message-bg: #1e3a5f;
--bot-message-bg: #3d3d3d;
--shadow-color: rgba(0, 0, 0, 0.4);
--glass-effect: rgba(255, 255, 255, 0.05);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Vazir', sans-serif;
background: var(--bg-color);
color: var(--text-color);
min-height: 100vh;
margin: 0;
padding: 20px;
transition: all 0.3s var(--animation-timing);
overflow-x: hidden;
}
.app-container {
max-width: 1200px;
margin: 0 auto;
background: var(--chat-bg);
border-radius: var(--border-radius);
box-shadow: 0 4px 20px var(--shadow-color);
overflow: hidden;
position: relative;
display: flex;
flex-direction: column;
min-height: calc(100vh - 40px);
}
.header {
height: var(--header-height);
background: linear-gradient(135deg, var(--primary-color), #005580);
padding: 20px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
border-radius: var(--border-radius) var(--border-radius) 0 0;
z-index: 10;
box-shadow: 0 2px 10px var(--shadow-color);
}
.header-content {
display: flex;
align-items: center;
gap: 30px;
}
.brain-icon {
width: var(--brain-size);
height: var(--brain-size);
filter: drop-shadow(3px 3px 5px rgba(0, 0, 0, 0.3));
animation: brainPulse 3s ease-in-out infinite;
}
@keyframes brainPulse {
0% { transform: scale(1) rotate3d(1, 1, 1, 0deg); }
50% { transform: scale(1.1) rotate3d(1, 1, 1, 180deg); }
100% { transform: scale(1) rotate3d(1, 1, 1, 360deg); }
}
.header h1 {
color: white;
margin: 0;
font-size: 2.5rem;
font-weight: bold;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
}
.chat-container {
flex: 1;
display: flex;
flex-direction: column;
padding: 20px;
position: relative;
overflow: hidden;
}
.messages {
flex: 1;
overflow-y: auto;
padding: 10px;
margin-bottom: 20px;
scroll-behavior: smooth;
}
.message {
display: flex;
align-items: flex-start;
margin: 10px 0;
max-width: 80%;
animation: messageSlide 0.3s var(--animation-timing);
}
@keyframes messageSlide {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.message-content {
flex: 1;
padding: 12px 15px;
border-radius: 15px;
position: relative;
box-shadow: 0 2px 5px var(--shadow-color);
}
.message-time {
font-size: 0.75rem;
color: #888;
margin: 0 10px;
white-space: nowrap;
align-self: flex-end;
}
.user-message {
margin-left: auto;
flex-direction: row-reverse;
}
.user-message .message-content {
background: var(--user-message-bg);
border-bottom-right-radius: 5px;
}
.bot-message {
margin-right: auto;
flex-direction: row;
}
.bot-message .message-content {
background: var(--bot-message-bg);
border-bottom-left-radius: 5px;
}
.input-area {
background: var(--chat-bg);
padding: 20px;
border-top: 1px solid var(--border-color);
}
.input-container {
display: grid;
grid-template-columns: auto 1fr auto;
gap: 15px;
align-items: center;
}
.controls {
display: flex;
gap: 8px;
}
.control-button {
width: 40px;
height: 40px;
border: none;
border-radius: 50%;
background: var(--primary-color);
color: white;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.2s var(--animation-timing);
box-shadow: 0 2px 5px var(--shadow-color);
}
.control-button:hover {
transform: translateY(-2px);
background: var(--hover-color);
}
.message-input {
width: 100%;
padding: 12px 20px;
border: 2px solid var(--border-color);
border-radius: 25px;
font-size: 1rem;
background: var(--chat-bg);
color: var(--text-color);
transition: all 0.3s var(--animation-timing);
}
.message-input:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 3px rgba(0, 136, 204, 0.2);
}
.send-button {
width: 50px;
height: 50px;
border: none;
border-radius: 50%;
background: var(--primary-color);
color: white;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.2s var(--animation-timing);
box-shadow: 0 2px 5px var(--shadow-color);
}
.send-button:hover {
transform: translateY(-2px);
background: var(--hover-color);
}
.send-icon {
width: 0;
height: 0;
border-left: 12px solid transparent;
border-right: 12px solid transparent;
border-bottom: 20px solid white;
transform: rotate(90deg);
}
.status-bar {
padding: 15px;
background: var(--chat-bg);
border-top: 1px solid var(--border-color);
}
.status-info {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 15px;
text-align: center;
}
.status-badge {
padding: 5px 10px;
border-radius: 15px;
font-size: 0.8rem;
display: inline-block;
margin-top: 5px;
}
.typing-indicator {
padding: 10px;
color: #666;
font-style: italic;
display: none;
}
.typing-indicator.active {
display: block;
animation: typing 1s infinite;
}
@keyframes typing {
0%, 100% { opacity: 0.5; }
50% { opacity: 1; }
}
@media (max-width: 768px) {
body {
padding: 10px;
}
:root {
--header-height: 100px;
--brain-size: 60px;
--border-radius: 15px;
}
.header h1 {
font-size: 1.8rem;
}
.message {
max-width: 90%;
}
.input-container {
grid-template-columns: 1fr auto;
}
.controls {
display: none;
}
.status-info {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="app-container">
<header class="header">
<div class="header-content">
<h1>دستیار هوش مصنوعی</h1>
<svg class="brain-icon" viewBox="0 0 100 100">
<!-- SVG content here -->
<defs>
<radialGradient id="glass" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="rgba(255, 255, 255, 0.9)" />
<stop offset="70%" stop-color="rgba(255, 255, 255, 0.3)" />
<stop offset="100%" stop-color="rgba(255, 255, 255, 0.1)" />
</radialGradient>
<linearGradient id="brainGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#ff9eb3" />
<stop offset="50%" stop-color="#ff85a3" />
<stop offset="100%" stop-color="#ff6293" />
</linearGradient>
<filter id="glow">
<feGaussianBlur stdDeviation="2" result="coloredBlur" />
<feMerge>
<feMergeNode in="coloredBlur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<g class="brain-group" filter="url(#glow)">
<path class="brain-path"
d="M30,10 C45,0 60,15 55,35 C65,40 60,55 45,50 C35,60 15,50 20,35 C10,30 15,15 30,10"
fill="url(#brainGradient)"
stroke="#d4357d"
stroke-width="2" />
<path class="brain-detail"
d="M25,15 C35,10 45,20 40,30"
fill="none"
stroke="#d4357d"
stroke-width="1.5" />
<path class="brain-detail"
d="M35,25 C45,20 50,30 45,40"
fill="none"
stroke="#d4357d"
stroke-width="1.5" />
</g>
<circle cx="50" cy="50" r="45"
fill="url(#glass)"
stroke="#ffffff"
stroke-width="2" />
<ellipse cx="35" cy="35" rx="15" ry="10"
fill="rgba(255, 255, 255, 0.4)"
transform="rotate(-30, 35, 35)" />
</svg>
</div>
</header>
<main class="chat-container">
<div class="messages" id="chat-messages">
<div class="message bot-message">
<div class="message-content">
سلام! من یک دستیار هوش مصنوعی هستم. چطور می‌توانم کمکتان کنم؟
</div>
<div class="message-time">12:00</div>
</div>
</div>
<div class="input-area">
<div class="input-container">
<div class="controls">
<button class="control-button" onclick="toggleTheme()" id="themeToggle">🌙</button>
<button class="control-button" onclick="toggleSound()" id="soundToggle">🔊</button>
<button class="control-button" onclick="clearChat()">🗑️</button>
<button class="control-button" onclick="downloadChat()">💾</button>
</div>
<input type="text"
class="message-input"
id="messageInput"
placeholder="پیام خود را بنویسید..."
autocomplete="off">
<button class="send-button" id="sendBtn" onclick="sendMessage()">
<div class="send-icon"></div>
</button>
</div>
</div>
</main>
<footer class="status-bar">
<div class="status-info">
<div>
<strong>وضعیت مدل:</strong>
<span id="modelStatus" class="status-badge bg-warning">در حال بررسی...</span>
</div>
<div>
<strong>وضعیت تلگرام:</strong>
<span id="telegramStatus" class="status-badge bg-warning">در حال بررسی...</span>
</div>
<div>
<strong>زمان سیستم:</strong>
<span id="systemTime" class="status-badge bg-info">-</span>
</div>
</div>
</footer>
</div>
<audio id="notificationSound" src="/static/notification.mp3"></audio>
<!-- JavaScript Codes -->
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.min.js"></script>
<script>
// WebSocket Connection
let ws = new WebSocket(
(window.location.protocol === 'https:' ? 'wss://' : 'ws://') +
window.location.host + '/ws'
);
let soundEnabled = true;
// WebSocket Event Handlers
ws.onopen = function() {
console.log('WebSocket Connected');
updateConnectionStatus('online');
};
ws.onclose = function() {
console.log('WebSocket Disconnected');
updateConnectionStatus('offline');
setTimeout(reconnectWebSocket, 3000);
};
ws.onerror = function(error) {
console.error('WebSocket Error:', error);
updateConnectionStatus('error');
};
ws.onmessage = function(event) {
const data = JSON.parse(event.data);
if (data.type === 'typing') {
handleTypingStatus(data.status);
} else {
addMessage(data.message, 'bot');
}
};
// Message Functions
function sendMessage() {
const input = document.getElementById('messageInput');
const message = input.value.trim();
if (message) {
addMessage(message, 'user');
ws.send(JSON.stringify({
type: 'message',
message: message
}));
input.value = '';
handleTypingStatus(true);
}
}
function addMessage(message, type) {
const messagesDiv = document.getElementById('chat-messages');
const messageDiv = document.createElement('div');
messageDiv.className = `message ${type}-message`;
const contentDiv = document.createElement('div');
contentDiv.className = 'message-content';
contentDiv.textContent = message;
const timeDiv = document.createElement('div');
timeDiv.className = 'message-time';
const time = new Date().toLocaleTimeString('fa-IR', {
hour: '2-digit',
minute: '2-digit'
});
timeDiv.textContent = time;
messageDiv.appendChild(contentDiv);
messageDiv.appendChild(timeDiv);
messagesDiv.appendChild(messageDiv);
messagesDiv.scrollTop = messagesDiv.scrollHeight;
if (type === 'bot' && soundEnabled) {
playNotification();
}
}
// UI Control Functions
function toggleTheme() {
document.body.classList.toggle('dark-theme');
const themeBtn = document.getElementById('themeToggle');
themeBtn.textContent = document.body.classList.contains('dark-theme') ? '☀️' : '🌙';
localStorage.setItem('theme', document.body.classList.contains('dark-theme') ? 'dark' : 'light');
}
function toggleSound() {
soundEnabled = !soundEnabled;
const soundBtn = document.getElementById('soundToggle');
soundBtn.textContent = soundEnabled ? '🔊' : '🔇';
localStorage.setItem('soundEnabled', soundEnabled);
}
function playNotification() {
const audio = document.getElementById('notificationSound');
audio.currentTime = 0;
audio.play().catch(err => console.error('Error playing sound:', err));
}
function clearChat() {
if (confirm('آیا مطمئن هستید که می‌خواهید تاریخچه چت را پاک کنید؟')) {
const messagesDiv = document.getElementById('chat-messages');
messagesDiv.innerHTML = '';
addMessage('سلام! من یک دستیار هوش مصنوعی هستم. چطور می‌توانم کمکتان کنم؟', 'bot');
}
}
function downloadChat() {
const messages = document.getElementById('chat-messages');
const text = Array.from(messages.children)
.map(msg => {
const content = msg.querySelector('.message-content').textContent;
const time = msg.querySelector('.message-time').textContent;
const type = msg.classList.contains('user-message') ? 'شما' : 'ربات';
return `[${time}] ${type}: ${content}`;
})
.join('\n');
const blob = new Blob([text], { type: 'text/plain;charset=utf-8' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `chat-${new Date().toLocaleDateString('fa-IR')}.txt`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
// Status Management
function updateConnectionStatus(status) {
const modelStatus = document.getElementById('modelStatus');
const statusText = {
'online': 'آنلاین',
'offline': 'آفلاین',
'error': 'خطا در اتصال'
}[status];
const statusClass = {
'online': 'bg-success',
'offline': 'bg-danger',
'error': 'bg-warning'
}[status];
modelStatus.textContent = statusText;
modelStatus.className = `status-badge ${statusClass}`;
}
// Typing Indicator
let typingTimer;
function handleTypingStatus(isTyping) {
if (isTyping) {
clearTimeout(typingTimer);
ws.send(JSON.stringify({ type: 'typing', status: true }));
typingTimer = setTimeout(() => {
ws.send(JSON.stringify({ type: 'typing', status: false }));
}, 1000);
}
}
// Event Listeners
document.addEventListener('DOMContentLoaded', function() {
// Load saved settings
if (localStorage.getItem('theme') === 'dark') {
document.body.classList.add('dark-theme');
document.getElementById('themeToggle').textContent = '☀️';
}
soundEnabled = localStorage.getItem('soundEnabled') !== 'false';
document.getElementById('soundToggle').textContent = soundEnabled ? '🔊' : '🔇';
// Input event listeners
const messageInput = document.getElementById('messageInput');
messageInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
sendMessage();
}
});
messageInput.addEventListener('input', function() {
handleTypingStatus(true);
});
// System time update
setInterval(() => {
const systemTime = document.getElementById('systemTime');
systemTime.textContent = new Date().toLocaleTimeString('fa-IR');
}, 1000);
});
// Connection Management
function reconnectWebSocket() {
ws = new WebSocket(
(window.location.protocol === 'https:' ? 'wss://' : 'ws://') +
window.location.host + '/ws'
);
}
window.addEventListener('online', function() {
reconnectWebSocket();
updateConnectionStatus('online');
});
window.addEventListener('offline', function() {
updateConnectionStatus('offline');
});
</script>
</body>
</html>