617 lines
17 KiB
TypeScript
617 lines
17 KiB
TypeScript
// 화면관리 시스템 타입 정의
|
|
|
|
// 기본 컴포넌트 타입
|
|
export type ComponentType = "container" | "row" | "column" | "widget" | "group" | "datatable";
|
|
|
|
// 웹 타입 정의
|
|
export type WebType =
|
|
| "text"
|
|
| "number"
|
|
| "date"
|
|
| "code"
|
|
| "entity"
|
|
| "textarea"
|
|
| "select"
|
|
| "checkbox"
|
|
| "radio"
|
|
| "file"
|
|
| "email"
|
|
| "tel"
|
|
| "datetime"
|
|
| "dropdown"
|
|
| "text_area"
|
|
| "boolean"
|
|
| "decimal";
|
|
|
|
// 위치 정보
|
|
export interface Position {
|
|
x: number;
|
|
y: number;
|
|
z?: number; // z-index (레이어 순서)
|
|
}
|
|
|
|
// 크기 정보
|
|
export interface Size {
|
|
width: number; // 1-12 그리드
|
|
height: number; // 픽셀
|
|
}
|
|
|
|
// 테이블 정보
|
|
export interface TableInfo {
|
|
tableName: string;
|
|
tableLabel: string;
|
|
columns: ColumnInfo[];
|
|
}
|
|
|
|
// 스타일 관련 타입
|
|
export interface ComponentStyle {
|
|
// 레이아웃
|
|
width?: string | number;
|
|
height?: string | number;
|
|
minWidth?: string | number;
|
|
minHeight?: string | number;
|
|
maxWidth?: string | number;
|
|
maxHeight?: string | number;
|
|
|
|
// 여백
|
|
margin?: string;
|
|
marginTop?: string | number;
|
|
marginRight?: string | number;
|
|
marginBottom?: string | number;
|
|
marginLeft?: string | number;
|
|
|
|
// 패딩
|
|
padding?: string;
|
|
paddingTop?: string | number;
|
|
paddingRight?: string | number;
|
|
paddingBottom?: string | number;
|
|
paddingLeft?: string | number;
|
|
|
|
// 테두리
|
|
border?: string;
|
|
borderWidth?: string | number;
|
|
borderStyle?: "solid" | "dashed" | "dotted" | "none";
|
|
borderColor?: string;
|
|
borderRadius?: string | number;
|
|
|
|
// 배경
|
|
backgroundColor?: string;
|
|
backgroundImage?: string;
|
|
backgroundSize?: "cover" | "contain" | "auto";
|
|
backgroundPosition?: string;
|
|
backgroundRepeat?: "repeat" | "no-repeat" | "repeat-x" | "repeat-y";
|
|
|
|
// 텍스트
|
|
color?: string;
|
|
fontSize?: string | number;
|
|
fontWeight?: "normal" | "bold" | "100" | "200" | "300" | "400" | "500" | "600" | "700" | "800" | "900";
|
|
fontFamily?: string;
|
|
textAlign?: "left" | "center" | "right" | "justify";
|
|
lineHeight?: string | number;
|
|
textDecoration?: "none" | "underline" | "line-through";
|
|
|
|
// 정렬
|
|
display?: "block" | "inline" | "inline-block" | "flex" | "grid" | "none";
|
|
flexDirection?: "row" | "row-reverse" | "column" | "column-reverse";
|
|
justifyContent?: "flex-start" | "flex-end" | "center" | "space-between" | "space-around" | "space-evenly";
|
|
alignItems?: "stretch" | "flex-start" | "flex-end" | "center" | "baseline";
|
|
gap?: string | number;
|
|
|
|
// 위치
|
|
position?: "static" | "relative" | "absolute" | "fixed" | "sticky";
|
|
top?: string | number;
|
|
right?: string | number;
|
|
bottom?: string | number;
|
|
left?: string | number;
|
|
zIndex?: number;
|
|
|
|
// 그림자
|
|
boxShadow?: string;
|
|
|
|
// 기타
|
|
opacity?: number;
|
|
overflow?: "visible" | "hidden" | "scroll" | "auto";
|
|
cursor?: string;
|
|
transition?: string;
|
|
transform?: string;
|
|
|
|
// 라벨 스타일
|
|
labelDisplay?: boolean; // 라벨 표시 여부
|
|
labelText?: string; // 라벨 텍스트 (기본값은 label 속성 사용)
|
|
labelFontSize?: string | number; // 라벨 폰트 크기
|
|
labelColor?: string; // 라벨 색상
|
|
labelFontWeight?: "normal" | "bold" | "100" | "200" | "300" | "400" | "500" | "600" | "700" | "800" | "900"; // 라벨 폰트 굵기
|
|
labelFontFamily?: string; // 라벨 폰트 패밀리
|
|
labelTextAlign?: "left" | "center" | "right"; // 라벨 텍스트 정렬
|
|
labelMarginBottom?: string | number; // 라벨과 컴포넌트 사이의 간격
|
|
labelBackgroundColor?: string; // 라벨 배경색
|
|
labelPadding?: string; // 라벨 패딩
|
|
labelBorderRadius?: string | number; // 라벨 모서리 둥글기
|
|
}
|
|
|
|
// BaseComponent에 스타일 속성 추가
|
|
export interface BaseComponent {
|
|
id: string;
|
|
type: ComponentType;
|
|
position: Position;
|
|
size: { width: number; height: number };
|
|
parentId?: string;
|
|
style?: ComponentStyle; // 스타일 속성 추가
|
|
tableName?: string; // 테이블명 추가
|
|
label?: string; // 라벨 추가
|
|
gridColumns?: number; // 그리드에서 차지할 컬럼 수 (1-12)
|
|
}
|
|
|
|
// 컨테이너 컴포넌트
|
|
export interface ContainerComponent extends BaseComponent {
|
|
type: "container";
|
|
title?: string;
|
|
backgroundColor?: string;
|
|
border?: string;
|
|
borderRadius?: number;
|
|
shadow?: string;
|
|
children?: string[]; // 자식 컴포넌트 ID 목록
|
|
}
|
|
|
|
// 그룹 컴포넌트
|
|
export interface GroupComponent extends BaseComponent {
|
|
type: "group";
|
|
title?: string;
|
|
backgroundColor?: string;
|
|
border?: string;
|
|
borderRadius?: number;
|
|
shadow?: string;
|
|
collapsible?: boolean;
|
|
collapsed?: boolean;
|
|
children?: string[]; // 자식 컴포넌트 ID 목록
|
|
}
|
|
|
|
// 행 컴포넌트
|
|
export interface RowComponent extends BaseComponent {
|
|
type: "row";
|
|
gap?: number;
|
|
alignItems?: "start" | "center" | "end" | "stretch";
|
|
justifyContent?: "start" | "center" | "end" | "space-between" | "space-around";
|
|
children?: string[]; // 자식 컴포넌트 ID 목록
|
|
}
|
|
|
|
// 열 컴포넌트
|
|
export interface ColumnComponent extends BaseComponent {
|
|
type: "column";
|
|
gap?: number;
|
|
alignItems?: "start" | "center" | "end" | "stretch";
|
|
justifyContent?: "start" | "center" | "end" | "space-between" | "space-around";
|
|
children?: string[]; // 자식 컴포넌트 ID 목록
|
|
}
|
|
|
|
// 위젯 컴포넌트
|
|
export interface WidgetComponent extends BaseComponent {
|
|
type: "widget";
|
|
tableName: string;
|
|
columnName: string;
|
|
widgetType: WebType;
|
|
label: string;
|
|
placeholder?: string;
|
|
required: boolean;
|
|
readonly: boolean;
|
|
validationRules?: ValidationRule[];
|
|
displayProperties?: Record<string, any>; // 레거시 지원용 (향후 제거 예정)
|
|
webTypeConfig?: WebTypeConfig; // 웹타입별 상세 설정
|
|
}
|
|
|
|
// 데이터 테이블 컬럼 설정
|
|
export interface DataTableColumn {
|
|
id: string;
|
|
columnName: string; // 실제 DB 컬럼명
|
|
label: string; // 화면에 표시될 라벨
|
|
widgetType: WebType; // 컬럼의 데이터 타입
|
|
gridColumns: number; // 그리드에서 차지할 컬럼 수 (1-12)
|
|
visible: boolean; // 테이블에 표시할지 여부
|
|
filterable: boolean; // 필터링 가능 여부
|
|
sortable: boolean; // 정렬 가능 여부
|
|
searchable: boolean; // 검색 대상 여부
|
|
webTypeConfig?: WebTypeConfig; // 컬럼별 상세 설정
|
|
}
|
|
|
|
// 데이터 테이블 필터 설정
|
|
export interface DataTableFilter {
|
|
columnName: string;
|
|
widgetType: WebType;
|
|
label: string;
|
|
gridColumns: number; // 필터에서 차지할 컬럼 수
|
|
webTypeConfig?: WebTypeConfig;
|
|
}
|
|
|
|
// 데이터 테이블 페이지네이션 설정
|
|
export interface DataTablePagination {
|
|
enabled: boolean;
|
|
pageSize: number; // 페이지당 행 수
|
|
pageSizeOptions: number[]; // 선택 가능한 페이지 크기들
|
|
showPageSizeSelector: boolean; // 페이지 크기 선택기 표시 여부
|
|
showPageInfo: boolean; // 페이지 정보 표시 여부
|
|
showFirstLast: boolean; // 처음/마지막 버튼 표시 여부
|
|
}
|
|
|
|
// 필드 자동 값 타입
|
|
export type FieldAutoValueType =
|
|
| "none" // 일반 입력
|
|
| "current_datetime" // 현재 날짜시간
|
|
| "current_date" // 현재 날짜
|
|
| "current_time" // 현재 시간
|
|
| "current_user" // 현재 사용자
|
|
| "uuid" // UUID 생성
|
|
| "sequence" // 시퀀스 번호
|
|
| "custom" // 사용자 정의 값
|
|
| "calculated"; // 계산 필드
|
|
|
|
// 고급 필드 설정
|
|
export interface AdvancedFieldConfig {
|
|
columnName: string; // 컬럼명
|
|
inputType: "normal" | "readonly" | "hidden" | "auto"; // 입력 타입
|
|
autoValueType: FieldAutoValueType; // 자동 값 타입
|
|
defaultValue?: string; // 기본값
|
|
customValue?: string; // 사용자 정의 값
|
|
calculationFormula?: string; // 계산 공식 (예: "{price} * {quantity}")
|
|
placeholder?: string; // 플레이스홀더
|
|
helpText?: string; // 도움말 텍스트
|
|
validationRules?: {
|
|
min?: number;
|
|
max?: number;
|
|
minLength?: number;
|
|
maxLength?: number;
|
|
pattern?: string;
|
|
customValidation?: string;
|
|
};
|
|
conditionalDisplay?: {
|
|
enabled: boolean;
|
|
condition: string; // 조건식 (예: "{status} === 'active'")
|
|
};
|
|
}
|
|
|
|
// 데이터 추가 모달 커스터마이징 설정
|
|
export interface DataTableAddModalConfig {
|
|
title: string; // 모달 제목
|
|
description: string; // 모달 설명
|
|
width: "sm" | "md" | "lg" | "xl" | "2xl" | "full"; // 모달 크기
|
|
layout: "single" | "two-column" | "grid"; // 레이아웃 타입
|
|
gridColumns: number; // 그리드 레이아웃 시 컬럼 수 (2-4)
|
|
fieldOrder: string[]; // 필드 표시 순서 (컬럼명 배열)
|
|
requiredFields: string[]; // 필수 필드 (컬럼명 배열)
|
|
hiddenFields: string[]; // 숨길 필드 (컬럼명 배열)
|
|
advancedFieldConfigs: Record<string, AdvancedFieldConfig>; // 고급 필드 설정
|
|
submitButtonText: string; // 제출 버튼 텍스트
|
|
cancelButtonText: string; // 취소 버튼 텍스트
|
|
}
|
|
|
|
// 데이터 테이블 컴포넌트
|
|
export interface DataTableComponent extends BaseComponent {
|
|
type: "datatable";
|
|
tableName: string; // 연결된 테이블명
|
|
title?: string; // 테이블 제목
|
|
columns: DataTableColumn[]; // 테이블 컬럼 설정
|
|
filters: DataTableFilter[]; // 검색 필터 설정
|
|
pagination: DataTablePagination; // 페이지네이션 설정
|
|
showSearchButton: boolean; // 검색 버튼 표시 여부
|
|
searchButtonText: string; // 검색 버튼 텍스트
|
|
enableExport: boolean; // 내보내기 기능 활성화
|
|
enableRefresh: boolean; // 새로고침 기능 활성화
|
|
enableAdd: boolean; // 데이터 추가 기능 활성화
|
|
enableEdit: boolean; // 데이터 수정 기능 활성화
|
|
enableDelete: boolean; // 데이터 삭제 기능 활성화
|
|
addButtonText: string; // 추가 버튼 텍스트
|
|
editButtonText: string; // 수정 버튼 텍스트
|
|
deleteButtonText: string; // 삭제 버튼 텍스트
|
|
addModalConfig: DataTableAddModalConfig; // 추가 모달 커스터마이징 설정
|
|
gridColumns: number; // 테이블이 차지할 그리드 컬럼 수
|
|
}
|
|
|
|
// 컴포넌트 유니온 타입
|
|
export type ComponentData =
|
|
| ContainerComponent
|
|
| GroupComponent
|
|
| RowComponent
|
|
| ColumnComponent
|
|
| WidgetComponent
|
|
| DataTableComponent;
|
|
|
|
// 레이아웃 데이터
|
|
export interface LayoutData {
|
|
components: ComponentData[];
|
|
gridSettings?: GridSettings;
|
|
}
|
|
|
|
// 그리드 설정
|
|
export interface GridSettings {
|
|
columns: number; // 기본값: 12
|
|
gap: number; // 기본값: 16px
|
|
padding: number; // 기본값: 16px
|
|
snapToGrid?: boolean; // 격자에 맞춤 여부 (기본값: true)
|
|
showGrid?: boolean; // 격자 표시 여부 (기본값: true)
|
|
gridColor?: string; // 격자 색상 (기본값: #d1d5db)
|
|
gridOpacity?: number; // 격자 투명도 (기본값: 0.5)
|
|
}
|
|
|
|
// 유효성 검증 규칙
|
|
export interface ValidationRule {
|
|
type: "required" | "minLength" | "maxLength" | "pattern" | "min" | "max" | "email" | "url";
|
|
value?: any;
|
|
message: string;
|
|
}
|
|
|
|
// 화면 정의
|
|
export interface ScreenDefinition {
|
|
screenId: number;
|
|
screenName: string;
|
|
screenCode: string;
|
|
tableName: string;
|
|
companyCode: string;
|
|
description?: string;
|
|
isActive: string;
|
|
createdDate: Date;
|
|
updatedDate: Date;
|
|
createdBy?: string;
|
|
updatedBy?: string;
|
|
}
|
|
|
|
// 화면 생성 요청
|
|
export interface CreateScreenRequest {
|
|
screenName: string;
|
|
screenCode: string;
|
|
tableName: string;
|
|
companyCode: string;
|
|
description?: string;
|
|
createdBy?: string;
|
|
}
|
|
|
|
// 화면 수정 요청
|
|
export interface UpdateScreenRequest {
|
|
screenName?: string;
|
|
description?: string;
|
|
isActive?: boolean;
|
|
updatedBy?: string;
|
|
}
|
|
|
|
// 레이아웃 저장 요청
|
|
export interface SaveLayoutRequest {
|
|
components: ComponentData[];
|
|
gridSettings?: GridSettings;
|
|
}
|
|
|
|
// 화면 템플릿
|
|
export interface ScreenTemplate {
|
|
templateId: number;
|
|
templateName: string;
|
|
templateType: string;
|
|
companyCode: string;
|
|
description?: string;
|
|
layoutData?: LayoutData;
|
|
isPublic: boolean;
|
|
createdBy?: string;
|
|
createdDate: Date;
|
|
}
|
|
|
|
// 메뉴 할당 요청
|
|
export interface MenuAssignmentRequest {
|
|
menuObjid: number;
|
|
companyCode: string;
|
|
displayOrder?: number;
|
|
createdBy?: string;
|
|
}
|
|
|
|
// 드래그 상태
|
|
export interface DragState {
|
|
isDragging: boolean;
|
|
draggedItem: ComponentData | null;
|
|
draggedComponent?: ComponentData | null; // 컴포넌트 재배치용
|
|
dragSource: "toolbox" | "canvas";
|
|
dropTarget: string | null;
|
|
dropZone?: DropZone;
|
|
dragOffset?: { x: number; y: number }; // 드래그 오프셋
|
|
}
|
|
|
|
// 드롭 영역
|
|
export interface DropZone {
|
|
id: string;
|
|
accepts: ComponentType[];
|
|
position: Position;
|
|
size: Size;
|
|
}
|
|
|
|
// 그룹화 상태
|
|
export interface GroupState {
|
|
isGrouping: boolean;
|
|
selectedComponents: string[];
|
|
groupTarget?: string | null;
|
|
groupMode?: "create" | "add" | "remove" | "ungroup";
|
|
groupTitle?: string;
|
|
groupStyle?: ComponentStyle;
|
|
}
|
|
|
|
// 그룹화 작업 타입
|
|
export interface GroupingAction {
|
|
type: "create" | "add" | "remove" | "ungroup";
|
|
componentIds: string[];
|
|
groupId?: string;
|
|
groupTitle?: string;
|
|
groupStyle?: ComponentStyle;
|
|
}
|
|
|
|
// 컬럼 정보 (테이블 타입관리 연계용)
|
|
export interface ColumnInfo {
|
|
tableName: string;
|
|
columnName: string;
|
|
columnLabel?: string;
|
|
dataType: string;
|
|
webType?: WebType;
|
|
widgetType?: WebType; // 프론트엔드에서 사용하는 필드 (webType과 동일)
|
|
isNullable: string;
|
|
required?: boolean; // isNullable에서 변환된 필드
|
|
columnDefault?: string;
|
|
characterMaximumLength?: number;
|
|
numericPrecision?: number;
|
|
numericScale?: number;
|
|
detailSettings?: string; // JSON 문자열
|
|
codeCategory?: string;
|
|
referenceTable?: string;
|
|
referenceColumn?: string;
|
|
isVisible?: boolean;
|
|
displayOrder?: number;
|
|
description?: string;
|
|
}
|
|
|
|
// 웹 타입 설정
|
|
export interface ColumnWebTypeSetting {
|
|
tableName: string;
|
|
columnName: string;
|
|
webType: WebType;
|
|
columnLabel?: string;
|
|
detailSettings?: Record<string, any>;
|
|
codeCategory?: string;
|
|
referenceTable?: string;
|
|
referenceColumn?: string;
|
|
isVisible?: boolean;
|
|
displayOrder?: number;
|
|
description?: string;
|
|
}
|
|
|
|
// 위젯 데이터
|
|
export interface WidgetData {
|
|
id: string;
|
|
tableName: string;
|
|
columnName: string;
|
|
type: WebType;
|
|
label: string;
|
|
required: boolean;
|
|
readonly: boolean;
|
|
[key: string]: any; // 추가 속성들
|
|
}
|
|
|
|
// API 응답 타입
|
|
export interface ApiResponse<T> {
|
|
success: boolean;
|
|
data?: T;
|
|
message?: string;
|
|
errorCode?: string;
|
|
}
|
|
|
|
// 페이지네이션 응답
|
|
export interface PaginatedResponse<T> {
|
|
data: T[];
|
|
total: number;
|
|
page: number;
|
|
size: number;
|
|
totalPages: number;
|
|
}
|
|
|
|
// ===== 웹타입별 상세 설정 인터페이스 =====
|
|
|
|
// 날짜/시간 타입 설정
|
|
export interface DateTypeConfig {
|
|
format: "YYYY-MM-DD" | "YYYY-MM-DD HH:mm" | "YYYY-MM-DD HH:mm:ss";
|
|
showTime: boolean;
|
|
minDate?: string;
|
|
maxDate?: string;
|
|
defaultValue?: string;
|
|
placeholder?: string;
|
|
}
|
|
|
|
// 숫자 타입 설정
|
|
export interface NumberTypeConfig {
|
|
min?: number;
|
|
max?: number;
|
|
step?: number;
|
|
format?: "integer" | "decimal" | "currency" | "percentage";
|
|
decimalPlaces?: number;
|
|
thousandSeparator?: boolean;
|
|
prefix?: string; // 접두사 (예: $, ₩)
|
|
suffix?: string; // 접미사 (예: %, kg)
|
|
placeholder?: string;
|
|
}
|
|
|
|
// 선택박스 타입 설정
|
|
export interface SelectTypeConfig {
|
|
options: Array<{ label: string; value: string; disabled?: boolean }>;
|
|
multiple?: boolean;
|
|
searchable?: boolean;
|
|
placeholder?: string;
|
|
allowClear?: boolean;
|
|
maxSelections?: number; // 다중 선택 시 최대 선택 개수
|
|
}
|
|
|
|
// 텍스트 타입 설정
|
|
export interface TextTypeConfig {
|
|
minLength?: number;
|
|
maxLength?: number;
|
|
pattern?: string; // 정규식 패턴
|
|
format?: "none" | "email" | "phone" | "url" | "korean" | "english";
|
|
placeholder?: string;
|
|
autocomplete?: string;
|
|
spellcheck?: boolean;
|
|
}
|
|
|
|
// 파일 타입 설정
|
|
export interface FileTypeConfig {
|
|
accept?: string; // MIME 타입 또는 확장자 (예: ".jpg,.png" 또는 "image/*")
|
|
multiple?: boolean;
|
|
maxSize?: number; // bytes
|
|
maxFiles?: number; // 다중 업로드 시 최대 파일 개수
|
|
preview?: boolean; // 미리보기 표시 여부
|
|
dragDrop?: boolean; // 드래그 앤 드롭 지원 여부
|
|
}
|
|
|
|
// 텍스트 영역 타입 설정
|
|
export interface TextareaTypeConfig extends TextTypeConfig {
|
|
rows?: number;
|
|
cols?: number;
|
|
resize?: "none" | "both" | "horizontal" | "vertical";
|
|
wrap?: "soft" | "hard" | "off";
|
|
}
|
|
|
|
// 체크박스 타입 설정
|
|
export interface CheckboxTypeConfig {
|
|
defaultChecked?: boolean;
|
|
trueValue?: string | number | boolean; // 체크 시 값
|
|
falseValue?: string | number | boolean; // 미체크 시 값
|
|
indeterminate?: boolean; // 불확실한 상태 지원
|
|
}
|
|
|
|
// 라디오 타입 설정
|
|
export interface RadioTypeConfig {
|
|
options: Array<{ label: string; value: string; disabled?: boolean }>;
|
|
inline?: boolean; // 가로 배치 여부
|
|
defaultValue?: string;
|
|
}
|
|
|
|
// 코드 타입 설정 (공통코드 연계)
|
|
export interface CodeTypeConfig {
|
|
codeCategory: string; // 공통코드 카테고리
|
|
displayFormat?: "label" | "value" | "both"; // 표시 형식
|
|
searchable?: boolean;
|
|
placeholder?: string;
|
|
allowClear?: boolean;
|
|
}
|
|
|
|
// 엔티티 타입 설정 (참조 테이블 연계)
|
|
export interface EntityTypeConfig {
|
|
referenceTable: string;
|
|
referenceColumn: string;
|
|
displayColumn?: string; // 표시할 컬럼명 (기본값: referenceColumn)
|
|
searchable?: boolean;
|
|
placeholder?: string;
|
|
allowClear?: boolean;
|
|
filters?: Record<string, any>; // 추가 필터 조건
|
|
}
|
|
|
|
// 웹타입별 설정 유니온 타입
|
|
export type WebTypeConfig =
|
|
| DateTypeConfig
|
|
| NumberTypeConfig
|
|
| SelectTypeConfig
|
|
| TextTypeConfig
|
|
| FileTypeConfig
|
|
| TextareaTypeConfig
|
|
| CheckboxTypeConfig
|
|
| RadioTypeConfig
|
|
| CodeTypeConfig
|
|
| EntityTypeConfig;
|