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
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();
|
|
}
|
|
}
|