diff --git a/src/components/Modal/DashboardDetailModal.ts b/src/components/Modal/DashboardDetailModal.ts
index 7c5fe94..7d43931 100644
--- a/src/components/Modal/DashboardDetailModal.ts
+++ b/src/components/Modal/DashboardDetailModal.ts
@@ -98,7 +98,7 @@ export function openSwUsageDetail(title: string, list: SoftwareAsset[]) {
thead.innerHTML = `
{
reader.onload = (e) => {
try {
const workbook = XLSX.read(e.target?.result, { type: 'binary' });
- const data: MasterAssetData = { pc: [], server: [], storage: [], equip: [], mobile: [], subSw: [], permSw: [], swUsers: [], logs: [] };
+ const data: MasterAssetData = { pc: [], server: [], storage: [], equip: [], mobile: [], subSw: [], permSw: [], cloud: [], hw: [], sw: [], swUsers: [], logs: [] };
workbook.SheetNames.forEach(sheetName => {
const rows = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName]) as any[];
if (sheetName === '개인PC') {
diff --git a/src/core/state.ts b/src/core/state.ts
index ed0fb5d..9b59c60 100644
--- a/src/core/state.ts
+++ b/src/core/state.ts
@@ -19,9 +19,10 @@ export interface MasterAssetData {
}
export interface AppState {
- activeCategory: 'dashboard' | 'hw' | 'sw';
+ activeCategory: 'dashboard' | 'hw' | 'sw' | 'ops';
activeSubTab: string; // '대시보드', '개인PC', '서버', '스토리지', '전산비품', '구독SW', '영구SW', '클라우드'
masterData: MasterAssetData;
+ activeCharts?: any[];
}
// 초기 상태
diff --git a/src/main.ts b/src/main.ts
index ecceb7e..6f4e412 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -26,7 +26,7 @@ async function apiBatchSave(url: string, data: any[], label: string) {
console.log(`✅ ${label} DB 저장 완료`);
} catch (err) {
console.error(`❌ ${label} DB 저장 오류:`, err);
- alert(`${label} 저장 중 오류가 발생했습니다: ${err.message}`);
+ alert(`${label} 저장 중 오류가 발생했습니다: ${(err as any).message}`);
}
}
@@ -125,9 +125,9 @@ function initApp() {
const file = (e.target as HTMLInputElement).files?.[0];
if (file) {
const data = await parseExcel(file);
- state.masterData = data;
+ state.masterData = { ...state.masterData, ...data };
await Promise.all([saveAllHardwareToDB(), saveAllSoftwareToDB()]);
- handleTabChange(state.activeSubTab);
+ refreshView();
}
});
diff --git a/src/views/Dashboard/HwDashboard.ts b/src/views/Dashboard/HwDashboard.ts
index d0466c7..c1c5e5b 100644
--- a/src/views/Dashboard/HwDashboard.ts
+++ b/src/views/Dashboard/HwDashboard.ts
@@ -77,10 +77,10 @@ export function renderHwDashboard(container: HTMLElement) {
최신 도입 모델 (${latestYear}년)
-
- ${latestAsset?.모델명 || '정보 없음'}
+
+ ${(latestAsset as any)?.모델명 || '정보 없음'}
-
+
diff --git a/src/views/DashboardView.ts b/src/views/DashboardView.ts
index c2425a4..ffca55d 100644
--- a/src/views/DashboardView.ts
+++ b/src/views/DashboardView.ts
@@ -11,7 +11,7 @@ export function renderDashboard(mainContent: HTMLElement) {
// 기존 차트 리소스 해제
if (state.activeCharts) {
- state.activeCharts.forEach(c => {
+ state.activeCharts.forEach((c: any) => {
if (c && typeof c.destroy === 'function') c.destroy();
});
}
diff --git a/src/views/List/StorageListView.ts b/src/views/List/StorageListView.ts
index 405fe09..335a836 100644
--- a/src/views/List/StorageListView.ts
+++ b/src/views/List/StorageListView.ts
@@ -14,8 +14,8 @@ export function renderStorageList(container: HTMLElement) {
const filterBar = document.createElement('div');
filterBar.className = 'search-bar';
- const corps = Array.from(new Set(fullList.map(a => a[ASSET_SCHEMA.CORP.key]))).filter(Boolean).sort();
- const orgUnits = Array.from(new Set(fullList.map(a => a[ASSET_SCHEMA.ORG.key]))).filter(Boolean).sort();
+ const corps = Array.from(new Set(fullList.map(a => (a as any)[ASSET_SCHEMA.CORP.key]))).filter(Boolean).sort();
+ const orgUnits = Array.from(new Set(fullList.map(a => (a as any)[ASSET_SCHEMA.ORG.key]))).filter(Boolean).sort();
filterBar.innerHTML = `
@@ -70,10 +70,10 @@ export function renderStorageList(container: HTMLElement) {
const filtered = fullList.filter(asset => {
const matchKeyword = !keyword ||
- String(asset[ASSET_SCHEMA.ASSET_CODE.key]||'').toLowerCase().includes(keyword) ||
- String(asset[ASSET_SCHEMA.ORG.key]||'').toLowerCase().includes(keyword);
- const matchCorp = !corp || asset[ASSET_SCHEMA.CORP.key] === corp;
- const matchOrg = !orgUnit || asset[ASSET_SCHEMA.ORG.key] === orgUnit;
+ String((asset as any)[ASSET_SCHEMA.ASSET_CODE.key]||'').toLowerCase().includes(keyword) ||
+ String((asset as any)[ASSET_SCHEMA.ORG.key]||'').toLowerCase().includes(keyword);
+ const matchCorp = !corp || (asset as any)[ASSET_SCHEMA.CORP.key] === corp;
+ const matchOrg = !orgUnit || (asset as any)[ASSET_SCHEMA.ORG.key] === orgUnit;
return matchKeyword && matchCorp && matchOrg;
});
@@ -87,8 +87,8 @@ export function renderStorageList(container: HTMLElement) {
const tr = document.createElement('tr');
tr.style.cursor = 'pointer';
- const mainManager = asset[ASSET_SCHEMA.MANAGER_MAIN.key] || '';
- const subManager = asset[ASSET_SCHEMA.MANAGER_SUB.key] || '';
+ const mainManager = (asset as any)[ASSET_SCHEMA.MANAGER_MAIN.key] || '';
+ const subManager = (asset as any)[ASSET_SCHEMA.MANAGER_SUB.key] || '';
const managerHtml = [
mainManager ? `${createBadge('정', 'primary')} ${mainManager}` : '',
subManager ? `${createBadge('부', 'muted')} ${subManager}` : ''
@@ -96,12 +96,12 @@ export function renderStorageList(container: HTMLElement) {
tr.innerHTML = `
${idx+1} |
- ${asset[ASSET_SCHEMA.CORP.key]} |
- ${asset[ASSET_SCHEMA.ORG.key]||'-'} |
- ${asset[ASSET_SCHEMA.ASSET_CODE.key]} |
+ ${(asset as any)[ASSET_SCHEMA.CORP.key]} |
+ ${(asset as any)[ASSET_SCHEMA.ORG.key]||'-'} |
+ ${(asset as any)[ASSET_SCHEMA.ASSET_CODE.key]} |
${formatInline(asset.용도)} |
${formatInline(asset.상세)} |
- ${formatInline(asset[ASSET_SCHEMA.LOCATION.key])} |
+ ${formatInline((asset as any)[ASSET_SCHEMA.LOCATION.key])} |
${managerHtml || '-'} |
`;
tr.addEventListener('click', () => openHwModal(asset, 'view'));
diff --git a/src/views/List/SwListView.ts b/src/views/List/SwListView.ts
index abd3a9a..875e620 100644
--- a/src/views/List/SwListView.ts
+++ b/src/views/List/SwListView.ts
@@ -76,9 +76,9 @@ export function renderSwList(container: HTMLElement) {
const corp = corpSelect ? corpSelect.value : '';
const filtered = fullList.filter(asset => {
- const matchKeyword = !keyword || (asset[ASSET_SCHEMA.PRODUCT.key] || '').toLowerCase().includes(keyword) || (asset.부서 || '').toLowerCase().includes(keyword);
+ const matchKeyword = !keyword || ((asset as any)[ASSET_SCHEMA.PRODUCT.key] || '').toLowerCase().includes(keyword) || (asset.부서 || '').toLowerCase().includes(keyword);
const matchField = !field || asset.분야 === field;
- const matchCorp = !corp || asset[ASSET_SCHEMA.CORP.key] === corp;
+ const matchCorp = !corp || (asset as any)[ASSET_SCHEMA.CORP.key] === corp;
return matchKeyword && matchField && matchCorp;
});
@@ -90,14 +90,14 @@ export function renderSwList(container: HTMLElement) {
filtered.forEach((asset, idx) => {
const assigned = state.masterData.swUsers.filter(u => u.sw_id === asset.id).length;
- const qty = typeof asset[ASSET_SCHEMA.QTY.key] === 'number' ? asset[ASSET_SCHEMA.QTY.key] : parseInt(asset[ASSET_SCHEMA.QTY.key]||'0', 10);
+ const qty = typeof (asset as any)[ASSET_SCHEMA.QTY.key] === 'number' ? (asset as any)[ASSET_SCHEMA.QTY.key] : parseInt((asset as any)[ASSET_SCHEMA.QTY.key]||'0', 10);
const avail = qty - assigned;
let statusBadge = '';
if (isSub) {
let isExpired = false;
- if (asset[ASSET_SCHEMA.EXPIRY.key]) {
- const parts = asset[ASSET_SCHEMA.EXPIRY.key].split('~');
+ if ((asset as any)[ASSET_SCHEMA.EXPIRY.key]) {
+ const parts = (asset as any)[ASSET_SCHEMA.EXPIRY.key].split('~');
const endDateStr = parts[parts.length - 1].trim().replace(/\./g, '-');
const endDate = new Date(endDateStr);
if (!isNaN(endDate.getTime())) {
@@ -117,12 +117,12 @@ export function renderSwList(container: HTMLElement) {
${idx+1} |
${statusBadge} |
${asset.분야||''} |
- ${asset[ASSET_SCHEMA.CORP.key]} |
+ ${(asset as any)[ASSET_SCHEMA.CORP.key]} |
${asset.부서||''} |
- ${asset[ASSET_SCHEMA.PRODUCT.key]} |
- ${asset[ASSET_SCHEMA.PURCHASE_YM.key]||''} |
- ${isSub ? `${asset[ASSET_SCHEMA.EXPIRY.key]||''} | ` : ''}
- ${Number(asset[ASSET_SCHEMA.PRICE.key]||0).toLocaleString()} |
+ ${(asset as any)[ASSET_SCHEMA.PRODUCT.key]} |
+ ${(asset as any)[ASSET_SCHEMA.PURCHASE_YM.key]||''} |
+ ${isSub ? `${(asset as any)[ASSET_SCHEMA.EXPIRY.key]||''} | ` : ''}
+ ${Number((asset as any)[ASSET_SCHEMA.PRICE.key]||0).toLocaleString()} |
${qty} |
${avail} |
`;