Предмет

This commit is contained in:
2026-07-03 12:02:46 +05:00
parent 8b5c03219f
commit 548b1dd59c
3 changed files with 92 additions and 0 deletions

View File

@@ -39,9 +39,36 @@ h2 { margin: 15px 0 8px; font-size: 16px; }
max-width: 300px;
}
.input-sm { max-width: 120px; }
.input-xs { max-width: 80px; }
#subject-select { max-width: 220px; }
.search-bar { margin-bottom: 15px; }
.filter-extras {
margin-bottom: 12px;
padding: 8px 12px;
background: #fafafa;
border: 1px solid #e0e0e0;
border-radius: 4px;
}
.filter-extras .form-row {
margin-bottom: 0;
display: flex;
align-items: center;
gap: 6px;
flex-wrap: wrap;
}
.filter-extras .form-row label {
min-width: auto;
font-weight: 500;
font-size: 13px;
margin-right: 2px;
}
.filter-extras .form-row label:not(:first-child) {
margin-left: 10px;
}
.filter-bar {
display: flex;
gap: 12px;

View File

@@ -98,9 +98,19 @@ router.post('/import', upload.single('xlsfile'), (req, res) => {
}
});
router.get('/subjects', (req, res) => {
const rows = dbAll('SELECT code, name FROM subjects ORDER BY is_mandatory DESC, name');
res.json(rows);
});
router.get('/students', (req, res) => {
const search = req.query.search || '';
const filter = req.query.filter || '';
const subjectCode = req.query.subject_code || '';
const scoreMin = req.query.score_min;
const scoreMax = req.query.score_max;
const gradeMin = req.query.grade_min;
const gradeMax = req.query.grade_max;
const baseQuery = `
SELECT s.*,
@@ -125,6 +135,27 @@ router.get('/students', (req, res) => {
params.push(like, like, like, like);
}
if (subjectCode) {
whereClauses.push('er.subject_code = ?');
params.push(subjectCode);
}
if (scoreMin !== undefined && scoreMin !== '') {
whereClauses.push('er.primary_score >= ?');
params.push(parseInt(scoreMin, 10));
}
if (scoreMax !== undefined && scoreMax !== '') {
whereClauses.push('er.primary_score <= ?');
params.push(parseInt(scoreMax, 10));
}
if (gradeMin !== undefined && gradeMin !== '') {
whereClauses.push('er.grade >= ?');
params.push(parseInt(gradeMin, 10));
}
if (gradeMax !== undefined && gradeMax !== '') {
whereClauses.push('er.grade <= ?');
params.push(parseInt(gradeMax, 10));
}
let havingClause = '';
if (filter === 'gia' || filter === 'oge') {
havingClause = 'HAVING elective_count > 0';

View File

@@ -72,6 +72,21 @@
</label>
</div>
<div class="filter-extras">
<div class="form-row">
<label>Предмет:</label>
<select id="subject-select" class="input" onchange="loadStudents()">
<option value="">Все предметы</option>
</select>
<label>Балл:</label>
<input type="number" id="score-min" class="input input-xs" placeholder="от" oninput="loadStudents()">
<input type="number" id="score-max" class="input input-xs" placeholder="до" oninput="loadStudents()">
<label>Оценка:</label>
<input type="number" id="grade-min" class="input input-xs" placeholder="от" min="2" max="5" oninput="loadStudents()">
<input type="number" id="grade-max" class="input input-xs" placeholder="до" min="2" max="5" oninput="loadStudents()">
</div>
</div>
<div class="search-bar">
<input type="text" id="search" class="input" placeholder="Поиск по ФИО или классу...">
</div>
@@ -125,9 +140,19 @@
async function loadStudents() {
const search = document.getElementById('search').value;
const filter = document.querySelector('input[name="filter"]:checked').value;
const subjectCode = document.getElementById('subject-select').value;
const scoreMin = document.getElementById('score-min').value;
const scoreMax = document.getElementById('score-max').value;
const gradeMin = document.getElementById('grade-min').value;
const gradeMax = document.getElementById('grade-max').value;
const params = new URLSearchParams();
if (search) params.set('search', search);
if (filter && filter !== 'all') params.set('filter', filter);
if (subjectCode) params.set('subject_code', subjectCode);
if (scoreMin) params.set('score_min', scoreMin);
if (scoreMax) params.set('score_max', scoreMax);
if (gradeMin) params.set('grade_min', gradeMin);
if (gradeMax) params.set('grade_max', gradeMax);
const url = '/api/students' + (params.toString() ? '?' + params.toString() : '');
const res = await fetch(url);
allStudents = await res.json();
@@ -145,6 +170,14 @@
parSel.innerHTML = parallels.map(p => `<option value="${esc(p)}">${esc(p)}-е классы</option>`).join('');
}
async function loadSubjects() {
const res = await fetch('/api/subjects');
const subjects = await res.json();
const sel = document.getElementById('subject-select');
sel.innerHTML = '<option value="">Все предметы</option>' +
subjects.map(s => `<option value="${esc(s.code)}">${esc(s.name)}</option>`).join('');
}
function toggleBatchMode() {
const scope = document.querySelector('input[name="batch-scope"]:checked').value;
document.getElementById('class-select').disabled = scope !== 'class';
@@ -236,6 +269,7 @@
loadStudents();
loadClasses();
loadSubjects();
</script>
</body>
</html>