feat: 대시보드 및 모달 컴포넌트 최적화, 클라우드 자산 뷰 추가
This commit is contained in:
@@ -23,6 +23,7 @@ export function generateDummyData(): MasterAssetData {
|
||||
const hw: HardwareAsset[] = [];
|
||||
const sw: SoftwareAsset[] = [];
|
||||
const swUsers: SWUser[] = [];
|
||||
const logs: any[] = [];
|
||||
|
||||
// 1. 개인PC 50개
|
||||
for (let i = 1; i <= 50; i++) {
|
||||
@@ -228,5 +229,51 @@ export function generateDummyData(): MasterAssetData {
|
||||
}
|
||||
}
|
||||
|
||||
return { hw, sw, swUsers, logs: [] };
|
||||
// 7. 클라우드 서비스 15개
|
||||
for (let i = 1; i <= 15; i++) {
|
||||
const swId = Math.random().toString(36).substring(2, 9);
|
||||
const platforms = ['AWS', 'Microsoft Azure', 'Google Cloud', 'Naver Cloud', 'Cafe24'];
|
||||
const pfmt = rand(platforms);
|
||||
|
||||
const billing = (Math.floor(Math.random() * 500) + 10) * 10000;
|
||||
const paymentDay = String(Math.floor(Math.random() * 28) + 1);
|
||||
|
||||
sw.push({
|
||||
id: swId,
|
||||
type: '클라우드',
|
||||
플랫폼명: pfmt,
|
||||
법인: rand(corps),
|
||||
부서: rand(depts),
|
||||
제품명: rand(['본사 홈페이지 운영', 'AI 분석 프로젝트', '인트라넷 백업용', '현장 모니터링 시스템']),
|
||||
계정명: `admin_${i}@hm.com`,
|
||||
결제수단: Math.random() > 0.5 ? '법인카드' : '인보이스',
|
||||
결제일: paymentDay,
|
||||
연결카드번호: String(Math.floor(Math.random() * 8999) + 1000), // 1000~9999
|
||||
당월청구액: String(billing),
|
||||
비고: Math.random() > 0.8 ? '비용 한도 초과 경고' : '',
|
||||
|
||||
// 더미 필수값
|
||||
구매일: '',
|
||||
금액: '',
|
||||
수량: 1,
|
||||
납품업체: ''
|
||||
});
|
||||
|
||||
// 4개월치 모의 결제 이력 생성
|
||||
for (let m = 0; m < 4; m++) {
|
||||
const logDate = new Date();
|
||||
logDate.setMonth(logDate.getMonth() - m);
|
||||
logDate.setDate(parseInt(paymentDay, 10));
|
||||
const historyBilling = Math.floor(billing * (1 + (Math.random() * 0.2 - 0.1)));
|
||||
logs.push({
|
||||
id: Math.random().toString(36).substring(2, 9),
|
||||
assetId: swId,
|
||||
date: `${logDate.getFullYear()}-${String(logDate.getMonth()+1).padStart(2,'0')}-${String(logDate.getDate()).padStart(2,'0')}`,
|
||||
user: `admin_${i}@hm.com`,
|
||||
details: `정기 결제 완료 (비용: ₩ ${historyBilling.toLocaleString()})`
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return { hw, sw, swUsers, logs };
|
||||
}
|
||||
|
||||
@@ -57,6 +57,11 @@ export interface SoftwareAsset {
|
||||
계정명: string;
|
||||
납품업체: string;
|
||||
비고: string;
|
||||
플랫폼명?: string;
|
||||
결제수단?: string;
|
||||
결제일?: string;
|
||||
연결카드번호?: string;
|
||||
당월청구액?: string;
|
||||
}
|
||||
|
||||
export interface SWUser {
|
||||
@@ -87,7 +92,7 @@ export interface MasterAssetData {
|
||||
}
|
||||
|
||||
const HW_TABS = ['개인PC', '서버', '스토리지', '전산비품'];
|
||||
const SW_TABS = ['구독SW', '영구SW'];
|
||||
const SW_TABS = ['구독SW', '영구SW', '클라우드'];
|
||||
|
||||
const HW_HEADERS = ['법인', '자산코드', '명칭', '위치', '관리자', 'IP주소', 'MACaddress', 'HW사양', 'OS', '구매일', '금액', '납품업체', '품의서명'];
|
||||
const PC_HEADERS = ['법인', '자산코드', '사용자', '위치', 'CPU', 'GPU', 'RAM', 'SSD1', 'SSD2', 'HDD1', 'HDD2', '구매일', '금액', '납품업체', '품의서명'];
|
||||
@@ -95,6 +100,7 @@ const SERVER_HEADERS = ['법인', '자산번호', '유형', '용도', '설치위
|
||||
const STORAGE_HEADERS = ['법인', '유형', '자산코드', '명칭', '위치', '모델명', '용량', '담당자(정)', '담당자(부)', 'IP주소', 'MAC주소', '구매일', '금액', '납품업체', '품의서명'];
|
||||
const SUB_SW_HEADERS = ['ID', '분야', '법인', '부서', '제품명', '구매일', '구독일', '금액', '수량', '계정명', '납품업체', '비고'];
|
||||
const PERM_SW_HEADERS = ['ID', '분야', '법인', '부서', '제품명', '구매일', '유지보수여부', '금액', '수량', '계정명', '납품업체', '비고'];
|
||||
const CLOUD_HEADERS = ['ID', '플랫폼명', '법인', '부서', '사용용도(제품명)', '계정명', '결제수단', '결제일', '연결카드번호', '당월청구액', '비고'];
|
||||
const SW_USER_HEADERS = ['id', 'swId', '법인', '부서', '팀', '직위', '이름', '사용기간', '신청서명'];
|
||||
const HISTORY_HEADERS = ['id', 'assetId', 'date', 'details', 'user'];
|
||||
|
||||
@@ -128,9 +134,11 @@ export function downloadTemplate() {
|
||||
});
|
||||
|
||||
SW_TABS.forEach(tab => {
|
||||
let hd = tab === '구독SW' ? SUB_SW_HEADERS : PERM_SW_HEADERS;
|
||||
let hd = tab === '구독SW' ? SUB_SW_HEADERS : (tab === '클라우드' ? CLOUD_HEADERS : PERM_SW_HEADERS);
|
||||
const ws = XLSX.utils.aoa_to_sheet([hd]);
|
||||
ws['!cols'] = [{wch:15}, {wch:15}, {wch:15}, {wch:20}, {wch:30}, {wch:15}, {wch:20}, {wch:15}, {wch:10}, {wch:20}, {wch:20}, {wch:30}];
|
||||
ws['!cols'] = tab === '클라우드'
|
||||
? [{wch:15}, {wch:20}, {wch:15}, {wch:20}, {wch:30}, {wch:25}, {wch:15}, {wch:10}, {wch:15}, {wch:15}, {wch:30}]
|
||||
: [{wch:15}, {wch:15}, {wch:15}, {wch:20}, {wch:30}, {wch:15}, {wch:20}, {wch:15}, {wch:10}, {wch:20}, {wch:20}, {wch:30}];
|
||||
XLSX.utils.book_append_sheet(wb, ws, tab);
|
||||
});
|
||||
|
||||
@@ -195,6 +203,11 @@ export function exportToExcel(masterData: MasterAssetData) {
|
||||
SUB_SW_HEADERS,
|
||||
...targetAssets.map(a => [a.id, a.분야||'', a.법인, a.부서||'', a.제품명, a.구매일, a.구독일, a.금액, a.수량, a.계정명, a.납품업체, a.비고])
|
||||
];
|
||||
} else if (tab === '클라우드') {
|
||||
wsData = [
|
||||
CLOUD_HEADERS,
|
||||
...targetAssets.map(a => [a.id, a.플랫폼명||'', a.법인, a.부서||'', a.제품명, a.계정명, a.결제수단||'', a.결제일||'', a.연결카드번호||'', a.당월청구액||'', a.비고])
|
||||
];
|
||||
} else {
|
||||
wsData = [
|
||||
PERM_SW_HEADERS,
|
||||
@@ -202,7 +215,9 @@ export function exportToExcel(masterData: MasterAssetData) {
|
||||
];
|
||||
}
|
||||
const ws = XLSX.utils.aoa_to_sheet(wsData);
|
||||
ws['!cols'] = [{wch:15}, {wch:15}, {wch:15}, {wch:20}, {wch:30}, {wch:15}, {wch:20}, {wch:15}, {wch:10}, {wch:20}, {wch:20}, {wch:30}];
|
||||
ws['!cols'] = tab === '클라우드'
|
||||
? [{wch:15}, {wch:20}, {wch:15}, {wch:20}, {wch:30}, {wch:25}, {wch:15}, {wch:10}, {wch:15}, {wch:15}, {wch:30}]
|
||||
: [{wch:15}, {wch:15}, {wch:15}, {wch:20}, {wch:30}, {wch:15}, {wch:20}, {wch:15}, {wch:10}, {wch:20}, {wch:20}, {wch:30}];
|
||||
XLSX.utils.book_append_sheet(wb, ws, tab);
|
||||
});
|
||||
|
||||
@@ -303,13 +318,34 @@ export async function parseExcel(file: File): Promise<MasterAssetData> {
|
||||
|
||||
if (SW_TABS.includes(sheetName)) {
|
||||
json.forEach(row => {
|
||||
swAssets.push({
|
||||
id: row['ID'] ? String(row['ID']) : Math.random().toString(36).substring(2, 9),
|
||||
type: sheetName, 분야: row['분야'] || '', 법인: row['법인'] || '', 부서: row['부서'] || '', 제품명: row['제품명'] || '',
|
||||
구매일: row['구매일'] || '', 구독일: row['구독일'] || '', 유지보수여부: row['유지보수여부'] === 'Y' || row['유지보수여부'] === true,
|
||||
금액: row['금액'] ? String(row['금액']) : '', 수량: parseInt(row['수량'] || '1', 10),
|
||||
계정명: row['계정명'] || '', 납품업체: row['납품업체'] || '', 비고: row['비고'] || '',
|
||||
});
|
||||
if (sheetName === '클라우드') {
|
||||
swAssets.push({
|
||||
id: row['ID'] ? String(row['ID']) : Math.random().toString(36).substring(2, 9),
|
||||
type: sheetName,
|
||||
플랫폼명: row['플랫폼명'] || '',
|
||||
법인: row['법인'] || '',
|
||||
부서: row['부서'] || '',
|
||||
제품명: row['사용용도(제품명)'] || '',
|
||||
구매일: '',
|
||||
금액: '',
|
||||
수량: 1,
|
||||
계정명: row['계정명'] || '',
|
||||
결제수단: row['결제수단'] || '',
|
||||
결제일: row['결제일'] ? String(row['결제일']) : '',
|
||||
연결카드번호: row['연결카드번호'] ? String(row['연결카드번호']) : '',
|
||||
당월청구액: row['당월청구액'] ? String(row['당월청구액']) : '',
|
||||
납품업체: '',
|
||||
비고: row['비고'] || '',
|
||||
});
|
||||
} else {
|
||||
swAssets.push({
|
||||
id: row['ID'] ? String(row['ID']) : Math.random().toString(36).substring(2, 9),
|
||||
type: sheetName, 분야: row['분야'] || '', 법인: row['법인'] || '', 부서: row['부서'] || '', 제품명: row['제품명'] || '',
|
||||
구매일: row['구매일'] || '', 구독일: row['구독일'] || '', 유지보수여부: row['유지보수여부'] === 'Y' || row['유지보수여부'] === true,
|
||||
금액: row['금액'] ? String(row['금액']) : '', 수량: parseInt(row['수량'] || '1', 10),
|
||||
계정명: row['계정명'] || '', 납품업체: row['납품업체'] || '', 비고: row['비고'] || '',
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ export const state: AppState = {
|
||||
masterData: {
|
||||
...dummy,
|
||||
hw: mergedHw, // 기본적으로 하드코딩된 데이터를 가지고 시작
|
||||
logs: []
|
||||
logs: dummy.logs || []
|
||||
},
|
||||
activeCategory: 'hw',
|
||||
activeSubTab: '대시보드',
|
||||
|
||||
Reference in New Issue
Block a user