Compare commits
No commits in common. "c7efe8ec33d714c8a46b407f0d0251d80e7ced74" and "54ca51258c25da4c5ca03c562789d14a813f526d" have entirely different histories.
c7efe8ec33
...
54ca51258c
|
|
@ -963,13 +963,6 @@ export function UniversalFormModalComponent({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 별도 테이블에 저장해야 하는 테이블 섹션 목록
|
|
||||||
const tableSectionsForSeparateTable = config.sections.filter(
|
|
||||||
(s) => s.type === "table" &&
|
|
||||||
s.tableConfig?.saveConfig?.targetTable &&
|
|
||||||
s.tableConfig.saveConfig.targetTable !== config.saveConfig.tableName
|
|
||||||
);
|
|
||||||
|
|
||||||
// 테이블 섹션이 있고 메인 테이블에 품목별로 저장하는 경우 (공통 + 개별 병합 저장)
|
// 테이블 섹션이 있고 메인 테이블에 품목별로 저장하는 경우 (공통 + 개별 병합 저장)
|
||||||
// targetTable이 없거나 메인 테이블과 같은 경우
|
// targetTable이 없거나 메인 테이블과 같은 경우
|
||||||
const tableSectionsForMainTable = config.sections.filter(
|
const tableSectionsForMainTable = config.sections.filter(
|
||||||
|
|
@ -978,12 +971,6 @@ export function UniversalFormModalComponent({
|
||||||
s.tableConfig.saveConfig.targetTable === config.saveConfig.tableName)
|
s.tableConfig.saveConfig.targetTable === config.saveConfig.tableName)
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log("[saveSingleRow] 메인 테이블:", config.saveConfig.tableName);
|
|
||||||
console.log("[saveSingleRow] 메인 테이블에 저장할 테이블 섹션:", tableSectionsForMainTable.map(s => s.id));
|
|
||||||
console.log("[saveSingleRow] 별도 테이블에 저장할 테이블 섹션:", tableSectionsForSeparateTable.map(s => s.id));
|
|
||||||
console.log("[saveSingleRow] 테이블 섹션 데이터 키:", Object.keys(tableSectionData));
|
|
||||||
console.log("[saveSingleRow] dataToSave 키:", Object.keys(dataToSave));
|
|
||||||
|
|
||||||
if (tableSectionsForMainTable.length > 0) {
|
if (tableSectionsForMainTable.length > 0) {
|
||||||
// 공통 저장 필드 수집 (sectionSaveModes 설정에 따라)
|
// 공통 저장 필드 수집 (sectionSaveModes 설정에 따라)
|
||||||
const commonFieldsData: Record<string, any> = {};
|
const commonFieldsData: Record<string, any> = {};
|
||||||
|
|
@ -1063,51 +1050,35 @@ export function UniversalFormModalComponent({
|
||||||
// 메인 레코드 ID가 필요한 경우 (response.data에서 가져오기)
|
// 메인 레코드 ID가 필요한 경우 (response.data에서 가져오기)
|
||||||
const mainRecordId = response.data?.data?.id;
|
const mainRecordId = response.data?.data?.id;
|
||||||
|
|
||||||
// 공통 저장 필드 수집: 다른 섹션(필드 타입)에서 공통 저장으로 설정된 필드 값
|
// 공통 저장 필드 수집 (sectionSaveModes 설정에 따라)
|
||||||
// 기본값: 필드 타입 섹션은 'common', 테이블 타입 섹션은 'individual'
|
|
||||||
const commonFieldsData: Record<string, any> = {};
|
const commonFieldsData: Record<string, any> = {};
|
||||||
const { sectionSaveModes } = config.saveConfig;
|
const { sectionSaveModes } = config.saveConfig;
|
||||||
|
|
||||||
// 다른 섹션에서 공통 저장으로 설정된 필드 값 수집
|
if (sectionSaveModes && sectionSaveModes.length > 0) {
|
||||||
for (const otherSection of config.sections) {
|
// 다른 섹션에서 공통 저장으로 설정된 필드 값 수집
|
||||||
if (otherSection.id === section.id) continue; // 현재 테이블 섹션은 건너뛰기
|
for (const otherSection of config.sections) {
|
||||||
|
if (otherSection.id === section.id) continue; // 현재 테이블 섹션은 건너뛰기
|
||||||
const sectionMode = sectionSaveModes?.find((s) => s.sectionId === otherSection.id);
|
|
||||||
// 기본값: 필드 타입 섹션은 'common', 테이블 타입 섹션은 'individual'
|
const sectionMode = sectionSaveModes.find((s) => s.sectionId === otherSection.id);
|
||||||
const defaultMode = otherSection.type === "table" ? "individual" : "common";
|
const defaultMode = otherSection.type === "table" ? "individual" : "common";
|
||||||
const sectionSaveMode = sectionMode?.saveMode || defaultMode;
|
const sectionSaveMode = sectionMode?.saveMode || defaultMode;
|
||||||
|
|
||||||
// 필드 타입 섹션의 필드들 처리
|
// 필드 타입 섹션의 필드들 처리
|
||||||
if (otherSection.type !== "table" && otherSection.fields) {
|
if (otherSection.type !== "table" && otherSection.fields) {
|
||||||
for (const field of otherSection.fields) {
|
for (const field of otherSection.fields) {
|
||||||
// 필드별 오버라이드 확인
|
// 필드별 오버라이드 확인
|
||||||
const fieldOverride = sectionMode?.fieldOverrides?.find((f) => f.fieldName === field.columnName);
|
const fieldOverride = sectionMode?.fieldOverrides?.find((f) => f.fieldName === field.columnName);
|
||||||
const fieldSaveMode = fieldOverride?.saveMode || sectionSaveMode;
|
const fieldSaveMode = fieldOverride?.saveMode || sectionSaveMode;
|
||||||
|
|
||||||
// 공통 저장이면 formData에서 값을 가져와 모든 품목에 적용
|
// 공통 저장이면 formData에서 값을 가져와 모든 품목에 적용
|
||||||
if (fieldSaveMode === "common" && formData[field.columnName] !== undefined) {
|
if (fieldSaveMode === "common" && formData[field.columnName] !== undefined) {
|
||||||
commonFieldsData[field.columnName] = formData[field.columnName];
|
commonFieldsData[field.columnName] = formData[field.columnName];
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 🆕 선택적 필드 그룹 (optionalFieldGroups)도 처리
|
|
||||||
if (otherSection.optionalFieldGroups && otherSection.optionalFieldGroups.length > 0) {
|
|
||||||
for (const optGroup of otherSection.optionalFieldGroups) {
|
|
||||||
if (optGroup.fields) {
|
|
||||||
for (const field of optGroup.fields) {
|
|
||||||
// 선택적 필드 그룹은 기본적으로 common 저장
|
|
||||||
if (formData[field.columnName] !== undefined) {
|
|
||||||
commonFieldsData[field.columnName] = formData[field.columnName];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("[saveSingleRow] 별도 테이블 저장 - 공통 필드:", Object.keys(commonFieldsData));
|
|
||||||
|
|
||||||
for (const item of sectionData) {
|
for (const item of sectionData) {
|
||||||
// 공통 필드 병합 + 개별 품목 데이터
|
// 공통 필드 병합 + 개별 품목 데이터
|
||||||
const itemToSave = { ...commonFieldsData, ...item };
|
const itemToSave = { ...commonFieldsData, ...item };
|
||||||
|
|
@ -1120,26 +1091,15 @@ export function UniversalFormModalComponent({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// _sourceData 등 내부 메타데이터 제거
|
|
||||||
Object.keys(itemToSave).forEach((key) => {
|
|
||||||
if (key.startsWith("_")) {
|
|
||||||
delete itemToSave[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 메인 레코드와 연결이 필요한 경우
|
// 메인 레코드와 연결이 필요한 경우
|
||||||
if (mainRecordId && config.saveConfig.primaryKeyColumn) {
|
if (mainRecordId && config.saveConfig.primaryKeyColumn) {
|
||||||
itemToSave[config.saveConfig.primaryKeyColumn] = mainRecordId;
|
itemToSave[config.saveConfig.primaryKeyColumn] = mainRecordId;
|
||||||
}
|
}
|
||||||
|
|
||||||
const saveResponse = await apiClient.post(
|
await apiClient.post(
|
||||||
`/table-management/tables/${section.tableConfig.saveConfig.targetTable}/add`,
|
`/table-management/tables/${section.tableConfig.saveConfig.targetTable}/add`,
|
||||||
itemToSave
|
itemToSave
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!saveResponse.data?.success) {
|
|
||||||
throw new Error(saveResponse.data?.message || `${section.title || "테이블 섹션"} 저장 실패`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1491,7 +1491,6 @@ export class ButtonActionExecutor {
|
||||||
* 🆕 Universal Form Modal 테이블 섹션 병합 저장 처리
|
* 🆕 Universal Form Modal 테이블 섹션 병합 저장 처리
|
||||||
* 범용_폼_모달 내부의 공통 필드 + _tableSection_ 데이터를 병합하여 품목별로 저장
|
* 범용_폼_모달 내부의 공통 필드 + _tableSection_ 데이터를 병합하여 품목별로 저장
|
||||||
* 수정 모드: INSERT/UPDATE/DELETE 지원
|
* 수정 모드: INSERT/UPDATE/DELETE 지원
|
||||||
* 🆕 섹션별 저장 테이블(targetTable) 지원 추가
|
|
||||||
*/
|
*/
|
||||||
private static async handleUniversalFormModalTableSectionSave(
|
private static async handleUniversalFormModalTableSectionSave(
|
||||||
config: ButtonActionConfig,
|
config: ButtonActionConfig,
|
||||||
|
|
@ -1515,66 +1514,7 @@ export class ButtonActionExecutor {
|
||||||
console.log("🎯 [handleUniversalFormModalTableSectionSave] Universal Form Modal 감지:", universalFormModalKey);
|
console.log("🎯 [handleUniversalFormModalTableSectionSave] Universal Form Modal 감지:", universalFormModalKey);
|
||||||
|
|
||||||
const modalData = formData[universalFormModalKey];
|
const modalData = formData[universalFormModalKey];
|
||||||
|
|
||||||
// 🆕 universal-form-modal 컴포넌트 설정 가져오기
|
|
||||||
// 1. componentConfigs에서 컴포넌트 ID로 찾기
|
|
||||||
// 2. allComponents에서 columnName으로 찾기
|
|
||||||
// 3. 화면 레이아웃 API에서 가져오기
|
|
||||||
let modalComponentConfig = context.componentConfigs?.[universalFormModalKey];
|
|
||||||
|
|
||||||
// componentConfigs에서 직접 찾지 못한 경우, allComponents에서 columnName으로 찾기
|
|
||||||
if (!modalComponentConfig && context.allComponents) {
|
|
||||||
const modalComponent = context.allComponents.find(
|
|
||||||
(comp: any) =>
|
|
||||||
comp.columnName === universalFormModalKey || comp.properties?.columnName === universalFormModalKey,
|
|
||||||
);
|
|
||||||
if (modalComponent) {
|
|
||||||
modalComponentConfig = modalComponent.componentConfig || modalComponent.properties?.componentConfig;
|
|
||||||
console.log("🎯 [handleUniversalFormModalTableSectionSave] allComponents에서 설정 찾음:", modalComponent.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 🆕 아직도 설정을 찾지 못했으면 화면 레이아웃 API에서 가져오기
|
|
||||||
if (!modalComponentConfig && screenId) {
|
|
||||||
try {
|
|
||||||
console.log("🔍 [handleUniversalFormModalTableSectionSave] 화면 레이아웃 API에서 설정 조회:", screenId);
|
|
||||||
const { screenApi } = await import("@/lib/api/screen");
|
|
||||||
const layoutData = await screenApi.getLayout(screenId);
|
|
||||||
|
|
||||||
if (layoutData && layoutData.components) {
|
|
||||||
// 레이아웃에서 universal-form-modal 컴포넌트 찾기
|
|
||||||
const modalLayout = (layoutData.components as any[]).find(
|
|
||||||
(comp) =>
|
|
||||||
comp.properties?.columnName === universalFormModalKey || comp.columnName === universalFormModalKey,
|
|
||||||
);
|
|
||||||
if (modalLayout) {
|
|
||||||
modalComponentConfig = modalLayout.properties?.componentConfig || modalLayout.componentConfig;
|
|
||||||
console.log(
|
|
||||||
"🎯 [handleUniversalFormModalTableSectionSave] 화면 레이아웃에서 설정 찾음:",
|
|
||||||
modalLayout.componentId,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.warn("⚠️ [handleUniversalFormModalTableSectionSave] 화면 레이아웃 조회 실패:", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const sections: any[] = modalComponentConfig?.sections || [];
|
|
||||||
const saveConfig = modalComponentConfig?.saveConfig || {};
|
|
||||||
|
|
||||||
console.log("🎯 [handleUniversalFormModalTableSectionSave] 컴포넌트 설정:", {
|
|
||||||
hasComponentConfig: !!modalComponentConfig,
|
|
||||||
sectionsCount: sections.length,
|
|
||||||
mainTableName: saveConfig.tableName || tableName,
|
|
||||||
sectionSaveModes: saveConfig.sectionSaveModes,
|
|
||||||
sectionDetails: sections.map((s: any) => ({
|
|
||||||
id: s.id,
|
|
||||||
type: s.type,
|
|
||||||
targetTable: s.tableConfig?.saveConfig?.targetTable,
|
|
||||||
})),
|
|
||||||
});
|
|
||||||
|
|
||||||
// _tableSection_ 데이터 추출
|
// _tableSection_ 데이터 추출
|
||||||
const tableSectionData: Record<string, any[]> = {};
|
const tableSectionData: Record<string, any[]> = {};
|
||||||
const commonFieldsData: Record<string, any> = {};
|
const commonFieldsData: Record<string, any> = {};
|
||||||
|
|
@ -1624,64 +1564,10 @@ export class ButtonActionExecutor {
|
||||||
let insertedCount = 0;
|
let insertedCount = 0;
|
||||||
let updatedCount = 0;
|
let updatedCount = 0;
|
||||||
let deletedCount = 0;
|
let deletedCount = 0;
|
||||||
let mainRecordId: number | null = null;
|
|
||||||
|
|
||||||
// 🆕 먼저 메인 테이블에 공통 데이터 저장 (별도 테이블이 있는 경우에만)
|
|
||||||
const hasSeparateTargetTable = sections.some(
|
|
||||||
(s) =>
|
|
||||||
s.type === "table" &&
|
|
||||||
s.tableConfig?.saveConfig?.targetTable &&
|
|
||||||
s.tableConfig.saveConfig.targetTable !== tableName,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (hasSeparateTargetTable && Object.keys(commonFieldsData).length > 0) {
|
|
||||||
console.log("📦 [handleUniversalFormModalTableSectionSave] 메인 테이블에 공통 데이터 저장:", tableName);
|
|
||||||
|
|
||||||
const mainRowToSave = { ...commonFieldsData, ...userInfo };
|
|
||||||
|
|
||||||
// 메타데이터 제거
|
|
||||||
Object.keys(mainRowToSave).forEach((key) => {
|
|
||||||
if (key.startsWith("_")) {
|
|
||||||
delete mainRowToSave[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log("📦 [handleUniversalFormModalTableSectionSave] 메인 테이블 저장 데이터:", mainRowToSave);
|
|
||||||
|
|
||||||
const mainSaveResult = await DynamicFormApi.saveFormData({
|
|
||||||
screenId: screenId!,
|
|
||||||
tableName: tableName!,
|
|
||||||
data: mainRowToSave,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!mainSaveResult.success) {
|
|
||||||
throw new Error(mainSaveResult.message || "메인 데이터 저장 실패");
|
|
||||||
}
|
|
||||||
|
|
||||||
mainRecordId = mainSaveResult.data?.id || null;
|
|
||||||
console.log("✅ [handleUniversalFormModalTableSectionSave] 메인 테이블 저장 완료, ID:", mainRecordId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 각 테이블 섹션 처리
|
// 각 테이블 섹션 처리
|
||||||
for (const [sectionId, currentItems] of Object.entries(tableSectionData)) {
|
for (const [sectionId, currentItems] of Object.entries(tableSectionData)) {
|
||||||
console.log(
|
console.log(`🔄 [handleUniversalFormModalTableSectionSave] 섹션 ${sectionId} 처리 시작: ${currentItems.length}개 품목`);
|
||||||
`🔄 [handleUniversalFormModalTableSectionSave] 섹션 ${sectionId} 처리 시작: ${currentItems.length}개 품목`,
|
|
||||||
);
|
|
||||||
|
|
||||||
// 🆕 해당 섹션의 설정 찾기
|
|
||||||
const sectionConfig = sections.find((s) => s.id === sectionId);
|
|
||||||
const targetTableName = sectionConfig?.tableConfig?.saveConfig?.targetTable;
|
|
||||||
|
|
||||||
// 🆕 실제 저장할 테이블 결정
|
|
||||||
// - targetTable이 있으면 해당 테이블에 저장
|
|
||||||
// - targetTable이 없으면 메인 테이블에 저장
|
|
||||||
const saveTableName = targetTableName || tableName!;
|
|
||||||
|
|
||||||
console.log(`📊 [handleUniversalFormModalTableSectionSave] 섹션 ${sectionId} 저장 테이블:`, {
|
|
||||||
targetTableName,
|
|
||||||
saveTableName,
|
|
||||||
isMainTable: saveTableName === tableName,
|
|
||||||
});
|
|
||||||
|
|
||||||
// 1️⃣ 신규 품목 INSERT (id가 없는 항목)
|
// 1️⃣ 신규 품목 INSERT (id가 없는 항목)
|
||||||
const newItems = currentItems.filter((item) => !item.id);
|
const newItems = currentItems.filter((item) => !item.id);
|
||||||
|
|
@ -1695,16 +1581,11 @@ export class ButtonActionExecutor {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 🆕 메인 레코드 ID 연결 (별도 테이블에 저장하는 경우)
|
console.log("➕ [INSERT] 신규 품목:", rowToSave);
|
||||||
if (targetTableName && mainRecordId && saveConfig.primaryKeyColumn) {
|
|
||||||
rowToSave[saveConfig.primaryKeyColumn] = mainRecordId;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("➕ [INSERT] 신규 품목:", { tableName: saveTableName, data: rowToSave });
|
|
||||||
|
|
||||||
const saveResult = await DynamicFormApi.saveFormData({
|
const saveResult = await DynamicFormApi.saveFormData({
|
||||||
screenId: screenId!,
|
screenId: screenId!,
|
||||||
tableName: saveTableName,
|
tableName: tableName!,
|
||||||
data: rowToSave,
|
data: rowToSave,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1731,14 +1612,9 @@ export class ButtonActionExecutor {
|
||||||
});
|
});
|
||||||
delete rowToSave.id; // id 제거하여 INSERT
|
delete rowToSave.id; // id 제거하여 INSERT
|
||||||
|
|
||||||
// 🆕 메인 레코드 ID 연결 (별도 테이블에 저장하는 경우)
|
|
||||||
if (targetTableName && mainRecordId && saveConfig.primaryKeyColumn) {
|
|
||||||
rowToSave[saveConfig.primaryKeyColumn] = mainRecordId;
|
|
||||||
}
|
|
||||||
|
|
||||||
const saveResult = await DynamicFormApi.saveFormData({
|
const saveResult = await DynamicFormApi.saveFormData({
|
||||||
screenId: screenId!,
|
screenId: screenId!,
|
||||||
tableName: saveTableName,
|
tableName: tableName!,
|
||||||
data: rowToSave,
|
data: rowToSave,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1755,14 +1631,14 @@ export class ButtonActionExecutor {
|
||||||
const hasChanges = this.checkForChanges(originalItem, currentDataWithCommon);
|
const hasChanges = this.checkForChanges(originalItem, currentDataWithCommon);
|
||||||
|
|
||||||
if (hasChanges) {
|
if (hasChanges) {
|
||||||
console.log(`🔄 [UPDATE] 품목 수정: id=${item.id}, tableName=${saveTableName}`);
|
console.log(`🔄 [UPDATE] 품목 수정: id=${item.id}`);
|
||||||
|
|
||||||
// 변경된 필드만 추출하여 부분 업데이트
|
// 변경된 필드만 추출하여 부분 업데이트
|
||||||
const updateResult = await DynamicFormApi.updateFormDataPartial(
|
const updateResult = await DynamicFormApi.updateFormDataPartial(
|
||||||
item.id,
|
item.id,
|
||||||
originalItem,
|
originalItem,
|
||||||
currentDataWithCommon,
|
currentDataWithCommon,
|
||||||
saveTableName,
|
tableName!,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!updateResult.success) {
|
if (!updateResult.success) {
|
||||||
|
|
@ -1780,9 +1656,9 @@ export class ButtonActionExecutor {
|
||||||
const deletedItems = originalGroupedData.filter((orig) => orig.id && !currentIds.has(orig.id));
|
const deletedItems = originalGroupedData.filter((orig) => orig.id && !currentIds.has(orig.id));
|
||||||
|
|
||||||
for (const deletedItem of deletedItems) {
|
for (const deletedItem of deletedItems) {
|
||||||
console.log(`🗑️ [DELETE] 품목 삭제: id=${deletedItem.id}, tableName=${saveTableName}`);
|
console.log(`🗑️ [DELETE] 품목 삭제: id=${deletedItem.id}`);
|
||||||
|
|
||||||
const deleteResult = await DynamicFormApi.deleteFormDataFromTable(saveTableName, deletedItem.id);
|
const deleteResult = await DynamicFormApi.deleteFormDataFromTable(tableName!, deletedItem.id);
|
||||||
|
|
||||||
if (!deleteResult.success) {
|
if (!deleteResult.success) {
|
||||||
throw new Error(deleteResult.message || "품목 삭제 실패");
|
throw new Error(deleteResult.message || "품목 삭제 실패");
|
||||||
|
|
@ -1794,7 +1670,6 @@ export class ButtonActionExecutor {
|
||||||
|
|
||||||
// 결과 메시지 생성
|
// 결과 메시지 생성
|
||||||
const resultParts: string[] = [];
|
const resultParts: string[] = [];
|
||||||
if (mainRecordId) resultParts.push("메인 데이터 저장");
|
|
||||||
if (insertedCount > 0) resultParts.push(`${insertedCount}개 추가`);
|
if (insertedCount > 0) resultParts.push(`${insertedCount}개 추가`);
|
||||||
if (updatedCount > 0) resultParts.push(`${updatedCount}개 수정`);
|
if (updatedCount > 0) resultParts.push(`${updatedCount}개 수정`);
|
||||||
if (deletedCount > 0) resultParts.push(`${deletedCount}개 삭제`);
|
if (deletedCount > 0) resultParts.push(`${deletedCount}개 삭제`);
|
||||||
|
|
@ -2270,20 +2145,17 @@ export class ButtonActionExecutor {
|
||||||
* 연관 데이터 버튼의 선택 데이터로 모달 열기
|
* 연관 데이터 버튼의 선택 데이터로 모달 열기
|
||||||
* RelatedDataButtons 컴포넌트에서 선택된 버튼 데이터를 모달로 전달
|
* RelatedDataButtons 컴포넌트에서 선택된 버튼 데이터를 모달로 전달
|
||||||
*/
|
*/
|
||||||
private static async handleOpenRelatedModal(
|
private static async handleOpenRelatedModal(config: ButtonActionConfig, context: ButtonActionContext): Promise<boolean> {
|
||||||
config: ButtonActionConfig,
|
|
||||||
context: ButtonActionContext,
|
|
||||||
): Promise<boolean> {
|
|
||||||
// 버튼 설정에서 targetScreenId 가져오기 (여러 위치에서 확인)
|
// 버튼 설정에서 targetScreenId 가져오기 (여러 위치에서 확인)
|
||||||
const targetScreenId = config.relatedModalConfig?.targetScreenId || config.targetScreenId;
|
const targetScreenId = config.relatedModalConfig?.targetScreenId || config.targetScreenId;
|
||||||
|
|
||||||
console.log("🔍 [openRelatedModal] 설정 확인:", {
|
console.log("🔍 [openRelatedModal] 설정 확인:", {
|
||||||
config,
|
config,
|
||||||
relatedModalConfig: config.relatedModalConfig,
|
relatedModalConfig: config.relatedModalConfig,
|
||||||
targetScreenId: config.targetScreenId,
|
targetScreenId: config.targetScreenId,
|
||||||
finalTargetScreenId: targetScreenId,
|
finalTargetScreenId: targetScreenId,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!targetScreenId) {
|
if (!targetScreenId) {
|
||||||
console.error("❌ [openRelatedModal] targetScreenId가 설정되지 않았습니다.");
|
console.error("❌ [openRelatedModal] targetScreenId가 설정되지 않았습니다.");
|
||||||
toast.error("모달 화면 ID가 설정되지 않았습니다.");
|
toast.error("모달 화면 ID가 설정되지 않았습니다.");
|
||||||
|
|
@ -2292,13 +2164,13 @@ export class ButtonActionExecutor {
|
||||||
|
|
||||||
// RelatedDataButtons에서 선택된 데이터 가져오기
|
// RelatedDataButtons에서 선택된 데이터 가져오기
|
||||||
const relatedData = window.__relatedButtonsSelectedData;
|
const relatedData = window.__relatedButtonsSelectedData;
|
||||||
|
|
||||||
console.log("🔍 [openRelatedModal] RelatedDataButtons 데이터:", {
|
console.log("🔍 [openRelatedModal] RelatedDataButtons 데이터:", {
|
||||||
relatedData,
|
relatedData,
|
||||||
selectedItem: relatedData?.selectedItem,
|
selectedItem: relatedData?.selectedItem,
|
||||||
config: relatedData?.config,
|
config: relatedData?.config,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!relatedData?.selectedItem) {
|
if (!relatedData?.selectedItem) {
|
||||||
console.warn("⚠️ [openRelatedModal] 선택된 버튼이 없습니다.");
|
console.warn("⚠️ [openRelatedModal] 선택된 버튼이 없습니다.");
|
||||||
toast.warning("먼저 버튼을 선택해주세요.");
|
toast.warning("먼저 버튼을 선택해주세요.");
|
||||||
|
|
@ -2309,14 +2181,14 @@ export class ButtonActionExecutor {
|
||||||
|
|
||||||
// 데이터 매핑 적용
|
// 데이터 매핑 적용
|
||||||
const initialData: Record<string, any> = {};
|
const initialData: Record<string, any> = {};
|
||||||
|
|
||||||
console.log("🔍 [openRelatedModal] 매핑 설정:", {
|
console.log("🔍 [openRelatedModal] 매핑 설정:", {
|
||||||
modalLink: relatedConfig?.modalLink,
|
modalLink: relatedConfig?.modalLink,
|
||||||
dataMapping: relatedConfig?.modalLink?.dataMapping,
|
dataMapping: relatedConfig?.modalLink?.dataMapping,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (relatedConfig?.modalLink?.dataMapping && relatedConfig.modalLink.dataMapping.length > 0) {
|
if (relatedConfig?.modalLink?.dataMapping && relatedConfig.modalLink.dataMapping.length > 0) {
|
||||||
relatedConfig.modalLink.dataMapping.forEach((mapping) => {
|
relatedConfig.modalLink.dataMapping.forEach(mapping => {
|
||||||
console.log("🔍 [openRelatedModal] 매핑 처리:", {
|
console.log("🔍 [openRelatedModal] 매핑 처리:", {
|
||||||
mapping,
|
mapping,
|
||||||
sourceField: mapping.sourceField,
|
sourceField: mapping.sourceField,
|
||||||
|
|
@ -2325,7 +2197,7 @@ export class ButtonActionExecutor {
|
||||||
selectedItemId: selectedItem.id,
|
selectedItemId: selectedItem.id,
|
||||||
rawDataValue: selectedItem.rawData[mapping.sourceField],
|
rawDataValue: selectedItem.rawData[mapping.sourceField],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (mapping.sourceField === "value") {
|
if (mapping.sourceField === "value") {
|
||||||
initialData[mapping.targetField] = selectedItem.value;
|
initialData[mapping.targetField] = selectedItem.value;
|
||||||
} else if (mapping.sourceField === "id") {
|
} else if (mapping.sourceField === "id") {
|
||||||
|
|
@ -2347,20 +2219,18 @@ export class ButtonActionExecutor {
|
||||||
});
|
});
|
||||||
|
|
||||||
// 모달 열기 이벤트 발생 (ScreenModal은 editData를 사용)
|
// 모달 열기 이벤트 발생 (ScreenModal은 editData를 사용)
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(new CustomEvent("openScreenModal", {
|
||||||
new CustomEvent("openScreenModal", {
|
detail: {
|
||||||
detail: {
|
screenId: targetScreenId,
|
||||||
screenId: targetScreenId,
|
title: config.modalTitle,
|
||||||
title: config.modalTitle,
|
description: config.modalDescription,
|
||||||
description: config.modalDescription,
|
editData: initialData, // ScreenModal은 editData로 폼 데이터를 받음
|
||||||
editData: initialData, // ScreenModal은 editData로 폼 데이터를 받음
|
onSuccess: () => {
|
||||||
onSuccess: () => {
|
// 성공 후 데이터 새로고침
|
||||||
// 성공 후 데이터 새로고침
|
window.dispatchEvent(new CustomEvent("refreshTableData"));
|
||||||
window.dispatchEvent(new CustomEvent("refreshTableData"));
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}),
|
},
|
||||||
);
|
}));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -3426,7 +3296,10 @@ export class ButtonActionExecutor {
|
||||||
* EditModal 등 외부에서도 호출 가능하도록 public으로 변경
|
* EditModal 등 외부에서도 호출 가능하도록 public으로 변경
|
||||||
* 다중 제어 순차 실행 지원
|
* 다중 제어 순차 실행 지원
|
||||||
*/
|
*/
|
||||||
public static async executeAfterSaveControl(config: ButtonActionConfig, context: ButtonActionContext): Promise<void> {
|
public static async executeAfterSaveControl(
|
||||||
|
config: ButtonActionConfig,
|
||||||
|
context: ButtonActionContext,
|
||||||
|
): Promise<void> {
|
||||||
console.log("🎯 저장 후 제어 실행:", {
|
console.log("🎯 저장 후 제어 실행:", {
|
||||||
enableDataflowControl: config.enableDataflowControl,
|
enableDataflowControl: config.enableDataflowControl,
|
||||||
dataflowConfig: config.dataflowConfig,
|
dataflowConfig: config.dataflowConfig,
|
||||||
|
|
@ -4869,7 +4742,7 @@ export class ButtonActionExecutor {
|
||||||
|
|
||||||
// 추적 중인지 확인 (새로고침 후에도 DB 상태 기반 종료 가능하도록 수정)
|
// 추적 중인지 확인 (새로고침 후에도 DB 상태 기반 종료 가능하도록 수정)
|
||||||
const isTrackingActive = !!this.trackingIntervalId;
|
const isTrackingActive = !!this.trackingIntervalId;
|
||||||
|
|
||||||
if (!isTrackingActive) {
|
if (!isTrackingActive) {
|
||||||
// 추적 중이 아니어도 DB 상태 변경은 진행 (새로고침 후 종료 지원)
|
// 추적 중이 아니어도 DB 상태 변경은 진행 (새로고침 후 종료 지원)
|
||||||
console.log("⚠️ [handleTrackingStop] trackingIntervalId 없음 - DB 상태 기반 종료 진행");
|
console.log("⚠️ [handleTrackingStop] trackingIntervalId 없음 - DB 상태 기반 종료 진행");
|
||||||
|
|
@ -4885,26 +4758,25 @@ export class ButtonActionExecutor {
|
||||||
let dbDeparture: string | null = null;
|
let dbDeparture: string | null = null;
|
||||||
let dbArrival: string | null = null;
|
let dbArrival: string | null = null;
|
||||||
let dbVehicleId: string | null = null;
|
let dbVehicleId: string | null = null;
|
||||||
|
|
||||||
const userId = context.userId || this.trackingUserId;
|
const userId = context.userId || this.trackingUserId;
|
||||||
if (userId) {
|
if (userId) {
|
||||||
try {
|
try {
|
||||||
const { apiClient } = await import("@/lib/api/client");
|
const { apiClient } = await import("@/lib/api/client");
|
||||||
const statusTableName =
|
const statusTableName = config.trackingStatusTableName || this.trackingConfig?.trackingStatusTableName || context.tableName || "vehicles";
|
||||||
config.trackingStatusTableName ||
|
|
||||||
this.trackingConfig?.trackingStatusTableName ||
|
|
||||||
context.tableName ||
|
|
||||||
"vehicles";
|
|
||||||
const keyField = config.trackingStatusKeyField || this.trackingConfig?.trackingStatusKeyField || "user_id";
|
const keyField = config.trackingStatusKeyField || this.trackingConfig?.trackingStatusKeyField || "user_id";
|
||||||
|
|
||||||
// DB에서 현재 차량 정보 조회
|
// DB에서 현재 차량 정보 조회
|
||||||
const vehicleResponse = await apiClient.post(`/table-management/tables/${statusTableName}/data`, {
|
const vehicleResponse = await apiClient.post(
|
||||||
page: 1,
|
`/table-management/tables/${statusTableName}/data`,
|
||||||
size: 1,
|
{
|
||||||
search: { [keyField]: userId },
|
page: 1,
|
||||||
autoFilter: true,
|
size: 1,
|
||||||
});
|
search: { [keyField]: userId },
|
||||||
|
autoFilter: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const vehicleData = vehicleResponse.data?.data?.data?.[0] || vehicleResponse.data?.data?.rows?.[0];
|
const vehicleData = vehicleResponse.data?.data?.data?.[0] || vehicleResponse.data?.data?.rows?.[0];
|
||||||
if (vehicleData) {
|
if (vehicleData) {
|
||||||
dbDeparture = vehicleData.departure || null;
|
dbDeparture = vehicleData.departure || null;
|
||||||
|
|
@ -4920,18 +4792,14 @@ export class ButtonActionExecutor {
|
||||||
// 마지막 위치 저장 (추적 중이었던 경우에만)
|
// 마지막 위치 저장 (추적 중이었던 경우에만)
|
||||||
if (isTrackingActive) {
|
if (isTrackingActive) {
|
||||||
// DB 값 우선, 없으면 formData 사용
|
// DB 값 우선, 없으면 formData 사용
|
||||||
const departure =
|
const departure = dbDeparture ||
|
||||||
dbDeparture ||
|
this.trackingContext?.formData?.[this.trackingConfig?.trackingDepartureField || "departure"] || null;
|
||||||
this.trackingContext?.formData?.[this.trackingConfig?.trackingDepartureField || "departure"] ||
|
const arrival = dbArrival ||
|
||||||
null;
|
this.trackingContext?.formData?.[this.trackingConfig?.trackingArrivalField || "arrival"] || null;
|
||||||
const arrival =
|
|
||||||
dbArrival || this.trackingContext?.formData?.[this.trackingConfig?.trackingArrivalField || "arrival"] || null;
|
|
||||||
const departureName = this.trackingContext?.formData?.["departure_name"] || null;
|
const departureName = this.trackingContext?.formData?.["departure_name"] || null;
|
||||||
const destinationName = this.trackingContext?.formData?.["destination_name"] || null;
|
const destinationName = this.trackingContext?.formData?.["destination_name"] || null;
|
||||||
const vehicleId =
|
const vehicleId = dbVehicleId ||
|
||||||
dbVehicleId ||
|
this.trackingContext?.formData?.[this.trackingConfig?.trackingVehicleIdField || "vehicle_id"] || null;
|
||||||
this.trackingContext?.formData?.[this.trackingConfig?.trackingVehicleIdField || "vehicle_id"] ||
|
|
||||||
null;
|
|
||||||
|
|
||||||
await this.saveLocationToHistory(
|
await this.saveLocationToHistory(
|
||||||
tripId,
|
tripId,
|
||||||
|
|
@ -5813,10 +5681,10 @@ export class ButtonActionExecutor {
|
||||||
const columnMappings = quickInsertConfig.columnMappings || [];
|
const columnMappings = quickInsertConfig.columnMappings || [];
|
||||||
|
|
||||||
for (const mapping of columnMappings) {
|
for (const mapping of columnMappings) {
|
||||||
console.log("📍 매핑 처리 시작:", mapping);
|
console.log(`📍 매핑 처리 시작:`, mapping);
|
||||||
|
|
||||||
if (!mapping.targetColumn) {
|
if (!mapping.targetColumn) {
|
||||||
console.log("📍 targetColumn 없음, 스킵");
|
console.log(`📍 targetColumn 없음, 스킵`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5824,12 +5692,12 @@ export class ButtonActionExecutor {
|
||||||
|
|
||||||
switch (mapping.sourceType) {
|
switch (mapping.sourceType) {
|
||||||
case "component":
|
case "component":
|
||||||
console.log("📍 component 타입 처리:", {
|
console.log(`📍 component 타입 처리:`, {
|
||||||
sourceComponentId: mapping.sourceComponentId,
|
sourceComponentId: mapping.sourceComponentId,
|
||||||
sourceColumnName: mapping.sourceColumnName,
|
sourceColumnName: mapping.sourceColumnName,
|
||||||
targetColumn: mapping.targetColumn,
|
targetColumn: mapping.targetColumn,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 컴포넌트의 현재 값
|
// 컴포넌트의 현재 값
|
||||||
if (mapping.sourceComponentId) {
|
if (mapping.sourceComponentId) {
|
||||||
// 1. sourceColumnName이 있으면 직접 사용 (가장 확실한 방법)
|
// 1. sourceColumnName이 있으면 직접 사용 (가장 확실한 방법)
|
||||||
|
|
@ -5837,34 +5705,34 @@ export class ButtonActionExecutor {
|
||||||
value = formData?.[mapping.sourceColumnName];
|
value = formData?.[mapping.sourceColumnName];
|
||||||
console.log(`📍 방법1 (sourceColumnName): ${mapping.sourceColumnName} = ${value}`);
|
console.log(`📍 방법1 (sourceColumnName): ${mapping.sourceColumnName} = ${value}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 없으면 컴포넌트 ID로 직접 찾기
|
// 2. 없으면 컴포넌트 ID로 직접 찾기
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
value = formData?.[mapping.sourceComponentId];
|
value = formData?.[mapping.sourceComponentId];
|
||||||
console.log(`📍 방법2 (sourceComponentId): ${mapping.sourceComponentId} = ${value}`);
|
console.log(`📍 방법2 (sourceComponentId): ${mapping.sourceComponentId} = ${value}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 없으면 allComponents에서 컴포넌트를 찾아 columnName으로 시도
|
// 3. 없으면 allComponents에서 컴포넌트를 찾아 columnName으로 시도
|
||||||
if (value === undefined && context.allComponents) {
|
if (value === undefined && context.allComponents) {
|
||||||
const comp = context.allComponents.find((c: any) => c.id === mapping.sourceComponentId);
|
const comp = context.allComponents.find((c: any) => c.id === mapping.sourceComponentId);
|
||||||
console.log("📍 방법3 찾은 컴포넌트:", comp);
|
console.log(`📍 방법3 찾은 컴포넌트:`, comp);
|
||||||
if (comp?.columnName) {
|
if (comp?.columnName) {
|
||||||
value = formData?.[comp.columnName];
|
value = formData?.[comp.columnName];
|
||||||
console.log(`📍 방법3 (allComponents): ${mapping.sourceComponentId} → ${comp.columnName} = ${value}`);
|
console.log(`📍 방법3 (allComponents): ${mapping.sourceComponentId} → ${comp.columnName} = ${value}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. targetColumn과 같은 이름의 키가 formData에 있으면 사용 (폴백)
|
// 4. targetColumn과 같은 이름의 키가 formData에 있으면 사용 (폴백)
|
||||||
if (value === undefined && mapping.targetColumn && formData?.[mapping.targetColumn] !== undefined) {
|
if (value === undefined && mapping.targetColumn && formData?.[mapping.targetColumn] !== undefined) {
|
||||||
value = formData[mapping.targetColumn];
|
value = formData[mapping.targetColumn];
|
||||||
console.log(`📍 방법4 (targetColumn 폴백): ${mapping.targetColumn} = ${value}`);
|
console.log(`📍 방법4 (targetColumn 폴백): ${mapping.targetColumn} = ${value}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 그래도 없으면 formData의 모든 키를 확인하고 로깅
|
// 5. 그래도 없으면 formData의 모든 키를 확인하고 로깅
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
console.log("📍 방법5: formData에서 값을 찾지 못함. formData 키들:", Object.keys(formData || {}));
|
console.log("📍 방법5: formData에서 값을 찾지 못함. formData 키들:", Object.keys(formData || {}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// sourceColumn이 지정된 경우 해당 속성 추출
|
// sourceColumn이 지정된 경우 해당 속성 추출
|
||||||
if (mapping.sourceColumn && value && typeof value === "object") {
|
if (mapping.sourceColumn && value && typeof value === "object") {
|
||||||
value = value[mapping.sourceColumn];
|
value = value[mapping.sourceColumn];
|
||||||
|
|
@ -5874,7 +5742,7 @@ export class ButtonActionExecutor {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "leftPanel":
|
case "leftPanel":
|
||||||
console.log("📍 leftPanel 타입 처리:", {
|
console.log(`📍 leftPanel 타입 처리:`, {
|
||||||
sourceColumn: mapping.sourceColumn,
|
sourceColumn: mapping.sourceColumn,
|
||||||
selectedLeftData: splitPanelContext?.selectedLeftData,
|
selectedLeftData: splitPanelContext?.selectedLeftData,
|
||||||
});
|
});
|
||||||
|
|
@ -5907,18 +5775,18 @@ export class ButtonActionExecutor {
|
||||||
}
|
}
|
||||||
console.log(`📍 currentUser 값: ${value}`);
|
console.log(`📍 currentUser 값: ${value}`);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
console.log(`📍 알 수 없는 sourceType: ${mapping.sourceType}`);
|
console.log(`📍 알 수 없는 sourceType: ${mapping.sourceType}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`📍 매핑 결과: targetColumn=${mapping.targetColumn}, value=${value}, type=${typeof value}`);
|
console.log(`📍 매핑 결과: targetColumn=${mapping.targetColumn}, value=${value}, type=${typeof value}`);
|
||||||
|
|
||||||
if (value !== undefined && value !== null && value !== "") {
|
if (value !== undefined && value !== null && value !== "") {
|
||||||
insertData[mapping.targetColumn] = value;
|
insertData[mapping.targetColumn] = value;
|
||||||
console.log(`📍 insertData에 추가됨: ${mapping.targetColumn} = ${value}`);
|
console.log(`📍 insertData에 추가됨: ${mapping.targetColumn} = ${value}`);
|
||||||
} else {
|
} else {
|
||||||
console.log("📍 값이 비어있어서 insertData에 추가 안됨");
|
console.log(`📍 값이 비어있어서 insertData에 추가 안됨`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5926,12 +5794,12 @@ export class ButtonActionExecutor {
|
||||||
if (splitPanelContext?.selectedLeftData) {
|
if (splitPanelContext?.selectedLeftData) {
|
||||||
const leftData = splitPanelContext.selectedLeftData;
|
const leftData = splitPanelContext.selectedLeftData;
|
||||||
console.log("📍 좌측 패널 자동 매핑 시작:", leftData);
|
console.log("📍 좌측 패널 자동 매핑 시작:", leftData);
|
||||||
|
|
||||||
// 대상 테이블의 컬럼 목록 조회
|
// 대상 테이블의 컬럼 목록 조회
|
||||||
let targetTableColumns: string[] = [];
|
let targetTableColumns: string[] = [];
|
||||||
try {
|
try {
|
||||||
const columnsResponse = await apiClient.get(
|
const columnsResponse = await apiClient.get(
|
||||||
`/table-management/tables/${quickInsertConfig.targetTable}/columns`,
|
`/table-management/tables/${quickInsertConfig.targetTable}/columns`
|
||||||
);
|
);
|
||||||
if (columnsResponse.data?.success && columnsResponse.data?.data) {
|
if (columnsResponse.data?.success && columnsResponse.data?.data) {
|
||||||
const columnsData = columnsResponse.data.data.columns || columnsResponse.data.data;
|
const columnsData = columnsResponse.data.data.columns || columnsResponse.data.data;
|
||||||
|
|
@ -5941,35 +5809,35 @@ export class ButtonActionExecutor {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("대상 테이블 컬럼 조회 실패:", error);
|
console.error("대상 테이블 컬럼 조회 실패:", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [key, val] of Object.entries(leftData)) {
|
for (const [key, val] of Object.entries(leftData)) {
|
||||||
// 이미 매핑된 컬럼은 스킵
|
// 이미 매핑된 컬럼은 스킵
|
||||||
if (insertData[key] !== undefined) {
|
if (insertData[key] !== undefined) {
|
||||||
console.log(`📍 자동 매핑 스킵 (이미 존재): ${key}`);
|
console.log(`📍 자동 매핑 스킵 (이미 존재): ${key}`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 대상 테이블에 해당 컬럼이 없으면 스킵
|
// 대상 테이블에 해당 컬럼이 없으면 스킵
|
||||||
if (targetTableColumns.length > 0 && !targetTableColumns.includes(key)) {
|
if (targetTableColumns.length > 0 && !targetTableColumns.includes(key)) {
|
||||||
console.log(`📍 자동 매핑 스킵 (대상 테이블에 없는 컬럼): ${key}`);
|
console.log(`📍 자동 매핑 스킵 (대상 테이블에 없는 컬럼): ${key}`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 시스템 컬럼 제외 (id, created_date, updated_date, writer 등)
|
// 시스템 컬럼 제외 (id, created_date, updated_date, writer 등)
|
||||||
const systemColumns = ["id", "created_date", "updated_date", "writer", "writer_name"];
|
const systemColumns = ['id', 'created_date', 'updated_date', 'writer', 'writer_name'];
|
||||||
if (systemColumns.includes(key)) {
|
if (systemColumns.includes(key)) {
|
||||||
console.log(`📍 자동 매핑 스킵 (시스템 컬럼): ${key}`);
|
console.log(`📍 자동 매핑 스킵 (시스템 컬럼): ${key}`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// _label, _name 으로 끝나는 표시용 컬럼 제외
|
// _label, _name 으로 끝나는 표시용 컬럼 제외
|
||||||
if (key.endsWith("_label") || key.endsWith("_name")) {
|
if (key.endsWith('_label') || key.endsWith('_name')) {
|
||||||
console.log(`📍 자동 매핑 스킵 (표시용 컬럼): ${key}`);
|
console.log(`📍 자동 매핑 스킵 (표시용 컬럼): ${key}`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 값이 있으면 자동 추가
|
// 값이 있으면 자동 추가
|
||||||
if (val !== undefined && val !== null && val !== "") {
|
if (val !== undefined && val !== null && val !== '') {
|
||||||
insertData[key] = val;
|
insertData[key] = val;
|
||||||
console.log(`📍 자동 매핑 추가: ${key} = ${val}`);
|
console.log(`📍 자동 매핑 추가: ${key} = ${val}`);
|
||||||
}
|
}
|
||||||
|
|
@ -5989,7 +5857,7 @@ export class ButtonActionExecutor {
|
||||||
enabled: quickInsertConfig.duplicateCheck?.enabled,
|
enabled: quickInsertConfig.duplicateCheck?.enabled,
|
||||||
columns: quickInsertConfig.duplicateCheck?.columns,
|
columns: quickInsertConfig.duplicateCheck?.columns,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (quickInsertConfig.duplicateCheck?.enabled && quickInsertConfig.duplicateCheck?.columns?.length > 0) {
|
if (quickInsertConfig.duplicateCheck?.enabled && quickInsertConfig.duplicateCheck?.columns?.length > 0) {
|
||||||
const duplicateCheckData: Record<string, any> = {};
|
const duplicateCheckData: Record<string, any> = {};
|
||||||
for (const col of quickInsertConfig.duplicateCheck.columns) {
|
for (const col of quickInsertConfig.duplicateCheck.columns) {
|
||||||
|
|
@ -6009,20 +5877,15 @@ export class ButtonActionExecutor {
|
||||||
page: 1,
|
page: 1,
|
||||||
pageSize: 1,
|
pageSize: 1,
|
||||||
search: duplicateCheckData,
|
search: duplicateCheckData,
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log("📍 중복 체크 응답:", checkResponse.data);
|
console.log("📍 중복 체크 응답:", checkResponse.data);
|
||||||
|
|
||||||
// 응답 구조: { success: true, data: { data: [...], total: N } } 또는 { success: true, data: [...] }
|
// 응답 구조: { success: true, data: { data: [...], total: N } } 또는 { success: true, data: [...] }
|
||||||
const existingData = checkResponse.data?.data?.data || checkResponse.data?.data || [];
|
const existingData = checkResponse.data?.data?.data || checkResponse.data?.data || [];
|
||||||
console.log(
|
console.log("📍 기존 데이터:", existingData, "길이:", Array.isArray(existingData) ? existingData.length : 0);
|
||||||
"📍 기존 데이터:",
|
|
||||||
existingData,
|
|
||||||
"길이:",
|
|
||||||
Array.isArray(existingData) ? existingData.length : 0,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (Array.isArray(existingData) && existingData.length > 0) {
|
if (Array.isArray(existingData) && existingData.length > 0) {
|
||||||
toast.error(quickInsertConfig.duplicateCheck.errorMessage || "이미 존재하는 데이터입니다.");
|
toast.error(quickInsertConfig.duplicateCheck.errorMessage || "이미 존재하는 데이터입니다.");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -6039,20 +5902,20 @@ export class ButtonActionExecutor {
|
||||||
// 데이터 저장
|
// 데이터 저장
|
||||||
const response = await apiClient.post(
|
const response = await apiClient.post(
|
||||||
`/table-management/tables/${quickInsertConfig.targetTable}/add`,
|
`/table-management/tables/${quickInsertConfig.targetTable}/add`,
|
||||||
insertData,
|
insertData
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.data?.success) {
|
if (response.data?.success) {
|
||||||
console.log("✅ Quick Insert 저장 성공");
|
console.log("✅ Quick Insert 저장 성공");
|
||||||
|
|
||||||
// 저장 후 동작 설정 로그
|
// 저장 후 동작 설정 로그
|
||||||
console.log("📍 afterInsert 설정:", quickInsertConfig.afterInsert);
|
console.log("📍 afterInsert 설정:", quickInsertConfig.afterInsert);
|
||||||
|
|
||||||
// 🆕 데이터 새로고침 (테이블리스트, 카드 디스플레이 컴포넌트 새로고침)
|
// 🆕 데이터 새로고침 (테이블리스트, 카드 디스플레이 컴포넌트 새로고침)
|
||||||
// refreshData가 명시적으로 false가 아니면 기본적으로 새로고침 실행
|
// refreshData가 명시적으로 false가 아니면 기본적으로 새로고침 실행
|
||||||
const shouldRefresh = quickInsertConfig.afterInsert?.refreshData !== false;
|
const shouldRefresh = quickInsertConfig.afterInsert?.refreshData !== false;
|
||||||
console.log("📍 데이터 새로고침 여부:", shouldRefresh);
|
console.log("📍 데이터 새로고침 여부:", shouldRefresh);
|
||||||
|
|
||||||
if (shouldRefresh) {
|
if (shouldRefresh) {
|
||||||
console.log("📍 데이터 새로고침 이벤트 발송");
|
console.log("📍 데이터 새로고침 이벤트 발송");
|
||||||
// 전역 이벤트로 테이블/카드 컴포넌트들에게 새로고침 알림
|
// 전역 이벤트로 테이블/카드 컴포넌트들에게 새로고침 알림
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue