joermd commited on
Commit
778176a
·
verified ·
1 Parent(s): 382813c

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +122 -559
index.html CHANGED
@@ -3,15 +3,12 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>منصة مراجعة النصوص والترجمات - شركة موندو لينجوا</title>
7
- <!-- استيراد Tailwind CSS, FontAwesome, Mammoth, SheetJS و jsPDF -->
8
  <link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
9
- <script src="https://cdnjs.cloudflare.com/ajax/libs/mammoth/1.6.0/mammoth.browser.min.js"></script>
10
- <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.17.4/xlsx.full.min.js"></script>
11
- <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
12
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
13
  <style>
14
- /* تأثيرات الحركة والتدرج */
15
  @keyframes gradient {
16
  0% { background-position: 0% 50%; }
17
  50% { background-position: 100% 50%; }
@@ -21,603 +18,169 @@
21
  background-size: 200% 200%;
22
  animation: gradient 15s ease infinite;
23
  }
24
- .transition-all { transition: all 0.3s ease-in-out; }
25
- .animate-scale { transition: transform 0.2s ease-in-out; }
26
- .animate-scale:hover { transform: scale(1.02); }
27
- .pulse-animation { animation: pulse 2s infinite; }
28
- @keyframes pulse {
29
- 0% { box-shadow: 0 0 0 0 rgba(0,0,0,0.2); }
30
- 70% { box-shadow: 0 0 0 10px rgba(0,0,0,0); }
31
- 100% { box-shadow: 0 0 0 0 rgba(0,0,0,0); }
32
  }
33
-
34
- /* تنسيق النصوص والتظليل */
35
- .text-comparison { line-height: 1.8; white-space: pre-wrap; }
36
- .highlight-missing {
37
- background-color: #f87171;
38
- color: #fff;
39
- padding: 0 4px;
40
- border-radius: 3px;
41
- font-weight: bold;
42
- }
43
- .highlight-number {
44
- background-color: #facc15;
45
- color: #000;
46
- padding: 0 4px;
47
- border-radius: 3px;
48
- font-weight: bold;
49
- }
50
- .highlight-abbreviation {
51
- background-color: #34d399;
52
- color: #fff;
53
- padding: 0 4px;
54
- border-radius: 3px;
55
- font-weight: bold;
56
- }
57
-
58
- /* تقسيم الفقرات وترقيمها */
59
- .line-item {
60
- margin-bottom: 1rem;
61
- padding: 0.5rem;
62
- border-bottom: 1px dashed #ccc;
63
- }
64
- .line-number {
65
- font-weight: bold;
66
- color: #4B5563;
67
- margin-left: 0.5rem;
68
- }
69
- .line-text { display: inline-block; }
70
-
71
- /* تصميم البطاقات */
72
- .card {
73
- background-color: #fff;
74
- border-radius: 1rem;
75
- box-shadow: 0 10px 25px -5px rgba(0,0,0,0.1);
76
- padding: 2rem;
77
- border: 1px solid #f3f4f6;
78
- }
79
- .card-hover:hover {
80
- box-shadow: 0 10px 25px -5px rgba(0,0,0,0.2);
81
- transform: translateY(-3px);
82
- }
83
- .icon { margin-left: 0.5rem; }
84
- .upload-label {
85
- display: flex;
86
- flex-direction: row-reverse;
87
- align-items: center;
88
- justify-content: center;
89
  }
90
  /* منطقة سلسلة التفكير */
91
  #chainOfThought {
92
  display: none;
93
- margin-top: 1rem;
94
- background-color: #f9fafb;
95
- padding: 1rem;
96
  border: 1px solid #e5e7eb;
97
  border-radius: 0.5rem;
 
98
  font-size: 0.9rem;
99
  direction: ltr;
100
  text-align: left;
101
  }
 
 
 
 
 
 
 
 
102
  </style>
103
  </head>
104
  <body class="bg-gradient-to-br from-gray-100 via-blue-100 to-indigo-100 min-h-screen">
105
- <div class="min-h-screen pb-12">
106
  <!-- رأس الصفحة -->
107
- <header class="bg-gradient-to-r from-indigo-800 via-purple-800 to-pink-800 animate-gradient text-white py-12 mb-12 shadow-2xl">
108
- <div class="max-w-6xl mx-auto px-4 text-center">
109
- <h1 class="text-6xl font-extrabold mb-4 animate-scale">
110
- منصة مراجعة النصوص والترجمات <i class="fas fa-chart-line icon"></i>
111
- </h1>
112
- <p class="text-2xl opacity-90">
113
- تحليل دقيق لاستخراج النصوص المفقودة فقط عبر ترجمة النص الهدف إلى لغة المصدر
114
- </p>
115
- </div>
116
  </header>
