/** * 班级操行分管理系统 - 历史记录页JS * * 开发者: Canglan * 版权归属: Sea Network Technology Studio * * 版权所有 © Sea Network Technology Studio */ (function() { 'use strict'; const role = window.PAGE_CONFIG.role; const currentUserId = window.PAGE_CONFIG.userId; let currentHistoryPage = 1; let totalHistoryPages = 1; function escapeHtml(str) { if (!str) return ''; var el = document.createElement('span'); el.appendChild(document.createTextNode(str)); return el.innerHTML; } async function loadStudentsForSelect() { const res = await apiGet('/api/admin/students', {page_size: 1000}); if (res && res.success) { let html = ''; res.data.students.forEach(s => { html += ''; }); document.getElementById('historyStudentId').innerHTML = html; } } // 筛选学生时自动取消合并记录 function onStudentFilterChange() { var studentId = document.getElementById('historyStudentId').value; if (studentId) { var grouped = document.getElementById('historyGrouped'); if (grouped) grouped.checked = false; } } // 折叠/展开筛选面板 function toggleFilterPanel() { var panel = document.getElementById('advancedFilters'); var btn = document.getElementById('filterToggleBtn'); if (panel.style.display === 'none') { panel.style.display = 'block'; btn.textContent = '收起筛选 ▲'; } else { panel.style.display = 'none'; btn.textContent = '展开筛选 ▼'; } } async function loadHistory(page) { page = page || 1; currentHistoryPage = page; var startDate = document.getElementById('historyStartDate').value; var endDate = document.getElementById('historyEndDate').value; var studentId = document.getElementById('historyStudentId').value; var reasonFilter = document.getElementById('historyReasonFilter').value; var isGrouped = document.getElementById('historyGrouped').checked; var statusFilter = document.getElementById('historyStatusFilter') ? document.getElementById('historyStatusFilter').value : ''; // 筛选学生时强制取消合并 if (studentId) isGrouped = false; var params = { page: page, page_size: 20, start_date: startDate, end_date: endDate }; if (studentId) params.student_id = studentId; if (reasonFilter) params.reason_prefix = reasonFilter; if (isGrouped) params.grouped = true; if (statusFilter !== '') params.is_revoked = parseInt(statusFilter); var res = await apiGet('/api/admin/conduct/history', params); if (res && res.success) { var nowrapStyle = ' style="white-space:nowrap;min-width:80px;"'; var headHtml = ''; if (isGrouped) { headHtml = '时间原因分值操作人涉及学生'; if (role === '班主任' || role === '班长') { headHtml += '操作'; } } else { headHtml = '时间学生分数变动原因操作人'; if (role === '班主任' || role === '班长' || role === '考勤委员') { headHtml += '操作'; } } document.getElementById('historyTableHead').innerHTML = headHtml; var html = ''; if (isGrouped) { res.data.records.forEach(function(record) { var pointsClass = record.points_change > 0 ? 'plus' : 'minus'; var names = record.student_names || ''; var allRevoked = record.all_revoked; var revokedStyle = allRevoked ? ' style="opacity:0.5;text-decoration:line-through;"' : ''; html += '' + '' + formatDateTime(record.created_at) + '' + '' + escapeHtml(record.reason) + '' + '' + (record.points_change > 0 ? '+' : '') + record.points_change + '×' + record.student_count + '' + '' + escapeHtml(record.recorder_name || '') + '' + '' + escapeHtml(names) + ''; if (role === '班主任' || role === '班长') { if (allRevoked) { html += '已撤销'; } else { html += ''; } } html += ''; }); if (res.data.records.length === 0) { var colSpan = (role === '班主任' || role === '班长') ? 6 : 5; html = '暂无记录'; } } else { res.data.records.forEach(function(record) { var pointsClass = record.points_change > 0 ? 'plus' : 'minus'; var revokedStyle = record.is_revoked == 1 ? ' style="opacity:0.5;text-decoration:line-through;"' : ''; html += '' + '' + formatDateTime(record.created_at) + '' + '' + escapeHtml(record.student_name) + '' + '' + (record.points_change > 0 ? '+' : '') + record.points_change + '' + '' + escapeHtml(record.reason) + '' + '' + escapeHtml(record.recorder_name) + ''; if (role === '班主任') { if (record.is_revoked == 1) { var revokerInfo = record.revoker_name ? '由 ' + escapeHtml(record.revoker_name) + ' 撤销' : '已撤销'; html += '' + revokerInfo + ''; } else { html += ''; } } else if (role === '班长') { if (record.is_revoked == 1) { var revokerInfo = record.revoker_name ? '由 ' + escapeHtml(record.revoker_name) + ' 撤销' : '已撤销'; html += '' + revokerInfo + ''; } else { html += ''; } } else if (role === '考勤委员') { if (record.is_revoked == 1) { html += '已撤销'; } else if (record.recorder_id == currentUserId) { html += ''; } else { html += '-'; } } html += ''; }); if (res.data.records.length === 0) { var colSpan = (role === '班主任' || role === '班长' || role === '考勤委员') ? 6 : 5; html = '暂无记录'; } } document.getElementById('historyList').innerHTML = html; totalHistoryPages = res.data.total_pages || 1; renderHistoryPagination(); } } function renderHistoryPagination() { renderSmartPagination('historyPagination', currentHistoryPage, totalHistoryPages, function(page) { loadHistory(page); }); } async function exportHistoryRecords() { var startDate = document.getElementById('historyStartDate').value; var endDate = document.getElementById('historyEndDate').value; var studentId = document.getElementById('historyStudentId').value; showToast('正在导出历史记录...', 'info'); try { var reasonFilter = document.getElementById('historyReasonFilter').value; var params = { page: 1, page_size: 1000 }; if (startDate) params.start_date = startDate; if (endDate) params.end_date = endDate; if (studentId) params.student_id = studentId; if (reasonFilter) params.reason_prefix = reasonFilter; var res = await apiGet('/api/admin/conduct/history', params); if (res && res.success && res.data.records) { var records = res.data.records; if (records.length === 0) { showToast('没有找到记录', 'warning'); return; } var csv = '\uFEFF'; csv += '时间,学号,姓名,分数变动,原因,操作人\n'; records.forEach(function(r) { csv += (r.created_at || '') + ',' + (r.student_no || '') + ',' + (r.student_name || '') + ',' + (r.points_change > 0 ? '+' : '') + r.points_change + ',' + (r.reason || '').replace(/,/g, ';') + ',' + (r.recorder_name || '') + '\n'; }); var blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); var url = URL.createObjectURL(blob); var link = document.createElement('a'); link.href = url; link.download = '历史记录_' + new Date().toISOString().slice(0,10) + '.csv'; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(url); showToast('导出成功,共' + records.length + '条记录'); } else { showToast('导出失败:' + (res && res.message || '未知错误'), 'error'); } } catch (err) { showToast('导出失败:' + err.message, 'error'); } } // 批量撤销合并记录(按条件查找并撤销) async function batchRevokeGrouped(reason, pointsChange, recorderName, createdAt) { if (!confirm('确定要撤销所有"' + reason + '"(' + (pointsChange > 0 ? '+' : '') + pointsChange + '分)的记录吗?')) return; showToast('正在批量撤销...', 'info'); try { var params = { page: 1, page_size: 1000, start_date: document.getElementById('historyStartDate').value, end_date: document.getElementById('historyEndDate').value, reason_prefix: reason.substring(0, 4), grouped: false }; var res = await apiGet('/api/admin/conduct/history', params); if (!res || !res.success || !res.data.records) { showToast('查询记录失败', 'error'); return; } var matchedIds = []; res.data.records.forEach(function(r) { if (r.reason === reason && r.points_change === pointsChange && r.is_revoked == 0) { matchedIds.push(r.record_id); } }); if (matchedIds.length === 0) { showToast('没有找到可撤销的记录', 'warning'); return; } var revokeRes = await apiPost('/api/admin/conduct/batch-revoke', { record_ids: matchedIds }); if (revokeRes && revokeRes.success) { showToast('批量撤销完成: ' + (revokeRes.data ? revokeRes.data.success_count : 0) + '条成功'); loadHistory(currentHistoryPage); } else { showToast(revokeRes && revokeRes.message || '批量撤销失败', 'error'); } } catch (err) { showToast('批量撤销失败: ' + err.message, 'error'); } } loadStudentsForSelect().then(function() { var urlParams = new URLSearchParams(window.location.search); var preStudentId = urlParams.get('student_id'); if (preStudentId) { document.getElementById('historyStudentId').value = preStudentId; onStudentFilterChange(); } loadHistory(); }); window.loadHistory = loadHistory; window.loadStudentsForSelect = loadStudentsForSelect; window.exportHistoryRecords = exportHistoryRecords; window.batchRevokeGrouped = batchRevokeGrouped; window.onStudentFilterChange = onStudentFilterChange; window.toggleFilterPanel = toggleFilterPanel; })();