Files
WebWork/frontend/views/teacher/grade_entry.html
T
祀梦 bcf2c71fad refactor(frontend): 重构前端目录结构并优化认证流程
将前端文件从html目录迁移到views目录,按功能模块组织
重构认证中间件和路由处理,简化页面权限控制
更新静态资源引用路径,统一使用/public前缀
添加学生仪表板页面,优化移动端显示
移除旧版html和js文件,更新样式和脚本
2025-12-21 22:07:23 +08:00

448 lines
18 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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>
<!-- 撅穃紡?-->
<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>