117
-
118
- <!-- المحتوى الرئيسي -->
119
- <main class="max-w-7xl mx-auto px-4 space-y-10">
120
- <!-- رفع الملفات وإدخال النصوص -->
121
- <div class="card card-hover">
122
- <h2 class="text-3xl font-bold text-gray-800 border-b pb-3 mb-6">
123
- <i class="fas fa-file-upload icon text-indigo-600"></i> تحميل الملفات / إدخال النصوص
124
- </h2>
125
- <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
126
- <!-- ملف المصدر -->
127
- <div class="group border-2 border-dashed border-indigo-300 rounded-xl p-10 text-center bg-indigo-50 hover:bg-indigo-100 transition-colors duration-300">
128
- <label class="cursor-pointer block upload-label">
129
- <input type="file" id="sourceFile" accept=".docx,.pdf,.xlsx,.xls" class="hidden">
130
- <span class="text-xl text-indigo-600 group-hover:text-indigo-700">ملف المصدر</span>
131
- <i class="fas fa-upload text-6xl text-indigo-500 mb-4"></i>
132
- </label>
133
- </div>
134
- <!-- ملف الهدف -->
135
- <div class="group border-2 border-dashed border-pink-300 rounded-xl p-10 text-center bg-pink-50 hover:bg-pink-100 transition-colors duration-300">
136
- <label class="cursor-pointer block upload-label">
137
- <input type="file" id="targetFile" accept=".docx,.pdf,.xlsx,.xls" class="hidden">
138
- <span class="text-xl text-pink-600 group-hover:text-pink-700">ملف الهدف</span>
139
- <i class="fas fa-download text-6xl text-pink-500 mb-4"></i>
140
- </label>
141
- </div>
142
- </div>
143
- <div id="processStatus" class="hidden mt-6">
144
- <div class="flex items-center justify-end space-x-3 bg-indigo-100 rounded-xl p-4">
145
- <span class="text-xl text-indigo-700">جارٍ معالجة الملف...</span>
146
- <div class="animate-spin h-10 w-10 border-4 border-indigo-600 rounded-full border-t-transparent"></div>
147
- </div>
148
- </div>
149
- <div class="mt-8 grid grid-cols-1 md:grid-cols-2 gap-8">
150
- <!-- إدخال النصوص يدويًا -->
151
- <div class="group">
152
- <label class="block text-2xl font-bold text-gray-700 mb-4">
153
- <i class="fas fa-language icon text-indigo-600"></i> النص المصدر
154
- </label>
155
- <textarea id="sourceText" dir="rtl" class="w-full px-8 py-6 border-2 border-gray-200 rounded-xl focus:ring-indigo-200 focus:border-indigo-400 transition-all resize-none text-xl" rows="8" placeholder="اكتب النص المصدر هنا..."></textarea>
156
- </div>
157
- <div class="group">
158
- <label class="block text-2xl font-bold text-gray-700 mb-4">
159
- <i class="fas fa-language icon text-pink-600"></i> النص الهدف
160
- </label>
161
- <textarea id="targetText" dir="ltr" class="w-full px-8 py-6 border-2 border-gray-200 rounded-xl focus:ring-pink-200 focus:border-pink-400 transition-all resize-none text-xl" rows="8" placeholder="اكتب النص الهدف هنا..."></textarea>
162
- </div>
163
- </div>
164
  </div>
165
-
166
- <!-- المصادر الإضافية -->
167
- <div class="card card-hover">
168
- <h2 class="text-3xl font-bold text-gray-800 border-b pb-3 mb-6">
169
- <i class="fas fa-book-open icon text-green-600"></i> مصادر إضافية
170
- </h2>
171
- <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
172
- <!-- رفع ملف المصادر -->
173
- <div class="group border-2 border-dashed border-green-300 rounded-xl p-10 text-center bg-green-50 hover:bg-green-100 transition-colors duration-300">
174
- <label class="cursor-pointer block upload-label">
175
- <input type="file" id="sourceExtraFile" accept=".docx,.pdf,.xlsx,.xls" class="hidden">
176
- <span class="text-xl text-green-600 group-hover:text-green-700">تحميل ملف المصادر</span>
177
- <i class="fas fa-upload text-6xl text-green-500 mb-4"></i>
178
- </label>
179
- </div>
180
- <!-- إدخال المصادر يدويًا -->
181
- <div class="group">
182
- <label class="block text-2xl font-bold text-gray-700 mb-4">
183
- <i class="fas fa-edit icon text-green-600"></i> إدخال المصادر يدويًا
184
- </label>
185
- <textarea id="sourceExtraText" dir="rtl" class="w-full px-8 py-6 border-2 border-green-200 rounded-xl focus:ring-green-200 focus:border-green-400 transition-all resize-none text-xl" rows="8" placeholder="اكتب المصادر هنا..."></textarea>
186
- </div>
187
- </div>
188
  </div>
189
-
190
- <!-- زر التحليل والمراجعة -->
191
- <button id="submitBtn" class="w-full bg-gradient-to-r from-indigo-700 to-pink-700 hover:from-indigo-800 hover:to-pink-800 text-white font-bold py-6 px-10 rounded-xl transition-all transform hover:scale-105 focus:ring-indigo-200 text-2xl shadow-2xl hover:shadow-2xl pulse-animation">
192
- <div class="flex items-center justify-center">
193
- <span>تحليل ومراجعة النصوص</span>
194
- <i class="fas fa-sync-alt icon mr-4"></i>
195
- </div>
196
  </button>
