|
|
|
@ -3,6 +3,9 @@
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
|
<title>知识点树形展示</title>
|
|
|
|
|
<!-- 添加LayUI CSS和JS -->
|
|
|
|
|
<link rel="stylesheet" href="/static/layui/css/layui.css">
|
|
|
|
|
<script src="/static/layui/layui.js"></script>
|
|
|
|
|
<style>
|
|
|
|
|
body {
|
|
|
|
|
margin: 0;
|
|
|
|
@ -111,9 +114,9 @@
|
|
|
|
|
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>';
|
|
|
|
|
(isThirdLevel ? '<button class="layui-btn layui-btn-sm" onclick="prerequisiteUpdate(\'' + node.id + '\')">维护</button>' : '') + '</td>';
|
|
|
|
|
html += '<td>' + (node.related || '') +
|
|
|
|
|
(isThirdLevel ? '<button onclick="relatedUpdate(\'' + node.id + '\')">维护</button>' : '') + '</td>';
|
|
|
|
|
(isThirdLevel ? '<button class="layui-btn layui-btn-sm layui-btn-normal" onclick="relatedUpdate(\'' + node.id + '\')">维护</button>' : '') + '</td>';
|
|
|
|
|
html += '</tr>';
|
|
|
|
|
|
|
|
|
|
if (node.open && node.children && node.children.length > 0) {
|
|
|
|
@ -155,175 +158,121 @@
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 修改prerequisiteUpdate和relatedUpdate函数
|
|
|
|
|
// 修改prerequisiteUpdate函数使用LayUI
|
|
|
|
|
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 = '×';
|
|
|
|
|
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 => {
|
|
|
|
|
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}`;
|
|
|
|
|
layui.use(['layer', 'form'], function(){
|
|
|
|
|
var layer = layui.layer;
|
|
|
|
|
var form = layui.form;
|
|
|
|
|
|
|
|
|
|
// 获取当前节点
|
|
|
|
|
const currentNode = findNodeById(treeData, nodeId);
|
|
|
|
|
|
|
|
|
|
// 获取当前节点的先修知识列表
|
|
|
|
|
const currentNode = findNodeById(treeData, currentNodeId);
|
|
|
|
|
if (currentNode && currentNode.prerequisite) {
|
|
|
|
|
// 如果当前节点有这个先修知识,则默认选中
|
|
|
|
|
const isSelected = currentNode.prerequisite.some(p => p.id === node.id);
|
|
|
|
|
checkbox.checked = isSelected;
|
|
|
|
|
// 构建HTML内容
|
|
|
|
|
let html = '<div style="padding: 20px;">';
|
|
|
|
|
html += '<form class="layui-form">';
|
|
|
|
|
|
|
|
|
|
allNodes.forEach(node => {
|
|
|
|
|
if (node.id !== nodeId && !node.isParent) {
|
|
|
|
|
const isSelected = currentNode && currentNode.prerequisite &&
|
|
|
|
|
currentNode.prerequisite.some(p => p.id === node.id);
|
|
|
|
|
|
|
|
|
|
html += '<div class="layui-form-item">';
|
|
|
|
|
html += '<input type="checkbox" name="node" value="' + node.id + '" title="' + node.title + '"' + (isSelected ? ' checked' : '') + '>';
|
|
|
|
|
html += '</div>';
|
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
html += '</form>';
|
|
|
|
|
html += '</div>';
|
|
|
|
|
|
|
|
|
|
// 弹出层
|
|
|
|
|
layer.open({
|
|
|
|
|
type: 1,
|
|
|
|
|
title: '选择先修知识',
|
|
|
|
|
content: html,
|
|
|
|
|
area: ['500px', '400px'],
|
|
|
|
|
btn: ['确定', '取消'],
|
|
|
|
|
yes: function(index, layero){
|
|
|
|
|
const selectedNodes = [];
|
|
|
|
|
$('input[name="node"]:checked').each(function(){
|
|
|
|
|
const node = findNodeById(treeData, $(this).val());
|
|
|
|
|
if (node) {
|
|
|
|
|
selectedNodes.push({
|
|
|
|
|
id: node.id,
|
|
|
|
|
title: node.title
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 调用后端接口
|
|
|
|
|
fetch('/api/update-prerequisites', {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
},
|
|
|
|
|
body: JSON.stringify({
|
|
|
|
|
node_id: nodeId,
|
|
|
|
|
prerequisites: selectedNodes
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
.then(response => response.json())
|
|
|
|
|
.then(data => {
|
|
|
|
|
if (data.code === 0) {
|
|
|
|
|
layer.msg('保存成功', {icon: 1});
|
|
|
|
|
setTimeout(() => location.reload(), 1000);
|
|
|
|
|
} else {
|
|
|
|
|
layer.msg('保存失败: ' + data.message, {icon: 2});
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(error => {
|
|
|
|
|
console.error('Error:', error);
|
|
|
|
|
layer.msg('保存出错', {icon: 2});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
layer.close(index);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
console.log(`当前操作的三级节点ID: ${currentNodeId}, 名称: ${currentNode.title}`);
|
|
|
|
|
console.log('选中的先修知识:');
|
|
|
|
|
selectedNodes.forEach(node => {
|
|
|
|
|
if (node.parentTitle) {
|
|
|
|
|
console.log(`ID: ${node.id}, 名称: 【${node.parentTitle}】${node.title}`);
|
|
|
|
|
|
|
|
|
|
form.render();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 修改维护按钮样式
|
|
|
|
|
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 {
|
|
|
|
|
console.log(`ID: ${node.id}, 名称: ${node.title}`);
|
|
|
|
|
html += '<span style="display:inline-block; width:16px;"></span>';
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
// 调用后端接口
|
|
|
|
|
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);
|
|
|
|
|
html += node.title + '</td>';
|
|
|
|
|
|
|
|
|
|
// 添加到页面
|
|
|
|
|
document.body.appendChild(modal);
|
|
|
|
|
}
|
|
|
|
|
// 修改后的维护按钮显示逻辑
|
|
|
|
|
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 class="layui-btn layui-btn-sm" onclick="prerequisiteUpdate(\'' + node.id + '\')">维护</button>' : '') + '</td>';
|
|
|
|
|
html += '<td>' + (node.related || '') +
|
|
|
|
|
(isThirdLevel ? '<button class="layui-btn layui-btn-sm layui-btn-normal" onclick="relatedUpdate(\'' + node.id + '\')">维护</button>' : '') + '</td>';
|
|
|
|
|
html += '</tr>';
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
if (node.open && node.children && node.children.length > 0) {
|
|
|
|
|
buildRows(node.children, level + 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buildRows(treeData);
|
|
|
|
|
$("#treeBody").html(html);
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|