Update Saqel Platform: 2026-08-28 15:41:53

This commit is contained in:
Hamza-Ayed
2026-08-28 15:41:53 +03:00
parent 974de0a641
commit 86bdee399d
3 changed files with 350 additions and 195 deletions
+38 -23
View File
@@ -10,6 +10,7 @@ class CurriculumStudio
{
$tree = CurriculumService::getCurriculumTree();
$treeJson = json_encode($tree, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP);
$serverStorageDir = realpath(__DIR__ . '/../../storage/curriculum') ?: (dirname(__DIR__, 2) . '/storage/curriculum');
ob_start();
?>
@@ -25,6 +26,7 @@ class CurriculumStudio
<link href="https://fonts.googleapis.com/css2?family=Alexandria:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet">
<script>
window.CURRICULUM_TREE = <?= $treeJson ?>;
window.SERVER_STORAGE_DIR = "<?= addslashes($serverStorageDir) ?>";
</script>
<style>
:root {
@@ -51,7 +53,7 @@ class CurriculumStudio
.container { max-width: 1400px; margin: 24px auto; padding: 0 20px; }
.main-layout { display: grid; grid-template-columns: 360px 1fr; gap: 24px; }
.main-layout { display: grid; grid-template-columns: 380px 1fr; gap: 24px; }
@media (max-width: 900px) { .main-layout { grid-template-columns: 1fr; } }
.tree-sidebar {
@@ -72,7 +74,7 @@ class CurriculumStudio
font-size: 12px; font-weight: 600; color: var(--text-secondary); margin: 4px 20px; padding: 3px 6px;
}
.tree-lesson {
font-size: 11.5px; color: var(--text-muted); margin: 3px 30px; padding: 5px 10px; border-radius: 8px;
font-size: 11.5px; color: var(--text-muted); margin: 3px 30px; padding: 6px 10px; border-radius: 8px;
cursor: pointer; transition: all 0.2s;
}
.tree-lesson:hover, .tree-lesson.active {
@@ -98,13 +100,15 @@ class CurriculumStudio
.search-box:focus { border-color: var(--accent-cyan); }
.md-editor {
width: 100%; height: 420px; background: rgba(0,0,0,0.5); border: 1px solid var(--border);
width: 100%; height: 480px; background: rgba(0,0,0,0.5); border: 1px solid var(--border);
border-radius: 14px; padding: 16px; color: #F1F5F9; font-family: monospace; font-size: 13px;
line-height: 1.6; resize: vertical; outline: none;
line-height: 1.7; resize: vertical; outline: none;
}
.empty-tree-state {
padding: 40px 20px; text-align: center; color: var(--text-muted); font-size: 13px; line-height: 1.6;
.server-path-box {
background: rgba(0,0,0,0.4); border: 1px solid var(--border); border-radius: 8px; padding: 6px 12px;
font-size: 11.5px; font-family: monospace; color: var(--accent-cyan); margin-bottom: 14px;
display: flex; align-items: center; justify-content: space-between;
}
</style>
</head>
@@ -115,7 +119,7 @@ class CurriculumStudio
<div style="display: flex; align-items: center; gap: 10px;">
<img src="/assets/images/saqel_logo.jpg" alt="صَقِل" style="width: 36px; height: 36px; border-radius: 10px;">
<span style="font-weight: 800; font-size: 18px; color: #FFF;">صَقِل Enterprise</span>
<span style="font-size: 11px; font-weight: 700; color: var(--accent-gold); background: rgba(255,209,102,0.12); padding: 2px 10px; border-radius: 980px;">استوديو إدارة وفهرسة المناهج الحية 📚</span>
<span style="font-size: 11px; font-weight: 700; color: var(--accent-gold); background: rgba(255,209,102,0.12); padding: 2px 10px; border-radius: 980px;">استوديو تفريغ وفهرسة المناهج الحية 📚</span>
</div>
<div style="display: flex; gap: 10px;">
<a href="/teacher" style="font-size: 12px; color: var(--accent-cyan); text-decoration: none; border: 1px solid rgba(0,245,212,0.3); padding: 5px 14px; border-radius: 980px;">استوديو المعلم 👨‍🏫</a>
@@ -129,13 +133,13 @@ class CurriculumStudio
<div class="workspace-card" style="margin-bottom: 24px; background: linear-gradient(135deg, rgba(30, 41, 59, 0.7), rgba(15, 23, 42, 0.9));">
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 16px;">
<div>
<h2 style="font-size: 20px; font-weight: 900; color: #FFF; margin-bottom: 4px;">رفع وتحليل كتاب المنهاج الوزاري PDF (معالجة حية 100%) 📑</h2>
<p style="font-size: 12.5px; color: var(--text-secondary);" id="upload_status_desc">اختر ملف كتاب المنهاج (PDF) ليقوم الخادم والذكاء الاصطناعي بفك تشفيره واستخراج الفصول والوحدات والدروس الحقيقية فوراً.</p>
<h2 style="font-size: 20px; font-weight: 900; color: #FFF; margin-bottom: 4px;">رفع وتفريغ كتب المناهج الوزارية (PDF ⟵ Markdown Tree) 📑</h2>
<p style="font-size: 12.5px; color: var(--text-secondary);" id="upload_status_desc">اختر ملف كتاب المنهاج (PDF) ليقوم الخادم بتفريغه وفهرسة وحداته ودروسه الحقيقية على القرص وتوليد ملفات المارك داون.</p>
</div>
<div style="display: flex; gap: 10px; align-items: center;">
<input type="file" id="curriculum_pdf_input" accept=".pdf" style="display: none;" onchange="handleRealPdfUpload(this)">
<button type="button" id="btn_upload_pdf" onclick="document.getElementById('curriculum_pdf_input').click()" class="btn-primary">
<span>📤 رفع ملف المنهاج PDF الحقيقي</span>
<span>📤 رفع كتاب المنهاج PDF الحقيقي</span>
</button>
</div>
</div>
@@ -155,23 +159,29 @@ class CurriculumStudio
<div class="workspace-card" id="workspace_content_area">
<div id="empty_selection_view" style="display: none; text-align: center; padding: 60px 20px;">
<div style="font-size: 48px; margin-bottom: 12px;">📚</div>
<h3 style="font-size: 18px; font-weight: 800; color: #FFF; margin-bottom: 8px;">لا يوجد درس محدد حالياً</h3>
<p style="font-size: 13px; color: var(--text-muted); max-width: 480px; margin: 0 auto;">ارفع كتاب المنهاج PDF أو اختر درساً من الشجرة الجانبية لمعاينة نتاجات التعلم والمارك داون المعتمد.</p>
<h3 style="font-size: 18px; font-weight: 800; color: #FFF; margin-bottom: 8px;">لا توجد مناهج مضافة حالياً</h3>
<p style="font-size: 13px; color: var(--text-muted); max-width: 480px; margin: 0 auto;">ارفع كتاب المنهاج PDF لبناء الشجرة وتفريغ الدروس بالمارك داون على السيرفر.</p>
</div>
<div id="active_lesson_view" style="display: none;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; flex-wrap: wrap; gap: 10px;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; flex-wrap: wrap; gap: 10px;">
<div>
<span style="font-size: 11px; font-weight: 800; color: var(--accent-cyan); background: rgba(0,245,212,0.1); padding: 2px 8px; border-radius: 6px;" id="current_breadcrumb"></span>
<h3 style="font-size: 18px; font-weight: 900; color: #FFF; margin-top: 6px;" id="current_lesson_title_display"></h3>
</div>
<button type="button" onclick="saveActiveMarkdown()" class="btn-primary" style="background: linear-gradient(135deg, #10B981, #059669);">
💾 حفظ واعتماد الدرس في الشجرة
💾 حفظ التعديلات على السيرفر
</button>
</div>
<!-- Exact Server Storage Path Readout -->
<div class="server-path-box">
<span>📁 مسار الملف على السيرفر: <strong id="server_file_path_display" style="color: #FFF;"></strong></span>
<span style="color: var(--accent-gold); font-size: 11px;">(ملف Markdown حي على القرص)</span>
</div>
<div style="margin-bottom: 14px;">
<span style="font-size: 12px; font-weight: 700; color: var(--text-muted); display: block; margin-bottom: 6px;">نتاجات التعلم والمفاهيم المستهدفة المستخرجة من الكتاب:</span>
<span style="font-size: 12px; font-weight: 700; color: var(--text-muted); display: block; margin-bottom: 6px;">نتاجات التعلم والمفاهيم المستهدفة:</span>
<div id="current_outcomes_tags" style="display: flex; gap: 8px; flex-wrap: wrap;"></div>
</div>
@@ -195,7 +205,7 @@ class CurriculumStudio
if (entries.length === 0) {
container.innerHTML = `
<div class="empty-tree-state">
<div style="padding: 40px 20px; text-align: center; color: var(--text-muted); font-size: 13px;">
<div style="font-size: 32px; margin-bottom: 8px;">📂</div>
<strong>لا توجد مناهج مفهرسة بعد</strong>
<p style="margin-top: 4px;">ارفع كتاب المنهاج الوزاري (PDF) عبر الزر بالأعلى ليتم بناء الشجرة وفهرستها تلقائياً.</p>
@@ -257,6 +267,7 @@ class CurriculumStudio
document.getElementById('current_breadcrumb').textContent = breadcrumb;
document.getElementById('current_lesson_title_display').textContent = title;
document.getElementById('server_file_path_display').textContent = `backend/storage/curriculum/${filePath}`;
// Render Outcomes
const tags = document.getElementById('current_outcomes_tags');
@@ -276,6 +287,9 @@ class CurriculumStudio
const data = await res.json();
if (res.ok && data.status === 'success') {
document.getElementById('lesson_markdown_editor').value = data.content || '';
if (data.server_full_path) {
document.getElementById('server_file_path_display').textContent = data.server_full_path;
}
}
} catch (e) {
console.error('Fetch markdown error:', e);
@@ -289,8 +303,8 @@ class CurriculumStudio
const btn = document.getElementById('btn_upload_pdf');
const desc = document.getElementById('upload_status_desc');
btn.disabled = true;
btn.innerHTML = '<span>⏳ جارٍ فك تشفير الكتاب بالذكاء الاصطناعي...</span>';
desc.textContent = `جارٍ معالجة وتفصيص ملف [${file.name}] وبناء شجرة المناهج الحقيقية...`;
btn.innerHTML = '<span>⏳ جارٍ فك تشفير وتفريغ الكتاب...</span>';
desc.textContent = `جارٍ تفريغ ملف [${file.name}] إلى شجرة ملفات Markdown حقيقية على السيرفر...`;
const formData = new FormData();
formData.append('pdf_file', file);
@@ -310,11 +324,12 @@ class CurriculumStudio
document.getElementById('empty_selection_view').style.display = 'none';
document.getElementById('active_lesson_view').style.display = 'block';
document.getElementById('lesson_markdown_editor').value = data.active_md || '';
document.getElementById('current_lesson_title_display').textContent = data.extracted_data?.units?.[0]?.lessons?.[0]?.title || 'الدرس المستخرج';
document.getElementById('current_breadcrumb').textContent = `${data.extracted_data?.grade_name} ⟵ ${data.extracted_data?.subject_name}`;
document.getElementById('current_lesson_title_display').textContent = data.active_title || 'الدرس المستخرج';
document.getElementById('current_breadcrumb').textContent = data.active_breadcrumb || 'المسار التعليمي';
document.getElementById('server_file_path_display').textContent = `${data.server_storage_dir}/${data.active_file}`;
}
alert(`✅ ${data.message}`);
alert(`✅ ${data.message}\n\nتم حفظ ملفات المنهاج على السيرفر في:\n${data.server_storage_dir}`);
desc.textContent = `تم اعتماد المنهاج [${file.name}] بنجاح في قاعدة المعرفة الشجرية!`;
} else {
alert('⚠️ ' + (data.message || 'فشلت معالجة الملف'));
@@ -324,7 +339,7 @@ class CurriculumStudio
alert('حدث خطأ في الاتصال بالخادم أثناء رفع الملف.');
} finally {
btn.disabled = false;
btn.innerHTML = '<span>📤 رفع ملف المنهاج PDF الحقيقي</span>';
btn.innerHTML = '<span>📤 رفع كتاب المنهاج PDF الحقيقي</span>';
input.value = '';
}
}
@@ -341,7 +356,7 @@ class CurriculumStudio
});
const data = await res.json();
if (res.ok && data.status === 'success') {
alert('✅ تم حفظ واعتماد التعديلات بنجاح في المنهاج الرسمي!');
alert(`✅ تم حفظ واعتماد التعديلات بنجاح في الملف:\n${data.server_full_path || currentFilePath}`);
} else {
alert('⚠️ فشل حفظ الملف');
}