feat: 서버 자산 관리 리스트 고도화 및 3개 관리대장 데이터 통합

This commit is contained in:
2026-04-14 18:01:52 +09:00
parent e4914ee66d
commit 157330b06d
8 changed files with 2054 additions and 457 deletions

View File

@@ -59,7 +59,27 @@ function renderHwTable(table: HTMLTableElement, container: HTMLElement, mainCont
});
} else {
if (state.activeSubTab === '서버') {
table.innerHTML = `<thead><tr><th>No</th><th>법인</th><th>자산번호</th><th>유형</th><th>용도</th><th>설치위치</th><th>담당자(정)</th><th>담당자(부)</th><th>IP 주소</th><th>원격접속</th><th>모델명</th><th>OS</th><th>CPU</th><th>RAM</th><th>GPU</th><th>Storage1</th><th>Storage2</th><th>Storage3</th><th>모니터링</th><th>비고</th><th>관리</th></tr></thead><tbody id="dynamic-tbody"></tbody>`;
table.innerHTML = `
<thead>
<tr>
<th>No</th>
<th>법인</th>
<th>자산번호</th>
<th>유형</th>
<th>용도</th>
<th>상세</th>
<th>설치위치</th>
<th>담당자</th>
<th>IP 주소</th>
<th>원격접속</th>
<th>모델명</th>
<th>OS</th>
<th>CPU</th>
<th>RAM</th>
<th>Storage</th>
</tr>
</thead>
<tbody id="dynamic-tbody"></tbody>`;
} else {
table.innerHTML = `<thead><tr><th>No</th><th>법인</th>${state.activeSubTab === '전산비품' ? '<th>유형</th>' : ''}<th>자산코드</th><th>명칭</th><th>위치</th><th>관리자</th><th>구매일</th><th>금액</th><th>관리</th></tr></thead><tbody id="dynamic-tbody"></tbody>`;
}
@@ -67,43 +87,74 @@ function renderHwTable(table: HTMLTableElement, container: HTMLElement, mainCont
container.appendChild(table);
mainContent.appendChild(container);
const tbody = document.getElementById('dynamic-tbody')!;
const colCount = state.activeSubTab === '서버' ? 21 : (state.activeSubTab === '전산비품' ? 11 : 10);
const colCount = state.activeSubTab === '서버' ? 15 : (state.activeSubTab === '전산비품' ? 11 : 10);
if (list.length === 0) { tbody.innerHTML = `<tr><td colspan="${colCount}">등록된 자산이 없습니다.</td></tr>`; return; }
list.forEach((asset, idx) => {
const tr = document.createElement('tr');
tr.style.cursor = 'pointer';
const formatInline = (v: any) => String(v || '').replace(/\n/g, ' / ').trim();
const getBadge = (text: string, bgColor: string) =>
`<span style="background:${bgColor}; color:white; font-size:10px; padding:1px 4px; border-radius:3px; font-weight:700; margin-right:4px; display:inline-block; line-height:1.2;">${text}</span>`;
if (state.activeSubTab === '서버') {
const mainManager = asset._정 || '';
const subManager = asset._부 || '';
// 담당자 배지화
const managerHtml = [
mainManager ? `${getBadge('정', '#1E5149')} ${mainManager}` : '',
subManager ? `${getBadge('부', '#9CA3AF')} ${subManager}` : ''
].filter(v => v !== '').join(' / ');
// 원격접속 배지화
const tools = (asset. || '').split('\n');
const ids = (asset.ID || '').split('\n');
const pws = (asset.PW || '').split('\n');
const maxLen = Math.max(tools.length, ids.length, pws.length);
let remoteItems = [];
for(let i=0; i<maxLen; i++) {
let toolName = tools[i] || '접속';
let badgeColor = '#3B82F6'; // 기본 파랑 (Remote)
if (toolName.toLowerCase().includes('any')) badgeColor = '#EF4444'; // Anydesk 빨강
if (toolName.toLowerCase().includes('chrome')) badgeColor = '#F59E0B'; // Chrome 노랑
let item = `${getBadge(toolName, badgeColor)}`;
if (ids[i] || pws[i]) {
item += ` (${ids[i] || '-'}/${pws[i] || '-'})`;
}
remoteItems.push(item);
}
const remoteHtml = remoteItems.join(' / ');
// IP 및 Storage (기존 유지)
const ipInfo = [asset.IP주소, asset.IP2].filter(v => v && v !== '').join(' / ');
const storageInfo = [asset.SSD1, asset.SSD2].filter(v => v && v !== '').join(' / ');
tr.innerHTML = `
<td>${idx+1}</td>
<td>${asset.}</td>
<td class="text-nowrap">${asset.}</td>
<td>${asset.storage유형 || '물리'}</td>
<td class="text-nowrap">${asset. || asset. || '-'}</td>
<td class="text-nowrap">${asset.}</td>
<td>${asset._정 || asset. || '-'}</td>
<td>${asset._부 || '-'}</td>
<td>${asset.IP주소}</td>
<td class="text-nowrap">${asset. || '-'}</td>
<td class="text-nowrap">${asset. || '-'}</td>
<td>${asset.OS || ''}</td>
<td>${asset.CPU || ''}</td>
<td>${asset.RAM || ''}</td>
<td>${asset.GPU || '-'}</td>
<td>${asset.SSD1 || '-'}</td>
<td>${asset.SSD2 || '-'}</td>
<td>${asset.HDD1 || '-'}</td>
<td>${asset. || '-'}</td>
<td>${asset. || '-'}</td>
<td><button class="btn-outline btn-edit">수정</button></td>
<td class="text-nowrap">${formatInline(asset.)}</td>
<td class="text-nowrap">${formatInline(asset.)}</td>
<td class="text-nowrap">${formatInline(asset.storage유형)}</td>
<td class="text-nowrap">${formatInline(asset.)}</td>
<td class="text-nowrap">${formatInline(asset.)}</td>
<td class="text-nowrap">${formatInline(asset.)}</td>
<td class="text-nowrap">${managerHtml}</td>
<td class="text-nowrap">${formatInline(ipInfo)}</td>
<td class="text-nowrap">${remoteHtml}</td>
<td class="text-nowrap">${formatInline(asset.)}</td>
<td class="text-nowrap">${formatInline(asset.OS)}</td>
<td class="text-nowrap">${formatInline(asset.CPU)}</td>
<td class="text-nowrap">${formatInline(asset.RAM)}</td>
<td class="text-nowrap">${formatInline(storageInfo)}</td>
`;
} else {
tr.innerHTML = `<td>${idx+1}</td><td>${asset.}</td>${state.activeSubTab === '전산비품' ? `<td>${asset.||'-'}</td>` : ''}<td>${asset.}</td><td>${asset.}</td><td>${asset.}</td><td>${asset.}</td><td>${asset.||''}</td><td>${asset.||''}</td><td><button class="btn-outline btn-edit">수정</button></td>`;
}
tr.addEventListener('click', (e) => { if (!(e.target as HTMLElement).closest('button')) openHwModal(asset); });
tr.querySelector('.btn-edit')?.addEventListener('click', () => openHwModal(asset));
tbody.appendChild(tr);
});
}