864 lines
26 KiB
TypeScript
864 lines
26 KiB
TypeScript
// 화면관리 시스템 타입 정의
|
||
|
||
// 기본 컴포넌트 타입
|
||
export type ComponentType = "container" | "row" | "column" | "widget" | "group" | "datatable" | "file" | "area";
|
||
|
||
// 웹 타입 정의
|
||
export type WebType =
|
||
| "text"
|
||
| "number"
|
||
| "date"
|
||
| "code"
|
||
| "entity"
|
||
| "textarea"
|
||
| "select"
|
||
| "checkbox"
|
||
| "radio"
|
||
| "file"
|
||
| "email"
|
||
| "tel"
|
||
| "datetime"
|
||
| "dropdown"
|
||
| "text_area"
|
||
| "boolean"
|
||
| "decimal"
|
||
| "button";
|
||
|
||
// 버튼 기능 타입 정의
|
||
export type ButtonActionType =
|
||
| "save" // 저장
|
||
| "delete" // 삭제
|
||
| "edit" // 수정
|
||
| "add" // 추가
|
||
| "search" // 검색
|
||
| "reset" // 초기화
|
||
| "submit" // 제출
|
||
| "close" // 닫기
|
||
| "popup" // 모달 열기
|
||
| "navigate" // 페이지 이동
|
||
| "custom"; // 사용자 정의
|
||
|
||
// 위치 정보
|
||
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)
|
||
inputType?: "direct" | "auto"; // 입력 타입 (직접입력/자동입력)
|
||
autoValueType?:
|
||
| "current_datetime"
|
||
| "current_date"
|
||
| "current_time"
|
||
| "current_user"
|
||
| "uuid"
|
||
| "sequence"
|
||
| "user_defined"; // 자동 값 타입
|
||
}
|
||
|
||
// 컨테이너 컴포넌트
|
||
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 type AreaLayoutType =
|
||
| "box" // 기본 박스
|
||
| "card" // 카드 형태 (그림자 + 둥근 모서리)
|
||
| "panel" // 패널 형태 (헤더 포함)
|
||
| "section" // 섹션 형태 (제목 + 구분선)
|
||
| "grid" // 그리드 레이아웃
|
||
| "flex-row" // 가로 플렉스
|
||
| "flex-column" // 세로 플렉스
|
||
| "sidebar" // 사이드바 레이아웃
|
||
| "header-content" // 헤더-컨텐츠 레이아웃
|
||
| "tabs" // 탭 레이아웃
|
||
| "accordion"; // 아코디언 레이아웃
|
||
|
||
// 영역 컴포넌트
|
||
export interface AreaComponent extends BaseComponent {
|
||
type: "area";
|
||
layoutType: AreaLayoutType;
|
||
title?: string;
|
||
description?: string;
|
||
|
||
// 레이아웃별 설정
|
||
layoutConfig?: {
|
||
// 그리드 레이아웃 설정
|
||
gridColumns?: number;
|
||
gridRows?: number;
|
||
gridGap?: number;
|
||
|
||
// 플렉스 레이아웃 설정
|
||
flexDirection?: "row" | "column";
|
||
flexWrap?: "nowrap" | "wrap" | "wrap-reverse";
|
||
justifyContent?: "flex-start" | "flex-end" | "center" | "space-between" | "space-around" | "space-evenly";
|
||
alignItems?: "stretch" | "flex-start" | "flex-end" | "center" | "baseline";
|
||
gap?: number;
|
||
|
||
// 탭 레이아웃 설정
|
||
tabPosition?: "top" | "bottom" | "left" | "right";
|
||
defaultActiveTab?: string;
|
||
|
||
// 사이드바 레이아웃 설정
|
||
sidebarPosition?: "left" | "right";
|
||
sidebarWidth?: number;
|
||
collapsible?: boolean;
|
||
|
||
// 아코디언 설정
|
||
allowMultiple?: boolean;
|
||
defaultExpanded?: string[];
|
||
};
|
||
|
||
// 스타일 설정
|
||
areaStyle?: {
|
||
backgroundColor?: string;
|
||
borderColor?: string;
|
||
borderWidth?: number;
|
||
borderStyle?: "solid" | "dashed" | "dotted" | "none";
|
||
borderRadius?: number;
|
||
padding?: number;
|
||
margin?: number;
|
||
shadow?: "none" | "sm" | "md" | "lg" | "xl";
|
||
|
||
// 헤더 스타일 (panel, section 타입용)
|
||
headerBackgroundColor?: string;
|
||
headerTextColor?: string;
|
||
headerHeight?: number;
|
||
headerPadding?: number;
|
||
|
||
// 그리드 라인 표시 (grid 타입용)
|
||
showGridLines?: boolean;
|
||
gridLineColor?: string;
|
||
};
|
||
|
||
children?: string[]; // 자식 컴포넌트 ID 목록
|
||
}
|
||
|
||
// 파일 첨부 컴포넌트
|
||
export interface FileComponent extends BaseComponent {
|
||
type: "file";
|
||
fileConfig: {
|
||
// 파일 업로드 설정
|
||
accept: string[]; // 허용 파일 타입 ['image/*', '.pdf', '.doc']
|
||
multiple: boolean; // 다중 파일 선택 허용
|
||
maxSize: number; // 최대 파일 크기 (MB)
|
||
maxFiles: number; // 최대 파일 개수
|
||
|
||
// 문서 분류 설정
|
||
docType: string; // 문서 타입 (CONTRACT, DRAWING, PHOTO, DOCUMENT, REPORT, OTHER)
|
||
docTypeName: string; // 문서 타입 표시명
|
||
|
||
// 연결 객체 설정
|
||
targetObjid?: string; // 연결된 주 객체 ID (예: 계약 ID, 프로젝트 ID)
|
||
parentTargetObjid?: string; // 부모 객체 ID (계층 구조용)
|
||
|
||
// 테이블 연결 설정 (새로 추가)
|
||
linkedTable?: string; // 연결할 테이블명 (예: company_mng, user_info)
|
||
linkedField?: string; // 연결할 필드명 (예: emp_id, user_id)
|
||
autoLink?: boolean; // 자동 연결 여부 (현재 레코드와 자동 연결)
|
||
recordId?: string; // 연결할 레코드 ID
|
||
|
||
// 가상 파일 컬럼 전용 설정
|
||
columnName?: string; // 가상 파일 컬럼명 (tableName:recordId:columnName 형태로 target_objid 생성)
|
||
isVirtualFileColumn?: boolean; // 가상 파일 컬럼 여부
|
||
|
||
// UI 설정
|
||
showPreview: boolean; // 미리보기 표시 여부
|
||
showProgress: boolean; // 업로드 진행률 표시
|
||
dragDropText: string; // 드래그앤드롭 안내 텍스트
|
||
uploadButtonText: string; // 업로드 버튼 텍스트
|
||
|
||
// 자동 업로드 설정
|
||
autoUpload: boolean; // 파일 선택 시 자동 업로드
|
||
chunkedUpload: boolean; // 대용량 파일 분할 업로드
|
||
};
|
||
|
||
// 업로드된 파일 목록
|
||
uploadedFiles: AttachedFileInfo[];
|
||
}
|
||
|
||
// 첨부파일 정보 (attach_file_info 테이블 기반)
|
||
export interface AttachedFileInfo {
|
||
objid: string; // 파일 고유 ID
|
||
savedFileName: string; // 서버에 저장된 파일명
|
||
realFileName: string; // 실제 파일명 (사용자가 본 원본명)
|
||
fileSize: number; // 파일 크기 (bytes)
|
||
fileExt: string; // 파일 확장자
|
||
filePath: string; // 파일 저장 경로
|
||
docType: string; // 문서 분류
|
||
docTypeName: string; // 문서 분류 표시명
|
||
targetObjid: string; // 연결 객체 ID
|
||
parentTargetObjid?: string; // 부모 객체 ID
|
||
companyCode: string; // 회사 코드
|
||
writer: string; // 작성자
|
||
regdate: string; // 등록일시
|
||
status: string; // 상태 (ACTIVE, DELETED)
|
||
|
||
// UI용 추가 속성
|
||
uploadProgress?: number; // 업로드 진행률 (0-100)
|
||
isUploading?: boolean; // 업로드 중 여부
|
||
hasError?: boolean; // 에러 발생 여부
|
||
errorMessage?: string; // 에러 메시지
|
||
}
|
||
|
||
// 위젯 컴포넌트
|
||
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; // 컬럼별 상세 설정
|
||
|
||
// 가상 파일 컬럼 관련 속성
|
||
isVirtualFileColumn?: boolean; // 가상 파일 컬럼인지 여부
|
||
fileColumnConfig?: {
|
||
docType?: string; // 문서 타입 (CONTRACT, DRAWING, PHOTO 등)
|
||
docTypeName?: string; // 문서 타입 표시명
|
||
maxFiles?: number; // 최대 파일 개수
|
||
accept?: string[]; // 허용 파일 타입
|
||
};
|
||
}
|
||
|
||
// 데이터 테이블 필터 설정
|
||
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
|
||
| AreaComponent
|
||
| WidgetComponent
|
||
| DataTableComponent
|
||
| FileComponent;
|
||
|
||
// 레이아웃 데이터
|
||
export interface LayoutData {
|
||
components: ComponentData[];
|
||
gridSettings?: GridSettings;
|
||
screenResolution?: ScreenResolution;
|
||
}
|
||
|
||
// 그리드 설정
|
||
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;
|
||
tableLabel?: 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과 동일)
|
||
inputType?: "direct" | "auto"; // 입력 타입
|
||
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" | "alphanumeric" | "numeric";
|
||
placeholder?: string;
|
||
defaultValue?: string; // 기본값
|
||
autocomplete?: string;
|
||
spellcheck?: boolean;
|
||
multiline?: boolean; // 여러 줄 입력 여부
|
||
// 자동입력 관련 설정
|
||
autoInput?: boolean; // 자동입력 활성화
|
||
autoValueType?:
|
||
| "current_datetime"
|
||
| "current_date"
|
||
| "current_time"
|
||
| "current_user"
|
||
| "uuid"
|
||
| "sequence"
|
||
| "custom"; // 자동값 타입
|
||
customValue?: string; // 사용자 정의 값
|
||
}
|
||
|
||
// 파일 타입 설정
|
||
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 interface ButtonTypeConfig {
|
||
actionType: ButtonActionType;
|
||
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link";
|
||
icon?: string; // Lucide 아이콘 이름
|
||
confirmMessage?: string; // 확인 메시지 (delete, submit 등에서 사용)
|
||
|
||
// 모달 관련 설정
|
||
popupTitle?: string;
|
||
popupContent?: string;
|
||
popupScreenId?: number; // 모달로 열 화면 ID
|
||
|
||
// 네비게이션 관련 설정
|
||
navigateType?: "url" | "screen"; // 네비게이션 방식: URL 직접 입력 또는 화면 선택
|
||
navigateUrl?: string;
|
||
navigateScreenId?: number; // 이동할 화면 ID
|
||
navigateTarget?: "_self" | "_blank";
|
||
|
||
// 커스텀 액션 설정
|
||
customAction?: string; // JavaScript 코드 또는 함수명
|
||
|
||
// 스타일 설정
|
||
backgroundColor?: string;
|
||
textColor?: string;
|
||
borderColor?: string;
|
||
}
|
||
|
||
// 화면 해상도 설정
|
||
export interface ScreenResolution {
|
||
width: number;
|
||
height: number;
|
||
name: string;
|
||
category: "desktop" | "tablet" | "mobile" | "custom";
|
||
}
|
||
|
||
// 미리 정의된 해상도 프리셋
|
||
export const SCREEN_RESOLUTIONS: ScreenResolution[] = [
|
||
// Desktop
|
||
{ width: 1920, height: 1080, name: "Full HD (1920×1080)", category: "desktop" },
|
||
{ width: 1366, height: 768, name: "HD (1366×768)", category: "desktop" },
|
||
{ width: 1440, height: 900, name: "WXGA+ (1440×900)", category: "desktop" },
|
||
{ width: 1280, height: 1024, name: "SXGA (1280×1024)", category: "desktop" },
|
||
|
||
// Tablet
|
||
{ width: 1024, height: 768, name: "iPad (1024×768)", category: "tablet" },
|
||
{ width: 768, height: 1024, name: "iPad Portrait (768×1024)", category: "tablet" },
|
||
{ width: 1112, height: 834, name: "iPad Pro 10.5 (1112×834)", category: "tablet" },
|
||
|
||
// Mobile
|
||
{ width: 375, height: 667, name: "iPhone SE (375×667)", category: "mobile" },
|
||
{ width: 414, height: 896, name: "iPhone 11 (414×896)", category: "mobile" },
|
||
{ width: 360, height: 640, name: "Android (360×640)", category: "mobile" },
|
||
];
|
||
|
||
// 웹타입별 설정 유니온 타입
|
||
export type WebTypeConfig =
|
||
| DateTypeConfig
|
||
| NumberTypeConfig
|
||
| SelectTypeConfig
|
||
| TextTypeConfig
|
||
| FileTypeConfig
|
||
| TextareaTypeConfig
|
||
| CheckboxTypeConfig
|
||
| RadioTypeConfig
|
||
| CodeTypeConfig
|
||
| EntityTypeConfig
|
||
| ButtonTypeConfig;
|