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.

270 lines
9.2 KiB

3 weeks ago
<!DOCTYPE html>
3 weeks ago
<html lang="zh">
3 weeks ago
<head>
<meta charset="UTF-8">
<title>知识点树形展示</title>
3 weeks ago
<!-- 添加LayUI CSS和JS -->
<link rel="stylesheet" href="/static/layui/css/layui.css">
<script src="/static/layui/layui.js"></script>
3 weeks ago
<style>
3 weeks ago
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;
}
3 weeks ago
#treeTable th:nth-child(2), #treeTable td:nth-child(2),
#treeTable th:nth-child(3), #treeTable td:nth-child(3),
#treeTable th:nth-child(4), #treeTable td:nth-child(4) {
width: 220px;
min-width: 220px;
max-width: 220px;
text-align: center;
border-right: 1px solid #ddd; /* 确保右侧边框闭合 */
}
#treeTable td:nth-child(4) {
display: flex;
justify-content: center;
gap: 5px;
min-height: 36px; /* 确保空单元格也有高度 */
}
</style>
3 weeks ago
</head>
<body>
3 weeks ago
<table id="treeTable">
<thead>
<tr>
<th>知识点</th>
<th>先修知识</th>
<th>相关知识</th>
3 weeks ago
<th>维护</th>
3 weeks ago
</tr>
</thead>
<tbody id="treeBody"></tbody>
</table>
3 weeks ago
3 weeks ago
<script src="/static/js/jquery-1.4.4.min.js"></script>
3 weeks ago
<script>
3 weeks ago
var treeData = [];
function toggleNode(nodeId) {
3 weeks ago
console.log('toggleNode', nodeId);
3 weeks ago
var node = findNodeById(treeData, nodeId);
if (node) {
node.open = !node.open;
3 weeks ago
// 强制重新渲染整个表格
3 weeks ago
updateTable();
3 weeks ago
}
3 weeks ago
}
3 weeks ago
function findParentTitle(node) {
3 weeks ago
if (!node || !node.parent_id) return '';
3 weeks ago
const parent = allNodes.find(n => n.id === node.parent_id);
return parent ? parent.title : '';
}
3 weeks ago
3 weeks ago
function findNodeById(nodes, id) {
3 weeks ago
for (const node of nodes) {
if (node.id === id) return node;
if (node.children) {
const found = findNodeById(node.children, id);
3 weeks ago
if (found) return found;
}
3 weeks ago
}
3 weeks ago
return null;
3 weeks ago
}
3 weeks ago
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) {
3 weeks ago
html += '<span class="toggle-icon" onclick="toggleNode(\'' + node.id + '\')">' +
(node.open ? '▼' : '▶') + '</span>';
3 weeks ago
} else {
html += '<span style="display:inline-block; width:16px;"></span>';
}
html += node.title + '</td>';
3 weeks ago
3 weeks ago
// 修改后的维护按钮显示逻辑
const isThirdLevel = node.parent_id && allNodes.find(n => n.id === node.parent_id)?.parent_id;
3 weeks ago
html += '<td>' + (node.prerequisite && node.prerequisite.length > 0 ?
node.prerequisite.map(p => p.title).join(', ') : '') + '</td>';
3 weeks ago
html += '<td>' + (node.related && node.related.length > 0 ?
node.related.map(r => r.title).join(', ') : '') + '</td>';
3 weeks ago
html += '<td>' + (isThirdLevel ?
'<button class="layui-btn layui-btn-sm" onclick="prerequisiteUpdate(\'' + node.id + '\')">先修知识</button> ' +
'<button class="layui-btn layui-btn-sm layui-btn-normal" onclick="relatedUpdate(\'' + node.id + '\')">相关知识</button>' : '') + '</td>';
3 weeks ago
html += '</tr>';
if (node.open && node.children && node.children.length > 0) {
buildRows(node.children, level + 1);
}
}
3 weeks ago
}
3 weeks ago
3 weeks ago
buildRows(treeData);
$("#treeBody").html(html);
3 weeks ago
}
3 weeks ago
// 初始化数据
3 weeks ago
// Move this declaration outside the AJAX call
var allNodes = [];
3 weeks ago
3 weeks ago
// Add flattenTree function definition before the AJAX call
3 weeks ago
function flattenTree(nodes) {
var result = [];
nodes.forEach(node => {
result.push(node);
if (node.children) {
result = result.concat(flattenTree(node.children));
}
});
return result;
}
3 weeks ago
3 weeks ago
$.ajax({
url: "/api/tree-data",
type: "GET",
3 weeks ago
success: function (res) {
3 weeks ago
if (res.code === 0) {
treeData = res.data;
allNodes = flattenTree(treeData);
updateTable();
}
}
});
3 weeks ago
3 weeks ago
// 修改prerequisiteUpdate和relatedUpdate函数
3 weeks ago
// 公共函数
function showKnowledgeSelector(nodeId, title, currentKnowledge, updateType) {
3 weeks ago
layui.use(['layer', 'form'], function () {
3 weeks ago
var layer = layui.layer;
var form = layui.form;
3 weeks ago
3 weeks ago
// 构建HTML内容
let html = '<div style="padding: 20px;">';
html += '<form class="layui-form">';
3 weeks ago
3 weeks ago
allNodes.forEach(node => {
if (node.id !== nodeId && !node.isParent) {
3 weeks ago
const isSelected = currentKnowledge &&
currentKnowledge.some(p => p.id === node.id);
3 weeks ago
const parentTitle = findParentTitle(node);
const displayTitle = parentTitle ? `【${parentTitle}】${node.title}` : node.title;
3 weeks ago
3 weeks ago
html += '<div class="layui-form-item">';
3 weeks ago
html += '<input type="checkbox" name="node" value="' + node.id + '" title="' + displayTitle + '"' + (isSelected ? ' checked' : '') + '>';
3 weeks ago
html += '</div>';
3 weeks ago
}
3 weeks ago
});
3 weeks ago
3 weeks ago
html += '</form>';
html += '</div>';
3 weeks ago
3 weeks ago
// 弹出层
layer.open({
type: 1,
3 weeks ago
title: '选择' + title,
3 weeks ago
content: html,
area: ['500px', '400px'],
btn: ['确定', '取消'],
3 weeks ago
yes: function (index, layero) {
3 weeks ago
const selectedNodes = [];
3 weeks ago
$('input[name="node"]:checked').each(function () {
3 weeks ago
const node = findNodeById(treeData, $(this).val());
if (node) {
selectedNodes.push({
id: node.id,
title: node.title
});
}
});
3 weeks ago
3 weeks ago
// 调用后端接口
3 weeks ago
fetch('/api/update-knowledge', {
3 weeks ago
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
node_id: nodeId,
3 weeks ago
knowledge: selectedNodes,
update_type: updateType
3 weeks ago
})
})
.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});
});
3 weeks ago
3 weeks ago
layer.close(index);
}
});
form.render();
});
}
3 weeks ago
// 修改后的prerequisiteUpdate函数
function prerequisiteUpdate(nodeId) {
const currentNode = findNodeById(treeData, nodeId);
showKnowledgeSelector(nodeId, '先修知识', currentNode.prerequisite, 'prerequisite');
}
3 weeks ago
3 weeks ago
// 修改后的relatedUpdate函数
function relatedUpdate(nodeId) {
const currentNode = findNodeById(treeData, nodeId);
showKnowledgeSelector(nodeId, '相关知识', currentNode.related, 'related');
3 weeks ago
}
3 weeks ago
</script>
</body>
3 weeks ago
</html>