Files
WebWork/frontend/views/teacher/grade_entry.html
祀梦 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><EFBFBD>鞟貍敶訫<EFBFBD> - XX摮行嵗<E8A18C>鞟貍蝞∠<E89D9E>蝟餌<E89D9F></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>
<!-- 撖潸⏛<E6BDB8>?-->
<nav class="navbar">
<div class="navbar-brand">
<a href="/"><i class="fas fa-graduation-cap"></i> XX摮行嵗<E8A18C>鞟貍蝞∠<E89D9E>蝟餌<E89D9F></a>
</div>
<div class="navbar-menu">
<a href="/teacher/dashboard" class="navbar-item"><i class="fas fa-tachometer-alt"></i> <20><EFBFBD>隞芾”<E88ABE>?/a>
<a href="/teacher/grade_entry" class="navbar-item active"><i class="fas fa-edit"></i> <20>鞟貍敶訫<E695B6></a>
<a href="/teacher/grade_management" class="navbar-item"><i class="fas fa-list"></i> <20>鞟貍蝞∠<E89D9E></a>
<div class="user-info">
<span class="user-name"><EFBFBD><EFBFBD><EFBFBD><EFBFBD></span>
<span class="user-role"><EFBFBD><EFBFBD></span>
<a href="/login" class="btn btn-outline btn-small"><i class="fas fa-sign-out-alt"></i> <20><><EFBFBD>?/a>
</div>
</div>
</nav>
<!-- <20><EFBFBD>撅穃紡<E7A983>?-->
<div class="container">
<div class="breadcrumb">
<a href="/">銝駁△</a>
<i class="fas fa-chevron-right"></i>
<a href="/teacher/dashboard"><EFBFBD><EFBFBD>隞芾”<EFBFBD>?/a>
<i class="fas fa-chevron-right"></i>
<span><EFBFBD>鞟貍敶訫<EFBFBD></span>
</div>
</div>
<!-- 銝餃<E98A9D>摰孵躹 -->
<div class="grade-entry-container">
<div class="entry-header">
<h1><i class="fas fa-edit"></i> <20>鞟貍敶訫<E695B6></h1>
<p>霂琿<EFBFBD>㗇𥋘<EFBFBD>剔漣<EFBFBD>諹紋蝔页<EFBFBD><EFBFBD><EFBFBD>銝箸<EFBFBD>銝芸郎<EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝏?/p>
</div>
<div class="entry-form">
<div class="form-row">
<div class="form-group">
<label for="class-select"><i class="fas fa-users"></i> <20>㗇𥋘<E39787>剔漣</label>
<select id="class-select" class="form-control">
<option value="">霂琿<EFBFBD>㗇𥋘<EFBFBD>剔漣</option>
<option value="class1">霈∠<EFBFBD><EFBFBD><EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?021蝥?<3F>?/option>
<option value="class2">霈∠<EFBFBD><EFBFBD><EFBFBD>摮虫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?021蝥?<3F>?/option>
<option value="class3">頧臭辣撌亦<EFBFBD>2021蝥?<3F>?/option>
<option value="class4">頧臭辣撌亦<EFBFBD>2021蝥?<3F>?/option>
<option value="class5">蝵𤑳<EFBFBD>撌亦<EFBFBD>2021蝥?<3F>?/option>
</select>
</div>
<div class="form-group">
<label for="course-name"><i class="fas fa-book"></i> 霂曄<E99C82><E69B84>滨妍</label>
<input type="text" id="course-name" placeholder="霂瑁<E99C82><E79181>亥紋蝔见<E89D94>蝘堆<E89D98><EFBFBD><E68692><EFBFBD>唳旿蝏𤘪<E89D8F><F0A498AA><EFBFBD><EFBFBD>雿𦦵頂蝏毺<E89D8F>">
</div>
</div>
<div class="form-group">
<label for="exam-date"><i class="fas fa-calendar-alt"></i> <20><><EFBFBD><EFBFBD><EFBFBD></label>
<input type="date" id="exam-date">
</div>
<div class="form-group">
<label><i class="fas fa-info-circle"></i><>釣霂湔<E99C82><EFBFBD><EFBFBD><EFBFBD></label>
<textarea id="remarks" rows="3" placeholder="<22><EFBFBD><E888AA>交𧋦甈∟<E79488><E2889F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>𦒘縑<F0A69298><EFBFBD><EFBFBD><E68692><EFBFBD>煺葉<E785BA><E89189><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E680A8><EFBFBD>蝑?></textarea>
</div>
<div class="students-table-container">
<h3><i class="fas fa-user-graduate"></i> 摮衣<E691AE><E8A1A3>鞟貍敶訫<E695B6></h3>
<p class="text-muted"><EFBFBD>㗇𥋘<EFBFBD>剔漣<EFBFBD>𠬍<EFBFBD>蝟餌<EFBFBD><EFBFBD><EFBFBD><EFBFBD>頧質砲<EFBFBD>剔漣<EFBFBD><EFBFBD><EFBFBD><EFBFBD>銵?/p>
<div id="students-loading" class="loading" style="display: none;">
<i class="fas fa-spinner"></i>
<p><EFBFBD><EFBFBD>㰘蝸摮衣<EFBFBD><EFBFBD>𡑒”...</p>
</div>
<div id="no-students" class="no-students" style="display: none;">
<i class="fas fa-user-slash"></i>
<p>霂亦号蝥扳<EFBFBD><EFBFBD>惩郎<EFBFBD><EFBFBD><EFBFBD><EFBFBD>霂瑕<EFBFBD>瘛餃<EFBFBD>摮衣<EFBFBD>靽⊥<EFBFBD></p>
</div>
<table id="students-table" class="students-table" style="display: none;">
<thead>
<tr>
<th>摮血噡</th>
<th>憪枏<EFBFBD></th>
<th>撟單𧒄<EFBFBD>鞟貍</th>
<th><EFBFBD>煺葉<EFBFBD>鞟貍</th>
<th><EFBFBD><EFBFBD><EFBFBD>鞟貍</th>
<th><EFBFBD><EFBFBD><EFBFBD>鞟貍</th>
</tr>
</thead>
<tbody id="students-tbody">
<!-- 摮衣<E691AE><E8A1A3>唳旿撠<E697BF><E692A0><EFBFBD>JavaScript<70><EFBFBD><E586BD><EFBFBD>頧?-->
</tbody>
</table>
</div>
<div class="form-actions">
<button id="cancel-btn" class="btn btn-secondary btn-large">
<i class="fas fa-times"></i> <20>𡝗<EFBFBD>
</button>
<button id="submit-btn" class="btn btn-primary btn-large" disabled>
<i class="fas fa-check"></i> <20>𣂷漱<F0A382B7>鞟貍
</button>
</div>
</div>
<div class="card">
<h3><i class="fas fa-lightbulb"></i> 雿輻鍂霂湔<E99C82></h3>
<ul class="text-muted">
<li>擐硋<EFBFBD><EFBFBD>㗇𥋘閬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝏拍<EFBFBD><EFBFBD>剔漣<EFBFBD>諹紋蝔?/li>
<li>蝟餌<EFBFBD>隡朞䌊<EFBFBD><EFBFBD>頧質砲<EFBFBD>剔漣<EFBFBD><EFBFBD><EFBFBD><EFBFBD>銵?/li>
<li>銝箸<EFBFBD>銝芸郎<EFBFBD><EFBFBD><EFBFBD>亙像<EFBFBD><EFBFBD>蝏押<EFBFBD><EFBFBD><EFBFBD>銝剜<EFBFBD>蝏拙<EFBFBD><EFBFBD><EFBFBD><EFBFBD>鞟貍</li>
<li><EFBFBD><EFBFBD><EFBFBD>鞟貍撠<EFBFBD><EFBFBD><EFBFBD><EFBFBD>滩䌊<EFBFBD>刻恣蝞梹<EFBFBD>暺䁅恕<EFBFBD><EFBFBD><EFBFBD>嚗𡁜像<EFBFBD>?0%嚗峕<E59A97>銝?0%嚗峕<E59A97><E5B395>?0%嚗?/li>
<li>蝖株恕<EFBFBD>㰘秤<EFBFBD>𡒊<EFBFBD><EFBFBD><EFBFBD>𨀣<EFBFBD>鈭斗<EFBFBD>蝏抽<EFBFBD><EFBFBD><EFBFBD><EFBFBD>摮䀹㺭<EFBFBD>?/li>
<li><EFBFBD>𣂷漱<EFBFBD>𤾸虾隞亙銁<EFBFBD>𨀣<EFBFBD>蝏拍恣<EFBFBD><EFBFBD><EFBFBD>嗪△<EFBFBD><EFBFBD><EFBFBD>靽格㺿撌脣<EFBFBD><EFBFBD><EFBFBD><EFBFBD>鞟貍</li>
</ul>
</div>
</div>
<!-- JavaScript -->
<script>
// 璅⊥<E79285>摮衣<E691AE><E8A1A3>唳旿
const mockStudents = [
{ id: '2021001', name: '撘牐<E69298>', usual: '', midterm: '', final: '', total: '' },
{ id: '2021002', name: '<27>𤾸<EFBFBD>', usual: '', midterm: '', final: '', total: '' },
{ id: '2021003', name: '<27><EFBFBD>', usual: '', midterm: '', final: '', total: '' },
{ id: '2021004', name: '韏萄<E99F8F>', usual: '', midterm: '', final: '', total: '' },
{ id: '2021005', name: '<27><EFBFBD>', usual: '', midterm: '', final: '', total: '' },
{ id: '2021006', name: '摮坔<E691AE>', usual: '', midterm: '', final: '', total: '' },
{ id: '2021007', name: '<27><EFBFBD>', usual: '', midterm: '', final: '', total: '' },
{ id: '2021008', name: '<27><EFBFBD>', usual: '', midterm: '', final: '', total: '' }
];
// DOM<4F><4D><EFBFBD>
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');
// 霈曄蔭暺䁅恕<E48185><E68195><EFBFBD><EFBFBD><EFBFBD>銝箔<E98A9D>憭? const today = new Date().toISOString().split('T')[0];
examDateInput.value = today;
// <20>剔漣<E58994>㗇𥋘<E39787><EFBFBD>鈭衤辣
classSelect.addEventListener('change', function() {
const selectedClass = this.value;
if (!selectedClass) {
hideStudentsTable();
submitBtn.disabled = true;
return;
}
// <20>曄內<E69B84>㰘蝸<E3B098><EFBFBD>? showLoading();
// 璅⊥<E79285>API靚<49>鍂撱嗉<E692B1>
setTimeout(() => {
loadStudentsForClass(selectedClass);
}, 1000);
});
// <20>㰘蝸摮衣<E691AE><E8A1A3>唳旿
function loadStudentsForClass(className) {
// 璅⊥<E79285>API<50><EFBFBD>
if (mockStudents.length > 0) {
renderStudentsTable(mockStudents);
} else {
showNoStudents();
}
}
// 皜脫<E79A9C>摮衣<E691AE>銵冽聢
function renderStudentsTable(students) {
hideLoading();
// 皜<>征銵冽聢
studentsTbody.innerHTML = '';
// 瘛餃<E7989B>摮衣<E691AE>銵? 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);
});
// <20>曄內銵冽聢
studentsTable.style.display = 'table';
noStudents.style.display = 'none';
// <20>舐鍂<E88890>𣂷漱<F0A382B7>厰僼
submitBtn.disabled = false;
// 瘛餃<E7989B><E9A483>鞟貍颲枏<E9A2B2>鈭衤辣<E8A1A4>穃𨯬
addGradeInputListeners();
}
// <20>曄內<E69B84>㰘蝸<E3B098><EFBFBD>? function showLoading() {
studentsLoading.style.display = 'block';
studentsTable.style.display = 'none';
noStudents.style.display = 'none';
}
// <20><EFBFBD><E99EB1>㰘蝸<E3B098><EFBFBD>? function hideLoading() {
studentsLoading.style.display = 'none';
}
// <20>曄內<E69B84>惩郎<E683A9><E9838E><EFBFBD>? function showNoStudents() {
hideLoading();
studentsTable.style.display = 'none';
noStudents.style.display = 'block';
}
// <20><EFBFBD>摮衣<E691AE>銵冽聢
function hideStudentsTable() {
studentsTable.style.display = 'none';
noStudents.style.display = 'none';
}
// 瘛餃<E7989B><E9A483>鞟貍颲枏<E9A2B2>鈭衤辣<E8A1A4>穃𨯬
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);
});
}
// 霈∠<E99C88><E288A0><EFBFBD><E9A489>鞟貍
function calculateTotalGrade(event) {
const input = event.target;
const index = input.getAttribute('data-index');
// <20><EFBFBD>銝劐葵<E58A90>鞟貍
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;
// 霈∠<E99C88><E288A0><EFBFBD><E9A489>鞟貍嚗<E8B28D><E59A97><EFBFBD><EFBFBD>撟單𧒄20%嚗峕<E59A97>銝?0%嚗峕<E59A97><E5B395>?0%嚗? const total = (usual * 0.2) + (midterm * 0.3) + (final * 0.5);
// <20>曄內<E69B84><EFBFBD><E9A489>鞟貍嚗<E8B28D><E59A97><EFBFBD><EFBFBD><E6BBA2><EFBFBD><E4BA99>湔㺭嚗? totalSpan.textContent = Math.round(total);
// <20>寞旿<E5AF9E>鞟貍<E99E9F><E8B28D>凒霈曄蔭憸𡏭𠧧
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';
}
}
// 銵典<E98AB5>撉諹<E69289>
function validateForm() {
const className = classSelect.value;
const courseName = courseNameInput.value.trim();
if (!className) {
alert('霂琿<E99C82>㗇𥋘<E39787>剔漣');
return false;
}
if (!courseName) {
alert('霂瑁<E99C82><E79181>亥紋蝔见<E89D94>蝘?);
courseNameInput.focus();
return false;
}
// 璉<><E79289>交糓<E4BAA4><EFBFBD>摮衣<E691AE><E8A1A3>鞟貍<E99E9F><E88AB8>? 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(`霂瑕<E79195>嗵洵${i + 1}銵<><EFBFBD><EFBFBD><E6AFBA><EFBFBD><EFBFBD><EFBFBD>蝏奈);
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}銵<><EFBFBD><EFBFBD><E6AFBA>鞟貍敹<E8B28D><EFBFBD>?-100銋钅𡢿`);
return false;
}
}
return true;
}
// <20><EFBFBD>銵典<E98AB5><E585B8>唳旿
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
};
}
// <20>𣂷漱銵典<E98AB5>
function submitForm() {
if (!validateForm()) {
return;
}
const formData = collectFormData();
// <20>曄內<E69B84>𣂷漱銝剔𠶖<E58994>? submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> <EFBFBD>𣂷?..';
submitBtn.disabled = true;
// 璅⊥<E79285>API靚<49>
setTimeout(() => {
// 璅⊥<E79285><E28AA5>𣂼<EFBFBD><F0A382BC><EFBFBD>
alert(`<EFBFBD>鞟貍<EFBFBD>𣂷漱<EFBFBD>𣂼<EFBFBD><EFBFBD>n<EFBFBD>剔漣嚗?{formData.className}\n霂曄<EFBFBD>嚗?{formData.courseName}\n<EFBFBD><EFBFBD><EFBFBD>?{formData.grades.length}<7D>滚郎<E6BB9A><E9838E><EFBFBD>蝏奈);
// <20>滨蔭<E6BBA8>厰僼<E58EB0><EFBFBD>? submitBtn.innerHTML = '<i class="fas fa-check"></i> <20>𣂷漱<F0A382B7>鞟貍';
submitBtn.disabled = false;
// <20>滨蔭銵典<E98AB5>
resetForm();
}, 1500);
}
// <20>滨蔭銵典<E98AB5>
function resetForm() {
classSelect.value = '';
courseNameInput.value = '';
examDateInput.value = today;
remarksInput.value = '';
// 皜<>征摮衣<E691AE>銵冽聢
studentsTbody.innerHTML = '';
studentsTable.style.display = 'none';
noStudents.style.display = 'none';
// 蝳<><EFBFBD>𣂷漱<F0A382B7>厰僼
submitBtn.disabled = true;
}
// <20>𡝗<EFBFBD><F0A19D97>厰僼鈭衤辣
cancelBtn.addEventListener('click', function() {
if (confirm('蝖桀<E89D96><EFBFBD><E996AC><EFBFBD><E798A8><EFBFBD><E59A97><EFBFBD>㗇𧊋靽嘥<E99DBD><E598A5><EFBFBD><EFBFBD><EFBFBD>隡帋腺憭晞<E686AD>?)) {
resetForm();
}
});
// <20>𣂷漱<F0A382B7>厰僼鈭衤辣
submitBtn.addEventListener('click', submitForm);
// 憿菟𢒰<E88F9F>㰘蝸<E3B098><EFBFBD>憪见<E686AA>
document.addEventListener('DOMContentLoaded', function() {
// 璉<><E79289>交糓<E4BAA4><EFBFBD><EFBFBD><E695B9><EFBFBD><EFBFBD><EFBFBD>? if (!classSelect.value) {
submitBtn.disabled = true;
}
});
</script>
</body>
</html>