docs: 품목정보 화면 구현 가이드 업데이트
- 품목정보 화면의 구현 예시를 추가하여 JSON 데이터 사용에 대한 주의사항을 명시하였습니다. - V2 컴포넌트 목록을 업데이트하고, 사용 가능한 컴포넌트에 대한 설명을 추가하였습니다. - 화면 구현 시 테이블 구조 분석 및 JSON 구조 작성 방법에 대한 지침을 포함하였습니다. - 각 컴포넌트의 역할과 사용법을 명확히 하여 개발자들이 쉽게 참고할 수 있도록 하였습니다.
This commit is contained in:
parent
6cd416fdaa
commit
7a9ec8d02c
|
|
@ -4,6 +4,53 @@
|
||||||
> 메뉴 경로: 기준정보 > 품목정보
|
> 메뉴 경로: 기준정보 > 품목정보
|
||||||
> 테이블: `item_info`
|
> 테이블: `item_info`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ 문서 사용 안내
|
||||||
|
|
||||||
|
> **이 문서는 "품목정보" 화면의 구현 예시입니다.**
|
||||||
|
>
|
||||||
|
> ### 📌 중요: JSON 데이터는 참고용입니다!
|
||||||
|
>
|
||||||
|
> 이 문서에 포함된 JSON 설정(레이아웃, 컴포넌트 구성 등)은 **품목정보 화면에 특화된 예시**입니다.
|
||||||
|
>
|
||||||
|
> **다른 화면을 구현할 때:**
|
||||||
|
> 1. 이 JSON을 그대로 복사해서 사용하지 마세요
|
||||||
|
> 2. 해당 화면의 **테이블 구조를 먼저 분석**하세요
|
||||||
|
> 3. 화면의 **요구사항과 기능을 파악**하세요
|
||||||
|
> 4. 분석 결과에 맞는 **새로운 JSON 구조를 작성**하세요
|
||||||
|
>
|
||||||
|
> ### 참고해야 할 항목
|
||||||
|
> - ✅ 문서 구조 및 작성 형식
|
||||||
|
> - ✅ V2 컴포넌트 종류 및 사용법
|
||||||
|
> - ✅ API 호출 방식 및 DB INSERT 절차
|
||||||
|
> - ✅ 컴포넌트 설정 패턴 (position, size, overrides 구조)
|
||||||
|
>
|
||||||
|
> ### 복사하면 안 되는 항목
|
||||||
|
> - ❌ 테이블명 (`item_info` → 해당 화면의 테이블로 변경)
|
||||||
|
> - ❌ 컬럼 설정 (해당 테이블의 컬럼에 맞게 작성)
|
||||||
|
> - ❌ 필드명 (`fieldName`, `columnName` 등)
|
||||||
|
> - ❌ 화면명, screen_code, company_code
|
||||||
|
> - ❌ screen_id, targetScreenId (동적 생성되는 값)
|
||||||
|
>
|
||||||
|
> ### 🚨 컴포넌트 부족 시 필수 명시 사항
|
||||||
|
>
|
||||||
|
> 화면 분석 결과, **현재 V2 컴포넌트로 구현이 불가능한 기능**이 있을 경우:
|
||||||
|
>
|
||||||
|
> 1. 문서에 **"구현 불가 항목"** 섹션을 반드시 추가
|
||||||
|
> 2. 다음 형식으로 명시:
|
||||||
|
>
|
||||||
|
> ```markdown
|
||||||
|
> ## 🚫 구현 불가 항목 (컴포넌트 개발 필요)
|
||||||
|
>
|
||||||
|
> | 기능 | 필요한 컴포넌트 | 현재 상태 | 비고 |
|
||||||
|
> |------|-----------------|-----------|------|
|
||||||
|
> | 트리 구조 표시 | v2-tree-view | 미구현 | 계층형 데이터 표시 필요 |
|
||||||
|
> | 드래그 앤 드롭 | v2-drag-drop | 미구현 | 순서 변경 기능 |
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> 3. 컴포넌트 개발 **우선순위/중요도** 명시
|
||||||
|
|
||||||
## 1. 테이블 선택 및 화면 구조
|
## 1. 테이블 선택 및 화면 구조
|
||||||
|
|
||||||
### 1.1 사용 테이블
|
### 1.1 사용 테이블
|
||||||
|
|
@ -83,19 +130,49 @@
|
||||||
└─────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2.2 컴포넌트 목록
|
### 2.2 사용 가능한 V2 컴포넌트 목록
|
||||||
|
|
||||||
|
> 📌 **V2 컴포넌트 전체 목록** - 화면 구성 시 사용 가능한 컴포넌트
|
||||||
|
|
||||||
|
| 컴포넌트 ID | 설명 | 카테고리 |
|
||||||
|
|-------------|------|----------|
|
||||||
|
| `v2-input` | 텍스트, 숫자, 비밀번호, 이메일 등 입력 | 입력 |
|
||||||
|
| `v2-select` | 드롭다운, 콤보박스, 라디오, 체크박스 | 입력 |
|
||||||
|
| `v2-date` | 날짜/시간 입력 | 입력 |
|
||||||
|
| `v2-button-primary` | 버튼 | 액션 |
|
||||||
|
| `v2-table-list` | 테이블 리스트 (CRUD) | 테이블 |
|
||||||
|
| `v2-table-search-widget` | 테이블 검색/필터 위젯 | 유틸리티 |
|
||||||
|
| `v2-pivot-grid` | 피벗 그리드 (다차원 분석) | 테이블 |
|
||||||
|
| `v2-aggregation-widget` | 집계 위젯 | 위젯 |
|
||||||
|
| `v2-text-display` | 텍스트 표시 (읽기 전용) | 표시 |
|
||||||
|
| `v2-card-display` | 카드 표시 | 표시 |
|
||||||
|
| `v2-divider-line` | 구분선 | 레이아웃 |
|
||||||
|
| `v2-section-card` | 섹션 카드 (그룹핑) | 레이아웃 |
|
||||||
|
| `v2-section-paper` | 섹션 페이퍼 (그룹핑) | 레이아웃 |
|
||||||
|
| `v2-split-panel-layout` | 분할 패널 레이아웃 | 레이아웃 |
|
||||||
|
| `v2-repeat-container` | 반복 컨테이너 | 레이아웃 |
|
||||||
|
| `v2-repeater` | 리피터 (동적 행) | 레이아웃 |
|
||||||
|
| `v2-category-manager` | 카테고리 관리 | 특수 |
|
||||||
|
| `v2-numbering-rule` | 채번규칙 | 특수 |
|
||||||
|
| `v2-media` | 미디어 (이미지/영상) | 미디어 |
|
||||||
|
| `v2-rack-structure` | 랙 구조 (창고) | 특수 |
|
||||||
|
| `v2-location-swap-selector` | 위치 스왑 선택기 | 특수 |
|
||||||
|
|
||||||
|
### 2.3 이 화면에서 사용하는 컴포넌트
|
||||||
|
|
||||||
| 컴포넌트 타입 | 역할 |
|
| 컴포넌트 타입 | 역할 |
|
||||||
|---------------|------|
|
|---------------|------|
|
||||||
| v2-table-search-widget | 검색 필터 |
|
| `v2-table-search-widget` | 검색 필터 |
|
||||||
| v2-table-list | 품목 데이터 테이블 |
|
| `v2-table-list` | 품목 데이터 테이블 |
|
||||||
| v2-button-primary | 코드변경 |
|
| `v2-button-primary` | 코드변경 |
|
||||||
| v2-button-primary | 업로드 (엑셀) |
|
| `v2-button-primary` | 업로드 (엑셀) |
|
||||||
| v2-button-primary | 다운로드 (엑셀) |
|
| `v2-button-primary` | 다운로드 (엑셀) |
|
||||||
| v2-button-primary | 등록 (모달 열기) |
|
| `v2-button-primary` | 등록 (모달 열기) |
|
||||||
| v2-button-primary | 복사 (모달 열기) |
|
| `v2-button-primary` | 복사 (모달 열기) |
|
||||||
| v2-button-primary | 수정 (모달 열기) |
|
| `v2-button-primary` | 수정 (모달 열기) |
|
||||||
| v2-button-primary | 삭제 |
|
| `v2-button-primary` | 삭제 |
|
||||||
|
| `v2-input` | 모달 - 텍스트 입력 필드 |
|
||||||
|
| `v2-select` | 모달 - 선택 필드 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -519,6 +596,14 @@ v2-table-search-widget ──── TableOptionsContext ──── v2-table-li
|
||||||
> 📌 실제 화면 저장은 `screen_definitions` + `screen_layouts_v2` 테이블을 사용합니다.
|
> 📌 실제 화면 저장은 `screen_definitions` + `screen_layouts_v2` 테이블을 사용합니다.
|
||||||
> `screen_layouts_v2`는 전체 레이아웃을 하나의 JSON (`layout_data`)으로 저장합니다.
|
> `screen_layouts_v2`는 전체 레이아웃을 하나의 JSON (`layout_data`)으로 저장합니다.
|
||||||
|
|
||||||
|
> ⚠️ **주의: 아래 JSON은 "품목정보" 화면 전용 예시입니다!**
|
||||||
|
>
|
||||||
|
> 다른 화면 구현 시:
|
||||||
|
> 1. **테이블 분석 필수** - 해당 화면이 사용하는 테이블 구조 파악
|
||||||
|
> 2. **컬럼 재정의** - `columns`, `fieldName` 등을 해당 테이블에 맞게 작성
|
||||||
|
> 3. **기능 요구사항 반영** - 버튼, 모달, 액션 등을 화면 요구사항에 맞게 구성
|
||||||
|
> 4. **ID 값 동적 처리** - `screen_id`, `targetScreenId`는 생성 시 할당되는 값 사용
|
||||||
|
|
||||||
### 8.1 테이블 구조
|
### 8.1 테이블 구조
|
||||||
|
|
||||||
#### screen_definitions
|
#### screen_definitions
|
||||||
|
|
@ -635,7 +720,7 @@ v2-table-search-widget ──── TableOptionsContext ──── v2-table-li
|
||||||
"webTypeConfig": {},
|
"webTypeConfig": {},
|
||||||
"horizontalScroll": { "enabled": true, "maxColumnWidth": 300, "minColumnWidth": 100, "maxVisibleColumns": 8 }
|
"horizontalScroll": { "enabled": true, "maxColumnWidth": 300, "minColumnWidth": 100, "maxVisibleColumns": 8 }
|
||||||
},
|
},
|
||||||
"displayOrder": 0
|
"displayOrder": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "comp_btn_code_merge",
|
"id": "comp_btn_code_merge",
|
||||||
|
|
@ -654,16 +739,9 @@ v2-table-search-widget ──── TableOptionsContext ──── v2-table-li
|
||||||
},
|
},
|
||||||
"variant": "primary",
|
"variant": "primary",
|
||||||
"actionType": "button",
|
"actionType": "button",
|
||||||
"webTypeConfig": {
|
"webTypeConfig": { "variant": "default", "actionType": "custom" }
|
||||||
"variant": "default",
|
|
||||||
"actionType": "custom",
|
|
||||||
"dataflowConfig": {
|
|
||||||
"flowConfig": { "flowId": 18, "flowName": "품번코드 통합", "contextData": {}, "executionTiming": "after" },
|
|
||||||
"selectedDiagramId": 18
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"displayOrder": 0
|
"displayOrder": 2
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "comp_btn_upload",
|
"id": "comp_btn_upload",
|
||||||
|
|
@ -676,14 +754,14 @@ v2-table-search-widget ──── TableOptionsContext ──── v2-table-li
|
||||||
"label": "기본 버튼",
|
"label": "기본 버튼",
|
||||||
"action": {
|
"action": {
|
||||||
"type": "excel_upload",
|
"type": "excel_upload",
|
||||||
"errorMessage": "저장 중 오류가 발생했습니다.",
|
"errorMessage": "업로드 중 오류가 발생했습니다.",
|
||||||
"successMessage": "저장되었습니다."
|
"successMessage": "업로드되었습니다."
|
||||||
},
|
},
|
||||||
"variant": "primary",
|
"variant": "primary",
|
||||||
"actionType": "button",
|
"actionType": "button",
|
||||||
"webTypeConfig": { "variant": "default", "actionType": "custom" }
|
"webTypeConfig": { "variant": "default", "actionType": "custom" }
|
||||||
},
|
},
|
||||||
"displayOrder": 0
|
"displayOrder": 3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "comp_btn_download",
|
"id": "comp_btn_download",
|
||||||
|
|
@ -696,14 +774,14 @@ v2-table-search-widget ──── TableOptionsContext ──── v2-table-li
|
||||||
"label": "기본 버튼",
|
"label": "기본 버튼",
|
||||||
"action": {
|
"action": {
|
||||||
"type": "excel_download",
|
"type": "excel_download",
|
||||||
"errorMessage": "저장 중 오류가 발생했습니다.",
|
"errorMessage": "다운로드 중 오류가 발생했습니다.",
|
||||||
"successMessage": "저장되었습니다."
|
"successMessage": "다운로드되었습니다."
|
||||||
},
|
},
|
||||||
"variant": "primary",
|
"variant": "primary",
|
||||||
"actionType": "button",
|
"actionType": "button",
|
||||||
"webTypeConfig": { "variant": "default", "actionType": "custom" }
|
"webTypeConfig": { "variant": "default", "actionType": "custom" }
|
||||||
},
|
},
|
||||||
"displayOrder": 0
|
"displayOrder": 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "comp_btn_register",
|
"id": "comp_btn_register",
|
||||||
|
|
@ -716,17 +794,17 @@ v2-table-search-widget ──── TableOptionsContext ──── v2-table-li
|
||||||
"label": "기본 버튼",
|
"label": "기본 버튼",
|
||||||
"action": {
|
"action": {
|
||||||
"type": "modal",
|
"type": "modal",
|
||||||
"modalSize": "md",
|
"modalSize": "lg",
|
||||||
"modalTitle": "품목 등록",
|
"modalTitle": "품목 등록",
|
||||||
|
"targetScreenId": {{modal_screen_id}},
|
||||||
"errorMessage": "저장 중 오류가 발생했습니다.",
|
"errorMessage": "저장 중 오류가 발생했습니다.",
|
||||||
"successMessage": "저장되었습니다.",
|
"successMessage": "저장되었습니다."
|
||||||
"targetScreenId": "{{modal_screen_id}}"
|
|
||||||
},
|
},
|
||||||
"variant": "primary",
|
"variant": "primary",
|
||||||
"actionType": "button",
|
"actionType": "button",
|
||||||
"webTypeConfig": { "variant": "default", "actionType": "custom" }
|
"webTypeConfig": { "variant": "default", "actionType": "custom" }
|
||||||
},
|
},
|
||||||
"displayOrder": 0
|
"displayOrder": 5
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "comp_btn_copy",
|
"id": "comp_btn_copy",
|
||||||
|
|
@ -739,15 +817,17 @@ v2-table-search-widget ──── TableOptionsContext ──── v2-table-li
|
||||||
"label": "기본 버튼",
|
"label": "기본 버튼",
|
||||||
"action": {
|
"action": {
|
||||||
"type": "copy",
|
"type": "copy",
|
||||||
"errorMessage": "저장 중 오류가 발생했습니다.",
|
"modalSize": "lg",
|
||||||
"successMessage": "저장되었습니다.",
|
"modalTitle": "품목 복사",
|
||||||
"targetScreenId": "{{modal_screen_id}}"
|
"targetScreenId": {{modal_screen_id}},
|
||||||
|
"errorMessage": "복사 중 오류가 발생했습니다.",
|
||||||
|
"successMessage": "복사되었습니다."
|
||||||
},
|
},
|
||||||
"variant": "primary",
|
"variant": "primary",
|
||||||
"actionType": "button",
|
"actionType": "button",
|
||||||
"webTypeConfig": { "variant": "default", "actionType": "custom" }
|
"webTypeConfig": { "variant": "default", "actionType": "custom" }
|
||||||
},
|
},
|
||||||
"displayOrder": 0
|
"displayOrder": 6
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "comp_btn_edit",
|
"id": "comp_btn_edit",
|
||||||
|
|
@ -760,15 +840,17 @@ v2-table-search-widget ──── TableOptionsContext ──── v2-table-li
|
||||||
"label": "기본 버튼",
|
"label": "기본 버튼",
|
||||||
"action": {
|
"action": {
|
||||||
"type": "edit",
|
"type": "edit",
|
||||||
"errorMessage": "저장 중 오류가 발생했습니다.",
|
"modalSize": "lg",
|
||||||
"successMessage": "저장되었습니다.",
|
"modalTitle": "품목 수정",
|
||||||
"targetScreenId": "{{modal_screen_id}}"
|
"targetScreenId": {{modal_screen_id}},
|
||||||
|
"errorMessage": "수정 중 오류가 발생했습니다.",
|
||||||
|
"successMessage": "수정되었습니다."
|
||||||
},
|
},
|
||||||
"variant": "primary",
|
"variant": "primary",
|
||||||
"actionType": "button",
|
"actionType": "button",
|
||||||
"webTypeConfig": { "variant": "default", "actionType": "custom" }
|
"webTypeConfig": { "variant": "default", "actionType": "custom" }
|
||||||
},
|
},
|
||||||
"displayOrder": 0
|
"displayOrder": 7
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "comp_btn_delete",
|
"id": "comp_btn_delete",
|
||||||
|
|
@ -781,14 +863,14 @@ v2-table-search-widget ──── TableOptionsContext ──── v2-table-li
|
||||||
"label": "기본 버튼",
|
"label": "기본 버튼",
|
||||||
"action": {
|
"action": {
|
||||||
"type": "delete",
|
"type": "delete",
|
||||||
"errorMessage": "저장 중 오류가 발생했습니다.",
|
"errorMessage": "삭제 중 오류가 발생했습니다.",
|
||||||
"successMessage": "저장되었습니다."
|
"successMessage": "삭제되었습니다."
|
||||||
},
|
},
|
||||||
"variant": "primary",
|
"variant": "danger",
|
||||||
"actionType": "button",
|
"actionType": "button",
|
||||||
"webTypeConfig": { "variant": "default", "actionType": "custom" }
|
"webTypeConfig": { "variant": "default", "actionType": "custom" }
|
||||||
},
|
},
|
||||||
"displayOrder": 0
|
"displayOrder": 8
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -809,17 +891,19 @@ v2-table-search-widget ──── TableOptionsContext ──── v2-table-li
|
||||||
|
|
||||||
#### 레이아웃 데이터 (screen_layouts_v2.layout_data)
|
#### 레이아웃 데이터 (screen_layouts_v2.layout_data)
|
||||||
|
|
||||||
|
> 📌 **실제 적용된 레이아웃** - 품목 등록/수정 폼 (모달용)
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"version": "2.0",
|
"version": "2.0",
|
||||||
"components": [
|
"components": [
|
||||||
{
|
{
|
||||||
"id": "comp_item_number",
|
"id": "comp_item_number",
|
||||||
"url": "@/lib/registry/components/v2-text-input",
|
"url": "@/lib/registry/components/v2-input",
|
||||||
"size": { "width": 300, "height": 60 },
|
"size": { "width": 300, "height": 60 },
|
||||||
"position": { "x": 20, "y": 20, "z": 1 },
|
"position": { "x": 20, "y": 20, "z": 1 },
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"type": "v2-text-input",
|
"type": "v2-input",
|
||||||
"label": "품번코드",
|
"label": "품번코드",
|
||||||
"fieldName": "item_number",
|
"fieldName": "item_number",
|
||||||
"placeholder": "품번코드를 입력하세요",
|
"placeholder": "품번코드를 입력하세요",
|
||||||
|
|
@ -829,11 +913,11 @@ v2-table-search-widget ──── TableOptionsContext ──── v2-table-li
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "comp_item_name",
|
"id": "comp_item_name",
|
||||||
"url": "@/lib/registry/components/v2-text-input",
|
"url": "@/lib/registry/components/v2-input",
|
||||||
"size": { "width": 300, "height": 60 },
|
"size": { "width": 300, "height": 60 },
|
||||||
"position": { "x": 340, "y": 20, "z": 1 },
|
"position": { "x": 340, "y": 20, "z": 1 },
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"type": "v2-text-input",
|
"type": "v2-input",
|
||||||
"label": "품명",
|
"label": "품명",
|
||||||
"fieldName": "item_name",
|
"fieldName": "item_name",
|
||||||
"placeholder": "품명을 입력하세요",
|
"placeholder": "품명을 입력하세요",
|
||||||
|
|
@ -842,23 +926,123 @@ v2-table-search-widget ──── TableOptionsContext ──── v2-table-li
|
||||||
"displayOrder": 1
|
"displayOrder": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "comp_status",
|
"id": "comp_size",
|
||||||
"url": "@/lib/registry/components/v2-select-basic",
|
"url": "@/lib/registry/components/v2-input",
|
||||||
"size": { "width": 300, "height": 60 },
|
"size": { "width": 300, "height": 60 },
|
||||||
"position": { "x": 20, "y": 100, "z": 1 },
|
"position": { "x": 20, "y": 100, "z": 1 },
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"type": "v2-select-basic",
|
"type": "v2-input",
|
||||||
"label": "상태",
|
"label": "규격",
|
||||||
"fieldName": "status",
|
"fieldName": "size",
|
||||||
"options": ["정상", "품절", "대기", "단종"]
|
"placeholder": "규격을 입력하세요"
|
||||||
},
|
},
|
||||||
"displayOrder": 2
|
"displayOrder": 2
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "comp_material",
|
||||||
|
"url": "@/lib/registry/components/v2-input",
|
||||||
|
"size": { "width": 300, "height": 60 },
|
||||||
|
"position": { "x": 340, "y": 100, "z": 1 },
|
||||||
|
"overrides": {
|
||||||
|
"type": "v2-input",
|
||||||
|
"label": "재질",
|
||||||
|
"fieldName": "material",
|
||||||
|
"placeholder": "재질을 입력하세요"
|
||||||
|
},
|
||||||
|
"displayOrder": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "comp_inventory_unit",
|
||||||
|
"url": "@/lib/registry/components/v2-input",
|
||||||
|
"size": { "width": 300, "height": 60 },
|
||||||
|
"position": { "x": 20, "y": 180, "z": 1 },
|
||||||
|
"overrides": {
|
||||||
|
"type": "v2-input",
|
||||||
|
"label": "재고단위",
|
||||||
|
"fieldName": "inventory_unit",
|
||||||
|
"placeholder": "재고단위를 입력하세요"
|
||||||
|
},
|
||||||
|
"displayOrder": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "comp_weight",
|
||||||
|
"url": "@/lib/registry/components/v2-input",
|
||||||
|
"size": { "width": 300, "height": 60 },
|
||||||
|
"position": { "x": 340, "y": 180, "z": 1 },
|
||||||
|
"overrides": {
|
||||||
|
"type": "v2-input",
|
||||||
|
"label": "중량",
|
||||||
|
"fieldName": "weight",
|
||||||
|
"placeholder": "중량을 입력하세요"
|
||||||
|
},
|
||||||
|
"displayOrder": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "comp_unit",
|
||||||
|
"url": "@/lib/registry/components/v2-input",
|
||||||
|
"size": { "width": 300, "height": 60 },
|
||||||
|
"position": { "x": 20, "y": 260, "z": 1 },
|
||||||
|
"overrides": {
|
||||||
|
"type": "v2-input",
|
||||||
|
"label": "단위",
|
||||||
|
"fieldName": "unit",
|
||||||
|
"placeholder": "단위를 입력하세요"
|
||||||
|
},
|
||||||
|
"displayOrder": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "comp_division",
|
||||||
|
"url": "@/lib/registry/components/v2-input",
|
||||||
|
"size": { "width": 300, "height": 60 },
|
||||||
|
"position": { "x": 340, "y": 260, "z": 1 },
|
||||||
|
"overrides": {
|
||||||
|
"type": "v2-input",
|
||||||
|
"label": "구분",
|
||||||
|
"fieldName": "division",
|
||||||
|
"placeholder": "구분을 입력하세요"
|
||||||
|
},
|
||||||
|
"displayOrder": 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "comp_type",
|
||||||
|
"url": "@/lib/registry/components/v2-input",
|
||||||
|
"size": { "width": 300, "height": 60 },
|
||||||
|
"position": { "x": 20, "y": 340, "z": 1 },
|
||||||
|
"overrides": {
|
||||||
|
"type": "v2-input",
|
||||||
|
"label": "유형",
|
||||||
|
"fieldName": "type",
|
||||||
|
"placeholder": "유형을 입력하세요"
|
||||||
|
},
|
||||||
|
"displayOrder": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "comp_status",
|
||||||
|
"url": "@/lib/registry/components/v2-select",
|
||||||
|
"size": { "width": 300, "height": 60 },
|
||||||
|
"position": { "x": 340, "y": 340, "z": 1 },
|
||||||
|
"overrides": {
|
||||||
|
"type": "v2-select",
|
||||||
|
"label": "상태",
|
||||||
|
"fieldName": "status",
|
||||||
|
"config": {
|
||||||
|
"mode": "dropdown",
|
||||||
|
"source": "static",
|
||||||
|
"options": [
|
||||||
|
{ "value": "정상", "label": "정상" },
|
||||||
|
{ "value": "품절", "label": "품절" },
|
||||||
|
{ "value": "대기", "label": "대기" },
|
||||||
|
{ "value": "단종", "label": "단종" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"displayOrder": 9
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "comp_btn_save",
|
"id": "comp_btn_save",
|
||||||
"url": "@/lib/registry/components/v2-button-primary",
|
"url": "@/lib/registry/components/v2-button-primary",
|
||||||
"size": { "width": 80, "height": 40 },
|
"size": { "width": 100, "height": 40 },
|
||||||
"position": { "x": 400, "y": 500, "z": 1 },
|
"position": { "x": 540, "y": 420, "z": 1 },
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"text": "저장",
|
"text": "저장",
|
||||||
"type": "v2-button-primary",
|
"type": "v2-button-primary",
|
||||||
|
|
@ -873,7 +1057,7 @@ v2-table-search-widget ──── TableOptionsContext ──── v2-table-li
|
||||||
"variant": "primary",
|
"variant": "primary",
|
||||||
"actionType": "button"
|
"actionType": "button"
|
||||||
},
|
},
|
||||||
"displayOrder": 20
|
"displayOrder": 10
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -940,35 +1124,175 @@ Authorization: Bearer {{token}}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 8.5 SQL 직접 INSERT (참고용)
|
### 8.5 SQL 직접 INSERT (실제 적용 방식)
|
||||||
|
|
||||||
> ⚠️ 일반적으로 API를 사용하지만, 대량 마이그레이션 시 직접 SQL 사용 가능
|
> 📌 **실제 테스트 완료된 방식**입니다. Docker psql을 통해 직접 DB에 삽입합니다.
|
||||||
|
|
||||||
|
#### Step 1: 모달 화면 먼저 생성 (등록/수정 폼)
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
-- Step 1: 화면 정의 (screen_code는 수동 지정 필요)
|
-- 모달 화면 정의
|
||||||
INSERT INTO screen_definitions (
|
INSERT INTO screen_definitions (
|
||||||
screen_name, screen_code, table_name, company_code, description
|
screen_code, screen_name, table_name, company_code, description, is_active
|
||||||
) VALUES (
|
) VALUES (
|
||||||
'품목정보', 'COMPANY_7_4', 'item_info', 'COMPANY_7', '품목 기본정보 관리 화면'
|
'COMPANY_19_ITEM_MODAL', 'Item Register/Edit Modal', 'item_info', 'COMPANY_19',
|
||||||
|
'Item registration and edit form modal', 'Y'
|
||||||
) RETURNING screen_id;
|
) RETURNING screen_id;
|
||||||
|
-- 예: screen_id = 3731 반환됨
|
||||||
|
```
|
||||||
|
|
||||||
-- Step 2: 레이아웃 저장 (screen_id 사용)
|
#### Step 2: 모달 레이아웃 저장
|
||||||
INSERT INTO screen_layouts_v2 (screen_id, company_code, layout_data)
|
|
||||||
|
```sql
|
||||||
|
-- 레이아웃 JSON을 파일로 저장 후 INSERT (한글 인코딩 문제 방지)
|
||||||
|
INSERT INTO screen_layouts_v2 (screen_id, company_code, layout_data, created_at, updated_at)
|
||||||
VALUES (
|
VALUES (
|
||||||
141, -- 위에서 반환된 screen_id
|
3731, -- Step 1에서 반환된 screen_id
|
||||||
'COMPANY_7',
|
'COMPANY_19',
|
||||||
'{"version": "2.0", "components": [...]}'::jsonb
|
'{"version":"2.0","components":[/* 8.3의 모달 components 배열 */]}'::jsonb,
|
||||||
|
NOW(), NOW()
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
### 8.6 주의사항
|
#### Step 3: 메인 화면 생성
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- 메인 화면 정의
|
||||||
|
INSERT INTO screen_definitions (
|
||||||
|
screen_code, screen_name, table_name, company_code, description, is_active
|
||||||
|
) VALUES (
|
||||||
|
'COMPANY_19_ITEM_INFO', 'Item Info', 'item_info', 'COMPANY_19',
|
||||||
|
'Item master data management', 'Y'
|
||||||
|
) RETURNING screen_id;
|
||||||
|
-- 예: screen_id = 3730 반환됨
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 4: 메인 레이아웃 저장 (모달 연결)
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- targetScreenId를 Step 1에서 생성한 모달 screen_id로 치환
|
||||||
|
INSERT INTO screen_layouts_v2 (screen_id, company_code, layout_data, created_at, updated_at)
|
||||||
|
VALUES (
|
||||||
|
3730, -- Step 3에서 반환된 screen_id
|
||||||
|
'COMPANY_19',
|
||||||
|
'{"version":"2.0","components":[/* 8.2의 components 배열, targetScreenId: 3731 */]}'::jsonb,
|
||||||
|
NOW(), NOW()
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 5: 메뉴에 화면 연결 (선택사항)
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- 기존 메뉴에 화면 연결 (screen_menu_assignments 테이블 사용)
|
||||||
|
INSERT INTO screen_menu_assignments (screen_id, menu_id, company_code, display_order)
|
||||||
|
VALUES (3730, 55566, 'COMPANY_19', 1);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.6 화면 생성 순서 (중요!)
|
||||||
|
|
||||||
|
```
|
||||||
|
1. 모달 화면 생성 (screen_definitions INSERT)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
2. 모달 레이아웃 저장 (screen_layouts_v2 INSERT)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
3. 메인 화면 생성 (screen_definitions INSERT)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
4. 메인 레이아웃 저장 (screen_layouts_v2 INSERT)
|
||||||
|
└── targetScreenId에 모달 screen_id 사용!
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
5. (선택) 메뉴에 화면 연결
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.7 주의사항
|
||||||
|
|
||||||
| 항목 | 설명 |
|
| 항목 | 설명 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| `screen_code` | API 사용 시 `generateScreenCode` 먼저 호출, 형식: `{company_code}_{순번}` |
|
| `screen_code` | 회사별 고유, 형식: `{COMPANY_CODE}_{용도}` (예: `COMPANY_19_ITEM_INFO`) |
|
||||||
| `screen_id` | 화면 생성 후 반환되는 값, 레이아웃 저장 시 필요 |
|
| `screen_id` | AUTO INCREMENT, INSERT 후 RETURNING으로 획득 |
|
||||||
| `component.id` | 고유 ID (UUID 또는 `comp_` prefix), 중복 불가 |
|
| `component.id` | `comp_` prefix 권장, 화면 내 중복 불가 |
|
||||||
| `component.url` | `@/lib/registry/components/v2-xxx` 형식 |
|
| `component.url` | `@/lib/registry/components/v2-xxx` 형식 정확히 사용 |
|
||||||
| `{{modal_screen_id}}` | 모달 화면 먼저 생성 후 실제 ID로 치환 |
|
| `component.type` | `overrides.type`과 URL 마지막 부분 일치 필요 |
|
||||||
|
| `targetScreenId` | **숫자** (문자열 아님), 모달 화면 먼저 생성 필요 |
|
||||||
| `version` | 반드시 `"2.0"` 사용 |
|
| `version` | 반드시 `"2.0"` 사용 |
|
||||||
| UNIQUE 제약 | `screen_layouts_v2`는 `(screen_id, company_code)` 조합이 유니크 |
|
| `layout_data` | JSONB 타입, 복잡한 JSON은 파일로 저장 후 `-f` 옵션으로 실행 |
|
||||||
|
| UNIQUE 제약 | `(screen_id, company_code)` 조합이 유니크 |
|
||||||
|
| 한글 처리 | Docker psql에서 한글 직접 입력 시 인코딩 문제 → 영문 사용 또는 파일 사용 |
|
||||||
|
|
||||||
|
### 8.8 컴포넌트 타입 레퍼런스
|
||||||
|
|
||||||
|
| 컴포넌트 | URL | type (overrides) |
|
||||||
|
|----------|-----|------------------|
|
||||||
|
| 텍스트 입력 | `v2-input` | `v2-input` |
|
||||||
|
| 선택 (드롭다운) | `v2-select` | `v2-select` |
|
||||||
|
| 날짜 입력 | `v2-date` | `v2-date` |
|
||||||
|
| 버튼 | `v2-button-primary` | `v2-button-primary` |
|
||||||
|
| 테이블 리스트 | `v2-table-list` | `v2-table-list` |
|
||||||
|
| 검색 위젯 | `v2-table-search-widget` | `v2-table-search-widget` |
|
||||||
|
| 텍스트 표시 | `v2-text-display` | `v2-text-display` |
|
||||||
|
| 구분선 | `v2-divider-line` | `v2-divider-line` |
|
||||||
|
| 섹션 카드 | `v2-section-card` | `v2-section-card` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 화면 구현 체크리스트
|
||||||
|
|
||||||
|
> 📋 새로운 화면을 구현할 때 아래 체크리스트를 순서대로 확인하세요.
|
||||||
|
|
||||||
|
### 9.1 분석 단계
|
||||||
|
|
||||||
|
| 체크 | 항목 | 설명 |
|
||||||
|
|:----:|------|------|
|
||||||
|
| ☐ | **테이블 구조 분석** | 해당 화면이 사용할 테이블 스키마 확인 (컬럼명, 타입, 필수 여부) |
|
||||||
|
| ☐ | **화면 기능 파악** | 조회/등록/수정/삭제, 검색, 필터, 그룹핑 등 필요 기능 목록화 |
|
||||||
|
| ☐ | **컴포넌트 매핑** | 필요 기능 → V2 컴포넌트 매핑 (2.2 목록 참조) |
|
||||||
|
| ☐ | **구현 불가 항목 확인** | 현재 V2 컴포넌트로 구현 불가능한 기능 파악 |
|
||||||
|
| ☐ | **대체 방안 검토** | 구현 불가 항목에 대해 기존 컴포넌트 조합으로 대체 가능 여부 확인 |
|
||||||
|
|
||||||
|
### 9.2 문서 작성 단계
|
||||||
|
|
||||||
|
| 체크 | 항목 | 설명 |
|
||||||
|
|:----:|------|------|
|
||||||
|
| ☐ | **테이블 정의 작성** | 1.1~1.2 형식으로 테이블/컬럼 정보 작성 |
|
||||||
|
| ☐ | **레이아웃 배치도 작성** | 2.1 형식으로 ASCII 다이어그램 작성 |
|
||||||
|
| ☐ | **사용 컴포넌트 목록** | 2.3 형식으로 이 화면에서 사용할 컴포넌트 정리 |
|
||||||
|
| ☐ | **모달 화면 정의** | 등록/수정 모달이 필요하면 별도 레이아웃 작성 |
|
||||||
|
| ☐ | **JSON 설정 작성** | 8.2~8.3 형식으로 layout_data JSON 작성 |
|
||||||
|
| ☐ | **구현 불가/대체 방안 명시** | 해당 사항 있으면 문서에 섹션 추가 |
|
||||||
|
|
||||||
|
### 9.3 INSERT 전 확인
|
||||||
|
|
||||||
|
| 체크 | 항목 | 설명 |
|
||||||
|
|:----:|------|------|
|
||||||
|
| ☐ | **company_code 확인** | 대상 회사 코드 정확한지 확인 |
|
||||||
|
| ☐ | **screen_code 형식** | `{COMPANY_CODE}_{용도}` 형식 준수 |
|
||||||
|
| ☐ | **모달 먼저 생성** | 모달 화면이 있으면 반드시 먼저 INSERT |
|
||||||
|
| ☐ | **JSON 파일 준비** | 복잡한 JSON은 파일로 저장 (한글 인코딩 대비) |
|
||||||
|
| ☐ | **컴포넌트 ID 고유성** | `comp_` prefix, 화면 내 중복 없는지 확인 |
|
||||||
|
| ☐ | **컴포넌트 URL/type 일치** | `url`의 마지막 부분과 `overrides.type` 동일한지 확인 |
|
||||||
|
| ☐ | **targetScreenId 치환** | 모달 screen_id를 숫자로 정확히 입력 |
|
||||||
|
|
||||||
|
### 9.4 INSERT 후 검증
|
||||||
|
|
||||||
|
| 체크 | 항목 | 설명 |
|
||||||
|
|:----:|------|------|
|
||||||
|
| ☐ | **화면 접속 테스트** | `/screens/{screen_id}` URL로 접속 |
|
||||||
|
| ☐ | **컴포넌트 렌더링 확인** | 모든 컴포넌트가 "미구현" 없이 표시되는지 확인 |
|
||||||
|
| ☐ | **검색 기능 테스트** | 검색 위젯 동작 확인 |
|
||||||
|
| ☐ | **테이블 데이터 로드** | 테이블에 데이터 표시되는지 확인 |
|
||||||
|
| ☐ | **버튼 동작 테스트** | 등록/수정/삭제 버튼 클릭 시 모달/액션 동작 확인 |
|
||||||
|
| ☐ | **모달 폼 테스트** | 모달 열림, 입력 필드 표시, 저장 동작 확인 |
|
||||||
|
| ☐ | **메뉴 연결 확인** | (연결한 경우) 메뉴에서 화면 접근 가능한지 확인 |
|
||||||
|
|
||||||
|
### 9.5 문제 발생 시 확인 사항
|
||||||
|
|
||||||
|
| 증상 | 확인 사항 |
|
||||||
|
|------|-----------|
|
||||||
|
| 화면이 안 보임 | `screen_layouts_v2`에 데이터 있는지 확인, `company_code` 일치 여부 |
|
||||||
|
| "미구현 컴포넌트" 표시 | `url`과 `overrides.type` 일치 여부, 컴포넌트명 오타 확인 |
|
||||||
|
| 모달이 안 열림 | `targetScreenId`가 숫자인지, 해당 screen_id 존재하는지 확인 |
|
||||||
|
| 테이블 데이터 없음 | `selectedTable` 값 확인, 테이블에 데이터 존재 여부 |
|
||||||
|
| 버튼 동작 안 함 | `action.type` 값 확인, `actionType: "button"` 설정 여부 |
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue