fix: classes.html JavaScript syntax error - remove template literals in onclick attributes
- Replace template literals with string concatenation to avoid HTML attribute parsing issues - Add escape function for proper HTML attribute values
This commit is contained in:
+28
-67
@@ -236,8 +236,6 @@ function toggleMineFilter() {
|
|||||||
|
|
||||||
// 加载班级列表
|
// 加载班级列表
|
||||||
function loadClasses() {
|
function loadClasses() {
|
||||||
saveClassFilterState();
|
|
||||||
|
|
||||||
const activeFilter = document.getElementById('activeFilter').value;
|
const activeFilter = document.getElementById('activeFilter').value;
|
||||||
const mineFilter = document.getElementById('mineFilterBtn').classList.contains('active');
|
const mineFilter = document.getElementById('mineFilterBtn').classList.contains('active');
|
||||||
let url = '/api/classes?';
|
let url = '/api/classes?';
|
||||||
@@ -248,69 +246,27 @@ function loadClasses() {
|
|||||||
fetch(url).then(r => r.json()).then(classes => {
|
fetch(url).then(r => r.json()).then(classes => {
|
||||||
const tbody = document.querySelector('#classesTable tbody');
|
const tbody = document.querySelector('#classesTable tbody');
|
||||||
const isAdmin = currentUserRole === 'admin';
|
const isAdmin = currentUserRole === 'admin';
|
||||||
tbody.innerHTML = classes.map(c => `
|
tbody.innerHTML = classes.map(c => {
|
||||||
<tr>
|
const esc = (s) => s == null ? '' : String(s).replace(/'/g, "\\'").replace(/"/g, '"');
|
||||||
<td>${c.id}</td>
|
const level = c.level || '启蒙';
|
||||||
<td>${c.name}</td>
|
const desc = c.description || '';
|
||||||
<td>${c.level || '启蒙'}</td>
|
const teacherId = c.teacher_id || 'null';
|
||||||
<td>${c.description || '-'}</td>
|
const active = c.active ? 'true' : 'false';
|
||||||
<td>${c.active ? '<span class="badge bg-success">进行中</span>' : '<span class="badge bg-secondary">已结束</span>'}</td>
|
return '<tr>' +
|
||||||
<td><a href="#" onclick="viewClassStudents(${c.id})"> ${c.student_count}</a></td>
|
'<td>' + c.id + '</td>' +
|
||||||
<td>${c.created_at}</td>
|
'<td>' + esc(c.name) + '</td>' +
|
||||||
<td>
|
'<td>' + level + '</td>' +
|
||||||
<button type="button" class="btn btn-sm btn-success me-1" onclick="openAssignGoalModal(${c.id}, '${c.name}')">分配目标</button>
|
'<td>' + esc(desc) + '</td>' +
|
||||||
${isAdmin ? `<button type="button" class="btn btn-sm btn-primary me-1" onclick="editClass(${c.id}, '${c.name}', ${c.teacher_id || 'null'}, '${c.description || ''}', ${c.active}, '${c.level || '启蒙'}')">编辑</button>
|
'<td>' + (c.active ? '<span class="badge bg-success">进行中</span>' : '<span class="badge bg-secondary">已结束</span>') + '</td>' +
|
||||||
<button type="button" class="btn btn-sm btn-danger" onclick="deleteClass(${c.id})">删除</button>` : ''}
|
'<td><a href="#" onclick="viewClassStudents(' + c.id + ')">' + c.student_count + '</a></td>' +
|
||||||
</td>
|
'<td>' + c.created_at + '</td>' +
|
||||||
</tr>
|
'<td>' +
|
||||||
`).join('');
|
'<button type="button" class="btn btn-sm btn-success me-1" onclick="openAssignGoalModal(' + c.id + ', \'' + esc(c.name) + '\')">分配目标</button>' +
|
||||||
});
|
(isAdmin ? '<button type="button" class="btn btn-sm btn-primary me-1" onclick="editClass(' + c.id + ', \'' + esc(c.name) + '\', ' + teacherId + ', \'' + esc(desc) + '\', ' + active + ', \'' + level + '\')">编辑</button>' : '') +
|
||||||
}
|
'<button type="button" class="btn btn-sm btn-danger" onclick="deleteClass(' + c.id + ')">删除</button>' +
|
||||||
loadClasses();
|
'</td>' +
|
||||||
};
|
'</tr>';
|
||||||
|
}).join('');
|
||||||
// 我的班级筛选
|
|
||||||
function toggleMineFilter() {
|
|
||||||
const btn = document.getElementById('mineFilterBtn');
|
|
||||||
btn.classList.toggle('active');
|
|
||||||
if (btn.classList.contains('active')) {
|
|
||||||
btn.classList.remove('btn-outline-secondary');
|
|
||||||
btn.classList.add('btn-primary');
|
|
||||||
} else {
|
|
||||||
btn.classList.remove('btn-primary');
|
|
||||||
btn.classList.add('btn-outline-secondary');
|
|
||||||
}
|
|
||||||
loadClasses();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加载班级列表
|
|
||||||
function loadClasses() {
|
|
||||||
const activeFilter = document.getElementById('activeFilter').value;
|
|
||||||
const mineFilter = document.getElementById('mineFilterBtn').classList.contains('active');
|
|
||||||
let url = '/api/classes?';
|
|
||||||
if (activeFilter) url += 'active=' + activeFilter + '&';
|
|
||||||
if (mineFilter) url += 'mine=true&';
|
|
||||||
url = url.endsWith('&') ? url.slice(0, -1) : url;
|
|
||||||
url = url.endsWith('?') ? '/api/classes' : url;
|
|
||||||
fetch(url).then(r => r.json()).then(classes => {
|
|
||||||
const tbody = document.querySelector('#classesTable tbody');
|
|
||||||
const isAdmin = currentUserRole === 'admin';
|
|
||||||
tbody.innerHTML = classes.map(c => `
|
|
||||||
<tr>
|
|
||||||
<td>${c.id}</td>
|
|
||||||
<td>${c.name}</td>
|
|
||||||
<td>${c.level || '启蒙'}</td>
|
|
||||||
<td>${c.description || '-'}</td>
|
|
||||||
<td>${c.active ? '<span class="badge bg-success">进行中</span>' : '<span class="badge bg-secondary">已结束</span>'}</td>
|
|
||||||
<td><a href="#" onclick="viewClassStudents(${c.id})">${c.student_count}</a></td>
|
|
||||||
<td>${c.created_at}</td>
|
|
||||||
<td>
|
|
||||||
<button type="button" class="btn btn-sm btn-success me-1" onclick="openAssignGoalModal(${c.id}, '${c.name}')">分配目标</button>
|
|
||||||
${isAdmin ? `<button type="button" class="btn btn-sm btn-primary me-1" onclick="editClass(${c.id}, '${c.name}', ${c.teacher_id || 'null'}, '${c.description || ''}', ${c.active}, '${c.level || '启蒙'}')">编辑</button>
|
|
||||||
<button type="button" class="btn btn-sm btn-danger" onclick="deleteClass(${c.id})">删除</button>` : ''}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
`).join('');
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,7 +474,8 @@ document.getElementById('confirm-assign-goal').addEventListener('click', async (
|
|||||||
// 弹出确认框
|
// 弹出确认框
|
||||||
if (!confirm('将给班级所有学员分配此目标,确定吗?')) return;
|
if (!confirm('将给班级所有学员分配此目标,确定吗?')) return;
|
||||||
|
|
||||||
const res = await fetch(`/api/classes/${currentClassId}/goals`, {
|
const url = '/api/classes/' + currentClassId + '/goals';
|
||||||
|
const res = await fetch(url, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {'Content-Type': 'application/json'},
|
headers: {'Content-Type': 'application/json'},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
@@ -533,7 +490,11 @@ document.getElementById('confirm-assign-goal').addEventListener('click', async (
|
|||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
assignGoalModal.hide();
|
assignGoalModal.hide();
|
||||||
alert(data.message + (data.skipped_count ? `(${data.skipped_count}个学员已分配此目标,跳过)` : ''));
|
let msg = data.message;
|
||||||
|
if (data.skipped_count) {
|
||||||
|
msg += ' (' + data.skipped_count + '个学员已分配此目标跳过)';
|
||||||
|
}
|
||||||
|
alert(msg);
|
||||||
} else {
|
} else {
|
||||||
const err = await res.json();
|
const err = await res.json();
|
||||||
alert(err.error || '分配失败');
|
alert(err.error || '分配失败');
|
||||||
|
|||||||
Reference in New Issue
Block a user