NewLife/cube-front

菜单页面调整
Yann authored at 2025-07-01 15:55:53
bdd8a1e
Tree
1 Parent(s) dce83fd
Summary: 1 changed files with 71 additions and 38 deletions.
Modified +71 -38
Modified +71 -38
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 {