$item) { // if ($item[$pidField] == 0) { // $tree[] = &$items[$id]; // } else { // if (isset($items[$item[$pidField]])) { // $items[$id]['level'] = $items[$item[$pidField]]['level'] + 1; // if (!isset($items[$item[$pidField]]['children'])) { // $items[$item[$pidField]]['children'] = []; // } // $items[$item[$pidField]]['children'][] = &$items[$id]; // } // } // } // return $tree; // } // /** // * 将树形结构扁平化为列表(带层级前缀) // * // * @param array $tree 树形结构数据 // * @param string $prefix 前缀字符 // * @param string $field 显示字段名 // * @param int $level 层级 // * @return array // */ // public static function flattenWithPrefix(array $tree, string $prefix = '--', string $field = 'name', int $level = 0): array // { // $result = []; // foreach ($tree as $item) { // $item[$field . '_with_prefix'] = str_repeat($prefix, $item['level']) . $item[$field]; // $result[] = $item; // if (isset($item['children']) && !empty($item['children'])) { // $children = static::flattenWithPrefix($item['children'], $prefix, $field, $item['level'] + 1); // $result = array_merge($result, $children); // } // } // return $result; // } // /** // * 根据父ID查找所有子节点(包括子孙节点) // * // * @param array $data 数据列表 // * @param int $parentId 父级ID // * @param string $pidField 父级字段名 // * @param string $idField ID字段名 // * @return array // */ // public static function findChildren(array $data, int $parentId, string $pidField = 'parent_id', string $idField = 'id'): array // { // $children = []; // foreach ($data as $item) { // if ($item[$pidField] == $parentId) { // $children[] = $item; // $grandChildren = static::findChildren($data, $item[$idField], $pidField, $idField); // $children = array_merge($children, $grandChildren); // } // } // return $children; // } // /** // * 获取指定节点的所有父级节点 // * // * @param array $data 数据列表 // * @param int $id 当前节点ID // * @param string $pidField 父级字段名 // * @param string $idField ID字段名 // * @return array // */ // public static function getParents(array $data, int $id, string $pidField = 'parent_id', string $idField = 'id'): array // { // $parents = []; // foreach ($data as $item) { // if ($item[$idField] == $id) { // if ($item[$pidField] != 0) { // $parents[] = $item; // $parentParents = static::getParents($data, $item[$pidField], $pidField, $idField); // $parents = array_merge($parents, $parentParents); // } // break; // } // } // return $parents; // } // /** // * 获取指定节点的子孙节点ID列表 // * // * @param array $data 数据列表 // * @param int $parentId 父级ID // * @param string $pidField 父级字段名 // * @param string $idField ID字段名 // * @return array // */ // public static function getChildrenIds(array $data, int $parentId, string $pidField = 'parent_id', string $idField = 'id'): array // { // $ids = []; // $children = static::findChildren($data, $parentId, $pidField, $idField); // foreach ($children as $child) { // $ids[] = $child[$idField]; // } // return $ids; // } // /** // * 检查是否有子节点 // * // * @param array $data 数据列表 // * @param int $parentId 父级ID // * @param string $pidField 父级字段名 // * @return bool // */ // public static function hasChildren(array $data, int $parentId, string $pidField = 'parent_id'): bool // { // foreach ($data as $item) { // if ($item[$pidField] == $parentId) { // return true; // } // } // return false; // } // /** // * 构建带有权限列表的资源树(权限不显示在树结构中) // * // * @param array $data 资源数据列表 // * @param int $parentId 父级ID // * @param string $pidField 父级字段名 // * @param string $idField ID字段名 // * @param string $typeField 类型字段名 // * @param string $permissionType 权限类型标识 // * @param int $level 当前层级 // * @return array // */ // public static function buildWithAuthList( // array $data, // int $parentId = 0, // string $pidField = 'parent_id', // string $idField = 'id', // string $typeField = 'type', // string $permissionType = 'permission', // int $level = 0 // ): array { // $tree = []; // foreach ($data as $item) { // // 只处理指定父级的非权限节点 // if ($item[$pidField] == $parentId && $item[$typeField] != $permissionType) { // $item['level'] = $level; // // 递归处理子节点(非权限类型) // $children = static::buildWithAuthList($data, $item[$idField], $pidField, $idField, $typeField, $permissionType, $level + 1); // if (!empty($children)) { // $item['children'] = $children; // } // // 收集当前节点下的所有权限 // $item['auth_list'] = static::collectDirectPermissions($data, $item[$idField], $pidField, $typeField, $permissionType); // $tree[] = $item; // } // } // return $tree; // } // /** // * 收集指定节点下的直接权限项(只收集直接子节点中的权限) // * // * @param array $data 数据列表 // * @param int $parentId 父级ID // * @param string $pidField 父级字段名 // * @param string $typeField 类型字段名 // * @param string $permissionType 权限类型标识 // * @return array // */ // public static function collectDirectPermissions1( // array $data, // int $parentId, // string $pidField = 'parent_id', // string $typeField = 'type', // string $permissionType = 'permission' // ): array { // $permissions = []; // foreach ($data as $item) { // // 收集直接子节点中的权限类型 // if ($item[$pidField] == $parentId && $item[$typeField] == $permissionType) { // $permissions[] = $item; // } // } // return $permissions; // } // /** // * 使用引用方式构建带有权限列表的资源树(权限不显示在树结构中) // * // * @param array $data 资源数据列表 // * @param string $pidField 父级字段名 // * @param string $idField ID字段名 // * @param string $typeField 类型字段名 // * @param string $permissionType 权限类型标识 // * @return array // */ // public static function buildWithAuthListAndReference( // array $data, // string $pidField = 'parent_id', // string $idField = 'id', // string $typeField = 'type', // string $permissionType = 'permission' // ): array { // $items = []; // $tree = []; // // 建立以id为索引的数组(只包含非权限节点) // foreach ($data as $item) { // if ($item[$typeField] != $permissionType) { // $item['level'] = 0; // $items[$item[$idField]] = $item; // } // } // // 构建树形结构 // foreach ($items as $id => $item) { // if ($item[$pidField] == 0) { // $tree[] = &$items[$id]; // } else { // if (isset($items[$item[$pidField]])) { // $items[$id]['level'] = $items[$item[$pidField]]['level'] + 1; // if (!isset($items[$item[$pidField]]['children'])) { // $items[$item[$pidField]]['children'] = []; // } // $items[$item[$pidField]]['children'][] = &$items[$id]; // } // } // } // // 为每个节点添加权限列表 // foreach ($items as &$item) { // $item['auth_list'] = static::collectDirectPermissions($data, $item[$idField], $pidField, $typeField, $permissionType); // } // return $tree; // } // 8.13 add /** * 构建前端需要的菜单树结构 * * @param array $data 服务端菜单数据 * @param int $parentId 父级ID * @return array */ public static function buildMenuTree(array $data, int $parentId = 0): array { $tree = []; foreach ($data as $item) { // 只处理非权限类型的节点 if ($item['parent_id'] == $parentId && $item['type'] != 'permission') { // 转换数据结构以匹配前端需要的格式 $menuItem = [ 'id' => $item['id'], 'path' => $item['url'] ?? '', 'name' => $item['name'], 'component' => $item['url'] ?? '', 'meta' => [ 'title' => $item['name'], 'icon' => $item['icon'] ?? '', 'isHide' => !empty($item['is_hide']), 'isHideTab' => !empty($item['is_hide_tab']), 'keepAlive' => !empty($item['keep_alive']), ] ]; // 收集当前节点下的所有权限 $permissions = static::collectDirectPermissions($data, $item['id']); if (!empty($permissions)) { $authList = []; foreach ($permissions as $permission) { $authList[] = [ 'id' => $permission['id'], 'title' => $permission['name'] ?? '', 'authMark' => $permission['code'] ?? '' ]; } $menuItem['meta']['authList'] = $authList; } // 将服务端额外字段放入meta中 $extraFields = static::getExtraFields($item); if (!empty($extraFields)) { $menuItem['meta'] = array_merge($menuItem['meta'], $extraFields); } // 递归处理子菜单 $children = static::buildMenuTree($data, $item['id']); if (!empty($children)) { $menuItem['children'] = $children; } $tree[] = $menuItem; } } return $tree; } /** * 使用引用方式构建前端需要的菜单树结构(性能更好) * * @param array $data 服务端菜单数据 * @return array */ public static function buildMenuTreeWithReference(array $data): array { $items = []; $tree = []; // 过滤出菜单类型的节点并转换数据结构 $menuData = array_filter($data, function($item) { return ($item['type'] ?? '') != 'permission'; }); // 建立以id为索引的数组并转换数据结构 foreach ($menuData as $item) { $items[$item['id']] = [ 'id' => $item['id'], 'path' => $item['url'] ?? '', 'name' => $item['name'], 'component' => $item['url'] ?? '', 'meta' => [ 'title' => $item['name'], 'icon' => $item['icon'] ?? '', 'isHide' => !empty($item['is_hide']), 'isHideTab' => !empty($item['is_hide_tab']), 'keepAlive' => !empty($item['keep_alive']), ] ]; // 将服务端额外字段放入meta中 $extraFields = static::getExtraFields($item); if (!empty($extraFields)) { $items[$item['id']]['meta'] = array_merge($items[$item['id']]['meta'], $extraFields); } } // 构建树形结构 foreach ($menuData as $item) { if ($item['parent_id'] == 0) { $tree[] = &$items[$item['id']]; } else { if (isset($items[$item['parent_id']])) { if (!isset($items[$item['parent_id']]['children'])) { $items[$item['parent_id']]['children'] = []; } $items[$item['parent_id']]['children'][] = &$items[$item['id']]; } } } // 为每个节点添加权限列表 foreach ($items as &$item) { $parentId = $item['id']; $permissions = static::collectDirectPermissions($data, $parentId); if (!empty($permissions)) { $authList = []; foreach ($permissions as $permission) { $authList[] = [ 'id' => $permission['id'], 'title' => $permission['name'] ?? '', 'authMark' => $permission['code'] ?? '' ]; } $item['meta']['authList'] = $authList; } } return $tree; } /** * 收集指定节点下的直接权限项(只收集直接子节点中的权限) * * @param array $data 数据列表 * @param int $parentId 父级ID * @return array */ public static function collectDirectPermissions(array $data, int $parentId): array { $permissions = []; foreach ($data as $item) { // 收集直接子节点中的权限类型 if ($item['parent_id'] == $parentId && ($item['type'] ?? '') == 'permission') { $permissions[] = $item; } } return $permissions; } /** * 获取需要放入meta的额外字段 * * @param array $item 菜单项 * @return array */ public static function getExtraFields(array $item): array { $extraFields = []; $standardFields = [ 'id', 'name', 'url', 'icon', 'parent_id', 'type', 'is_hide', 'is_hide_tab', 'keep_alive', 'code', 'level' ]; foreach ($item as $key => $value) { // 如果不是标准字段且不是auth_list,则放入extraFields if (!in_array($key, $standardFields) && $key !== 'auth_list') { // 转换下划线命名到驼峰命名 $camelKey = lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $key)))); $extraFields[$camelKey] = $value; } } return $extraFields; } }