326 lines
11 KiB
Vue
326 lines
11 KiB
Vue
<template>
|
||
<div>
|
||
<!-- 调试信息 -->
|
||
<div style="margin-bottom: 20px; padding: 15px; background: #f5f7fa; border-radius: 8px;">
|
||
<el-button size="small" @click="showDebugInfo">查看调试信息</el-button>
|
||
<el-button size="small" @click="showRawData">查看原始数据</el-button>
|
||
<el-button size="small" type="primary" @click="testTreeStructure">测试树形结构</el-button>
|
||
<el-button size="small" type="success" @click="getCategories">重新加载数据</el-button>
|
||
<span style="margin-left: 20px; color: #666;">
|
||
数据总数: {{ tableData.length }} |
|
||
树形层级: {{ getMaxLevel() }}级
|
||
</span>
|
||
</div>
|
||
|
||
<el-table :data="tableData" style="width: 100%;margin-bottom: 20px;" row-key="id" border v-loading="loading"
|
||
element-loading-text="加载中..." element-loading-spinner="el-icon-loading"
|
||
:tree-props="{ children: 'children' }" :default-expand-all="false" :expand-on-click-node="false">
|
||
<el-table-column prop="name" label="名称" min-width="120">
|
||
</el-table-column>
|
||
<el-table-column prop="id" label="id" min-width="200">
|
||
</el-table-column>
|
||
<el-table-column prop="level" label="层级" min-width="120">
|
||
</el-table-column>
|
||
<el-table-column label="操作" width="280" fixed="right">
|
||
<template slot-scope="scope">
|
||
<el-button type="text" size="small" @click="addNode(scope.row, 'sibling')">新增同级</el-button>
|
||
<el-button type="text" size="small" @click="addNode(scope.row, 'child')">新增子级</el-button>
|
||
<el-button type="text" size="small" @click="editNode(scope.row)">编辑</el-button>
|
||
<el-button type="text" size="small" @click="deleteNode(scope.row)"
|
||
style="color: #F56C6C;">删除</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
|
||
|
||
<el-drawer title="菜单管理" :visible.sync="drawer" :direction="direction">
|
||
|
||
<div style="margin: 20px;"></div>
|
||
<el-form :label-position="labelPosition" label-width="80px" :model="formLabelAlign">
|
||
<el-form-item label="菜单名称">
|
||
<el-input v-model="formLabelAlign.name"></el-input>
|
||
</el-form-item>
|
||
|
||
|
||
</el-form>
|
||
</el-drawer>
|
||
</div>
|
||
</template>
|
||
<script>
|
||
import { reqNcMatchMenu } from '@/api/ncmatch';
|
||
export default {
|
||
name: 'menuMangement',
|
||
data() {
|
||
return {
|
||
loading: false,
|
||
categories: [],
|
||
tableData: [], // 移除硬编码的测试数据
|
||
drawer: false,
|
||
direction: 'rtl',
|
||
labelPosition: 'right',
|
||
formLabelAlign: {
|
||
name: '',
|
||
region: '',
|
||
type: ''
|
||
}
|
||
}
|
||
},
|
||
created() {
|
||
this.getCategories();
|
||
},
|
||
methods: {
|
||
addNode(row, type) {
|
||
this.drawer = true;
|
||
console.log('新增节点:', row, '类型:', type);
|
||
},
|
||
getCategories() {
|
||
this.loading = true;
|
||
reqNcMatchMenu({ url_link: window.location.href }).then(res => {
|
||
this.loading = false;
|
||
if (res.status) {
|
||
this.categories = this.buildSimpleTree(res.data);
|
||
this.tableData = this.categories; // 使用精简的树形结构
|
||
console.log("构建的精简树结构:", this.categories);
|
||
}
|
||
}).catch(error => {
|
||
this.loading = false;
|
||
console.error('获取菜单数据失败:', error);
|
||
});
|
||
},
|
||
editNode(row) {
|
||
this.drawer = true;
|
||
console.log('编辑节点:', row);
|
||
},
|
||
deleteNode(row) {
|
||
this.drawer = true;
|
||
console.log('删除节点:', row);
|
||
},
|
||
buildTree(data, parentId = null) {
|
||
if (!Array.isArray(data)) {
|
||
console.log('数据不是数组:', data);
|
||
return [];
|
||
}
|
||
|
||
console.log('构建树结构,当前parentId:', parentId, '数据长度:', data.length);
|
||
|
||
// 找出当前层级的节点
|
||
const currentNodes = data.filter(item => {
|
||
// 处理顶级节点(parentid 为 null 或空字符串)
|
||
if (parentId === null) {
|
||
return !item.parentid || item.parentid === '' || item.parentid === '0';
|
||
}
|
||
return item.parentid === parentId;
|
||
});
|
||
|
||
console.log('当前层级节点数量:', currentNodes.length, '节点:', currentNodes);
|
||
|
||
if (currentNodes.length === 0) return [];
|
||
|
||
// 处理每个节点
|
||
return currentNodes.map(node => {
|
||
const resultNode = {
|
||
id: node.id,
|
||
name: node.name || '未命名',
|
||
parentid: node.parentid
|
||
};
|
||
|
||
// 递归处理子节点
|
||
const children = this.buildSimpleTree(data, node.id);
|
||
|
||
// 只有当有子节点时才添加 children 字段
|
||
if (children && children.length > 0) {
|
||
resultNode.children = children;
|
||
}
|
||
|
||
return resultNode;
|
||
});
|
||
},
|
||
|
||
// 精简的树形结构构建方法
|
||
buildSimpleTree(data, parentId = null) {
|
||
if (!Array.isArray(data)) {
|
||
return [];
|
||
}
|
||
|
||
// 找出当前层级的节点
|
||
const currentNodes = data.filter(item => {
|
||
if (parentId === null) {
|
||
return !item.parentid || item.parentid === '' || item.parentid === '0';
|
||
}
|
||
return item.parentid === parentId;
|
||
});
|
||
|
||
if (currentNodes.length === 0) return [];
|
||
|
||
// 处理每个节点,只保留必要字段
|
||
return currentNodes.map(node => {
|
||
const resultNode = {
|
||
id: node.id,
|
||
name: node.name || '未命名',
|
||
parentid: node.parentid
|
||
};
|
||
|
||
// 递归处理子节点
|
||
const children = this.buildSimpleTree(data, node.id);
|
||
|
||
// 只有当有子节点时才添加 children 字段
|
||
if (children && children.length > 0) {
|
||
resultNode.children = children;
|
||
}
|
||
|
||
return resultNode;
|
||
});
|
||
},
|
||
|
||
// 计算节点层级
|
||
calculateLevel(data, nodeId) {
|
||
let level = 1;
|
||
let currentId = nodeId;
|
||
|
||
while (true) {
|
||
const parent = data.find(item => item.id === currentId);
|
||
if (!parent || !parent.parentid || parent.parentid === '' || parent.parentid === '0') {
|
||
break;
|
||
}
|
||
level++;
|
||
currentId = parent.parentid;
|
||
}
|
||
|
||
return level;
|
||
},
|
||
showDebugInfo() {
|
||
console.log("当前 tableData 的结构:", this.tableData);
|
||
console.log("当前 tableData 的层级分布:", this.getLevelDistribution());
|
||
console.log("当前 tableData 的最大层级:", this.getMaxLevel());
|
||
|
||
// 检查树形结构
|
||
this.checkTreeStructure(this.tableData);
|
||
},
|
||
|
||
// 检查树形结构
|
||
checkTreeStructure(nodes, level = 0) {
|
||
if (!Array.isArray(nodes)) return;
|
||
|
||
nodes.forEach(node => {
|
||
const indent = ' '.repeat(level);
|
||
console.log(`${indent}📁 ${node.name} (ID: ${node.id})`);
|
||
console.log(`${indent} - hasChildren: ${node.hasChildren}`);
|
||
console.log(`${indent} - children.length: ${node.children ? node.children.length : 'undefined'}`);
|
||
console.log(`${indent} - level: ${node.level}`);
|
||
|
||
if (node.children && node.children.length > 0) {
|
||
this.checkTreeStructure(node.children, level + 1);
|
||
}
|
||
});
|
||
},
|
||
showRawData() {
|
||
console.log("原始数据:", this.categories);
|
||
},
|
||
|
||
// 测试树形结构
|
||
testTreeStructure() {
|
||
const testData = [
|
||
{
|
||
id: 1,
|
||
name: '一级菜单1',
|
||
parentid: null
|
||
},
|
||
{
|
||
id: 2,
|
||
name: '一级菜单2',
|
||
parentid: null
|
||
},
|
||
{
|
||
id: 3,
|
||
name: '一级菜单3',
|
||
parentid: null,
|
||
children: [
|
||
{
|
||
id: 31,
|
||
name: '二级菜单3-1',
|
||
parentid: 3
|
||
},
|
||
{
|
||
id: 32,
|
||
name: '二级菜单3-2',
|
||
parentid: 3,
|
||
children: [
|
||
{
|
||
id: 321,
|
||
name: '三级菜单3-2-1',
|
||
parentid: 32
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
];
|
||
|
||
console.log("精简测试数据:", testData);
|
||
this.tableData = testData;
|
||
},
|
||
getLevelDistribution() {
|
||
const levels = {};
|
||
this.tableData.forEach(node => {
|
||
const level = node.level;
|
||
if (levels[level]) {
|
||
levels[level]++;
|
||
} else {
|
||
levels[level] = 1;
|
||
}
|
||
});
|
||
return levels;
|
||
},
|
||
getMaxLevel() {
|
||
let maxLevel = 0;
|
||
this.tableData.forEach(node => {
|
||
if (node.level > maxLevel) {
|
||
maxLevel = node.level;
|
||
}
|
||
});
|
||
return maxLevel;
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
<style scoped>
|
||
.el-table {
|
||
border-radius: 8px;
|
||
overflow: hidden;
|
||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.el-table th {
|
||
background-color: #f5f7fa;
|
||
color: #606266;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.el-table td {
|
||
padding: 12px 0;
|
||
}
|
||
|
||
.el-button--text {
|
||
padding: 4px 8px;
|
||
margin: 0 2px;
|
||
}
|
||
|
||
.el-button--text:hover {
|
||
background-color: #f5f7fa;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
.el-tag {
|
||
border-radius: 4px;
|
||
}
|
||
|
||
/* 树形表格的缩进样式 */
|
||
.el-table__expand-icon {
|
||
margin-right: 8px;
|
||
}
|
||
|
||
/* 加载状态样式 */
|
||
.el-loading-mask {
|
||
background-color: rgba(255, 255, 255, 0.8);
|
||
}
|
||
</style> |