feat: 메인 테이블 데이터 자동 로드 및 autoFill 기능 개선

- 메인 테이블에서 사용자 회사 코드로 데이터를 자동으로 로드하여 폼에 채우는 기능을 추가하였습니다.
- displayColumn 파라미터를 선택적으로 변경하여, 누락 시 전체 레코드를 반환하도록 수정하였습니다.
- 엔티티 조인 테이블에 고유 접두사를 추가하여 메인 테이블과의 키 중복을 방지하였습니다.
- autoFill 설정을 복원하고 저장하는 기능을 추가하여 자동 입력 기능을 강화하였습니다.
This commit is contained in:
kjs 2026-02-02 12:01:39 +09:00
parent 0614609f2b
commit 4447911892
4 changed files with 97 additions and 7 deletions

View File

@ -662,14 +662,14 @@ export async function getTableRecord(
logger.info(`필터: ${filterColumn} = ${filterValue}`);
logger.info(`표시 컬럼: ${displayColumn}`);
if (!tableName || !filterColumn || !filterValue || !displayColumn) {
if (!tableName || !filterColumn || !filterValue) {
const response: ApiResponse<null> = {
success: false,
message: "필수 파라미터가 누락되었습니다.",
error: {
code: "MISSING_PARAMETERS",
details:
"tableName, filterColumn, filterValue, displayColumn이 필요합니다.",
"tableName, filterColumn, filterValue가 필요합니다. displayColumn은 선택적입니다.",
},
};
res.status(400).json(response);
@ -701,9 +701,12 @@ export async function getTableRecord(
}
const record = result.data[0];
const displayValue = record[displayColumn];
// displayColumn이 "*"이거나 없으면 전체 레코드 반환
const displayValue = displayColumn && displayColumn !== "*"
? record[displayColumn]
: record;
logger.info(`레코드 조회 완료: ${displayColumn} = ${displayValue}`);
logger.info(`레코드 조회 완료: ${displayColumn || "*"} = ${typeof displayValue === 'object' ? '[전체 레코드]' : displayValue}`);
const response: ApiResponse<{ value: any; record: any }> = {
success: true,

View File

@ -202,7 +202,89 @@ function ScreenViewPage() {
}
}, [screenId]);
// 🆕 autoFill 자동 입력 초기화
// 🆕 메인 테이블 데이터 자동 로드 (단일 레코드 폼)
// 화면의 메인 테이블에서 사용자 회사 코드로 데이터를 조회하여 폼에 자동 채움
useEffect(() => {
const loadMainTableData = async () => {
if (!screen || !layout || !layout.components || !companyCode) {
return;
}
const mainTableName = screen.tableName;
if (!mainTableName) {
return;
}
// 테이블 위젯이 없는 경우에만 자동 로드 (테이블이 있으면 행 선택으로 데이터 로드)
const hasTableWidget = layout.components.some(
(comp: any) =>
comp.componentType === "table-list" ||
comp.componentType === "v2-table-list" ||
comp.widgetType === "table"
);
if (hasTableWidget) {
console.log("📋 테이블 위젯이 있어 자동 로드 건너뜀 (행 선택으로 데이터 로드)");
return;
}
// 인풋 컴포넌트들 중 메인 테이블의 컬럼을 사용하는 것들 찾기
const inputComponents = layout.components.filter((comp: any) => {
const compType = comp.componentType || comp.widgetType;
const isInputType = compType?.includes("input") ||
compType?.includes("select") ||
compType?.includes("textarea") ||
compType?.includes("v2-input") ||
compType?.includes("v2-select");
const hasColumnName = !!(comp as any).columnName;
return isInputType && hasColumnName;
});
if (inputComponents.length === 0) {
return;
}
// 메인 테이블에서 현재 회사의 데이터 조회
try {
const { tableTypeApi } = await import("@/lib/api/screen");
// company_code로 필터링하여 단일 레코드 조회
const result = await tableTypeApi.getTableRecord(
mainTableName,
"company_code",
companyCode,
"*" // 모든 컬럼
);
if (result && result.record) {
console.log("📦 메인 테이블 데이터 자동 로드:", mainTableName, result.record);
// 각 인풋 컴포넌트에 해당하는 데이터 채우기
const newFormData: Record<string, any> = {};
inputComponents.forEach((comp: any) => {
const columnName = comp.columnName;
if (columnName && result.record[columnName] !== undefined) {
newFormData[columnName] = result.record[columnName];
}
});
if (Object.keys(newFormData).length > 0) {
setFormData((prev) => ({
...prev,
...newFormData,
}));
}
}
} catch (error) {
console.log("메인 테이블 자동 로드 실패 (정상일 수 있음):", error);
// 에러는 무시 - 데이터가 없거나 권한이 없을 수 있음
}
};
loadMainTableData();
}, [screen, layout, companyCode]);
// 🆕 개별 autoFill 처리 (메인 테이블과 다른 테이블에서 조회하는 경우)
useEffect(() => {
const initAutoFill = async () => {
if (!layout || !layout.components || !user) {
@ -215,7 +297,7 @@ function ScreenViewPage() {
const widget = comp as any;
const fieldName = widget.columnName || widget.id;
// autoFill 처리
// autoFill 처리 (명시적으로 설정된 경우만)
if (widget.autoFill?.enabled || (comp as any).autoFill?.enabled) {
const autoFillConfig = widget.autoFill || (comp as any).autoFill;
const currentValue = formData[fieldName];

View File

@ -431,7 +431,8 @@ export const TablesPanel: React.FC<TablesPanelProps> = ({
}
return (
<div key={joinTable.tableName} className="space-y-1">
// 엔티티 조인 테이블에 고유 접두사 추가 (메인 테이블과 키 중복 방지)
<div key={`entity-join-${joinTable.tableName}`} className="space-y-1">
{/* 조인 테이블 헤더 */}
<div
className="flex cursor-pointer items-center justify-between rounded-md bg-cyan-50 p-2 hover:bg-cyan-100"

View File

@ -66,6 +66,8 @@ export function convertV2ToLegacy(v2Layout: LayoutV2 | null): LegacyLayoutData |
codeCategory: overrides.codeCategory,
inputType: overrides.inputType,
webType: overrides.webType,
// 🆕 autoFill 설정 복원 (자동 입력 기능)
autoFill: overrides.autoFill,
// 기존 구조 호환을 위한 추가 필드
style: {},
parentId: null,
@ -115,6 +117,8 @@ export function convertLegacyToV2(legacyLayout: LegacyLayoutData): LayoutV2 {
if (comp.codeCategory) topLevelProps.codeCategory = comp.codeCategory;
if (comp.inputType) topLevelProps.inputType = comp.inputType;
if (comp.webType) topLevelProps.webType = comp.webType;
// 🆕 autoFill 설정 저장 (자동 입력 기능)
if (comp.autoFill) topLevelProps.autoFill = comp.autoFill;
// 현재 설정에서 차이값만 추출
const fullConfig = comp.componentConfig || {};