Merge branch 'kwshin-node' of http://39.117.244.52:3000/kjs/ERP-node into jskim-node
This commit is contained in:
+441
-121
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* 리포트 관리 시스템 타입 정의
|
||||
*/
|
||||
|
||||
// 리포트 템플릿
|
||||
export interface ReportTemplate {
|
||||
template_id: string;
|
||||
template_name_kor: string;
|
||||
@@ -21,12 +16,12 @@ export interface ReportTemplate {
|
||||
updated_by: string | null;
|
||||
}
|
||||
|
||||
// 리포트 마스터
|
||||
export interface ReportMaster {
|
||||
report_id: string;
|
||||
report_name_kor: string;
|
||||
report_name_eng: string | null;
|
||||
template_id: string | null;
|
||||
template_name: string | null;
|
||||
report_type: string;
|
||||
company_code: string | null;
|
||||
description: string | null;
|
||||
@@ -37,7 +32,6 @@ export interface ReportMaster {
|
||||
updated_by: string | null;
|
||||
}
|
||||
|
||||
// 리포트 레이아웃
|
||||
export interface ReportLayout {
|
||||
layout_id: string;
|
||||
report_id: string;
|
||||
@@ -49,14 +43,13 @@ export interface ReportLayout {
|
||||
margin_left: number;
|
||||
margin_right: number;
|
||||
components: ComponentConfig[];
|
||||
pages?: ReportPage[]; // 새 페이지 구조 (옵셔널, 하위 호환성)
|
||||
pages?: ReportPage[];
|
||||
created_at: string;
|
||||
created_by: string | null;
|
||||
updated_at: string | null;
|
||||
updated_by: string | null;
|
||||
}
|
||||
|
||||
// 리포트 쿼리
|
||||
export interface ReportQuery {
|
||||
query_id: string;
|
||||
report_id: string;
|
||||
@@ -64,7 +57,7 @@ export interface ReportQuery {
|
||||
query_type: "MASTER" | "DETAIL";
|
||||
sql_query: string;
|
||||
parameters: string[];
|
||||
external_connection_id: number | null; // 외부 DB 연결 ID
|
||||
external_connection_id: number | null;
|
||||
display_order: number;
|
||||
created_at: string;
|
||||
created_by: string | null;
|
||||
@@ -72,7 +65,6 @@ export interface ReportQuery {
|
||||
updated_by: string | null;
|
||||
}
|
||||
|
||||
// 외부 DB 연결 (간단한 버전)
|
||||
export interface ExternalConnection {
|
||||
id: number;
|
||||
connection_name: string;
|
||||
@@ -81,29 +73,24 @@ export interface ExternalConnection {
|
||||
is_active: string;
|
||||
}
|
||||
|
||||
// 워터마크 설정
|
||||
export interface WatermarkConfig {
|
||||
enabled: boolean;
|
||||
type: "text" | "image";
|
||||
// 텍스트 워터마크
|
||||
text?: string;
|
||||
fontSize?: number;
|
||||
fontColor?: string;
|
||||
// 이미지 워터마크
|
||||
imageUrl?: string;
|
||||
// 공통 설정
|
||||
opacity: number; // 0~1
|
||||
opacity: number;
|
||||
style: "diagonal" | "center" | "tile";
|
||||
rotation?: number; // 대각선일 때 각도 (기본 -45)
|
||||
rotation?: number;
|
||||
}
|
||||
|
||||
// 페이지 설정
|
||||
export interface ReportPage {
|
||||
page_id: string;
|
||||
page_name: string;
|
||||
page_order: number;
|
||||
width: number; // mm
|
||||
height: number; // mm
|
||||
width: number;
|
||||
height: number;
|
||||
orientation: "portrait" | "landscape";
|
||||
margins: {
|
||||
top: number;
|
||||
@@ -115,16 +102,14 @@ export interface ReportPage {
|
||||
components: ComponentConfig[];
|
||||
}
|
||||
|
||||
// 레이아웃 설정 (페이지 기반)
|
||||
export interface ReportLayoutConfig {
|
||||
pages: ReportPage[];
|
||||
watermark?: WatermarkConfig; // 전체 페이지 공유 워터마크
|
||||
watermark?: WatermarkConfig;
|
||||
}
|
||||
|
||||
// 컴포넌트 설정
|
||||
export interface ComponentConfig {
|
||||
id: string;
|
||||
type: string; // "text", "label", "table", "image", "divider", "signature", "stamp"
|
||||
type: string;
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
@@ -139,7 +124,15 @@ export interface ComponentConfig {
|
||||
borderColor?: string;
|
||||
borderRadius?: number;
|
||||
textAlign?: string;
|
||||
verticalAlign?: "top" | "middle" | "bottom";
|
||||
padding?: number;
|
||||
lineHeight?: number;
|
||||
letterSpacing?: number;
|
||||
textDecoration?: "none" | "underline" | "line-through";
|
||||
fontStyle?: "normal" | "italic";
|
||||
textTransform?: "none" | "uppercase" | "lowercase";
|
||||
textOverflow?: "clip" | "ellipsis" | "wrap";
|
||||
textPreset?: string;
|
||||
queryId?: string;
|
||||
fieldName?: string;
|
||||
defaultValue?: string;
|
||||
@@ -147,118 +140,174 @@ export interface ComponentConfig {
|
||||
visible?: boolean;
|
||||
printable?: boolean;
|
||||
conditional?: string;
|
||||
locked?: boolean; // 잠금 여부 (편집/이동/삭제 방지)
|
||||
groupId?: string; // 그룹 ID (같은 그룹 ID를 가진 컴포넌트는 함께 움직임)
|
||||
// 이미지 전용
|
||||
imageUrl?: string; // 이미지 URL 또는 업로드된 파일 경로
|
||||
imageFile?: File; // 업로드된 이미지 파일 (클라이언트 측에서만 사용)
|
||||
objectFit?: "contain" | "cover" | "fill" | "none"; // 이미지 맞춤 방식
|
||||
// 구분선 전용
|
||||
orientation?: "horizontal" | "vertical"; // 구분선 방향
|
||||
lineStyle?: "solid" | "dashed" | "dotted" | "double"; // 선 스타일
|
||||
lineWidth?: number; // 구분선 두께 (borderWidth와 별도)
|
||||
lineColor?: string; // 구분선 색상 (borderColor와 별도)
|
||||
// 서명/도장 전용
|
||||
showLabel?: boolean; // 레이블 표시 여부 ("서명:", "(인)")
|
||||
labelText?: string; // 커스텀 레이블 텍스트
|
||||
labelPosition?: "top" | "left" | "bottom" | "right"; // 레이블 위치
|
||||
personName?: string; // 도장란 이름 (예: "홍길동")
|
||||
// 테이블 전용
|
||||
conditionalRule?: ConditionalRule;
|
||||
conditionalRules?: ConditionalRule[];
|
||||
gridConditionalRule?: ConditionalRule;
|
||||
gridConditionalRules?: ConditionalRule[];
|
||||
locked?: boolean;
|
||||
groupId?: string;
|
||||
imageUrl?: string;
|
||||
imageFile?: File;
|
||||
objectFit?: "contain" | "cover" | "fill" | "none";
|
||||
imageOpacity?: number;
|
||||
imageBorderRadius?: number;
|
||||
imageCaption?: string;
|
||||
imageCaptionPosition?: "top" | "bottom";
|
||||
imageCaptionFontSize?: number;
|
||||
imageCaptionColor?: string;
|
||||
imageCaptionAlign?: "left" | "center" | "right";
|
||||
imageAlt?: string;
|
||||
imageRotation?: number;
|
||||
imageFlipH?: boolean;
|
||||
imageFlipV?: boolean;
|
||||
imageCropX?: number;
|
||||
imageCropY?: number;
|
||||
imageCropWidth?: number;
|
||||
imageCropHeight?: number;
|
||||
orientation?: "horizontal" | "vertical";
|
||||
lineStyle?: "solid" | "dashed" | "dotted" | "double";
|
||||
lineWidth?: number;
|
||||
lineColor?: string;
|
||||
showLabel?: boolean;
|
||||
labelText?: string;
|
||||
labelPosition?: "top" | "left" | "bottom" | "right";
|
||||
personName?: string;
|
||||
tableColumns?: Array<{
|
||||
field: string; // 필드명
|
||||
header: string; // 헤더 표시명
|
||||
width?: number; // 컬럼 너비 (px)
|
||||
align?: "left" | "center" | "right"; // 정렬
|
||||
field: string;
|
||||
header: string;
|
||||
width?: number;
|
||||
align?: "left" | "center" | "right";
|
||||
mappingType?: "field" | "formula";
|
||||
formula?: string;
|
||||
summaryType?: "SUM" | "AVG" | "COUNT" | "NONE";
|
||||
/** 컬럼 표시 여부 — false일 때 렌더링에서 제외 (기본: true) */
|
||||
visible?: boolean;
|
||||
/** 숫자 포맷 — "none" | "comma" | "currency" (기본: "none") */
|
||||
numberFormat?: "none" | "comma" | "currency";
|
||||
/** 통화 단위 (numberFormat="currency"일 때, 기본: "원") */
|
||||
currencySuffix?: string;
|
||||
}>;
|
||||
headerBackgroundColor?: string; // 헤더 배경색
|
||||
headerTextColor?: string; // 헤더 텍스트 색상
|
||||
showBorder?: boolean; // 테두리 표시
|
||||
rowHeight?: number; // 행 높이 (px)
|
||||
// 페이지 번호 전용
|
||||
pageNumberFormat?: "number" | "numberTotal" | "koreanNumber"; // 페이지 번호 포맷
|
||||
// 카드 컴포넌트 전용
|
||||
cardTitle?: string; // 카드 제목
|
||||
showFooter?: boolean;
|
||||
exportSummaryId?: string;
|
||||
headerBackgroundColor?: string;
|
||||
headerTextColor?: string;
|
||||
showBorder?: boolean;
|
||||
rowHeight?: number;
|
||||
pageNumberFormat?: "number" | "numberTotal" | "koreanNumber";
|
||||
cardTitle?: string;
|
||||
cardItems?: Array<{
|
||||
label: string; // 항목 라벨 (예: "회사명")
|
||||
value: string; // 항목 값 (예: "당사 주식회사") 또는 기본값
|
||||
fieldName?: string; // 쿼리 필드명 (바인딩용)
|
||||
label: string;
|
||||
value: string;
|
||||
fieldName?: string;
|
||||
}>;
|
||||
labelWidth?: number; // 라벨 컬럼 너비 (px)
|
||||
showCardBorder?: boolean; // 카드 테두리 표시 여부
|
||||
showCardTitle?: boolean; // 카드 제목 표시 여부
|
||||
titleFontSize?: number; // 제목 폰트 크기
|
||||
labelFontSize?: number; // 라벨 폰트 크기
|
||||
valueFontSize?: number; // 값 폰트 크기
|
||||
titleColor?: string; // 제목 색상
|
||||
labelColor?: string; // 라벨 색상
|
||||
valueColor?: string; // 값 색상
|
||||
// 계산 컴포넌트 전용
|
||||
labelWidth?: number;
|
||||
showCardBorder?: boolean;
|
||||
showCardTitle?: boolean;
|
||||
titleFontSize?: number;
|
||||
labelFontSize?: number;
|
||||
valueFontSize?: number;
|
||||
titleColor?: string;
|
||||
labelColor?: string;
|
||||
valueColor?: string;
|
||||
calcItems?: Array<{
|
||||
label: string; // 항목 라벨 (예: "공급가액")
|
||||
value: number | string; // 항목 값 또는 기본값
|
||||
operator: "+" | "-" | "x" | "÷"; // 연산자
|
||||
fieldName?: string; // 쿼리 필드명 (바인딩용)
|
||||
label: string;
|
||||
value: number | string;
|
||||
operator: "+" | "-" | "x" | "÷";
|
||||
fieldName?: string;
|
||||
}>;
|
||||
resultLabel?: string; // 결과 라벨 (예: "합계 금액")
|
||||
resultColor?: string; // 결과 색상
|
||||
resultFontSize?: number; // 결과 폰트 크기
|
||||
showCalcBorder?: boolean; // 테두리 표시 여부
|
||||
numberFormat?: "none" | "comma" | "currency"; // 숫자 포맷 (없음, 천단위, 원화)
|
||||
currencySuffix?: string; // 통화 접미사 (예: "원")
|
||||
// 바코드 컴포넌트 전용
|
||||
barcodeType?: "CODE128" | "CODE39" | "EAN13" | "EAN8" | "UPC" | "QR"; // 바코드 타입
|
||||
barcodeValue?: string; // 고정값
|
||||
barcodeFieldName?: string; // 쿼리 필드 바인딩
|
||||
showBarcodeText?: boolean; // 바코드 아래 텍스트 표시 (1D만)
|
||||
barcodeColor?: string; // 바코드 색상
|
||||
barcodeBackground?: string; // 배경 색상
|
||||
barcodeMargin?: number; // 여백
|
||||
qrErrorCorrectionLevel?: "L" | "M" | "Q" | "H"; // QR 오류 보정 수준
|
||||
// QR코드 다중 필드 (JSON 형식)
|
||||
resultLabel?: string;
|
||||
resultColor?: string;
|
||||
resultFontSize?: number;
|
||||
showCalcBorder?: boolean;
|
||||
numberFormat?: "none" | "comma" | "currency";
|
||||
currencySuffix?: string;
|
||||
barcodeType?: "CODE128" | "CODE39" | "EAN13" | "EAN8" | "UPC" | "QR";
|
||||
barcodeValue?: string;
|
||||
barcodeFieldName?: string;
|
||||
showBarcodeText?: boolean;
|
||||
barcodeColor?: string;
|
||||
barcodeBackground?: string;
|
||||
barcodeMargin?: number;
|
||||
qrErrorCorrectionLevel?: "L" | "M" | "Q" | "H";
|
||||
qrDataFields?: Array<{
|
||||
fieldName: string; // 쿼리 필드명
|
||||
label: string; // JSON 키 이름
|
||||
fieldName: string;
|
||||
label: string;
|
||||
}>;
|
||||
qrUseMultiField?: boolean; // 다중 필드 사용 여부
|
||||
qrIncludeAllRows?: boolean; // 모든 행 포함 (배열 JSON)
|
||||
// 체크박스 컴포넌트 전용
|
||||
checkboxChecked?: boolean; // 체크 상태 (고정값)
|
||||
checkboxFieldName?: string; // 쿼리 필드 바인딩 (truthy/falsy 값)
|
||||
checkboxLabel?: string; // 체크박스 옆 레이블 텍스트
|
||||
checkboxSize?: number; // 체크박스 크기 (px)
|
||||
checkboxColor?: string; // 체크 색상
|
||||
checkboxBorderColor?: string; // 테두리 색상
|
||||
checkboxLabelPosition?: "left" | "right"; // 레이블 위치
|
||||
qrUseMultiField?: boolean;
|
||||
qrIncludeAllRows?: boolean;
|
||||
checkboxChecked?: boolean;
|
||||
checkboxFieldName?: string;
|
||||
checkboxLabel?: string;
|
||||
checkboxSize?: number;
|
||||
checkboxColor?: string;
|
||||
checkboxBorderColor?: string;
|
||||
checkboxLabelPosition?: "left" | "right";
|
||||
chartQueryId?: string;
|
||||
chartLabelField?: string;
|
||||
chartValueField?: string;
|
||||
chartColors?: string[];
|
||||
chartInnerRadius?: number;
|
||||
chartShowLegend?: boolean;
|
||||
chartTitle?: string;
|
||||
/** 테이블 컴포넌트의 데이터 소스 테이블/뷰명 */
|
||||
dataTableName?: string;
|
||||
/** 테이블 모드에서 미리보기 행 수 */
|
||||
tableRowCount?: number;
|
||||
content?: string;
|
||||
text?: string;
|
||||
conditionalStyles?: Array<{ value: string; backgroundColor?: string; fontColor?: string }>;
|
||||
// 비주얼 쿼리 빌더 (table 컴포넌트 전용)
|
||||
visualQuery?: VisualQuery;
|
||||
visualDataSource?: VisualDataSource;
|
||||
// 카드 레이아웃 설정 (card 컴포넌트 전용 - v3)
|
||||
cardLayoutConfig?: CardLayoutConfig;
|
||||
|
||||
// 그리드 양식 모드 (table 컴포넌트 전용)
|
||||
gridMode?: boolean;
|
||||
gridCells?: GridCell[];
|
||||
gridRowCount?: number;
|
||||
gridColCount?: number;
|
||||
gridColWidths?: number[];
|
||||
gridRowHeights?: number[];
|
||||
gridHeaderRows?: number;
|
||||
gridHeaderCols?: number;
|
||||
/** 격자 모드 하단 요약(푸터) 행 수 */
|
||||
gridFooterRows?: number;
|
||||
/** 격자 모드 푸터 표시 여부 */
|
||||
gridShowFooter?: boolean;
|
||||
}
|
||||
|
||||
// 리포트 상세
|
||||
export interface ReportDetail {
|
||||
report: ReportMaster;
|
||||
layout: ReportLayout | null;
|
||||
queries: ReportQuery[];
|
||||
menuObjids?: number[]; // 연결된 메뉴 ID 목록
|
||||
menuObjids?: number[];
|
||||
}
|
||||
|
||||
// 리포트 목록 응답
|
||||
export interface GetReportsResponse {
|
||||
items: ReportMaster[];
|
||||
total: number;
|
||||
page: number;
|
||||
limit: number;
|
||||
typeSummary: Array<{ type: string; count: number }>;
|
||||
allTypes: string[];
|
||||
recentActivity: Array<{ date: string; count: number }>;
|
||||
recentTotal: number;
|
||||
}
|
||||
|
||||
// 리포트 목록 조회 파라미터
|
||||
export interface GetReportsParams {
|
||||
page?: number;
|
||||
limit?: number;
|
||||
searchText?: string;
|
||||
searchField?: "report_name" | "created_by" | "report_type" | "updated_at" | "created_at";
|
||||
startDate?: string;
|
||||
endDate?: string;
|
||||
reportType?: string;
|
||||
useYn?: string;
|
||||
sortBy?: string;
|
||||
sortOrder?: "ASC" | "DESC";
|
||||
}
|
||||
|
||||
// 리포트 생성 요청
|
||||
export interface CreateReportRequest {
|
||||
reportNameKor: string;
|
||||
reportNameEng?: string;
|
||||
@@ -268,7 +317,6 @@ export interface CreateReportRequest {
|
||||
companyCode?: string;
|
||||
}
|
||||
|
||||
// 리포트 수정 요청
|
||||
export interface UpdateReportRequest {
|
||||
reportNameKor?: string;
|
||||
reportNameEng?: string;
|
||||
@@ -277,9 +325,8 @@ export interface UpdateReportRequest {
|
||||
useYn?: string;
|
||||
}
|
||||
|
||||
// 레이아웃 저장 요청
|
||||
export interface SaveLayoutRequest {
|
||||
layoutConfig: ReportLayoutConfig; // 페이지 기반 구조
|
||||
layoutConfig: ReportLayoutConfig;
|
||||
queries?: Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -288,31 +335,304 @@ export interface SaveLayoutRequest {
|
||||
parameters: string[];
|
||||
externalConnectionId?: number;
|
||||
}>;
|
||||
menuObjids?: number[]; // 연결할 메뉴 ID 목록
|
||||
|
||||
// 하위 호환성 (deprecated)
|
||||
canvasWidth?: number;
|
||||
canvasHeight?: number;
|
||||
pageOrientation?: string;
|
||||
marginTop?: number;
|
||||
marginBottom?: number;
|
||||
marginLeft?: number;
|
||||
marginRight?: number;
|
||||
components?: ComponentConfig[];
|
||||
menuObjids?: number[];
|
||||
}
|
||||
|
||||
// 템플릿 목록 응답
|
||||
export interface GetTemplatesResponse {
|
||||
system: ReportTemplate[];
|
||||
custom: ReportTemplate[];
|
||||
}
|
||||
|
||||
// 템플릿 생성 요청
|
||||
export interface CreateTemplateRequest {
|
||||
templateNameKor: string;
|
||||
templateNameEng?: string;
|
||||
templateType: string;
|
||||
description?: string;
|
||||
layoutConfig?: any;
|
||||
defaultQueries?: any;
|
||||
layoutConfig?: Record<string, unknown>;
|
||||
defaultQueries?: Array<Record<string, unknown>>;
|
||||
}
|
||||
|
||||
export interface GetReportsByMenuResponse {
|
||||
items: ReportMaster[];
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface ConditionalRule {
|
||||
queryId: string;
|
||||
field: string;
|
||||
operator: "eq" | "ne" | "gt" | "lt" | "gte" | "lte" | "contains" | "notEmpty" | "empty";
|
||||
value: string;
|
||||
action: "show" | "hide";
|
||||
}
|
||||
|
||||
export interface VisualQueryFormulaColumn {
|
||||
alias: string;
|
||||
header: string;
|
||||
expression: string;
|
||||
}
|
||||
|
||||
export interface VisualQuery {
|
||||
tableName: string;
|
||||
limit?: number;
|
||||
columns: string[];
|
||||
formulaColumns: VisualQueryFormulaColumn[];
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// 그리드 양식 셀 타입 정의 (복잡한 테이블 — 셀 병합, 고정텍스트/데이터 혼합)
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface GridCell {
|
||||
id: string;
|
||||
row: number;
|
||||
col: number;
|
||||
rowSpan?: number;
|
||||
colSpan?: number;
|
||||
cellType: "static" | "field" | "formula";
|
||||
value?: string;
|
||||
field?: string;
|
||||
formula?: string;
|
||||
align?: "left" | "center" | "right";
|
||||
verticalAlign?: "top" | "middle" | "bottom";
|
||||
fontWeight?: "normal" | "bold";
|
||||
fontSize?: number;
|
||||
backgroundColor?: string;
|
||||
textColor?: string;
|
||||
borderStyle?: "thin" | "medium" | "thick" | "none";
|
||||
numberFormat?: "none" | "comma" | "currency";
|
||||
currencySuffix?: string;
|
||||
merged?: boolean;
|
||||
mergedBy?: string;
|
||||
/** 셀 요약(집계) 유형 — 격자 모드에서 푸터 행 셀에 적용 */
|
||||
summaryType?: "SUM" | "AVG" | "COUNT" | "NONE";
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// 카드 레이아웃 v3 타입 정의
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/** 카드 내부 요소 타입 */
|
||||
export type CardElementType =
|
||||
| "header" | "dataCell" | "divider" | "badge"
|
||||
| "image" | "number" | "date" | "link" | "status" | "spacer" | "staticText";
|
||||
|
||||
/** 데이터 셀 방향 */
|
||||
export type CellDirection = "vertical" | "horizontal";
|
||||
|
||||
/** 카드 요소 공통 인터페이스 */
|
||||
export interface CardElementBase {
|
||||
id: string;
|
||||
type: CardElementType;
|
||||
colspan?: number;
|
||||
rowspan?: number;
|
||||
direction?: CellDirection;
|
||||
}
|
||||
|
||||
/** 헤더 요소 */
|
||||
export interface CardHeaderElement extends CardElementBase {
|
||||
type: "header";
|
||||
icon?: string;
|
||||
iconColor?: string;
|
||||
title: string;
|
||||
titleColor?: string;
|
||||
titleFontSize?: number;
|
||||
fontSize?: number;
|
||||
color?: string;
|
||||
fontWeight?: string;
|
||||
}
|
||||
|
||||
/** 데이터 셀 요소 */
|
||||
export interface CardDataCellElement extends CardElementBase {
|
||||
type: "dataCell";
|
||||
direction: CellDirection;
|
||||
label: string;
|
||||
columnName?: string;
|
||||
inputType?: "text" | "date" | "number" | "select" | "readonly";
|
||||
required?: boolean;
|
||||
placeholder?: string;
|
||||
selectOptions?: string[];
|
||||
labelWidth?: number;
|
||||
labelFontSize?: number;
|
||||
labelColor?: string;
|
||||
valueFontSize?: number;
|
||||
valueColor?: string;
|
||||
labelFontWeight?: string;
|
||||
}
|
||||
|
||||
/** 구분선 요소 */
|
||||
export interface CardDividerElement extends CardElementBase {
|
||||
type: "divider";
|
||||
style?: "solid" | "dashed" | "dotted";
|
||||
color?: string;
|
||||
thickness?: number;
|
||||
}
|
||||
|
||||
/** 뱃지 요소 */
|
||||
export interface CardBadgeElement extends CardElementBase {
|
||||
type: "badge";
|
||||
label?: string;
|
||||
columnName?: string;
|
||||
colorMap?: Record<string, string>;
|
||||
bgColor?: string;
|
||||
textColor?: string;
|
||||
}
|
||||
|
||||
/** 이미지 요소 */
|
||||
export interface CardImageElement extends CardElementBase {
|
||||
type: "image";
|
||||
columnName?: string;
|
||||
altText?: string;
|
||||
objectFit?: "contain" | "cover" | "fill";
|
||||
height?: number;
|
||||
}
|
||||
|
||||
/** 숫자/금액 요소 */
|
||||
export interface CardNumberElement extends CardElementBase {
|
||||
type: "number";
|
||||
label: string;
|
||||
columnName?: string;
|
||||
numberFormat?: "none" | "comma" | "currency";
|
||||
currencySuffix?: string;
|
||||
labelFontSize?: number;
|
||||
labelColor?: string;
|
||||
valueFontSize?: number;
|
||||
valueColor?: string;
|
||||
}
|
||||
|
||||
/** 날짜 요소 */
|
||||
export interface CardDateElement extends CardElementBase {
|
||||
type: "date";
|
||||
label: string;
|
||||
columnName?: string;
|
||||
dateFormat?: string;
|
||||
labelFontSize?: number;
|
||||
labelColor?: string;
|
||||
valueFontSize?: number;
|
||||
valueColor?: string;
|
||||
}
|
||||
|
||||
/** 링크 요소 */
|
||||
export interface CardLinkElement extends CardElementBase {
|
||||
type: "link";
|
||||
label: string;
|
||||
columnName?: string;
|
||||
linkText?: string;
|
||||
openInNewTab?: boolean;
|
||||
}
|
||||
|
||||
/** 상태 요소 */
|
||||
export interface CardStatusElement extends CardElementBase {
|
||||
type: "status";
|
||||
columnName?: string;
|
||||
statusMappings?: Array<{ value: string; label: string; color: string }>;
|
||||
}
|
||||
|
||||
/** 빈 공간 요소 */
|
||||
export interface CardSpacerElement extends CardElementBase {
|
||||
type: "spacer";
|
||||
height?: number;
|
||||
}
|
||||
|
||||
/** 고정 텍스트 요소 */
|
||||
export interface CardStaticTextElement extends CardElementBase {
|
||||
type: "staticText";
|
||||
text: string;
|
||||
fontSize?: number;
|
||||
color?: string;
|
||||
fontWeight?: "normal" | "bold";
|
||||
textAlign?: "left" | "center" | "right";
|
||||
}
|
||||
|
||||
/** 통합 요소 타입 */
|
||||
export type CardElement =
|
||||
| CardHeaderElement
|
||||
| CardDataCellElement
|
||||
| CardDividerElement
|
||||
| CardBadgeElement
|
||||
| CardImageElement
|
||||
| CardNumberElement
|
||||
| CardDateElement
|
||||
| CardLinkElement
|
||||
| CardStatusElement
|
||||
| CardSpacerElement
|
||||
| CardStaticTextElement;
|
||||
|
||||
/** 카드 행 정의 */
|
||||
export interface CardLayoutRow {
|
||||
id: string;
|
||||
gridColumns: number;
|
||||
elements: CardElement[];
|
||||
height?: string;
|
||||
gap?: string;
|
||||
marginBottom?: string;
|
||||
}
|
||||
|
||||
/** 카드 레이아웃 전체 설정 */
|
||||
export interface CardLayoutConfig {
|
||||
tableName?: string;
|
||||
primaryKey?: string;
|
||||
rows: CardLayoutRow[];
|
||||
padding?: string;
|
||||
gap?: string;
|
||||
borderStyle?: string;
|
||||
borderColor?: string;
|
||||
backgroundColor?: string;
|
||||
headerTitleFontSize?: number;
|
||||
headerTitleColor?: string;
|
||||
labelFontSize?: number;
|
||||
labelColor?: string;
|
||||
valueFontSize?: number;
|
||||
valueColor?: string;
|
||||
dividerThickness?: number;
|
||||
dividerColor?: string;
|
||||
accentBorderColor?: string;
|
||||
accentBorderWidth?: number;
|
||||
borderRadius?: string;
|
||||
borderWidth?: number;
|
||||
headerFontWeight?: "normal" | "bold";
|
||||
valueFontWeight?: "normal" | "bold";
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// 그리드 설정
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface GridConfig {
|
||||
visible: boolean;
|
||||
snapToGrid: boolean;
|
||||
cellWidth: number;
|
||||
cellHeight: number;
|
||||
columns: number;
|
||||
rows: number;
|
||||
gridColor: string;
|
||||
gridOpacity: number;
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// 비주얼 데이터 소스 (마스터-디테일 구조)
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface VisualColumn {
|
||||
name: string;
|
||||
label?: string;
|
||||
dataType?: string;
|
||||
selected?: boolean;
|
||||
}
|
||||
|
||||
export interface JoinKeyPair {
|
||||
masterColumn: string;
|
||||
detailColumn: string;
|
||||
autoDetected?: boolean;
|
||||
}
|
||||
|
||||
export interface VisualDetailSource {
|
||||
id: string;
|
||||
tableName: string;
|
||||
columns: VisualColumn[];
|
||||
joinKeys: JoinKeyPair[];
|
||||
}
|
||||
|
||||
export interface VisualDataSource {
|
||||
master: { tableName: string; columns: VisualColumn[] };
|
||||
details: VisualDetailSource[];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user