v1.2版本更新发布
This commit is contained in:
@@ -44,6 +44,9 @@ DEDUCTION_HOMEWORK_LATE=1
|
||||
# 作业-每次加减分上限(绝对值)
|
||||
HOMEWORK_MAX_POINTS=3
|
||||
|
||||
# 学习委员单次加减分上限(绝对值)
|
||||
STUDY_COMMISSIONER_MAX_POINTS=5
|
||||
|
||||
# 考勤-缺勤扣分
|
||||
DEDUCTION_ATTENDANCE_ABSENT=5
|
||||
# 考勤-迟到扣分
|
||||
|
||||
@@ -20,7 +20,7 @@ if (!isset($_SESSION['user_id']) || $_SESSION['user_type'] !== 'admin') {
|
||||
$page_title = '操行分管理';
|
||||
$role = $_SESSION['role'] ?? '';
|
||||
|
||||
if (!in_array($role, ['班主任', '班长', '劳动委员', '志愿委员'])) {
|
||||
if (!in_array($role, ['班主任', '班长', '学习委员', '劳动委员', '志愿委员'])) {
|
||||
header('Location: /admin/dashboard.php');
|
||||
exit();
|
||||
}
|
||||
@@ -209,6 +209,7 @@ loadStudents();
|
||||
<input type="number" id="pointsChange" required placeholder="正数为加分,负数为扣分">
|
||||
<small><?php
|
||||
if ($role === '班长') echo '班长单次±5分以内';
|
||||
elseif ($role === '学习委员') echo '学习委员单次±5分以内';
|
||||
elseif ($role === '劳动委员') echo '劳动委员仅限±1分';
|
||||
elseif ($role === '志愿委员') echo '志愿委员仅限加分';
|
||||
else echo '班主任无限制';
|
||||
|
||||
@@ -37,7 +37,7 @@ include __DIR__ . '/../includes/header.php';
|
||||
<div class="table-wrapper">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr><th>排名</th><th>学号</th><th>姓名</th><th>操行分</th></tr>
|
||||
<tr><th>排名</th><th>学号</th><th>姓名</th><th>操行分</th><th>前%</th></tr>
|
||||
</thead>
|
||||
<tbody id="rankingList"></tbody>
|
||||
</table>
|
||||
@@ -69,17 +69,25 @@ async function loadDashboard() {
|
||||
|
||||
const rankingRes = await apiGet('/api/student/ranking', { limit: 100 });
|
||||
if (rankingRes && rankingRes.success) {
|
||||
const totalStudents = rankingRes.data.total_students || 0;
|
||||
let html = '';
|
||||
rankingRes.data.ranking.forEach((student, index) => {
|
||||
const rank = index + 1;
|
||||
let percentile = '--';
|
||||
if (totalStudents > 0) {
|
||||
const pct = Math.floor(rank / totalStudents * 100);
|
||||
percentile = (pct === 0 ? 1 : pct) + '%';
|
||||
}
|
||||
html += `<tr>
|
||||
<td>${index + 1}</td>
|
||||
<td>${rank}</td>
|
||||
<td>${escapeHtml(student.student_no)}</td>
|
||||
<td>${escapeHtml(student.name)}</td>
|
||||
<td>${student.total_points}</td>
|
||||
<td>前${percentile}</td>
|
||||
</tr>`;
|
||||
});
|
||||
if (rankingRes.data.ranking.length === 0) {
|
||||
html = '<tr><td colspan="4" style="text-align:center;">暂无数据</td></tr>';
|
||||
html = '<tr><td colspan="5" style="text-align:center;">暂无数据</td></tr>';
|
||||
}
|
||||
document.getElementById('rankingList').innerHTML = html;
|
||||
}
|
||||
|
||||
307
frontend/admin/semesters.php
Normal file
307
frontend/admin/semesters.php
Normal file
@@ -0,0 +1,307 @@
|
||||
<?php
|
||||
/**
|
||||
* 班级操行分管理系统 - 学期管理页面
|
||||
*
|
||||
* 开发者: Canglan
|
||||
* 联系方式: admin@sea-studio.top
|
||||
* 版权归属: Sea Network Technology Studio
|
||||
* 许可证: MIT License
|
||||
*
|
||||
* 版权所有 © Sea Network Technology Studio
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id']) || $_SESSION['user_type'] !== 'admin') {
|
||||
header('Location: /index.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
$role = $_SESSION['role'] ?? '';
|
||||
if ($role !== '班主任') {
|
||||
header('Location: /admin/dashboard.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
$page_title = '学期管理';
|
||||
include __DIR__ . '/../includes/header.php';
|
||||
?>
|
||||
|
||||
<?php include __DIR__ . '/../includes/nav.php'; ?>
|
||||
|
||||
<div class="container">
|
||||
<div class="card">
|
||||
<div class="action-bar">
|
||||
<button class="btn btn-primary" onclick="showCreateSemesterModal()">创建新学期</button>
|
||||
</div>
|
||||
<div class="table-wrapper">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>学期名称</th>
|
||||
<th>开始日期</th>
|
||||
<th>结束日期</th>
|
||||
<th>状态</th>
|
||||
<th>创建时间</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="semesterList"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 创建学期模态框 -->
|
||||
<div id="createSemesterModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3>创建新学期</h3>
|
||||
<button class="modal-close" onclick="closeModal('createSemesterModal')">×</button>
|
||||
</div>
|
||||
<form onsubmit="event.preventDefault(); submitCreateSemester()">
|
||||
<div class="form-group">
|
||||
<label>学期名称 <span style="color:red;">*</span></label>
|
||||
<input type="text" id="semesterName" required placeholder="如:2025春季学期" maxlength="100">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>开始日期</label>
|
||||
<input type="date" id="semesterStartDate">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>结束日期</label>
|
||||
<input type="date" id="semesterEndDate">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary">创建并激活</button>
|
||||
<button type="button" class="btn" onclick="closeModal('createSemesterModal')">取消</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 归档确认模态框 -->
|
||||
<div id="archiveConfirmModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3>确认归档学期</h3>
|
||||
<button class="modal-close" onclick="closeModal('archiveConfirmModal')">×</button>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<p id="archiveConfirmText" style="margin: 10px 0;"></p>
|
||||
<p style="color: #e74c3c; font-size: 14px;">注意:归档后该学期的操行分记录将不可修改或撤销,但可以查看归档数据。</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" onclick="confirmArchive()">确认归档</button>
|
||||
<button type="button" class="btn" onclick="closeModal('archiveConfirmModal')">取消</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 归档数据查看模态框 -->
|
||||
<div id="archiveDataModal" class="modal">
|
||||
<div class="modal-content" style="max-width: 700px;">
|
||||
<div class="modal-header">
|
||||
<h3 id="archiveDataTitle">归档数据</h3>
|
||||
<button class="modal-close" onclick="closeModal('archiveDataModal')">×</button>
|
||||
</div>
|
||||
<div class="table-wrapper">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>排名</th>
|
||||
<th>学号</th>
|
||||
<th>姓名</th>
|
||||
<th>最终操行分</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="archiveDataList"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="pagination" id="archivePagination"></div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn" onclick="closeModal('archiveDataModal')">关闭</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var archiveSemesterId = null;
|
||||
var archivePage = 1;
|
||||
var archiveTotalPages = 1;
|
||||
|
||||
async function loadSemesters() {
|
||||
const res = await apiGet('/api/semester/list');
|
||||
if (res && res.success) {
|
||||
let html = '';
|
||||
const semesters = res.data || [];
|
||||
semesters.forEach(sem => {
|
||||
let statusText = '';
|
||||
let statusClass = '';
|
||||
if (sem.is_archived) {
|
||||
statusText = '已归档';
|
||||
statusClass = 'status-badge status-not_submitted';
|
||||
} else if (sem.is_active) {
|
||||
statusText = '当前学期';
|
||||
statusClass = 'status-badge status-submitted';
|
||||
} else {
|
||||
statusText = '未激活';
|
||||
statusClass = 'status-badge status-late';
|
||||
}
|
||||
|
||||
let actions = '';
|
||||
if (!sem.is_archived) {
|
||||
if (!sem.is_active) {
|
||||
actions += `<button class="btn btn-sm btn-primary" onclick="activateSemester(${sem.semester_id})">激活</button> `;
|
||||
}
|
||||
actions += `<button class="btn btn-sm btn-warning" onclick="showArchiveConfirm(${sem.semester_id}, '${escapeHtml(sem.semester_name)}')">归档</button> `;
|
||||
}
|
||||
if (sem.is_archived) {
|
||||
actions += `<button class="btn btn-sm btn-secondary" onclick="viewArchiveData(${sem.semester_id}, '${escapeHtml(sem.semester_name)}')">查看归档</button>`;
|
||||
}
|
||||
|
||||
html += `<tr>
|
||||
<td>${escapeHtml(sem.semester_name)}</td>
|
||||
<td>${formatDate(sem.start_date)}</td>
|
||||
<td>${formatDate(sem.end_date)}</td>
|
||||
<td><span class="${statusClass}">${statusText}</span></td>
|
||||
<td>${formatDateTime(sem.created_at)}</td>
|
||||
<td>${actions}</td>
|
||||
</tr>`;
|
||||
});
|
||||
if (semesters.length === 0) {
|
||||
html = '<tr><td colspan="6" style="text-align:center;">暂无学期,请点击上方按钮创建新学期</td></tr>';
|
||||
}
|
||||
document.getElementById('semesterList').innerHTML = html;
|
||||
}
|
||||
}
|
||||
|
||||
function showCreateSemesterModal() {
|
||||
document.getElementById('semesterName').value = '';
|
||||
document.getElementById('semesterStartDate').value = '';
|
||||
document.getElementById('semesterEndDate').value = '';
|
||||
document.getElementById('createSemesterModal').style.display = 'flex';
|
||||
}
|
||||
|
||||
async function submitCreateSemester() {
|
||||
const name = document.getElementById('semesterName').value.trim();
|
||||
const startDate = document.getElementById('semesterStartDate').value;
|
||||
const endDate = document.getElementById('semesterEndDate').value;
|
||||
|
||||
if (!name) {
|
||||
showToast('请输入学期名称', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await apiPost('/api/semester/create', {
|
||||
semester_name: name,
|
||||
start_date: startDate || null,
|
||||
end_date: endDate || null
|
||||
});
|
||||
|
||||
if (res && res.success) {
|
||||
showToast('学期创建成功并已激活');
|
||||
closeModal('createSemesterModal');
|
||||
loadSemesters();
|
||||
} else {
|
||||
showToast(res?.message || '创建失败', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function activateSemester(semesterId) {
|
||||
if (!confirm('确认将此学期设为当前活跃学期?其他学期将被设为非活跃。')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await apiPut(`/api/semester/activate/${semesterId}`);
|
||||
if (res && res.success) {
|
||||
showToast(res.message || '已设为当前学期');
|
||||
loadSemesters();
|
||||
} else {
|
||||
showToast(res?.message || '操作失败', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function showArchiveConfirm(semesterId, semesterName) {
|
||||
archiveSemesterId = semesterId;
|
||||
document.getElementById('archiveConfirmText').innerHTML =
|
||||
`确定要归档学期 "<strong>${semesterName}</strong>" 吗?<br>归档后将保存所有学生的当前操行分快照,该学期数据将变为只读。`;
|
||||
document.getElementById('archiveConfirmModal').style.display = 'flex';
|
||||
}
|
||||
|
||||
async function confirmArchive() {
|
||||
if (!archiveSemesterId) return;
|
||||
|
||||
const res = await apiPost(`/api/semester/archive/${archiveSemesterId}`);
|
||||
if (res && res.success) {
|
||||
showToast(res.message || '归档成功');
|
||||
closeModal('archiveConfirmModal');
|
||||
archiveSemesterId = null;
|
||||
loadSemesters();
|
||||
} else {
|
||||
showToast(res?.message || '归档失败', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function viewArchiveData(semesterId, semesterName, page) {
|
||||
page = page || 1;
|
||||
archivePage = page;
|
||||
document.getElementById('archiveDataTitle').textContent = `归档数据 - ${semesterName}`;
|
||||
|
||||
const res = await apiGet(`/api/semester/archive/${semesterId}/records`, {
|
||||
page: page, page_size: 50
|
||||
});
|
||||
|
||||
if (res && res.success) {
|
||||
const data = res.data || {};
|
||||
const archives = data.archives || [];
|
||||
let html = '';
|
||||
archives.forEach(a => {
|
||||
html += `<tr>
|
||||
<td>${a.rank_position || '-'}</td>
|
||||
<td>${escapeHtml(a.student_no)}</td>
|
||||
<td>${escapeHtml(a.student_name)}</td>
|
||||
<td>${a.final_points}</td>
|
||||
</tr>`;
|
||||
});
|
||||
if (archives.length === 0) {
|
||||
html = '<tr><td colspan="4" style="text-align:center;">暂无归档数据</td></tr>';
|
||||
}
|
||||
document.getElementById('archiveDataList').innerHTML = html;
|
||||
|
||||
archiveTotalPages = data.total_pages || 1;
|
||||
renderArchivePagination(semesterId, semesterName);
|
||||
document.getElementById('archiveDataModal').style.display = 'flex';
|
||||
} else {
|
||||
showToast(res?.message || '获取归档数据失败', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function renderArchivePagination(semesterId, semesterName) {
|
||||
const container = document.getElementById('archivePagination');
|
||||
if (!container) return;
|
||||
if (archiveTotalPages <= 1) {
|
||||
container.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
let html = '';
|
||||
for (let i = 1; i <= archiveTotalPages; i++) {
|
||||
if (i === archivePage) {
|
||||
html += `<span class="active">${i}</span>`;
|
||||
} else {
|
||||
html += `<a href="#" onclick="viewArchiveData(${semesterId}, '${escapeHtml(semesterName)}', ${i}); return false;">${i}</a>`;
|
||||
}
|
||||
}
|
||||
container.innerHTML = html;
|
||||
}
|
||||
|
||||
function closeModal(modalId) {
|
||||
const modal = document.getElementById(modalId);
|
||||
if (modal) modal.style.display = 'none';
|
||||
}
|
||||
|
||||
loadSemesters();
|
||||
</script>
|
||||
<script src="/assets/js/admin.js"></script>
|
||||
|
||||
<?php include __DIR__ . '/../includes/footer.php'; ?>
|
||||
@@ -16,6 +16,9 @@
|
||||
<?php if ($role === '班主任'): ?>
|
||||
<a href="/admin/admins.php" class="nav-item<?php echo $current_page === 'admins' ? ' active' : ''; ?>">管理员管理</a>
|
||||
<?php endif; ?>
|
||||
<?php if ($role === '班主任'): ?>
|
||||
<a href="/admin/semesters.php" class="nav-item<?php echo $current_page === 'semesters' ? ' active' : ''; ?>">学期管理</a>
|
||||
<?php endif; ?>
|
||||
<a href="/admin/history.php" class="nav-item<?php echo $current_page === 'history' ? ' active' : ''; ?>">历史记录</a>
|
||||
<a href="/admin/password.php" class="nav-item<?php echo $current_page === 'password' ? ' active' : ''; ?>">修改密码</a>
|
||||
</div>
|
||||
|
||||
@@ -73,14 +73,17 @@ async function loadDashboard() {
|
||||
document.getElementById('totalPoints').textContent = res.data.total_points;
|
||||
}
|
||||
|
||||
// 加载排名信息
|
||||
// 加载排名信息
|
||||
const rankRes = await apiGet('/api/parent/child/ranking');
|
||||
if (rankRes && rankRes.success) {
|
||||
const rank = rankRes.data.rank;
|
||||
const total = rankRes.data.total_students;
|
||||
document.getElementById('studentRank').textContent = rank ? `第${rank}名` : '--';
|
||||
if (rank) {
|
||||
document.getElementById('studentRank').textContent = `第${rank}名`;
|
||||
} else {
|
||||
document.getElementById('studentRank').textContent = '--';
|
||||
}
|
||||
}
|
||||
|
||||
// 显示初始分提示
|
||||
const initialPoints = window.STUDENT_INITIAL_POINTS || 60;
|
||||
document.getElementById('initialPointsHint').textContent = `初始操行分为 ${initialPoints} 分`;
|
||||
|
||||
@@ -77,6 +77,7 @@ include __DIR__ . '/../includes/header.php';
|
||||
<button class="nav-item" data-page="conduct">操行分详情</button>
|
||||
<button class="nav-item" data-page="homework">作业情况</button>
|
||||
<button class="nav-item" data-page="attendance">考勤记录</button>
|
||||
<a href="/student/semester_history.php" class="nav-item">学期记录</a>
|
||||
<button class="nav-item" data-page="password">修改密码</button>
|
||||
</div>
|
||||
|
||||
@@ -301,7 +302,7 @@ include __DIR__ . '/../includes/header.php';
|
||||
const ranking = rankingRes.data.ranking || [];
|
||||
const rank = ranking.find(s => s.student_id === parseInt(STUDENT_ID));
|
||||
if (rank) {
|
||||
document.getElementById('studentRank').textContent = rank.rank;
|
||||
document.getElementById('studentRank').textContent = `第${rank.rank}名`;
|
||||
} else {
|
||||
document.getElementById('studentRank').textContent = '--';
|
||||
}
|
||||
|
||||
189
frontend/student/semester_history.php
Normal file
189
frontend/student/semester_history.php
Normal file
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
/**
|
||||
* 班级操行分管理系统 - 学生端学期记录页面
|
||||
*
|
||||
* 开发者: Canglan
|
||||
* 联系方式: admin@sea-studio.top
|
||||
* 版权归属: Sea Network Technology Studio
|
||||
* 许可证: MIT License
|
||||
*
|
||||
* 版权所有 © Sea Network Technology Studio
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../config.php';
|
||||
|
||||
// 检查登录状态
|
||||
if (!isset($_SESSION['user_id']) || $_SESSION['user_type'] !== 'student') {
|
||||
header('Location: /index.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
$page_title = '学期记录';
|
||||
$student_id = $_SESSION['student_id'];
|
||||
include __DIR__ . '/../includes/header.php';
|
||||
?>
|
||||
|
||||
<style>
|
||||
.nav .nav-item {
|
||||
display: inline-block;
|
||||
padding: 8px 16px;
|
||||
margin: 0 4px;
|
||||
border: none;
|
||||
background: none;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
border-bottom: 2px solid transparent;
|
||||
}
|
||||
.nav .nav-item.active {
|
||||
color: #667eea;
|
||||
border-bottom-color: #667eea;
|
||||
font-weight: bold;
|
||||
}
|
||||
.semester-card {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin-bottom: 16px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
|
||||
}
|
||||
.semester-card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
.semester-name {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
.semester-date {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
.semester-stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
.semester-stat-item {
|
||||
padding: 8px;
|
||||
}
|
||||
.semester-stat-value {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #667eea;
|
||||
}
|
||||
.semester-stat-label {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
color: #999;
|
||||
}
|
||||
.empty-state-icon {
|
||||
font-size: 48px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.archived-badge {
|
||||
display: inline-block;
|
||||
padding: 2px 8px;
|
||||
background: #e8f5e9;
|
||||
color: #388e3c;
|
||||
border-radius: 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="nav">
|
||||
<a href="/student/dashboard.php" class="nav-item">首页</a>
|
||||
<a href="/student/dashboard.php" class="nav-item">操行分详情</a>
|
||||
<a href="/student/dashboard.php" class="nav-item">作业情况</a>
|
||||
<a href="/student/dashboard.php" class="nav-item">考勤记录</a>
|
||||
<a href="/student/semester_history.php" class="nav-item active">学期记录</a>
|
||||
<a href="/student/dashboard.php" class="nav-item">修改密码</a>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="card">
|
||||
<div class="card-title">历史学期记录</div>
|
||||
<div id="semesterRecords"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
async function loadSemesterRecords() {
|
||||
try {
|
||||
const res = await apiGet('/api/student/semester-records');
|
||||
if (res && res.success) {
|
||||
const records = res.data.records || [];
|
||||
const container = document.getElementById('semesterRecords');
|
||||
|
||||
if (records.length === 0) {
|
||||
container.innerHTML = `
|
||||
<div class="empty-state">
|
||||
<div class="empty-state-icon">📋</div>
|
||||
<p>暂无历史学期记录</p>
|
||||
<p style="font-size: 13px; margin-top: 8px;">学期归档后,您的成绩记录将显示在这里</p>
|
||||
</div>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
let html = '';
|
||||
records.forEach(record => {
|
||||
const dateRange = record.start_date && record.end_date
|
||||
? `${record.start_date} ~ ${record.end_date}`
|
||||
: '';
|
||||
html += `
|
||||
<div class="semester-card">
|
||||
<div class="semester-card-header">
|
||||
<div>
|
||||
<div class="semester-name">${escapeHtml(record.semester_name)}</div>
|
||||
${dateRange ? `<div class="semester-date">${dateRange}</div>` : ''}
|
||||
</div>
|
||||
<span class="archived-badge">已归档</span>
|
||||
</div>
|
||||
<div class="semester-stats">
|
||||
<div class="semester-stat-item">
|
||||
<div class="semester-stat-value">${record.final_points}</div>
|
||||
<div class="semester-stat-label">最终操行分</div>
|
||||
</div>
|
||||
<div class="semester-stat-item">
|
||||
<div class="semester-stat-value">${record.rank_position || '--'}</div>
|
||||
<div class="semester-stat-label">班级排名</div>
|
||||
</div>
|
||||
<div class="semester-stat-item">
|
||||
<div class="semester-stat-value">${record.total_students || '--'}</div>
|
||||
<div class="semester-stat-label">班级总人数</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
container.innerHTML = html;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载学期记录失败:', error);
|
||||
document.getElementById('semesterRecords').innerHTML = `
|
||||
<div class="empty-state">
|
||||
<div class="empty-state-icon">⚠️</div>
|
||||
<p>加载失败,请稍后重试</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
loadSemesterRecords();
|
||||
</script>
|
||||
<script src="/assets/js/student.js"></script>
|
||||
|
||||
<?php include __DIR__ . '/../includes/footer.php'; ?>
|
||||
Reference in New Issue
Block a user