v2.2更新
This commit is contained in:
@@ -132,13 +132,8 @@ function formatDateTime(dateStr) {
|
||||
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')} ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
function getStatusBadge(status, type = 'homework') {
|
||||
function getStatusBadge(status, type = 'attendance') {
|
||||
const statusMap = {
|
||||
homework: {
|
||||
'submitted': '已提交',
|
||||
'not_submitted': '未提交',
|
||||
'late': '迟交'
|
||||
},
|
||||
attendance: {
|
||||
'present': '出勤',
|
||||
'absent': '缺勤',
|
||||
@@ -146,15 +141,13 @@ function getStatusBadge(status, type = 'homework') {
|
||||
'leave': '请假'
|
||||
}
|
||||
};
|
||||
const texts = statusMap[type] || statusMap.homework;
|
||||
const texts = statusMap[type] || statusMap.attendance;
|
||||
const text = texts[status] || status;
|
||||
let className = 'status-badge ';
|
||||
switch (status) {
|
||||
case 'submitted':
|
||||
case 'present':
|
||||
className += 'status-submitted';
|
||||
break;
|
||||
case 'not_submitted':
|
||||
case 'absent':
|
||||
className += 'status-not_submitted';
|
||||
break;
|
||||
|
||||
@@ -118,11 +118,113 @@ async function exportMoralityRecords() {
|
||||
console.error('导出失败:', err);
|
||||
}
|
||||
}
|
||||
// 宿舍集体加分相关
|
||||
var dormitoryStudentIds = [];
|
||||
|
||||
async function showDormitoryPointsModal() {
|
||||
dormitoryStudentIds = [];
|
||||
document.getElementById('dormitorySelect').innerHTML = '<option value="">-- 请选择宿舍 --</option>';
|
||||
document.getElementById('dormitoryStudentsGroup').style.display = 'none';
|
||||
document.getElementById('dormitoryStudentsList').innerHTML = '';
|
||||
document.getElementById('dormitoryPointsChange').value = '';
|
||||
document.getElementById('dormitoryPointsReason').value = '';
|
||||
|
||||
// 加载宿舍列表
|
||||
const res = await apiGet('/api/admin/students/dormitories');
|
||||
if (res && res.success && res.data.dormitories) {
|
||||
const select = document.getElementById('dormitorySelect');
|
||||
res.data.dormitories.forEach(d => {
|
||||
const option = document.createElement('option');
|
||||
option.value = d;
|
||||
option.textContent = d;
|
||||
select.appendChild(option);
|
||||
});
|
||||
}
|
||||
|
||||
document.getElementById('dormitoryPointsModal').style.display = 'flex';
|
||||
}
|
||||
|
||||
async function onDormitorySelected() {
|
||||
const dormitory = document.getElementById('dormitorySelect').value;
|
||||
const studentsGroup = document.getElementById('dormitoryStudentsGroup');
|
||||
const studentsList = document.getElementById('dormitoryStudentsList');
|
||||
const studentsCount = document.getElementById('dormitoryStudentsCount');
|
||||
|
||||
dormitoryStudentIds = [];
|
||||
studentsList.innerHTML = '';
|
||||
|
||||
if (!dormitory) {
|
||||
studentsGroup.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
// 加载该宿舍的学生
|
||||
const res = await apiGet('/api/admin/students', { dormitory_number: dormitory, page_size: 1000 });
|
||||
if (res && res.success && res.data.students) {
|
||||
const students = res.data.students;
|
||||
if (students.length === 0) {
|
||||
studentsList.innerHTML = '<p style="color: var(--text-secondary);">该宿舍暂无学生</p>';
|
||||
studentsCount.textContent = '';
|
||||
} else {
|
||||
students.forEach(s => {
|
||||
dormitoryStudentIds.push(s.student_id);
|
||||
const div = document.createElement('div');
|
||||
div.style.cssText = 'display: flex; justify-content: space-between; padding: 4px 0; border-bottom: 1px solid var(--border-color);';
|
||||
div.innerHTML = `<span>${escapeHtml(s.name)}</span><span style="color: var(--text-secondary);">${escapeHtml(s.student_no)}</span>`;
|
||||
studentsList.appendChild(div);
|
||||
});
|
||||
studentsCount.textContent = `共 ${students.length} 人`;
|
||||
}
|
||||
studentsGroup.style.display = 'block';
|
||||
} else {
|
||||
studentsList.innerHTML = '<p style="color: var(--text-secondary);">加载失败</p>';
|
||||
studentsGroup.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
async function submitDormitoryPoints() {
|
||||
if (dormitoryStudentIds.length === 0) {
|
||||
showToast('该宿舍没有学生', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
const pointsChange = parseInt(document.getElementById('dormitoryPointsChange').value);
|
||||
const reason = document.getElementById('dormitoryPointsReason').value;
|
||||
|
||||
if (isNaN(pointsChange) || pointsChange === 0) {
|
||||
showToast('分值不能为0', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!reason.trim()) {
|
||||
showToast('请填写原因', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const data = {
|
||||
student_ids: dormitoryStudentIds,
|
||||
points_change: pointsChange,
|
||||
reason: reason
|
||||
};
|
||||
|
||||
const res = await apiPost('/api/admin/conduct/add', data);
|
||||
|
||||
if (res && res.success) {
|
||||
showToast(`操作成功: ${res.data.success_count} 人成功`);
|
||||
closeModal('dormitoryPointsModal');
|
||||
loadStudents();
|
||||
} else {
|
||||
showToast(res?.message || '操作失败', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
loadStudents();
|
||||
|
||||
window.loadStudents = loadStudents;
|
||||
window.showSinglePointsModal = showSinglePointsModal;
|
||||
window.exportMoralityRecords = exportMoralityRecords;
|
||||
window.showDormitoryPointsModal = showDormitoryPointsModal;
|
||||
window.onDormitorySelected = onDormitorySelected;
|
||||
window.submitDormitoryPoints = submitDormitoryPoints;
|
||||
|
||||
})();
|
||||
|
||||
@@ -25,9 +25,15 @@ async function loadDashboard() {
|
||||
}
|
||||
|
||||
let quickActions = '';
|
||||
if (role === '班主任' || role === '班长' || role === '劳动委员' || role === '志愿委员') {
|
||||
if (role === '班主任' || role === '班长' || role === '学习委员' || role === '劳动委员' || role === '志愿委员') {
|
||||
quickActions += '<button class="btn btn-primary" onclick="location.href=\'/admin/conduct.php\'">操行分管理</button>';
|
||||
}
|
||||
if (role === '班主任' || role === '学习委员') {
|
||||
quickActions += '<button class="btn btn-primary" onclick="location.href=\'/admin/homework.php\'">作业扣分</button>';
|
||||
}
|
||||
if (role === '班主任' || role === '考勤委员') {
|
||||
quickActions += '<button class="btn btn-primary" onclick="location.href=\'/admin/attendance.php\'">考勤管理</button>';
|
||||
}
|
||||
if (role === '班主任') {
|
||||
quickActions += '<button class="btn btn-outline" onclick="location.href=\'/admin/students.php\'">导入学生</button>';
|
||||
quickActions += '<button class="btn btn-secondary" onclick="location.href=\'/admin/conduct.php\'">导出德育分记录</button>';
|
||||
|
||||
@@ -40,7 +40,7 @@ async function loadHistory(page = 1) {
|
||||
end_date: endDate
|
||||
};
|
||||
if (studentId) params.student_id = studentId;
|
||||
if (relatedType && !isGrouped) params.related_type = relatedType;
|
||||
if (relatedType) params.related_type = relatedType;
|
||||
if (isGrouped) params.grouped = true;
|
||||
|
||||
const res = await apiGet('/api/admin/conduct/history', params);
|
||||
|
||||
@@ -146,7 +146,7 @@
|
||||
const students = data.students || [];
|
||||
|
||||
let html = '<h4>预览数据</h4><div class="table-wrapper"><table><thead><tr>';
|
||||
html += '<th>学号</th><th>姓名</th><th>家长手机号</th><th>初始密码</th>';
|
||||
html += '<th>学号</th><th>姓名</th><th>家长手机号</th><th>宿舍号</th><th>初始密码</th>';
|
||||
html += '</tr></thead><tbody>';
|
||||
|
||||
students.forEach(s => {
|
||||
@@ -154,6 +154,7 @@
|
||||
<td>${escapeHtml(s.student_no || '')}</td>
|
||||
<td>${escapeHtml(s.name || '')}</td>
|
||||
<td>${escapeHtml(s.parent_phone || '')}</td>
|
||||
<td>${escapeHtml(s.dormitory_number || '-')}</td>
|
||||
<td>${escapeHtml(s.password || '123456')}</td>
|
||||
</tr>`;
|
||||
});
|
||||
|
||||
@@ -16,25 +16,18 @@ async function loadHomework() {
|
||||
const res = await apiGet(`/api/student/homework/${STUDENT_ID}`);
|
||||
if (res && res.success) {
|
||||
let html = '';
|
||||
res.data.homework.forEach(hw => {
|
||||
// 提交状态
|
||||
let statusDisplay = '-';
|
||||
if (hw.status) {
|
||||
statusDisplay = getStatusBadge(hw.status, 'homework');
|
||||
}
|
||||
// 扣分显示
|
||||
const pointsDisplay = hw.points ? `<span class="text-danger">${hw.points}分</span>` : '-';
|
||||
|
||||
res.data.homework.forEach(record => {
|
||||
const pointsClass = record.points_change > 0 ? 'plus' : 'minus';
|
||||
const pointsColor = record.points_change > 0 ? '#38a169' : '#e53e3e';
|
||||
html += `<tr>
|
||||
<td>${escapeHtml(hw.title)}</td>
|
||||
<td>${escapeHtml(hw.subject_name)}</td>
|
||||
<td>${hw.deadline || '-'}</td>
|
||||
<td>${statusDisplay}</td>
|
||||
<td>${pointsDisplay}</td>
|
||||
<td>${formatDateTime(record.created_at)}</td>
|
||||
<td style="color: ${pointsColor}; font-weight: bold;">${record.points_change > 0 ? '+' : ''}${record.points_change}</td>
|
||||
<td>${escapeHtml(record.reason)}</td>
|
||||
<td>${escapeHtml(record.recorder_name || '-')}</td>
|
||||
</tr>`;
|
||||
});
|
||||
if (res.data.homework.length === 0) {
|
||||
html = '<tr><td colspan="5" style="text-align:center; padding: 40px; color: #999;">📝 暂无作业记录</td></tr>';
|
||||
html = '<tr><td colspan="4" style="text-align:center; padding: 40px; color: #999;">📝 暂无作业扣分记录</td></tr>';
|
||||
}
|
||||
document.getElementById('homeworkList').innerHTML = html;
|
||||
}
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
/**
|
||||
* 班级操行分管理系统 - 科目管理页JS
|
||||
*
|
||||
* 开发者: Canglan
|
||||
* 版权归属: Sea Network Technology Studio
|
||||
*
|
||||
* 版权所有 © Sea Network Technology Studio
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
async function loadSubjects() {
|
||||
const res = await apiGet('/api/subject/list');
|
||||
if (res && res.success) {
|
||||
let html = '';
|
||||
res.data.subjects.forEach(sub => {
|
||||
html += `
|
||||
<div class="subject-item">
|
||||
<span class="subject-name">${escapeHtml(sub.subject_name)}</span>
|
||||
<span class="subject-code">${escapeHtml(sub.subject_code || '')}</span>
|
||||
<span class="subject-status ${sub.is_active ? 'subject-status-active' : 'subject-status-inactive'}">
|
||||
${sub.is_active ? '启用' : '禁用'}
|
||||
</span>
|
||||
<button class="btn btn-sm btn-outline" onclick="showEditSubjectModal(${sub.subject_id}, '${escapeHtml(sub.subject_name)}', '${escapeHtml(sub.subject_code || '')}', ${sub.sort_order || 0})">编辑</button>
|
||||
<button class="btn btn-sm btn-ghost" onclick="toggleSubject(${sub.subject_id}, ${!sub.is_active})">
|
||||
${sub.is_active ? '禁用' : '启用'}
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger" onclick="deleteSubject(${sub.subject_id})">删除</button>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
if (res.data.subjects.length === 0) {
|
||||
html = '<p style="text-align:center;padding:40px;">暂无科目,请点击"添加科目"</p>';
|
||||
}
|
||||
document.getElementById('subjectList').innerHTML = html;
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleSubject(subjectId, enable) {
|
||||
const res = await apiPut(`/api/subject/update/${subjectId}`, { is_active: enable });
|
||||
if (res && res.success) {
|
||||
showToast(enable ? '科目已启用' : '科目已禁用');
|
||||
loadSubjects();
|
||||
} else {
|
||||
showToast(res?.message || '操作失败', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteSubject(subjectId) {
|
||||
if (!confirm('确定要删除该科目吗?')) return;
|
||||
const res = await apiDelete('/api/subject/delete/' + subjectId);
|
||||
if (res && res.success) {
|
||||
showToast('科目删除成功');
|
||||
loadSubjects();
|
||||
} else {
|
||||
showToast(res?.message || '删除失败', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function showEditSubjectModal(subjectId, name, code, sortOrder) {
|
||||
document.getElementById('editSubjectId').value = subjectId;
|
||||
document.getElementById('editSubjectName').value = name;
|
||||
document.getElementById('editSubjectCode').value = code;
|
||||
document.getElementById('editSubjectSortOrder').value = sortOrder;
|
||||
document.getElementById('editSubjectModal').style.display = 'flex';
|
||||
}
|
||||
|
||||
async function submitEditSubject() {
|
||||
const subjectId = document.getElementById('editSubjectId').value;
|
||||
const subjectName = document.getElementById('editSubjectName').value.trim();
|
||||
const subjectCode = document.getElementById('editSubjectCode').value.trim();
|
||||
const sortOrder = document.getElementById('editSubjectSortOrder').value;
|
||||
|
||||
if (!subjectName) {
|
||||
showToast('请填写科目名称', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
const data = { subject_name: subjectName };
|
||||
if (subjectCode) data.subject_code = subjectCode;
|
||||
if (sortOrder !== '') data.sort_order = parseInt(sortOrder);
|
||||
|
||||
const res = await apiPut(`/api/subject/update/${subjectId}`, data);
|
||||
if (res && res.success) {
|
||||
showToast('科目更新成功');
|
||||
closeModal('editSubjectModal');
|
||||
loadSubjects();
|
||||
} else {
|
||||
showToast(res?.message || '更新失败', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
loadSubjects();
|
||||
|
||||
window.loadSubjects = loadSubjects;
|
||||
window.toggleSubject = toggleSubject;
|
||||
window.deleteSubject = deleteSubject;
|
||||
window.showEditSubjectModal = showEditSubjectModal;
|
||||
window.submitEditSubject = submitEditSubject;
|
||||
|
||||
})();
|
||||
Reference in New Issue
Block a user