From f6691730ceed412c95fe374207b43841b7be4d2f Mon Sep 17 00:00:00 2001 From: Hyungi Ahn Date: Sat, 25 Oct 2025 09:24:32 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EB=AA=A9=EB=A1=9D=20=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=203=EA=B0=9C=20=ED=95=98=EC=9C=84=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EA=B6=8C=ED=95=9C=20=EC=8B=9C=EC=8A=A4=ED=85=9C=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 목록 관리를 수신함, 관리함, 폐기함 3개 하위 페이지로 세분화하고 각각 별도의 권한 관리가 가능하도록 시스템 구현 Backend Changes: - page_permissions.py: issues_inbox, issues_management, issues_archive 권한 추가 - 수신함: 기본 접근 허용 (true) - 관리함, 폐기함: 관리자 권한 필요 (false) Frontend Changes: - permissions.js: 3개 하위 페이지 권한 정의 추가 - common-header.js: 드롭다운 하위 메뉴 구조 구현 * 데스크톱: 호버 드롭다운 메뉴 * 모바일: 접을 수 있는 하위 메뉴 - admin.html: 권한 관리 UI에 새 페이지들 추가 Features: - 권한별 하위 메뉴 필터링 - 반응형 드롭다운 메뉴 - 개별 페이지별 권한 제어 - 관리자 페이지에서 세부 권한 설정 가능 Next: 실제 페이지 파일 생성 및 기능 구현 예정 --- backend/routers/page_permissions.py | 3 + frontend/admin.html | 5 +- .../static/js/components/common-header.js | 108 +++++++++++++++++- frontend/static/js/core/permissions.js | 3 + 4 files changed, 116 insertions(+), 3 deletions(-) diff --git a/backend/routers/page_permissions.py b/backend/routers/page_permissions.py index 2971fe6..4258208 100644 --- a/backend/routers/page_permissions.py +++ b/backend/routers/page_permissions.py @@ -45,6 +45,9 @@ DEFAULT_PAGES = { 'issues_create': {'title': '부적합 등록', 'default_access': True}, 'issues_view': {'title': '부적합 조회', 'default_access': True}, 'issues_manage': {'title': '부적합 관리', 'default_access': True}, + 'issues_inbox': {'title': '수신함', 'default_access': True}, + 'issues_management': {'title': '관리함', 'default_access': False}, + 'issues_archive': {'title': '폐기함', 'default_access': False}, 'projects_manage': {'title': '프로젝트 관리', 'default_access': False}, 'daily_work': {'title': '일일 공수', 'default_access': False}, 'reports': {'title': '보고서', 'default_access': False} diff --git a/frontend/admin.html b/frontend/admin.html index 852e725..d53831f 100644 --- a/frontend/admin.html +++ b/frontend/admin.html @@ -525,7 +525,10 @@ const defaultPages = { 'issues_create': { title: '부적합 등록', defaultAccess: true }, 'issues_view': { title: '부적합 조회', defaultAccess: true }, - 'issues_manage': { title: '부적합 관리', defaultAccess: false }, + 'issues_manage': { title: '부적합 관리', defaultAccess: true }, + 'issues_inbox': { title: '수신함', defaultAccess: true }, + 'issues_management': { title: '관리함', defaultAccess: false }, + 'issues_archive': { title: '폐기함', defaultAccess: false }, 'projects_manage': { title: '프로젝트 관리', defaultAccess: false }, 'daily_work': { title: '일일 공수', defaultAccess: false }, 'reports': { title: '보고서', defaultAccess: false } diff --git a/frontend/static/js/components/common-header.js b/frontend/static/js/components/common-header.js index 4c7f061..84c6a7d 100644 --- a/frontend/static/js/components/common-header.js +++ b/frontend/static/js/components/common-header.js @@ -49,7 +49,33 @@ class CommonHeader { url: '/index.html#list', pageName: 'issues_manage', color: 'text-orange-600', - bgColor: 'bg-orange-50 hover:bg-orange-100' + bgColor: 'bg-orange-50 hover:bg-orange-100', + subMenus: [ + { + id: 'issues_inbox', + title: '수신함', + icon: 'fas fa-inbox', + url: '/issues-inbox.html', + pageName: 'issues_inbox', + color: 'text-blue-600' + }, + { + id: 'issues_management', + title: '관리함', + icon: 'fas fa-cog', + url: '/issues-management.html', + pageName: 'issues_management', + color: 'text-green-600' + }, + { + id: 'issues_archive', + title: '폐기함', + icon: 'fas fa-archive', + url: '/issues-archive.html', + pageName: 'issues_archive', + color: 'text-gray-600' + } + ] }, { id: 'reports', @@ -229,6 +255,10 @@ class CommonHeader { return this.menuItems.filter(menu => { // admin은 모든 메뉴 접근 가능 if (this.currentUser?.role === 'admin') { + // 하위 메뉴가 있는 경우 하위 메뉴도 필터링 + if (menu.subMenus) { + menu.accessibleSubMenus = menu.subMenus; + } return true; } @@ -237,7 +267,20 @@ class CommonHeader { return ['issues_create', 'issues_view'].includes(menu.id); } - return window.canAccessPage(menu.pageName); + // 메인 메뉴 권한 체크 + const hasMainAccess = window.canAccessPage(menu.pageName); + + // 하위 메뉴가 있는 경우 접근 가능한 하위 메뉴 필터링 + if (menu.subMenus) { + menu.accessibleSubMenus = menu.subMenus.filter(subMenu => + window.canAccessPage(subMenu.pageName) + ); + + // 메인 메뉴 접근 권한이 없어도 하위 메뉴 중 하나라도 접근 가능하면 표시 + return hasMainAccess || menu.accessibleSubMenus.length > 0; + } + + return hasMainAccess; }); } @@ -248,6 +291,36 @@ class CommonHeader { const isActive = this.currentPage === menu.id; const activeClass = isActive ? 'bg-blue-100 text-blue-700' : `${menu.bgColor} ${menu.color}`; + // 하위 메뉴가 있는 경우 드롭다운 메뉴 생성 + if (menu.accessibleSubMenus && menu.accessibleSubMenus.length > 0) { + return ` +
+ + + + +
+ `; + } + + // 일반 메뉴 아이템 return ` 0) { + return ` +
+ + + + +
+ `; + } + + // 일반 메뉴 아이템 return `