From 9dc8a51f4c4cd1378419aa2e2d7910cc4b32b28c Mon Sep 17 00:00:00 2001 From: kjs Date: Thu, 13 Nov 2025 12:27:36 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EB=A9=94=EB=89=B4=20URL=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0=20=EC=8B=9C=20=ED=99=94=EB=A9=B4=20=ED=95=A0=EB=8B=B9?= =?UTF-8?q?=EB=8F=84=20=ED=95=A8=EA=BB=98=20=ED=95=B4=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 문제점 - menu_url을 빈 값으로 저장해도 screen_menu_assignments 테이블의 화면 할당(is_active='Y')이 남아있어 메뉴 클릭 시 여전히 화면이 열림 - AppLayout의 handleMenuClick이 우선적으로 screen_menu_assignments를 조회하므로 menu_url보다 화면 할당이 우선 적용됨 ## 해결방법 ### updateMenu (메뉴 수정) - menu_url이 null/빈값일 때 screen_menu_assignments의 is_active를 'N'으로 업데이트 - 화면 할당과 menu_url을 동기화하여 완전한 할당 해제 ### saveMenu (메뉴 생성) - 기존과 동일하게 menu_url이 없으면 screen_code를 null로 설정 - INSERT 시 screen_code 컬럼을 명시적으로 포함 ## 메뉴 클릭 동작 순서 1. screen_menu_assignments 조회 (우선순위) 2. is_active='N'이면 할당된 화면 없음으로 간주 3. menu_url이 있으면 해당 URL로 이동 4. 둘 다 없으면 "연결된 페이지가 없습니다" 경고 이제 메뉴에서 URL을 제거하면 화면 할당도 완전히 해제됩니다. --- .../src/controllers/adminController.ts | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/backend-node/src/controllers/adminController.ts b/backend-node/src/controllers/adminController.ts index 02a11996..b3ecbffb 100644 --- a/backend-node/src/controllers/adminController.ts +++ b/backend-node/src/controllers/adminController.ts @@ -1127,12 +1127,16 @@ export async function saveMenu( const objid = Date.now(); // 고유 ID 생성 const companyCode = requestCompanyCode || userCompanyCode; + // menu_url이 비어있으면 screen_code도 null로 설정 + const menuUrl = menuData.menuUrl || null; + const screenCode = menuUrl ? menuData.screenCode || null : null; + const [savedMenu] = await query( `INSERT INTO menu_info ( objid, menu_type, parent_obj_id, menu_name_kor, menu_name_eng, seq, menu_url, menu_desc, writer, regdate, status, - system_name, company_code, lang_key, lang_key_desc - ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15) + system_name, company_code, lang_key, lang_key_desc, screen_code + ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16) RETURNING *`, [ objid, @@ -1141,7 +1145,7 @@ export async function saveMenu( menuData.menuNameKor, menuData.menuNameEng || null, menuData.seq ? Number(menuData.seq) : null, - menuData.menuUrl || null, + menuUrl, menuData.menuDesc || null, req.user?.userId || "admin", new Date(), @@ -1150,6 +1154,7 @@ export async function saveMenu( companyCode, menuData.langKey || null, menuData.langKeyDesc || null, + screenCode, ] ); @@ -1314,6 +1319,17 @@ export async function updateMenu( ] ); + // menu_url이 비어있으면 화면 할당도 해제 (screen_menu_assignments의 is_active를 'N'으로) + if (!menuUrl) { + await query( + `UPDATE screen_menu_assignments + SET is_active = 'N', updated_date = NOW() + WHERE menu_objid = $1 AND company_code = $2`, + [Number(menuId), companyCode] + ); + logger.info("화면 할당 비활성화", { menuId, companyCode }); + } + logger.info("메뉴 수정 성공", { updatedMenu }); const response: ApiResponse = {