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

575 lines
23 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>鞟貍亥砭/蝞∠ - 摮衣鞟貍蝞∠蝟餌</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="nav-container">
<div class="nav-brand">
<a href="/">
<i class="fas fa-graduation-cap"></i>
<span>XX摮行嵗鞟貍蝞∠蝟餌</span>
</a>
</div>
<div class="nav-menu">
<a href="/teacher/dashboard" class="nav-link">
<i class="fas fa-tachometer-alt"></i>
<span>隞芾”?/span>
</a>
<a href="/teacher/grade_entry" class="nav-link">
<i class="fas fa-edit"></i>
<span>鞟貍敶訫</span>
</a>
<a href="/teacher/grade_management" class="nav-link active">
<i class="fas fa-search"></i>
<span>鞟貍蝞∠</span>
</a>
</div>
<div class="nav-user">
<div class="user-info">
<i class="fas fa-user-circle"></i>
<span>撘㰘</span>
</div>
<a href="/login" class="btn-logout">
<i class="fas fa-sign-out-alt"></i>
<span>?/span>
</a>
</div>
</div>
</nav>
<!-- 銝餃摰孵躹 -->
<main class="main-content">
<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 class="page-header">
<h1 class="page-title">鞟貍亥砭/蝞∠</h1>
<p class="page-description">亥砭𣳇膄摮衣鞟貍霈啣</p>
</div>
<!-- 蝑偦匧躹?-->
<div class="filter-section">
<h2 class="filter-title">
<i class="fas fa-filter"></i>
蝑偦㗇辺隞? </h2>
<div class="filter-form">
<div class="form-group">
<label for="class-select">剔漣</label>
<select id="class-select" class="form-control">
<option value="">剔漣</option>
<option value="class1">霈∠摮虫??/option>
<option value="class2">霈∠摮虫??/option>
<option value="class3">頧臭辣撌亦1?/option>
<option value="class4">頧臭辣撌亦2?/option>
<option value="class5">蝵𤑳撌亦1?/option>
</select>
</div>
<div class="form-group">
<label for="course-select">霂曄</label>
<select id="course-select" class="form-control">
<option value="">霂曄</option>
<option value="course1">唳旿蝏𤘪</option>
<option value="course2">蝟餌</option>
<option value="course3">霈∠蝏?/option>
<option value="course4">唳旿摨梶頂蝏?/option>
<option value="course5">頧臭辣撌亦</option>
</select>
</div>
<div class="form-group">
<label for="student-id">摮衣摮血噡</label>
<input type="text" id="student-id" class="form-control" placeholder="颲枏摮衣摮血噡">
</div>
<div class="form-group">
<label for="student-name">摮衣憪枏</label>
<input type="text" id="student-name" class="form-control" placeholder="颲枏摮衣憪枏">
</div>
<div class="filter-actions">
<button id="search-btn" class="btn-search">
<i class="fas fa-search"></i>
亥砭
</button>
<button id="reset-btn" class="btn-reset">
<i class="fas fa-redo"></i>
滨蔭
</button>
</div>
</div>
</div>
<!-- 蝏𤘪 -->
<div class="results-section">
<div class="results-header">
<h2 class="results-title">亥砭蝏𤘪</h2>
<div class="results-actions">
<button id="export-btn" class="btn-export">
<i class="fas fa-file-export"></i>
撖澆枂鞟貍
</button>
<button id="batch-delete-btn" class="btn-batch-delete">
<i class="fas fa-trash-alt"></i>
𣳇膄
</button>
</div>
</div>
<div class="table-responsive">
<table class="grade-table">
<thead>
<tr>
<th><input type="checkbox" id="select-all"></th>
<th>摮血噡</th>
<th>憪枏</th>
<th>剔漣</th>
<th>霂曄</th>
<th>撟單𧒄鞟貍</th>
<th>煺葉鞟貍</th>
<th>鞟貍</th>
<th>鞟貍</th>
<th>蝑厩漣</th>
<th></th>
</tr>
</thead>
<tbody id="grade-table-body">
<!-- 唳旿撠JavaScript頧?-->
<tr>
<td colspan="11" class="loading">
<i class="fas fa-spinner fa-spin"></i>
<p>㰘蝸鞟貍唳旿...</p>
</td>
</tr>
</tbody>
</table>
</div>
<!-- △ -->
<div class="pagination">
<button id="prev-page" disabled>銝𠹺憿?/button>
<button class="active">1</button>
<button>2</button>
<button>3</button>
<button id="next-page">銝衤憿?/button>
</div>
</div>
</div>
</main>
<!-- 憿菔 -->
<footer class="footer">
<div class="container">
<p>&copy; 2023 XX摮行嵗鞟貍蝞∠蝟餌. ?</p>
<p>舀𣈲? 霈∠摮虫臬郎?/p>
</div>
</footer>
<script>
// 璅⊥鞟貍唳旿
const mockGrades = [
{
id: 1,
studentId: "20230001",
studentName: "撘牐",
className: "霈∠摮虫??,
courseName: "唳旿蝏𤘪",
regularScore: 85,
midtermScore: 88,
finalScore: 90,
totalScore: 88.5,
grade: "隡条"
},
{
id: 2,
studentId: "20230002",
studentName: "𤾸",
className: "摮虫??,
courseName: "唳旿蝏𤘪",
regularScore: 78,
midtermScore: 82,
finalScore: 85,
totalScore: 82.3,
grade: "臬末"
},
{
id: 3,
studentId: "20230003",
studentName: "",
className: "霈∠摮虫??,
courseName: "蝟餌",
regularScore: 92,
midtermScore: 88,
finalScore: 95,
totalScore: 91.8,
grade: "隡条"
},
{
id: 4,
studentId: "20230004",
studentName: "韏萄",
className: "摮虫??,
courseName: "蝟餌",
regularScore: 65,
midtermScore: 70,
finalScore: 68,
totalScore: 67.9,
grade: "𦠜聢"
},
{
id: 5,
studentId: "20230005",
studentName: "",
className: "頧臭辣撌亦1?,
courseName: "唳旿摨梶頂蝏?,
regularScore: 88,
midtermScore: 85,
finalScore: 90,
totalScore: 87.9,
grade: "臬末"
},
{
id: 6,
studentId: "20230006",
studentName: "摮坔",
className: "頧臭辣撌亦1?,
courseName: "唳旿摨梶頂蝏?,
regularScore: 75,
midtermScore: 78,
finalScore: 80,
totalScore: 78.1,
grade: "銝剔"
},
{
id: 7,
studentId: "20230007",
studentName: "",
className: "頧臭辣撌亦2?,
courseName: "頧臭辣撌亦",
regularScore: 90,
midtermScore: 92,
finalScore: 88,
totalScore: 89.6,
grade: "隡条"
},
{
id: 8,
studentId: "20230008",
studentName: "",
className: "頧臭辣撌亦2?,
courseName: "頧臭辣撌亦",
regularScore: 82,
midtermScore: 85,
finalScore: 87,
totalScore: 85.1,
grade: "臬末"
}
];
// DOM
const searchBtn = document.getElementById('search-btn');
const resetBtn = document.getElementById('reset-btn');
const exportBtn = document.getElementById('export-btn');
const batchDeleteBtn = document.getElementById('batch-delete-btn');
const selectAllCheckbox = document.getElementById('select-all');
const gradeTableBody = document.getElementById('grade-table-body');
const classSelect = document.getElementById('class-select');
const courseSelect = document.getElementById('course-select');
const studentIdInput = document.getElementById('student-id');
const studentNameInput = document.getElementById('student-name');
// 敶枏劐葉蝏呼D
let selectedGradeIds = new Set();
// 㚚△? function initPage() {
renderGradeTable(mockGrades);
setupEventListeners();
updateSelectedCount();
}
// 皜脫鞟貍銵冽聢
function renderGradeTable(grades) {
if (grades.length === 0) {
gradeTableBody.innerHTML = `
<tr>
<td colspan="11" class="no-results">
<i class="fas fa-search"></i>
<h3>芣𪄳啁㮾蝏抵扇敶?/h3>
<p>霂瑕霂閗㗇辺隞嗆瘛餃鞟貍霈啣</p>
</td>
</tr>
`;
return;
}
let tableHTML = '';
grades.forEach(grade => {
// 寞旿鞟貍蝖桀CSS蝐? let gradeClass = 'grade-cell';
if (grade.totalScore >= 90) {
gradeClass += ' grade-excellent';
} else if (grade.totalScore >= 80) {
gradeClass += ' grade-good';
} else if (grade.totalScore < 60) {
gradeClass += ' grade-poor';
}
// 寞旿鞟貍蝖桀蝑厩漣
let gradeLevel = grade.grade;
tableHTML += `
<tr data-grade-id="${grade.id}">
<td>
<input type="checkbox" class="grade-checkbox" data-id="${grade.id}">
</td>
<td>${grade.studentId}</td>
<td>${grade.studentName}</td>
<td>${grade.className}</td>
<td>${grade.courseName}</td>
<td>${grade.regularScore}</td>
<td>${grade.midtermScore}</td>
<td>${grade.finalScore}</td>
<td class="${gradeClass}">${grade.totalScore.toFixed(1)}</td>
<td>${gradeLevel}</td>
<td>
<div class="action-buttons">
<button class="btn-edit" onclick="editGrade(${grade.id})">
<i class="fas fa-edit"></i> 靽格㺿
</button>
<button class="btn-delete" onclick="deleteGrade(${grade.id})">
<i class="fas fa-trash"></i> 𣳇膄
</button>
</div>
</td>
</tr>
`;
});
gradeTableBody.innerHTML = tableHTML;
// 齿鰵蝏穃憭漤鈭衤辣
document.querySelectorAll('.grade-checkbox').forEach(checkbox => {
checkbox.addEventListener('change', function() {
const gradeId = parseInt(this.getAttribute('data-id'));
if (this.checked) {
selectedGradeIds.add(gradeId);
} else {
selectedGradeIds.delete(gradeId);
selectAllCheckbox.checked = false;
}
updateSelectedCount();
});
});
}
// 霈曄蔭鈭衤辣穃𨯬? function setupEventListeners() {
// 亥砭厰僼
searchBtn.addEventListener('click', function() {
performSearch();
});
// 滨蔭厰僼
resetBtn.addEventListener('click', function() {
classSelect.value = '';
courseSelect.value = '';
studentIdInput.value = '';
studentNameInput.value = '';
renderGradeTable(mockGrades);
selectedGradeIds.clear();
selectAllCheckbox.checked = false;
updateSelectedCount();
});
// 撖澆枂厰僼
exportBtn.addEventListener('click', function() {
exportGrades();
});
// 𣳇膄厰僼
batchDeleteBtn.addEventListener('click', function() {
if (selectedGradeIds.size === 0) {
alert('霂瑕㗇𥋘閬鞟貍霈啣嚗?);
return;
}
if (confirm(`蝖桀劐葉?${selectedGradeIds.size} 蝏抵扇敶訫銝滚虾)) {
batchDeleteGrades();
}
});
//
selectAllCheckbox.addEventListener('change', function() {
const checkboxes = document.querySelectorAll('.grade-checkbox');
checkboxes.forEach(checkbox => {
checkbox.checked = this.checked;
const gradeId = parseInt(checkbox.getAttribute('data-id'));
if (this.checked) {
selectedGradeIds.add(gradeId);
} else {
selectedGradeIds.delete(gradeId);
}
});
updateSelectedCount();
});
// 颲枏頧阡睸𦦵揣
[studentIdInput, studentNameInput].forEach(input => {
input.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
performSearch();
}
});
});
}
// 𦦵揣
function performSearch() {
const selectedClass = classSelect.value;
const selectedCourse = courseSelect.value;
const studentId = studentIdInput.value.trim();
const studentName = studentNameInput.value.trim();
// 曄內㰘蝸? gradeTableBody.innerHTML = `
<tr>
<td colspan="11" class="loading">
<i class="fas fa-spinner fa-spin"></i>
<p>甇𦦵揣鞟貍唳旿...</p>
</td>
</tr>
`;
// 璅⊥API撱嗉
setTimeout(() => {
let filteredGrades = mockGrades.filter(grade => {
// 剔漣蝑偦? if (selectedClass && grade.className !== selectedClass) {
return false;
}
// 霂曄蝑偦? if (selectedCourse && grade.courseName !== selectedCourse) {
return false;
}
// 摮血噡蝑偦? if (studentId && !grade.studentId.includes(studentId)) {
return false;
}
// 憪枏蝑偦? if (studentName && !grade.studentName.includes(studentName)) {
return false;
}
return true;
});
renderGradeTable(filteredGrades);
selectedGradeIds.clear();
selectAllCheckbox.checked = false;
updateSelectedCount();
}, 500);
}
// 撖澆枂鞟貍
function exportGrades() {
// 餈䠷摨磰砲靚𡒊垢API撖澆枂鞟貍
// 𧒄雿輻鍂璅⊥撖澆枂
alert('鞟貍撖澆枂銁撘睲葉嚗Excel龦SV撖澆枂?);
// 璅⊥撖澆枂餈
exportBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 撖澆枂銝?..';
exportBtn.disabled = true;
setTimeout(() => {
exportBtn.innerHTML = '<i class="fas fa-file-export"></i> 撖澆枂鞟貍';
exportBtn.disabled = false;
// 其葉嚗諹閫血辣銝贝蝸
// 𧒄曄內𣂼
showNotification('鞟貍撖澆枂𣂼隞嗅歇撘憪衤頧賬?, 'success');
}, 1500);
}
// 𣳇膄鞟貍
function batchDeleteGrades() {
// 餈䠷摨磰砲靚𡒊垢API𣳇膄鞟貍
// 𧒄雿輻鍂璅⊥𣳇膄
batchDeleteBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 𣳇膄銝?..';
batchDeleteBtn.disabled = true;
setTimeout(() => {
// 隞擧芋桐葉𣳇膄劐葉蝏? selectedGradeIds.forEach(id => {
const index = mockGrades.findIndex(grade => grade.id === id);
if (index !== -1) {
mockGrades.splice(index, 1);
}
});
// 齿鰵皜脫銵冽聢
renderGradeTable(mockGrades);
selectedGradeIds.clear();
selectAllCheckbox.checked = false;
batchDeleteBtn.innerHTML = '<i class="fas fa-trash-alt"></i> 𣳇膄';
batchDeleteBtn.disabled = false;
showNotification(`𣂼𣳇膄 ${selectedGradeIds.size} 蝏抵扇敶𤏪`, 'success');
updateSelectedCount();
}, 1000);
}
// 蝻𤥁鞟貍
function editGrade(gradeId) {
// 餈䠷摨磰砲頝唾蓮颲煾△蝻𤥁璅⊥
// 𧒄曄內鞟內
alert(`蝻𤥁鞟貍 ID: ${gradeId}\n其葉嚗諹蝻𤥁銵典);
}
// 𣳇膄蓥葵鞟貍
function deleteGrade(gradeId) {
if (confirm('蝖桀蝏抵扇敶訫銝滚虾?)) {
// 餈䠷摨磰砲靚𡒊垢API𣳇膄鞟貍
// 𧒄雿輻鍂璅⊥𣳇膄
const index = mockGrades.findIndex(grade => grade.id === gradeId);
if (index !== -1) {
mockGrades.splice(index, 1);
renderGradeTable(mockGrades);
selectedGradeIds.delete(gradeId);
updateSelectedCount();
showNotification('鞟貍霈啣撌脣', 'success');
}
}
}
// 湔鰵劐葉霈⊥㺭
function updateSelectedCount() {
const count = selectedGradeIds.size;
if (count > 0) {
batchDeleteBtn.innerHTML = `<i class="fas fa-trash-alt"></i> 𣳇膄 (${count})`;
} else {
batchDeleteBtn.innerHTML = '<i class="fas fa-trash-alt"></i> 𣳇膄';
}
}
// 曄內𡁶䰻
function showNotification(message, type = 'info') {
// 其葉嚗諹曄內銝銝芰𡁶䰻蝏
// 𧒄雿輻鍂alert
alert(message);
}
// 憿菟𢒰㰘蝸摰峕𤾸憪见
document.addEventListener('DOMContentLoaded', initPage);
</script>
</body>
</html>