135 lines
5.2 KiB
PHP
135 lines
5.2 KiB
PHP
<?php
|
||
|
||
namespace App\Services\Nasa;
|
||
|
||
use App\Models\Nasa\Navigation as NasaNavigation;
|
||
use Illuminate\Support\Collection;
|
||
|
||
class NavigationService
|
||
{
|
||
public function aGetInfo($sCurrentPermissionSlug): array
|
||
{
|
||
// 1. 获取当前高亮的菜单节点
|
||
$oCurrentMenu = NasaNavigation::where("sPermissionSlug", $sCurrentPermissionSlug)
|
||
->available()
|
||
->first();
|
||
|
||
if (!$oCurrentMenu) {
|
||
return [
|
||
"aTopMenus" => $this->aGetTopMenus(),
|
||
"aSubMenus" => [],
|
||
"aTabMenus" => [],
|
||
"aMenuPath" => [],
|
||
];
|
||
}
|
||
|
||
$aTopMenus = $this->aGetTopMenus();
|
||
|
||
// 2. 获取面包屑的原始集合(链条顺序依然是:[一级, 二级, 三级...])
|
||
$cMenuPathCollection = $oCurrentMenu->cGetAncestorsAndSelf();
|
||
|
||
// ================= 核心修改:利用 keyBy 将 sComponentType 作为键 =================
|
||
// 它会自动将数组转换为:['TOP_BAR' => [...], 'LEFT_MENU' => [...]] 的高内聚结构
|
||
$aMenuPath = $cMenuPathCollection->keyBy('sComponentType')->toArray();
|
||
// ==============================================================================
|
||
|
||
// 3. 提取一级根节点(注意:集合 keyBy 后内部指针会变,所以我们从原集合中安全 get(0) 获取一级)
|
||
$oRootMenu = $cMenuPathCollection->first();
|
||
|
||
$aSubMenus = [];
|
||
$aTabMenus = [];
|
||
|
||
if ($oRootMenu) {
|
||
// 拉出该顶级菜单下的所有无限级子树
|
||
$oRootMenuWithTree = NasaNavigation::with('childrenRecursive')
|
||
->where('id', $oRootMenu->id)
|
||
->first();
|
||
|
||
if ($oRootMenuWithTree && $oRootMenuWithTree->childrenRecursive) {
|
||
// 【二级侧边栏逻辑】:保持原样
|
||
$aSubMenus = $oRootMenuWithTree->childrenRecursive
|
||
->transform(function (NasaNavigation $oSubMenu) {
|
||
$oSubMenu->sUrl = $oSubMenu->sGetFinalUrl();
|
||
return $oSubMenu;
|
||
})
|
||
->groupBy('sGroup')
|
||
->toArray();
|
||
|
||
// ================= 三级 Tab 菜单解析优化 =================
|
||
// 以前是通过 ->get(1) 硬编码拿二级。现在既然改了结构,
|
||
// 我们可以直接通过你定义的二级类型键(假设叫 TYPE_SIDE_BAR,请根据你 Model 里的常量自行替换)安全捞取
|
||
$oLevel2Menu = $cMenuPathCollection->firstWhere('sComponentType', NasaNavigation::TYPE_SIDEBAR_MENU);
|
||
|
||
if ($oLevel2Menu) {
|
||
// 去子树内存里捞出这个二级节点
|
||
$oCurrentLevel2InTree = $oRootMenuWithTree->childrenRecursive
|
||
->firstWhere('id', $oLevel2Menu->id);
|
||
|
||
if ($oCurrentLevel2InTree && $oCurrentLevel2InTree->childrenRecursive->isNotEmpty()) {
|
||
$aTabMenus = $oCurrentLevel2InTree->childrenRecursive
|
||
->transform(function (NasaNavigation $oTabMenu) {
|
||
$oTabMenu->sUrl = $oTabMenu->sGetFinalUrl();
|
||
return $oTabMenu;
|
||
})
|
||
->toArray();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return [
|
||
"aTopMenus" => $aTopMenus,
|
||
"aSubMenus" => $aSubMenus,
|
||
"aTabMenus" => $aTabMenus,
|
||
"aMenuPath" => $aMenuPath, // 这里的键已经是你的组件类型字符串了
|
||
];
|
||
}
|
||
|
||
|
||
/**
|
||
* 获取全局顶级大区 (TOP_BAR)
|
||
*/
|
||
public function aGetTopMenus(): array
|
||
{
|
||
return NasaNavigation::with('childrenRecursive') // 一口气拉出无限级树结构,只有 2-3 条 SQL
|
||
->where('iParentId', 0)
|
||
->where('sComponentType', NasaNavigation::TYPE_TOP_BAR)
|
||
->available()
|
||
->orderBy('iSort', 'asc')
|
||
->get()
|
||
->transform(function (NasaNavigation $oMenu) {
|
||
// 让顶级菜单自己去递归嗅探最底层的有效 URL
|
||
$oMenu->sUrl = $oMenu->sGetFinalUrl();
|
||
return $oMenu;
|
||
})
|
||
->groupBy('sGroup')
|
||
->toArray();
|
||
}
|
||
|
||
/**
|
||
* 抓取侧边栏业务菜单树
|
||
*/
|
||
public function aGetSubMenus($iParentId): Array
|
||
{
|
||
return NasaNavigation::where('iParentId', $iParentId)
|
||
->where('sComponentType', NasaNavigation::TYPE_SIDEBAR_MENU)
|
||
->available()
|
||
->orderBy('iSort', 'asc')
|
||
->get()
|
||
->map(function ($oMenu) {
|
||
// 将模型转成数组
|
||
$aMenu = $oMenu->toArray();
|
||
|
||
// 🎯 核心防空伞:动态算好 sUrl,有就给,没有就给空字符串 ''
|
||
$aMenu['sUrl'] = \Illuminate\Support\Facades\Route::has($oMenu->sPermissionSlug)
|
||
? route($oMenu->sPermissionSlug)
|
||
: '';
|
||
|
||
return $aMenu;
|
||
})
|
||
->groupBy('sGroup')
|
||
->toArray();
|
||
}
|
||
|
||
}
|