feat(menus): 메뉴 일괄 선택 삭제/복구/영구삭제 기능 추가

- GlobalMenu 모델에 getSection(), getMeta() 메서드 추가 (import 모드 500 에러 해결)
- table.blade.php: normal 모드에서 체크박스 + 드래그 핸들 분리
- index.blade.php: 선택 삭제/복구/영구삭제 버튼 및 JS 함수 추가
- MenuController: bulkDelete, bulkRestore, bulkForceDelete API 추가
- routes/api.php: bulk 엔드포인트 3개 등록

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-22 10:51:06 +09:00
parent 20d92ea51b
commit 3f34e84bfc
5 changed files with 361 additions and 3 deletions

View File

@@ -450,4 +450,109 @@ public function copyFromGlobal(Request $request): JsonResponse
], 500);
}
}
/**
* 선택 삭제 (일괄 soft delete)
*/
public function bulkDelete(Request $request): JsonResponse
{
$validated = $request->validate([
'menu_ids' => 'required|array|min:1',
'menu_ids.*' => 'required|integer',
]);
try {
$deleted = 0;
foreach ($validated['menu_ids'] as $menuId) {
if ($this->menuService->deleteMenu($menuId)) {
$deleted++;
}
}
return response()->json([
'success' => true,
'message' => "{$deleted}개 메뉴가 삭제되었습니다.",
'deleted' => $deleted,
]);
} catch (\Exception $e) {
return response()->json([
'success' => false,
'message' => '메뉴 삭제에 실패했습니다: '.$e->getMessage(),
], 500);
}
}
/**
* 선택 복원 (일괄 restore)
*/
public function bulkRestore(Request $request): JsonResponse
{
$validated = $request->validate([
'menu_ids' => 'required|array|min:1',
'menu_ids.*' => 'required|integer',
]);
try {
$restored = 0;
foreach ($validated['menu_ids'] as $menuId) {
$this->menuService->restoreMenu($menuId);
$restored++;
}
return response()->json([
'success' => true,
'message' => "{$restored}개 메뉴가 복원되었습니다.",
'restored' => $restored,
]);
} catch (\Exception $e) {
return response()->json([
'success' => false,
'message' => '메뉴 복원에 실패했습니다: '.$e->getMessage(),
], 500);
}
}
/**
* 선택 영구삭제 (일괄 force delete, 슈퍼관리자 전용)
*/
public function bulkForceDelete(Request $request): JsonResponse
{
// 슈퍼관리자 권한 체크
if (! auth()->user()?->is_super_admin) {
return response()->json([
'success' => false,
'message' => '권한이 없습니다.',
], 403);
}
$validated = $request->validate([
'menu_ids' => 'required|array|min:1',
'menu_ids.*' => 'required|integer',
]);
try {
$deleted = 0;
$totalPermissions = 0;
foreach ($validated['menu_ids'] as $menuId) {
$result = $this->menuService->forceDeleteMenu($menuId);
if ($result['success']) {
$deleted++;
$totalPermissions += count($result['deleted_permissions'] ?? []);
}
}
return response()->json([
'success' => true,
'message' => "{$deleted}개 메뉴가 영구 삭제되었습니다. (연관 권한 {$totalPermissions}개 삭제)",
'deleted' => $deleted,
'deleted_permissions' => $totalPermissions,
]);
} catch (\Exception $e) {
return response()->json([
'success' => false,
'message' => '메뉴 영구삭제에 실패했습니다: '.$e->getMessage(),
], 500);
}
}
}