From bab960b50ee5582768fca4b3d921e0264f0118e2 Mon Sep 17 00:00:00 2001 From: kjs Date: Tue, 11 Nov 2025 10:29:47 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=97=91=EC=85=80=20=EB=8B=A4=EC=9A=B4?= =?UTF-8?q?=EB=A1=9C=EB=93=9C=20=ED=8C=8C=EC=9D=BC=EB=AA=85=EC=9D=84=20?= =?UTF-8?q?=EB=A9=94=EB=89=B4=20=EC=9D=B4=EB=A6=84=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 메뉴 클릭 시 localStorage에 메뉴 이름 저장 (useMenu, AppLayout) - 엑셀 다운로드 시 localStorage의 메뉴 이름을 파일명으로 사용 - 백엔드 카테고리 컬럼 조회 쿼리 파라미터 버그 수정 - API 호출 시 불필요한 autoFilter 파라미터 제거 파일명 형식: {메뉴이름}_{날짜}.xlsx 예시: 품목등록테스트_2025-11-11.xlsx --- .../src/services/tableCategoryValueService.ts | 4 +++- frontend/components/layout/AppLayout.tsx | 6 ++++++ frontend/hooks/useMenu.ts | 6 ++++++ frontend/lib/utils/buttonActions.ts | 16 +++++++++++++--- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/backend-node/src/services/tableCategoryValueService.ts b/backend-node/src/services/tableCategoryValueService.ts index 8a20aac1..7646dead 100644 --- a/backend-node/src/services/tableCategoryValueService.ts +++ b/backend-node/src/services/tableCategoryValueService.ts @@ -62,7 +62,9 @@ class TableCategoryValueService { logger.info("회사별 카테고리 컬럼 조회", { companyCode }); } - const result = await pool.query(query, [tableName, companyCode]); + // 쿼리 파라미터는 company_code에 따라 다름 + const params = companyCode === "*" ? [tableName] : [tableName, companyCode]; + const result = await pool.query(query, params); logger.info(`카테고리 컬럼 ${result.rows.length}개 조회 완료`, { tableName, diff --git a/frontend/components/layout/AppLayout.tsx b/frontend/components/layout/AppLayout.tsx index 1ad00044..51c070cd 100644 --- a/frontend/components/layout/AppLayout.tsx +++ b/frontend/components/layout/AppLayout.tsx @@ -259,6 +259,12 @@ function AppLayoutInner({ children }: AppLayoutProps) { if (menu.hasChildren) { toggleMenu(menu.id); } else { + // 메뉴 이름 저장 (엑셀 다운로드 파일명에 사용) + const menuName = menu.label || menu.name || "메뉴"; + if (typeof window !== "undefined") { + localStorage.setItem("currentMenuName", menuName); + } + // 먼저 할당된 화면이 있는지 확인 (URL 유무와 관계없이) try { const menuObjid = menu.objid || menu.id; diff --git a/frontend/hooks/useMenu.ts b/frontend/hooks/useMenu.ts index bab8a68f..48c93ce7 100644 --- a/frontend/hooks/useMenu.ts +++ b/frontend/hooks/useMenu.ts @@ -160,6 +160,12 @@ export const useMenu = (user: any, authLoading: boolean) => { if (menu.children && menu.children.length > 0) { toggleMenu(String(menu.OBJID)); } else { + // 메뉴 이름 저장 (엑셀 다운로드 파일명에 사용) + const menuName = menu.MENU_NAME_KOR || menu.menuNameKor || menu.TRANSLATED_NAME || "메뉴"; + if (typeof window !== "undefined") { + localStorage.setItem("currentMenuName", menuName); + } + // 먼저 할당된 화면이 있는지 확인 (URL 유무와 관계없이) try { const menuObjid = menu.OBJID || menu.objid; diff --git a/frontend/lib/utils/buttonActions.ts b/frontend/lib/utils/buttonActions.ts index 6f6a8f4d..ef3b3747 100644 --- a/frontend/lib/utils/buttonActions.ts +++ b/frontend/lib/utils/buttonActions.ts @@ -1970,7 +1970,7 @@ export class ButtonActionExecutor { sortOrder: (context.sortOrder || storedData?.sortOrder || "asc") as "asc" | "desc", search: filterConditions, // ✅ 필터 조건 enableEntityJoin: true, // ✅ Entity 조인 - autoFilter: true, // ✅ company_code 자동 필터링 (멀티테넌시) + // autoFilter는 entityJoinApi.getTableDataWithJoins 내부에서 자동으로 적용됨 }; // 🔒 멀티테넌시 준수: autoFilter로 company_code 자동 적용 @@ -2027,8 +2027,18 @@ export class ButtonActionExecutor { return false; } - // 파일명 생성 - const fileName = config.excelFileName || `${context.tableName || "데이터"}_${new Date().toISOString().split("T")[0]}.xlsx`; + // 파일명 생성 (메뉴 이름 우선 사용) + let defaultFileName = context.tableName || "데이터"; + + // localStorage에서 메뉴 이름 가져오기 + if (typeof window !== "undefined") { + const menuName = localStorage.getItem("currentMenuName"); + if (menuName) { + defaultFileName = menuName; + } + } + + const fileName = config.excelFileName || `${defaultFileName}_${new Date().toISOString().split("T")[0]}.xlsx`; const sheetName = config.excelSheetName || "Sheet1"; const includeHeaders = config.excelIncludeHeaders !== false;