화면 복사기능 수정
This commit is contained in:
@@ -2101,55 +2101,109 @@ export class ScreenManagementService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 화면에 연결된 모달 화면들을 자동 감지
|
||||
* 버튼 컴포넌트의 popup 액션에서 targetScreenId를 추출
|
||||
* 화면에 연결된 모달/화면들을 재귀적으로 자동 감지
|
||||
* - 버튼 컴포넌트: popup/modal/edit/openModalWithData 액션의 targetScreenId
|
||||
* - 조건부 컨테이너: sections[].screenId (조건별 화면 할당)
|
||||
* - 중첩된 화면들도 모두 감지 (재귀)
|
||||
*/
|
||||
async detectLinkedModalScreens(
|
||||
screenId: number
|
||||
): Promise<{ screenId: number; screenName: string; screenCode: string }[]> {
|
||||
// 화면의 모든 레이아웃 조회
|
||||
const layouts = await query<any>(
|
||||
`SELECT layout_id, properties
|
||||
FROM screen_layouts
|
||||
WHERE screen_id = $1
|
||||
AND component_type = 'component'
|
||||
AND properties IS NOT NULL`,
|
||||
[screenId]
|
||||
);
|
||||
console.log(`\n🔍 [재귀 감지 시작] 화면 ID: ${screenId}`);
|
||||
|
||||
const allLinkedScreenIds = new Set<number>();
|
||||
const visited = new Set<number>(); // 무한 루프 방지
|
||||
const queue: number[] = [screenId]; // BFS 큐
|
||||
|
||||
const linkedScreenIds = new Set<number>();
|
||||
// BFS로 연결된 모든 화면 탐색
|
||||
while (queue.length > 0) {
|
||||
const currentScreenId = queue.shift()!;
|
||||
|
||||
// 이미 방문한 화면은 스킵 (순환 참조 방지)
|
||||
if (visited.has(currentScreenId)) {
|
||||
console.log(`⏭️ 이미 방문한 화면 스킵: ${currentScreenId}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
visited.add(currentScreenId);
|
||||
console.log(`\n📋 현재 탐색 중인 화면: ${currentScreenId} (깊이: ${visited.size})`);
|
||||
|
||||
// 각 레이아웃에서 버튼의 popup/modal/edit 액션 확인
|
||||
for (const layout of layouts) {
|
||||
try {
|
||||
const properties = layout.properties;
|
||||
|
||||
// 버튼 컴포넌트인지 확인
|
||||
if (properties?.componentType === "button" || properties?.componentType?.startsWith("button-")) {
|
||||
const action = properties?.componentConfig?.action;
|
||||
// 현재 화면의 모든 레이아웃 조회
|
||||
const layouts = await query<any>(
|
||||
`SELECT layout_id, properties
|
||||
FROM screen_layouts
|
||||
WHERE screen_id = $1
|
||||
AND component_type = 'component'
|
||||
AND properties IS NOT NULL`,
|
||||
[currentScreenId]
|
||||
);
|
||||
|
||||
console.log(` 📦 레이아웃 개수: ${layouts.length}`);
|
||||
|
||||
// 각 레이아웃에서 연결된 화면 ID 확인
|
||||
for (const layout of layouts) {
|
||||
try {
|
||||
const properties = layout.properties;
|
||||
|
||||
// popup, modal, edit 액션이고 targetScreenId가 있는 경우
|
||||
// edit 액션도 수정 폼 모달을 열기 때문에 포함
|
||||
if ((action?.type === "popup" || action?.type === "modal" || action?.type === "edit") && action?.targetScreenId) {
|
||||
const targetScreenId = parseInt(action.targetScreenId);
|
||||
if (!isNaN(targetScreenId)) {
|
||||
linkedScreenIds.add(targetScreenId);
|
||||
console.log(`🔗 연결된 모달 화면 발견: screenId=${targetScreenId}, actionType=${action.type} (레이아웃 ${layout.layout_id})`);
|
||||
// 1. 버튼 컴포넌트의 액션 확인
|
||||
if (properties?.componentType === "button" || properties?.componentType?.startsWith("button-")) {
|
||||
const action = properties?.componentConfig?.action;
|
||||
|
||||
const modalActionTypes = ["popup", "modal", "edit", "openModalWithData"];
|
||||
if (modalActionTypes.includes(action?.type) && action?.targetScreenId) {
|
||||
const targetScreenId = parseInt(action.targetScreenId);
|
||||
if (!isNaN(targetScreenId) && targetScreenId !== currentScreenId) {
|
||||
// 메인 화면이 아닌 경우에만 추가
|
||||
if (targetScreenId !== screenId) {
|
||||
allLinkedScreenIds.add(targetScreenId);
|
||||
}
|
||||
// 아직 방문하지 않은 화면이면 큐에 추가
|
||||
if (!visited.has(targetScreenId)) {
|
||||
queue.push(targetScreenId);
|
||||
console.log(` 🔗 [버튼] 연결된 화면 발견: ${targetScreenId} (action: ${action.type}) → 큐에 추가`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. conditional-container 컴포넌트의 sections 확인
|
||||
if (properties?.componentType === "conditional-container") {
|
||||
const sections = properties?.componentConfig?.sections || [];
|
||||
|
||||
for (const section of sections) {
|
||||
if (section?.screenId) {
|
||||
const sectionScreenId = parseInt(section.screenId);
|
||||
if (!isNaN(sectionScreenId) && sectionScreenId !== currentScreenId) {
|
||||
// 메인 화면이 아닌 경우에만 추가
|
||||
if (sectionScreenId !== screenId) {
|
||||
allLinkedScreenIds.add(sectionScreenId);
|
||||
}
|
||||
// 아직 방문하지 않은 화면이면 큐에 추가
|
||||
if (!visited.has(sectionScreenId)) {
|
||||
queue.push(sectionScreenId);
|
||||
console.log(` 🔗 [조건부컨테이너] 연결된 화면 발견: ${sectionScreenId} (condition: ${section.condition}) → 큐에 추가`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(` ⚠️ 레이아웃 ${layout.layout_id} 파싱 오류:`, error);
|
||||
}
|
||||
} catch (error) {
|
||||
// JSON 파싱 오류 등은 무시하고 계속 진행
|
||||
console.warn(`레이아웃 ${layout.layout_id} 파싱 오류:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n✅ [재귀 감지 완료] 총 방문한 화면: ${visited.size}개, 연결된 화면: ${allLinkedScreenIds.size}개`);
|
||||
console.log(` 방문한 화면 ID: [${Array.from(visited).join(", ")}]`);
|
||||
console.log(` 연결된 화면 ID: [${Array.from(allLinkedScreenIds).join(", ")}]`);
|
||||
|
||||
// 감지된 화면 ID들의 정보 조회
|
||||
if (linkedScreenIds.size === 0) {
|
||||
if (allLinkedScreenIds.size === 0) {
|
||||
console.log(`ℹ️ 연결된 화면이 없습니다.`);
|
||||
return [];
|
||||
}
|
||||
|
||||
const screenIds = Array.from(linkedScreenIds);
|
||||
const screenIds = Array.from(allLinkedScreenIds);
|
||||
const placeholders = screenIds.map((_, i) => `$${i + 1}`).join(", ");
|
||||
|
||||
const linkedScreens = await query<any>(
|
||||
@@ -2161,6 +2215,11 @@ export class ScreenManagementService {
|
||||
screenIds
|
||||
);
|
||||
|
||||
console.log(`\n📋 최종 감지된 화면 목록:`);
|
||||
linkedScreens.forEach((s: any) => {
|
||||
console.log(` - ${s.screen_name} (ID: ${s.screen_id}, 코드: ${s.screen_code})`);
|
||||
});
|
||||
|
||||
return linkedScreens.map((s) => ({
|
||||
screenId: s.screen_id,
|
||||
screenName: s.screen_name,
|
||||
@@ -2430,23 +2489,23 @@ export class ScreenManagementService {
|
||||
for (const layout of layouts) {
|
||||
try {
|
||||
const properties = layout.properties;
|
||||
let needsUpdate = false;
|
||||
|
||||
// 버튼 컴포넌트인지 확인
|
||||
// 1. 버튼 컴포넌트의 targetScreenId 업데이트
|
||||
if (
|
||||
properties?.componentType === "button" ||
|
||||
properties?.componentType?.startsWith("button-")
|
||||
) {
|
||||
const action = properties?.componentConfig?.action;
|
||||
|
||||
// targetScreenId가 있는 액션 (popup, modal, edit)
|
||||
// targetScreenId가 있는 액션 (popup, modal, edit, openModalWithData)
|
||||
const modalActionTypes = ["popup", "modal", "edit", "openModalWithData"];
|
||||
if (
|
||||
(action?.type === "popup" ||
|
||||
action?.type === "modal" ||
|
||||
action?.type === "edit") &&
|
||||
modalActionTypes.includes(action?.type) &&
|
||||
action?.targetScreenId
|
||||
) {
|
||||
const oldScreenId = parseInt(action.targetScreenId);
|
||||
console.log(`🔍 버튼 발견: layout ${layout.layout_id}, action=${action.type}, targetScreenId=${oldScreenId}`);
|
||||
console.log(`🔍 [버튼] 발견: layout ${layout.layout_id}, action=${action.type}, targetScreenId=${oldScreenId}`);
|
||||
|
||||
// 매핑에 있으면 업데이트
|
||||
if (screenIdMapping.has(oldScreenId)) {
|
||||
@@ -2456,31 +2515,63 @@ export class ScreenManagementService {
|
||||
// properties 업데이트
|
||||
properties.componentConfig.action.targetScreenId =
|
||||
newScreenId.toString();
|
||||
needsUpdate = true;
|
||||
|
||||
// 데이터베이스 업데이트
|
||||
await query(
|
||||
`UPDATE screen_layouts
|
||||
SET properties = $1
|
||||
WHERE layout_id = $2`,
|
||||
[JSON.stringify(properties), layout.layout_id]
|
||||
);
|
||||
|
||||
updateCount++;
|
||||
console.log(
|
||||
`🔗 버튼 targetScreenId 업데이트: ${oldScreenId} → ${newScreenId} (layout ${layout.layout_id})`
|
||||
`🔗 [버튼] targetScreenId 업데이트 준비: ${oldScreenId} → ${newScreenId} (layout ${layout.layout_id})`
|
||||
);
|
||||
} else {
|
||||
console.log(`⚠️ 매핑 없음: ${oldScreenId} (업데이트 건너뜀)`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. conditional-container 컴포넌트의 sections[].screenId 업데이트
|
||||
if (properties?.componentType === "conditional-container") {
|
||||
const sections = properties?.componentConfig?.sections || [];
|
||||
|
||||
for (const section of sections) {
|
||||
if (section?.screenId) {
|
||||
const oldScreenId = parseInt(section.screenId);
|
||||
console.log(`🔍 [조건부컨테이너] section 발견: layout ${layout.layout_id}, condition=${section.condition}, screenId=${oldScreenId}`);
|
||||
|
||||
// 매핑에 있으면 업데이트
|
||||
if (screenIdMapping.has(oldScreenId)) {
|
||||
const newScreenId = screenIdMapping.get(oldScreenId)!;
|
||||
console.log(`✅ 매핑 발견: ${oldScreenId} → ${newScreenId}`);
|
||||
|
||||
// section.screenId 업데이트
|
||||
section.screenId = newScreenId;
|
||||
needsUpdate = true;
|
||||
|
||||
console.log(
|
||||
`🔗 [조건부컨테이너] screenId 업데이트 준비: ${oldScreenId} → ${newScreenId} (layout ${layout.layout_id}, condition=${section.condition})`
|
||||
);
|
||||
} else {
|
||||
console.log(`⚠️ 매핑 없음: ${oldScreenId} (업데이트 건너뜀)`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 업데이트가 필요한 경우 DB 저장
|
||||
if (needsUpdate) {
|
||||
await query(
|
||||
`UPDATE screen_layouts
|
||||
SET properties = $1
|
||||
WHERE layout_id = $2`,
|
||||
[JSON.stringify(properties), layout.layout_id]
|
||||
);
|
||||
updateCount++;
|
||||
console.log(`💾 레이아웃 ${layout.layout_id} 업데이트 완료`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(`❌ 레이아웃 ${layout.layout_id} 업데이트 오류:`, error);
|
||||
// 개별 레이아웃 오류는 무시하고 계속 진행
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`✅ 총 ${updateCount}개 버튼의 targetScreenId 업데이트 완료`);
|
||||
console.log(`✅ 총 ${updateCount}개 레이아웃의 연결된 화면 ID 업데이트 완료 (버튼 + 조건부컨테이너)`);
|
||||
return updateCount;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user