197
-
198
- <!-- عرض النتائج -->
199
- <div id="resultSection" class="card hidden">
200
- <h2 class="text-3xl font-bold text-gray-800 border-b pb-4 mb-6">
201
- <i class="fas fa-search icon text-green-600"></i> نتائج التحليل والمقارنة
202
- </h2>
203
- <div id="errorsList" class="space-y-4 mb-6"></div>
204
- <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
205
- <div>
206
- <h4 class="text-2xl font-bold text-gray-700 mb-4">
207
- <i class="fas fa-file-alt icon text-indigo-600"></i> النص المصدر (مع التعليم)
208
- </h4>
209
- <div id="sourceTextReview" class="bg-indigo-50 rounded-xl p-8 min-h-[250px] border-2 border-indigo-200 text-comparison"></div>
210
- </div>
211
- <div>
212
- <h4 class="text-2xl font-bold text-gray-700 mb-4">
213
- <i class="fas fa-file-alt icon text-pink-600"></i> النص الهدف (بدون تعليم)
214
- </h4>
215
- <div id="targetTextReview" class="bg-gray-50 rounded-xl p-8 min-h-[250px] border-2 border-gray-300 text-comparison"></div>
216
- </div>
217
- </div>
218
- <div id="explanationBox" class="mt-8">
219
- <h2 class="text-3xl font-bold text-gray-800 border-b pb-4 mb-6">
220
- <i class="fas fa-info-circle icon text-green-600"></i> شرح الاختلافات
221
- </h2>
222
- <div id="explanationText" class="text-2xl text-gray-700"></div>
223
- </div>
224
- <!-- منطقة سلسلة التفكير -->
225
- <div id="chainOfThought">
226
- <h3 class="text-lg font-bold text-gray-800 mb-2">سلسلة التفكير:</h3>
227
- <pre id="chainText" class="whitespace-pre-wrap text-gray-700"></pre>
228
- </div>
229
- </div>
230
-
231
- <!-- قسم معلومات المترجم والتقرير وإعادة المراجعة -->
232
- <div id="reportSection" class="card hidden">
233
- <h2 class="text-3xl font-bold text-gray-800 border-b pb-4 mb-6">
234
- معلومات وتقرير المراجعة
235
- </h2>
236
- <div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-6">
237
- <div>
238
- <label class="block text-2xl font-bold text-gray-700 mb-2">اسم/كود المترجم</label>
239
- <input id="translatorName" type="text" class="w-full px-4 py-3 border-2 border-gray-300 rounded-xl focus:ring-indigo-200 focus:border-indigo-400 text-xl" placeholder="أدخل اسم المترجم أو الكود">
240
- </div>
241
- <div>
242
- <label class="block text-2xl font-bold text-gray-700 mb-2">التقييم</label>
243
- <select id="translatorRating" class="w-full px-4 py-3 border-2 border-gray-300 rounded-xl focus:ring-indigo-200 focus:border-indigo-400 text-xl">
244
- <option value="5">5 - ممتاز</option>
245
- <option value="4">4 - جيد جداً</option>
246
- <option value="3">3 - جيد</option>
247
- <option value="2">2 - متوسط</option>
248
- <option value="1">1 - ضعيف</option>
249
- </select>
250
- </div>
251
- <div class="flex flex-col justify-end">
252
- <button id="reReviewBtn" class="w-full bg-yellow-500 hover:bg-yellow-600 text-white font-bold py-3 px-4 rounded-xl transition-all text-xl shadow-lg">
253
- إعادة المراجعة
254
- </button>
255
- </div>
256
- </div>
257
- <div class="flex items-center justify-around">
258
- <button id="downloadPdfBtn" class="bg-green-600 hover:bg-green-700 text-white font-bold py-3 px-6 rounded-xl transition-all text-xl shadow-lg">
259
- تنزيل التقرير PDF
260
- </button>
261
- <button id="downloadWordBtn" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-6 rounded-xl transition-all text-xl shadow-lg">
262
- تن��يل التقرير Word
263
- </button>
264
- </div>
265
- </div>
266
-
267
- </main>
268
  </div>
269
-
270
- <!-- جافا سكريبت: الوظائف والتحليل وتنزيل التقرير -->
271
  <script>
272
- (function() {
273
  "use strict";
274
 
275
- // متغير لإعادة المحاولة إذا ظهر "server is busy"
276
- let retryCount = 0;
277
-
278
- /* برومت مبسط:
279
- - ترجم النص الهدف إلى لغة النص المصدر.
280
- - قارن بين النص المصدر والنص الهدف المترجم.
281
- - ضع الاختلافات (النصوص الناقصة) بين أقواس ().
282
- - أضف تعريفاً مبسطاً يوضح الفرق بين النصين.
283
- - إذا كانت النصوص متطابقة، اكتب [MATCH].
284
- - أضف "مكافأة: لقد نجحت في التحدي!" إذا كانت النتائج دقيقة، أو "عقوبة: فشلت في التحدي!" إذا كان هناك خطأ.
285
- - إذا ظهر "server is busy"، أعد المحاولة.
286
-
287
  النص المصدر:
288
  {source}
289
-
290
  النص الهدف:
291
  {target}`;
292
 
293
- // دوال مساعدة عامة
294
- const countWords = text =>
295
- text.trim().split(/\s+/).filter(word => word !== "").length;
296
-
297
- const escapeRegExp = string =>
298
- string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
299
-
300
- // تقسيم النص إلى فقرات مرقمة
301
- const splitIntoLines = text =>
302
- text.split(/\n+/).map((line, i) => {
303
- line = line.trim();
304
- if(line && !line.endsWith('.')) { line += '.'; }
305
- return `<div class="line-item"><span class="line-number">${i+1}:</span><span class="line-text">${line}</span></div>`;
306
- }).join('');
307
-
308
- // الحصول على رقم السطر الذي يحتوي على عبارة معينة
309
- const getLineNumber = (text, substring) => {
310
- const index = text.indexOf(substring);
311
- if (index === -1) return "غير محدد";
312
- return text.substring(0, index).split("\n").length;
313
  };
314
-
315
- // تطبيق التظليل على النص المصدر بناءً على نتائج التحليل
316
- const applyHighlights = (originalText, analysisOutput) => {
317
- let highlightedText = originalText;
318
- let match;
319
- // تظليل النصوص المفقودة
320
- const missingRegex = /__(.*?)__/g;
321
- while ((match = missingRegex.exec(analysisOutput)) !== null) {
322
- const phrase = match[1].trim();
323
- if (phrase) {
324
- const replacement = `<span class="highlight-missing">(${phrase})</span>`;
325
- const phraseRegex = new RegExp(escapeRegExp(phrase), 'g');
326
- highlightedText = highlightedText.replace(phraseRegex, replacement);
327
- }
328
- }
329
- // تظليل الأرقام والتواريخ
330
- const numberRegex = /<([^<>]+)>/g;
331
- while ((match = numberRegex.exec(analysisOutput)) !== null) {
332
- const phrase = match[1].trim();
333
- if (phrase) {
334
- const replacement = `<span class="highlight-number">(${phrase})</span>`;
335
- const phraseRegex = new RegExp(escapeRegExp(phrase), 'g');
336
- highlightedText = highlightedText.replace(phraseRegex, replacement);
337
- }
338
- }
339
- // تظليل الاختصارات
340
- const abbrRegex = /{ABBR}(.*?){\/ABBR}/g;
341
- while ((match = abbrRegex.exec(analysisOutput)) !== null) {
342
- const phrase = match[1].trim();
343
- if (phrase) {
344
- const replacement = `<span class="highlight-abbreviation">(${phrase})</span>`;
345
- const phraseRegex = new RegExp(escapeRegExp(phrase), 'g');
346
- highlightedText = highlightedText.replace(phraseRegex, replacement);
347
- }
348
- }
349
- return highlightedText;
350
  };
351
-
352
- // توليد شرح تفصيلي للاختلافات
353
- const generateExplanation = (sourceText, analysisOutput) => {
354
- let explanations = [];
355
- const iconMissing = `<i class="fas fa-exclamation-triangle mr-1"></i>`;
356
- const iconNumber = `<i class="fas fa-hashtag mr-1"></i>`;
357
- const iconMeaning = `<i class="fas fa-info-circle mr-1"></i>`;
358
- const iconAbbr = `<i class="fas fa-font mr-1"></i>`;
359
-
360
- // شرح النصوص المفقودة
361
- const missingRegex = /__(.*?)__/g;
362
- let match;
363
- while ((match = missingRegex.exec(analysisOutput)) !== null) {
364
- const phrase = match[1].trim();
365
- if (phrase) {
366
- const lineNum = getLineNumber(sourceText, phrase);
367
- explanations.push(`<p>${iconMissing} في السطر ${lineNum}: النص المفقود (${phrase})</p>`);
368
- }
369
- }
370
- // شرح الأرقام والتواريخ
371
- const numberRegex = /<([^<>]+)>/g;
372
- while ((match = numberRegex.exec(analysisOutput)) !== null) {
373
- const phrase = match[1].trim();
374
- if (phrase) {
375
- const lineNum = getLineNumber(sourceText, phrase);
376
- explanations.push(`<p>${iconNumber} في السطر ${lineNum}: الرقم/التاريخ (${phrase})</p>`);
377
- }
378
- }
379
- // شرح اختلاف المعنى
380
- const meaningRegex = /\[MEANING\](.*?)\[\/MEANING\]/g;
381
- while ((match = meaningRegex.exec(analysisOutput)) !== null) {
382
- const phrase = match[1].trim();
383
- if (phrase) {
384
- const lineNum = getLineNumber(sourceText, phrase);
385
- explanations.push(`<p>${iconMeaning} في السطر ${lineNum}: اختلاف المعنى (${phrase})</p>`);
386
- }
387
- }
388
- // شرح الاختصارات
389
- const abbrRegex = /{ABBR}(.*?){\/ABBR}/g;
390
- while ((match = abbrRegex.exec(analysisOutput)) !== null) {
391
- const phrase = match[1].trim();
392
- if (phrase) {
393
- const lineNum = getLineNumber(sourceText, phrase);
394
- explanations.push(`<p>${iconAbbr} في السطر ${lineNum}: الاختصار (${phrase})</p>`);
395
- }
396
- }
397
-
398
- const usedSource = analysisOutput.includes('[USED_SOURCE]');
399
- let sourceNote = usedSource ? `<p><i class="fas fa-book-reader mr-1"></i> تم استخدام مصادر خارجية.</p>`
400
- : `<p><i class="fas fa-book mr-1"></i> لم يتم استخدام مصادر خارجية.</p>`;
401
-
402
- if (explanations.length === 0) {
403
- return `<p><i class="fas fa-check-circle mr-2"></i> لا توجد اختلافات ملحوظة.</p>` + sourceNote;
404
- }
405
- return explanations.join('') + sourceNote;
406
- };
407
-
408
- // دالة معالجة الملفات (PDF, DOCX, Excel)
409
- const processFile = async file => {
410
- let text = "";
411
  try {
412
- if (file.type === 'application/pdf') {
413
- const form = new FormData();
414
- form.append('image', file);
415
- const response = await fetch('https://demo.api4ai.cloud/ocr/v1/results', {
416
- method: 'POST',
417
- body: form,
418
- headers: { 'A4A-CLIENT-APP-ID': 'sample' }
419
- });
420
- const data = await response.json();
421
- text = data.results?.[0]?.entities?.[0]?.objects?.[0]?.entities?.[0]?.text || "";
422
- } else if (file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
423
- const arrayBuffer = await file.arrayBuffer();
424
- const result = await mammoth.extractRawText({ arrayBuffer });
425
- text = result.value;
426
- } else if (file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || file.type === 'application/vnd.ms-excel') {
427
- const arrayBuffer = await file.arrayBuffer();
428
- const workbook = XLSX.read(arrayBuffer, { type: 'array' });
429
- let sheetData = [];
430
- workbook.SheetNames.forEach(sheetName => {
431
- const sheet = workbook.Sheets[sheetName];
432
- const html = XLSX.utils.sheet_to_html(sheet);
433
- sheetData.push(html);
434
- });
435
- text = sheetData.join('\n');
436
- } else {
437
- throw new Error('نوع الملف غير مدعوم');
438
  }
 
 
439
  } catch (error) {
440
- console.error('Error processing file:', error);
441
  throw error;
442
  }
443
- return text;
444
- };
445
-
446
- // التعامل مع رفع الملفات
447
- const processFileInput = (inputId, targetTextAreaId, errorMsg) => {
448
- document.getElementById(inputId)?.addEventListener('change', async (event) => {
449
- const file = event.target.files[0];
450
- if (!file) return;
451
- document.getElementById('processStatus').classList.remove('hidden');
452
- try {
453
- const text = await processFile(file);
454
- document.getElementById(targetTextAreaId).value = text;
455
- } catch (error) {
456
- addError(errorMsg);
457
- } finally {
458
- document.getElementById('processStatus').classList.add('hidden');
459
- }
460
- });
461
- };
462
-
463
- // رفع ملفات المصدر، الهدف والمصادر الإضافية
464
- processFileInput('sourceFile', 'sourceText', 'خطأ في معالجة ملف المصدر');
465
- processFileInput('targetFile', 'targetText', 'خطأ في معالجة ملف الهدف');
466
- processFileInput('sourceExtraFile', 'sourceExtraText', 'خطأ في معالجة ملف المصادر الإضافية');
467
-
468
- // دالة عرض الأخطاء
469
- const addError = (message, type = 'error') => {
470
- const errorsList = document.getElementById('errorsList');
471
- if (!errorsList) return;
472
- const errorDiv = document.createElement('div');
473
- errorDiv.className = `p-4 rounded-xl ${type === 'error' ? 'bg-red-50 text-red-700' : 'bg-yellow-50 text-yellow-700'}`;
474
- errorDiv.innerHTML = `<div class="flex items-center">
475
- <i class="fas fa-${type === 'error' ? 'exclamation-circle' : 'info-circle'} mr-2"></i>
476
- <span>${message}</span>
477
- </div>`;
478
- errorsList.appendChild(errorDiv);
479
- };
480
-
481
- // وظيفة تنزيل التقرير بصيغة PDF
482
- const downloadReportPDF = () => {
483
- const { jsPDF } = window.jspdf;
484
- const doc = new jsPDF({ orientation: 'p', unit: 'pt', format: 'a4' });
485
- doc.setFont('Arial');
486
- doc.setFontSize(12);
487
- const translatorInfo = `اسم المترجم/الكود: ${document.getElementById('translatorName').value}\nالتقييم: ${document.getElementById('translatorRating').value}`;
488
- const errorsText = document.getElementById('explanationText').innerText;
489
- const report = `تقرير الأخطاء:\n\n${errorsText}\n\n${translatorInfo}`;
490
- doc.text(report, 10, 30, { align: 'right' });
491
- doc.save("تقرير_المراجعة.pdf");
492
- };
493
-
494
- // وظيفة تنزيل التقرير بصيغة Word
495
- const downloadReportWord = () => {
496
- const translatorInfo = `اسم المترجم/الكود: ${document.getElementById('translatorName').value}\nالتقييم: ${document.getElementById('translatorRating').value}\n\n`;
497
- const errorsText = document.getElementById('explanationText').innerText;
498
- const report = `\uFEFFتقرير الأخطاء:\n\n${errorsText}\n\n${translatorInfo}`;
499
- const blob = new Blob([report], { type: 'application/msword;charset=utf-8' });
500
- const link = document.createElement('a');
501
- link.href = URL.createObjectURL(blob);
502
- link.download = "تقرير_المراجعة.doc";
503
- link.click();
504
- };
505
-
506
- // إعادة المراجعة
507
- const reReview = () => {
508
- document.getElementById('resultSection').classList.add('hidden');
509
- document.getElementById('reportSection').classList.add('hidden');
510
- document.getElementById('errorsList').innerHTML = '';
511
- document.getElementById('sourceTextReview').innerHTML = '';
512
- document.getElementById('targetTextReview').innerHTML = '';
513
- document.getElementById('explanationText').innerHTML = '';
514
- document.getElementById('chainOfThought').style.display = "none";
515
- retryCount = 0;
516
- };
517
-
518
- // عملية التحليل عند الضغط على زر التحليل
519
- document.getElementById('submitBtn').addEventListener('click', async () => {
520
- const sourceText = document.getElementById('sourceText').value;
521
- const targetText = document.getElementById('targetText').value;
522
- document.getElementById('errorsList').innerHTML = '';
523
- document.getElementById('resultSection').classList.remove('hidden');
524
-
525
  if (!sourceText || !targetText) {
526
- addError('يرجى إدخال كلا النصين المصدر والهدف');
527
  return;
528
  }
529
-
530
- if (countWords(sourceText) !== countWords(targetText)) {
531
- addError(`عدد كلمات النص المصدر يختلف عن النص الهدف`, 'warning');
532
- }
533
-
534
  try {
535
- const progressDiv = document.createElement('div');
536
- progressDiv.className = "bg-indigo-100 p-4 rounded-xl mb-4";
537
- progressDiv.innerHTML = `<div class="flex items-center justify-end">
538
- <span class="text-xl">جارٍ التحليل...</span>
539
- <div class="animate-spin h-10 w-10 border-4 border-indigo-600 rounded-full border-t-transparent ml-4"></div>
540
- </div>`;
541
- document.getElementById('errorsList').appendChild(progressDiv);
542
-
543
- // التأكد من إرسال النصوص: تسجيل الـ payload في وحدة التحكم
544
- const prompt = ANALYSIS_PROMPT
545
- .replace("{source}", sourceText)
546
- .replace("{target}", targetText);
547
- const payload = {
548
- model: "deepseek-chat",
549
- messages: [
550
- { role: "system", content: "أنت نموذج DeepSeek؛ ترجم النص الهدف إلى لغة النص المصدر ثم قارن بينهما واخرج فقط الاختلافات (النصوص الناقصة) مع وضعها بين أقواس ()." },
551
- { role: "user", content: prompt }
552
- ],
553
- temperature: 0.3,
554
- max_tokens: 2048,
555
- stream: false
556
- };
557
- console.log("Sending payload:", payload);
558
-
559
- const response = await fetch('https://api.deepseek.com/chat/completions', {
560
- method: 'POST',
561
- headers: {
562
- 'Authorization': 'Bearer sk-15606736ed9e4aea8b7cc11a195d2b01',
563
- 'Content-Type': 'application/json'
564
- },
565
- body: JSON.stringify(payload)
566
- });
567
-
568
- if (!response.ok) {
569
- throw new Error('حدث خطأ بالشبكة: ' + response.statusText);
570
- }
571
- const data = await response.json();
572
- let analysisOutput = data.choices[0].message.content.trim();
573
- progressDiv.remove();
574
-
575
- // عرض سلسلة التفكير في منطقة خاصة (قبل التعليم)
576
  document.getElementById('chainText').innerText = analysisOutput;
577
  document.getElementById('chainOfThought').style.display = "block";
578
-
579
- // إذا ظهر "server is busy" أعد المحاولة
580
- if (analysisOutput.toLowerCase().includes("server is busy")) {
581
- if (retryCount < 3) {
582
- retryCount++;
583
- setTimeout(() => {
584
- document.getElementById('submitBtn').click();
585
- }, 3000);
586
- return;
587
- } else {
588
- throw new Error("الخادم مشغول. يرجى المحاولة لاحقاً.");
589
- }
590
- }
591
-
592
- if (analysisOutput.includes('[MATCH]')) {
593
- const checkDiv = document.createElement('div');
594
- checkDiv.className = "p-4 rounded-xl bg-green-50 text-green-700 flex items-center";
595
- checkDiv.innerHTML = `<i class="fas fa-check-circle mr-2"></i> <span>النصوص متطابقة تماماً</span>`;
596
- document.getElementById('errorsList').appendChild(checkDiv);
597
- document.getElementById('sourceTextReview').innerHTML = splitIntoLines(sourceText);
598
- document.getElementById('targetTextReview').innerHTML = splitIntoLines(targetText);
599
- document.getElementById('explanationText').innerHTML = `<p class="text-xl">النصوص متطابقة ولا يوجد اختلاف.</p>`;
600
- } else {
601
- const sourceHighlighted = applyHighlights(sourceText, analysisOutput);
602
- document.getElementById('sourceTextReview').innerHTML = splitIntoLines(sourceHighlighted);
603
- document.getElementById('targetTextReview').innerHTML = splitIntoLines(targetText);
604
- const explanationHTML = generateExplanation(sourceText, analysisOutput);
605
- document.getElementById('explanationText').innerHTML = explanationHTML;
606
- }
607
-
608
- document.getElementById('reportSection').classList.remove('hidden');
609
-
610
  } catch (error) {
611
- document.getElementById('errorsList').innerHTML = '';
612
- addError(`خطأ في التحليل: ${error.message}`);
 
613
  }
614
  });
615
-
616
- // مستمعي الأحداث لأزرار التقرير وإعادة المراجعة
617
- document.getElementById('downloadPdfBtn').addEventListener('click', downloadReportPDF);
618
- document.getElementById('downloadWordBtn').addEventListener('click', downloadReportWord);
619
- document.getElementById('reReviewBtn').addEventListener('click', reReview);
620
-
621
  })();
622
  </script>
623
  </body>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>تحليل بسيط للنصوص والترجمات</title>
7
+ <!-- استيراد Tailwind CSS وFontAwesome -->
8
  <link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
 
 
 
9
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
10
  <style>
11
+ /* تأثيرات خلفية متدرجة وحركة بسيطة */
12
  @keyframes gradient {
13
  0% { background-position: 0% 50%; }
14
  50% { background-position: 100% 50%; }
 
18
  background-size: 200% 200%;
19
  animation: gradient 15s ease infinite;
20
  }
21
+ .spinner {
22
+ border: 4px solid #f3f3f3;
23
+ border-top: 4px solid #4f46e5;
24
+ border-radius: 50%;
25
+ width: 40px;
26
+ height: 40px;
27
+ animation: spin 1s linear infinite;
 
28
  }
29
+ @keyframes spin {
30
+ 0% { transform: rotate(0deg); }
31
+ 100% { transform: rotate(360deg); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  }
33
  /* منطقة سلسلة التفكير */
34
  #chainOfThought {
35
  display: none;
36
+ background: #f9fafb;
37
+ padding: 0.5rem;
 
38
  border: 1px solid #e5e7eb;
39
  border-radius: 0.5rem;
40
+ margin-top: 1rem;
41
  font-size: 0.9rem;
42
  direction: ltr;
43
  text-align: left;
44
  }
45
+ /* تظليل الاختلافات */
46
+ .highlight {
47
+ color: white;
48
+ background-color: #ef4444;
49
+ padding: 0 3px;
50
+ border-radius: 3px;
51
+ font-weight: bold;
52
+ }
53
  </style>
54
  </head>
55
  <body class="bg-gradient-to-br from-gray-100 via-blue-100 to-indigo-100 min-h-screen">
56
+ <div class="max-w-5xl mx-auto py-12">
57
  <!-- رأس الصفحة -->
58
+ <header class="text-center mb-12">
59
+ <h1 class="text-5xl font-bold mb-4 animate-gradient">تحليل النصوص والترجمات</h1>
60
+ <p class="text-2xl">ترجم النص الهدف إلى العربية مع الاهتمام بالتعليم، ثم قارن مع النص المصدر واخرج الاختلافات (النصوص الناقصة) فقط.</p>
 
 
 
 
 
 
61
  </header>
62
+
63
+ <!-- منطقة الإدخال -->
64
+ <div class="space-y-6">
65
+ <div>
66
+ <label class="block text-2xl font-bold mb-2">النص المصدر</label>
67
+ <textarea id="sourceText" class="w-full p-4 border rounded-lg" rows="6" placeholder="اكتب النص المصدر هنا..."></textarea>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  </div>
69
+ <div>
70
+ <label class="block text-2xl font-bold mb-2">النص الهدف</label>
71
+ <textarea id="targetText" class="w-full p-4 border rounded-lg" rows="6" placeholder="اكتب النص الهدف هنا..."></textarea>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  </div>
73
+ </div>
74
+
75
+ <!-- زر التحليل ومؤشر التحميل -->
76
+ <div class="mt-6 flex items-center justify-center space-x-4">
77
+ <button id="analyzeBtn" class="px-8 py-4 bg-indigo-600 text-white font-bold rounded-lg hover:bg-indigo-700 transition">
78
+ تحليل ومراجعة النصوص
 
79
  </button>
80
+ <div id="loadingIndicator" class="spinner hidden"></div>
81
+ </div>
82
+
83
+ <!-- منطقة سلسلة التفكير -->
84
+ <div id="chainOfThought" class="mt-6">
85
+ <strong>سلسلة التفكير:</strong>
86
+ <pre id="chainText"></pre>
87
+ </div>
88
+
89
+ <!-- منطقة النتائج -->
90
+ <div id="resultSection" class="mt-8 hidden">
91
+ <h2 class="text-3xl font-bold mb-4">النتائج:</h2>
92
+ <div id="diffResult" class="p-4 border rounded-lg"></div>
93
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  </div>
95
+
 
96
  <script>
97
+ (function(){
98
  "use strict";
99
 
100
+ // برومت بسيط: يطلب من DeepSeek ترجمة النص الهدف إلى العربية مع التعليم، ثم مقارنة النصوص واستخراج الاختلافات (النصوص الناقصة) فقط مع وضعها بين أقواس.
101
+ const PROMPT = `ترجم النص الهدف إلى العربية مع الاهتمام بالتعليم، ثم قارن بين النص المصدر والنص الهدف المُترجم واخرج الاختلافات فقط (النصوص الناقصة) مع وضعها بين أقواس ().
 
 
 
 
 
 
 
 
 
 
102
  النص المصدر:
103
  {source}
 
104
  النص الهدف:
105
  {target}`;
106
 
107
+ // دالة عرض مؤشر التحميل
108
+ const showLoading = () => {
109
+ document.getElementById('loadingIndicator').classList.remove('hidden');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  };
111
+ const hideLoading = () => {
112
+ document.getElementById('loadingIndicator').classList.add('hidden');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  };
114
+
115
+ // دالة إرسال الطلب للنموذج
116
+ async function analyzeText(source, target) {
117
+ const payload = {
118
+ model: "deepseek-chat",
119
+ messages: [
120
+ { role: "system", content: "أنت نموذج DeepSeek. قم بترجمة النص الهدف إلى العربية مع الاهتمام بالتعليم ثم قارن مع النص المصدر واخرج الاختلافات (النصوص الناقصة) فقط مع وضعها بين أقواس ()." },
121
+ { role: "user", content: PROMPT.replace("{source}", source).replace("{target}", target) }
122
+ ],
123
+ temperature: 0.3,
124
+ max_tokens: 1024,
125
+ stream: false
126
+ };
127
+
128
+ console.log("Payload:", payload); // للتأكد من إرسال النصوص
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  try {
130
+ const response = await fetch("https://api.deepseek.com/chat/completions", {
131
+ method: "POST",
132
+ headers: {
133
+ "Authorization": "Bearer sk-15606736ed9e4aea8b7cc11a195d2b01",
134
+ "Content-Type": "application/json"
135
+ },
136
+ body: JSON.stringify(payload)
137
+ });
138
+ if (!response.ok) {
139
+ throw new Error("حدث خطأ في الاتصال: " + response.statusText);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  }
141
+ const data = await response.json();
142
+ return data.choices[0].message.content.trim();
143
  } catch (error) {
 
144
  throw error;
145
  }
146
+ }
147
+
148
+ // دالة معالجة النتيجة وتظليل الاختلافات
149
+ function processResult(source, analysisOutput) {
150
+ // هنا نقوم بتطبيق تظليل بسيط: نضع الاختلافات بين أقواس.
151
+ // افترضنا أن الاختلافات تظهر ضمن علامات معينة مثل __النص__ للنص المفقود.
152
+ // يمكن تعديل هذا الجزء حسب تنسيق الناتج.
153
+ let processed = analysisOutput.replace(/__(.*?)__/g, '<span class="highlight">($1)</span>');
154
+ return processed;
155
+ }
156
+
157
+ // مستمع الزر
158
+ document.getElementById('analyzeBtn').addEventListener('click', async () => {
159
+ const sourceText = document.getElementById('sourceText').value.trim();
160
+ const targetText = document.getElementById('targetText').value.trim();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  if (!sourceText || !targetText) {
162
+ alert("يرجى إدخال كلا النصين.");
163
  return;
164
  }
165
+ // إظهار مؤشر التحميل
166
+ showLoading();
167
+ document.getElementById('resultSection').classList.add('hidden');
168
+ document.getElementById('chainOfThought').style.display = "none";
 
169
  try {
170
+ const analysisOutput = await analyzeText(sourceText, targetText);
171
+ // عرض سلسلة التفكير قبل التعليم
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
  document.getElementById('chainText').innerText = analysisOutput;
173
  document.getElementById('chainOfThought').style.display = "block";
174
+ // معالجة الناتج (تظليل الاختلافات)
175
+ const diffResult = processResult(sourceText, analysisOutput);
176
+ document.getElementById('diffResult').innerHTML = diffResult;
177
+ document.getElementById('resultSection').classList.remove('hidden');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  } catch (error) {
179
+ alert("خطأ أثناء التحليل: " + error.message);
180
+ } finally {
181
+ hideLoading();
182
  }
183
  });
 
 
 
 
 
 
184
  })();
185
  </script>
186
  </body>