feat: 수정 모달 자동 닫기 및 테이블 새로고침 기능 구현
- EditModal: 저장 완료 후 자동으로 닫히고 부모 테이블 새로고침 - buttonActions.ts: 저장 성공 후 closeEditModal 이벤트 발생 - InteractiveScreenViewerDynamic: onSave prop 추가하여 EditModal 연동 - InteractiveDataTable: EditModal 열 때 onSave 콜백으로 loadData 전달 - 두 가지 시나리오 모두 지원: 1. InteractiveScreenViewerDynamic 버튼의 onSave 호출 2. DynamicComponentRenderer 버튼의 buttonActions.ts 처리
This commit is contained in:
parent
aef62454c2
commit
8e9daf5b22
|
|
@ -102,13 +102,6 @@ export const EditModal: React.FC<EditModalProps> = ({ className }) => {
|
|||
useEffect(() => {
|
||||
const handleOpenEditModal = (event: CustomEvent) => {
|
||||
const { screenId, title, description, modalSize, editData, onSave } = event.detail;
|
||||
console.log("🚀 EditModal 열기 이벤트 수신:", {
|
||||
screenId,
|
||||
title,
|
||||
description,
|
||||
modalSize,
|
||||
editData,
|
||||
});
|
||||
|
||||
setModalState({
|
||||
isOpen: true,
|
||||
|
|
@ -126,7 +119,16 @@ export const EditModal: React.FC<EditModalProps> = ({ className }) => {
|
|||
};
|
||||
|
||||
const handleCloseEditModal = () => {
|
||||
console.log("🚪 EditModal 닫기 이벤트 수신");
|
||||
// 부모 컴포넌트의 onSave 콜백 실행 (테이블 새로고침)
|
||||
if (modalState.onSave) {
|
||||
try {
|
||||
modalState.onSave();
|
||||
} catch (callbackError) {
|
||||
console.error("⚠️ onSave 콜백 에러:", callbackError);
|
||||
}
|
||||
}
|
||||
|
||||
// 모달 닫기
|
||||
handleClose();
|
||||
};
|
||||
|
||||
|
|
@ -137,7 +139,7 @@ export const EditModal: React.FC<EditModalProps> = ({ className }) => {
|
|||
window.removeEventListener("openEditModal", handleOpenEditModal as EventListener);
|
||||
window.removeEventListener("closeEditModal", handleCloseEditModal);
|
||||
};
|
||||
}, []);
|
||||
}, [modalState.onSave]); // modalState.onSave를 의존성에 추가하여 최신 콜백 참조
|
||||
|
||||
// 화면 데이터 로딩
|
||||
useEffect(() => {
|
||||
|
|
@ -211,12 +213,6 @@ export const EditModal: React.FC<EditModalProps> = ({ className }) => {
|
|||
}
|
||||
|
||||
try {
|
||||
console.log("💾 수정 저장 시작:", {
|
||||
tableName: screenData.screenInfo.tableName,
|
||||
formData,
|
||||
originalData,
|
||||
});
|
||||
|
||||
// 변경된 필드만 추출
|
||||
const changedData: Record<string, any> = {};
|
||||
Object.keys(formData).forEach((key) => {
|
||||
|
|
@ -225,26 +221,33 @@ export const EditModal: React.FC<EditModalProps> = ({ className }) => {
|
|||
}
|
||||
});
|
||||
|
||||
console.log("📝 변경된 필드:", changedData);
|
||||
|
||||
if (Object.keys(changedData).length === 0) {
|
||||
toast.info("변경된 내용이 없습니다.");
|
||||
handleClose();
|
||||
return;
|
||||
}
|
||||
|
||||
// 기본키 확인 (id 또는 첫 번째 키)
|
||||
const recordId = originalData.id || Object.values(originalData)[0];
|
||||
|
||||
// UPDATE 액션 실행
|
||||
const response = await dynamicFormApi.updateData(screenData.screenInfo.tableName, {
|
||||
...originalData, // 원본 데이터 (WHERE 조건용)
|
||||
...changedData, // 변경된 데이터만
|
||||
});
|
||||
const response = await dynamicFormApi.updateFormDataPartial(
|
||||
recordId,
|
||||
originalData,
|
||||
changedData,
|
||||
screenData.screenInfo.tableName,
|
||||
);
|
||||
|
||||
if (response.success) {
|
||||
toast.success("데이터가 수정되었습니다.");
|
||||
|
||||
// 부모 컴포넌트의 onSave 콜백 실행
|
||||
// 부모 컴포넌트의 onSave 콜백 실행 (테이블 새로고침)
|
||||
if (modalState.onSave) {
|
||||
modalState.onSave();
|
||||
try {
|
||||
modalState.onSave();
|
||||
} catch (callbackError) {
|
||||
console.error("⚠️ onSave 콜백 에러:", callbackError);
|
||||
}
|
||||
}
|
||||
|
||||
handleClose();
|
||||
|
|
@ -335,16 +338,10 @@ export const EditModal: React.FC<EditModalProps> = ({ className }) => {
|
|||
allComponents={screenData.components}
|
||||
formData={formData}
|
||||
onFormDataChange={(fieldName, value) => {
|
||||
console.log(`🎯 EditModal onFormDataChange 호출: ${fieldName} = "${value}"`);
|
||||
console.log("📋 현재 formData:", formData);
|
||||
setFormData((prev) => {
|
||||
const newFormData = {
|
||||
...prev,
|
||||
[fieldName]: value,
|
||||
};
|
||||
console.log("📝 EditModal 업데이트된 formData:", newFormData);
|
||||
return newFormData;
|
||||
});
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
[fieldName]: value,
|
||||
}));
|
||||
}}
|
||||
screenInfo={{
|
||||
id: modalState.screenId!,
|
||||
|
|
|
|||
|
|
@ -769,7 +769,7 @@ export const InteractiveDataTable: React.FC<InteractiveDataTableProps> = ({
|
|||
setShowSaveModal(true);
|
||||
}, [getDisplayColumns, generateAutoValue, component.addModalConfig]);
|
||||
|
||||
// 데이터 수정 핸들러 (SaveModal 사용)
|
||||
// 데이터 수정 핸들러 (EditModal 사용)
|
||||
const handleEditData = useCallback(() => {
|
||||
if (selectedRows.size !== 1) return;
|
||||
|
||||
|
|
@ -793,17 +793,25 @@ export const InteractiveDataTable: React.FC<InteractiveDataTableProps> = ({
|
|||
initialData[col.columnName] = selectedRowData[col.columnName] || "";
|
||||
});
|
||||
|
||||
setEditFormData(initialData);
|
||||
setEditingRowData(selectedRowData);
|
||||
|
||||
// 수정 모달 설정에서 제목과 설명 가져오기
|
||||
const editModalTitle = component.editModalConfig?.title || "";
|
||||
const editModalTitle = component.editModalConfig?.title || "데이터 수정";
|
||||
const editModalDescription = component.editModalConfig?.description || "";
|
||||
|
||||
console.log("📝 수정 모달 설정:", { editModalTitle, editModalDescription });
|
||||
|
||||
setShowEditModal(true);
|
||||
}, [selectedRows, data, getDisplayColumns, component.editModalConfig]);
|
||||
// 전역 EditModal 열기 이벤트 발생
|
||||
const event = new CustomEvent("openEditModal", {
|
||||
detail: {
|
||||
screenId,
|
||||
title: editModalTitle,
|
||||
description: editModalDescription,
|
||||
modalSize: "lg",
|
||||
editData: initialData,
|
||||
onSave: () => {
|
||||
loadData(); // 테이블 데이터 새로고침
|
||||
},
|
||||
},
|
||||
});
|
||||
window.dispatchEvent(event);
|
||||
}, [selectedRows, data, getDisplayColumns, component.addModalConfig, component.editModalConfig, loadData]);
|
||||
|
||||
// 수정 폼 데이터 변경 핸들러
|
||||
const handleEditFormChange = useCallback((columnName: string, value: any) => {
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ interface InteractiveScreenViewerProps {
|
|||
id: number;
|
||||
tableName?: string;
|
||||
};
|
||||
onSave?: () => Promise<void>;
|
||||
}
|
||||
|
||||
export const InteractiveScreenViewerDynamic: React.FC<InteractiveScreenViewerProps> = ({
|
||||
|
|
@ -47,6 +48,7 @@ export const InteractiveScreenViewerDynamic: React.FC<InteractiveScreenViewerPro
|
|||
onFormDataChange,
|
||||
hideLabel = false,
|
||||
screenInfo,
|
||||
onSave,
|
||||
}) => {
|
||||
const { isPreviewMode } = useScreenPreview(); // 프리뷰 모드 확인
|
||||
const { userName, user } = useAuth();
|
||||
|
|
@ -204,8 +206,7 @@ export const InteractiveScreenViewerDynamic: React.FC<InteractiveScreenViewerPro
|
|||
// 테이블 컴포넌트는 자체적으로 loadData 호출
|
||||
}}
|
||||
onClose={() => {
|
||||
// 화면 닫기 로직 (필요시 구현)
|
||||
console.log("🚪 화면 닫기 요청");
|
||||
// buttonActions.ts가 이미 처리함
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
|
@ -299,6 +300,18 @@ export const InteractiveScreenViewerDynamic: React.FC<InteractiveScreenViewerPro
|
|||
|
||||
// 버튼 액션 핸들러들
|
||||
const handleSaveAction = async () => {
|
||||
// EditModal에서 전달된 onSave가 있으면 우선 사용 (수정 모달)
|
||||
if (onSave) {
|
||||
try {
|
||||
await onSave();
|
||||
} catch (error) {
|
||||
console.error("저장 오류:", error);
|
||||
toast.error("저장 중 오류가 발생했습니다.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 일반 저장 액션 (신규 생성)
|
||||
if (!screenInfo?.tableName) {
|
||||
toast.error("테이블명이 설정되지 않았습니다.");
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -381,19 +381,37 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
|
|||
|
||||
// 실행취소
|
||||
const undo = useCallback(() => {
|
||||
if (historyIndex > 0) {
|
||||
setHistoryIndex((prev) => prev - 1);
|
||||
setLayout(history[historyIndex - 1]);
|
||||
}
|
||||
}, [history, historyIndex]);
|
||||
setHistoryIndex((prevIndex) => {
|
||||
if (prevIndex > 0) {
|
||||
const newIndex = prevIndex - 1;
|
||||
setHistory((prevHistory) => {
|
||||
if (prevHistory[newIndex]) {
|
||||
setLayout(prevHistory[newIndex]);
|
||||
}
|
||||
return prevHistory;
|
||||
});
|
||||
return newIndex;
|
||||
}
|
||||
return prevIndex;
|
||||
});
|
||||
}, []);
|
||||
|
||||
// 다시실행
|
||||
const redo = useCallback(() => {
|
||||
if (historyIndex < history.length - 1) {
|
||||
setHistoryIndex((prev) => prev + 1);
|
||||
setLayout(history[historyIndex + 1]);
|
||||
}
|
||||
}, [history, historyIndex]);
|
||||
setHistoryIndex((prevIndex) => {
|
||||
let newIndex = prevIndex;
|
||||
setHistory((prevHistory) => {
|
||||
if (prevIndex < prevHistory.length - 1) {
|
||||
newIndex = prevIndex + 1;
|
||||
if (prevHistory[newIndex]) {
|
||||
setLayout(prevHistory[newIndex]);
|
||||
}
|
||||
}
|
||||
return prevHistory;
|
||||
});
|
||||
return newIndex;
|
||||
});
|
||||
}, []);
|
||||
|
||||
// 컴포넌트 속성 업데이트
|
||||
const updateComponentProperty = useCallback(
|
||||
|
|
|
|||
|
|
@ -234,9 +234,13 @@ export class ButtonActionExecutor {
|
|||
throw new Error("저장에 필요한 정보가 부족합니다. (테이블명 또는 화면ID 누락)");
|
||||
}
|
||||
|
||||
// 테이블과 플로우 모두 새로고침
|
||||
// 테이블과 플로우 새로고침 (모달 닫기 전에 실행)
|
||||
context.onRefresh?.();
|
||||
context.onFlowRefresh?.();
|
||||
|
||||
// 저장 성공 후 EditModal 닫기 이벤트 발생
|
||||
window.dispatchEvent(new CustomEvent("closeEditModal"));
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("저장 오류:", error);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,386 @@
|
|||
# 화면관리 및 테이블관리 시스템 개선사항 목록
|
||||
|
||||
## 문서 정보
|
||||
- **작성일**: 2025-11-03
|
||||
- **목적**: 사용자 피드백 기반 개선사항 정리
|
||||
- **우선순위**: 높음
|
||||
|
||||
---
|
||||
|
||||
## 1. 화면관리 (Screen Management) 개선사항
|
||||
|
||||
### 1.1 리스트 컬럼 Width 조절 기능
|
||||
**현재 문제**: 리스트 컬럼의 너비가 고정되어 있어 사용자가 조절할 수 없음
|
||||
|
||||
**요구사항**:
|
||||
- 사용자가 각 컬럼의 너비를 드래그로 조절할 수 있어야 함
|
||||
- 조절된 너비는 저장되어 다음 접속 시에도 유지되어야 함
|
||||
- 최소/최대 너비 제한 필요
|
||||
|
||||
**구현 방안**:
|
||||
- 컬럼 헤더에 리사이저 핸들 추가
|
||||
- `ComponentData` 인터페이스에 `columnWidths` 속성 추가
|
||||
- PropertiesPanel에서 개별 컬럼 너비 설정 UI 제공
|
||||
|
||||
**관련 파일**:
|
||||
- `frontend/components/screen/ScreenDesigner.tsx`
|
||||
- `frontend/components/screen/RealtimePreview.tsx`
|
||||
- `frontend/types/screen.ts`
|
||||
|
||||
---
|
||||
|
||||
### 1.2 되돌리기(Undo) 단축키 에러 수정
|
||||
**현재 문제**: 되돌리기 단축키(Ctrl+Z/Cmd+Z) 실행 시 에러 발생
|
||||
|
||||
**요구사항**:
|
||||
- 되돌리기 기능이 안정적으로 작동해야 함
|
||||
- 다시 실행(Redo) 기능도 함께 제공 (Ctrl+Y/Cmd+Shift+Z)
|
||||
|
||||
**구현 방안**:
|
||||
- 히스토리 스택 구현 (최대 50개 상태 저장)
|
||||
- `useUndo` 커스텀 훅 생성
|
||||
- 키보드 단축키 이벤트 리스너 추가
|
||||
|
||||
**관련 파일**:
|
||||
- `frontend/hooks/useUndo.ts` (신규 생성)
|
||||
- `frontend/components/screen/ScreenDesigner.tsx`
|
||||
|
||||
---
|
||||
|
||||
### 1.3 리스트 헤더 스타일 개선
|
||||
**현재 문제**: 리스트 헤더가 눈에 잘 띄지 않음
|
||||
|
||||
**요구사항**:
|
||||
- 헤더가 시각적으로 구분되어야 함
|
||||
- 배경색, 폰트 굵기, 테두리 등으로 강조
|
||||
|
||||
**구현 방안**:
|
||||
- 헤더 기본 스타일 변경:
|
||||
- 배경색: `bg-muted` → `bg-primary/10`
|
||||
- 폰트: `font-medium` → `font-semibold`
|
||||
- 하단 테두리: `border-b-2 border-primary`
|
||||
|
||||
**관련 파일**:
|
||||
- `frontend/components/screen/RealtimePreview.tsx`
|
||||
- `frontend/components/screen-viewer/InteractiveScreenViewer.tsx`
|
||||
|
||||
---
|
||||
|
||||
### 1.4 텍스트 줄바꿈 문제 방지
|
||||
**현재 문제**: 화면을 줄였을 때 텍스트가 2줄로 나뉘거나 깨지는 현상
|
||||
|
||||
**요구사항**:
|
||||
- 텍스트가 항상 1줄로 표시되어야 함
|
||||
- 긴 텍스트는 말줄임표(...) 처리
|
||||
|
||||
**구현 방안**:
|
||||
- 모든 텍스트 요소에 다음 클래스 적용:
|
||||
```tsx
|
||||
className="truncate whitespace-nowrap overflow-hidden"
|
||||
```
|
||||
- 툴팁으로 전체 텍스트 표시
|
||||
|
||||
**관련 파일**:
|
||||
- 모든 컴포넌트의 텍스트 렌더링 부분
|
||||
|
||||
---
|
||||
|
||||
### 1.5 수정 모달 자동 닫기
|
||||
**현재 문제**: 수정 완료 후 모달이 자동으로 닫히지 않음
|
||||
|
||||
**요구사항**:
|
||||
- 수정 완료 시 모달이 즉시 닫혀야 함
|
||||
- 성공 메시지 표시 후 닫기
|
||||
|
||||
**구현 방안**:
|
||||
```typescript
|
||||
const handleUpdate = async () => {
|
||||
const result = await updateData(formData);
|
||||
if (result.success) {
|
||||
toast.success("수정이 완료되었습니다");
|
||||
setIsModalOpen(false); // 모달 닫기
|
||||
refreshList(); // 목록 새로고침
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
**관련 파일**:
|
||||
- `frontend/components/screen-viewer/InteractiveScreenViewer.tsx`
|
||||
|
||||
---
|
||||
|
||||
### 1.6 테이블 Align 조절 기능
|
||||
**현재 문제**: 테이블 컬럼의 정렬(align)을 사용자가 조절할 수 없음
|
||||
|
||||
**요구사항**:
|
||||
- 각 컬럼의 정렬을 left/center/right로 설정 가능해야 함
|
||||
- 숫자 타입은 기본적으로 right 정렬
|
||||
|
||||
**구현 방안**:
|
||||
- `TableColumnConfig` 인터페이스에 `align` 속성 추가
|
||||
- PropertiesPanel에서 정렬 선택 UI 제공
|
||||
- 컬럼 타입별 기본 정렬 설정
|
||||
|
||||
**관련 파일**:
|
||||
- `frontend/types/screen.ts`
|
||||
- `frontend/components/screen/PropertiesPanel.tsx`
|
||||
|
||||
---
|
||||
|
||||
### 1.7 숫자 천 단위 콤마 표시
|
||||
**현재 문제**: 숫자가 콤마 없이 표시됨
|
||||
|
||||
**요구사항**:
|
||||
- 모든 숫자는 천 단위마다 콤마(,)를 찍어야 함
|
||||
- 예: 1000000 → 1,000,000
|
||||
|
||||
**구현 방안**:
|
||||
```typescript
|
||||
// 유틸리티 함수 생성
|
||||
export const formatNumber = (value: number | string): string => {
|
||||
const num = typeof value === "string" ? parseFloat(value) : value;
|
||||
if (isNaN(num)) return "0";
|
||||
return new Intl.NumberFormat("ko-KR").format(num);
|
||||
};
|
||||
```
|
||||
|
||||
**관련 파일**:
|
||||
- `frontend/lib/utils/numberFormat.ts` (신규 생성)
|
||||
- 모든 숫자 표시 컴포넌트
|
||||
|
||||
---
|
||||
|
||||
### 1.8 Drilldown UI 개선
|
||||
**현재 문제**: 화면이 횡으로 너무 길게 나열됨
|
||||
|
||||
**요구사항**:
|
||||
- 계층적 구조로 정보 표시
|
||||
- 펼치기/접기 기능으로 공간 절약
|
||||
|
||||
**구현 방안**:
|
||||
- Accordion 컴포넌트 활용
|
||||
- 탭 네비게이션 구조 적용
|
||||
- 마스터-디테일 레이아웃 패턴
|
||||
|
||||
**관련 파일**:
|
||||
- `frontend/components/screen/ScreenDesigner.tsx`
|
||||
- `frontend/components/ui/accordion.tsx`
|
||||
|
||||
---
|
||||
|
||||
## 2. 테이블 관리 (Table Management) 개선사항
|
||||
|
||||
### 2.1 테이블 기본 정보 선택 기능
|
||||
**현재 문제**: 테이블 기본 정보를 사용자가 선택할 수 없음
|
||||
|
||||
**요구사항**:
|
||||
- 테이블 생성/수정 시 다음 정보를 선택 가능해야 함:
|
||||
- 테이블 타입 (마스터/트랜잭션/코드)
|
||||
- 카테고리
|
||||
- 로그 사용 여부
|
||||
- 버전 관리 여부
|
||||
- 소프트 삭제 여부
|
||||
|
||||
**구현 방안**:
|
||||
- `TableManagement.tsx`에 선택 UI 추가
|
||||
- `CREATE TABLE` DDL 자동 생성 시 옵션 반영
|
||||
|
||||
**관련 파일**:
|
||||
- `frontend/components/table/TableManagement.tsx`
|
||||
- `backend-node/src/controllers/tableController.ts`
|
||||
|
||||
---
|
||||
|
||||
### 2.2 컬럼 추가 기능
|
||||
**현재 문제**: 기존 테이블에 새 컬럼을 추가하는 기능 부족
|
||||
|
||||
**요구사항**:
|
||||
- 테이블 수정 시 컬럼을 동적으로 추가할 수 있어야 함
|
||||
- `ALTER TABLE ADD COLUMN` DDL 자동 생성
|
||||
- 컬럼 순서 조정 기능
|
||||
|
||||
**구현 방안**:
|
||||
```typescript
|
||||
// 컬럼 추가 API
|
||||
POST /api/table-management/tables/:tableName/columns
|
||||
{
|
||||
"columnName": "new_column",
|
||||
"dataType": "VARCHAR(100)",
|
||||
"nullable": true,
|
||||
"defaultValue": null
|
||||
}
|
||||
```
|
||||
|
||||
**관련 파일**:
|
||||
- `frontend/components/table/TableManagement.tsx`
|
||||
- `backend-node/src/controllers/tableController.ts`
|
||||
- `backend-node/src/services/ddlExecutionService.ts`
|
||||
|
||||
---
|
||||
|
||||
### 2.3 테이블 복제 기능
|
||||
**현재 문제**: 기존 테이블의 구조를 재사용하기 어려움
|
||||
|
||||
**요구사항**:
|
||||
- 기존 테이블을 복제하여 새 테이블 생성
|
||||
- 다음 정보를 복사:
|
||||
- 컬럼 구조 (이름, 타입, 제약조건)
|
||||
- 인덱스 정의
|
||||
- 외래키 관계 (선택적)
|
||||
- 데이터는 복사하지 않음 (구조만)
|
||||
|
||||
**구현 방안**:
|
||||
```typescript
|
||||
// 테이블 복제 API
|
||||
POST /api/table-management/tables/:sourceTableName/clone
|
||||
{
|
||||
"newTableName": "cloned_table",
|
||||
"includeIndexes": true,
|
||||
"includeForeignKeys": false,
|
||||
"copyData": false
|
||||
}
|
||||
```
|
||||
|
||||
**구현 단계**:
|
||||
1. 원본 테이블 정보 조회 (INFORMATION_SCHEMA)
|
||||
2. DDL 스크립트 생성
|
||||
3. 새 테이블 생성
|
||||
4. 인덱스 및 제약조건 추가
|
||||
5. 감사 로그 기록
|
||||
|
||||
**관련 파일**:
|
||||
- `frontend/components/table/TableManagement.tsx`
|
||||
- `backend-node/src/controllers/tableController.ts`
|
||||
- `backend-node/src/services/ddlExecutionService.ts`
|
||||
|
||||
**참고 문서**:
|
||||
- `/Users/kimjuseok/ERP-node/테이블_복제_기능_구현_계획서.md`
|
||||
|
||||
---
|
||||
|
||||
### 2.4 채번 Rule 관리 기능
|
||||
**현재 문제**: 자동 채번 규칙을 사용자가 관리할 수 없음
|
||||
|
||||
**요구사항**:
|
||||
- 채번 규칙 생성/수정/삭제 UI
|
||||
- 규칙 형식:
|
||||
- 접두사 (예: "PROD-")
|
||||
- 날짜 포맷 (예: "YYYYMMDD")
|
||||
- 일련번호 자릿수 (예: 5자리 → 00001)
|
||||
- 구분자 (예: "-")
|
||||
- 예시: `PROD-20251103-00001`
|
||||
|
||||
**구현 방안**:
|
||||
```typescript
|
||||
interface NumberingRule {
|
||||
id: string;
|
||||
ruleName: string;
|
||||
prefix: string;
|
||||
dateFormat?: "YYYY" | "YYYYMM" | "YYYYMMDD" | "YYYYMMDD-HH";
|
||||
sequenceDigits: number;
|
||||
separator: string;
|
||||
resetPeriod: "none" | "daily" | "monthly" | "yearly";
|
||||
currentSequence: number;
|
||||
tableName: string;
|
||||
columnName: string;
|
||||
}
|
||||
```
|
||||
|
||||
**관련 파일**:
|
||||
- `frontend/components/table/NumberingRuleManagement.tsx` (신규 생성)
|
||||
- `backend-node/src/controllers/numberingRuleController.ts` (신규 생성)
|
||||
- `backend-node/src/services/numberingRuleService.ts` (신규 생성)
|
||||
|
||||
---
|
||||
|
||||
## 3. 제어 관리 (Flow Management) 개선사항
|
||||
|
||||
### 3.1 제목 클릭 시 노드 선택 해제
|
||||
**현재 문제**: 제목을 입력할 때 백스페이스를 누르면 노드가 삭제됨
|
||||
|
||||
**요구사항**:
|
||||
- 제목(플로우명) 입력란 클릭 시 노드 선택이 해제되어야 함
|
||||
- 백스페이스 키가 텍스트 입력으로만 작동해야 함
|
||||
|
||||
**구현 방안**:
|
||||
```typescript
|
||||
const handleTitleClick = (e: React.MouseEvent) => {
|
||||
e.stopPropagation(); // 이벤트 전파 중지
|
||||
setSelectedNodes([]); // 노드 선택 해제
|
||||
};
|
||||
|
||||
const handleTitleKeyDown = (e: React.KeyboardEvent) => {
|
||||
e.stopPropagation(); // 백스페이스 키가 노드 삭제로 전파되지 않도록
|
||||
};
|
||||
|
||||
<Input
|
||||
value={flowName}
|
||||
onClick={handleTitleClick}
|
||||
onKeyDown={handleTitleKeyDown}
|
||||
onChange={(e) => setFlowName(e.target.value)}
|
||||
/>
|
||||
```
|
||||
|
||||
**관련 파일**:
|
||||
- `frontend/components/flow/FlowDesigner.tsx`
|
||||
- `frontend/components/flow/FlowCanvas.tsx`
|
||||
|
||||
---
|
||||
|
||||
## 4. 우선순위 및 구현 일정
|
||||
|
||||
### 높음 (즉시 수정 필요)
|
||||
1. **되돌리기 단축키 에러 수정** - 기능 오류
|
||||
2. **수정 모달 자동 닫기** - 사용자 경험 저해
|
||||
3. **제어관리 제목 입력 문제** - 데이터 손실 위험
|
||||
4. **숫자 천 단위 콤마 표시** - 가독성 문제
|
||||
|
||||
### 중간 (2주 내 완료)
|
||||
5. **리스트 컬럼 Width 조절**
|
||||
6. **리스트 헤더 스타일 개선**
|
||||
7. **텍스트 줄바꿈 문제 방지**
|
||||
8. **테이블 Align 조절**
|
||||
9. **컬럼 추가 기능**
|
||||
|
||||
### 낮음 (기능 추가)
|
||||
10. **테이블 기본 정보 선택**
|
||||
11. **테이블 복제 기능**
|
||||
12. **Drilldown UI 개선**
|
||||
13. **채번 Rule 관리**
|
||||
|
||||
---
|
||||
|
||||
## 5. 테스트 계획
|
||||
|
||||
각 개선사항 완료 시 다음을 확인:
|
||||
|
||||
### 기능 테스트
|
||||
- [ ] 새 기능이 정상 작동함
|
||||
- [ ] 기존 기능에 영향 없음
|
||||
- [ ] 에러 처리가 적절함
|
||||
|
||||
### 사용자 경험 테스트
|
||||
- [ ] UI가 직관적임
|
||||
- [ ] 반응 속도가 빠름
|
||||
- [ ] 모바일/태블릿 대응
|
||||
|
||||
### 성능 테스트
|
||||
- [ ] 대량 데이터 처리 시 성능 저하 없음
|
||||
- [ ] 메모리 누수 없음
|
||||
|
||||
---
|
||||
|
||||
## 6. 참고 문서
|
||||
|
||||
- [화면관리 시스템 현황](화면관리_및_테이블관리_개선사항_목록.md)
|
||||
- [테이블 복제 기능 계획서](테이블_복제_기능_구현_계획서.md)
|
||||
- [Shadcn/ui 레이아웃 패턴](docs/shadcn-ui-레이아웃-패턴-분석-보고서.md)
|
||||
|
||||
---
|
||||
|
||||
## 변경 이력
|
||||
|
||||
| 날짜 | 작성자 | 내용 |
|
||||
|------|--------|------|
|
||||
| 2025-11-03 | 개발팀 | 초안 작성 |
|
||||
|
||||
Loading…
Reference in New Issue