feat: 多班级版 v2.0 - Go后端重写 + 43轮代码审查

- 后端从 Python FastAPI 重写为 Go Gin(端口 56789)
- 多班级完全隔离
- 超级管理员独立登录
- 课代表作业管理、排行榜分项排行
- 角色加减分上下限可配置
- 家长改密功能(可开关)
- 周度/月度重置功能
- MySQL 5.7 兼容
- 43轮代码审查+全部修复
- Apache 2.0 许可证
This commit is contained in:
2026-06-22 10:06:10 +08:00
parent 4084afc53c
commit d6dec878bd
214 changed files with 12622 additions and 9725 deletions

View File

@@ -1,5 +1,5 @@
/**
* 班级操行分管理系统 - 操行分管理页JS
* 多班级版班级管理系统 - 操行分管理页JS
*
* 开发者: Canglan
* 版权归属: Sea Network Technology Studio
@@ -20,7 +20,7 @@ async function loadStudents() {
<td>${escapeHtml(student.student_no)}</td>
<td><a href="/admin/history.php?student_id=${student.student_id}" class="link">${escapeHtml(student.name)}</a></td>
<td>${student.total_points}</td>
<td><button class="btn btn-sm btn-outline" onclick="showSinglePointsModal(${student.student_id}, '${escapeHtml(student.name)}')">加减分</button></td>
<td><button class="btn btn-sm btn-outline js-single-points" data-student-id="${student.student_id}" data-student-name="${escapeHtml(student.name)}">加减分</button></td>
</tr>`;
});
if (res.data.students.length === 0) {
@@ -39,7 +39,7 @@ function showSinglePointsModal(studentId, studentName) {
}
async function exportMoralityRecords() {
showToast('正在导出德育分记录...', 'info');
showToast('正在导出操行分记录...', 'info');
try {
const studentsRes = await apiGet('/api/admin/students', { page_size: 1000 });
@@ -54,13 +54,20 @@ async function exportMoralityRecords() {
return;
}
const historyRes = await apiGet('/api/admin/conduct/history', { page: 1, page_size: 1000 });
if (!historyRes || !historyRes.success) {
showToast('获取历史记录失败', 'error');
return;
}
const allRecords = historyRes.data.records || [];
const allRecords = [];
let page = 1;
let totalPages = 1;
do {
const historyRes = await apiGet('/api/admin/conduct/history', { page: page, page_size: 500 });
if (!historyRes || !historyRes.success) {
showToast('获取历史记录失败', 'error');
return;
}
const records = historyRes.data.records || [];
allRecords.push(...records);
totalPages = historyRes.data.total_pages || 1;
page++;
} while (page <= totalPages);
const recordsByStudent = {};
allRecords.forEach(record => {
@@ -90,7 +97,7 @@ async function exportMoralityRecords() {
if (field === null || field === undefined) return '';
let str = String(field).replace(/[\r\n]+/g, ' ');
str = str.replace(/"/g, '""');
if (/[\,\;\"\s]/.test(str)) {
if (/[\,\"\s]/.test(str)) {
str = '"' + str + '"';
}
return str;
@@ -106,7 +113,7 @@ async function exportMoralityRecords() {
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = `德育分记录_${new Date().toISOString().slice(0,10)}.csv`;
link.download = `操行分记录_${new Date().toISOString().slice(0,10)}.csv`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
@@ -119,7 +126,7 @@ async function exportMoralityRecords() {
}
}
// 宿舍集体加分相关
var dormitoryStudentIds = [];
let dormitoryStudentIds = [];
async function showDormitoryPointsModal() {
dormitoryStudentIds = [];
@@ -196,6 +203,11 @@ async function submitDormitoryPoints() {
return;
}
if (Math.abs(pointsChange) > 100) {
showToast('分值绝对值不能超过100', 'error');
return;
}
if (!reason.trim()) {
showToast('请填写原因', 'error');
return;
@@ -204,7 +216,8 @@ async function submitDormitoryPoints() {
const data = {
student_ids: dormitoryStudentIds,
points_change: pointsChange,
reason: reason
reason: reason,
related_type: 'manual'
};
const res = await apiPost('/api/admin/conduct/add', data);
@@ -220,6 +233,16 @@ async function submitDormitoryPoints() {
loadStudents();
document.getElementById('studentList').addEventListener('click', function(e) {
const btn = e.target.closest('.js-single-points');
if (btn) {
showSinglePointsModal(
parseInt(btn.dataset.studentId, 10),
btn.dataset.studentName
);
}
});
window.loadStudents = loadStudents;
window.showSinglePointsModal = showSinglePointsModal;
window.exportMoralityRecords = exportMoralityRecords;