Really-amin commited on
Commit
027e9c6
1 Parent(s): 654965e

Upload 2 files

Browse files
Files changed (2) hide show
  1. templates/index.html +979 -0
  2. templates/massage.mp3 +0 -0
templates/index.html ADDED
@@ -0,0 +1,979 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ <!DOCTYPE html>
3
+ <html dir="rtl" lang="fa">
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
7
+ <meta name="description" content="دستیار هوش مصنوعی پیشرفته با قابلیت چت و پاسخگویی هوشمند">
8
+ <meta name="keywords" content="هوش مصنوعی, چت بات, دستیار هوشمند, پردازش زبان طبیعی">
9
+ <meta name="theme-color" content="#0088cc">
10
+ <meta name="apple-mobile-web-app-capable" content="yes">
11
+ <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
12
+ <title>دستیار هوش مصنوعی پیشرفته</title>
13
+
14
+ <!-- فونت و استایل‌های خارجی -->
15
+ <link href="https://cdn.jsdelivr.net/gh/rastikerdar/vazir-font@v30.1.0/dist/font-face.css" rel="stylesheet">
16
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
17
+
18
+ <style>
19
+ :root {
20
+ --bg-color: #f0f2f5;
21
+ --chat-bg: white;
22
+ --text-color: #333;
23
+ --border-color: #ddd;
24
+ --primary-color: #0088cc;
25
+ --hover-color: #006699;
26
+ --user-message-bg: #e3f2fd;
27
+ --bot-message-bg: #f5f5f5;
28
+ --shadow-color: rgba(0, 0, 0, 0.1);
29
+ --header-gradient-start: #0088cc;
30
+ --header-gradient-end: #005580;
31
+ --input-bg: #ffffff;
32
+ --placeholder-color: #95a5a6;
33
+ --message-time-color: #7f8c8d;
34
+ --system-message-bg: #fff3cd;
35
+ --system-message-color: #856404;
36
+ --maintenance-bg: #f8d7da;
37
+ --maintenance-color: #721c24;
38
+ --header-text: #ffffff;
39
+ --header-height: 120px;
40
+ --border-radius: 20px;
41
+ --control-button-bg: #0088cc;
42
+ --status-bar-bg: rgba(255, 255, 255, 0.95);
43
+ --typing-indicator-color: #606060;
44
+ --disabled-bg: #f8f9fa;
45
+ }
46
+
47
+ .dark-theme {
48
+ --bg-color: #1a1a1a;
49
+ --chat-bg: #2d2d2d;
50
+ --text-color: #ecf0f1;
51
+ --border-color: #444444;
52
+ --primary-color: #0099ff;
53
+ --hover-color: #0077cc;
54
+ --user-message-bg: #1e3a5f;
55
+ --bot-message-bg: #3d3d3d;
56
+ --shadow-color: rgba(0, 0, 0, 0.3);
57
+ --header-gradient-start: #004466;
58
+ --header-gradient-end: #002233;
59
+ --input-bg: #383838;
60
+ --placeholder-color: #95a5a6;
61
+ --message-time-color: #95a5a6;
62
+ --system-message-bg: #3d2c00;
63
+ --system-message-color: #ffd970;
64
+ --maintenance-bg: #442226;
65
+ --maintenance-color: #ff8c95;
66
+ --status-bar-bg: rgba(45, 45, 45, 0.95);
67
+ --typing-indicator-color: #b0b0b0;
68
+ --disabled-bg: #2a2a2a;
69
+ }
70
+
71
+ * {
72
+ margin: 0;
73
+ padding: 0;
74
+ box-sizing: border-box;
75
+ transition: background-color 0.3s ease, color 0.3s ease;
76
+ }
77
+
78
+ body {
79
+ font-family: 'Vazir', Tahoma, Arial, sans-serif;
80
+ background: var(--bg-color);
81
+ color: var(--text-color);
82
+ min-height: 100vh;
83
+ margin: 0;
84
+ padding: 20px;
85
+ line-height: 1.6;
86
+ }
87
+
88
+ .app-container {
89
+ max-width: 1200px;
90
+ margin: 0 auto;
91
+ background: var(--chat-bg);
92
+ border-radius: var(--border-radius);
93
+ box-shadow: 0 5px 25px var(--shadow-color);
94
+ overflow: hidden;
95
+ display: flex;
96
+ flex-direction: column;
97
+ height: calc(100vh - 40px);
98
+ position: relative;
99
+ }
100
+
101
+ .header {
102
+ background: linear-gradient(135deg,
103
+ var(--header-gradient-start),
104
+ var(--header-gradient-end));
105
+ padding: 20px;
106
+ height: var(--header-height);
107
+ display: flex;
108
+ align-items: center;
109
+ justify-content: center;
110
+ position: relative;
111
+ z-index: 2;
112
+ }
113
+
114
+ .header-content {
115
+ display: flex;
116
+ align-items: center;
117
+ gap: 20px;
118
+ animation: fadeInDown 0.5s ease-out;
119
+ }
120
+
121
+ .header h1 {
122
+ color: var(--header-text);
123
+ margin: 0;
124
+ font-size: 2.2rem;
125
+ font-weight: bold;
126
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
127
+ }
128
+
129
+ .brain-icon {
130
+ width: 80px;
131
+ height: 80px;
132
+ filter: drop-shadow(3px 3px 5px rgba(0, 0, 0, 0.3));
133
+ animation: float 3s ease-in-out infinite;
134
+ }
135
+
136
+ @keyframes float {
137
+ 0%, 100% { transform: translateY(0); }
138
+ 50% { transform: translateY(-8px); }
139
+ }
140
+
141
+ .chat-container {
142
+ flex: 1;
143
+ display: flex;
144
+ flex-direction: column;
145
+ position: relative;
146
+ overflow: hidden;
147
+ padding: 20px;
148
+ gap: 20px;
149
+ }
150
+
151
+ .status-bar {
152
+ background: var(--status-bar-bg);
153
+ padding: 15px;
154
+ border-bottom: 1px solid var(--border-color);
155
+ backdrop-filter: blur(10px);
156
+ -webkit-backdrop-filter: blur(10px);
157
+ position: sticky;
158
+ top: 0;
159
+ z-index: 1;
160
+ }
161
+
162
+ .status-info {
163
+ display: grid;
164
+ grid-template-columns: repeat(3, 1fr);
165
+ gap: 15px;
166
+ text-align: center;
167
+ }
168
+
169
+ .messages {
170
+ flex: 1;
171
+ overflow-y: auto;
172
+ padding: 10px;
173
+ scroll-behavior: smooth;
174
+ }
175
+
176
+ .messages::-webkit-scrollbar {
177
+ width: 8px;
178
+ }
179
+
180
+ .messages::-webkit-scrollbar-track {
181
+ background: var(--chat-bg);
182
+ border-radius: 4px;
183
+ }
184
+
185
+ .messages::-webkit-scrollbar-thumb {
186
+ background: var(--border-color);
187
+ border-radius: 4px;
188
+ }
189
+
190
+ .message {
191
+ margin: 12px 0;
192
+ padding: 15px;
193
+ border-radius: 15px;
194
+ max-width: 80%;
195
+ position: relative;
196
+ animation: messageAppear 0.3s ease;
197
+ line-height: 1.6;
198
+ font-size: 1rem;
199
+ box-shadow: 0 2px 5px var(--shadow-color);
200
+ }
201
+
202
+ @keyframes messageAppear {
203
+ from {
204
+ opacity: 0;
205
+ transform: translateY(20px);
206
+ }
207
+ to {
208
+ opacity: 1;
209
+ transform: translateY(0);
210
+ }
211
+ }
212
+
213
+ .user-message {
214
+ background: var(--user-message-bg);
215
+ margin-right: auto !important;
216
+ margin-left: 20px !important;
217
+ border-radius: 15px 15px 0 15px;
218
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08),
219
+ 0 1px 3px rgba(0, 0, 0, 0.12);
220
+ }
221
+
222
+ .bot-message {
223
+ background: var(--bot-message-bg);
224
+ margin-left: auto !important;
225
+ margin-right: 20px !important;
226
+ border-radius: 15px 15px 15px 0;
227
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08),
228
+ 0 1px 3px rgba(0, 0, 0, 0.12);
229
+ }
230
+
231
+ .message:hover {
232
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12),
233
+ 0 2px 4px rgba(0, 0, 0, 0.08);
234
+ }
235
+
236
+ .message-time {
237
+ font-size: 0.75rem;
238
+ color: var(--message-time-color);
239
+ position: absolute;
240
+ bottom: 5px;
241
+ left: 10px;
242
+ opacity: 0.8;
243
+ }
244
+
245
+ .typing-indicator {
246
+ padding: 10px 20px;
247
+ background: var(--chat-bg);
248
+ border-radius: 15px;
249
+ display: none;
250
+ color: var(--typing-indicator-color);
251
+ font-size: 0.9em;
252
+ margin: 5px 15px;
253
+ border: 1px solid var(--border-color);
254
+ animation: pulse 1.5s infinite;
255
+ }
256
+
257
+ .typing-indicator.active {
258
+ display: inline-block;
259
+ }
260
+
261
+ @keyframes pulse {
262
+ 0%, 100% { opacity: 1; }
263
+ 50% { opacity: 0.5; }
264
+ }
265
+
266
+ .input-area {
267
+ background: var(--chat-bg);
268
+ padding: 20px;
269
+ border-top: 1px solid var(--border-color);
270
+ position: relative;
271
+ }
272
+
273
+ .input-container {
274
+ display: grid;
275
+ grid-template-columns: auto 1fr auto;
276
+ gap: 15px;
277
+ align-items: center;
278
+ background: var(--input-bg);
279
+ border-radius: 25px;
280
+ padding: 5px;
281
+ box-shadow: 0 2px 10px var(--shadow-color);
282
+ }
283
+
284
+ .message-input {
285
+ padding: 12px 20px;
286
+ border: 2px solid var(--border-color);
287
+ border-radius: 25px;
288
+ font-size: 1rem;
289
+ background: var(--input-bg);
290
+ color: var(--text-color);
291
+ width: 100%;
292
+ transition: all 0.3s ease;
293
+ }
294
+
295
+ .message-input:focus {
296
+ outline: none;
297
+ border-color: var(--primary-color);
298
+ box-shadow: 0 0 0 3px rgba(0, 136, 204, 0.1);
299
+ background: var(--input-bg);
300
+ }
301
+
302
+ .message-input::placeholder {
303
+ color: var(--border-color);
304
+ }
305
+
306
+ .send-button {
307
+ width: 50px;
308
+ height: 50px;
309
+ border-radius: 50%;
310
+ border: none;
311
+ background: var(--primary-color);
312
+ color: white;
313
+ cursor: pointer;
314
+ transition: all 0.3s ease;
315
+ display: flex;
316
+ align-items: center;
317
+ justify-content: center;
318
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
319
+ }
320
+
321
+ .send-button:hover:not(:disabled) {
322
+ transform: translateY(-2px);
323
+ background: var(--hover-color);
324
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
325
+ }
326
+
327
+ .dark-theme .message {
328
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2),
329
+ 0 1px 3px rgba(0, 0, 0, 0.3);
330
+ }
331
+
332
+ .dark-theme .message:hover {
333
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25),
334
+ 0 2px 4px rgba(0, 0, 0, 0.15);
335
+ }
336
+
337
+ .dark-theme .message-input {
338
+ background: var(--input-bg);
339
+ color: var(--text-color);
340
+ border-color: var(--border-color);
341
+ }
342
+
343
+ .system-message {
344
+ background: var(--system-message-bg);
345
+ color: var(--system-message-color);
346
+ padding: 12px 15px;
347
+ border-radius: 10px;
348
+ margin: 10px 15px;
349
+ border: 1px solid var(--border-color);
350
+ animation: slideIn 0.3s ease;
351
+ }
352
+
353
+ .maintenance-mode {
354
+ background: var(--maintenance-bg);
355
+ color: var(--maintenance-color);
356
+ padding: 12px 15px;
357
+ border-radius: 10px;
358
+ margin: 10px 15px;
359
+ border: 1px solid var(--border-color);
360
+ animation: slideIn 0.3s ease;
361
+ }
362
+
363
+ @keyframes slideIn {
364
+ from {
365
+ transform: translateX(100%);
366
+ opacity: 0;
367
+ }
368
+ to {
369
+ transform: translateX(0);
370
+ opacity: 1;
371
+ }
372
+ }
373
+
374
+ @keyframes fadeInDown {
375
+ from {
376
+ opacity: 0;
377
+ transform: translateY(-20px);
378
+ }
379
+ to {
380
+ opacity: 1;
381
+ transform: translateY(0);
382
+ }
383
+ }
384
+
385
+ @keyframes fadeIn {
386
+ from { opacity: 0; }
387
+ to { opacity: 1; }
388
+ }
389
+
390
+ @media (max-width: 768px) {
391
+ body {
392
+ padding: 10px;
393
+ }
394
+
395
+ :root {
396
+ --header-height: 100px;
397
+ --border-radius: 15px;
398
+ }
399
+
400
+ .header h1 {
401
+ font-size: 1.5rem;
402
+ }
403
+
404
+ .brain-icon {
405
+ width: 50px;
406
+ height: 50px;
407
+ }
408
+
409
+ .message {
410
+ max-width: 90%;
411
+ padding: 12px;
412
+ font-size: 0.95rem;
413
+ }
414
+
415
+ .controls {
416
+ display: none;
417
+ }
418
+
419
+ .input-container {
420
+ grid-template-columns: 1fr auto;
421
+ gap: 10px;
422
+ }
423
+
424
+ .status-info {
425
+ grid-template-columns: 1fr;
426
+ gap: 10px;
427
+ }
428
+
429
+ .send-button {
430
+ width: 45px;
431
+ height: 45px;
432
+ }
433
+
434
+ .message-input {
435
+ padding: 10px 15px;
436
+ font-size: 0.95rem;
437
+ }
438
+ }
439
+
440
+ @keyframes ripple {
441
+ 0% {
442
+ transform: scale(0.8);
443
+ opacity: 1;
444
+ }
445
+ 100% {
446
+ transform: scale(2);
447
+ opacity: 0;
448
+ }
449
+ }
450
+
451
+ .ripple {
452
+ position: relative;
453
+ overflow: hidden;
454
+ }
455
+
456
+ .ripple:after {
457
+ content: '';
458
+ position: absolute;
459
+ width: 100%;
460
+ height: 100%;
461
+ top: 0;
462
+ left: 0;
463
+ background: rgba(255, 255, 255, 0.3);
464
+ border-radius: 50%;
465
+ transform: scale(0);
466
+ animation: ripple 0.6s linear;
467
+ pointer-events: none;
468
+ }
469
+ </style>
470
+ </head>
471
+ <body>
472
+ <div class="app-container">
473
+ <header class="header">
474
+ <div class="header-content">
475
+ <h1>دستیار هوش مصنوعی</h1>
476
+ <svg class="brain-icon" viewBox="0 0 100 100">
477
+ <defs>
478
+ <radialGradient id="glass" cx="50%" cy="50%" r="50%">
479
+ <stop offset="0%" stop-color="rgba(255, 255, 255, 0.9)"/>
480
+ <stop offset="100%" stop-color="rgba(255, 255, 255, 0.3)"/>
481
+ </radialGradient>
482
+ <linearGradient id="brainGradient" x1="0%" y1="0%" x2="100%" y2="100%">
483
+ <stop offset="0%" stop-color="#ff9eb3"/>
484
+ <stop offset="50%" stop-color="#ff85a3"/>
485
+ <stop offset="100%" stop-color="#ff6293"/>
486
+ </linearGradient>
487
+ <filter id="shadow">
488
+ <feDropShadow dx="2" dy="2" stdDeviation="2" flood-opacity="0.3"/>
489
+ </filter>
490
+ </defs>
491
+
492
+ <g transform="translate(20, 25)" filter="url(#shadow)">
493
+ <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"
494
+ fill="url(#brainGradient)"
495
+ stroke="#d4357d"
496
+ stroke-width="2">
497
+ <animate attributeName="d"
498
+ dur="3s"
499
+ repeatCount="indefinite"
500
+ values="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;
501
+ M30,12 C45,2 58,17 53,37 C63,42 58,57 43,52 C33,62 17,52 22,37 C12,32 17,17 30,12;
502
+ 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"/>
503
+ </path>
504
+ <path d="M25,15 C35,10 45,20 40,30"
505
+ fill="none"
506
+ stroke="#d4357d"
507
+ stroke-width="1.5">
508
+ <animate attributeName="d"
509
+ dur="3s"
510
+ repeatCount="indefinite"
511
+ values="M25,15 C35,10 45,20 40,30;
512
+ M25,17 C35,12 45,22 40,32;
513
+ M25,15 C35,10 45,20 40,30"/>
514
+ </path>
515
+ <path d="M35,25 C45,20 50,30 45,40"
516
+ fill="none"
517
+ stroke="#d4357d"
518
+ stroke-width="1.5">
519
+ <animate attributeName="d"
520
+ dur="3s"
521
+ repeatCount="indefinite"
522
+ values="M35,25 C45,20 50,30 45,40;
523
+ M35,27 C45,22 50,32 45,42;
524
+ M35,25 C45,20 50,30 45,40"/>
525
+ </path>
526
+ <path d="M25,30 C35,25 40,35 35,45"
527
+ fill="none"
528
+ stroke="#d4357d"
529
+ stroke-width="1.5">
530
+ <animate attributeName="d"
531
+ dur="3s"
532
+ repeatCount="indefinite"
533
+ values="M25,30 C35,25 40,35 35,45;
534
+ M25,32 C35,27 40,37 35,47;
535
+ M25,30 C35,25 40,35 35,45"/>
536
+ </path>
537
+ </g>
538
+ <circle cx="50" cy="50" r="45"
539
+ fill="url(#glass)"
540
+ stroke="#ffffff"
541
+ stroke-width="2">
542
+ <animate attributeName="r"
543
+ dur="3s"
544
+ repeatCount="indefinite"
545
+ values="45;43;45"/>
546
+ </circle>
547
+ <ellipse cx="35" cy="35"
548
+ rx="15" ry="10"
549
+ fill="rgba(255, 255, 255, 0.4)"
550
+ transform="rotate(-30, 35, 35)">
551
+ <animate attributeName="ry"
552
+ dur="3s"
553
+ repeatCount="indefinite"
554
+ values="10;9;10"/>
555
+ </ellipse>
556
+ </svg>
557
+ </div>
558
+ </header>
559
+
560
+ <div class="status-bar">
561
+ <div class="status-info">
562
+ <div>
563
+ <strong>وضعیت مدل:</strong>
564
+ <span id="model-status" class="badge bg-warning">در حال بررسی...</span>
565
+ </div>
566
+ <div>
567
+ <strong>وضعیت اتصال:</strong>
568
+ <span id="connection-status" class="badge bg-warning">در حال بررسی...</span>
569
+ </div>
570
+ <div>
571
+ <strong>زمان سیستم:</strong>
572
+ <span id="system-time" class="badge bg-info">-</span>
573
+ </div>
574
+ </div>
575
+ </div>
576
+
577
+ <main class="chat-container">
578
+ <div class="messages" id="chat-messages">
579
+ <div class="message bot-message">
580
+ سلام! من یک دستیار هوش مصنوعی هستم. چطور می‌توانم کمکتان کنم؟
581
+ <span class="message-time">12:00</span>
582
+ </div>
583
+ </div>
584
+
585
+ <div class="typing-indicator" id="typingIndicator">
586
+ <span>در حال تایپ</span>
587
+ <span class="dots">...</span>
588
+ </div>
589
+
590
+ <div class="input-area">
591
+ <div class="input-container" id="inputContainer">
592
+ <div class="controls">
593
+ <button class="control-button ripple" onclick="toggleTheme()" id="themeToggle" title="تغییر تم">🌙</button>
594
+ <button class="control-button ripple" onclick="toggleSound()" id="soundToggle" title="صدا">🔊</button>
595
+ <button class="control-button ripple" onclick="clearChat()" title="پاک کردن تاریخچه">🗑️</button>
596
+ <button class="control-button ripple" onclick="downloadChat()" title="دانلود تاریخچه">💾</button>
597
+ </div>
598
+ <input type="text"
599
+ class="message-input"
600
+ id="messageInput"
601
+ placeholder="پیام خود را بنویسید..."
602
+ autocomplete="off"
603
+ disabled>
604
+ <button class="send-button ripple" id="sendButton" onclick="sendMessage()" disabled>
605
+ <svg viewBox="0 0 24 24" width="24" height="24">
606
+ <path fill="currentColor" d="M2,21L23,12L2,3V10L17,12L2,14V21Z"/>
607
+ </svg>
608
+ </button>
609
+ </div>
610
+ </div>
611
+ </main>
612
+ </div>
613
+
614
+ <script>
615
+ let ws;
616
+ let soundEnabled = true;
617
+ let reconnectAttempts = 0;
618
+ const maxReconnectAttempts = 5;
619
+ const messageSound = new Audio('/static/message.mp3');
620
+ let chatEnabled = false;
621
+ let isTyping = false;
622
+ let typingTimeout;
623
+
624
+ // تابع اتصال به WebSocket
625
+ // تغییر در // تغییر در تابع connectWebSocket
626
+ function connectWebSocket() {
627
+ const clientId = Math.random().toString(36).substring(7);
628
+ ws = new WebSocket(
629
+ (window.location.protocol === 'https:' ? 'wss://' : 'ws://') +
630
+ window.location.host + '/ws/' + clientId
631
+ );
632
+
633
+ ws.onmessage = handleWebSocketMessage;
634
+ ws.onopen = handleWebSocketOpen;
635
+ ws.onclose = handleWebSocketClose;
636
+ ws.onerror = handleWebSocketError;
637
+ }
638
+ // تغییر در تابع sendMessage
639
+ function sendMessage() {
640
+ const input = document.getElementById('messageInput');
641
+ const message = input.value.trim();
642
+
643
+ if (message && chatEnabled) {
644
+ if (ws.readyState === WebSocket.OPEN) {
645
+ try {
646
+ addMessage(message, 'user');
647
+ ws.send(message); // تغییر این خط - فقط متن پیام رو ارسال می‌کنیم
648
+ input.value = '';
649
+ handleTypingStatus(true);
650
+
651
+ const sendButton = document.getElementById('sendButton');
652
+ sendButton.classList.add('active');
653
+ setTimeout(() => sendButton.classList.remove('active'), 200);
654
+ } catch (e) {
655
+ handleError("خطا در ارسال پیام");
656
+ }
657
+ } else {
658
+ handleError("اتصال به سرور برقرار نیست");
659
+ connectWebSocket();
660
+ }
661
+ }
662
+ }
663
+ // مدیریت پیام‌های دریافتی
664
+ function handleWebSocketMessage(event) {
665
+ try {
666
+ const data = JSON.parse(event.data);
667
+
668
+ switch(data.type) {
669
+ case 'typing':
670
+ handleTypingStatus(data.status);
671
+ break;
672
+ case 'message':
673
+ handleBotMessage(data.message);
674
+ break;
675
+ case 'error':
676
+ handleError(data.message);
677
+ break;
678
+ default:
679
+ handleBotMessage(data.message || event.data);
680
+ }
681
+ } catch (e) {
682
+ console.error("خطا در پردازش پیام:", e);
683
+ handleBotMessage(event.data);
684
+ }
685
+ }
686
+
687
+ // مدیریت باز شدن اتصال
688
+ function handleWebSocketOpen() {
689
+ updateConnectionStatus(true);
690
+ enableChat();
691
+ reconnectAttempts = 0;
692
+ updateStatus();
693
+
694
+ const successMessage = document.createElement('div');
695
+ successMessage.className = 'system-message';
696
+ successMessage.textContent = "✅ اتصال با موفقیت برقرار شد";
697
+ document.getElementById('chat-messages').appendChild(successMessage);
698
+ setTimeout(() => successMessage.remove(), 3000);
699
+ }
700
+
701
+ // مدیریت بسته شدن اتصال
702
+ function handleWebSocketClose() {
703
+ updateConnectionStatus(false);
704
+ disableChat();
705
+
706
+ if (reconnectAttempts < maxReconnectAttempts) {
707
+ reconnectAttempts++;
708
+ const delay = 5000 * reconnectAttempts;
709
+ handleError(`تلاش مجدد برای اتصال در ${delay/1000} ثانیه دیگر...`);
710
+ setTimeout(connectWebSocket, delay);
711
+ } else {
712
+ handleError("اتصال به سرور برقرار نیست. لطفاً صفحه را مجدداً بارگذاری کنید.");
713
+ }
714
+ }
715
+
716
+ // مدیریت خطاهای اتصال
717
+ function handleWebSocketError(error) {
718
+ console.error("خطای WebSocket:", error);
719
+ handleError("خطا در ارتباط با سرور");
720
+ }
721
+
722
+ // به‌روزرسانی وضعیت اتصال
723
+ function updateConnectionStatus(connected) {
724
+ const statusElement = document.getElementById('connection-status');
725
+ if (connected) {
726
+ statusElement.className = 'badge bg-success';
727
+ statusElement.textContent = 'متصل';
728
+ } else {
729
+ statusElement.className = 'badge bg-danger';
730
+ statusElement.textContent = 'قطع شده';
731
+ }
732
+ }
733
+
734
+ // فعال‌سازی چت
735
+ function enableChat() {
736
+ chatEnabled = true;
737
+ }
738
+
739
+ // غیرفعال‌سازی چت
740
+ function disableChat() {
741
+ chatEnabled = false;
742
+ document.getElementById('messageInput').disabled = true;
743
+ document.getElementById('sendButton').disabled = true;
744
+ }
745
+
746
+ // مدیریت وضعیت تایپ
747
+ function handleTypingStatus(status) {
748
+ clearTimeout(typingTimeout);
749
+ const indicator = document.getElementById('typingIndicator');
750
+
751
+ if (status) {
752
+ indicator.classList.add('active');
753
+ isTyping = true;
754
+ typingTimeout = setTimeout(() => {
755
+ indicator.classList.remove('active');
756
+ isTyping = false;
757
+ }, 10000);
758
+ } else {
759
+ indicator.classList.remove('active');
760
+ isTyping = false;
761
+ }
762
+ }
763
+
764
+ // مدیریت پیام‌های دریافتی از بات
765
+ function handleBotMessage(message) {
766
+ handleTypingStatus(false);
767
+ addMessage(message, 'bot');
768
+ if (soundEnabled) playMessageSound();
769
+ }
770
+
771
+ // مدیریت خطاها
772
+ function handleError(message) {
773
+ const errorDiv = document.createElement('div');
774
+ errorDiv.className = 'system-message';
775
+ errorDiv.innerHTML = `⚠️ ${message}`;
776
+ document.getElementById('chat-messages').appendChild(errorDiv);
777
+ }
778
+
779
+ // ارسال پیام
780
+ // ��غییر در تابع connectWebSocket
781
+ function connectWebSocket() {
782
+ const clientId = Math.random().toString(36).substring(7);
783
+ ws = new WebSocket(
784
+ (window.location.protocol === 'https:' ? 'wss://' : 'ws://') +
785
+ window.location.host + '/ws/' + clientId
786
+ );
787
+
788
+ ws.onmessage = handleWebSocketMessage;
789
+ ws.onopen = handleWebSocketOpen;
790
+ ws.onclose = handleWebSocketClose;
791
+ ws.onerror = handleWebSocketError;
792
+ }
793
+
794
+ async function updateStatus() {
795
+ try {
796
+ const response = await fetch('/status');
797
+ const status = await response.json();
798
+
799
+ const modelStatus = document.getElementById('model-status');
800
+ modelStatus.className = `badge ${status.model_loaded ? 'bg-success' : 'bg-danger'}`;
801
+ modelStatus.textContent = status.model_loaded ? 'فعال' : 'غیرفعال';
802
+
803
+ if (status.maintenance_mode) {
804
+ disableChat();
805
+ if (!document.querySelector('.maintenance-mode')) {
806
+ const maintenanceDiv = document.createElement('div');
807
+ maintenanceDiv.className = 'maintenance-mode';
808
+ maintenanceDiv.innerHTML = "🔧 سیستم در حال تعمیر است. لطفاً بعداً مراجعه کنید.";
809
+ document.getElementById('chat-messages').appendChild(maintenanceDiv);
810
+ }
811
+ } else if (!chatEnabled && status.model_loaded) {
812
+ enableChat();
813
+ }
814
+ } catch (e) {
815
+ console.error("خطا در به‌روزرسانی وضعیت:", e);
816
+ handleError("خطا در دریافت وضعیت سیستم");
817
+ }
818
+ }
819
+
820
+ // تغییر تم
821
+ function toggleTheme() {
822
+ document.body.classList.toggle('dark-theme');
823
+ const themeBtn = document.getElementById('themeToggle');
824
+ themeBtn.textContent = document.body.classList.contains('dark-theme') ? '☀️' : '🌙';
825
+ localStorage.setItem('theme', document.body.classList.contains('dark-theme') ? 'dark' : 'light');
826
+ themeBtn.classList.add('ripple');
827
+ setTimeout(() => themeBtn.classList.remove('ripple'), 600);
828
+ }
829
+
830
+ // تغییر وضعیت صدا
831
+ function toggleSound() {
832
+ soundEnabled = !soundEnabled;
833
+ const soundBtn = document.getElementById('soundToggle');
834
+ soundBtn.textContent = soundEnabled ? '🔊' : '🔇';
835
+ localStorage.setItem('sound', soundEnabled.toString());
836
+ soundBtn.classList.add('ripple');
837
+ setTimeout(() => soundBtn.classList.remove('ripple'), 600);
838
+ }
839
+
840
+ // پخش صدای پیام
841
+ async function playMessageSound() {
842
+ try {
843
+ await messageSound.play();
844
+ } catch (e) {
845
+ console.log('خطا در پخش صدا:', e);
846
+ }
847
+ }
848
+
849
+ // اضافه کردن پیام به چت
850
+ function addMessage(message, type) {
851
+ const messagesDiv = document.getElementById('chat-messages');
852
+ const messageDiv = document.createElement('div');
853
+ messageDiv.className = `message ${type}-message`;
854
+
855
+ const sanitizedMessage = message.replace(/</g, '&lt;').replace(/>/g, '&gt;');
856
+ const time = new Date().toLocaleTimeString('fa-IR', {
857
+ hour: '2-digit',
858
+ minute: '2-digit'
859
+ });
860
+
861
+ messageDiv.innerHTML = `
862
+ <div class="message-content">${sanitizedMessage}</div>
863
+ <span class="message-time">${time}</span>
864
+ `;
865
+
866
+ messagesDiv.appendChild(messageDiv);
867
+ requestAnimationFrame(() => {
868
+ messageDiv.scrollIntoView({ behavior: 'smooth', block: 'end' });
869
+ });
870
+ }
871
+
872
+ // دانلود تاریخچه چت
873
+ function downloadChat() {
874
+ const messages = document.getElementById('chat-messages');
875
+ const text = Array.from(messages.children)
876
+ .map(msg => {
877
+ const content = msg.querySelector('.message-content')?.textContent || msg.textContent;
878
+ const time = msg.querySelector('.message-time')?.textContent || '';
879
+ let type = 'سیستم';
880
+ if (msg.classList.contains('user-message')) type = 'شما';
881
+ else if (msg.classList.contains('bot-message')) type = 'دستیار';
882
+ return `[${time}] ${type}: ${content}`;
883
+ })
884
+ .join('\n');
885
+
886
+ const now = new Date().toLocaleDateString('fa-IR');
887
+ const blob = new Blob([text], { type: 'text/plain;charset=utf-8' });
888
+ const url = URL.createObjectURL(blob);
889
+ const a = document.createElement('a');
890
+ a.href = url;
891
+ a.download = `chat-${now}.txt`;
892
+ document.body.appendChild(a);
893
+ a.click();
894
+ document.body.removeChild(a);
895
+ URL.revokeObjectURL(url);
896
+
897
+ handleError("✅ تاریخچه چت با موفقیت دانلود شد");
898
+ }
899
+
900
+ // پاک کردن تاریخچه چت
901
+ function clearChat() {
902
+ if (confirm('آیا مطمئن هستید که می‌خواهید تاریخچه چت را پاک کنید؟')) {
903
+ const messages = document.getElementById('chat-messages');
904
+ const currentTime = new Date().toLocaleTimeString('fa-IR', {
905
+ hour: '2-digit',
906
+ minute: '2-digit'
907
+ });
908
+
909
+ messages.innerHTML = `
910
+ <div class="message bot-message">
911
+ سلام! من یک دستیار هوش مصنوعی هستم. چطور می‌توانم کمکتان کنم؟
912
+ <span class="message-time">${currentTime}</span>
913
+ </div>
914
+ `;
915
+ handleError("✅ تاریخچه چت با موفقیت پاک شد");
916
+ }
917
+ }
918
+
919
+ // به‌روزرسانی زمان سیستم
920
+ function updateSystemTime() {
921
+ const systemTime = document.getElementById('system-time');
922
+ systemTime.textContent = new Date().toLocaleString('fa-IR');
923
+ }
924
+
925
+ // مدیریت کلید Enter
926
+ function handleEnterKey(event) {
927
+ if (event.key === 'Enter' && !event.shiftKey) {
928
+ event.preventDefault();
929
+ sendMessage();
930
+ }
931
+ }
932
+
933
+ // فعال کردن ورودی زمانی که موس وارد باکس ورودی می‌شود
934
+ function enableChatInput() {
935
+ if (!chatEnabled) return;
936
+ const messageInput = document.getElementById('messageInput');
937
+ const sendButton = document.getElementById('sendButton');
938
+ messageInput.disabled = false;
939
+ sendButton.disabled = false;
940
+ messageInput.focus();
941
+ }
942
+
943
+ // مقداردهی اولیه
944
+ function initialize() {
945
+ const savedTheme = localStorage.getItem('theme');
946
+ if (savedTheme === 'dark') {
947
+ document.body.classList.add('dark-theme');
948
+ document.getElementById('themeToggle').textContent = '☀️';
949
+ }
950
+
951
+ const savedSound = localStorage.getItem('sound');
952
+ if (savedSound === 'false') {
953
+ soundEnabled = false;
954
+ document.getElementById('soundToggle').textContent = '🔇';
955
+ }
956
+
957
+ connectWebSocket();
958
+
959
+ setInterval(updateStatus, 30000);
960
+ setInterval(updateSystemTime, 1000);
961
+ updateSystemTime();
962
+
963
+ if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
964
+ && !localStorage.getItem('theme')) {
965
+ document.body.classList.add('dark-theme');
966
+ document.getElementById('themeToggle').textContent = '☀️';
967
+ }
968
+
969
+ document.getElementById('messageInput').addEventListener('keypress', handleEnterKey);
970
+
971
+ // اینجا رویداد ماوس رو اضافه می‌کنیم
972
+ const inputContainer = document.getElementById('inputContainer');
973
+ inputContainer.addEventListener('mouseover', enableChatInput);
974
+ }
975
+
976
+ window.addEventListener('load', initialize);
977
+ </script>
978
+ </body>
979
+ </html>
templates/massage.mp3 ADDED
Binary file (68.5 kB). View file