/** * 班级操行分管理系统 - 管理端JS * * 开发者: Canglan * 联系方式: admin@sea-studio.top * 版权归属: Sea Network Technology Studio * 许可证: MIT License * * 版权所有 © Sea Network Technology Studio */ // 全局变量(使用 var 避免与页面级 let 重复声明冲突) var selectedStudentIds = []; var currentPage = 1; var totalPages = 1; var currentHistoryPage = 1; // 显示批量加减分模态框 function showBatchPointsModal() { selectedStudentIds = []; document.querySelectorAll('.student-checkbox:checked').forEach(cb => { selectedStudentIds.push(parseInt(cb.dataset.id)); }); if (selectedStudentIds.length === 0) { showToast('请先选择学生', 'warning'); return; } document.getElementById('selectedStudentsCount').innerHTML = `${selectedStudentIds.length} 人`; document.getElementById('pointsChange').value = ''; document.getElementById('pointsReason').value = ''; document.getElementById('batchPointsModal').style.display = 'flex'; } // 提交批量加减分 async function submitBatchPoints() { const pointsChange = parseInt(document.getElementById('pointsChange').value); const reason = document.getElementById('pointsReason').value; if (isNaN(pointsChange) || pointsChange === 0) { showToast('分值不能为0', 'error'); return; } if (!reason.trim()) { showToast('请填写原因', 'error'); return; } const res = await apiPost('/api/admin/conduct/add', { student_ids: selectedStudentIds, points_change: pointsChange, reason: reason }); if (res && res.success) { showToast(`操作成功: ${res.data.success_count} 人成功`); closeModal('batchPointsModal'); loadStudents(); if (typeof loadConductStudents === 'function') loadConductStudents(); } else { showToast(res?.message || '操作失败', 'error'); } } // 显示导入模态框 function showImportModal() { document.getElementById('importModal').style.display = 'flex'; document.getElementById('importPreview').style.display = 'none'; document.getElementById('importPreview').innerHTML = ''; document.getElementById('importBtn').style.display = 'none'; document.getElementById('importFile').value = ''; } // 预览导入文件 function previewImportFile() { const file = document.getElementById('importFile').files[0]; if (!file) return; const reader = new FileReader(); reader.onload = function(e) { try { const data = JSON.parse(e.target.result); const students = data.students || []; let html = '
| 学号 | 姓名 | 家长手机号 | 初始密码 | '; html += '
|---|---|---|---|
| ${escapeHtml(s.student_no || '')} | ${escapeHtml(s.name || '')} | ${escapeHtml(s.parent_phone || '')} | ${escapeHtml(s.password || '123456')} |
共 ${students.length} 条记录,初始操行分默认为60分
`; document.getElementById('importPreview').innerHTML = html; document.getElementById('importPreview').style.display = 'block'; document.getElementById('importBtn').style.display = 'inline-block'; } catch (error) { showToast('JSON格式错误', 'error'); } }; reader.readAsText(file); } // 执行导入 async function doImport() { const file = document.getElementById('importFile').files[0]; if (!file) { showToast('请选择文件', 'warning'); return; } const formData = new FormData(); formData.append('file', file); const token = getToken(); const response = await fetch(`${API_BASE_URL}/api/admin/students/import`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}` }, body: formData }); const result = await response.json(); if (result.success) { showToast(result.message); closeModal('importModal'); loadStudents(); // 显示详细导入结果 if (result.data && result.data.results) { const failedList = result.data.results.filter(r => !r.success); if (failedList.length > 0) { let detail = '失败详情:\n'; failedList.forEach(r => { detail += `${r.student_no || '未知'}: ${r.error}\n`; }); alert(detail); } } } else { showToast(result.message, 'error'); } } // 显示新增学生模态框 function showAddStudentModal() { document.getElementById('addStudentModal').style.display = 'flex'; document.getElementById('addStudentForm').reset(); } // 提交新增学生 async function submitAddStudent() { const studentNo = document.getElementById('studentNo').value.trim(); const name = document.getElementById('studentName').value.trim(); const parentPhone = document.getElementById('parentPhone').value.trim(); if (!studentNo || !name) { showToast('请填写学号和姓名', 'warning'); return; } const res = await apiPost('/api/admin/students', { student_no: studentNo, name: name, parent_phone: parentPhone }); if (res && res.success) { showToast('学生添加成功'); closeModal('addStudentModal'); loadStudents(); } else { showToast(res?.message || '添加失败', 'error'); } } // 显示添加管理员模态框 function showAddAdminModal() { document.getElementById('addAdminModal').style.display = 'flex'; document.getElementById('addAdminForm')?.reset(); } // 提交添加管理员 async function submitAddAdmin() { const username = document.getElementById('adminUsername').value.trim(); const realName = document.getElementById('adminRealName').value.trim(); const password = document.getElementById('adminPassword').value; const roleType = document.getElementById('adminRole').value; if (!username || !realName || !roleType) { showToast('请填写完整信息', 'warning'); return; } const res = await apiPost('/api/admin/add', { username: username, real_name: realName, password: password || undefined, role_type: roleType }); if (res && res.success) { let msg = `管理员 ${res.data.username} 添加成功`; if (res.data.password) msg += `,密码: ${res.data.password}`; showToast(msg); closeModal('addAdminModal'); loadAdmins(); } else { showToast(res?.message || '添加失败', 'error'); } } // 显示添加科目模态框 function showAddSubjectModal() { document.getElementById('addSubjectModal').style.display = 'flex'; document.getElementById('addSubjectForm').reset(); } // 提交添加科目 async function submitAddSubject() { const subjectName = document.getElementById('subjectName').value.trim(); const subjectCode = document.getElementById('subjectCode').value.trim(); if (!subjectName) { showToast('请填写科目名称', 'warning'); return; } const res = await apiPost('/api/subject/create', { subject_name: subjectName, subject_code: subjectCode }); if (res && res.success) { showToast('科目添加成功'); closeModal('addSubjectModal'); loadSubjects(); } else { showToast(res?.message || '添加失败', 'error'); } } // 撤销扣分记录 async function revokeRecord(recordId) { if (!confirm('确定要撤销这条记录吗?撤销后学生分数将恢复。')) return; const res = await apiPost('/api/admin/conduct/revoke', { record_id: recordId }); if (res && res.success) { showToast('撤销成功'); loadHistory(currentHistoryPage); } else { showToast(res?.message || '撤销失败', 'error'); } } // 反撤销(恢复)记录 async function restoreRecord(recordId) { if (!confirm('确定要反撤销这条记录吗?分数变动将重新生效。')) return; const res = await apiPost('/api/admin/conduct/restore', { record_id: recordId }); if (res && res.success) { showToast('反撤销成功'); loadHistory(currentHistoryPage); } else { showToast(res?.message || '反撤销失败', 'error'); } } // 关闭模态框 function closeModal(modalId) { const modal = document.getElementById(modalId); if (modal) { modal.style.display = 'none'; } } // HTML转义 function escapeHtml(str) { if (!str) return ''; return str.replace(/[&<>]/g, function(m) { if (m === '&') return '&'; if (m === '<') return '<'; if (m === '>') return '>'; return m; }); } // 全选功能 function toggleSelectAll() { const selectAll = document.getElementById('selectAll'); if (selectAll) { document.querySelectorAll('.student-checkbox').forEach(cb => { cb.checked = selectAll.checked; }); } } // 绑定文件选择事件 document.addEventListener('DOMContentLoaded', () => { const fileInput = document.getElementById('importFile'); if (fileInput) { fileInput.addEventListener('change', previewImportFile); } }); // ===== 学生编辑/删除/重置密码 ===== function showEditStudentModal(studentId, studentNo, name, phone) { document.getElementById('editStudentId').value = studentId; document.getElementById('editStudentNo').value = studentNo; document.getElementById('editStudentName').value = name; document.getElementById('editStudentPhone').value = phone || ''; document.getElementById('editStudentModal').style.display = 'flex'; } async function submitEditStudent() { const studentId = document.getElementById('editStudentId').value; const name = document.getElementById('editStudentName').value.trim(); const phone = document.getElementById('editStudentPhone').value.trim(); if (!name) { showToast('请输入姓名', 'warning'); return; } const res = await apiPut(`/api/admin/students/${studentId}`, { name: name, parent_phone: phone || null }); if (res && res.success) { showToast('学生信息更新成功'); closeModal('editStudentModal'); location.reload(); } else { showToast(res?.message || '更新失败', 'error'); } } function showResetStudentPasswordModal(studentId, name) { document.getElementById('resetStudentId').value = studentId; document.getElementById('resetStudentInfo').textContent = `正在重置学生 "${name}" 的密码`; document.getElementById('newStudentPassword').value = ''; document.getElementById('resetStudentPasswordModal').style.display = 'flex'; } async function submitResetStudentPassword() { const studentId = document.getElementById('resetStudentId').value; const newPassword = document.getElementById('newStudentPassword').value; if (!newPassword || newPassword.length < 6) { showToast('密码至少6位', 'warning'); return; } const res = await apiPost(`/api/admin/students/reset-password/${studentId}`, { new_password: newPassword }); if (res && res.success) { showToast('密码重置成功'); closeModal('resetStudentPasswordModal'); } else { showToast(res?.message || '重置失败', 'error'); } } async function deleteStudent(studentId, name) { if (!confirm(`确定要删除学生 "${name}" 吗?删除后学生账号将被禁用。`)) return; const res = await apiDelete(`/api/admin/students/${studentId}`); if (res && res.success) { showToast('学生删除成功'); location.reload(); } else { showToast(res?.message || '删除失败', 'error'); } }