v3
This commit is contained in:
@@ -6,7 +6,7 @@ body {
|
|||||||
color: #333;
|
color: #333;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
.container { max-width: 960px; margin: 0 auto; padding: 20px; }
|
.container { max-width: 100%; margin: 0 auto; padding: 20px; }
|
||||||
h1 { margin-bottom: 15px; }
|
h1 { margin-bottom: 15px; }
|
||||||
h2 { margin: 15px 0 8px; font-size: 16px; }
|
h2 { margin: 15px 0 8px; font-size: 16px; }
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,9 @@ router.get('/students', (req, res) => {
|
|||||||
SELECT s.*,
|
SELECT s.*,
|
||||||
COUNT(er.id) as exam_count,
|
COUNT(er.id) as exam_count,
|
||||||
SUM(CASE WHEN s2.is_mandatory = 0 THEN 1 ELSE 0 END) as elective_count,
|
SUM(CASE WHEN s2.is_mandatory = 0 THEN 1 ELSE 0 END) as elective_count,
|
||||||
SUM(CASE WHEN s2.is_mandatory = 1 AND er.grade IS NOT NULL THEN 1 ELSE 0 END) as mandatory_grades
|
SUM(CASE WHEN s2.is_mandatory = 1 AND er.grade IS NOT NULL THEN 1 ELSE 0 END) as mandatory_grades,
|
||||||
|
SUM(CASE WHEN s2.is_mandatory = 1 AND er.grade IS NOT NULL AND er.grade < 3 THEN 1 ELSE 0 END) as low_grades,
|
||||||
|
GROUP_CONCAT(s2.name || ' ' || CAST(er.grade AS TEXT), ' / ') as subjects_list
|
||||||
FROM students s
|
FROM students s
|
||||||
LEFT JOIN exam_results er ON er.student_id = s.id
|
LEFT JOIN exam_results er ON er.student_id = s.id
|
||||||
LEFT JOIN subjects s2 ON s2.code = er.subject_code
|
LEFT JOIN subjects s2 ON s2.code = er.subject_code
|
||||||
@@ -129,6 +131,8 @@ router.get('/students', (req, res) => {
|
|||||||
)`);
|
)`);
|
||||||
} else if (filter === 'secondyear') {
|
} else if (filter === 'secondyear') {
|
||||||
havingClause = 'HAVING elective_count = 0 AND COUNT(er.id) = 1';
|
havingClause = 'HAVING elective_count = 0 AND COUNT(er.id) = 1';
|
||||||
|
} else if (filter === 'lowgrade') {
|
||||||
|
havingClause = 'HAVING low_grades > 0';
|
||||||
}
|
}
|
||||||
|
|
||||||
const wherePart = whereClauses.length ? 'WHERE ' + whereClauses.join(' AND ') : '';
|
const wherePart = whereClauses.length ? 'WHERE ' + whereClauses.join(' AND ') : '';
|
||||||
|
|||||||
@@ -63,6 +63,9 @@
|
|||||||
<label class="filter-label" style="background:#fff0d0;color:#860">
|
<label class="filter-label" style="background:#fff0d0;color:#860">
|
||||||
<input type="radio" name="filter" value="secondyear" onchange="onFilterChange()"> Второгодники
|
<input type="radio" name="filter" value="secondyear" onchange="onFilterChange()"> Второгодники
|
||||||
</label>
|
</label>
|
||||||
|
<label class="filter-label" style="background:#fdd;color:#a00">
|
||||||
|
<input type="radio" name="filter" value="lowgrade" onchange="onFilterChange()"> Отметка < 3
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="search-bar">
|
<div class="search-bar">
|
||||||
@@ -79,6 +82,7 @@
|
|||||||
<th>Класс</th>
|
<th>Класс</th>
|
||||||
<th>Предметов</th>
|
<th>Предметов</th>
|
||||||
<th>Тип</th>
|
<th>Тип</th>
|
||||||
|
<th>Предметы (оценка)</th>
|
||||||
<th>Действия</th>
|
<th>Действия</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -154,6 +158,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatSubjectsList(list) {
|
||||||
|
if (!list) return '—';
|
||||||
|
return list.split(' / ').map(item => {
|
||||||
|
const m = item.match(/^(.*?)\s*(\d)\s*$/);
|
||||||
|
if (m && parseInt(m[2]) < 3) return `<span style="color:#c0392b;font-weight:600">${esc(item)}</span>`;
|
||||||
|
return esc(item);
|
||||||
|
}).join(' / ');
|
||||||
|
}
|
||||||
|
|
||||||
function renderTable(students) {
|
function renderTable(students) {
|
||||||
const tbody = document.querySelector('#students-table tbody');
|
const tbody = document.querySelector('#students-table tbody');
|
||||||
tbody.innerHTML = students.map((s, i) => {
|
tbody.innerHTML = students.map((s, i) => {
|
||||||
@@ -164,7 +177,7 @@
|
|||||||
const examType = isOge ? 'ОГЭ' : 'ГВЭ';
|
const examType = isOge ? 'ОГЭ' : 'ГВЭ';
|
||||||
const examTypeClass = isOge ? 'badge-gia' : 'badge-gve';
|
const examTypeClass = isOge ? 'badge-gia' : 'badge-gve';
|
||||||
return `
|
return `
|
||||||
<tr class="${rowClass}">
|
<tr class="${rowClass}" onclick="window.location.href='/student/${s.id}'" style="cursor:pointer">
|
||||||
<td>${i + 1}</td>
|
<td>${i + 1}</td>
|
||||||
<td>${esc(s.last_name)}</td>
|
<td>${esc(s.last_name)}</td>
|
||||||
<td>${esc(s.first_name)}</td>
|
<td>${esc(s.first_name)}</td>
|
||||||
@@ -172,7 +185,8 @@
|
|||||||
<td>${esc(s.class)}</td>
|
<td>${esc(s.class)}</td>
|
||||||
<td>${s.exam_count}</td>
|
<td>${s.exam_count}</td>
|
||||||
<td><span class="badge ${examTypeClass}">${examType}</span></td>
|
<td><span class="badge ${examTypeClass}">${examType}</span></td>
|
||||||
<td><a href="/student/${s.id}" class="btn btn-sm">Открыть</a></td>
|
<td style="font-size:11px;max-width:250px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap" title="${esc(s.subjects_list || '')}">${formatSubjectsList(s.subjects_list)}</td>
|
||||||
|
<td onclick="event.stopPropagation()"><a href="/student/${s.id}" class="btn btn-sm">Открыть</a></td>
|
||||||
</tr>`;
|
</tr>`;
|
||||||
}).join('');
|
}).join('');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user