화면 분할패널 수정모드 수정

This commit is contained in:
kjs 2025-12-01 10:09:19 +09:00
parent bd4e3e507d
commit 1503dd87bb
3 changed files with 177 additions and 7 deletions

View File

@ -177,7 +177,6 @@ export const ScreenModal: React.FC<ScreenModalProps> = ({ className }) => {
});
setScreenData(null);
setFormData({});
setSelectedData([]); // 🆕 선택된 데이터 초기화
setContinuousMode(false);
localStorage.setItem("screenModal_continuousMode", "false"); // localStorage에 저장
console.log("🔄 연속 모드 초기화: false");
@ -637,8 +636,6 @@ export const ScreenModal: React.FC<ScreenModalProps> = ({ className }) => {
userId={userId}
userName={userName}
companyCode={user?.companyCode}
// 🆕 선택된 데이터 전달 (RepeatScreenModal 등에서 사용)
groupedData={selectedData.length > 0 ? selectedData : undefined}
/>
);
})}

View File

@ -244,11 +244,46 @@ const RepeaterFieldGroupComponent: React.FC<ComponentRendererProps> = (props) =>
const currentValue = parsedValueRef.current;
// mode가 "replace"인 경우 기존 데이터 대체, 그 외에는 추가
// 🆕 필터링된 데이터 사용
const mode = typeof mappingRulesOrMode === "string" ? mappingRulesOrMode : "append";
const newItems = mode === "replace" ? filteredData : [...currentValue, ...filteredData];
let newItems: any[];
let addedCount = 0;
let duplicateCount = 0;
if (mode === "replace") {
newItems = filteredData;
addedCount = filteredData.length;
} else {
// 🆕 중복 체크: id 또는 고유 식별자를 기준으로 이미 존재하는 항목 제외
const existingIds = new Set(
currentValue
.map((item: any) => item.id || item.po_item_id || item.item_id)
.filter(Boolean)
);
const uniqueNewItems = filteredData.filter((item: any) => {
const itemId = item.id || item.po_item_id || item.item_id;
if (itemId && existingIds.has(itemId)) {
duplicateCount++;
return false; // 중복 항목 제외
}
return true;
});
newItems = [...currentValue, ...uniqueNewItems];
addedCount = uniqueNewItems.length;
}
console.log("📥 [RepeaterFieldGroup] 최종 데이터:", { currentValue, newItems, mode });
console.log("📥 [RepeaterFieldGroup] 최종 데이터:", {
currentValue,
newItems,
mode,
addedCount,
duplicateCount,
});
// 🆕 groupedData 상태도 직접 업데이트 (UI 즉시 반영)
setGroupedData(newItems);
// JSON 문자열로 변환하여 저장
const jsonValue = JSON.stringify(newItems);
@ -268,7 +303,16 @@ const RepeaterFieldGroupComponent: React.FC<ComponentRendererProps> = (props) =>
onChangeRef.current(jsonValue);
}
toast.success(`${filteredData.length}개 항목이 추가되었습니다`);
// 결과 메시지 표시
if (addedCount > 0) {
if (duplicateCount > 0) {
toast.success(`${addedCount}개 항목이 추가되었습니다 (${duplicateCount}개 중복 제외)`);
} else {
toast.success(`${addedCount}개 항목이 추가되었습니다`);
}
} else if (duplicateCount > 0) {
toast.warning(`${duplicateCount}개 항목이 이미 추가되어 있습니다`);
}
}, []);
// DataReceivable 인터페이스 구현
@ -311,6 +355,31 @@ const RepeaterFieldGroupComponent: React.FC<ComponentRendererProps> = (props) =>
}
}, [splitPanelContext, screenContext?.splitPanelPosition, component.id, dataReceiver]);
// 🆕 전역 이벤트 리스너 (splitPanelDataTransfer)
useEffect(() => {
const handleSplitPanelDataTransfer = (event: CustomEvent) => {
const { data, mode, mappingRules } = event.detail;
console.log("📥 [RepeaterFieldGroup] splitPanelDataTransfer 이벤트 수신:", {
dataCount: data?.length,
mode,
componentId: component.id,
});
// 우측 패널의 리피터 필드 그룹만 데이터를 수신
const splitPanelPosition = screenContext?.splitPanelPosition;
if (splitPanelPosition === "right" && data && data.length > 0) {
handleReceiveData(data, mappingRules || mode || "append");
}
};
window.addEventListener("splitPanelDataTransfer", handleSplitPanelDataTransfer as EventListener);
return () => {
window.removeEventListener("splitPanelDataTransfer", handleSplitPanelDataTransfer as EventListener);
};
}, [screenContext?.splitPanelPosition, handleReceiveData, component.id]);
return (
<RepeaterInput
value={parsedValue}

View File

@ -237,6 +237,9 @@ export class ButtonActionExecutor {
case "code_merge":
return await this.handleCodeMerge(config, context);
case "transferData":
return await this.handleTransferData(config, context);
default:
console.warn(`지원되지 않는 액션 타입: ${config.type}`);
return false;
@ -3190,6 +3193,102 @@ export class ButtonActionExecutor {
}
}
/**
* ( )
*/
private static async handleTransferData(config: ButtonActionConfig, context: ButtonActionContext): Promise<boolean> {
try {
console.log("📤 [handleTransferData] 데이터 전달 시작:", { config, context });
// 선택된 행 데이터 확인
const selectedRows = context.selectedRowsData || context.flowSelectedData || [];
if (!selectedRows || selectedRows.length === 0) {
toast.error("전달할 데이터를 선택해주세요.");
return false;
}
console.log("📤 [handleTransferData] 선택된 데이터:", selectedRows);
// dataTransfer 설정 확인
const dataTransfer = config.dataTransfer;
if (!dataTransfer) {
// dataTransfer 설정이 없으면 기본 동작: 전역 이벤트로 데이터 전달
console.log("📤 [handleTransferData] dataTransfer 설정 없음 - 전역 이벤트 발생");
const transferEvent = new CustomEvent("splitPanelDataTransfer", {
detail: {
data: selectedRows,
mode: "append",
sourcePosition: "left",
},
});
window.dispatchEvent(transferEvent);
toast.success(`${selectedRows.length}개 항목이 전달되었습니다.`);
return true;
}
// dataTransfer 설정이 있는 경우
const { targetType, targetComponentId, targetScreenId, mappingRules, receiveMode } = dataTransfer;
if (targetType === "component" && targetComponentId) {
// 같은 화면 내 컴포넌트로 전달
console.log("📤 [handleTransferData] 컴포넌트로 전달:", targetComponentId);
const transferEvent = new CustomEvent("componentDataTransfer", {
detail: {
targetComponentId,
data: selectedRows,
mappingRules,
mode: receiveMode || "append",
},
});
window.dispatchEvent(transferEvent);
toast.success(`${selectedRows.length}개 항목이 전달되었습니다.`);
return true;
} else if (targetType === "screen" && targetScreenId) {
// 다른 화면으로 전달 (분할 패널 등)
console.log("📤 [handleTransferData] 화면으로 전달:", targetScreenId);
const transferEvent = new CustomEvent("screenDataTransfer", {
detail: {
targetScreenId,
data: selectedRows,
mappingRules,
mode: receiveMode || "append",
},
});
window.dispatchEvent(transferEvent);
toast.success(`${selectedRows.length}개 항목이 전달되었습니다.`);
return true;
} else {
// 기본: 분할 패널 데이터 전달 이벤트
console.log("📤 [handleTransferData] 기본 분할 패널 전달");
const transferEvent = new CustomEvent("splitPanelDataTransfer", {
detail: {
data: selectedRows,
mappingRules,
mode: receiveMode || "append",
sourcePosition: "left",
},
});
window.dispatchEvent(transferEvent);
toast.success(`${selectedRows.length}개 항목이 전달되었습니다.`);
return true;
}
} catch (error: any) {
console.error("❌ 데이터 전달 실패:", error);
toast.error(error.message || "데이터 전달 중 오류가 발생했습니다.");
return false;
}
}
/**
*
*/
@ -3293,4 +3392,9 @@ export const DEFAULT_BUTTON_ACTIONS: Record<ButtonActionType, Partial<ButtonActi
successMessage: "코드 병합이 완료되었습니다.",
errorMessage: "코드 병합 중 오류가 발생했습니다.",
},
transferData: {
type: "transferData",
successMessage: "데이터가 전달되었습니다.",
errorMessage: "데이터 전달 중 오류가 발생했습니다.",
},
};