refactor: 코드 정리 및 불필요한 로그 제거
- scheduleService.ts에서 스케줄 생성 로직을 간소화하고, 불필요한 줄바꿈을 제거하여 가독성을 향상시켰습니다. - v2-sales-order-modal-layout.json에서 JSON 포맷을 정리하여 일관성을 유지했습니다. - page.tsx, ScreenModal.tsx, ScreenDesigner.tsx, V2Input.tsx, V2Select.tsx, V2SelectConfigPanel.tsx, SimpleRepeaterTableComponent.tsx, ButtonPrimaryComponent.tsx, FileUploadComponent.tsx 등 여러 파일에서 디버깅 로그를 제거하여 코드의 깔끔함을 유지했습니다. - 전반적으로 코드의 가독성을 높이고, 불필요한 로그를 제거하여 유지보수성을 개선했습니다.
This commit is contained in:
@@ -123,34 +123,16 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
}, [isRecordMode, recordTableName, recordId, columnName]);
|
||||
|
||||
// 🔑 레코드별 고유 키 생성 (localStorage, 전역 상태용)
|
||||
// 🆕 columnName을 포함하여 같은 화면의 여러 파일 업로드 컴포넌트 구분
|
||||
const getUniqueKey = useCallback(() => {
|
||||
if (isRecordMode && recordTableName && recordId) {
|
||||
// 레코드 모드: 테이블명:레코드ID:컴포넌트ID 형태로 고유 키 생성
|
||||
return `fileUpload_${recordTableName}_${recordId}_${component.id}`;
|
||||
// 레코드 모드: 테이블명:레코드ID:컴포넌트ID:컬럼명 형태로 고유 키 생성
|
||||
return `fileUpload_${recordTableName}_${recordId}_${component.id}_${columnName}`;
|
||||
}
|
||||
// 기본 모드: 컴포넌트 ID만 사용
|
||||
return `fileUpload_${component.id}`;
|
||||
}, [isRecordMode, recordTableName, recordId, component.id]);
|
||||
// 기본 모드: 컴포넌트 ID + 컬럼명 사용
|
||||
return `fileUpload_${component.id}_${columnName}`;
|
||||
}, [isRecordMode, recordTableName, recordId, component.id, columnName]);
|
||||
|
||||
// 🔍 디버깅: 레코드 모드 상태 로깅
|
||||
useEffect(() => {
|
||||
console.log("📎 [FileUploadComponent] 모드 확인:", {
|
||||
isRecordMode,
|
||||
recordTableName,
|
||||
recordId,
|
||||
columnName,
|
||||
targetObjid: getRecordTargetObjid(),
|
||||
uniqueKey: getUniqueKey(),
|
||||
formDataKeys: formData ? Object.keys(formData) : [],
|
||||
// 🔍 추가 디버깅: formData.id 확인 (수정 모드 판단에 사용됨)
|
||||
"formData.id": formData?.id,
|
||||
"formData.tableName": formData?.tableName,
|
||||
"formData.image": formData?.image,
|
||||
"component.tableName": component.tableName,
|
||||
"component.columnName": component.columnName,
|
||||
"component.id": component.id,
|
||||
});
|
||||
}, [isRecordMode, recordTableName, recordId, columnName, getRecordTargetObjid, getUniqueKey, formData, component.tableName, component.columnName, component.id]);
|
||||
|
||||
// 🆕 레코드 ID 변경 시 파일 목록 초기화 및 새로 로드
|
||||
const prevRecordIdRef = useRef<any>(null);
|
||||
@@ -160,19 +142,12 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
const modeChanged = prevIsRecordModeRef.current !== null && prevIsRecordModeRef.current !== isRecordMode;
|
||||
|
||||
if (recordIdChanged || modeChanged) {
|
||||
console.log("📎 [FileUploadComponent] 레코드 상태 변경 감지:", {
|
||||
prevRecordId: prevRecordIdRef.current,
|
||||
currentRecordId: recordId,
|
||||
prevIsRecordMode: prevIsRecordModeRef.current,
|
||||
currentIsRecordMode: isRecordMode,
|
||||
});
|
||||
prevRecordIdRef.current = recordId;
|
||||
prevIsRecordModeRef.current = isRecordMode;
|
||||
|
||||
// 레코드 ID가 변경되거나 등록 모드(isRecordMode=false)로 전환되면 파일 목록 초기화
|
||||
// 등록 모드에서는 항상 빈 상태로 시작해야 함
|
||||
if (isRecordMode || !recordId) {
|
||||
console.log("📎 [FileUploadComponent] 파일 목록 초기화 (새 레코드 또는 레코드 변경)");
|
||||
setUploadedFiles([]);
|
||||
setRepresentativeImageUrl(null);
|
||||
}
|
||||
@@ -189,7 +164,6 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
|
||||
// 등록 모드(새 레코드)인 경우 파일 복원 스킵 - 빈 상태 유지
|
||||
if (!isRecordMode || !recordId) {
|
||||
console.log("📎 [FileUploadComponent] 등록 모드: 파일 복원 스킵 (빈 상태 유지)");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -200,13 +174,6 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
if (backupFiles) {
|
||||
const parsedFiles = JSON.parse(backupFiles);
|
||||
if (parsedFiles.length > 0) {
|
||||
console.log("🚀 컴포넌트 마운트 시 파일 즉시 복원:", {
|
||||
uniqueKey: backupKey,
|
||||
componentId: component.id,
|
||||
recordId: recordId,
|
||||
restoredFiles: parsedFiles.length,
|
||||
files: parsedFiles.map((f: any) => ({ objid: f.objid, name: f.realFileName })),
|
||||
});
|
||||
setUploadedFiles(parsedFiles);
|
||||
|
||||
// 전역 상태에도 복원 (레코드별 고유 키 사용)
|
||||
@@ -224,26 +191,20 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
}, [component.id, getUniqueKey, recordId, isRecordMode]); // 레코드별 고유 키 변경 시 재실행
|
||||
|
||||
// 🔑 수정 모드: formData[columnName]에 저장된 objid로 이미지 로드
|
||||
// 이 로직은 isRecordMode와 상관없이 formData에 이미지 objid가 있으면 표시
|
||||
// 🆕 formData 전체가 아닌 특정 컬럼 값만 의존하도록 수정 (다른 컴포넌트 영향 방지)
|
||||
const imageObjidFromFormData = formData?.[columnName];
|
||||
|
||||
useEffect(() => {
|
||||
const imageObjid = formData?.[columnName];
|
||||
|
||||
// 이미지 objid가 있고, 숫자 문자열인 경우에만 처리
|
||||
if (imageObjid && /^\d+$/.test(String(imageObjid))) {
|
||||
console.log("🖼️ [FileUploadComponent] formData에서 이미지 objid 발견:", {
|
||||
columnName,
|
||||
imageObjid,
|
||||
currentFilesCount: uploadedFiles.length,
|
||||
});
|
||||
if (imageObjidFromFormData && /^\d+$/.test(String(imageObjidFromFormData))) {
|
||||
const objidStr = String(imageObjidFromFormData);
|
||||
|
||||
// 이미 같은 objid의 파일이 로드되어 있으면 스킵
|
||||
const alreadyLoaded = uploadedFiles.some(f => String(f.objid) === String(imageObjid));
|
||||
const alreadyLoaded = uploadedFiles.some(f => String(f.objid) === objidStr);
|
||||
if (alreadyLoaded) {
|
||||
console.log("🖼️ [FileUploadComponent] 이미 로드된 이미지, 스킵");
|
||||
return;
|
||||
}
|
||||
|
||||
const objidStr = String(imageObjid);
|
||||
const previewUrl = `/api/files/preview/${objidStr}`;
|
||||
|
||||
// 🔑 실제 파일 정보 조회
|
||||
@@ -254,12 +215,6 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
if (fileInfoResponse.success && fileInfoResponse.data) {
|
||||
const { realFileName, fileSize, fileExt, regdate, isRepresentative } = fileInfoResponse.data;
|
||||
|
||||
console.log("🖼️ [FileUploadComponent] 파일 정보 조회 성공:", {
|
||||
objid: objidStr,
|
||||
realFileName,
|
||||
fileExt,
|
||||
});
|
||||
|
||||
const fileInfo = {
|
||||
objid: objidStr,
|
||||
realFileName: realFileName,
|
||||
@@ -296,46 +251,39 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
}
|
||||
})();
|
||||
}
|
||||
}, [formData, columnName, uploadedFiles]);
|
||||
}, [imageObjidFromFormData, columnName, component.id]); // 🆕 formData 대신 특정 컬럼 값만 의존
|
||||
|
||||
// 🎯 화면설계 모드에서 실제 화면으로의 실시간 동기화 이벤트 리스너
|
||||
// 🆕 columnName도 체크하여 같은 화면의 다른 파일 업로드 컴포넌트와 구분
|
||||
useEffect(() => {
|
||||
const handleDesignModeFileChange = (event: CustomEvent) => {
|
||||
console.log("🎯🎯🎯 FileUploadComponent 화면설계 모드 파일 변경 이벤트 수신:", {
|
||||
eventComponentId: event.detail.componentId,
|
||||
currentComponentId: component.id,
|
||||
isMatch: event.detail.componentId === component.id,
|
||||
filesCount: event.detail.files?.length || 0,
|
||||
action: event.detail.action,
|
||||
source: event.detail.source,
|
||||
eventDetail: event.detail,
|
||||
});
|
||||
const eventColumnName = event.detail.eventColumnName || event.detail.columnName;
|
||||
|
||||
// 🆕 고유 키 또는 (컴포넌트ID + 컬럼명) 조합으로 체크
|
||||
const isForThisComponent =
|
||||
(event.detail.uniqueKey && event.detail.uniqueKey === currentUniqueKey) ||
|
||||
(event.detail.componentId === component.id && eventColumnName === columnName) ||
|
||||
(event.detail.componentId === component.id && !eventColumnName); // 이전 호환성
|
||||
|
||||
// 현재 컴포넌트와 일치하고 화면설계 모드에서 온 이벤트인 경우
|
||||
if (event.detail.componentId === component.id && event.detail.source === "designMode") {
|
||||
// 🆕 현재 컴포넌트와 일치하고 화면설계 모드에서 온 이벤트인 경우
|
||||
if (isForThisComponent && event.detail.source === "designMode") {
|
||||
// 파일 상태 업데이트
|
||||
const newFiles = event.detail.files || [];
|
||||
setUploadedFiles(newFiles);
|
||||
|
||||
// localStorage 백업 업데이트 (레코드별 고유 키 사용)
|
||||
try {
|
||||
const backupKey = getUniqueKey();
|
||||
const backupKey = currentUniqueKey;
|
||||
localStorage.setItem(backupKey, JSON.stringify(newFiles));
|
||||
console.log("💾 화면설계 모드 동기화 후 localStorage 백업 업데이트:", {
|
||||
uniqueKey: backupKey,
|
||||
componentId: component.id,
|
||||
recordId: recordId,
|
||||
fileCount: newFiles.length,
|
||||
});
|
||||
} catch (e) {
|
||||
console.warn("localStorage 백업 업데이트 실패:", e);
|
||||
}
|
||||
|
||||
// 전역 상태 업데이트
|
||||
// 전역 상태 업데이트 (🆕 고유 키 사용)
|
||||
if (typeof window !== "undefined") {
|
||||
(window as any).globalFileState = {
|
||||
...(window as any).globalFileState,
|
||||
[component.id]: newFiles,
|
||||
[currentUniqueKey]: newFiles,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -346,11 +294,6 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
lastFileUpdate: event.detail.timestamp,
|
||||
});
|
||||
}
|
||||
|
||||
console.log("🎉🎉🎉 화면설계 모드 → 실제 화면 동기화 완료:", {
|
||||
componentId: component.id,
|
||||
finalFileCount: newFiles.length,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -369,25 +312,10 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
|
||||
// 🔑 등록 모드(새 레코드)인 경우 파일 조회 스킵 - 빈 상태 유지
|
||||
if (!isRecordMode || !recordId) {
|
||||
console.log("📂 [FileUploadComponent] 등록 모드: 파일 조회 스킵 (빈 상태 유지)", {
|
||||
isRecordMode,
|
||||
recordId,
|
||||
componentId: component.id,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// 🔑 레코드 모드: 해당 행의 파일만 조회
|
||||
if (isRecordMode && recordTableName && recordId) {
|
||||
console.log("📂 [FileUploadComponent] 레코드 모드 파일 조회:", {
|
||||
tableName: recordTableName,
|
||||
recordId: recordId,
|
||||
columnName: columnName,
|
||||
targetObjid: getRecordTargetObjid(),
|
||||
});
|
||||
}
|
||||
|
||||
// 1. formData에서 screenId 가져오기
|
||||
let screenId = formData?.screenId;
|
||||
|
||||
@@ -424,8 +352,6 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
columnName: columnName, // 🔑 레코드 모드에서 사용하는 columnName
|
||||
};
|
||||
|
||||
console.log("📂 [FileUploadComponent] 파일 조회 파라미터:", params);
|
||||
|
||||
const response = await getComponentFiles(params);
|
||||
|
||||
if (response.success) {
|
||||
@@ -457,12 +383,6 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
const additionalFiles = parsedBackupFiles.filter((f: any) => !serverObjIds.has(f.objid));
|
||||
|
||||
finalFiles = [...formattedFiles, ...additionalFiles];
|
||||
console.log("📂 [FileUploadComponent] 파일 병합 완료:", {
|
||||
uniqueKey,
|
||||
serverFiles: formattedFiles.length,
|
||||
localFiles: parsedBackupFiles.length,
|
||||
finalFiles: finalFiles.length,
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn("파일 병합 중 오류:", e);
|
||||
@@ -505,16 +425,6 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
const componentFiles = (component as any)?.uploadedFiles || [];
|
||||
const lastUpdate = (component as any)?.lastFileUpdate;
|
||||
|
||||
console.log("🔄 FileUploadComponent 파일 동기화 시작:", {
|
||||
componentId: component.id,
|
||||
componentFiles: componentFiles.length,
|
||||
formData: formData,
|
||||
screenId: formData?.screenId,
|
||||
tableName: formData?.tableName, // 🔍 테이블명 확인
|
||||
recordId: formData?.id, // 🔍 레코드 ID 확인
|
||||
currentUploadedFiles: uploadedFiles.length,
|
||||
});
|
||||
|
||||
// 🔒 항상 DB에서 최신 파일 목록을 조회 (멀티테넌시 격리)
|
||||
loadComponentFiles().then((dbLoadSuccess) => {
|
||||
if (dbLoadSuccess) {
|
||||
@@ -523,9 +433,10 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
|
||||
// DB 로드 실패 시에만 기존 로직 사용 (하위 호환성)
|
||||
|
||||
// 전역 상태에서 최신 파일 정보 가져오기
|
||||
// 전역 상태에서 최신 파일 정보 가져오기 (🆕 고유 키 사용)
|
||||
const globalFileState = typeof window !== "undefined" ? (window as any).globalFileState || {} : {};
|
||||
const globalFiles = globalFileState[component.id] || [];
|
||||
const uniqueKeyForFallback = getUniqueKey();
|
||||
const globalFiles = globalFileState[uniqueKeyForFallback] || globalFileState[component.id] || [];
|
||||
|
||||
// 최신 파일 정보 사용 (전역 상태 > 컴포넌트 속성)
|
||||
const currentFiles = globalFiles.length > 0 ? globalFiles : componentFiles;
|
||||
@@ -540,36 +451,27 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
}, [loadComponentFiles, component.id, (component as any)?.uploadedFiles, (component as any)?.lastFileUpdate]);
|
||||
|
||||
// 전역 상태 변경 감지 (모든 파일 컴포넌트 동기화 + 화면 복원)
|
||||
// 🆕 columnName을 포함한 고유 키로 구분하여 다른 파일 업로드 컴포넌트에 영향 방지
|
||||
const currentUniqueKey = getUniqueKey();
|
||||
|
||||
useEffect(() => {
|
||||
const handleGlobalFileStateChange = (event: CustomEvent) => {
|
||||
const { componentId, files, fileCount, timestamp, isRestore } = event.detail;
|
||||
const { componentId, files, fileCount, timestamp, isRestore, uniqueKey: eventUniqueKey, eventColumnName } = event.detail;
|
||||
|
||||
console.log("🔄 FileUploadComponent 전역 상태 변경 감지:", {
|
||||
currentComponentId: component.id,
|
||||
eventComponentId: componentId,
|
||||
isForThisComponent: componentId === component.id,
|
||||
newFileCount: fileCount,
|
||||
currentFileCount: uploadedFiles.length,
|
||||
timestamp,
|
||||
isRestore: !!isRestore,
|
||||
});
|
||||
// 🆕 고유 키 또는 (컴포넌트ID + 컬럼명) 조합으로 체크
|
||||
const isForThisComponent =
|
||||
(eventUniqueKey && eventUniqueKey === currentUniqueKey) ||
|
||||
(componentId === component.id && eventColumnName === columnName);
|
||||
|
||||
// 같은 컴포넌트 ID인 경우에만 업데이트
|
||||
if (componentId === component.id) {
|
||||
const logMessage = isRestore ? "🔄 화면 복원으로 파일 상태 동기화" : "✅ 파일 상태 동기화 적용";
|
||||
console.log(logMessage, {
|
||||
componentId: component.id,
|
||||
이전파일수: uploadedFiles?.length || 0,
|
||||
새파일수: files?.length || 0,
|
||||
files: files?.map((f: any) => ({ objid: f.objid, name: f.realFileName })) || [],
|
||||
});
|
||||
// 🆕 같은 고유 키인 경우에만 업데이트 (componentId + columnName 조합)
|
||||
if (isForThisComponent) {
|
||||
|
||||
setUploadedFiles(files);
|
||||
setForceUpdate((prev) => prev + 1);
|
||||
|
||||
// localStorage 백업도 업데이트 (레코드별 고유 키 사용)
|
||||
try {
|
||||
const backupKey = getUniqueKey();
|
||||
const backupKey = currentUniqueKey;
|
||||
localStorage.setItem(backupKey, JSON.stringify(files));
|
||||
} catch (e) {
|
||||
console.warn("localStorage 백업 실패:", e);
|
||||
@@ -584,7 +486,7 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
window.removeEventListener("globalFileStateChanged", handleGlobalFileStateChange as EventListener);
|
||||
};
|
||||
}
|
||||
}, [component.id, uploadedFiles.length]);
|
||||
}, [component.id, columnName, currentUniqueKey, uploadedFiles.length]);
|
||||
|
||||
// 파일 업로드 설정 - componentConfig가 undefined일 수 있으므로 안전하게 처리
|
||||
const safeComponentConfig = componentConfig || {};
|
||||
@@ -598,18 +500,8 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
|
||||
// 파일 선택 핸들러
|
||||
const handleFileSelect = useCallback(() => {
|
||||
console.log("🎯 handleFileSelect 호출됨:", {
|
||||
hasFileInputRef: !!fileInputRef.current,
|
||||
fileInputRef: fileInputRef.current,
|
||||
fileInputType: fileInputRef.current?.type,
|
||||
fileInputHidden: fileInputRef.current?.className,
|
||||
});
|
||||
|
||||
if (fileInputRef.current) {
|
||||
console.log("✅ fileInputRef.current.click() 호출");
|
||||
fileInputRef.current.click();
|
||||
} else {
|
||||
console.log("❌ fileInputRef.current가 null입니다");
|
||||
}
|
||||
}, []);
|
||||
|
||||
@@ -680,34 +572,17 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
if (effectiveIsRecordMode && effectiveTableName && effectiveRecordId) {
|
||||
// 🎯 레코드 모드: 특정 행에 파일 연결
|
||||
targetObjid = `${effectiveTableName}:${effectiveRecordId}:${effectiveColumnName}`;
|
||||
console.log("📁 [레코드 모드] 파일 업로드:", {
|
||||
targetObjid,
|
||||
tableName: effectiveTableName,
|
||||
recordId: effectiveRecordId,
|
||||
columnName: effectiveColumnName,
|
||||
});
|
||||
} else if (screenId) {
|
||||
// 🔑 템플릿 파일 (백엔드 조회 형식과 동일하게)
|
||||
targetObjid = `screen_files:${screenId}:${component.id}:${effectiveColumnName}`;
|
||||
console.log("📝 [템플릿 모드] 파일 업로드:", targetObjid);
|
||||
} else {
|
||||
// 기본값 (화면관리에서 사용)
|
||||
targetObjid = `temp_${component.id}`;
|
||||
console.log("📝 [기본 모드] 파일 업로드:", targetObjid);
|
||||
}
|
||||
|
||||
// 🔒 현재 사용자의 회사 코드 가져오기 (멀티테넌시 격리)
|
||||
const userCompanyCode = user?.companyCode || (window as any).__user__?.companyCode;
|
||||
|
||||
console.log("📤 [FileUploadComponent] 파일 업로드 준비:", {
|
||||
userCompanyCode,
|
||||
isRecordMode: effectiveIsRecordMode,
|
||||
tableName: effectiveTableName,
|
||||
recordId: effectiveRecordId,
|
||||
columnName: effectiveColumnName,
|
||||
targetObjid,
|
||||
});
|
||||
|
||||
// 🔑 레코드 모드일 때는 effectiveTableName을 우선 사용
|
||||
// formData.linkedTable이 'screen_files' 같은 기본값일 수 있으므로 레코드 모드에서는 무시
|
||||
const finalLinkedTable = effectiveIsRecordMode
|
||||
@@ -732,27 +607,11 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
isRecordMode: effectiveIsRecordMode,
|
||||
};
|
||||
|
||||
console.log("📤 [FileUploadComponent] uploadData 최종:", {
|
||||
isRecordMode: effectiveIsRecordMode,
|
||||
linkedTable: finalLinkedTable,
|
||||
recordId: effectiveRecordId,
|
||||
columnName: effectiveColumnName,
|
||||
targetObjid,
|
||||
});
|
||||
|
||||
|
||||
console.log("🚀 [FileUploadComponent] uploadFiles API 호출 직전:", {
|
||||
filesCount: filesToUpload.length,
|
||||
uploadData,
|
||||
});
|
||||
|
||||
const response = await uploadFiles({
|
||||
files: filesToUpload,
|
||||
...uploadData,
|
||||
});
|
||||
|
||||
console.log("📥 [FileUploadComponent] uploadFiles API 응답:", response);
|
||||
|
||||
if (response.success) {
|
||||
// FileUploadResponse 타입에 맞게 files 배열 사용
|
||||
const fileData = response.files || (response as any).data || [];
|
||||
@@ -811,9 +670,11 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
});
|
||||
|
||||
// 모든 파일 컴포넌트에 동기화 이벤트 발생
|
||||
// 🆕 columnName 추가하여 같은 화면의 다른 파일 업로드 컴포넌트와 구분
|
||||
const syncEvent = new CustomEvent("globalFileStateChanged", {
|
||||
detail: {
|
||||
componentId: component.id,
|
||||
eventColumnName: columnName, // 🆕 컬럼명 추가
|
||||
uniqueKey: uniqueKey, // 🆕 고유 키 추가
|
||||
recordId: recordId, // 🆕 레코드 ID 추가
|
||||
files: updatedFiles,
|
||||
@@ -822,25 +683,11 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
},
|
||||
});
|
||||
window.dispatchEvent(syncEvent);
|
||||
|
||||
console.log("🌐 전역 파일 상태 업데이트 및 동기화 이벤트 발생:", {
|
||||
componentId: component.id,
|
||||
fileCount: updatedFiles.length,
|
||||
globalState: Object.keys(globalFileState).map((id) => ({
|
||||
id,
|
||||
fileCount: globalFileState[id]?.length || 0,
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
// 컴포넌트 업데이트
|
||||
if (onUpdate) {
|
||||
const timestamp = Date.now();
|
||||
console.log("🔄 onUpdate 호출:", {
|
||||
componentId: component.id,
|
||||
uploadedFiles: updatedFiles.length,
|
||||
timestamp: timestamp,
|
||||
});
|
||||
onUpdate({
|
||||
uploadedFiles: updatedFiles,
|
||||
lastFileUpdate: timestamp,
|
||||
@@ -858,15 +705,6 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
? fileObjids.join(',') // 복수 파일: 콤마 구분
|
||||
: (fileObjids[0] || ''); // 단일 파일: 첫 번째 파일 ID
|
||||
|
||||
console.log("📎 [파일 업로드] 컬럼 데이터 동기화:", {
|
||||
tableName: effectiveTableName,
|
||||
recordId: effectiveRecordId,
|
||||
columnName: effectiveColumnName,
|
||||
columnValue,
|
||||
fileCount: updatedFiles.length,
|
||||
isMultiple: fileConfig.multiple,
|
||||
});
|
||||
|
||||
// onFormDataChange를 (fieldName, value) 형태로 호출 (SaveModal 호환)
|
||||
onFormDataChange(effectiveColumnName, columnValue);
|
||||
}
|
||||
@@ -883,13 +721,6 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
},
|
||||
});
|
||||
window.dispatchEvent(refreshEvent);
|
||||
console.log("🔄 그리드 파일 상태 새로고침 이벤트 발생:", {
|
||||
tableName: effectiveTableName,
|
||||
recordId: effectiveRecordId,
|
||||
columnName: effectiveColumnName,
|
||||
targetObjid,
|
||||
fileCount: updatedFiles.length,
|
||||
});
|
||||
}
|
||||
|
||||
// 컴포넌트 설정 콜백
|
||||
@@ -972,9 +803,11 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
(window as any).globalFileState = globalFileState;
|
||||
|
||||
// 모든 파일 컴포넌트에 동기화 이벤트 발생
|
||||
// 🆕 columnName 추가하여 같은 화면의 다른 파일 업로드 컴포넌트와 구분
|
||||
const syncEvent = new CustomEvent("globalFileStateChanged", {
|
||||
detail: {
|
||||
componentId: component.id,
|
||||
eventColumnName: columnName, // 🆕 컬럼명 추가
|
||||
uniqueKey: uniqueKey, // 🆕 고유 키 추가
|
||||
recordId: recordId, // 🆕 레코드 ID 추가
|
||||
files: updatedFiles,
|
||||
@@ -985,12 +818,6 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
},
|
||||
});
|
||||
window.dispatchEvent(syncEvent);
|
||||
|
||||
console.log("🗑️ 파일 삭제 후 전역 상태 동기화:", {
|
||||
componentId: component.id,
|
||||
deletedFile: fileName,
|
||||
remainingFiles: updatedFiles.length,
|
||||
});
|
||||
}
|
||||
|
||||
// 컴포넌트 업데이트
|
||||
@@ -1010,14 +837,6 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
? fileObjids.join(',')
|
||||
: (fileObjids[0] || '');
|
||||
|
||||
console.log("📎 [파일 삭제] 컬럼 데이터 동기화:", {
|
||||
tableName: recordTableName,
|
||||
recordId: recordId,
|
||||
columnName: columnName,
|
||||
columnValue,
|
||||
remainingFiles: updatedFiles.length,
|
||||
});
|
||||
|
||||
// onFormDataChange를 (fieldName, value) 형태로 호출 (SaveModal 호환)
|
||||
onFormDataChange(columnName, columnValue);
|
||||
}
|
||||
@@ -1053,16 +872,10 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
|
||||
// 🔑 이미 previewUrl이 설정된 경우 바로 사용 (API 호출 스킵)
|
||||
if (file.previewUrl) {
|
||||
console.log("🖼️ 대표 이미지: previewUrl 사용:", file.previewUrl);
|
||||
setRepresentativeImageUrl(file.previewUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("🖼️ 대표 이미지 로드 시작:", {
|
||||
objid: file.objid,
|
||||
fileName: file.realFileName,
|
||||
});
|
||||
|
||||
// API 클라이언트를 통해 Blob으로 다운로드 (인증 토큰 포함)
|
||||
// 🔑 download 대신 preview 사용 (공개 접근)
|
||||
const response = await apiClient.get(`/files/preview/${file.objid}`, {
|
||||
@@ -1082,7 +895,6 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
}
|
||||
|
||||
setRepresentativeImageUrl(url);
|
||||
console.log("✅ 대표 이미지 로드 성공:", url);
|
||||
} catch (error: any) {
|
||||
console.error("❌ 대표 이미지 로드 실패:", {
|
||||
file: file.realFileName,
|
||||
@@ -1113,12 +925,6 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
|
||||
// 대표 이미지 로드
|
||||
loadRepresentativeImage(file);
|
||||
|
||||
console.log("✅ 대표 파일 설정 완료:", {
|
||||
componentId: component.id,
|
||||
representativeFile: file.realFileName,
|
||||
objid: file.objid,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("❌ 대표 파일 설정 실패:", e);
|
||||
}
|
||||
@@ -1146,22 +952,13 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
// 드래그 앤 드롭 핸들러
|
||||
const handleDragOver = useCallback(
|
||||
(e: React.DragEvent) => {
|
||||
console.log("🎯 드래그 오버 이벤트 감지:", {
|
||||
readonly: safeComponentConfig.readonly,
|
||||
disabled: safeComponentConfig.disabled,
|
||||
dragOver: dragOver,
|
||||
});
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (!safeComponentConfig.readonly && !safeComponentConfig.disabled) {
|
||||
setDragOver(true);
|
||||
console.log("✅ 드래그 오버 활성화");
|
||||
} else {
|
||||
console.log("❌ 드래그 차단됨: readonly 또는 disabled");
|
||||
}
|
||||
},
|
||||
[safeComponentConfig.readonly, safeComponentConfig.disabled, dragOver],
|
||||
[safeComponentConfig.readonly, safeComponentConfig.disabled],
|
||||
);
|
||||
|
||||
const handleDragLeave = useCallback((e: React.DragEvent) => {
|
||||
@@ -1189,19 +986,10 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
|
||||
// 클릭 핸들러
|
||||
const handleClick = useCallback(
|
||||
(e: React.MouseEvent) => {
|
||||
console.log("🖱️ 파일 업로드 영역 클릭:", {
|
||||
readonly: safeComponentConfig.readonly,
|
||||
disabled: safeComponentConfig.disabled,
|
||||
hasHandleFileSelect: !!handleFileSelect,
|
||||
});
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (!safeComponentConfig.readonly && !safeComponentConfig.disabled) {
|
||||
console.log("✅ 파일 선택 함수 호출");
|
||||
handleFileSelect();
|
||||
} else {
|
||||
console.log("❌ 클릭 차단됨: readonly 또는 disabled");
|
||||
}
|
||||
onClick?.();
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user