feat: 메뉴 복사 기능 - 2단계 복사 방식으로 화면 참조 매핑 문제 해결

- 문제: 화면 복사 시 참조되는 화면이 아직 복사되지 않아 screenIdMap에 매핑 정보가 없었음
- 해결: 2단계 복사 방식 도입
  1단계: 모든 screen_definitions 먼저 복사하여 screenIdMap 완성
  2단계: screen_layouts 복사하면서 완성된 screenIdMap으로 참조 업데이트
- 결과: targetScreenId가 올바르게 새 회사의 화면 ID로 매핑됨 (예: 149 → 517)
- 추가: 화면 수집 시 문자열 타입 ID도 올바르게 파싱하도록 개선
- 추가: 참조 화면 발견 및 업데이트 로그 추가

관련 파일:
- backend-node/src/services/menuCopyService.ts
- db/migrations/1003_add_source_menu_objid_to_menu_info.sql
- db/scripts/cleanup_company_11_*.sql
This commit is contained in:
kjs
2025-11-21 14:37:09 +09:00
parent bb49073bf7
commit c70998fa4f
11 changed files with 4021 additions and 16 deletions

View File

@@ -14,6 +14,7 @@ interface MenuTableProps {
title: string;
onAddMenu: (parentId: string, menuType: string, level: number) => void;
onEditMenu: (menuId: string) => void;
onCopyMenu: (menuId: string, menuName: string) => void; // 복사 추가
onToggleStatus: (menuId: string) => void;
selectedMenus: Set<string>;
onMenuSelectionChange: (menuId: string, checked: boolean) => void;
@@ -22,6 +23,7 @@ interface MenuTableProps {
onToggleExpand: (menuId: string) => void;
// 다국어 텍스트 props 추가
uiTexts: Record<string, string>;
isSuperAdmin?: boolean; // SUPER_ADMIN 여부 추가
}
export const MenuTable: React.FC<MenuTableProps> = ({
@@ -29,6 +31,7 @@ export const MenuTable: React.FC<MenuTableProps> = ({
title,
onAddMenu,
onEditMenu,
onCopyMenu,
onToggleStatus,
selectedMenus,
onMenuSelectionChange,
@@ -36,6 +39,7 @@ export const MenuTable: React.FC<MenuTableProps> = ({
expandedMenus,
onToggleExpand,
uiTexts,
isSuperAdmin = false, // 기본값 false
}) => {
// 다국어 텍스트 가져오기 함수
const getText = (key: string, fallback?: string): string => {
@@ -281,14 +285,26 @@ export const MenuTable: React.FC<MenuTableProps> = ({
<TableCell className="h-16">
<div className="flex flex-nowrap gap-1">
{lev === 1 && (
<Button
size="sm"
variant="outline"
className="min-w-[40px] px-1 py-1 text-xs"
onClick={() => onAddMenu(objid, menuType, lev)}
>
{getText(MENU_MANAGEMENT_KEYS.BUTTON_ADD)}
</Button>
<>
<Button
size="sm"
variant="outline"
className="min-w-[40px] px-1 py-1 text-xs"
onClick={() => onAddMenu(objid, menuType, lev)}
>
{getText(MENU_MANAGEMENT_KEYS.BUTTON_ADD)}
</Button>
{isSuperAdmin && (
<Button
size="sm"
variant="outline"
className="min-w-[40px] px-1 py-1 text-xs"
onClick={() => onCopyMenu(objid, menuNameKor || "메뉴")}
>
</Button>
)}
</>
)}
{lev === 2 && (
<>
@@ -308,17 +324,39 @@ export const MenuTable: React.FC<MenuTableProps> = ({
>
{getText(MENU_MANAGEMENT_KEYS.BUTTON_EDIT)}
</Button>
{isSuperAdmin && (
<Button
size="sm"
variant="outline"
className="min-w-[40px] px-1 py-1 text-xs"
onClick={() => onCopyMenu(objid, menuNameKor || "메뉴")}
>
</Button>
)}
</>
)}
{lev > 2 && (
<Button
size="sm"
variant="outline"
className="min-w-[40px] px-1 py-1 text-xs"
onClick={() => onEditMenu(objid)}
>
{getText(MENU_MANAGEMENT_KEYS.BUTTON_EDIT)}
</Button>
<>
<Button
size="sm"
variant="outline"
className="min-w-[40px] px-1 py-1 text-xs"
onClick={() => onEditMenu(objid)}
>
{getText(MENU_MANAGEMENT_KEYS.BUTTON_EDIT)}
</Button>
{isSuperAdmin && (
<Button
size="sm"
variant="outline"
className="min-w-[40px] px-1 py-1 text-xs"
onClick={() => onCopyMenu(objid, menuNameKor || "메뉴")}
>
</Button>
)}
</>
)}
</div>
</TableCell>