This commit is contained in:
2026-06-30 11:51:34 +07:00
parent fd08bee7ab
commit 0abf48ea2d
28 changed files with 3514 additions and 37 deletions

View File

@@ -390,6 +390,31 @@ body {
.status-banner.mode-exam { border-left-color: #7c3aed; }
.status-banner.mode-exam .monitor-mode-tag { background: #f5f3ff; color: #6d28d9; }
.exam-panel {
border: 1px solid #c4b5fd;
background: linear-gradient(135deg, #faf5ff 0%, #fff 100%);
padding: 1rem 1.15rem;
margin-bottom: 0.75rem;
}
.exam-panel-desc {
margin: 0 0 0.85rem;
font-size: 0.85rem;
color: var(--text-secondary);
}
.exam-panel-actions {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
align-items: center;
}
.exam-wait, .exam-done {
font-size: 0.82rem;
color: var(--text-muted);
}
.stats-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);

View File

@@ -20,7 +20,8 @@ let stats = {
classCode: '',
currentPeriod: 0,
currentCourseName: '',
shifts: []
shifts: [],
exam: null
};
let chatOpen = false;
@@ -65,6 +66,14 @@ function init() {
if (data?.staffId) bannerStaffId = Number(data.staffId);
pulseChatFab();
});
window.runtime.EventsOn('exam:paper-sent', () => {
if (loggedIn) {
window.go.main.App.GetStats().then((s) => {
stats = { ...stats, ...s };
updateExamPanel();
}).catch(console.error);
}
});
checkLogin();
}
@@ -169,6 +178,63 @@ function renderShiftsTable(shifts) {
`;
}
function renderExamPanel() {
const ex = stats.exam;
if (!ex || stats.monitorMode !== 'exam') return '';
const paperBtn = ex.paperSent
? `<button type="button" class="btn btn-primary" id="btn-exam-paper">📄 Xem đề${ex.paperTitle ? ` (${ex.paperTitle})` : ''}</button>`
: `<span class="exam-wait">Chờ giảng viên gửi đề...</span>`;
const quizBtn = ex.quizUrl
? `<button type="button" class="btn btn-secondary" id="btn-exam-quiz">📝 Làm trắc nghiệm</button>`
: '';
const submitBtn = ex.submitted
? `<span class="exam-done">✓ Đã nộp bài tự luận</span>`
: `<button type="button" class="btn btn-primary" id="btn-exam-submit">📦 Nộp bài (chọn folder)</button>`;
return `
<div class="card exam-panel" id="exam-panel">
<div class="card-title-row">
<div class="card-title">📝 ${ex.examName || 'Phòng thi'}</div>
</div>
<p class="exam-panel-desc">Bạn đang trong giờ thi. Làm bài theo hướng dẫn của giảng viên.</p>
<div class="exam-panel-actions">
${paperBtn}
${quizBtn}
${submitBtn}
</div>
</div>
`;
}
function wireExamPanel() {
const paper = document.getElementById('btn-exam-paper');
if (paper) paper.addEventListener('click', () => {
window.go.main.App.OpenExamPaper().catch((e) => alert(e?.message || e));
});
const quiz = document.getElementById('btn-exam-quiz');
if (quiz) quiz.addEventListener('click', () => {
window.go.main.App.OpenExamQuiz().catch((e) => alert(e?.message || e));
});
const submit = document.getElementById('btn-exam-submit');
if (submit) submit.addEventListener('click', async () => {
try {
const name = await window.go.main.App.SubmitExamWork();
alert(`Đã nộp bài: ${name}`);
const fresh = await window.go.main.App.GetStats();
stats = { ...stats, ...fresh };
updateExamPanel();
} catch (e) {
alert(e?.message || e || 'Nộp bài thất bại');
}
});
}
function updateExamPanel() {
const host = document.getElementById('exam-panel-host');
if (!host) return;
host.innerHTML = renderExamPanel();
wireExamPanel();
}
function renderDashboard() {
if (!studentInfo) return;
@@ -227,6 +293,8 @@ function renderDashboard() {
</div>
</div>
<div id="exam-panel-host">${renderExamPanel()}</div>
<div class="stats-grid stats-grid--two">
<div class="card stat-card">
<div class="stat-icon-wrap">📡</div>
@@ -275,6 +343,7 @@ function renderDashboard() {
await window.go.main.App.Logout();
}
});
wireExamPanel();
}
function ensureChatWidget() {
@@ -497,11 +566,17 @@ function startStatsTicker() {
const statusSubEl = document.getElementById('status-sub');
if (statusSubEl) {
statusSubEl.innerText = stats.currentPeriod > 0 && stats.currentCourseName
? `Ca ${stats.currentPeriod} · ${stats.currentCourseName}`
: 'Theo dõi theo lịch học của lớp';
if (stats.monitorMode === 'exam' && stats.exam?.examName) {
statusSubEl.innerText = stats.exam.examName;
} else {
statusSubEl.innerText = stats.currentPeriod > 0 && stats.currentCourseName
? `Ca ${stats.currentPeriod} · ${stats.currentCourseName}`
: 'Theo dõi theo lịch học của lớp';
}
}
updateExamPanel();
const onlineEl = document.getElementById('clock-online');
if (onlineEl) onlineEl.innerText = formatDuration(stats.onlineSecs || 0);