feat: 实现教师资料更新、操作日志和系统设置功能
新增教师资料更新功能,包括个人信息修改和密码更新 添加操作日志记录系统,记录用户关键操作 实现系统设置模块,支持动态配置系统参数 重构数据库模型,新增教师表和系统设置表 优化成绩录入逻辑,支持平时分、期中和期末成绩计算 添加数据导出功能,支持学生、教师和成绩数据导出 完善管理员后台,增加统计图表和操作日志查看
This commit is contained in:
@@ -3,445 +3,242 @@
|
||||
<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">
|
||||
<title>成绩录入 - 教师端</title>
|
||||
<!-- Bootstrap 5 CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
<!-- Google Fonts -->
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--sidebar-width: 260px;
|
||||
--primary-color: #1cc88a;
|
||||
--secondary-color: #858796;
|
||||
--light-bg: #f8f9fc;
|
||||
--teacher-gradient: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Noto Sans SC', sans-serif;
|
||||
background-color: var(--light-bg);
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* 侧边栏样式 */
|
||||
.sidebar {
|
||||
width: var(--sidebar-width);
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background: var(--teacher-gradient);
|
||||
color: white;
|
||||
z-index: 1000;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.sidebar-header {
|
||||
padding: 2rem 1.5rem;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
.sidebar-brand {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 700;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.user-profile {
|
||||
padding: 2rem 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
background: rgba(255,255,255,0.2);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto 1rem;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.user-info h6 { margin-bottom: 0.25rem; font-weight: 600; }
|
||||
.user-info p { font-size: 0.85rem; opacity: 0.8; margin-bottom: 0; }
|
||||
|
||||
.nav-menu { padding: 1rem 0; }
|
||||
.nav-item { padding: 0.25rem 1rem; }
|
||||
|
||||
.nav-link {
|
||||
color: rgba(255,255,255,0.8);
|
||||
padding: 0.8rem 1.25rem;
|
||||
border-radius: 0.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
transition: all 0.2s;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.nav-link:hover, .nav-link.active {
|
||||
color: white;
|
||||
background: rgba(255,255,255,0.15);
|
||||
}
|
||||
|
||||
.nav-link i { width: 20px; text-align: center; }
|
||||
|
||||
/* 主内容区 */
|
||||
.main-content {
|
||||
margin-left: var(--sidebar-width);
|
||||
padding: 2rem;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.top-navbar {
|
||||
background: white;
|
||||
padding: 1rem 2rem;
|
||||
border-radius: 1rem;
|
||||
box-shadow: 0 0.15rem 1.75rem 0 rgba(58, 59, 69, 0.1);
|
||||
margin-bottom: 2rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.page-heading h4 { margin-bottom: 0; font-weight: 700; color: #333; }
|
||||
|
||||
@media (max-width: 992px) {
|
||||
.sidebar { left: -var(--sidebar-width); }
|
||||
.main-content { margin-left: 0; }
|
||||
.sidebar.active { left: 0; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- 撖潸⏛�?-->
|
||||
<nav class="navbar">
|
||||
<div class="navbar-brand">
|
||||
<a href="/"><i class="fas fa-graduation-cap"></i> XX摮行嵗�鞟貍蝞∠�蝟餌�</a>
|
||||
<!-- 侧边栏 -->
|
||||
<div class="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<a href="#" class="sidebar-brand">
|
||||
<i class="fas fa-chalkboard-teacher"></i>
|
||||
<span>成绩管理系统</span>
|
||||
</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 class="user-profile">
|
||||
<div class="user-avatar">
|
||||
<i class="fas fa-user-tie"></i>
|
||||
</div>
|
||||
<div class="user-info text-white">
|
||||
<h6 id="teacherName">加载中...</h6>
|
||||
<p>教师 | <span id="teacherId">...</span></p>
|
||||
</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>
|
||||
<nav class="nav-menu">
|
||||
<div class="nav-item">
|
||||
<a href="/teacher/dashboard" class="nav-link">
|
||||
<i class="fas fa-tachometer-alt"></i>
|
||||
<span>教师仪表板</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="nav-item">
|
||||
<a href="/teacher/grade_entry" class="nav-link active">
|
||||
<i class="fas fa-edit"></i>
|
||||
<span>成绩录入</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="nav-item">
|
||||
<a href="/teacher/grade_management" class="nav-link">
|
||||
<i class="fas fa-tasks"></i>
|
||||
<span>成绩管理</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="nav-item">
|
||||
<a href="/teacher/profile" class="nav-link">
|
||||
<i class="fas fa-user-edit"></i>
|
||||
<span>个人资料</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="nav-item mt-4">
|
||||
<a href="javascript:void(0)" id="logoutBtn" class="nav-link text-warning">
|
||||
<i class="fas fa-sign-out-alt"></i>
|
||||
<span>退出登录</span>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<!-- 主内容 -->
|
||||
<div class="main-content">
|
||||
<!-- 顶部导航 -->
|
||||
<div class="top-navbar">
|
||||
<div class="page-heading">
|
||||
<h4>成绩录入</h4>
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<div class="text-end d-none d-md-block">
|
||||
<div class="small text-muted" id="currentTime"></div>
|
||||
<div class="fw-bold" id="userName">加载中...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 录入卡片 -->
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-body p-4">
|
||||
<div class="row mb-4 align-items-end">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label text-muted small fw-bold">选择课程</label>
|
||||
<select id="courseSelect" class="form-select">
|
||||
<option value="">加载课程中...</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-8 text-end">
|
||||
<div class="alert alert-info d-inline-block mb-0 py-2 px-3 small">
|
||||
<i class="fas fa-info-circle me-1"></i> 请先选择课程,系统将自动加载该课程的学生名单
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>学号</th>
|
||||
<th>姓名</th>
|
||||
<th style="width: 120px;">平时成绩</th>
|
||||
<th style="width: 120px;">期中成绩</th>
|
||||
<th style="width: 120px;">期末成绩</th>
|
||||
<th>总评</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="studentTableBody">
|
||||
<tr>
|
||||
<td colspan="7" class="text-center py-5 text-muted">
|
||||
<i class="fas fa-arrow-up mb-2"></i><br>
|
||||
请选择课程以加载学生列表
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</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>
|
||||
<!-- Bootstrap 5 JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="/public/js/auth.js"></script>
|
||||
<script src="/public/js/teacher.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
Reference in New Issue
Block a user