bcf2c71fad
将前端文件从html目录迁移到views目录,按功能模块组织 重构认证中间件和路由处理,简化页面权限控制 更新静态资源引用路径,统一使用/public前缀 添加学生仪表板页面,优化移动端显示 移除旧版html和js文件,更新样式和脚本
448 lines
18 KiB
HTML
448 lines
18 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>�鞟貍敶訫� - XX摮行嵗�鞟貍蝞∠�蝟餌�</title>
|
||
<link rel="stylesheet" href="/public/css/style.css">
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||
|
||
</head>
|
||
<body>
|
||
<!-- 撖潸⏛�?-->
|
||
<nav class="navbar">
|
||
<div class="navbar-brand">
|
||
<a href="/"><i class="fas fa-graduation-cap"></i> XX摮行嵗�鞟貍蝞∠�蝟餌�</a>
|
||
</div>
|
||
<div class="navbar-menu">
|
||
<a href="/teacher/dashboard" class="navbar-item"><i class="fas fa-tachometer-alt"></i> �坔�隞芾”�?/a>
|
||
<a href="/teacher/grade_entry" class="navbar-item active"><i class="fas fa-edit"></i> �鞟貍敶訫�</a>
|
||
<a href="/teacher/grade_management" class="navbar-item"><i class="fas fa-list"></i> �鞟貍蝞∠�</a>
|
||
<div class="user-info">
|
||
<span class="user-name">�舘���</span>
|
||
<span class="user-role">�坔�</span>
|
||
<a href="/login" class="btn btn-outline btn-small"><i class="fas fa-sign-out-alt"></i> ���?/a>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
|
||
<!-- �W�撅穃紡�?-->
|
||
<div class="container">
|
||
<div class="breadcrumb">
|
||
<a href="/">銝駁△</a>
|
||
<i class="fas fa-chevron-right"></i>
|
||
<a href="/teacher/dashboard">�坔�隞芾”�?/a>
|
||
<i class="fas fa-chevron-right"></i>
|
||
<span>�鞟貍敶訫�</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 銝餃�摰孵躹 -->
|
||
<div class="grade-entry-container">
|
||
<div class="entry-header">
|
||
<h1><i class="fas fa-edit"></i> �鞟貍敶訫�</h1>
|
||
<p>霂琿�㗇𥋘�剔漣�諹紋蝔页��嗅�銝箸�銝芸郎�笔��交�蝏?/p>
|
||
</div>
|
||
|
||
<div class="entry-form">
|
||
<div class="form-row">
|
||
<div class="form-group">
|
||
<label for="class-select"><i class="fas fa-users"></i> �㗇𥋘�剔漣</label>
|
||
<select id="class-select" class="form-control">
|
||
<option value="">霂琿�㗇𥋘�剔漣</option>
|
||
<option value="class1">霈∠��箇�摮虫����?021蝥?�?/option>
|
||
<option value="class2">霈∠��箇�摮虫����?021蝥?�?/option>
|
||
<option value="class3">頧臭辣撌亦�2021蝥?�?/option>
|
||
<option value="class4">頧臭辣撌亦�2021蝥?�?/option>
|
||
<option value="class5">蝵𤑳�撌亦�2021蝥?�?/option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="course-name"><i class="fas fa-book"></i> 霂曄��滨妍</label>
|
||
<input type="text" id="course-name" placeholder="霂瑁��亥紋蝔见�蝘堆�憒���唳旿蝏𤘪����雿𦦵頂蝏毺�">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="exam-date"><i class="fas fa-calendar-alt"></i> ����交�</label>
|
||
<input type="date" id="exam-date">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label><i class="fas fa-info-circle"></i> 憭�釣霂湔�嚗�虾�㚁�</label>
|
||
<textarea id="remarks" rows="3" placeholder="�航��交𧋦甈∟�����秩�𦒘縑�荔�憒���煺葉�������怨���蝑?></textarea>
|
||
</div>
|
||
|
||
<div class="students-table-container">
|
||
<h3><i class="fas fa-user-graduate"></i> 摮衣��鞟貍敶訫�</h3>
|
||
<p class="text-muted">�㗇𥋘�剔漣�𠬍�蝟餌�撠�䌊�典�頧質砲�剔漣��郎�笔�銵?/p>
|
||
|
||
<div id="students-loading" class="loading" style="display: none;">
|
||
<i class="fas fa-spinner"></i>
|
||
<p>甇�銁�㰘蝸摮衣��𡑒”...</p>
|
||
</div>
|
||
|
||
<div id="no-students" class="no-students" style="display: none;">
|
||
<i class="fas fa-user-slash"></i>
|
||
<p>霂亦号蝥扳��惩郎��㺭�殷�霂瑕�瘛餃�摮衣�靽⊥�</p>
|
||
</div>
|
||
|
||
<table id="students-table" class="students-table" style="display: none;">
|
||
<thead>
|
||
<tr>
|
||
<th>摮血噡</th>
|
||
<th>憪枏�</th>
|
||
<th>撟單𧒄�鞟貍</th>
|
||
<th>�煺葉�鞟貍</th>
|
||
<th>��錰�鞟貍</th>
|
||
<th>�餉��鞟貍</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="students-tbody">
|
||
<!-- 摮衣��唳旿撠��朞�JavaScript�冽���頧?-->
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="form-actions">
|
||
<button id="cancel-btn" class="btn btn-secondary btn-large">
|
||
<i class="fas fa-times"></i> �𡝗�
|
||
</button>
|
||
<button id="submit-btn" class="btn btn-primary btn-large" disabled>
|
||
<i class="fas fa-check"></i> �𣂷漱�鞟貍
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h3><i class="fas fa-lightbulb"></i> 雿輻鍂霂湔�</h3>
|
||
<ul class="text-muted">
|
||
<li>擐硋��㗇𥋘閬���交�蝏拍��剔漣�諹紋蝔?/li>
|
||
<li>蝟餌�隡朞䌊�典�頧質砲�剔漣��郎�笔�銵?/li>
|
||
<li>銝箸�銝芸郎�蠘��亙像�嗆�蝏押���銝剜�蝏拙���錰�鞟貍</li>
|
||
<li>�餉��鞟貍撠�覔�格��滩䌊�刻恣蝞梹�暺䁅恕���嚗𡁜像�?0%嚗峕�銝?0%嚗峕��?0%嚗?/li>
|
||
<li>蝖株恕�㰘秤�𡒊��領�𨀣�鈭斗�蝏抽�脲��桐�摮䀹㺭�?/li>
|
||
<li>�𣂷漱�𤾸虾隞亙銁�𨀣�蝏拍恣���嗪△�X䰻�见�靽格㺿撌脣��亦��鞟貍</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- JavaScript -->
|
||
<script>
|
||
// 璅⊥�摮衣��唳旿
|
||
const mockStudents = [
|
||
{ id: '2021001', name: '撘牐�', usual: '', midterm: '', final: '', total: '' },
|
||
{ id: '2021002', name: '�𤾸�', usual: '', midterm: '', final: '', total: '' },
|
||
{ id: '2021003', name: '�衤�', usual: '', midterm: '', final: '', total: '' },
|
||
{ id: '2021004', name: '韏萄�', usual: '', midterm: '', final: '', total: '' },
|
||
{ id: '2021005', name: '�曹�', usual: '', midterm: '', final: '', total: '' },
|
||
{ id: '2021006', name: '摮坔�', usual: '', midterm: '', final: '', total: '' },
|
||
{ id: '2021007', name: '�其�', usual: '', midterm: '', final: '', total: '' },
|
||
{ id: '2021008', name: '�游�', usual: '', midterm: '', final: '', total: '' }
|
||
];
|
||
|
||
// DOM���
|
||
const classSelect = document.getElementById('class-select');
|
||
const courseNameInput = document.getElementById('course-name');
|
||
const examDateInput = document.getElementById('exam-date');
|
||
const remarksInput = document.getElementById('remarks');
|
||
const studentsLoading = document.getElementById('students-loading');
|
||
const noStudents = document.getElementById('no-students');
|
||
const studentsTable = document.getElementById('students-table');
|
||
const studentsTbody = document.getElementById('students-tbody');
|
||
const cancelBtn = document.getElementById('cancel-btn');
|
||
const submitBtn = document.getElementById('submit-btn');
|
||
|
||
// 霈曄蔭暺䁅恕����交�銝箔�憭? const today = new Date().toISOString().split('T')[0];
|
||
examDateInput.value = today;
|
||
|
||
// �剔漣�㗇𥋘�睃�鈭衤辣
|
||
classSelect.addEventListener('change', function() {
|
||
const selectedClass = this.value;
|
||
|
||
if (!selectedClass) {
|
||
hideStudentsTable();
|
||
submitBtn.disabled = true;
|
||
return;
|
||
}
|
||
|
||
// �曄內�㰘蝸�嗆�? showLoading();
|
||
|
||
// 璅⊥�API靚�鍂撱嗉�
|
||
setTimeout(() => {
|
||
loadStudentsForClass(selectedClass);
|
||
}, 1000);
|
||
});
|
||
|
||
// �㰘蝸摮衣��唳旿
|
||
function loadStudentsForClass(className) {
|
||
// 璅⊥�API�滚�
|
||
if (mockStudents.length > 0) {
|
||
renderStudentsTable(mockStudents);
|
||
} else {
|
||
showNoStudents();
|
||
}
|
||
}
|
||
|
||
// 皜脫�摮衣�銵冽聢
|
||
function renderStudentsTable(students) {
|
||
hideLoading();
|
||
|
||
// 皜�征銵冽聢
|
||
studentsTbody.innerHTML = '';
|
||
|
||
// 瘛餃�摮衣�銵? students.forEach((student, index) => {
|
||
const row = document.createElement('tr');
|
||
row.innerHTML = `
|
||
<td>${student.id}</td>
|
||
<td>${student.name}</td>
|
||
<td>
|
||
<input type="number" class="grade-input usual-grade"
|
||
data-index="${index}" min="0" max="100"
|
||
placeholder="0-100" value="${student.usual}">
|
||
</td>
|
||
<td>
|
||
<input type="number" class="grade-input midterm-grade"
|
||
data-index="${index}" min="0" max="100"
|
||
placeholder="0-100" value="${student.midterm}">
|
||
</td>
|
||
<td>
|
||
<input type="number" class="grade-input final-grade"
|
||
data-index="${index}" min="0" max="100"
|
||
placeholder="0-100" value="${student.final}">
|
||
</td>
|
||
<td>
|
||
<span class="total-grade" data-index="${index}">${student.total || ''}</span>
|
||
</td>
|
||
`;
|
||
|
||
studentsTbody.appendChild(row);
|
||
});
|
||
|
||
// �曄內銵冽聢
|
||
studentsTable.style.display = 'table';
|
||
noStudents.style.display = 'none';
|
||
|
||
// �舐鍂�𣂷漱�厰僼
|
||
submitBtn.disabled = false;
|
||
|
||
// 瘛餃��鞟貍颲枏�鈭衤辣�穃𨯬
|
||
addGradeInputListeners();
|
||
}
|
||
|
||
// �曄內�㰘蝸�嗆�? function showLoading() {
|
||
studentsLoading.style.display = 'block';
|
||
studentsTable.style.display = 'none';
|
||
noStudents.style.display = 'none';
|
||
}
|
||
|
||
// �鞱��㰘蝸�嗆�? function hideLoading() {
|
||
studentsLoading.style.display = 'none';
|
||
}
|
||
|
||
// �曄內�惩郎��㺭�? function showNoStudents() {
|
||
hideLoading();
|
||
studentsTable.style.display = 'none';
|
||
noStudents.style.display = 'block';
|
||
}
|
||
|
||
// �鞱�摮衣�銵冽聢
|
||
function hideStudentsTable() {
|
||
studentsTable.style.display = 'none';
|
||
noStudents.style.display = 'none';
|
||
}
|
||
|
||
// 瘛餃��鞟貍颲枏�鈭衤辣�穃𨯬
|
||
function addGradeInputListeners() {
|
||
const usualGrades = document.querySelectorAll('.usual-grade');
|
||
const midtermGrades = document.querySelectorAll('.midterm-grade');
|
||
const finalGrades = document.querySelectorAll('.final-grade');
|
||
|
||
usualGrades.forEach(input => {
|
||
input.addEventListener('input', calculateTotalGrade);
|
||
});
|
||
|
||
midtermGrades.forEach(input => {
|
||
input.addEventListener('input', calculateTotalGrade);
|
||
});
|
||
|
||
finalGrades.forEach(input => {
|
||
input.addEventListener('input', calculateTotalGrade);
|
||
});
|
||
}
|
||
|
||
// 霈∠��餉��鞟貍
|
||
function calculateTotalGrade(event) {
|
||
const input = event.target;
|
||
const index = input.getAttribute('data-index');
|
||
|
||
// �瑕�銝劐葵�鞟貍
|
||
const usualInput = document.querySelector(`.usual-grade[data-index="${index}"]`);
|
||
const midtermInput = document.querySelector(`.midterm-grade[data-index="${index}"]`);
|
||
const finalInput = document.querySelector(`.final-grade[data-index="${index}"]`);
|
||
const totalSpan = document.querySelector(`.total-grade[data-index="${index}"]`);
|
||
|
||
const usual = parseFloat(usualInput.value) || 0;
|
||
const midterm = parseFloat(midtermInput.value) || 0;
|
||
const final = parseFloat(finalInput.value) || 0;
|
||
|
||
// 霈∠��餉��鞟貍嚗���㵪�撟單𧒄20%嚗峕�銝?0%嚗峕��?0%嚗? const total = (usual * 0.2) + (midterm * 0.3) + (final * 0.5);
|
||
|
||
// �曄內�餉��鞟貍嚗���滢��亙��湔㺭嚗? totalSpan.textContent = Math.round(total);
|
||
|
||
// �寞旿�鞟貍��凒霈曄蔭憸𡏭𠧧
|
||
if (total >= 90) {
|
||
totalSpan.style.color = '#38a169';
|
||
totalSpan.style.fontWeight = 'bold';
|
||
} else if (total >= 60) {
|
||
totalSpan.style.color = '#d69e2e';
|
||
totalSpan.style.fontWeight = 'normal';
|
||
} else {
|
||
totalSpan.style.color = '#e53e3e';
|
||
totalSpan.style.fontWeight = 'bold';
|
||
}
|
||
}
|
||
|
||
// 銵典�撉諹�
|
||
function validateForm() {
|
||
const className = classSelect.value;
|
||
const courseName = courseNameInput.value.trim();
|
||
|
||
if (!className) {
|
||
alert('霂琿�㗇𥋘�剔漣');
|
||
return false;
|
||
}
|
||
|
||
if (!courseName) {
|
||
alert('霂瑁��亥紋蝔见�蝘?);
|
||
courseNameInput.focus();
|
||
return false;
|
||
}
|
||
|
||
// 璉��交糓�行�摮衣��鞟貍�芸‵�? const usualGrades = document.querySelectorAll('.usual-grade');
|
||
const midtermGrades = document.querySelectorAll('.midterm-grade');
|
||
const finalGrades = document.querySelectorAll('.final-grade');
|
||
|
||
for (let i = 0; i < usualGrades.length; i++) {
|
||
const usual = usualGrades[i].value.trim();
|
||
const midterm = midtermGrades[i].value.trim();
|
||
const final = finalGrades[i].value.trim();
|
||
|
||
if (!usual || !midterm || !final) {
|
||
alert(`霂瑕‵�嗵洵${i + 1}銵�郎�毺����㗇�蝏奈);
|
||
return false;
|
||
}
|
||
|
||
const usualNum = parseFloat(usual);
|
||
const midtermNum = parseFloat(midterm);
|
||
const finalNum = parseFloat(final);
|
||
|
||
if (usualNum < 0 || usualNum > 100 ||
|
||
midtermNum < 0 || midtermNum > 100 ||
|
||
finalNum < 0 || finalNum > 100) {
|
||
alert(`蝚?{i + 1}銵�郎�毺��鞟貍敹�◆�?-100銋钅𡢿`);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
// �園�銵典��唳旿
|
||
function collectFormData() {
|
||
const className = classSelect.options[classSelect.selectedIndex].text;
|
||
const courseName = courseNameInput.value.trim();
|
||
const examDate = examDateInput.value;
|
||
const remarks = remarksInput.value.trim();
|
||
|
||
const grades = [];
|
||
const rows = studentsTbody.querySelectorAll('tr');
|
||
|
||
rows.forEach((row, index) => {
|
||
const studentId = row.cells[0].textContent;
|
||
const studentName = row.cells[1].textContent;
|
||
const usual = row.cells[2].querySelector('input').value;
|
||
const midterm = row.cells[3].querySelector('input').value;
|
||
const final = row.cells[4].querySelector('input').value;
|
||
const total = row.cells[5].querySelector('span').textContent;
|
||
|
||
grades.push({
|
||
studentId,
|
||
studentName,
|
||
usual: parseFloat(usual),
|
||
midterm: parseFloat(midterm),
|
||
final: parseFloat(final),
|
||
total: parseFloat(total)
|
||
});
|
||
});
|
||
|
||
return {
|
||
className,
|
||
courseName,
|
||
examDate,
|
||
remarks,
|
||
grades
|
||
};
|
||
}
|
||
|
||
// �𣂷漱銵典�
|
||
function submitForm() {
|
||
if (!validateForm()) {
|
||
return;
|
||
}
|
||
|
||
const formData = collectFormData();
|
||
|
||
// �曄內�𣂷漱銝剔𠶖�? submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> �𣂷漱銝?..';
|
||
submitBtn.disabled = true;
|
||
|
||
// 璅⊥�API靚�鍂
|
||
setTimeout(() => {
|
||
// 璅⊥��𣂼��滚�
|
||
alert(`�鞟貍�𣂷漱�𣂼�嚗�n�剔漣嚗?{formData.className}\n霂曄�嚗?{formData.courseName}\n�勗��?{formData.grades.length}�滚郎���蝏奈);
|
||
|
||
// �滨蔭�厰僼�嗆�? submitBtn.innerHTML = '<i class="fas fa-check"></i> �𣂷漱�鞟貍';
|
||
submitBtn.disabled = false;
|
||
|
||
// �滨蔭銵典�
|
||
resetForm();
|
||
}, 1500);
|
||
}
|
||
|
||
// �滨蔭銵典�
|
||
function resetForm() {
|
||
classSelect.value = '';
|
||
courseNameInput.value = '';
|
||
examDateInput.value = today;
|
||
remarksInput.value = '';
|
||
|
||
// 皜�征摮衣�銵冽聢
|
||
studentsTbody.innerHTML = '';
|
||
studentsTable.style.display = 'none';
|
||
noStudents.style.display = 'none';
|
||
|
||
// 蝳�鍂�𣂷漱�厰僼
|
||
submitBtn.disabled = true;
|
||
}
|
||
|
||
// �𡝗��厰僼鈭衤辣
|
||
cancelBtn.addEventListener('click', function() {
|
||
if (confirm('蝖桀�閬��瘨��嚗���㗇𧊋靽嘥���凒�孵�隡帋腺憭晞�?)) {
|
||
resetForm();
|
||
}
|
||
});
|
||
|
||
// �𣂷漱�厰僼鈭衤辣
|
||
submitBtn.addEventListener('click', submitForm);
|
||
|
||
// 憿菟𢒰�㰘蝸�嗅�憪见�
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
// 璉��交糓�行�敹����㺭�? if (!classSelect.value) {
|
||
submitBtn.disabled = true;
|
||
}
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|