You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

171 lines
6.0 KiB

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\AdminMenu;
use App\Models\RoleMenuPermission;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Schema;
class AdminMenuController extends Controller
{
public function index(Request $request): JsonResponse
{
$query = AdminMenu::query()
->where('is_visible', true)
->where(function ($query) {
$query->whereNull('path')->orWhere('path', '!=', '/study-tours/categories');
})
->orderBy('sort')
->orderBy('id');
$user = $request->user();
if ($user && Schema::hasTable('role_menu_permissions')) {
$roleMenuIds = RoleMenuPermission::query()
->where('role', (string) $user->role)
->pluck('menu_id')
->map(fn ($id) => (int) $id)
->values();
if ($roleMenuIds->isNotEmpty()) {
$query->whereIn('id', $roleMenuIds);
}
}
$menus = $query->get(['id', 'name', 'path', 'icon', 'parent_id', 'sort']);
$visibleIds = $menus->pluck('id')->map(fn ($id) => (int) $id)->values();
if ($visibleIds->isNotEmpty()) {
$parentIds = $menus->pluck('parent_id')->map(fn ($id) => (int) $id)->filter(fn ($id) => $id > 0)->unique()->values();
if ($parentIds->isNotEmpty()) {
$parents = AdminMenu::query()
->whereIn('id', $parentIds)
->where('is_visible', true)
->get(['id', 'name', 'path', 'icon', 'parent_id', 'sort']);
$menus = $menus->merge($parents)->unique('id')->sortBy([['sort', 'asc'], ['id', 'asc']])->values();
}
}
return response()->json($this->buildTree($menus));
}
public function listAll(Request $request): JsonResponse
{
$menus = AdminMenu::query()
->orderBy('sort')
->orderBy('id')
->get(['id', 'name', 'path', 'icon', 'parent_id', 'sort', 'is_visible']);
return response()->json($menus);
}
public function store(Request $request): JsonResponse
{
$this->ensureSuperAdmin($request);
$data = $request->validate([
'name' => ['required', 'string', 'max:100'],
'path' => ['nullable', 'string', 'max:255'],
'icon' => ['nullable', 'string', 'max:100'],
'parent_id' => ['nullable', 'integer', 'min:0'],
'sort' => ['nullable', 'integer', 'min:0'],
'is_visible' => ['nullable', 'boolean'],
]);
$parentId = (int) ($data['parent_id'] ?? 0);
if ($parentId > 0) {
$exists = AdminMenu::query()->where('id', $parentId)->exists();
abort_unless($exists, 422, '父级菜单不存在');
}
$menu = AdminMenu::create([
'name' => $data['name'],
'path' => $data['path'] ?? null,
'icon' => $data['icon'] ?? null,
'parent_id' => $parentId,
'sort' => (int) ($data['sort'] ?? 0),
'is_visible' => (bool) ($data['is_visible'] ?? true),
]);
return response()->json($menu, 201);
}
public function update(Request $request, AdminMenu $adminMenu): JsonResponse
{
$this->ensureSuperAdmin($request);
$data = $request->validate([
'name' => ['required', 'string', 'max:100'],
'path' => ['nullable', 'string', 'max:255'],
'icon' => ['nullable', 'string', 'max:100'],
'parent_id' => ['nullable', 'integer', 'min:0'],
'sort' => ['nullable', 'integer', 'min:0'],
'is_visible' => ['nullable', 'boolean'],
]);
$parentId = (int) ($data['parent_id'] ?? 0);
if ($parentId > 0) {
abort_unless($parentId !== $adminMenu->id, 422, '父级菜单不能是自身');
$exists = AdminMenu::query()->where('id', $parentId)->exists();
abort_unless($exists, 422, '父级菜单不存在');
}
$adminMenu->fill([
'name' => $data['name'],
'path' => $data['path'] ?? null,
'icon' => $data['icon'] ?? null,
'parent_id' => $parentId,
'sort' => (int) ($data['sort'] ?? 0),
'is_visible' => (bool) ($data['is_visible'] ?? true),
])->save();
return response()->json($adminMenu);
}
public function destroy(Request $request, AdminMenu $adminMenu): JsonResponse
{
$this->ensureSuperAdmin($request);
$hasChildren = AdminMenu::query()->where('parent_id', $adminMenu->id)->exists();
abort_if($hasChildren, 422, '请先删除子菜单');
$adminMenu->delete();
return response()->json(['message' => '删除成功']);
}
private function normalizeMenuName(string $name): string
{
if ($name === '黑名单管理') {
return '用户管理';
}
return $name;
}
private function ensureSuperAdmin(Request $request): void
{
abort_unless($request->user()?->isSuperAdmin(), 403, '仅超级管理员可操作');
}
private function buildTree($menus): array
{
return $menus->where('parent_id', 0)->values()->map(function (AdminMenu $menu) use ($menus) {
$children = $menus
->where('parent_id', $menu->id)
->values()
->map(fn (AdminMenu $child) => [
'id' => $child->id,
'name' => $this->normalizeMenuName($child->name),
'path' => $child->path,
'icon' => $child->icon,
])
->all();
return [
'id' => $menu->id,
'name' => $this->normalizeMenuName($menu->name),
'path' => $menu->path,
'icon' => $menu->icon,
'children' => $children,
];
})->all();
}
}