2025-09-01 11:48:12 +09:00
|
|
|
import { apiClient } from "./client";
|
|
|
|
|
import {
|
|
|
|
|
ScreenDefinition,
|
|
|
|
|
CreateScreenRequest,
|
|
|
|
|
UpdateScreenRequest,
|
|
|
|
|
PaginatedResponse,
|
|
|
|
|
ScreenTemplate,
|
|
|
|
|
LayoutData,
|
|
|
|
|
} from "@/types/screen";
|
|
|
|
|
|
|
|
|
|
// 화면 정의 관련 API
|
|
|
|
|
export const screenApi = {
|
|
|
|
|
// 화면 목록 조회
|
|
|
|
|
getScreens: async (params: {
|
|
|
|
|
page?: number;
|
|
|
|
|
size?: number;
|
|
|
|
|
companyCode?: string;
|
|
|
|
|
searchTerm?: string;
|
|
|
|
|
}): Promise<PaginatedResponse<ScreenDefinition>> => {
|
|
|
|
|
const response = await apiClient.get("/screen-management/screens", { params });
|
2025-09-01 17:57:52 +09:00
|
|
|
const raw = response.data || {};
|
|
|
|
|
const items: any[] = (raw.data ?? raw.items ?? []) as any[];
|
|
|
|
|
const mapped: ScreenDefinition[] = items.map((it) => ({
|
|
|
|
|
...it,
|
|
|
|
|
// 문자열로 온 날짜를 Date 객체로 변환 (이미 Date이면 그대로 유지)
|
|
|
|
|
createdDate: it.createdDate ? new Date(it.createdDate) : undefined,
|
|
|
|
|
updatedDate: it.updatedDate ? new Date(it.updatedDate) : undefined,
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
const page = raw.page ?? params.page ?? 1;
|
|
|
|
|
const size = raw.size ?? params.size ?? mapped.length;
|
|
|
|
|
const total = raw.total ?? mapped.length;
|
|
|
|
|
const totalPages = raw.totalPages ?? Math.max(1, Math.ceil(total / (size || 1)));
|
|
|
|
|
|
|
|
|
|
return { data: mapped, total, page, size, totalPages };
|
2025-09-01 11:48:12 +09:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 화면 상세 조회
|
|
|
|
|
getScreen: async (screenId: number): Promise<ScreenDefinition> => {
|
|
|
|
|
const response = await apiClient.get(`/screen-management/screens/${screenId}`);
|
2025-09-01 17:57:52 +09:00
|
|
|
const raw = response.data?.data || response.data;
|
|
|
|
|
return {
|
|
|
|
|
...raw,
|
|
|
|
|
createdDate: raw?.createdDate ? new Date(raw.createdDate) : undefined,
|
|
|
|
|
updatedDate: raw?.updatedDate ? new Date(raw.updatedDate) : undefined,
|
|
|
|
|
} as ScreenDefinition;
|
2025-09-01 11:48:12 +09:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 화면 생성
|
|
|
|
|
createScreen: async (screenData: CreateScreenRequest): Promise<ScreenDefinition> => {
|
|
|
|
|
const response = await apiClient.post("/screen-management/screens", screenData);
|
|
|
|
|
return response.data.data;
|
|
|
|
|
},
|
|
|
|
|
|
2025-09-01 17:57:52 +09:00
|
|
|
// 화면 코드 자동 생성 (회사코드 + 순번)
|
|
|
|
|
generateScreenCode: async (companyCode: string): Promise<string> => {
|
|
|
|
|
const response = await apiClient.get(`/screen-management/generate-screen-code/${companyCode}`);
|
|
|
|
|
return response.data.data.screenCode;
|
|
|
|
|
},
|
|
|
|
|
|
2025-09-01 11:48:12 +09:00
|
|
|
// 화면 수정
|
|
|
|
|
updateScreen: async (screenId: number, screenData: UpdateScreenRequest): Promise<ScreenDefinition> => {
|
|
|
|
|
const response = await apiClient.put(`/screen-management/screens/${screenId}`, screenData);
|
|
|
|
|
return response.data.data;
|
|
|
|
|
},
|
|
|
|
|
|
2025-10-15 18:31:40 +09:00
|
|
|
// 화면 정보 수정 (메타데이터만)
|
|
|
|
|
updateScreenInfo: async (
|
|
|
|
|
screenId: number,
|
|
|
|
|
data: { screenName: string; description?: string; isActive: string },
|
|
|
|
|
): Promise<void> => {
|
|
|
|
|
await apiClient.put(`/screen-management/screens/${screenId}/info`, data);
|
|
|
|
|
},
|
|
|
|
|
|
2025-09-08 13:10:09 +09:00
|
|
|
// 화면 의존성 체크
|
|
|
|
|
checkScreenDependencies: async (
|
|
|
|
|
screenId: number,
|
|
|
|
|
): Promise<{
|
|
|
|
|
hasDependencies: boolean;
|
|
|
|
|
dependencies: Array<{
|
|
|
|
|
screenId: number;
|
|
|
|
|
screenName: string;
|
|
|
|
|
screenCode: string;
|
|
|
|
|
componentId: string;
|
|
|
|
|
componentType: string;
|
|
|
|
|
referenceType: string;
|
|
|
|
|
}>;
|
|
|
|
|
}> => {
|
|
|
|
|
const response = await apiClient.get(`/screen-management/screens/${screenId}/dependencies`);
|
|
|
|
|
return response.data;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 화면 삭제 (휴지통으로 이동)
|
|
|
|
|
deleteScreen: async (screenId: number, deleteReason?: string, force?: boolean): Promise<void> => {
|
|
|
|
|
await apiClient.delete(`/screen-management/screens/${screenId}`, {
|
|
|
|
|
data: { deleteReason, force },
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 휴지통 화면 목록 조회
|
|
|
|
|
getDeletedScreens: async (params: {
|
|
|
|
|
page?: number;
|
|
|
|
|
size?: number;
|
|
|
|
|
}): Promise<
|
|
|
|
|
PaginatedResponse<ScreenDefinition & { deletedDate?: Date; deletedBy?: string; deleteReason?: string }>
|
|
|
|
|
> => {
|
|
|
|
|
const response = await apiClient.get("/screen-management/screens/trash/list", { params });
|
|
|
|
|
const raw = response.data || {};
|
|
|
|
|
const items: any[] = (raw.data ?? raw.items ?? []) as any[];
|
|
|
|
|
const mapped = items.map((it) => ({
|
|
|
|
|
...it,
|
|
|
|
|
createdDate: it.createdDate ? new Date(it.createdDate) : undefined,
|
|
|
|
|
updatedDate: it.updatedDate ? new Date(it.updatedDate) : undefined,
|
|
|
|
|
deletedDate: it.deletedDate ? new Date(it.deletedDate) : undefined,
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
const page = raw.page ?? params.page ?? 1;
|
|
|
|
|
const size = raw.size ?? params.size ?? mapped.length;
|
|
|
|
|
const total = raw.total ?? mapped.length;
|
|
|
|
|
const totalPages = raw.totalPages ?? Math.max(1, Math.ceil(total / (size || 1)));
|
|
|
|
|
|
|
|
|
|
return { data: mapped, total, page, size, totalPages };
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 휴지통 화면 일괄 영구 삭제
|
|
|
|
|
bulkPermanentDeleteScreens: async (
|
|
|
|
|
screenIds: number[],
|
|
|
|
|
): Promise<{
|
|
|
|
|
deletedCount: number;
|
|
|
|
|
skippedCount: number;
|
|
|
|
|
errors: Array<{ screenId: number; error: string }>;
|
|
|
|
|
}> => {
|
|
|
|
|
const response = await apiClient.delete("/screen-management/screens/trash/bulk", {
|
|
|
|
|
data: { screenIds },
|
|
|
|
|
});
|
|
|
|
|
return response.data.result;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 화면 복원 (휴지통에서 복원)
|
|
|
|
|
restoreScreen: async (screenId: number): Promise<void> => {
|
|
|
|
|
await apiClient.post(`/screen-management/screens/${screenId}/restore`);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 화면 영구 삭제
|
|
|
|
|
permanentDeleteScreen: async (screenId: number): Promise<void> => {
|
|
|
|
|
await apiClient.delete(`/screen-management/screens/${screenId}/permanent`);
|
2025-09-01 11:48:12 +09:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 화면 레이아웃 저장
|
|
|
|
|
saveLayout: async (screenId: number, layoutData: LayoutData): Promise<void> => {
|
|
|
|
|
await apiClient.post(`/screen-management/screens/${screenId}/layout`, layoutData);
|
|
|
|
|
},
|
|
|
|
|
|
2025-10-31 17:21:47 +09:00
|
|
|
// 화면 레이아웃 저장 (ScreenDesigner_new.tsx용)
|
|
|
|
|
saveScreenLayout: async (screenId: number, layoutData: LayoutData): Promise<ApiResponse<void>> => {
|
|
|
|
|
const response = await apiClient.post(`/screen-management/screens/${screenId}/layout`, layoutData);
|
|
|
|
|
return response.data;
|
|
|
|
|
},
|
|
|
|
|
|
2025-09-01 11:48:12 +09:00
|
|
|
// 화면 레이아웃 조회
|
|
|
|
|
getLayout: async (screenId: number): Promise<LayoutData> => {
|
|
|
|
|
const response = await apiClient.get(`/screen-management/screens/${screenId}/layout`);
|
|
|
|
|
return response.data.data;
|
|
|
|
|
},
|
2025-09-03 18:23:47 +09:00
|
|
|
|
|
|
|
|
// 화면 복사 (화면정보 + 레이아웃 모두 복사)
|
|
|
|
|
copyScreen: async (
|
|
|
|
|
sourceScreenId: number,
|
|
|
|
|
copyData: {
|
|
|
|
|
screenName: string;
|
|
|
|
|
screenCode: string;
|
|
|
|
|
description?: string;
|
|
|
|
|
},
|
|
|
|
|
): Promise<ScreenDefinition> => {
|
|
|
|
|
const response = await apiClient.post(`/screen-management/screens/${sourceScreenId}/copy`, copyData);
|
|
|
|
|
return response.data.data;
|
|
|
|
|
},
|
2025-09-01 11:48:12 +09:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 템플릿 관련 API
|
|
|
|
|
export const templateApi = {
|
|
|
|
|
// 템플릿 목록 조회
|
|
|
|
|
getTemplates: async (params: {
|
|
|
|
|
companyCode?: string;
|
|
|
|
|
templateType?: string;
|
|
|
|
|
isPublic?: boolean;
|
|
|
|
|
}): Promise<ScreenTemplate[]> => {
|
|
|
|
|
const response = await apiClient.get("/screen-management/templates", { params });
|
|
|
|
|
return response.data.data;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 템플릿 상세 조회
|
|
|
|
|
getTemplate: async (templateId: number): Promise<ScreenTemplate> => {
|
|
|
|
|
const response = await apiClient.get(`/screen-management/templates/${templateId}`);
|
|
|
|
|
return response.data.data;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 템플릿 생성
|
|
|
|
|
createTemplate: async (templateData: Partial<ScreenTemplate>): Promise<ScreenTemplate> => {
|
|
|
|
|
const response = await apiClient.post("/screen-management/templates", templateData);
|
|
|
|
|
return response.data.data;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 템플릿 수정
|
|
|
|
|
updateTemplate: async (templateId: number, templateData: Partial<ScreenTemplate>): Promise<ScreenTemplate> => {
|
|
|
|
|
const response = await apiClient.put(`/screen-management/templates/${templateId}`, templateData);
|
|
|
|
|
return response.data.data;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 템플릿 삭제
|
|
|
|
|
deleteTemplate: async (templateId: number): Promise<void> => {
|
|
|
|
|
await apiClient.delete(`/screen-management/templates/${templateId}`);
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 테이블 타입 관련 API
|
|
|
|
|
export const tableTypeApi = {
|
|
|
|
|
// 테이블 목록 조회
|
|
|
|
|
getTables: async (): Promise<
|
|
|
|
|
Array<{ tableName: string; displayName: string; description: string; columnCount: string }>
|
|
|
|
|
> => {
|
|
|
|
|
const response = await apiClient.get("/table-management/tables");
|
|
|
|
|
return response.data.data;
|
|
|
|
|
},
|
|
|
|
|
|
2025-09-08 14:20:01 +09:00
|
|
|
// 테이블 라벨 조회
|
|
|
|
|
getTableLabel: async (tableName: string): Promise<{ tableLabel?: string; description?: string }> => {
|
|
|
|
|
try {
|
|
|
|
|
const response = await apiClient.get(`/table-management/tables/${tableName}/labels`);
|
|
|
|
|
return response.data.data || {};
|
|
|
|
|
} catch (error) {
|
|
|
|
|
// 라벨이 없으면 빈 객체 반환
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2025-09-18 17:17:06 +09:00
|
|
|
// 테이블 컬럼 정보 조회 (모든 컬럼)
|
2025-09-01 11:48:12 +09:00
|
|
|
getColumns: async (tableName: string): Promise<any[]> => {
|
2025-09-18 17:17:06 +09:00
|
|
|
const response = await apiClient.get(`/table-management/tables/${tableName}/columns?size=1000`);
|
2025-09-08 14:20:01 +09:00
|
|
|
// 새로운 API 응답 구조에 맞게 수정: { columns, total, page, size, totalPages }
|
|
|
|
|
const data = response.data.data || response.data;
|
|
|
|
|
return data.columns || data || [];
|
2025-09-01 11:48:12 +09:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 컬럼 웹 타입 설정
|
|
|
|
|
setColumnWebType: async (
|
|
|
|
|
tableName: string,
|
|
|
|
|
columnName: string,
|
|
|
|
|
webType: string,
|
|
|
|
|
detailSettings?: Record<string, any>,
|
2025-09-04 14:23:35 +09:00
|
|
|
inputType?: "direct" | "auto",
|
2025-09-01 11:48:12 +09:00
|
|
|
): Promise<void> => {
|
|
|
|
|
await apiClient.put(`/table-management/tables/${tableName}/columns/${columnName}/web-type`, {
|
|
|
|
|
webType,
|
|
|
|
|
detailSettings,
|
2025-09-04 14:23:35 +09:00
|
|
|
inputType,
|
2025-09-01 11:48:12 +09:00
|
|
|
});
|
|
|
|
|
},
|
2025-09-03 15:23:12 +09:00
|
|
|
|
|
|
|
|
// 테이블 데이터 조회 (페이지네이션 + 검색)
|
|
|
|
|
getTableData: async (
|
|
|
|
|
tableName: string,
|
|
|
|
|
params: {
|
|
|
|
|
page?: number;
|
|
|
|
|
size?: number;
|
|
|
|
|
search?: Record<string, any>; // 검색 조건
|
|
|
|
|
sortBy?: string;
|
|
|
|
|
sortOrder?: "asc" | "desc";
|
|
|
|
|
} = {},
|
|
|
|
|
): Promise<{
|
|
|
|
|
data: Record<string, any>[];
|
|
|
|
|
total: number;
|
|
|
|
|
page: number;
|
|
|
|
|
size: number;
|
|
|
|
|
totalPages: number;
|
|
|
|
|
}> => {
|
|
|
|
|
const response = await apiClient.post(`/table-management/tables/${tableName}/data`, params);
|
|
|
|
|
const raw = response.data?.data || response.data;
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
data: raw.data || [],
|
|
|
|
|
total: raw.total || 0,
|
|
|
|
|
page: raw.page || params.page || 1,
|
|
|
|
|
size: raw.size || params.size || 10,
|
|
|
|
|
totalPages: raw.totalPages || Math.ceil((raw.total || 0) / (params.size || 10)),
|
|
|
|
|
};
|
|
|
|
|
},
|
2025-09-03 16:38:10 +09:00
|
|
|
|
|
|
|
|
// 데이터 추가
|
|
|
|
|
addTableData: async (tableName: string, data: Record<string, any>): Promise<void> => {
|
|
|
|
|
await apiClient.post(`/table-management/tables/${tableName}/add`, data);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 데이터 수정
|
|
|
|
|
editTableData: async (
|
|
|
|
|
tableName: string,
|
|
|
|
|
originalData: Record<string, any>,
|
|
|
|
|
updatedData: Record<string, any>,
|
|
|
|
|
): Promise<void> => {
|
|
|
|
|
await apiClient.put(`/table-management/tables/${tableName}/edit`, {
|
|
|
|
|
originalData,
|
|
|
|
|
updatedData,
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 데이터 삭제 (단일 또는 다중)
|
|
|
|
|
deleteTableData: async (tableName: string, data: Record<string, any>[] | { ids: string[] }): Promise<void> => {
|
|
|
|
|
await apiClient.delete(`/table-management/tables/${tableName}/delete`, { data });
|
|
|
|
|
},
|
2025-09-01 11:48:12 +09:00
|
|
|
};
|
2025-09-01 18:42:59 +09:00
|
|
|
|
|
|
|
|
// 메뉴-화면 할당 관련 API
|
|
|
|
|
export const menuScreenApi = {
|
|
|
|
|
// 화면을 메뉴에 할당
|
|
|
|
|
assignScreenToMenu: async (screenId: number, menuObjid: number, displayOrder?: number): Promise<void> => {
|
|
|
|
|
await apiClient.post(`/screen-management/screens/${screenId}/assign-menu`, {
|
|
|
|
|
menuObjid,
|
|
|
|
|
displayOrder,
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 메뉴별 할당된 화면 목록 조회
|
|
|
|
|
getScreensByMenu: async (menuObjid: number): Promise<ScreenDefinition[]> => {
|
|
|
|
|
const response = await apiClient.get(`/screen-management/menus/${menuObjid}/screens`);
|
|
|
|
|
return response.data.data.map((screen: any) => ({
|
|
|
|
|
...screen,
|
|
|
|
|
createdDate: screen.createdDate ? new Date(screen.createdDate) : new Date(),
|
|
|
|
|
updatedDate: screen.updatedDate ? new Date(screen.updatedDate) : new Date(),
|
|
|
|
|
}));
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 화면-메뉴 할당 해제
|
|
|
|
|
unassignScreenFromMenu: async (screenId: number, menuObjid: number): Promise<void> => {
|
|
|
|
|
await apiClient.delete(`/screen-management/screens/${screenId}/menus/${menuObjid}`);
|
|
|
|
|
},
|
|
|
|
|
};
|