|
|
|
<!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 findNodeById(nodes, id) {
|
|
|
|
for (var i = 0; i < nodes.length; i++) {
|
|
|
|
if (nodes[i].id == id) return nodes[i];
|
|
|
|
if (nodes[i].children) {
|
|
|
|
var found = findNodeById(nodes[i].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>';
|
|
|
|
|
|
|
|
|
|
|
|
// 修改维护按钮的HTML生成部分
|
|
|
|
html += '<td>' + (node.prerequisite || '') +
|
|
|
|
(node.isParent && node.parent_id ? '<button onclick="prerequisiteUpdate(\'' + node.id + '\')">维护</button>' : '') + '</td>';
|
|
|
|
html += '<td>' + (node.related || '') +
|
|
|
|
(node.isParent && node.parent_id ? '<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 node = findNodeById(treeData, nodeId);
|
|
|
|
if (!node) {
|
|
|
|
console.error('Node not found:', nodeId);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 创建模态框容器
|
|
|
|
const modal = document.createElement('div');
|
|
|
|
modal.style.position = 'fixed';
|
|
|
|
modal.style.top = '50%';
|
|
|
|
modal.style.left = '50%';
|
|
|
|
modal.style.transform = 'translate(-50%, -50%)';
|
|
|
|
modal.style.width = '500px';
|
|
|
|
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 = '×';
|
|
|
|
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);
|
|
|
|
|
|
|
|
// 创建多选下拉框
|
|
|
|
const select = document.createElement('select');
|
|
|
|
select.multiple = true;
|
|
|
|
select.style.width = '100%';
|
|
|
|
select.style.height = '200px';
|
|
|
|
select.style.margin = '10px 0';
|
|
|
|
select.style.padding = '5px';
|
|
|
|
|
|
|
|
// 添加选项
|
|
|
|
allNodes.forEach(n => {
|
|
|
|
if (n.id !== nodeId) {
|
|
|
|
const option = document.createElement('option');
|
|
|
|
option.value = n.id;
|
|
|
|
option.text = n.title;
|
|
|
|
select.appendChild(option);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// 创建确定按钮
|
|
|
|
const button = document.createElement('button');
|
|
|
|
button.textContent = '确定';
|
|
|
|
button.style.padding = '8px 16px';
|
|
|
|
button.style.backgroundColor = '#4CAF50';
|
|
|
|
button.style.color = 'white';
|
|
|
|
button.style.border = 'none';
|
|
|
|
button.style.borderRadius = '4px';
|
|
|
|
button.style.cursor = 'pointer';
|
|
|
|
button.onclick = function() {
|
|
|
|
document.body.removeChild(modal);
|
|
|
|
};
|
|
|
|
|
|
|
|
// 添加到模态框
|
|
|
|
modal.appendChild(header);
|
|
|
|
modal.appendChild(select);
|
|
|
|
modal.appendChild(button);
|
|
|
|
|
|
|
|
// 添加到页面
|
|
|
|
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>
|