You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

323 lines
11 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>知识点树形展示</title>
<style>
body {
margin: 0;
padding: 0;
font-family: Microsoft YaHei;
}
#treeTable {
width: 100%;
border-collapse: collapse;
}
#treeTable th, #treeTable td {
padding: 8px;
border: 1px solid #ddd;
}
#treeTable th {
background: #f5f5f5;
}
.level-0 td:first-child {
padding-left: 10px;
}
.level-1 td:first-child {
padding-left: 30px;
}
.level-2 td:first-child {
padding-left: 50px;
}
.level-3 td:first-child {
padding-left: 70px;
}
.toggle-icon {
cursor: pointer;
margin-right: 5px;
}
</style>
</head>
<body>
<table id="treeTable">
<thead>
<tr>
<th>知识点</th>
<th>先修知识</th>
<th>相关知识</th>
</tr>
</thead>
<tbody id="treeBody"></tbody>
</table>
<script src="/static/zTree/js/jquery-1.4.4.min.js"></script>
<script>
var treeData = [];
function toggleNode(nodeId) {
console.log('toggleNode', nodeId);
var node = findNodeById(treeData, nodeId);
if (node) {
node.open = !node.open;
// 强制重新渲染整个表格
updateTable();
}
}
function findParentTitle(node) {
if (!node || !node.parent_id) return '';
const parent = allNodes.find(n => n.id === node.parent_id);
return parent ? parent.title : '';
}
function findNodeById(nodes, id) {
for (const node of nodes) {
if (node.id === id) return node;
if (node.children) {
const found = findNodeById(node.children, id);
if (found) return found;
}
}
return null;
}
function updateTable() {
var html = '';
function buildRows(nodes, level) {
level = level || 0;
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
html += '<tr class="level-' + level + '">';
html += '<td style="padding-left:' + (level * 20) + 'px">';
if (node.children && node.children.length > 0) {
html += '<span class="toggle-icon" onclick="toggleNode(\'' + node.id + '\')">' +
(node.open ? '▼' : '▶') + '</span>';
} else {
html += '<span style="display:inline-block; width:16px;"></span>';
}
html += node.title + '</td>';
// 修改后的维护按钮显示逻辑
const isThirdLevel = node.parent_id && allNodes.find(n => n.id === node.parent_id)?.parent_id;
html += '<td>' + (node.prerequisite && node.prerequisite.length > 0 ?
node.prerequisite.map(p => p.title).join(', ') : '') +
(isThirdLevel ? '<button onclick="prerequisiteUpdate(\'' + node.id + '\')">维护</button>' : '') + '</td>';
html += '<td>' + (node.related || '') +
(isThirdLevel ? '<button onclick="relatedUpdate(\'' + node.id + '\')">维护</button>' : '') + '</td>';
html += '</tr>';
if (node.open && node.children && node.children.length > 0) {
buildRows(node.children, level + 1);
}
}
}
buildRows(treeData);
$("#treeBody").html(html);
}
// 初始化数据
// Move this declaration outside the AJAX call
var allNodes = [];
// Add flattenTree function definition before the AJAX call
function flattenTree(nodes) {
var result = [];
nodes.forEach(node => {
result.push(node);
if (node.children) {
result = result.concat(flattenTree(node.children));
}
});
return result;
}
$.ajax({
url: "/api/tree-data",
type: "GET",
success: function (res) {
if (res.code === 0) {
treeData = res.data;
allNodes = flattenTree(treeData);
updateTable();
}
}
});
// 修改prerequisiteUpdate和relatedUpdate函数
function prerequisiteUpdate(nodeId) {
const currentNodeId = nodeId; // Define the variable from function parameter
const modal = document.createElement('div');
modal.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: rgba(255, 255, 255, 0.95); // 修改背景为不透明
padding: 20px;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
z-index: 1000;
width: 500px;
max-width: 90%;
modal.style.width = '600px';
modal.style.padding = '20px';
modal.style.backgroundColor = 'white';
modal.style.border = '1px solid #ccc';
modal.style.borderRadius = '5px';
modal.style.boxShadow = '0 0 10px rgba(0,0,0,0.2)';
modal.style.zIndex = '1000';
`;
// 创建标题和关闭按钮
const header = document.createElement('div');
header.style.display = 'flex';
header.style.justifyContent = 'space-between';
header.style.alignItems = 'center';
header.style.marginBottom = '15px';
const title = document.createElement('h3');
title.textContent = '选择先修知识';
title.style.margin = '0';
const closeBtn = document.createElement('button');
closeBtn.innerHTML = '&times;';
closeBtn.style.background = 'none';
closeBtn.style.border = 'none';
closeBtn.style.fontSize = '20px';
closeBtn.style.cursor = 'pointer';
closeBtn.onclick = function () {
document.body.removeChild(modal);
};
header.appendChild(title);
header.appendChild(closeBtn);
// 创建多选下拉框
// 替换select元素为checkbox列表
const container = document.createElement('div');
container.style.cssText = `
max-height: 300px;
overflow-y: auto;
margin-bottom: 10px;
`;
// 为每个节点创建checkbox
allNodes.forEach(node => {
console.log('Node title:', typeof node.title, node.title); // 添加调试
if (node.id !== currentNodeId && !node.isParent) {
const div = document.createElement('div');
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.value = node.id;
checkbox.id = `node_${node.id}`;
const label = document.createElement('label');
label.htmlFor = `node_${node.id}`;
label.textContent = node.title; // 修改这里直接显示节点title
div.appendChild(checkbox);
div.appendChild(label);
container.appendChild(div);
}
});
// Create confirm button before using it
const confirmBtn = document.createElement('button');
confirmBtn.textContent = '确定';
confirmBtn.style.marginTop = '10px';
confirmBtn.style.padding = '5px 15px';
confirmBtn.style.backgroundColor = '#4CAF50';
confirmBtn.style.color = 'white';
confirmBtn.style.border = 'none';
confirmBtn.style.borderRadius = '4px';
confirmBtn.style.cursor = 'pointer';
confirmBtn.onclick = function () {
const currentNode = findNodeById(treeData, currentNodeId);
if (!currentNode) {
console.error('找不到当前节点:', currentNodeId);
return;
}
const selectedNodes = [];
const checkboxes = container.querySelectorAll('input[type="checkbox"]:checked');
checkboxes.forEach(checkbox => {
const node = findNodeById(treeData, checkbox.value);
if (node) {
selectedNodes.push({
id: node.id,
title: node.title
});
}
});
console.log(`当前操作的三级节点ID: ${currentNodeId}, 名称: ${currentNode.title}`);
console.log('选中的先修知识:');
selectedNodes.forEach(node => {
if (node.parentTitle) {
console.log(`ID: ${node.id}, 名称: 【${node.parentTitle}${node.title}`);
} else {
console.log(`ID: ${node.id}, 名称: ${node.title}`);
}
});
// 调用后端接口
fetch('/api/update-prerequisites', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
node_id: currentNodeId,
prerequisites: selectedNodes
})
})
.then(response => response.json())
.then(data => {
if (data.code === 0) {
alert('保存成功');
location.reload(); // 刷新页面
} else {
alert('保存失败: ' + data.message);
}
})
.catch(error => {
console.error('Error:', error);
alert('保存出错');
});
modal.remove();
};
// 添加到模态框
modal.appendChild(header);
modal.appendChild(container);
modal.appendChild(confirmBtn);
// 添加到页面
document.body.appendChild(modal);
}
function relatedUpdate(nodeId) {
// 同样修改relatedUpdate函数
const node = findNodeById(treeData, nodeId);
if (node) {
alert(`相关知识 Node ID: ${node.id}\nNode Title: ${node.title}`);
} else {
console.error('Node not found:', nodeId);
}
}
</script>
</body>
</html>