diff --git a/apps/cube-admin/src/pages/admin/menu/index.vue b/apps/cube-admin/src/pages/admin/menu/index.vue
index 8e32358..de7f350 100644
--- a/apps/cube-admin/src/pages/admin/menu/index.vue
+++ b/apps/cube-admin/src/pages/admin/menu/index.vue
@@ -34,13 +34,18 @@
style="margin-bottom: 16px;"
/>
- <el-table :data="tableData" border style="width: 100%" v-loading="loading" row-key="id" default-expand-all
- :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" @selection-change="handleSelectionChange">
+ <el-table :data="tableData" border style="width: 100%" v-loading="loading"
+ row-key="id"
+ default-expand-all
+ :tree-props="{ children: 'children' }"
+ @selection-change="handleSelectionChange"
+ :show-header="true"
+ :highlight-current-row="true">
<el-table-column type="selection" width="55" />
<el-table-column prop="id" label="编号" width="80" />
- <el-table-column prop="name" label="名称" />
- <el-table-column prop="displayName" label="显示名" />
- <el-table-column prop="url" label="链接" />
+ <el-table-column prop="name" label="名称" min-width="150" />
+ <el-table-column prop="displayName" label="显示名" min-width="150" />
+ <el-table-column prop="url" label="链接" min-width="150" />
<el-table-column prop="sort" label="排序" width="80" />
<el-table-column prop="icon" label="图标" width="100">
<template #default="scope">
@@ -48,7 +53,7 @@
<span v-else>-</span>
</template>
</el-table-column>
- <el-table-column prop="updateTime" label="更新时间" />
+ <el-table-column prop="updateTime" label="更新时间" min-width="150" />
<el-table-column label="可见" width="80">
<template #default="scope">
<el-tag :type="scope.row.visible ? 'success' : 'danger'">
@@ -70,7 +75,7 @@
</el-tag>
</template>
</el-table-column>
- <el-table-column label="操作" width="180">
+ <el-table-column label="操作" width="180" fixed="right">
<template #default="scope">
<el-button type="primary" size="small" @click="handleEdit(scope.row)">编辑</el-button>
<el-button type="danger" size="small" @click="handleDelete(scope.row)">删除</el-button>
@@ -226,45 +231,71 @@ const formRules = reactive<FormRules>({
]
});
-// 构建树结构并排序
+// 构建树结构并排序(使用队列,非递归方式)
const buildTreeData = (data: Menu[]): Menu[] => {
- const map = new Map<number, Menu>();
- const roots: Menu[] = [];
+ if (!data || data.length === 0) {
+ return [];
+ }
- // 先按sort字段排序
- const sortedData = [...data].sort((a, b) => a.sort - b.sort);
+ // 创建节点映射表和根节点数组
+ const nodeMap = new Map<number, Menu>();
+ const roots: Menu[] = [];
- // 将所有节点加入map
- sortedData.forEach(item => {
- map.set(item.id, { ...item, children: [] });
+ // 步骤1:初始化所有节点
+ data.forEach(item => {
+ const node = { ...item };
+ // 确保清理之前的树状属性
+ node.children = [];
+ delete node.hasChildren;
+ nodeMap.set(item.id, node);
});
- // 构建树结构
- sortedData.forEach(item => {
- const node = map.get(item.id)!;
+ // 步骤2:建立父子关系
+ data.forEach(item => {
+ const node = nodeMap.get(item.id)!;
+
if (item.parentID === 0) {
+ // parentID为0的是根节点
roots.push(node);
} else {
- const parent = map.get(item.parentID);
+ // 找到父节点并建立关系
+ const parent = nodeMap.get(item.parentID);
if (parent) {
- parent.children = parent.children || [];
+ if (!parent.children) {
+ parent.children = [];
+ }
parent.children.push(node);
- parent.hasChildren = true;
+ } else {
+ // 如果找不到父节点,作为根节点处理
+ roots.push(node);
}
}
});
- // 对每个层级的children再次排序
- const sortChildren = (nodes: Menu[]) => {
- nodes.sort((a, b) => a.sort - b.sort);
- nodes.forEach(node => {
- if (node.children && node.children.length > 0) {
- sortChildren(node.children);
- }
- });
+ // 步骤3:清理空的children数组并排序
+ const processNode = (node: Menu) => {
+ if (node.children && node.children.length === 0) {
+ delete node.children;
+ } else if (node.children && node.children.length > 0) {
+ // 对子节点排序
+ node.children.sort((a, b) => a.sort - b.sort);
+ // 递归处理子节点
+ node.children.forEach(child => processNode(child));
+ }
};
- sortChildren(roots);
+ // 对根节点排序
+ roots.sort((a, b) => a.sort - b.sort);
+
+ // 处理所有节点
+ roots.forEach(root => processNode(root));
+
+ console.log('构建树状结构完成:', {
+ 原始数据数量: data.length,
+ 根节点数量: roots.length,
+ 树结构: roots
+ });
+
return roots;
};
@@ -287,23 +318,25 @@ const loadData = async () => {
let dataList: Menu[] = [];
- // 处理不同的响应格式
+ // 处理API响应数据
if (Array.isArray(response)) {
// 直接返回数组的响应
dataList = response;
- } else if (response && typeof response === 'object') {
- // 包含分页信息的响应或标准API响应格式
- if ('data' in response && Array.isArray(response.data)) {
- dataList = response.data;
- } else if (Array.isArray(response)) {
- dataList = response;
- }
+ } else if (response && typeof response === 'object' && 'data' in response) {
+ // 标准API响应格式,从data字段取数据
+ dataList = Array.isArray(response.data) ? response.data : [];
+ } else {
+ dataList = [];
}
+ console.log('菜单原始数据:', dataList);
+
// 构建树结构并排序
tableData.value = buildTreeData(dataList);
total.value = dataList.length;
+ console.log('构建后的树状数据:', tableData.value);
+
// 同时保存平铺的数据用于菜单选项(排除当前编辑的菜单)
menuOptions.value = dataList.filter(item => item.id !== form.id);
} catch {